mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-14 06:24:29 +01:00
From Entity to Inventory
- Started work on belts no longer moving itementities around
This commit is contained in:
parent
c2814f8ad2
commit
25cac1fe8e
@ -6,7 +6,7 @@ import com.simibubi.create.modules.IModule;
|
|||||||
import com.simibubi.create.modules.contraptions.WrenchItem;
|
import com.simibubi.create.modules.contraptions.WrenchItem;
|
||||||
import com.simibubi.create.modules.contraptions.WrenchItemRenderer;
|
import com.simibubi.create.modules.contraptions.WrenchItemRenderer;
|
||||||
import com.simibubi.create.modules.contraptions.relays.VerticalGearboxItem;
|
import com.simibubi.create.modules.contraptions.relays.VerticalGearboxItem;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltItem;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItem;
|
||||||
import com.simibubi.create.modules.curiosities.ChromaticCompoundCubeItem;
|
import com.simibubi.create.modules.curiosities.ChromaticCompoundCubeItem;
|
||||||
import com.simibubi.create.modules.curiosities.deforester.DeforesterItem;
|
import com.simibubi.create.modules.curiosities.deforester.DeforesterItem;
|
||||||
import com.simibubi.create.modules.curiosities.deforester.DeforesterItemRenderer;
|
import com.simibubi.create.modules.curiosities.deforester.DeforesterItemRenderer;
|
||||||
@ -82,7 +82,7 @@ public enum AllItems {
|
|||||||
BLUEPRINT(new SchematicItem(standardItemProperties())),
|
BLUEPRINT(new SchematicItem(standardItemProperties())),
|
||||||
|
|
||||||
__CONTRAPTIONS__(),
|
__CONTRAPTIONS__(),
|
||||||
BELT_CONNECTOR(new BeltItem(standardItemProperties())),
|
BELT_CONNECTOR(new BeltConnectorItem(standardItemProperties())),
|
||||||
VERTICAL_GEARBOX(new VerticalGearboxItem(new Properties())),
|
VERTICAL_GEARBOX(new VerticalGearboxItem(new Properties())),
|
||||||
FLOUR(ingredient()),
|
FLOUR(ingredient()),
|
||||||
DOUGH(ingredient()),
|
DOUGH(ingredient()),
|
||||||
|
@ -10,7 +10,7 @@ import com.simibubi.create.foundation.utility.TooltipHelper;
|
|||||||
import com.simibubi.create.modules.contraptions.KineticDebugger;
|
import com.simibubi.create.modules.contraptions.KineticDebugger;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.TurntableHandler;
|
import com.simibubi.create.modules.contraptions.receivers.TurntableHandler;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltItemHandler;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItemHandler;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
@ -56,7 +56,7 @@ public class ClientEvents {
|
|||||||
|
|
||||||
public static void onGameTick() {
|
public static void onGameTick() {
|
||||||
CreateClient.gameTick();
|
CreateClient.gameTick();
|
||||||
BeltItemHandler.gameTick();
|
BeltConnectorItemHandler.gameTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
|
@ -4,6 +4,7 @@ import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer;
|
|||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer;
|
||||||
|
import com.simibubi.create.modules.contraptions.relays.belt.FastItemRenderer;
|
||||||
|
|
||||||
import net.minecraft.client.resources.ReloadListener;
|
import net.minecraft.client.resources.ReloadListener;
|
||||||
import net.minecraft.profiler.IProfiler;
|
import net.minecraft.profiler.IProfiler;
|
||||||
@ -22,6 +23,7 @@ public class CachedBufferReloader extends ReloadListener<String> {
|
|||||||
ContraptionRenderer.invalidateCache();
|
ContraptionRenderer.invalidateCache();
|
||||||
MechanicalBearingTileEntityRenderer.invalidateCache();
|
MechanicalBearingTileEntityRenderer.invalidateCache();
|
||||||
ColoredIndicatorRenderer.invalidateCache();
|
ColoredIndicatorRenderer.invalidateCache();
|
||||||
|
FastItemRenderer.invalidateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,12 +76,6 @@ public class RotationPropagator {
|
|||||||
return connected ? 1 : 0;
|
return connected ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attached Fans
|
|
||||||
if (ENCASED_FAN.typeOf(stateFrom) && ENCASED_FAN.typeOf(stateTo)) {
|
|
||||||
if (stateFrom.get(AXIS) == stateTo.get(AXIS))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Large Gear <-> Large Gear
|
// Large Gear <-> Large Gear
|
||||||
if (isLargeToLargeGear(stateFrom, stateTo, diff)) {
|
if (isLargeToLargeGear(stateFrom, stateTo, diff)) {
|
||||||
Axis sourceAxis = stateFrom.get(AXIS);
|
Axis sourceAxis = stateFrom.get(AXIS);
|
||||||
|
@ -34,7 +34,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
|||||||
@EventBusSubscriber(value = Dist.CLIENT)
|
@EventBusSubscriber(value = Dist.CLIENT)
|
||||||
public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTileEntity> {
|
public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTileEntity> {
|
||||||
|
|
||||||
protected static Map<BlockState, BufferManipulator> cachedBuffers;
|
public static Map<BlockState, BufferManipulator> cachedBuffers;
|
||||||
public static boolean rainbowMode = false;
|
public static boolean rainbowMode = false;
|
||||||
|
|
||||||
public static class BlockModelSpinner extends BufferManipulator {
|
public static class BlockModelSpinner extends BufferManipulator {
|
||||||
|
@ -9,12 +9,13 @@ import com.simibubi.create.foundation.block.IWithTileEntity;
|
|||||||
import com.simibubi.create.foundation.block.IWithoutBlockItem;
|
import com.simibubi.create.foundation.block.IWithoutBlockItem;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
|
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity.TransportedEntityInfo;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.DyeColor;
|
import net.minecraft.item.DyeColor;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
@ -31,121 +32,90 @@ import net.minecraft.util.IStringSerializable;
|
|||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.BlockRayTraceResult;
|
import net.minecraft.util.math.BlockRayTraceResult;
|
||||||
import net.minecraft.util.math.RayTraceResult;
|
import net.minecraft.util.math.RayTraceResult;
|
||||||
import net.minecraft.util.math.Vec3i;
|
|
||||||
import net.minecraft.util.math.shapes.IBooleanFunction;
|
|
||||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||||
import net.minecraft.util.math.shapes.VoxelShape;
|
import net.minecraft.util.math.shapes.VoxelShape;
|
||||||
import net.minecraft.util.math.shapes.VoxelShapes;
|
|
||||||
import net.minecraft.world.IBlockReader;
|
import net.minecraft.world.IBlockReader;
|
||||||
import net.minecraft.world.IWorldReader;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.common.Tags;
|
import net.minecraftforge.common.Tags;
|
||||||
|
import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
|
import net.minecraftforge.items.ItemStackHandler;
|
||||||
|
|
||||||
public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockItem, IWithTileEntity<BeltTileEntity> {
|
public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockItem, IWithTileEntity<BeltTileEntity> {
|
||||||
|
|
||||||
public static final IProperty<Slope> SLOPE = EnumProperty.create("slope", Slope.class);
|
public static final IProperty<Slope> SLOPE = EnumProperty.create("slope", Slope.class);
|
||||||
public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
|
public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
|
||||||
|
|
||||||
private static final VoxelShape FULL = makeCuboidShape(0, 0, 0, 16, 16, 16),
|
|
||||||
FLAT_STRAIGHT_X = makeCuboidShape(1, 3, 0, 15, 13, 16),
|
|
||||||
FLAT_STRAIGHT_Z = makeCuboidShape(0, 3, 1, 16, 13, 15),
|
|
||||||
VERTICAL_STRAIGHT_X = makeCuboidShape(3, 0, 1, 13, 16, 15),
|
|
||||||
VERTICAL_STRAIGHT_Z = makeCuboidShape(1, 0, 3, 15, 16, 13),
|
|
||||||
|
|
||||||
SLOPE_END_EAST = makeCuboidShape(0, 3, 1, 10, 13, 15),
|
|
||||||
SLOPE_END_WEST = makeCuboidShape(6, 3, 1, 16, 13, 15),
|
|
||||||
SLOPE_END_SOUTH = makeCuboidShape(1, 3, 0, 15, 13, 10),
|
|
||||||
SLOPE_END_NORTH = makeCuboidShape(1, 3, 6, 15, 13, 16),
|
|
||||||
|
|
||||||
SLOPE_BUILDING_BLOCK_X = makeCuboidShape(5, 5, 1, 11, 11, 15),
|
|
||||||
SLOPE_BUILDING_BLOCK_Z = makeCuboidShape(1, 5, 5, 15, 11, 11),
|
|
||||||
|
|
||||||
SLOPE_UPWARD_END_EAST = VoxelShapes.or(SLOPE_END_EAST, createHalfSlope(Direction.EAST, false)),
|
|
||||||
SLOPE_UPWARD_END_WEST = VoxelShapes.or(SLOPE_END_WEST, createHalfSlope(Direction.WEST, false)),
|
|
||||||
SLOPE_UPWARD_END_SOUTH = VoxelShapes.or(SLOPE_END_SOUTH, createHalfSlope(Direction.SOUTH, false)),
|
|
||||||
SLOPE_UPWARD_END_NORTH = VoxelShapes.or(SLOPE_END_NORTH, createHalfSlope(Direction.NORTH, false)),
|
|
||||||
|
|
||||||
SLOPE_DOWNWARD_END_EAST = VoxelShapes.or(SLOPE_END_EAST, createHalfSlope(Direction.EAST, true)),
|
|
||||||
SLOPE_DOWNWARD_END_WEST = VoxelShapes.or(SLOPE_END_WEST, createHalfSlope(Direction.WEST, true)),
|
|
||||||
SLOPE_DOWNWARD_END_SOUTH = VoxelShapes.or(SLOPE_END_SOUTH, createHalfSlope(Direction.SOUTH, true)),
|
|
||||||
SLOPE_DOWNWARD_END_NORTH = VoxelShapes.or(SLOPE_END_NORTH, createHalfSlope(Direction.NORTH, true)),
|
|
||||||
|
|
||||||
SLOPE_EAST = createSlope(Direction.EAST), SLOPE_WEST = createSlope(Direction.WEST),
|
|
||||||
SLOPE_NORTH = createSlope(Direction.NORTH), SLOPE_SOUTH = createSlope(Direction.SOUTH);
|
|
||||||
|
|
||||||
public BeltBlock() {
|
public BeltBlock() {
|
||||||
super(Properties.from(Blocks.BROWN_WOOL));
|
super(Properties.from(Blocks.BROWN_WOOL));
|
||||||
setDefaultState(getDefaultState().with(SLOPE, Slope.HORIZONTAL).with(PART, Part.START));
|
setDefaultState(getDefaultState().with(SLOPE, Slope.HORIZONTAL).with(PART, Part.START));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasShaftTowards(World world, BlockPos pos, BlockState state, Direction face) {
|
||||||
|
if (face.getAxis() != getRotationAxis(state))
|
||||||
|
return false;
|
||||||
|
BeltTileEntity beltEntity = (BeltTileEntity) world.getTileEntity(pos);
|
||||||
|
return beltEntity != null && beltEntity.hasPulley();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Axis getRotationAxis(BlockState state) {
|
||||||
|
return state.get(HORIZONTAL_FACING).rotateY().getAxis();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos,
|
public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos,
|
||||||
PlayerEntity player) {
|
PlayerEntity player) {
|
||||||
return new ItemStack(AllItems.BELT_CONNECTOR.item);
|
return AllItems.BELT_CONNECTOR.asStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLanded(IBlockReader worldIn, Entity entityIn) {
|
public void onLanded(IBlockReader worldIn, Entity entityIn) {
|
||||||
super.onLanded(worldIn, entityIn);
|
super.onLanded(worldIn, entityIn);
|
||||||
|
|
||||||
if (entityIn instanceof PlayerEntity && entityIn.isSneaking())
|
|
||||||
return;
|
|
||||||
if (entityIn instanceof PlayerEntity && ((PlayerEntity) entityIn).moveVertical > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BeltTileEntity belt = null;
|
|
||||||
BlockPos entityPosition = entityIn.getPosition();
|
BlockPos entityPosition = entityIn.getPosition();
|
||||||
|
BlockPos beltPos = null;
|
||||||
|
|
||||||
if (AllBlocks.BELT.typeOf(worldIn.getBlockState(entityPosition)))
|
if (AllBlocks.BELT.typeOf(worldIn.getBlockState(entityPosition)))
|
||||||
belt = (BeltTileEntity) worldIn.getTileEntity(entityPosition);
|
beltPos = entityPosition;
|
||||||
else if (AllBlocks.BELT.typeOf(worldIn.getBlockState(entityPosition.down())))
|
else if (AllBlocks.BELT.typeOf(worldIn.getBlockState(entityPosition.down())))
|
||||||
belt = (BeltTileEntity) worldIn.getTileEntity(entityPosition.down());
|
beltPos = entityPosition.down();
|
||||||
|
if (beltPos == null)
|
||||||
if (belt == null || !belt.hasSource())
|
return;
|
||||||
|
if (!(worldIn instanceof World))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BeltTileEntity controller = (BeltTileEntity) worldIn.getTileEntity(belt.getController());
|
onEntityCollision(worldIn.getBlockState(beltPos), (World) worldIn, beltPos, entityIn);
|
||||||
|
|
||||||
if (controller == null)
|
|
||||||
return;
|
|
||||||
if (controller.passengers == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (controller.passengers.containsKey(entityIn))
|
|
||||||
controller.passengers.get(entityIn).refresh(belt.getPos(), belt.getBlockState());
|
|
||||||
else
|
|
||||||
controller.passengers.put(entityIn, new TransportedEntityInfo(belt.getPos(), belt.getBlockState()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getSlipperiness(BlockState state, IWorldReader world, BlockPos pos, Entity entity) {
|
|
||||||
return super.getSlipperiness(state, world, pos, entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) {
|
public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) {
|
||||||
if (entityIn instanceof PlayerEntity && entityIn.isSneaking())
|
|
||||||
return;
|
|
||||||
if (entityIn instanceof PlayerEntity && ((PlayerEntity) entityIn).moveVertical > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BeltTileEntity belt = null;
|
BeltTileEntity belt = null;
|
||||||
belt = (BeltTileEntity) worldIn.getTileEntity(pos);
|
belt = (BeltTileEntity) worldIn.getTileEntity(pos);
|
||||||
|
|
||||||
if (belt == null || !belt.hasSource())
|
if (entityIn instanceof PlayerEntity && entityIn.isSneaking())
|
||||||
return;
|
return;
|
||||||
|
if (belt == null || belt.getSpeed() == 0)
|
||||||
|
return;
|
||||||
|
if (entityIn instanceof ItemEntity && entityIn.isAlive()) {
|
||||||
|
if (worldIn.isRemote)
|
||||||
|
return;
|
||||||
|
withTileEntityDo(worldIn, pos, te -> {
|
||||||
|
ItemEntity itemEntity = (ItemEntity) entityIn;
|
||||||
|
ItemStack remainder = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
|
||||||
|
.orElseGet(() -> new ItemStackHandler(0)).insertItem(0, itemEntity.getItem().copy(), false);
|
||||||
|
if (remainder.isEmpty())
|
||||||
|
itemEntity.remove();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BeltTileEntity controller = (BeltTileEntity) worldIn.getTileEntity(belt.getController());
|
BeltTileEntity controller = (BeltTileEntity) worldIn.getTileEntity(belt.getController());
|
||||||
|
if (controller == null || controller.passengers == null)
|
||||||
if (controller == null)
|
|
||||||
return;
|
return;
|
||||||
if (controller.passengers == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (controller.passengers.containsKey(entityIn)) {
|
if (controller.passengers.containsKey(entityIn)) {
|
||||||
TransportedEntityInfo transportedEntityInfo = controller.passengers.get(entityIn);
|
TransportedEntityInfo info = controller.passengers.get(entityIn);
|
||||||
if (transportedEntityInfo.ticksSinceLastCollision != 0 || pos.equals(entityIn.getPosition()))
|
if (info.ticksSinceLastCollision != 0 || pos.equals(entityIn.getPosition()))
|
||||||
transportedEntityInfo.refresh(pos, state);
|
info.refresh(pos, state);
|
||||||
} else
|
} else
|
||||||
controller.passengers.put(entityIn, new TransportedEntityInfo(pos, state));
|
controller.passengers.put(entityIn, new TransportedEntityInfo(pos, state));
|
||||||
}
|
}
|
||||||
@ -167,7 +137,12 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
|
|||||||
return false;
|
return false;
|
||||||
if (worldIn.isRemote)
|
if (worldIn.isRemote)
|
||||||
return true;
|
return true;
|
||||||
withTileEntityDo(worldIn, pos, te -> te.applyColor(DyeColor.getColor(heldItem)));
|
withTileEntityDo(worldIn, pos, te -> {
|
||||||
|
DyeColor dyeColor = DyeColor.getColor(heldItem);
|
||||||
|
if (dyeColor == null)
|
||||||
|
return;
|
||||||
|
te.applyColor(dyeColor);
|
||||||
|
});
|
||||||
if (!player.isCreative())
|
if (!player.isCreative())
|
||||||
heldItem.shrink(1);
|
heldItem.shrink(1);
|
||||||
return true;
|
return true;
|
||||||
@ -186,45 +161,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||||
Direction facing = state.get(HORIZONTAL_FACING);
|
return BeltShapes.getShape(state, worldIn, pos, context);
|
||||||
Axis axis = facing.getAxis();
|
|
||||||
Part part = state.get(PART);
|
|
||||||
Slope slope = state.get(SLOPE);
|
|
||||||
|
|
||||||
if (slope == Slope.HORIZONTAL)
|
|
||||||
return axis == Axis.Z ? FLAT_STRAIGHT_X : FLAT_STRAIGHT_Z;
|
|
||||||
if (slope == Slope.VERTICAL)
|
|
||||||
return axis == Axis.X ? VERTICAL_STRAIGHT_X : VERTICAL_STRAIGHT_Z;
|
|
||||||
|
|
||||||
if (part != Part.MIDDLE) {
|
|
||||||
if (part == Part.START)
|
|
||||||
slope = slope == Slope.UPWARD ? Slope.DOWNWARD : Slope.UPWARD;
|
|
||||||
else
|
|
||||||
facing = facing.getOpposite();
|
|
||||||
|
|
||||||
if (facing == Direction.NORTH)
|
|
||||||
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_NORTH : SLOPE_DOWNWARD_END_NORTH;
|
|
||||||
if (facing == Direction.SOUTH)
|
|
||||||
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_SOUTH : SLOPE_DOWNWARD_END_SOUTH;
|
|
||||||
if (facing == Direction.EAST)
|
|
||||||
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_EAST : SLOPE_DOWNWARD_END_EAST;
|
|
||||||
if (facing == Direction.WEST)
|
|
||||||
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_WEST : SLOPE_DOWNWARD_END_WEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slope == Slope.DOWNWARD)
|
|
||||||
facing = facing.getOpposite();
|
|
||||||
|
|
||||||
if (facing == Direction.NORTH)
|
|
||||||
return SLOPE_NORTH;
|
|
||||||
if (facing == Direction.SOUTH)
|
|
||||||
return SLOPE_SOUTH;
|
|
||||||
if (facing == Direction.EAST)
|
|
||||||
return SLOPE_EAST;
|
|
||||||
if (facing == Direction.WEST)
|
|
||||||
return SLOPE_WEST;
|
|
||||||
|
|
||||||
return FULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -308,19 +245,6 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasShaftTowards(World world, BlockPos pos, BlockState state, Direction face) {
|
|
||||||
if (face.getAxis() != getRotationAxis(state))
|
|
||||||
return false;
|
|
||||||
BeltTileEntity beltEntity = (BeltTileEntity) world.getTileEntity(pos);
|
|
||||||
return beltEntity != null && beltEntity.hasPulley();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Axis getRotationAxis(BlockState state) {
|
|
||||||
return state.get(HORIZONTAL_FACING).getAxis() == Axis.X ? Axis.Z : Axis.X;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Slope implements IStringSerializable {
|
public enum Slope implements IStringSerializable {
|
||||||
HORIZONTAL, UPWARD, DOWNWARD, VERTICAL;
|
HORIZONTAL, UPWARD, DOWNWARD, VERTICAL;
|
||||||
|
|
||||||
@ -339,18 +263,6 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isUpperEnd(BlockState state, float speed) {
|
|
||||||
Direction facing = state.get(HORIZONTAL_FACING);
|
|
||||||
if (state.get(SLOPE) == Slope.UPWARD && state.get(PART) == Part.END) {
|
|
||||||
return facing.getAxisDirection().getOffset() * Math.signum(speed) == (facing.getAxis() == Axis.X ? -1 : 1);
|
|
||||||
}
|
|
||||||
if (state.get(SLOPE) == Slope.DOWNWARD && state.get(PART) == Part.START) {
|
|
||||||
return facing.getAxisDirection().getOffset() * Math.signum(speed) == (facing.getAxis() == Axis.Z ? -1 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<BlockPos> getBeltChain(World world, BlockPos controllerPos) {
|
public static List<BlockPos> getBeltChain(World world, BlockPos controllerPos) {
|
||||||
List<BlockPos> positions = new LinkedList<>();
|
List<BlockPos> positions = new LinkedList<>();
|
||||||
|
|
||||||
@ -382,33 +294,4 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
|
|||||||
return positions;
|
return positions;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static VoxelShape createSlope(Direction facing) {
|
|
||||||
return VoxelShapes.or(createHalfSlope(facing.getOpposite(), false), createHalfSlope(facing, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static VoxelShape createHalfSlope(Direction facing, boolean upward) {
|
|
||||||
VoxelShape shape = VoxelShapes.empty();
|
|
||||||
VoxelShape buildingBlock = facing.getAxis() == Axis.X ? SLOPE_BUILDING_BLOCK_X : SLOPE_BUILDING_BLOCK_Z;
|
|
||||||
Vec3i directionVec = facing.getDirectionVec();
|
|
||||||
|
|
||||||
int x = directionVec.getX();
|
|
||||||
int y = upward ? 1 : -1;
|
|
||||||
int z = directionVec.getZ();
|
|
||||||
|
|
||||||
for (int segment = 0; segment < 6; segment++)
|
|
||||||
shape = VoxelShapes.or(shape,
|
|
||||||
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f));
|
|
||||||
|
|
||||||
if (!upward)
|
|
||||||
return shape;
|
|
||||||
|
|
||||||
VoxelShape mask = makeCuboidShape(0, -8, 0, 16, 24, 16);
|
|
||||||
for (int segment = 6; segment < 11; segment++)
|
|
||||||
shape = VoxelShapes.or(shape,
|
|
||||||
VoxelShapes.combine(mask,
|
|
||||||
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f),
|
|
||||||
IBooleanFunction.AND));
|
|
||||||
return shape;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import java.util.List;
|
|||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.CreateConfig;
|
import com.simibubi.create.CreateConfig;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||||
|
import com.simibubi.create.modules.contraptions.relays.ShaftBlock;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
|
||||||
|
|
||||||
@ -22,9 +23,9 @@ import net.minecraft.util.Direction.AxisDirection;
|
|||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class BeltItem extends Item {
|
public class BeltConnectorItem extends Item {
|
||||||
|
|
||||||
public BeltItem(Properties properties) {
|
public BeltConnectorItem(Properties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,11 +96,22 @@ public class BeltItem extends Item {
|
|||||||
List<BlockPos> beltsToCreate = getBeltChainBetween(start, end, slope, facing);
|
List<BlockPos> beltsToCreate = getBeltChainBetween(start, end, slope, facing);
|
||||||
BlockState beltBlock = AllBlocks.BELT.get().getDefaultState();
|
BlockState beltBlock = AllBlocks.BELT.get().getDefaultState();
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
for (BlockPos pos : beltsToCreate) {
|
for (BlockPos pos : beltsToCreate) {
|
||||||
BeltBlock.Part part = pos.equals(start) ? Part.START : pos.equals(end) ? Part.END : Part.MIDDLE;
|
BeltBlock.Part part = pos.equals(start) ? Part.START : pos.equals(end) ? Part.END : Part.MIDDLE;
|
||||||
|
boolean pulley = AllBlocks.SHAFT.typeOf(world.getBlockState(pos));
|
||||||
world.setBlockState(pos, beltBlock.with(BeltBlock.SLOPE, slope).with(BeltBlock.PART, part)
|
world.setBlockState(pos, beltBlock.with(BeltBlock.SLOPE, slope).with(BeltBlock.PART, part)
|
||||||
.with(BeltBlock.HORIZONTAL_FACING, facing), 3);
|
.with(BeltBlock.HORIZONTAL_FACING, facing), 3);
|
||||||
connectBelt(world, pos, start);
|
|
||||||
|
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(pos);
|
||||||
|
if (te != null) {
|
||||||
|
te.setController(start);
|
||||||
|
te.beltLength = beltsToCreate.size();
|
||||||
|
te.index = index;
|
||||||
|
te.hasPulley = pulley;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,12 +163,6 @@ public class BeltItem extends Item {
|
|||||||
return positions;
|
return positions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connectBelt(World world, BlockPos pos, BlockPos target) {
|
|
||||||
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(pos);
|
|
||||||
if (te != null)
|
|
||||||
te.setController(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean canConnect(World world, BlockPos first, BlockPos second) {
|
public static boolean canConnect(World world, BlockPos first, BlockPos second) {
|
||||||
if (!world.isAreaLoaded(first, 1))
|
if (!world.isAreaLoaded(first, 1))
|
||||||
return false;
|
return false;
|
||||||
@ -190,11 +196,15 @@ public class BeltItem extends Item {
|
|||||||
int limit = 1000;
|
int limit = 1000;
|
||||||
for (BlockPos currentPos = first.add(step); !currentPos.equals(second)
|
for (BlockPos currentPos = first.add(step); !currentPos.equals(second)
|
||||||
&& limit-- > 0; currentPos = currentPos.add(step)) {
|
&& limit-- > 0; currentPos = currentPos.add(step)) {
|
||||||
if (!world.getBlockState(currentPos).getMaterial().isReplaceable())
|
BlockState blockState = world.getBlockState(currentPos);
|
||||||
|
if (AllBlocks.SHAFT.typeOf(blockState) && blockState.get(ShaftBlock.AXIS) == axis)
|
||||||
|
continue;
|
||||||
|
if (!blockState.getMaterial().isReplaceable())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean validateAxis(World world, BlockPos pos) {
|
public static boolean validateAxis(World world, BlockPos pos) {
|
@ -23,7 +23,7 @@ import net.minecraft.util.math.RayTraceResult;
|
|||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class BeltItemHandler {
|
public class BeltConnectorItemHandler {
|
||||||
|
|
||||||
private static Random r = new Random();
|
private static Random r = new Random();
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ public class BeltItemHandler {
|
|||||||
if (!selected.withinDistance(first, CreateConfig.parameters.maxBeltLength.get()))
|
if (!selected.withinDistance(first, CreateConfig.parameters.maxBeltLength.get()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
boolean canConnect = BeltItem.validateAxis(world, selected) && BeltItem.canConnect(world, first, selected);
|
boolean canConnect = BeltConnectorItem.validateAxis(world, selected) && BeltConnectorItem.canConnect(world, first, selected);
|
||||||
|
|
||||||
Vec3d start = new Vec3d(first);
|
Vec3d start = new Vec3d(first);
|
||||||
Vec3d end = new Vec3d(selected);
|
Vec3d end = new Vec3d(selected);
|
@ -0,0 +1,352 @@
|
|||||||
|
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.ListNBT;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.util.math.Vec3i;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.common.util.Constants.NBT;
|
||||||
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
|
||||||
|
public class BeltInventory {
|
||||||
|
|
||||||
|
final BeltTileEntity belt;
|
||||||
|
final List<TransportedItemStack> items;
|
||||||
|
boolean beltMovementPositive;
|
||||||
|
final float SEGMENT_WINDOW = .75f;
|
||||||
|
|
||||||
|
public BeltInventory(BeltTileEntity te) {
|
||||||
|
this.belt = te;
|
||||||
|
items = new LinkedList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
|
||||||
|
// Reverse item collection if belt just reversed
|
||||||
|
if (beltMovementPositive != movingPositive()) {
|
||||||
|
beltMovementPositive = movingPositive();
|
||||||
|
Collections.reverse(items);
|
||||||
|
belt.markDirty();
|
||||||
|
belt.sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assuming the first entry is furthest on the belt
|
||||||
|
TransportedItemStack stackInFront = null;
|
||||||
|
TransportedItemStack current = null;
|
||||||
|
Iterator<TransportedItemStack> iterator = items.iterator();
|
||||||
|
float beltSpeed = belt.getBeltMovementSpeed();
|
||||||
|
float spacing = 1;
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
stackInFront = current;
|
||||||
|
current = iterator.next();
|
||||||
|
|
||||||
|
if (current.stack.isEmpty()) {
|
||||||
|
iterator.remove();
|
||||||
|
current = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float movement = beltSpeed;
|
||||||
|
|
||||||
|
// Don't move if other items are waiting in front
|
||||||
|
float currentPos = current.beltPosition;
|
||||||
|
if (stackInFront != null) {
|
||||||
|
float diff = stackInFront.beltPosition - currentPos;
|
||||||
|
if (Math.abs(diff) <= spacing)
|
||||||
|
continue;
|
||||||
|
movement = beltMovementPositive ? Math.min(movement, diff - spacing)
|
||||||
|
: Math.max(movement, diff + spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
float diffToEnd = beltMovementPositive ? belt.beltLength - currentPos : -currentPos;
|
||||||
|
float limitedMovement = beltMovementPositive ? Math.min(movement, diffToEnd)
|
||||||
|
: Math.max(movement, diffToEnd);
|
||||||
|
|
||||||
|
int segmentBefore = (int) currentPos;
|
||||||
|
float min = segmentBefore + .5f - (SEGMENT_WINDOW / 2);
|
||||||
|
float max = segmentBefore + .5f + (SEGMENT_WINDOW / 2);
|
||||||
|
if (currentPos < min || currentPos > max)
|
||||||
|
segmentBefore = -1;
|
||||||
|
|
||||||
|
current.beltPosition += limitedMovement;
|
||||||
|
|
||||||
|
int segmentAfter = (int) currentPos;
|
||||||
|
min = segmentAfter + .5f - (SEGMENT_WINDOW / 2);
|
||||||
|
max = segmentAfter + .5f + (SEGMENT_WINDOW / 2);
|
||||||
|
if (currentPos < min || currentPos > max)
|
||||||
|
segmentAfter = -1;
|
||||||
|
|
||||||
|
// Item changed segments
|
||||||
|
World world = belt.getWorld();
|
||||||
|
if (segmentBefore != segmentAfter) {
|
||||||
|
for (int segment : new int[] { segmentBefore, segmentAfter }) {
|
||||||
|
if (segment == -1)
|
||||||
|
continue;
|
||||||
|
if (!world.isRemote)
|
||||||
|
world.updateComparatorOutputLevel(getPositionForOffset(segment),
|
||||||
|
belt.getBlockState().getBlock());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End reached
|
||||||
|
if (limitedMovement != movement) {
|
||||||
|
if (world.isRemote)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BlockPos nextPosition = getPositionForOffset(beltMovementPositive ? belt.beltLength : -1);
|
||||||
|
BlockState state = world.getBlockState(nextPosition);
|
||||||
|
Direction movementFacing = belt.getMovementFacing();
|
||||||
|
|
||||||
|
// next block is not a belt
|
||||||
|
if (!AllBlocks.BELT.typeOf(state)) {
|
||||||
|
if (!Block.hasSolidSide(state, world, nextPosition, movementFacing.getOpposite())) {
|
||||||
|
eject(current);
|
||||||
|
iterator.remove();
|
||||||
|
current = null;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next block is a belt
|
||||||
|
TileEntity te = world.getTileEntity(nextPosition);
|
||||||
|
if (te == null || !(te instanceof BeltTileEntity))
|
||||||
|
continue;
|
||||||
|
BeltTileEntity nextBelt = (BeltTileEntity) te;
|
||||||
|
Direction nextMovementFacing = nextBelt.getMovementFacing();
|
||||||
|
|
||||||
|
// next belt goes the opposite way
|
||||||
|
if (nextMovementFacing == movementFacing.getOpposite())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Inserting into other belt
|
||||||
|
BlockPos controller = nextBelt.getController();
|
||||||
|
if (!world.isBlockPresent(controller))
|
||||||
|
continue;
|
||||||
|
te = world.getTileEntity(controller);
|
||||||
|
if (te == null || !(te instanceof BeltTileEntity))
|
||||||
|
continue;
|
||||||
|
BeltTileEntity nextBeltController = (BeltTileEntity) te;
|
||||||
|
BeltInventory nextInventory = nextBeltController.getInventory();
|
||||||
|
|
||||||
|
if (!nextInventory.canInsertAt(nextBelt.index))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
current.beltPosition = nextBelt.index + .5f;
|
||||||
|
current.insertedAt = nextBelt.index;
|
||||||
|
nextInventory.insert(current);
|
||||||
|
iterator.remove();
|
||||||
|
current = null;
|
||||||
|
belt.sendData();
|
||||||
|
nextBeltController.sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TransportedItemStack implements Comparable<TransportedItemStack> {
|
||||||
|
public ItemStack stack;
|
||||||
|
public float beltPosition;
|
||||||
|
public float sideOffset;
|
||||||
|
public int insertedAt;
|
||||||
|
|
||||||
|
public TransportedItemStack(ItemStack stack) {
|
||||||
|
this.stack = stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(TransportedItemStack o) {
|
||||||
|
return beltPosition < o.beltPosition ? 1 : beltPosition > o.beltPosition ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundNBT serializeNBT() {
|
||||||
|
CompoundNBT nbt = new CompoundNBT();
|
||||||
|
nbt.put("Item", stack.serializeNBT());
|
||||||
|
nbt.putFloat("Pos", beltPosition);
|
||||||
|
nbt.putFloat("Offset", sideOffset);
|
||||||
|
nbt.putInt("InSegment", insertedAt);
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TransportedItemStack read(CompoundNBT nbt) {
|
||||||
|
TransportedItemStack stack = new TransportedItemStack(ItemStack.read(nbt.getCompound("Item")));
|
||||||
|
stack.beltPosition = nbt.getFloat("Pos");
|
||||||
|
stack.sideOffset = nbt.getFloat("Offset");
|
||||||
|
stack.insertedAt = nbt.getInt("InSegment");
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canInsertAt(int segment) {
|
||||||
|
float min = segment + .5f - (SEGMENT_WINDOW / 2);
|
||||||
|
float max = segment + .5f + (SEGMENT_WINDOW / 2);
|
||||||
|
|
||||||
|
for (TransportedItemStack stack : items) {
|
||||||
|
float currentPos = stack.beltPosition;
|
||||||
|
|
||||||
|
// Searched past relevant stacks
|
||||||
|
if (beltMovementPositive ? currentPos < segment : currentPos - 1 > segment)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Item inside extraction window
|
||||||
|
if (currentPos > min && currentPos < max)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Items on the belt get prioritized if the previous item was inserted on the
|
||||||
|
// same segment
|
||||||
|
if (stack.insertedAt == segment && currentPos <= segment + 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void insert(TransportedItemStack newStack) {
|
||||||
|
int index = 0;
|
||||||
|
if (items.isEmpty())
|
||||||
|
items.add(newStack);
|
||||||
|
for (TransportedItemStack stack : items) {
|
||||||
|
if (stack.compareTo(newStack) > 0 == beltMovementPositive)
|
||||||
|
break;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
items.add(index, newStack);
|
||||||
|
belt.markDirty();
|
||||||
|
belt.sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TransportedItemStack getStackAtOffset(int offset) {
|
||||||
|
float min = offset + .5f - (SEGMENT_WINDOW / 2);
|
||||||
|
float max = offset + .5f + (SEGMENT_WINDOW / 2);
|
||||||
|
for (TransportedItemStack stack : items) {
|
||||||
|
if (stack.beltPosition > max)
|
||||||
|
break;
|
||||||
|
if (stack.beltPosition > min)
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void read(CompoundNBT nbt) {
|
||||||
|
items.clear();
|
||||||
|
nbt.getList("Items", NBT.TAG_COMPOUND)
|
||||||
|
.forEach(inbt -> items.add(TransportedItemStack.read((CompoundNBT) inbt)));
|
||||||
|
beltMovementPositive = nbt.getBoolean("PositiveOrder");
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundNBT write() {
|
||||||
|
CompoundNBT nbt = new CompoundNBT();
|
||||||
|
ListNBT itemsNBT = new ListNBT();
|
||||||
|
items.forEach(stack -> itemsNBT.add(stack.serializeNBT()));
|
||||||
|
nbt.put("Items", itemsNBT);
|
||||||
|
nbt.putBoolean("PositiveOrder", beltMovementPositive);
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void eject(TransportedItemStack stack) {
|
||||||
|
ItemStack ejected = stack.stack;
|
||||||
|
Vec3d outPos = getVectorForOffset(stack.beltPosition);
|
||||||
|
ItemEntity entity = new ItemEntity(belt.getWorld(), outPos.x, outPos.y, outPos.z, ejected);
|
||||||
|
entity.setMotion(new Vec3d(belt.getBeltChainDirection()).scale(Math.abs(belt.getBeltMovementSpeed())));
|
||||||
|
entity.velocityChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vec3d getVectorForOffset(float offset) {
|
||||||
|
Vec3d vec = VecHelper.getCenterOf(belt.getPos());
|
||||||
|
vec.add(new Vec3d(belt.getBeltChainDirection()).scale(offset));
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockPos getPositionForOffset(int offset) {
|
||||||
|
BlockPos pos = belt.getPos();
|
||||||
|
Vec3i vec = belt.getBeltChainDirection();
|
||||||
|
return pos.add(offset * vec.getX(), offset * vec.getY(), offset * vec.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean movingPositive() {
|
||||||
|
return belt.getBeltMovementSpeed() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ItemHandlerSegment implements IItemHandler {
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
public ItemHandlerSegment(int offset) {
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSlots() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getStackInSlot(int slot) {
|
||||||
|
TransportedItemStack stackAtOffset = getStackAtOffset(offset);
|
||||||
|
if (stackAtOffset == null)
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
return stackAtOffset.stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
|
||||||
|
if (canInsertAt(offset)) {
|
||||||
|
if (!simulate) {
|
||||||
|
TransportedItemStack newStack = new TransportedItemStack(stack);
|
||||||
|
newStack.insertedAt = offset;
|
||||||
|
newStack.beltPosition = offset + .5f;
|
||||||
|
insert(newStack);
|
||||||
|
}
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack extractItem(int slot, int amount, boolean simulate) {
|
||||||
|
TransportedItemStack transported = getStackAtOffset(offset);
|
||||||
|
if (transported == null)
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
|
||||||
|
amount = Math.min(amount, transported.stack.getCount());
|
||||||
|
ItemStack extracted = simulate ? transported.stack.copy().split(amount) : transported.stack.split(amount);
|
||||||
|
if (!simulate) {
|
||||||
|
belt.markDirty();
|
||||||
|
belt.sendData();
|
||||||
|
}
|
||||||
|
return extracted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSlotLimit(int slot) {
|
||||||
|
return Math.min(getStackInSlot(slot).getMaxStackSize(), 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isItemValid(int slot, ItemStack stack) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public IItemHandler createHandlerForSegment(int segment) {
|
||||||
|
return new ItemHandlerSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
|
import com.simibubi.create.foundation.utility.BufferManipulator;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
class BeltModelAnimator extends BufferManipulator {
|
||||||
|
protected static TextureAtlasSprite beltTextures;
|
||||||
|
protected static TextureAtlasSprite originalTexture;
|
||||||
|
|
||||||
|
public BeltModelAnimator(ByteBuffer template) {
|
||||||
|
super(template);
|
||||||
|
if (beltTextures == null)
|
||||||
|
initSprites();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initSprites() {
|
||||||
|
AtlasTexture textureMap = Minecraft.getInstance().getTextureMap();
|
||||||
|
originalTexture = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt"));
|
||||||
|
beltTextures = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt_animated"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer getTransformed(BeltTileEntity te, float x, float y, float z, int color) {
|
||||||
|
original.rewind();
|
||||||
|
mutable.rewind();
|
||||||
|
|
||||||
|
float textureOffsetX = 0;
|
||||||
|
float textureOffsetY = 0;
|
||||||
|
|
||||||
|
if (te.getSpeed() != 0) {
|
||||||
|
float time = AnimationTickHolder.getRenderTick();
|
||||||
|
Direction direction = te.getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
|
||||||
|
if (direction == Direction.EAST || direction == Direction.NORTH)
|
||||||
|
time = -time;
|
||||||
|
int textureIndex = (int) ((te.getSpeed() * time / 8) % 16);
|
||||||
|
if (textureIndex < 0)
|
||||||
|
textureIndex += 16;
|
||||||
|
|
||||||
|
textureOffsetX = beltTextures.getInterpolatedU((textureIndex % 4) * 4) - originalTexture.getMinU();
|
||||||
|
textureOffsetY = beltTextures.getInterpolatedV((textureIndex / 4) * 4) - originalTexture.getMinV();
|
||||||
|
}
|
||||||
|
|
||||||
|
final BlockState blockState = te.getBlockState();
|
||||||
|
int packedLightCoords = blockState.getPackedLightmapCoords(te.getWorld(), te.getPos());
|
||||||
|
float texOffX = textureOffsetX;
|
||||||
|
float texOffY = textureOffsetY;
|
||||||
|
|
||||||
|
boolean defaultColor = color == -1;
|
||||||
|
int b = defaultColor ? 128 : color & 0xFF;
|
||||||
|
int g = defaultColor ? 128 : (color >> 8) & 0xFF;
|
||||||
|
int r = defaultColor ? 128 : (color >> 16) & 0xFF;
|
||||||
|
|
||||||
|
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
|
||||||
|
putPos(mutable, vertex, getX(original, vertex) + x, getY(original, vertex) + y,
|
||||||
|
getZ(original, vertex) + z);
|
||||||
|
putLight(mutable, vertex, packedLightCoords);
|
||||||
|
|
||||||
|
int bufferPosition = getBufferPosition(vertex);
|
||||||
|
mutable.putFloat(bufferPosition + 16, original.getFloat(bufferPosition + 16) + texOffX);
|
||||||
|
mutable.putFloat(bufferPosition + 20, original.getFloat(bufferPosition + 20) + texOffY);
|
||||||
|
|
||||||
|
byte lumByte = getR(original, vertex);
|
||||||
|
float lum = (lumByte < 0 ? 255 + lumByte : lumByte) / 256f;
|
||||||
|
|
||||||
|
int r2 = (int) (r * lum);
|
||||||
|
int g2 = (int) (g * lum);
|
||||||
|
int b2 = (int) (b * lum);
|
||||||
|
putColor(mutable, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mutable;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,184 @@
|
|||||||
|
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||||
|
|
||||||
|
import static net.minecraft.entity.MoverType.SELF;
|
||||||
|
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
|
||||||
|
import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
|
||||||
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
|
||||||
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.potion.EffectInstance;
|
||||||
|
import net.minecraft.potion.Effects;
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.util.math.Vec3i;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class BeltMovementHandler {
|
||||||
|
|
||||||
|
public static class TransportedEntityInfo {
|
||||||
|
int ticksSinceLastCollision;
|
||||||
|
BlockPos lastCollidedPos;
|
||||||
|
BlockState lastCollidedState;
|
||||||
|
|
||||||
|
public TransportedEntityInfo(BlockPos collision, BlockState belt) {
|
||||||
|
refresh(collision, belt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh(BlockPos collision, BlockState belt) {
|
||||||
|
ticksSinceLastCollision = 0;
|
||||||
|
lastCollidedPos = new BlockPos(collision).toImmutable();
|
||||||
|
lastCollidedState = belt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransportedEntityInfo tick() {
|
||||||
|
ticksSinceLastCollision++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canBeTransported(Entity entity) {
|
||||||
|
if (!entity.isAlive())
|
||||||
|
return false;
|
||||||
|
if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isSneaking())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void transportEntity(BeltTileEntity beltTe, Entity entityIn, TransportedEntityInfo info) {
|
||||||
|
BlockPos pos = info.lastCollidedPos;
|
||||||
|
World world = beltTe.getWorld();
|
||||||
|
TileEntity te = world.getTileEntity(pos);
|
||||||
|
TileEntity tileEntityBelowPassenger = world.getTileEntity(entityIn.getPosition());
|
||||||
|
BlockState blockState = info.lastCollidedState;
|
||||||
|
Direction movementFacing = Direction.getFacingFromAxisDirection(
|
||||||
|
blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis(),
|
||||||
|
beltTe.getSpeed() < 0 ? POSITIVE : NEGATIVE);
|
||||||
|
|
||||||
|
boolean collidedWithBelt = te instanceof BeltTileEntity;
|
||||||
|
boolean betweenBelts = tileEntityBelowPassenger instanceof BeltTileEntity && tileEntityBelowPassenger != te;
|
||||||
|
|
||||||
|
// Don't fight other Belts
|
||||||
|
if (!collidedWithBelt || betweenBelts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Too slow
|
||||||
|
boolean notHorizontal = beltTe.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL;
|
||||||
|
if (Math.abs(beltTe.getSpeed()) < (notHorizontal ? 32 : 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Not on top
|
||||||
|
if (entityIn.posY - .25f < pos.getY())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Lock entities in place
|
||||||
|
boolean isPlayer = entityIn instanceof PlayerEntity;
|
||||||
|
if (entityIn instanceof LivingEntity && !isPlayer) {
|
||||||
|
((LivingEntity) entityIn).addPotionEffect(new EffectInstance(Effects.SLOWNESS, 1, 9, false, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
BeltTileEntity belt = (BeltTileEntity) te;
|
||||||
|
|
||||||
|
// Attachment pauses movement
|
||||||
|
for (BeltAttachmentState state : belt.attachmentTracker.attachments) {
|
||||||
|
if (state.attachment.handleEntity(belt, entityIn, state)) {
|
||||||
|
info.ticksSinceLastCollision--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
|
||||||
|
final Slope slope = blockState.get(BeltBlock.SLOPE);
|
||||||
|
final Axis axis = beltFacing.getAxis();
|
||||||
|
float movementSpeed = beltTe.getBeltMovementSpeed();
|
||||||
|
final Direction movementDirection = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis);
|
||||||
|
|
||||||
|
Vec3i centeringDirection = Direction.getFacingFromAxis(POSITIVE, beltFacing.rotateY().getAxis())
|
||||||
|
.getDirectionVec();
|
||||||
|
Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(movementSpeed);
|
||||||
|
|
||||||
|
double diffCenter = axis == Axis.Z ? (pos.getX() + .5f - entityIn.posX) : (pos.getZ() + .5f - entityIn.posZ);
|
||||||
|
if (Math.abs(diffCenter) > 48 / 64f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Part part = blockState.get(BeltBlock.PART);
|
||||||
|
float top = 13 / 16f;
|
||||||
|
boolean onSlope = notHorizontal && (part == Part.MIDDLE
|
||||||
|
|| part == (slope == Slope.UPWARD ? Part.END : Part.START) && entityIn.posY - pos.getY() < top
|
||||||
|
|| part == (slope == Slope.UPWARD ? Part.START : Part.END) && entityIn.posY - pos.getY() > top);
|
||||||
|
|
||||||
|
boolean movingDown = onSlope && slope == (movementFacing == beltFacing ? Slope.DOWNWARD : Slope.UPWARD);
|
||||||
|
boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? Slope.UPWARD : Slope.DOWNWARD);
|
||||||
|
|
||||||
|
if (beltFacing.getAxis() == Axis.Z) {
|
||||||
|
boolean b = movingDown;
|
||||||
|
movingDown = movingUp;
|
||||||
|
movingUp = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (movingUp)
|
||||||
|
movement = movement.add(0, Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
|
||||||
|
if (movingDown)
|
||||||
|
movement = movement.add(0, -Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
|
||||||
|
|
||||||
|
Vec3d centering = new Vec3d(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4);
|
||||||
|
movement = movement.add(centering);
|
||||||
|
|
||||||
|
float step = entityIn.stepHeight;
|
||||||
|
if (!isPlayer)
|
||||||
|
entityIn.stepHeight = 1;
|
||||||
|
|
||||||
|
// Entity Collisions
|
||||||
|
if (Math.abs(movementSpeed) < .5f) {
|
||||||
|
Vec3d checkDistance = movement.scale(2f).add(movement.normalize());
|
||||||
|
AxisAlignedBB bb = entityIn.getBoundingBox();
|
||||||
|
AxisAlignedBB checkBB = new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
|
||||||
|
if (!world
|
||||||
|
.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB.offset(checkDistance)
|
||||||
|
.grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z)))
|
||||||
|
.isEmpty()) {
|
||||||
|
entityIn.setMotion(0, 0, 0);
|
||||||
|
info.ticksSinceLastCollision--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (movingUp) {
|
||||||
|
float minVelocity = .13f;
|
||||||
|
float yMovement = (float) -(Math.max(Math.abs(movement.y), minVelocity));
|
||||||
|
entityIn.move(SELF, new Vec3d(0, yMovement, 0));
|
||||||
|
entityIn.move(SELF, movement.mul(1, 0, 1));
|
||||||
|
} else if (movingDown) {
|
||||||
|
entityIn.move(SELF, movement.mul(1, 0, 1));
|
||||||
|
entityIn.move(SELF, movement.mul(0, 1, 0));
|
||||||
|
} else {
|
||||||
|
entityIn.move(SELF, movement);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPlayer)
|
||||||
|
entityIn.stepHeight = step;
|
||||||
|
|
||||||
|
boolean movedPastEndingSlope = onSlope && (AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition()))
|
||||||
|
|| AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition().down())));
|
||||||
|
|
||||||
|
if (movedPastEndingSlope && !movingDown && Math.abs(movementSpeed) > 0)
|
||||||
|
entityIn.setPosition(entityIn.posX, entityIn.posY + movement.y, entityIn.posZ);
|
||||||
|
if (movedPastEndingSlope) {
|
||||||
|
entityIn.setMotion(movement);
|
||||||
|
entityIn.velocityChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||||
|
|
||||||
|
import static net.minecraft.block.Block.makeCuboidShape;
|
||||||
|
|
||||||
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
|
||||||
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3i;
|
||||||
|
import net.minecraft.util.math.shapes.IBooleanFunction;
|
||||||
|
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShape;
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||||
|
import net.minecraft.world.IBlockReader;
|
||||||
|
|
||||||
|
public class BeltShapes {
|
||||||
|
|
||||||
|
private static final VoxelShape FULL = makeCuboidShape(0, 0, 0, 16, 16, 16),
|
||||||
|
FLAT_STRAIGHT_X = makeCuboidShape(1, 3, 0, 15, 13, 16),
|
||||||
|
FLAT_STRAIGHT_Z = makeCuboidShape(0, 3, 1, 16, 13, 15),
|
||||||
|
VERTICAL_STRAIGHT_X = makeCuboidShape(3, 0, 1, 13, 16, 15),
|
||||||
|
VERTICAL_STRAIGHT_Z = makeCuboidShape(1, 0, 3, 15, 16, 13),
|
||||||
|
|
||||||
|
SLOPE_END_EAST = makeCuboidShape(0, 3, 1, 10, 13, 15),
|
||||||
|
SLOPE_END_WEST = makeCuboidShape(6, 3, 1, 16, 13, 15),
|
||||||
|
SLOPE_END_SOUTH = makeCuboidShape(1, 3, 0, 15, 13, 10),
|
||||||
|
SLOPE_END_NORTH = makeCuboidShape(1, 3, 6, 15, 13, 16),
|
||||||
|
|
||||||
|
SLOPE_BUILDING_BLOCK_X = makeCuboidShape(5, 5, 1, 11, 11, 15),
|
||||||
|
SLOPE_BUILDING_BLOCK_Z = makeCuboidShape(1, 5, 5, 15, 11, 11),
|
||||||
|
|
||||||
|
SLOPE_UPWARD_END_EAST = VoxelShapes.or(SLOPE_END_EAST, createHalfSlope(Direction.EAST, false)),
|
||||||
|
SLOPE_UPWARD_END_WEST = VoxelShapes.or(SLOPE_END_WEST, createHalfSlope(Direction.WEST, false)),
|
||||||
|
SLOPE_UPWARD_END_SOUTH = VoxelShapes.or(SLOPE_END_SOUTH, createHalfSlope(Direction.SOUTH, false)),
|
||||||
|
SLOPE_UPWARD_END_NORTH = VoxelShapes.or(SLOPE_END_NORTH, createHalfSlope(Direction.NORTH, false)),
|
||||||
|
|
||||||
|
SLOPE_DOWNWARD_END_EAST = VoxelShapes.or(SLOPE_END_EAST, createHalfSlope(Direction.EAST, true)),
|
||||||
|
SLOPE_DOWNWARD_END_WEST = VoxelShapes.or(SLOPE_END_WEST, createHalfSlope(Direction.WEST, true)),
|
||||||
|
SLOPE_DOWNWARD_END_SOUTH = VoxelShapes.or(SLOPE_END_SOUTH, createHalfSlope(Direction.SOUTH, true)),
|
||||||
|
SLOPE_DOWNWARD_END_NORTH = VoxelShapes.or(SLOPE_END_NORTH, createHalfSlope(Direction.NORTH, true)),
|
||||||
|
|
||||||
|
SLOPE_EAST = createSlope(Direction.EAST), SLOPE_WEST = createSlope(Direction.WEST),
|
||||||
|
SLOPE_NORTH = createSlope(Direction.NORTH), SLOPE_SOUTH = createSlope(Direction.SOUTH);
|
||||||
|
|
||||||
|
public static VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||||
|
Direction facing = state.get(BeltBlock.HORIZONTAL_FACING);
|
||||||
|
Axis axis = facing.getAxis();
|
||||||
|
Part part = state.get(BeltBlock.PART);
|
||||||
|
Slope slope = state.get(BeltBlock.SLOPE);
|
||||||
|
|
||||||
|
if (slope == Slope.HORIZONTAL)
|
||||||
|
return axis == Axis.Z ? FLAT_STRAIGHT_X : FLAT_STRAIGHT_Z;
|
||||||
|
if (slope == Slope.VERTICAL)
|
||||||
|
return axis == Axis.X ? VERTICAL_STRAIGHT_X : VERTICAL_STRAIGHT_Z;
|
||||||
|
|
||||||
|
if (part != Part.MIDDLE) {
|
||||||
|
boolean upward = slope == Slope.UPWARD;
|
||||||
|
if (part == Part.START)
|
||||||
|
slope = upward ? Slope.DOWNWARD : Slope.UPWARD;
|
||||||
|
else
|
||||||
|
facing = facing.getOpposite();
|
||||||
|
|
||||||
|
if (facing == Direction.NORTH)
|
||||||
|
return upward ? SLOPE_UPWARD_END_NORTH : SLOPE_DOWNWARD_END_NORTH;
|
||||||
|
if (facing == Direction.SOUTH)
|
||||||
|
return upward ? SLOPE_UPWARD_END_SOUTH : SLOPE_DOWNWARD_END_SOUTH;
|
||||||
|
if (facing == Direction.EAST)
|
||||||
|
return upward ? SLOPE_UPWARD_END_EAST : SLOPE_DOWNWARD_END_EAST;
|
||||||
|
if (facing == Direction.WEST)
|
||||||
|
return upward ? SLOPE_UPWARD_END_WEST : SLOPE_DOWNWARD_END_WEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slope == Slope.DOWNWARD)
|
||||||
|
facing = facing.getOpposite();
|
||||||
|
|
||||||
|
if (facing == Direction.NORTH)
|
||||||
|
return SLOPE_NORTH;
|
||||||
|
if (facing == Direction.SOUTH)
|
||||||
|
return SLOPE_SOUTH;
|
||||||
|
if (facing == Direction.EAST)
|
||||||
|
return SLOPE_EAST;
|
||||||
|
if (facing == Direction.WEST)
|
||||||
|
return SLOPE_WEST;
|
||||||
|
|
||||||
|
return FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static VoxelShape createSlope(Direction facing) {
|
||||||
|
return VoxelShapes.or(createHalfSlope(facing.getOpposite(), false), createHalfSlope(facing, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static VoxelShape createHalfSlope(Direction facing, boolean upward) {
|
||||||
|
VoxelShape shape = VoxelShapes.empty();
|
||||||
|
VoxelShape buildingBlock = facing.getAxis() == Axis.X ? SLOPE_BUILDING_BLOCK_X : SLOPE_BUILDING_BLOCK_Z;
|
||||||
|
Vec3i directionVec = facing.getDirectionVec();
|
||||||
|
|
||||||
|
int x = directionVec.getX();
|
||||||
|
int y = upward ? 1 : -1;
|
||||||
|
int z = directionVec.getZ();
|
||||||
|
|
||||||
|
for (int segment = 0; segment < 6; segment++)
|
||||||
|
shape = VoxelShapes.or(shape,
|
||||||
|
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f));
|
||||||
|
|
||||||
|
if (!upward)
|
||||||
|
return shape;
|
||||||
|
|
||||||
|
VoxelShape mask = makeCuboidShape(0, -8, 0, 16, 24, 16);
|
||||||
|
for (int segment = 6; segment < 11; segment++)
|
||||||
|
shape = VoxelShapes.or(shape,
|
||||||
|
VoxelShapes.combine(mask,
|
||||||
|
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f),
|
||||||
|
IBooleanFunction.AND));
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,13 @@
|
|||||||
package com.simibubi.create.modules.contraptions.relays.belt;
|
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||||
|
|
||||||
|
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part.END;
|
||||||
|
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part.MIDDLE;
|
||||||
|
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope.DOWNWARD;
|
||||||
|
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope.HORIZONTAL;
|
||||||
|
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope.UPWARD;
|
||||||
|
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
|
||||||
|
import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -9,113 +17,167 @@ import com.simibubi.create.AllBlocks;
|
|||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.foundation.utility.ColorHelper;
|
import com.simibubi.create.foundation.utility.ColorHelper;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
|
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.Tracker;
|
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.Tracker;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
|
||||||
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.entity.MoverType;
|
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.item.DyeColor;
|
import net.minecraft.item.DyeColor;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.nbt.NBTUtil;
|
import net.minecraft.nbt.NBTUtil;
|
||||||
import net.minecraft.potion.EffectInstance;
|
|
||||||
import net.minecraft.potion.Effects;
|
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.Direction.AxisDirection;
|
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
import net.minecraft.util.math.Vec3i;
|
import net.minecraft.util.math.Vec3i;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
|
||||||
public class BeltTileEntity extends KineticTileEntity {
|
public class BeltTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
protected BlockPos controller;
|
|
||||||
public Map<Entity, TransportedEntityInfo> passengers;
|
public Map<Entity, TransportedEntityInfo> passengers;
|
||||||
public AllBeltAttachments.Tracker attachmentTracker;
|
public AllBeltAttachments.Tracker attachmentTracker;
|
||||||
private CompoundNBT trackerUpdateTag;
|
|
||||||
public int color;
|
public int color;
|
||||||
|
public int beltLength;
|
||||||
|
public int index;
|
||||||
|
public boolean hasPulley;
|
||||||
|
|
||||||
protected static class TransportedEntityInfo {
|
protected BlockPos controller;
|
||||||
int ticksSinceLastCollision;
|
protected BeltInventory inventory;
|
||||||
BlockPos lastCollidedPos;
|
protected LazyOptional<IItemHandler> itemHandler;
|
||||||
BlockState lastCollidedState;
|
|
||||||
|
|
||||||
public TransportedEntityInfo(BlockPos collision, BlockState belt) {
|
private CompoundNBT trackerUpdateTag;
|
||||||
refresh(collision, belt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refresh(BlockPos collision, BlockState belt) {
|
|
||||||
ticksSinceLastCollision = 0;
|
|
||||||
lastCollidedPos = new BlockPos(collision).toImmutable();
|
|
||||||
lastCollidedState = belt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransportedEntityInfo tick() {
|
|
||||||
ticksSinceLastCollision++;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BeltTileEntity() {
|
public BeltTileEntity() {
|
||||||
super(AllTileEntities.BELT.type);
|
super(AllTileEntities.BELT.type);
|
||||||
controller = BlockPos.ZERO;
|
controller = BlockPos.ZERO;
|
||||||
attachmentTracker = new Tracker(this);
|
attachmentTracker = new Tracker(this);
|
||||||
|
itemHandler = LazyOptional.empty();
|
||||||
color = -1;
|
color = -1;
|
||||||
|
beltLength = -1;
|
||||||
|
index = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isLastBelt() {
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
|
// Initialize Belt Attachments
|
||||||
|
if (world != null && trackerUpdateTag != null) {
|
||||||
|
attachmentTracker.readAndSearch(trackerUpdateTag, this);
|
||||||
|
trackerUpdateTag = null;
|
||||||
|
}
|
||||||
if (getSpeed() == 0)
|
if (getSpeed() == 0)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
Direction direction = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
|
initializeItemHandler();
|
||||||
if (getBlockState().get(BeltBlock.SLOPE) == Slope.VERTICAL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Part part = getBlockState().get(BeltBlock.PART);
|
// Move Items
|
||||||
if (part == Part.MIDDLE)
|
if (!isController())
|
||||||
return false;
|
return;
|
||||||
|
getInventory().tick();
|
||||||
|
|
||||||
boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection().getOffset() == 1))
|
// Move Entities
|
||||||
^ direction.getAxis() == Axis.X;
|
if (passengers == null)
|
||||||
return part == Part.START ^ movingPositively;
|
passengers = new HashMap<>();
|
||||||
|
|
||||||
|
List<Entity> toRemove = new ArrayList<>();
|
||||||
|
passengers.forEach((entity, info) -> {
|
||||||
|
boolean canBeTransported = BeltMovementHandler.canBeTransported(entity);
|
||||||
|
boolean leftTheBelt = info.ticksSinceLastCollision > ((getBlockState().get(BeltBlock.SLOPE) != HORIZONTAL)
|
||||||
|
? 3
|
||||||
|
: 1);
|
||||||
|
if (!canBeTransported || leftTheBelt) {
|
||||||
|
toRemove.add(entity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.tick();
|
||||||
|
BeltMovementHandler.transportEntity(this, entity, info);
|
||||||
|
});
|
||||||
|
toRemove.forEach(passengers::remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AxisAlignedBB getRenderBoundingBox() {
|
||||||
|
if (!isController())
|
||||||
|
return super.getRenderBoundingBox();
|
||||||
|
return super.getRenderBoundingBox().grow(beltLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initializeItemHandler() {
|
||||||
|
if (world.isRemote || itemHandler.isPresent())
|
||||||
|
return;
|
||||||
|
if (!world.isBlockPresent(controller))
|
||||||
|
return;
|
||||||
|
TileEntity te = world.getTileEntity(controller);
|
||||||
|
if (te == null || !(te instanceof BeltTileEntity))
|
||||||
|
return;
|
||||||
|
IItemHandler handler = ((BeltTileEntity) te).getInventory().createHandlerForSegment(index);
|
||||||
|
itemHandler = LazyOptional.of(() -> handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFastRenderer() {
|
||||||
|
return !isController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
|
||||||
|
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
|
||||||
|
return itemHandler.cast();
|
||||||
|
return super.getCapability(cap, side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
super.remove();
|
||||||
|
itemHandler.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT write(CompoundNBT compound) {
|
public CompoundNBT write(CompoundNBT compound) {
|
||||||
|
attachmentTracker.write(compound);
|
||||||
compound.put("Controller", NBTUtil.writeBlockPos(controller));
|
compound.put("Controller", NBTUtil.writeBlockPos(controller));
|
||||||
compound.putInt("Color", color);
|
compound.putInt("Color", color);
|
||||||
attachmentTracker.write(compound);
|
compound.putInt("Length", beltLength);
|
||||||
|
compound.putInt("Index", index);
|
||||||
|
compound.putBoolean("Pulley", hasPulley);
|
||||||
|
|
||||||
|
if (isController())
|
||||||
|
compound.put("Inventory", getInventory().write());
|
||||||
return super.write(compound);
|
return super.write(compound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(CompoundNBT compound) {
|
public void read(CompoundNBT compound) {
|
||||||
controller = NBTUtil.readBlockPos(compound.getCompound("Controller"));
|
|
||||||
trackerUpdateTag = compound;
|
trackerUpdateTag = compound;
|
||||||
|
controller = NBTUtil.readBlockPos(compound.getCompound("Controller"));
|
||||||
color = compound.getInt("Color");
|
color = compound.getInt("Color");
|
||||||
|
beltLength = compound.getInt("Length");
|
||||||
|
index = compound.getInt("Index");
|
||||||
|
hasPulley = compound.getBoolean("Pulley");
|
||||||
|
|
||||||
|
if (isController())
|
||||||
|
getInventory().read(compound.getCompound("Inventory"));
|
||||||
super.read(compound);
|
super.read(compound);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyColor(DyeColor colorIn) {
|
public void applyColor(DyeColor colorIn) {
|
||||||
int colorValue = colorIn.getMapColor().colorValue;
|
int colorValue = colorIn.getMapColor().colorValue;
|
||||||
for (BlockPos blockPos : BeltBlock.getBeltChain(world, getController())) {
|
for (BlockPos blockPos : BeltBlock.getBeltChain(world, getController())) {
|
||||||
BeltTileEntity tileEntity = (BeltTileEntity) world.getTileEntity(blockPos);
|
BeltTileEntity belt = (BeltTileEntity) world.getTileEntity(blockPos);
|
||||||
if (tileEntity != null) {
|
if (belt == null)
|
||||||
if (tileEntity.color == -1) {
|
continue;
|
||||||
tileEntity.color = colorValue;
|
belt.color = belt.color == -1 ? colorValue : ColorHelper.mixColors(belt.color, colorValue, .5f);
|
||||||
} else {
|
belt.markDirty();
|
||||||
tileEntity.color = ColorHelper.mixColors(tileEntity.color, colorValue, .5f);
|
belt.sendData();
|
||||||
}
|
|
||||||
tileEntity.sendData();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,178 +193,81 @@ public class BeltTileEntity extends KineticTileEntity {
|
|||||||
return controller.equals(pos);
|
return controller.equals(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getBeltMovementSpeed() {
|
||||||
|
return getSpeed() / 1600f;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasPulley() {
|
public boolean hasPulley() {
|
||||||
if (!AllBlocks.BELT.typeOf(getBlockState()))
|
if (!AllBlocks.BELT.typeOf(getBlockState()))
|
||||||
return false;
|
return false;
|
||||||
return getBlockState().get(BeltBlock.PART) == Part.END || getBlockState().get(BeltBlock.PART) == Part.START;
|
Part part = getBlockState().get(BeltBlock.PART);
|
||||||
|
return part == END || part == Part.START || hasPulley;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected boolean isLastBelt() {
|
||||||
public void tick() {
|
|
||||||
super.tick();
|
|
||||||
|
|
||||||
if (world != null && trackerUpdateTag != null) {
|
|
||||||
attachmentTracker.readAndSearch(trackerUpdateTag, this);
|
|
||||||
trackerUpdateTag = null;
|
|
||||||
}
|
|
||||||
if (!isController())
|
|
||||||
return;
|
|
||||||
if (passengers == null)
|
|
||||||
passengers = new HashMap<>();
|
|
||||||
|
|
||||||
passengers.forEach((entity, info) -> {
|
|
||||||
transportEntity(entity, info);
|
|
||||||
});
|
|
||||||
|
|
||||||
List<Entity> toRemove = new ArrayList<>();
|
|
||||||
passengers.forEach((entity, info) -> {
|
|
||||||
if (!canTransport(entity))
|
|
||||||
toRemove.add(entity);
|
|
||||||
if (info.ticksSinceLastCollision > ((getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL) ? 3 : 1)) {
|
|
||||||
toRemove.add(entity);
|
|
||||||
}
|
|
||||||
info.tick();
|
|
||||||
});
|
|
||||||
toRemove.forEach(e -> {
|
|
||||||
if (e instanceof ItemEntity)
|
|
||||||
((ItemEntity) e).setAgeToCreativeDespawnTime();
|
|
||||||
passengers.remove(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (getSpeed() == 0)
|
if (getSpeed() == 0)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
|
Direction direction = getBeltFacing();
|
||||||
|
if (getBlockState().get(BeltBlock.SLOPE) == Slope.VERTICAL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Part part = getBlockState().get(BeltBlock.PART);
|
||||||
|
if (part == MIDDLE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection().getOffset() == 1))
|
||||||
|
^ direction.getAxis() == Axis.X;
|
||||||
|
return part == Part.START ^ movingPositively;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void transportEntity(Entity entityIn, TransportedEntityInfo info) {
|
public Vec3i getMovementDirection(boolean firstHalf) {
|
||||||
BlockPos pos = info.lastCollidedPos;
|
return this.getMovementDirection(firstHalf, false);
|
||||||
TileEntity te = world.getTileEntity(pos);
|
}
|
||||||
TileEntity tileEntityBelowPassenger = world.getTileEntity(entityIn.getPosition());
|
|
||||||
BlockState blockState = info.lastCollidedState;
|
|
||||||
Direction movementFacing = Direction.getFacingFromAxisDirection(
|
|
||||||
blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis(),
|
|
||||||
getSpeed() < 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE);
|
|
||||||
|
|
||||||
boolean collidedWithBelt = te instanceof BeltTileEntity;
|
public Vec3i getBeltChainDirection() {
|
||||||
boolean betweenBelts = tileEntityBelowPassenger instanceof BeltTileEntity && tileEntityBelowPassenger != te;
|
return this.getMovementDirection(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Don't fight other Belts
|
protected Vec3i getMovementDirection(boolean firstHalf, boolean ignoreHalves) {
|
||||||
if (!collidedWithBelt || betweenBelts) {
|
if (getSpeed() == 0)
|
||||||
return;
|
return BlockPos.ZERO;
|
||||||
}
|
|
||||||
|
|
||||||
// Too slow
|
|
||||||
boolean notHorizontal = getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL;
|
|
||||||
if (Math.abs(getSpeed()) < (notHorizontal ? 32 : 1))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Not on top
|
|
||||||
if (entityIn.posY - .25f < pos.getY())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Lock entities in place
|
|
||||||
if (entityIn instanceof LivingEntity && !(entityIn instanceof PlayerEntity)) {
|
|
||||||
((LivingEntity) entityIn).addPotionEffect(new EffectInstance(Effects.SLOWNESS, 1, 9, false, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
BeltTileEntity belt = (BeltTileEntity) te;
|
|
||||||
|
|
||||||
// Attachment pauses movement
|
|
||||||
for (BeltAttachmentState state : belt.attachmentTracker.attachments) {
|
|
||||||
if (state.attachment.handleEntity(belt, entityIn, state)) {
|
|
||||||
info.ticksSinceLastCollision--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
final BlockState blockState = getBlockState();
|
||||||
final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
|
final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
|
||||||
final Slope slope = blockState.get(BeltBlock.SLOPE);
|
final Slope slope = blockState.get(BeltBlock.SLOPE);
|
||||||
|
final Part part = blockState.get(BeltBlock.PART);
|
||||||
final Axis axis = beltFacing.getAxis();
|
final Axis axis = beltFacing.getAxis();
|
||||||
float movementSpeed = ((KineticTileEntity) te).getSpeed() / 1600f;
|
|
||||||
final Direction movementDirection = Direction
|
|
||||||
.getFacingFromAxis(axis == Axis.X ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE, axis);
|
|
||||||
|
|
||||||
Vec3i centeringDirection = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis == Axis.X ? Axis.Z : Axis.X)
|
Direction movementFacing = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis);
|
||||||
.getDirectionVec();
|
boolean notHorizontal = blockState.get(BeltBlock.SLOPE) != HORIZONTAL;
|
||||||
Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(movementSpeed);
|
if (getSpeed() < 0)
|
||||||
|
movementFacing = movementFacing.getOpposite();
|
||||||
|
Vec3i movement = movementFacing.getDirectionVec();
|
||||||
|
|
||||||
double diffCenter = axis == Axis.Z ? (pos.getX() + .5f - entityIn.posX) : (pos.getZ() + .5f - entityIn.posZ);
|
boolean slopeBeforeHalf = (part == END) == (beltFacing.getAxisDirection() == POSITIVE);
|
||||||
float maxDiffCenter = (entityIn instanceof ItemEntity) ? 32 / 64f : 48 / 64f;
|
boolean onSlope = notHorizontal && (part == MIDDLE || slopeBeforeHalf == firstHalf || ignoreHalves);
|
||||||
if (Math.abs(diffCenter) > maxDiffCenter)
|
boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? UPWARD : DOWNWARD);
|
||||||
return;
|
|
||||||
|
|
||||||
Part part = blockState.get(BeltBlock.PART);
|
if (!onSlope)
|
||||||
float top = 13 / 16f;
|
return movement;
|
||||||
boolean onSlope = notHorizontal && (part == Part.MIDDLE
|
|
||||||
|| part == (slope == Slope.UPWARD ? Part.END : Part.START) && entityIn.posY - pos.getY() < top
|
|
||||||
|| part == (slope == Slope.UPWARD ? Part.START : Part.END) && entityIn.posY - pos.getY() > top);
|
|
||||||
|
|
||||||
boolean movingDown = onSlope && slope == (movementFacing == beltFacing ? Slope.DOWNWARD : Slope.UPWARD);
|
return new Vec3i(movement.getX(), movingUp ? 1 : -1, movement.getZ());
|
||||||
boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? Slope.UPWARD : Slope.DOWNWARD);
|
|
||||||
|
|
||||||
if (beltFacing.getAxis() == Axis.Z) {
|
|
||||||
boolean b = movingDown;
|
|
||||||
movingDown = movingUp;
|
|
||||||
movingUp = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (movingUp)
|
|
||||||
movement = movement.add(0, Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
|
|
||||||
if (movingDown)
|
|
||||||
movement = movement.add(0, -Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
|
|
||||||
|
|
||||||
Vec3d centering = new Vec3d(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4);
|
|
||||||
movement = movement.add(centering);
|
|
||||||
|
|
||||||
float step = entityIn.stepHeight;
|
|
||||||
if (!(entityIn instanceof PlayerEntity))
|
|
||||||
entityIn.stepHeight = 1;
|
|
||||||
|
|
||||||
// Entity Collisions
|
|
||||||
if (Math.abs(movementSpeed) < .5f) {
|
|
||||||
Vec3d checkDistance = movement.scale(2f).add(movement.normalize());
|
|
||||||
AxisAlignedBB bb = entityIn.getBoundingBox();
|
|
||||||
AxisAlignedBB checkBB = new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
|
|
||||||
if (!world
|
|
||||||
.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB.offset(checkDistance)
|
|
||||||
.grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z)))
|
|
||||||
.isEmpty()) {
|
|
||||||
entityIn.setMotion(0, 0, 0);
|
|
||||||
info.ticksSinceLastCollision--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (movingUp) {
|
|
||||||
float minVelocity = entityIn instanceof ItemEntity ? .09f : .13f;
|
|
||||||
float yMovement = (float) -(Math.max(Math.abs(movement.y), minVelocity));
|
|
||||||
entityIn.move(MoverType.SELF, new Vec3d(0, yMovement, 0));
|
|
||||||
entityIn.move(MoverType.SELF, movement.mul(1, 0, 1));
|
|
||||||
} else if (movingDown) {
|
|
||||||
entityIn.move(MoverType.SELF, movement.mul(1, 0, 1));
|
|
||||||
entityIn.move(MoverType.SELF, movement.mul(0, 1, 0));
|
|
||||||
} else {
|
|
||||||
entityIn.move(MoverType.SELF, movement);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(entityIn instanceof PlayerEntity))
|
|
||||||
entityIn.stepHeight = step;
|
|
||||||
|
|
||||||
boolean movedPastEndingSlope = onSlope && (AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition()))
|
|
||||||
|| AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition().down())));
|
|
||||||
|
|
||||||
if (movedPastEndingSlope && !movingDown && Math.abs(movementSpeed) > 0)
|
|
||||||
entityIn.setPosition(entityIn.posX, entityIn.posY + movement.y, entityIn.posZ);
|
|
||||||
if (movedPastEndingSlope)
|
|
||||||
entityIn.setMotion(movement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canTransport(Entity entity) {
|
protected Direction getMovementFacing() {
|
||||||
if (!entity.isAlive())
|
return Direction.getFacingFromAxisDirection(getBeltFacing().getAxis(),
|
||||||
return false;
|
getBeltMovementSpeed() < 0 ? POSITIVE : NEGATIVE);
|
||||||
if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isSneaking())
|
}
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
protected Direction getBeltFacing() {
|
||||||
|
return getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeltInventory getInventory() {
|
||||||
|
if (inventory == null)
|
||||||
|
inventory = new BeltInventory(this);
|
||||||
|
return inventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,114 +1,81 @@
|
|||||||
package com.simibubi.create.modules.contraptions.relays.belt;
|
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.foundation.utility.TessellatorHelper;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
|
||||||
import com.simibubi.create.foundation.utility.BufferManipulator;
|
|
||||||
import com.simibubi.create.modules.contraptions.base.IRotate;
|
import com.simibubi.create.modules.contraptions.base.IRotate;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
||||||
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer.BlockModelSpinner;
|
||||||
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
import net.minecraft.client.renderer.texture.AtlasTexture;
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||||
|
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.util.math.Vec3i;
|
||||||
|
|
||||||
public class BeltTileEntityRenderer extends KineticTileEntityRenderer {
|
@SuppressWarnings("deprecation")
|
||||||
|
public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> {
|
||||||
|
|
||||||
protected static class BeltModelAnimator extends BufferManipulator {
|
@Override
|
||||||
protected static TextureAtlasSprite beltTextures;
|
public void render(BeltTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) {
|
||||||
protected static TextureAtlasSprite originalTexture;
|
super.render(te, x, y, z, partialTicks, destroyStage);
|
||||||
|
if (te.isController()) {
|
||||||
|
GlStateManager.pushMatrix();
|
||||||
|
GlStateManager.translated(x + .5, y + 13 / 16f + .25, z + .5);
|
||||||
|
|
||||||
public BeltModelAnimator(ByteBuffer template) {
|
for (TransportedItemStack transported : te.getInventory().items) {
|
||||||
super(template);
|
GlStateManager.pushMatrix();
|
||||||
if (beltTextures == null)
|
Vec3i direction = te.getBeltChainDirection();
|
||||||
initSprites();
|
float offset = transported.beltPosition;
|
||||||
}
|
Vec3d offsetVec = new Vec3d(direction).scale(offset);
|
||||||
|
GlStateManager.translated(offsetVec.x, offsetVec.y, offsetVec.z);
|
||||||
private void initSprites() {
|
Minecraft.getInstance().getItemRenderer().renderItem(transported.stack, TransformType.FIXED);
|
||||||
AtlasTexture textureMap = Minecraft.getInstance().getTextureMap();
|
GlStateManager.popMatrix();
|
||||||
originalTexture = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt"));
|
|
||||||
beltTextures = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt_animated"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer getTransformed(BeltTileEntity te, float x, float y, float z, int color) {
|
|
||||||
original.rewind();
|
|
||||||
mutable.rewind();
|
|
||||||
|
|
||||||
float textureOffsetX = 0;
|
|
||||||
float textureOffsetY = 0;
|
|
||||||
|
|
||||||
if (te.getSpeed() != 0) {
|
|
||||||
float time = AnimationTickHolder.getRenderTick();
|
|
||||||
Direction direction = te.getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
|
|
||||||
if (direction == Direction.EAST || direction == Direction.NORTH)
|
|
||||||
time = -time;
|
|
||||||
int textureIndex = (int) ((te.getSpeed() * time / 8) % 16);
|
|
||||||
if (textureIndex < 0)
|
|
||||||
textureIndex += 16;
|
|
||||||
|
|
||||||
textureOffsetX = beltTextures.getInterpolatedU((textureIndex % 4) * 4) - originalTexture.getMinU();
|
|
||||||
textureOffsetY = beltTextures.getInterpolatedV((textureIndex / 4) * 4) - originalTexture.getMinV();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final BlockState blockState = te.getBlockState();
|
GlStateManager.popMatrix();
|
||||||
int packedLightCoords = blockState.getPackedLightmapCoords(te.getWorld(), te.getPos());
|
|
||||||
float texOffX = textureOffsetX;
|
|
||||||
float texOffY = textureOffsetY;
|
|
||||||
|
|
||||||
boolean defaultColor = color == -1;
|
|
||||||
int b = defaultColor ? 128 : color & 0xFF;
|
|
||||||
int g = defaultColor ? 128 : (color >> 8) & 0xFF;
|
|
||||||
int r = defaultColor ? 128 : (color >> 16) & 0xFF;
|
|
||||||
|
|
||||||
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
|
|
||||||
putPos(mutable, vertex, getX(original, vertex) + x, getY(original, vertex) + y,
|
|
||||||
getZ(original, vertex) + z);
|
|
||||||
putLight(mutable, vertex, packedLightCoords);
|
|
||||||
|
|
||||||
int bufferPosition = getBufferPosition(vertex);
|
|
||||||
mutable.putFloat(bufferPosition + 16, original.getFloat(bufferPosition + 16) + texOffX);
|
|
||||||
mutable.putFloat(bufferPosition + 20, original.getFloat(bufferPosition + 20) + texOffY);
|
|
||||||
|
|
||||||
byte lumByte = getR(original, vertex);
|
|
||||||
float lum = (lumByte < 0 ? 255 + lumByte : lumByte) / 256f;
|
|
||||||
|
|
||||||
int r2 = (int) (r * lum);
|
|
||||||
int g2 = (int) (g * lum);
|
|
||||||
int b2 = (int) (b * lum);
|
|
||||||
putColor(mutable, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mutable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TessellatorHelper.prepareFastRender();
|
||||||
|
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
|
||||||
|
renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, Tessellator.getInstance().getBuffer());
|
||||||
|
TessellatorHelper.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
|
public void renderTileEntityFast(BeltTileEntity te, double x, double y, double z, float partialTicks,
|
||||||
int destroyStage, BufferBuilder buffer) {
|
int destroyStage, BufferBuilder buffer) {
|
||||||
BeltTileEntity beltEntity = (BeltTileEntity) te;
|
|
||||||
|
|
||||||
if (beltEntity.hasPulley())
|
if (te.hasPulley()) {
|
||||||
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer);
|
final BlockState state = getRenderedBlockState(te);
|
||||||
|
KineticTileEntityRenderer.cacheIfMissing(state, getWorld(), BlockModelSpinner::new);
|
||||||
|
final BlockPos pos = te.getPos();
|
||||||
|
Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState());
|
||||||
|
float angle = KineticTileEntityRenderer.getAngleForTe(te, pos, axis);
|
||||||
|
KineticTileEntityRenderer.renderFromCache(buffer, state, getWorld(), (float) x, (float) y, (float) z, pos,
|
||||||
|
axis, angle);
|
||||||
|
}
|
||||||
|
|
||||||
cacheIfMissing(beltEntity.getBlockState(), getWorld(), BeltModelAnimator::new);
|
KineticTileEntityRenderer.cacheIfMissing(te.getBlockState(), getWorld(), BeltModelAnimator::new);
|
||||||
renderBeltFromCache(beltEntity, (float) x, (float) y, (float) z, buffer);
|
renderBeltFromCache(te, (float) x, (float) y, (float) z, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BlockState getRenderedBlockState(KineticTileEntity te) {
|
protected BlockState getRenderedBlockState(KineticTileEntity te) {
|
||||||
return AllBlocks.BELT_PULLEY.get().getDefaultState().with(BlockStateProperties.AXIS,
|
return AllBlocks.BELT_PULLEY.get().getDefaultState().with(BlockStateProperties.AXIS,
|
||||||
((IRotate) AllBlocks.BELT.get()).getRotationAxis(te.getBlockState()));
|
((IRotate) AllBlocks.BELT.get()).getRotationAxis(te.getBlockState()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderBeltFromCache(BeltTileEntity te, float x, float y, float z, BufferBuilder buffer) {
|
public void renderBeltFromCache(BeltTileEntity te, float x, float y, float z, BufferBuilder buffer) {
|
||||||
buffer.putBulkData(
|
buffer.putBulkData(((BeltModelAnimator) KineticTileEntityRenderer.cachedBuffers.get(te.getBlockState()))
|
||||||
((BeltModelAnimator) cachedBuffers.get(te.getBlockState())).getTransformed(te, x, y, z, te.color));
|
.getTransformed(te, x, y, z, te.color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,120 @@
|
|||||||
|
package com.simibubi.create.modules.contraptions.relays.belt;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.simibubi.create.foundation.utility.BufferManipulator;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
import net.minecraft.client.renderer.ItemRenderer;
|
||||||
|
import net.minecraft.client.renderer.model.IBakedModel;
|
||||||
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||||
|
|
||||||
|
public class FastItemRenderer extends BufferManipulator {
|
||||||
|
|
||||||
|
public FastItemRenderer(ByteBuffer original) {
|
||||||
|
super(original);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer getTranslatedAndRotated(World world, float x, float y, float z, float yaw, float pitch) {
|
||||||
|
original.rewind();
|
||||||
|
mutable.rewind();
|
||||||
|
|
||||||
|
float cosYaw = MathHelper.cos(yaw);
|
||||||
|
float sinYaw = MathHelper.sin(yaw);
|
||||||
|
float cosPitch = MathHelper.cos(pitch);
|
||||||
|
float sinPitch = MathHelper.sin(pitch);
|
||||||
|
|
||||||
|
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
|
||||||
|
float xL = getX(original, vertex); // - (float) rotationOffset.x;
|
||||||
|
float yL = getY(original, vertex); // - (float) rotationOffset.y;
|
||||||
|
float zL = getZ(original, vertex); // - (float) rotationOffset.z;
|
||||||
|
|
||||||
|
float xL2 = rotateX(xL, yL, zL, sinPitch, cosPitch, Axis.X);
|
||||||
|
float yL2 = rotateY(xL, yL, zL, sinPitch, cosPitch, Axis.X);
|
||||||
|
float zL2 = rotateZ(xL, yL, zL, sinPitch, cosPitch, Axis.X);
|
||||||
|
//
|
||||||
|
xL = rotateX(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
|
||||||
|
yL = rotateY(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
|
||||||
|
zL = rotateZ(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
|
||||||
|
|
||||||
|
float xPos = xL + x; // + (float) (offset.x + rotationOffset.x);
|
||||||
|
float yPos = yL + y; // + (float) (offset.y + rotationOffset.y);
|
||||||
|
float zPos = zL + z; // + (float) (offset.z + rotationOffset.z);
|
||||||
|
putPos(mutable, vertex, xPos, yPos, zPos);
|
||||||
|
BlockPos pos = new BlockPos(xPos + .5f, yPos + .5f, zPos + .5f);
|
||||||
|
putLight(mutable, vertex, world.getCombinedLight(pos, 15));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mutable;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Cache<Item, FastItemRenderer> cachedItems;
|
||||||
|
|
||||||
|
public static void renderItem(BufferBuilder buffer, World world, ItemStack stack, float x, float y, float z,
|
||||||
|
float yaw, float pitch) {
|
||||||
|
if (stack.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
|
||||||
|
IBakedModel model = itemRenderer.getModelWithOverrides(stack);
|
||||||
|
|
||||||
|
if (model.isBuiltInRenderer()) {
|
||||||
|
renderItemIntoBuffer(stack, itemRenderer, model, 0, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheIfMissing(stack);
|
||||||
|
FastItemRenderer renderer = cachedItems.getIfPresent(stack.getItem());
|
||||||
|
if (renderer == null)
|
||||||
|
return;
|
||||||
|
buffer.putBulkData(renderer.getTranslatedAndRotated(world, x, y +1, z, yaw, pitch));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void cacheIfMissing(ItemStack stack) {
|
||||||
|
if (cachedItems == null)
|
||||||
|
cachedItems = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.SECONDS).build();
|
||||||
|
if (cachedItems.getIfPresent(stack.getItem()) != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
|
||||||
|
IBakedModel model = itemRenderer.getModelWithOverrides(stack);
|
||||||
|
|
||||||
|
int color = 0;
|
||||||
|
BufferBuilder bufferbuilder = new BufferBuilder(0);
|
||||||
|
bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
||||||
|
renderItemIntoBuffer(stack, itemRenderer, model, color, bufferbuilder);
|
||||||
|
bufferbuilder.finishDrawing();
|
||||||
|
cachedItems.put(stack.getItem(), new FastItemRenderer(bufferbuilder.getByteBuffer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void renderItemIntoBuffer(ItemStack stack, ItemRenderer itemRenderer, IBakedModel model, int color,
|
||||||
|
BufferBuilder bufferbuilder) {
|
||||||
|
Random random = new Random(42L);
|
||||||
|
for (Direction direction : Direction.values())
|
||||||
|
itemRenderer.renderQuads(bufferbuilder, model.getQuads(null, direction, random, EmptyModelData.INSTANCE),
|
||||||
|
color, stack);
|
||||||
|
itemRenderer.renderQuads(bufferbuilder, model.getQuads(null, null, random, EmptyModelData.INSTANCE), color,
|
||||||
|
stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void invalidateCache() {
|
||||||
|
if (cachedItems != null)
|
||||||
|
cachedItems.invalidateAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:block",
|
||||||
|
"pools": [
|
||||||
|
{
|
||||||
|
"rolls": 1,
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"name": "create:belt_support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"condition": "minecraft:survives_explosion"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user