From ce1c5d86975843d9a568f78ae3a2fe20e0a4ffef Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Sun, 28 Jun 2020 13:31:11 +0200 Subject: [PATCH] Belt funnel & World funnel implementation - Funnels on belts can now extract and insert items according to their setting and filter - Funnels can now push/pull items to/from a depot - Fixed creative crates not marking their inventory as removed when destroyed - Funnels can now pick up items colliding with their front face - When holding a funnel the game will now always prefer placement over block interaction - Fixed items not able to be held in place by tunnels --- .../java/com/simibubi/create/AllShapes.java | 4 + .../relays/belt/BeltTileEntity.java | 5 +- .../BeltFunnelInteractionHandler.java | 63 +++++++++++ .../relays/belt/transport/BeltInventory.java | 13 ++- .../BeltTunnelInteractionHandler.java | 4 +- .../block/depot/DepotTileEntity.java | 12 +- .../inventories/CreativeCrateTileEntity.java | 14 ++- .../block/realityFunnel/BeltFunnelBlock.java | 25 +++++ .../block/realityFunnel/FunnelItem.java | 12 ++ .../realityFunnel/RealityFunnelBlock.java | 65 ++++++++++- .../RealityFunnelTileEntity.java | 105 +++++++++++++++++- .../TransportedItemStackHandlerBehaviour.java | 14 ++- .../inventory/ExtractingBehaviour.java | 7 +- 13 files changed, 314 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index 787f245af..daddda735 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -69,6 +69,10 @@ public class AllShapes { .add(1, 6, 1, 15, 10, 15) .add(0, 10, 0, 16, 16, 16) .forDirectional(UP), + REALITY_FUNNEL_COLLISION = shape(3, -2, 3, 13, 2, 13).add(2, 2, 2, 14, 6, 14) + .add(1, 6, 1, 15, 10, 15) + .add(0, 10, 0, 16, 13, 16) + .forDirectional(UP), CHUTE_FUNNEL = shape(3, -2, 3, 13, 2, 13).add(2, 2, 2, 14, 6, 14) .add(1, 5, 1, 15, 16, 15) .add(0, 8, 0, 16, 14, 16) diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java index 90d9dba00..d04364db7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java @@ -338,11 +338,12 @@ public class BeltTileEntity extends KineticTileEntity { return inventory; } - private void applyToAllItems(Function> processFunction) { + private void applyToAllItems(float maxDistanceFromCenter, + Function> processFunction) { BeltTileEntity controller = getControllerTE(); if (controller != null) controller.getInventory() - .applyToEachWithin(index + .5f, .51f, processFunction); + .applyToEachWithin(index + .5f, maxDistanceFromCenter, processFunction); } private Vec3d getWorldPositionOf(TransportedItemStack transported) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java new file mode 100644 index 000000000..b15b3d2f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java @@ -0,0 +1,63 @@ +package com.simibubi.create.content.contraptions.relays.belt.transport; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; +import com.simibubi.create.content.logistics.block.realityFunnel.BeltFunnelBlock; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InsertingBehaviour; + +import net.minecraft.block.BlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +public class BeltFunnelInteractionHandler { + + public static boolean checkForFunnels(BeltInventory beltInventory, TransportedItemStack currentItem, + float nextOffset) { + boolean beltMovementPositive = beltInventory.beltMovementPositive; + int firstUpcomingSegment = (int) (currentItem.beltPosition + (beltMovementPositive ? .5f : -.5f)); + int step = beltMovementPositive ? 1 : -1; + firstUpcomingSegment = MathHelper.clamp(firstUpcomingSegment, 0, beltInventory.belt.beltLength - 1); + + for (int segment = firstUpcomingSegment; beltMovementPositive ? segment + .5f <= nextOffset + : segment + .5f >= nextOffset; segment += step) { + BlockPos funnelPos = BeltHelper.getPositionForOffset(beltInventory.belt, segment) + .up(); + World world = beltInventory.belt.getWorld(); + BlockState funnelState = world.getBlockState(funnelPos); + if (!AllBlocks.BELT_FUNNEL.has(funnelState)) + continue; + if (funnelState.get(BeltFunnelBlock.HORIZONTAL_FACING) != beltInventory.belt.getMovementFacing() + .getOpposite()) + continue; + + currentItem.beltPosition = segment + .5f; + + if (funnelState.get(BeltFunnelBlock.PUSHING)) + return true; + if (funnelState.get(BeltFunnelBlock.POWERED)) + return true; + InsertingBehaviour behaviour = TileEntityBehaviour.get(world, funnelPos, InsertingBehaviour.TYPE); + FilteringBehaviour filtering = TileEntityBehaviour.get(world, funnelPos, FilteringBehaviour.TYPE); + if (behaviour == null || world.isRemote) + return true; + if (filtering != null && !filtering.test(currentItem.stack)) + return true; + + ItemStack before = currentItem.stack.copy(); + ItemStack remainder = behaviour.insert(before, false); + if (before.equals(remainder, false)) + return true; + + currentItem.stack = remainder; + beltInventory.belt.sendData(); + return true; + } + + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java index 2106571e9..eeccc7c90 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java @@ -138,7 +138,12 @@ public class BeltInventory { } // Belt Tunnels - BeltTunnelInteractionHandler.flapTunnelsAndCheckIfStuck(this, currentItem, nextOffset); + if (BeltTunnelInteractionHandler.flapTunnelsAndCheckIfStuck(this, currentItem, nextOffset)) + continue; + + // Belt Funnels + if (BeltFunnelInteractionHandler.checkForFunnels(this, currentItem, nextOffset)) + continue; // Apply Movement currentItem.beltPosition += limitedMovement; @@ -154,10 +159,8 @@ public class BeltInventory { int lastOffset = beltMovementPositive ? belt.beltLength - 1 : 0; BlockPos nextPosition = BeltHelper.getPositionForOffset(belt, beltMovementPositive ? belt.beltLength : -1); - if (ending == Ending.FUNNEL) { - // TODO + if (ending == Ending.FUNNEL) continue; - } if (ending == Ending.INSERT) { DirectBeltInputBehaviour inputBehaviour = @@ -267,7 +270,7 @@ public class BeltInventory { } private enum Ending { - UNRESOLVED(0), EJECT(0), INSERT(.25f), FUNNEL(.35f), BLOCKED(.45f); + UNRESOLVED(0), EJECT(0), INSERT(.25f), FUNNEL(.5f), BLOCKED(.45f); private float margin; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java index 7f7d69a75..de2a8bb91 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java @@ -28,8 +28,10 @@ public class BeltTunnelInteractionHandler { if (!beltInventory.beltMovementPositive && nextOffset == 0) upcomingSegment = -1; if (currentSegment != upcomingSegment) { - if (stuckAtTunnel(beltInventory, upcomingSegment, current.stack, movementFacing)) + if (stuckAtTunnel(beltInventory, upcomingSegment, current.stack, movementFacing)) { + current.beltPosition = currentSegment + (beltInventory.beltMovementPositive ? .99f : -.01f); return true; + } if (!beltInventory.belt.getWorld().isRemote) { flapTunnel(beltInventory, currentSegment, movementFacing, false); flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java index 414a6083b..343ab0567 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java @@ -148,9 +148,12 @@ public class DepotTileEntity extends SmartTileEntity { return empty; } - private void applyToAllItems(Function> processFunction) { + private void applyToAllItems(float maxDistanceFromCentre, + Function> processFunction) { if (heldItem == null) return; + if (.5f - heldItem.beltPosition > maxDistanceFromCentre) + return; boolean dirty = false; List toBeAdded = new ArrayList<>(); @@ -187,10 +190,11 @@ public class DepotTileEntity extends SmartTileEntity { sendData(); } } - + public boolean isOutputEmpty() { - for (int i = 0; i < processingOutputBuffer.getSlots(); i++) - if (!processingOutputBuffer.getStackInSlot(i).isEmpty()) + for (int i = 0; i < processingOutputBuffer.getSlots(); i++) + if (!processingOutputBuffer.getStackInSlot(i) + .isEmpty()) return false; return true; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java index a98bee4e5..af0fba545 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java @@ -57,6 +57,12 @@ public class CreativeCrateTileEntity extends CrateTileEntity { otherCrate.filter.setFilter(filter); } + @Override + public void remove() { + if (itemHandler != null) + itemHandler.invalidate(); + } + private CreativeCrateTileEntity getOtherCrate() { if (!AllBlocks.CREATIVE_CRATE.has(getBlockState())) return null; @@ -72,8 +78,9 @@ public class CreativeCrateTileEntity extends CrateTileEntity { CreativeCrateTileEntity otherCrate = getOtherCrate(); if (otherCrate == null) return; - - filter.withCallback($ -> {}); + + filter.withCallback($ -> { + }); filter.setFilter(otherCrate.filter.getFilter()); filter.withCallback(this::filterChanged); } @@ -90,7 +97,8 @@ public class CreativeCrateTileEntity extends CrateTileEntity { @Override protected void rotate(BlockState state, MatrixStack ms) { - MatrixStacker.of(ms).rotateX(90); + MatrixStacker.of(ms) + .rotateX(90); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/BeltFunnelBlock.java index 14feeab13..7d1b7857d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/BeltFunnelBlock.java @@ -1,8 +1,10 @@ package com.simibubi.create.content.logistics.block.realityFunnel; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope; +import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; import com.simibubi.create.content.logistics.block.depot.DepotBlock; import com.simibubi.create.foundation.utility.Lang; @@ -10,9 +12,11 @@ import com.simibubi.create.foundation.utility.VoxelShaper; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.item.BlockItemUseContext; import net.minecraft.state.EnumProperty; import net.minecraft.state.IProperty; import net.minecraft.state.StateContainer.Builder; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; @@ -22,6 +26,7 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.ILightReader; import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; +import net.minecraft.world.World; public class BeltFunnelBlock extends HorizontalInteractionFunnelBlock { @@ -47,6 +52,26 @@ public class BeltFunnelBlock extends HorizontalInteractionFunnelBlock { setDefaultState(getDefaultState().with(SHAPE, Shape.RETRACTED)); } + @Override + public BlockState getStateForPlacement(BlockItemUseContext ctx) { + BlockState state = super.getStateForPlacement(ctx); + World world = ctx.getWorld(); + BlockPos posBelow = ctx.getPos() + .down(); + BlockState stateBelow = world.getBlockState(posBelow); + if (!AllBlocks.BELT.has(stateBelow)) + return state; + TileEntity teBelow = world.getTileEntity(posBelow); + if (teBelow == null || !(teBelow instanceof BeltTileEntity)) + return state; + BeltTileEntity beltTileEntity = (BeltTileEntity) teBelow; + if (beltTileEntity.getSpeed() == 0) + return state; + Direction movementFacing = beltTileEntity.getMovementFacing(); + Direction funnelFacing = ctx.getFace(); + return state.with(PUSHING, movementFacing == funnelFacing); + } + @Override protected void fillStateContainer(Builder p_206840_1_) { super.fillStateContainer(p_206840_1_.add(SHAPE)); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/FunnelItem.java b/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/FunnelItem.java index 5dd0d6ed8..da693fe5b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/FunnelItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/FunnelItem.java @@ -10,13 +10,25 @@ import net.minecraft.util.Direction; import net.minecraft.util.Rotation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.Event.Result; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +@EventBusSubscriber public class FunnelItem extends BlockItem { public FunnelItem(Block p_i48527_1_, Properties p_i48527_2_) { super(p_i48527_1_, p_i48527_2_); } + @SubscribeEvent + public static void funnelItemAlwaysPlacesWhenUsed(PlayerInteractEvent.RightClickBlock event) { + if (event.getItemStack() + .getItem() instanceof FunnelItem) + event.setUseBlock(Result.DENY); + } + @Override protected BlockState getStateForPlacement(BlockItemUseContext ctx) { BlockState state = super.getStateForPlacement(ctx); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/RealityFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/RealityFunnelBlock.java index 69cc5eb62..b0985465a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/RealityFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/RealityFunnelBlock.java @@ -6,17 +6,27 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.logistics.block.chute.ChuteBlock; +import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InsertingBehaviour; +import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.BlockItemUseContext; +import net.minecraft.item.ItemStack; import net.minecraft.state.BooleanProperty; import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; +import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; @@ -24,7 +34,7 @@ import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; -public class RealityFunnelBlock extends ProperDirectionalBlock { +public class RealityFunnelBlock extends ProperDirectionalBlock implements ITE { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; @@ -48,6 +58,39 @@ public class RealityFunnelBlock extends ProperDirectionalBlock { .isBlockPowered(context.getPos())); } + @Override + public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) { + if (worldIn.isRemote) + return; + if (!(entityIn instanceof ItemEntity)) + return; + if (state.get(POWERED)) + return; + ItemEntity itemEntity = (ItemEntity) entityIn; + + Direction direction = state.get(FACING); + Vec3d diff = entityIn.getPositionVec() + .subtract(VecHelper.getCenterOf(pos)); + double projectedDiff = direction.getAxis() + .getCoordinate(diff.x, diff.y, diff.z); + if (projectedDiff < 0 == (direction.getAxisDirection() == AxisDirection.POSITIVE)) + return; + + FilteringBehaviour filter = TileEntityBehaviour.get(worldIn, pos, FilteringBehaviour.TYPE); + InsertingBehaviour inserter = TileEntityBehaviour.get(worldIn, pos, InsertingBehaviour.TYPE); + if (inserter == null) + return; + ItemStack toInsert = itemEntity.getItem(); + if (filter != null && !filter.test(toInsert)) + return; + + ItemStack remainder = inserter.insert(toInsert, false); + if (remainder.isEmpty()) + itemEntity.remove(); + if (remainder.getCount() < toInsert.getCount()) + itemEntity.setItem(remainder); + } + @Override public boolean hasTileEntity(BlockState state) { return true; @@ -64,11 +107,17 @@ public class RealityFunnelBlock extends ProperDirectionalBlock { } @Override - public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, - ISelectionContext p_220053_4_) { + public VoxelShape getShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext context) { return AllShapes.REALITY_FUNNEL.get(state.get(FACING)); } + @Override + public VoxelShape getCollisionShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext context) { + if (context.getEntity() instanceof ItemEntity) + return AllShapes.REALITY_FUNNEL_COLLISION.get(state.get(FACING)); + return getShape(state, world, pos, context); + } + @Override public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState p_196271_3_, IWorld world, BlockPos pos, BlockPos p_196271_6_) { @@ -131,9 +180,8 @@ public class RealityFunnelBlock extends ProperDirectionalBlock { @Override public void onReplaced(BlockState p_196243_1_, World p_196243_2_, BlockPos p_196243_3_, BlockState p_196243_4_, boolean p_196243_5_) { - if (p_196243_1_.hasTileEntity() - && (p_196243_1_.getBlock() != p_196243_4_.getBlock() && !isFunnel(p_196243_4_) - || !p_196243_4_.hasTileEntity())) { + if (p_196243_1_.hasTileEntity() && (p_196243_1_.getBlock() != p_196243_4_.getBlock() && !isFunnel(p_196243_4_) + || !p_196243_4_.hasTileEntity())) { p_196243_2_.removeTileEntity(p_196243_3_); } } @@ -144,4 +192,9 @@ public class RealityFunnelBlock extends ProperDirectionalBlock { || state.getBlock() instanceof HorizontalInteractionFunnelBlock; } + @Override + public Class getTileEntityClass() { + return RealityFunnelTileEntity.class; + } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/RealityFunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/RealityFunnelTileEntity.java index 39283c24a..4e13c7819 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/RealityFunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/realityFunnel/RealityFunnelTileEntity.java @@ -1,36 +1,135 @@ package com.simibubi.create.content.logistics.block.realityFunnel; +import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.inventory.ExtractingBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InsertingBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InventoryManagementBehaviour.Attachments; +import net.minecraft.block.BlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; public class RealityFunnelTileEntity extends SmartTileEntity { private FilteringBehaviour filtering; private InsertingBehaviour inserting; + private ExtractingBehaviour extracting; + + static enum Mode { + INVALID, PAUSED, COLLECT, BELT, CHUTE_SIDE, CHUTE_END + } public RealityFunnelTileEntity(TileEntityType tileEntityTypeIn) { super(tileEntityTypeIn); } + public Mode determineCurrentMode() { + BlockState state = getBlockState(); + if (!RealityFunnelBlock.isFunnel(state)) + return Mode.INVALID; + if (state.get(BlockStateProperties.POWERED)) + return Mode.PAUSED; + if (AllBlocks.BELT_FUNNEL.has(state)) + return Mode.BELT; + if (AllBlocks.CHUTE_FUNNEL.has(state)) + return Mode.CHUTE_SIDE; + + Direction facing = RealityFunnelBlock.getFunnelFacing(state); + BlockState input = world.getBlockState(pos.offset(facing)); + + if (AllBlocks.CHUTE.has(input)) + return Mode.CHUTE_END; + return Mode.COLLECT; + } + + @Override + public void tick() { + super.tick(); + Mode mode = determineCurrentMode(); + if (mode == Mode.BELT) + tickAsBeltFunnel(); + } + + public void tickAsBeltFunnel() { + BlockState blockState = getBlockState(); + Direction facing = blockState.get(BeltFunnelBlock.HORIZONTAL_FACING); + if (world.isRemote) + return; + + if (!blockState.get(BeltFunnelBlock.PUSHING)) { + // Belts handle insertion from their side + if (AllBlocks.BELT.has(world.getBlockState(pos.down()))) + return; + TransportedItemStackHandlerBehaviour handler = + TileEntityBehaviour.get(world, pos.down(), TransportedItemStackHandlerBehaviour.TYPE); + if (handler == null) + return; + handler.handleCenteredProcessingOnAllItems(1 / 32f, this::collectFromHandler); + return; + } + + DirectBeltInputBehaviour inputBehaviour = + TileEntityBehaviour.get(world, pos.down(), DirectBeltInputBehaviour.TYPE); + if (inputBehaviour == null) + return; + if (!inputBehaviour.canInsertFromSide(facing)) + return; + + extracting.setCallback(stack -> inputBehaviour.handleInsertion(stack, facing, false)); + extracting.withAdditionalFilter(stack -> inputBehaviour.handleInsertion(stack, facing, true) + .isEmpty()); + extracting.extract(); + } + + private List collectFromHandler(TransportedItemStack stack) { + ItemStack toInsert = stack.stack.copy(); + if (!filtering.test(toInsert)) + return null; + ItemStack remainder = inserting.insert(toInsert, false); + if (remainder.equals(stack.stack, false)) + return null; + List list = new ArrayList<>(); + if (remainder.isEmpty()) + return list; + TransportedItemStack changed = stack.copy(); + changed.stack = remainder; + list.add(changed); + return list; + } + @Override public void addBehaviours(List behaviours) { + Supplier>> direction = + Attachments.toward(() -> RealityFunnelBlock.getFunnelFacing(getBlockState()) + .getOpposite()); + + inserting = new InsertingBehaviour(this, direction); + extracting = new ExtractingBehaviour(this, direction); filtering = new FilteringBehaviour(this, new FunnelFilterSlotPositioning()); + behaviours.add(filtering); - inserting = - new InsertingBehaviour(this, Attachments.toward(() -> RealityFunnelBlock.getFunnelFacing(getBlockState()))); behaviours.add(inserting); + behaviours.add(extracting); } @Override public double getMaxRenderDistanceSquared() { return 64; } - + } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java index d6484749c..4e667247a 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java @@ -22,20 +22,25 @@ public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour { this.processingCallback = processingCallback; positionGetter = t -> VecHelper.getCenterOf(te.getPos()); } - + public TransportedItemStackHandlerBehaviour withStackPlacement(PositionGetter function) { this.positionGetter = function; return this; } public void handleProcessingOnAllItems(Function> processFunction) { - this.processingCallback.applyToAllItems(processFunction); + handleCenteredProcessingOnAllItems(.51f, processFunction); + } + + public void handleCenteredProcessingOnAllItems(float maxDistanceFromCenter, + Function> processFunction) { + this.processingCallback.applyToAllItems(maxDistanceFromCenter, processFunction); } public Vec3d getWorldPositionOf(TransportedItemStack transported) { return positionGetter.getWorldPositionVector(transported); } - + @Override public BehaviourType getType() { return TYPE; @@ -43,7 +48,8 @@ public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour { @FunctionalInterface public interface ProcessingCallback { - public void applyToAllItems(Function> processFunction); + public void applyToAllItems(float maxDistanceFromCenter, + Function> processFunction); } @FunctionalInterface diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/ExtractingBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/ExtractingBehaviour.java index a7ed96207..aff1a79e1 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/ExtractingBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/ExtractingBehaviour.java @@ -27,8 +27,13 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour { private Predicate customFilter; private Consumer callback; + public ExtractingBehaviour(SmartTileEntity te, Supplier>> attachments) { + this(te, attachments, item -> { + }); + } + public ExtractingBehaviour(SmartTileEntity te, Supplier>> attachments, - Consumer onExtract) { + Consumer onExtract) { super(te, attachments); customAmountFilter = stack -> 64; customFilter = stack -> true;