From e742149c8d18ca093348d7fa1c758821bd584751 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Mon, 18 Nov 2019 16:14:26 +0100 Subject: [PATCH] Filterable Funnels - Belt funnels can now be assigned filters for better item routing - Fixed items facing the wrong way if moving on a slope in negative directions - Items can now be picked up from belts by right clicking --- .../com/simibubi/create/AllTileEntities.java | 2 + .../contraptions/relays/belt/BeltBlock.java | 25 ++++++- .../relays/belt/BeltInventory.java | 4 +- .../relays/belt/BeltTileEntity.java | 2 +- .../relays/belt/BeltTileEntityRenderer.java | 5 +- .../block/belts/BeltFunnelBlock.java | 70 ++++++++++++++++++- .../block/belts/BeltFunnelTileEntity.java | 35 +++++++++- .../belts/BeltFunnelTileEntityRenderer.java | 22 ++++++ 8 files changed, 154 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntityRenderer.java diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 168771242..81c136b9b 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -44,6 +44,7 @@ import com.simibubi.create.modules.logistics.block.LinkedTileEntityRenderer; import com.simibubi.create.modules.logistics.block.RedstoneBridgeTileEntity; import com.simibubi.create.modules.logistics.block.StockswitchTileEntity; import com.simibubi.create.modules.logistics.block.belts.BeltFunnelTileEntity; +import com.simibubi.create.modules.logistics.block.belts.BeltFunnelTileEntityRenderer; import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntity; import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntityRenderer; import com.simibubi.create.modules.logistics.block.belts.ExtractorTileEntity; @@ -180,6 +181,7 @@ public enum AllTileEntities { bind(RedstoneBridgeTileEntity.class, new LinkedTileEntityRenderer()); bind(LinkedExtractorTileEntity.class, new LinkedExtractorTileEntityRenderer()); bind(ExtractorTileEntity.class, new ExtractorTileEntityRenderer()); + bind(BeltFunnelTileEntity.class, new BeltFunnelTileEntityRenderer()); bind(EntityDetectorTileEntity.class, new EntityDetectorTileEntityRenderer()); bind(MechanicalPressTileEntity.class, new MechanicalPressTileEntityRenderer()); bind(FlexpeaterTileEntity.class, new FlexpeaterTileEntityRenderer()); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java index ca3d9c498..2d59c8d71 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java @@ -1,5 +1,6 @@ package com.simibubi.create.modules.contraptions.relays.belt; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -114,6 +115,8 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt BeltTileEntity belt = null; belt = (BeltTileEntity) worldIn.getTileEntity(pos); + if (state.get(SLOPE) == Slope.VERTICAL) + return; if (entityIn instanceof PlayerEntity && entityIn.isSneaking()) return; if (belt == null || belt.getSpeed() == 0) @@ -162,6 +165,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt boolean isShaft = heldItem.getItem() == AllBlocks.SHAFT.get().asItem(); boolean isCasing = heldItem.getItem() == AllBlocks.LOGISTICAL_CASING.get().asItem(); boolean isDye = Tags.Items.DYES.contains(heldItem.getItem()); + boolean isHand = heldItem.isEmpty() && handIn == Hand.MAIN_HAND; if (isDye) { if (worldIn.isRemote) @@ -182,6 +186,25 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt return false; BeltTileEntity belt = (BeltTileEntity) te; + if (isHand) { + TileEntity controllerTe = worldIn.getTileEntity(belt.getController()); + if (controllerTe == null || !(controllerTe instanceof BeltTileEntity)) + return false; + if (worldIn.isRemote) + return true; + BeltTileEntity controllerBelt = (BeltTileEntity) controllerTe; + for (Iterator iterator = controllerBelt.getInventory().items.iterator(); iterator + .hasNext();) { + TransportedItemStack transportedItemStack = iterator.next(); + if (Math.abs(belt.index + .5 - transportedItemStack.beltPosition) < .75f) { + player.inventory.placeItemBackInInventory(worldIn, transportedItemStack.stack); + iterator.remove(); + controllerBelt.markDirty(); + controllerBelt.sendData(); + } + } + } + if (isShaft) { if (state.get(PART) != Part.MIDDLE) return false; @@ -255,7 +278,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt public PathNodeType getAiPathNodeType(BlockState state, IBlockReader world, BlockPos pos, MobEntity entity) { return PathNodeType.DANGER_OTHER; } - + @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { return VoxelShapes.or(BeltShapes.getShape(state), BeltShapes.getCasingShape(state)); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java index c2397f6d2..afa335b11 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java @@ -121,8 +121,8 @@ public class BeltInventory { // See if any new belt processing catches the item int upcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f)); for (int segment = upcomingSegment; beltMovementPositive - ? segment <= current.beltPosition + limitedMovement - : segment >= current.beltPosition + limitedMovement; segment += beltMovementPositive ? 1 : -1) { + ? segment + .5f <= current.beltPosition + limitedMovement + : segment + .5f >= current.beltPosition + limitedMovement; segment += beltMovementPositive ? 1 : -1) { BeltTileEntity beltSegment = getBeltSegment(segmentBefore); if (beltSegment == null) break; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java index 282cc42b5..e55311eec 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java @@ -263,7 +263,7 @@ public class BeltTileEntity extends KineticTileEntity { return new Vec3i(movement.getX(), movingUp ? 1 : -1, movement.getZ()); } - protected Direction getMovementFacing() { + public Direction getMovementFacing() { return Direction.getFacingFromAxisDirection(getBeltFacing().getAxis(), getBeltMovementSpeed() < 0 ? POSITIVE : NEGATIVE); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java index 6ff662825..f55c973e7 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java @@ -64,7 +64,8 @@ public class BeltTileEntityRenderer extends TileEntityRenderer { boolean onSlope = slope != Slope.HORIZONTAL && MathHelper.clamp(offset, .5f, te.beltLength - .5f) == offset; float slopeAngle = onSlope - ? slope == Slope.DOWNWARD ^ te.getDirectionAwareBeltMovementSpeed() > 0 ? -45 : 45 + ? slope == Slope.DOWNWARD ^ te.getDirectionAwareBeltMovementSpeed() > 0 + ^ te.getBeltMovementSpeed() < 0 ? -45 : 45 : 0; GlStateManager.translated(offsetVec.x, offsetVec.y, offsetVec.z); @@ -150,5 +151,5 @@ public class BeltTileEntityRenderer extends TileEntityRenderer { buffer.putBulkData(((BeltModelAnimator) KineticTileEntityRenderer.cachedBuffers .get(te.getBlockState().with(BeltBlock.CASING, false))).getTransformed(te, x, y, z, te.color)); } - + } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java index 3f80864a3..8b156f226 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java @@ -1,27 +1,35 @@ package com.simibubi.create.modules.logistics.block.belts; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.block.IWithTileEntity; +import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment; -import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; +import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; +import com.simibubi.create.modules.logistics.block.IBlockWithFilter; import com.simibubi.create.modules.logistics.block.IInventoryManipulator; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.HorizontalBlock; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemStack; import net.minecraft.state.StateContainer.Builder; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; +import net.minecraft.util.Hand; +import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; @@ -30,7 +38,8 @@ import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; -public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, IWithTileEntity { +public class BeltFunnelBlock extends HorizontalBlock + implements IBeltAttachment, IWithTileEntity, IBlockWithFilter { public static final VoxelShape SHAPE_NORTH = makeCuboidShape(3, -4, -1, 13, 8, 5), SHAPE_SOUTH = makeCuboidShape(3, -4, 11, 13, 8, 17), SHAPE_WEST = makeCuboidShape(-1, -4, 3, 5, 8, 13), @@ -38,6 +47,7 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, public BeltFunnelBlock() { super(Properties.from(Blocks.ANDESITE)); + cacheItemPositions(); } @Override @@ -154,6 +164,12 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, @Override public boolean processItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) { + Direction movementFacing = te.getMovementFacing(); + if (movementFacing.getAxis() == Axis.Z) + movementFacing = movementFacing.getOpposite(); + if (movementFacing != te.getWorld().getBlockState(state.attachmentPos) + .get(HORIZONTAL_FACING)) + return false; return process(te, transported, state); } @@ -167,4 +183,54 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, return true; } + @Override + public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + BlockRayTraceResult hit) { + return handleActivatedFilterSlots(state, worldIn, pos, player, handIn, hit); + } + + private static final List itemPositions = new ArrayList<>(Direction.values().length); + + private void cacheItemPositions() { + itemPositions.clear(); + + Vec3d position = Vec3d.ZERO; + Vec3d shift = VecHelper.getCenterOf(BlockPos.ZERO); + float zFightOffset = 1 / 128f; + + for (int i = 0; i < 4; i++) { + Direction facing = Direction.byHorizontalIndex(i); + position = new Vec3d(8f / 16f + zFightOffset, 9f / 16f, 2.25f / 16f); + + float angle = facing.getHorizontalAngle(); + if (facing.getAxis() == Axis.X) + angle = -angle; + + position = VecHelper.rotate(position.subtract(shift), angle, Axis.Y).add(shift); + + itemPositions.add(position); + } + } + + @Override + public boolean showsCount() { + return true; + } + + @Override + public float getItemHitboxScale() { + return 1.76f / 16f; + } + + @Override + public Vec3d getFilterPosition(BlockState state) { + Direction facing = state.get(HORIZONTAL_FACING).getOpposite(); + return itemPositions.get(facing.getHorizontalIndex()); + } + + @Override + public Direction getFilterFacing(BlockState state) { + return state.get(HORIZONTAL_FACING).getOpposite(); + } + } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java index 48dede4ac..9987bc0c3 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java @@ -4,6 +4,7 @@ import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.SyncedTileEntity; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.ItemHandlerSegment; +import com.simibubi.create.modules.logistics.block.IHaveFilter; import com.simibubi.create.modules.logistics.block.IInventoryManipulator; import net.minecraft.item.ItemStack; @@ -21,27 +22,32 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; -public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableTileEntity, IInventoryManipulator { +public class BeltFunnelTileEntity extends SyncedTileEntity + implements ITickableTileEntity, IInventoryManipulator, IHaveFilter { private LazyOptional inventory; protected boolean waitingForInventorySpace; private boolean initialize; + private ItemStack filter; private ItemStack justEaten; public BeltFunnelTileEntity() { super(AllTileEntities.BELT_FUNNEL.type); inventory = LazyOptional.empty(); + filter = ItemStack.EMPTY; } @Override public void read(CompoundNBT compound) { + filter = ItemStack.read(compound.getCompound("Filter")); waitingForInventorySpace = compound.getBoolean("Waiting"); super.read(compound); } @Override public CompoundNBT write(CompoundNBT compound) { + compound.put("Filter", filter.serializeNBT()); compound.putBoolean("Waiting", waitingForInventorySpace); return super.write(compound); } @@ -109,16 +115,26 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT return stack; if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerSegment)) return stack; + if (!filter.isEmpty() && !ItemStack.areItemsEqual(filter, stack)) + return stack; IItemHandler inv = inventory.orElse(null); - ItemStack remainder = ItemHandlerHelper.insertItemStacked(inv, stack.copy(), false); + ItemStack inserted = stack.copy(); + int amountToExtract = Math.min(filter.isEmpty() ? 64 : filter.getCount(), stack.getCount()); + inserted.setCount(amountToExtract); + + ItemStack remainder = ItemHandlerHelper.insertItemStacked(inv, inserted, false); if (remainder.isEmpty()) { if (!world.isRemote) world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_EAT, SoundCategory.BLOCKS, .125f, 1f); - justEaten = stack; + justEaten = stack.copy(); + remainder = stack.copy(); + remainder.setCount(stack.getCount() - amountToExtract); + } else { waitingForInventorySpace = true; + remainder.grow(stack.getCount() - amountToExtract); } sendData(); @@ -134,4 +150,17 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT 1 / 6f, zSpeed); } + @Override + public void setFilter(ItemStack stack) { + filter = stack.copy(); + markDirty(); + sendData(); + neighborChanged(); + } + + @Override + public ItemStack getFilter() { + return filter.copy(); + } + } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntityRenderer.java new file mode 100644 index 000000000..3dac7ee86 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntityRenderer.java @@ -0,0 +1,22 @@ +package com.simibubi.create.modules.logistics.block.belts; + +import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer; + +import net.minecraft.client.renderer.tileentity.TileEntityRenderer; + +public class BeltFunnelTileEntityRenderer extends TileEntityRenderer { + + FilteredTileEntityRenderer filterRenderer; + + public BeltFunnelTileEntityRenderer() { + filterRenderer = new FilteredTileEntityRenderer(); + } + + @Override + public void render(BeltFunnelTileEntity tileEntityIn, double x, double y, double z, float partialTicks, + int destroyStage) { + super.render(tileEntityIn, x, y, z, partialTicks, destroyStage); + filterRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage); + } + +}