mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-11 04:22:00 +01:00
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
This commit is contained in:
parent
f7ad748a09
commit
ce1c5d8697
13 changed files with 314 additions and 29 deletions
|
@ -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)
|
||||
|
|
|
@ -338,11 +338,12 @@ public class BeltTileEntity extends KineticTileEntity {
|
|||
return inventory;
|
||||
}
|
||||
|
||||
private void applyToAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||
private void applyToAllItems(float maxDistanceFromCenter,
|
||||
Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||
BeltTileEntity controller = getControllerTE();
|
||||
if (controller != null)
|
||||
controller.getInventory()
|
||||
.applyToEachWithin(index + .5f, .51f, processFunction);
|
||||
.applyToEachWithin(index + .5f, maxDistanceFromCenter, processFunction);
|
||||
}
|
||||
|
||||
private Vec3d getWorldPositionOf(TransportedItemStack transported) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -148,9 +148,12 @@ public class DepotTileEntity extends SmartTileEntity {
|
|||
return empty;
|
||||
}
|
||||
|
||||
private void applyToAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||
private void applyToAllItems(float maxDistanceFromCentre,
|
||||
Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||
if (heldItem == null)
|
||||
return;
|
||||
if (.5f - heldItem.beltPosition > maxDistanceFromCentre)
|
||||
return;
|
||||
|
||||
boolean dirty = false;
|
||||
List<TransportedItemStack> toBeAdded = new ArrayList<>();
|
||||
|
@ -190,7 +193,8 @@ public class DepotTileEntity extends SmartTileEntity {
|
|||
|
||||
public boolean isOutputEmpty() {
|
||||
for (int i = 0; i < processingOutputBuffer.getSlots(); i++)
|
||||
if (!processingOutputBuffer.getStackInSlot(i).isEmpty())
|
||||
if (!processingOutputBuffer.getStackInSlot(i)
|
||||
.isEmpty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -73,7 +79,8 @@ public class CreativeCrateTileEntity extends CrateTileEntity {
|
|||
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
|
||||
|
|
|
@ -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<Block, BlockState> p_206840_1_) {
|
||||
super.fillStateContainer(p_206840_1_.add(SHAPE));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<RealityFunnelTileEntity> {
|
||||
|
||||
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,8 +180,7 @@ 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_)
|
||||
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<RealityFunnelTileEntity> getTileEntityClass() {
|
||||
return RealityFunnelTileEntity.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,31 +1,130 @@
|
|||
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<TransportedItemStack> 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<TransportedItemStack> 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<TileEntityBehaviour> behaviours) {
|
||||
Supplier<List<Pair<BlockPos, Direction>>> 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
|
||||
|
|
|
@ -29,7 +29,12 @@ public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour {
|
|||
}
|
||||
|
||||
public void handleProcessingOnAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||
this.processingCallback.applyToAllItems(processFunction);
|
||||
handleCenteredProcessingOnAllItems(.51f, processFunction);
|
||||
}
|
||||
|
||||
public void handleCenteredProcessingOnAllItems(float maxDistanceFromCenter,
|
||||
Function<TransportedItemStack, List<TransportedItemStack>> processFunction) {
|
||||
this.processingCallback.applyToAllItems(maxDistanceFromCenter, processFunction);
|
||||
}
|
||||
|
||||
public Vec3d getWorldPositionOf(TransportedItemStack transported) {
|
||||
|
@ -43,7 +48,8 @@ public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour {
|
|||
|
||||
@FunctionalInterface
|
||||
public interface ProcessingCallback {
|
||||
public void applyToAllItems(Function<TransportedItemStack, List<TransportedItemStack>> processFunction);
|
||||
public void applyToAllItems(float maxDistanceFromCenter,
|
||||
Function<TransportedItemStack, List<TransportedItemStack>> processFunction);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
|
|
@ -27,6 +27,11 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour {
|
|||
private Predicate<ItemStack> customFilter;
|
||||
private Consumer<ItemStack> callback;
|
||||
|
||||
public ExtractingBehaviour(SmartTileEntity te, Supplier<List<Pair<BlockPos, Direction>>> attachments) {
|
||||
this(te, attachments, item -> {
|
||||
});
|
||||
}
|
||||
|
||||
public ExtractingBehaviour(SmartTileEntity te, Supplier<List<Pair<BlockPos, Direction>>> attachments,
|
||||
Consumer<ItemStack> onExtract) {
|
||||
super(te, attachments);
|
||||
|
|
Loading…
Reference in a new issue