From 16e08a0693e216f8f91ef2a3a64b07bdc5a41f0b Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Thu, 9 Jul 2020 21:55:14 +0200 Subject: [PATCH] Distribu-tunnel - Fixed dynamic Mechanical Arm parts not being lit correctly - Fixed Mechanical Arm not always initializing interaction points on the client - Belt tunnels now create side-openings for belt-like blocks such as the depot - Belt tunnels no longer create flaps when there is a belt funnel connected to that side - Brass tunnels can now distribute items among their output sides and other connected tunnels, taking into account their sided filtering --- .../contraptions/relays/belt/BeltBlock.java | 31 +-- .../relays/belt/BeltTileEntity.java | 22 +- .../BeltTunnelInteractionHandler.java | 41 ++- .../block/belts/tunnel/BeltTunnelBlock.java | 23 +- .../belts/tunnel/BeltTunnelTileEntity.java | 7 + .../belts/tunnel/BrassTunnelItemHandler.java | 59 ++++ .../belts/tunnel/BrassTunnelTileEntity.java | 262 +++++++++++++++--- .../block/mechanicalArm/ArmRenderer.java | 12 +- .../block/mechanicalArm/ArmTileEntity.java | 27 +- 9 files changed, 393 insertions(+), 91 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelItemHandler.java diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java index 200fa5989..5fc571d61 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java @@ -57,6 +57,7 @@ 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; +import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraft.world.WorldType; @@ -212,11 +213,6 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE getBeltChain(World world, BlockPos controllerPos) { 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 fbade212a..dc6ae7376 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 @@ -19,6 +19,7 @@ import com.simibubi.create.content.contraptions.relays.belt.transport.BeltMoveme import com.simibubi.create.content.contraptions.relays.belt.transport.BeltTunnelInteractionHandler; import com.simibubi.create.content.contraptions.relays.belt.transport.ItemHandlerBeltSegment; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelTileEntity; 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; @@ -79,7 +80,6 @@ public class BeltTileEntity extends KineticTileEntity { public void addBehaviours(List behaviours) { super.addBehaviours(behaviours); behaviours.add(new DirectBeltInputBehaviour(this) - .onlyInsertWhen(d -> getSpeed() != 0 && getMovementFacing() != d.getOpposite()) .setInsertionHandler(this::tryInsertingFromSide)); behaviours.add(new TransportedItemStackHandlerBehaviour(this, this::applyToAllItems) .withStackPlacement(this::getWorldPositionOf)); @@ -397,13 +397,31 @@ public class BeltTileEntity extends KineticTileEntity { BeltTileEntity nextBeltController = getControllerTE(); ItemStack inserted = transportedStack.stack; ItemStack empty = ItemStack.EMPTY; - + if (nextBeltController == null) return inserted; BeltInventory nextInventory = nextBeltController.getInventory(); + + TileEntity teAbove = world.getTileEntity(pos.up()); + if (teAbove instanceof BrassTunnelTileEntity) { + BrassTunnelTileEntity tunnelTE = (BrassTunnelTileEntity) teAbove; + if (tunnelTE.hasDistributionBehaviour()) { + if (!tunnelTE.getStackToDistribute().isEmpty()) + return inserted; + if (!tunnelTE.testFlapFilter(side.getOpposite(), inserted)) + return inserted; + if (!simulate) { + BeltTunnelInteractionHandler.flapTunnel(nextInventory, index, side.getOpposite(), true); + tunnelTE.setStackToDistribute(inserted); + } + return empty; + } + } if (getSpeed() == 0) return inserted; + if (getMovementFacing() == side.getOpposite()) + return inserted; if (!nextInventory.canInsertAtFromSide(index, side)) return inserted; if (simulate) 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 533cfcd25..b916628dc 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,13 +28,35 @@ public class BeltTunnelInteractionHandler { upcomingSegment = -1; if (currentSegment != upcomingSegment) { if (stuckAtTunnel(beltInventory, upcomingSegment, current.stack, movementFacing)) { - current.beltPosition = currentSegment + (beltInventory.beltMovementPositive ? .99f : -.01f); + current.beltPosition = currentSegment + (beltInventory.beltMovementPositive ? .99f : .01f); return true; } - if (!beltInventory.belt.getWorld().isRemote) { + boolean onServer = !beltInventory.belt.getWorld().isRemote; + boolean removed = false; + BeltTunnelTileEntity nextTunnel = getTunnelOnSegement(beltInventory, upcomingSegment); + if (nextTunnel instanceof BrassTunnelTileEntity) { + BrassTunnelTileEntity brassTunnel = (BrassTunnelTileEntity) nextTunnel; + if (brassTunnel.hasDistributionBehaviour()) { + if (!brassTunnel.getStackToDistribute() + .isEmpty()) + return true; + if (onServer) { + brassTunnel.setStackToDistribute(current.stack); + current.stack = ItemStack.EMPTY; + beltInventory.belt.sendData(); + beltInventory.belt.markDirty(); + } + removed = true; + } + } + + if (onServer) { flapTunnel(beltInventory, currentSegment, movementFacing, false); flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true); } + + if (removed) + return true; } return false; @@ -58,21 +80,28 @@ public class BeltTunnelInteractionHandler { } public static void flapTunnel(BeltInventory beltInventory, int offset, Direction side, boolean inward) { + BeltTunnelTileEntity te = getTunnelOnSegement(beltInventory, offset); + if (te == null) + return; + te.flap(side, inward ^ side.getAxis() == Axis.Z); + } + + protected static BeltTunnelTileEntity getTunnelOnSegement(BeltInventory beltInventory, int offset) { BeltTileEntity belt = beltInventory.belt; if (belt.getBlockState() .get(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL) - return; + return null; BlockPos pos = BeltHelper.getPositionForOffset(belt, offset) .up(); if (!(belt.getWorld() .getBlockState(pos) .getBlock() instanceof BeltTunnelBlock)) - return; + return null; TileEntity te = belt.getWorld() .getTileEntity(pos); if (te == null || !(te instanceof BeltTunnelTileEntity)) - return; - ((BeltTunnelTileEntity) te).flap(side, inward ^ side.getAxis() == Axis.Z); + return null; + return ((BeltTunnelTileEntity) te); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java index b25c6d32b..b9690831c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java @@ -7,6 +7,8 @@ import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; @@ -122,7 +124,7 @@ public class BeltTunnelBlock extends Block implements ITE, return tunnelState; } - public void updateTunnel(World world, BlockPos pos) { + public void updateTunnel(IWorld world, BlockPos pos) { BlockState tunnel = world.getBlockState(pos); BlockState newTunnel = getTunnelState(world, pos); if (tunnel != newTunnel) { @@ -144,14 +146,8 @@ public class BeltTunnelBlock extends Block implements ITE, // T and Cross Direction left = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis) .rotateY(); - BlockState leftState = reader.getBlockState(pos.offset(left) - .down()); - boolean onLeft = AllBlocks.BELT.has(leftState) && leftState.get(BeltBlock.HORIZONTAL_FACING) - .getAxis() != axis; - BlockState rightState = reader.getBlockState(pos.offset(left.getOpposite()) - .down()); - boolean onRight = AllBlocks.BELT.has(rightState) && rightState.get(BeltBlock.HORIZONTAL_FACING) - .getAxis() != axis; + boolean onLeft = hasValidOutput(reader, pos.down(), left); + boolean onRight = hasValidOutput(reader, pos.down(), left.getOpposite()); if (onLeft && onRight) state = state.with(SHAPE, Shape.CROSS); @@ -178,6 +174,15 @@ public class BeltTunnelBlock extends Block implements ITE, return state; } + private boolean hasValidOutput(IBlockReader world, BlockPos pos, Direction side) { + BlockState blockState = world.getBlockState(pos.offset(side)); + if (AllBlocks.BELT.has(blockState)) + return blockState.get(BeltBlock.HORIZONTAL_FACING).getAxis() == side.getAxis(); + DirectBeltInputBehaviour behaviour = + TileEntityBehaviour.get(world, pos.offset(side), DirectBeltInputBehaviour.TYPE); + return behaviour != null && behaviour.canInsertFromSide(side); + } + @Override public ActionResultType onWrenched(BlockState state, ItemUseContext context) { if (!hasWindow(state)) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java index cc59e8eff..123476662 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java @@ -10,6 +10,7 @@ import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock.Shape; +import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingValue; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; @@ -130,6 +131,12 @@ public class BeltTunnelTileEntity extends SmartTileEntity { if (!positive && shape == Shape.T_RIGHT) continue; } + + BlockState funnelState = world.getBlockState(getPos().offset(direction)); + if (funnelState.getBlock() instanceof BeltFunnelBlock) + if (funnelState.get(BeltFunnelBlock.HORIZONTAL_FACING) == direction.getOpposite()) + continue; + flaps.put(direction, new InterpolatedChasingValue().start(.25f) .target(0) .withSpeed(.05f)); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelItemHandler.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelItemHandler.java new file mode 100644 index 000000000..b103dd5ae --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelItemHandler.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.logistics.block.belts.tunnel; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; + +public class BrassTunnelItemHandler implements IItemHandler { + + private BrassTunnelTileEntity te; + + public BrassTunnelItemHandler(BrassTunnelTileEntity te) { + this.te = te; + } + + @Override + public int getSlots() { + return 1; + } + + @Override + public ItemStack getStackInSlot(int slot) { + return te.stackToDistribute; + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (!te.hasDistributionBehaviour()) { + LazyOptional beltCapability = te.getBeltCapability(); + if (!beltCapability.isPresent()) + return stack; + return beltCapability.orElse(null).insertItem(slot, stack, simulate); + } + + if (!te.stackToDistribute.isEmpty()) + return stack; + if (!simulate) + te.setStackToDistribute(stack); + return ItemStack.EMPTY; + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + LazyOptional beltCapability = te.getBeltCapability(); + if (!beltCapability.isPresent()) + return ItemStack.EMPTY; + return beltCapability.orElse(null).extractItem(slot, amount, simulate); + } + + @Override + public int getSlotLimit(int slot) { + return te.stackToDistribute.isEmpty() ? 64 : te.stackToDistribute.getMaxStackSize(); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java index ada0f6279..97b70ce99 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java @@ -10,6 +10,7 @@ import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; +import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; @@ -17,7 +18,9 @@ import com.simibubi.create.foundation.tileEntity.behaviour.filtering.SidedFilter import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; +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.NBTUtil; @@ -27,7 +30,12 @@ import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants.NBT; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; public class BrassTunnelTileEntity extends BeltTunnelTileEntity { @@ -42,26 +50,170 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity { int distributionDistanceLeft; int distributionDistanceRight; + private LazyOptional beltCapability; + private LazyOptional tunnelCapability; + public BrassTunnelTileEntity(TileEntityType type) { super(type); distributionTargets = new ArrayList<>(); stackToDistribute = ItemStack.EMPTY; + beltCapability = LazyOptional.empty(); + tunnelCapability = LazyOptional.of(() -> new BrassTunnelItemHandler(this)); } -// @Override -// public void tick() { -// super.tick(); -// -// if (stackToDistribute.isEmpty()) -// return; -// if (distributionProgress == -1) { -// distributionTargets.clear(); -// for (Pair pair : gatherValidOutputs()) { -// -// } -// } -// -// } + @Override + public void tick() { + super.tick(); + BeltTileEntity beltBelow = BeltHelper.getSegmentTE(world, pos.down()); + + if (beltBelow == null || beltBelow.getSpeed() == 0) + return; + if (stackToDistribute.isEmpty()) + return; + if (world.isRemote) + return; + + if (distributionProgress == -1) { + distributionTargets.clear(); + distributionDistanceLeft = 0; + distributionDistanceRight = 0; + for (Pair pair : gatherValidOutputs()) { + BrassTunnelTileEntity tunnel = pair.getKey(); + Direction output = pair.getValue(); + if (!insertIntoTunnel(tunnel, output, stackToDistribute, true).isEmpty()) + continue; + distributionTargets.add(Pair.of(tunnel.pos, output)); + int distance = tunnel.pos.getX() + tunnel.pos.getZ() - pos.getX() - pos.getZ(); + if (distance < 0) + distributionDistanceLeft = Math.max(distributionDistanceLeft, -distance); + else + distributionDistanceRight = Math.max(distributionDistanceRight, distance); + } + + if (distributionTargets.isEmpty()) + return; + + distributionProgress = 0; + sendData(); + return; + } + + // TODO this is instant for now + if (distributionProgress == 0) { + List> validTargets = new ArrayList<>(); + for (Pair pair : distributionTargets) { + BlockPos tunnelPos = pair.getKey(); + Direction output = pair.getValue(); + TileEntity te = world.getTileEntity(tunnelPos); + if (!(te instanceof BrassTunnelTileEntity)) + continue; + validTargets.add(Pair.of((BrassTunnelTileEntity) te, output)); + } + + if (validTargets.size() == 0) { + distributionProgress = -1; + sendData(); + return; + } + + int stackSizeBefore = stackToDistribute.getCount(); + int stackSizeForOutput = stackSizeBefore / validTargets.size(); + int remainder = stackSizeBefore % validTargets.size(); + + for (Pair pair : validTargets) { + BrassTunnelTileEntity tunnel = pair.getKey(); + Direction side = pair.getValue(); + int stackSize = stackSizeForOutput + (remainder > 0 ? 1 : 0); + ItemStack toOutput = stackToDistribute.copy() + .split(stackSize); + if (!insertIntoTunnel(tunnel, side, toOutput, false).isEmpty()) + continue; + stackToDistribute.shrink(stackSize); + remainder--; + } + + distributionProgress = -1; + markDirty(); + sendData(); + return; + } + + } + + public void setStackToDistribute(ItemStack stack) { + stackToDistribute = stack; + distributionProgress = -1; + sendData(); + markDirty(); + } + + public ItemStack getStackToDistribute() { + return stackToDistribute; + } + + protected ItemStack insertIntoTunnel(BrassTunnelTileEntity tunnel, Direction side, ItemStack stack, + boolean simulate) { + if (stack.isEmpty()) + return stack; + if (!tunnel.testFlapFilter(side, stack)) + return stack; + + BeltTileEntity below = BeltHelper.getSegmentTE(world, tunnel.pos.down()); + if (below == null) + return stack; + BlockPos offset = tunnel.getPos() + .down() + .offset(side); + DirectBeltInputBehaviour sideOutput = TileEntityBehaviour.get(world, offset, DirectBeltInputBehaviour.TYPE); + if (sideOutput != null) { + ItemStack result = sideOutput.handleInsertion(stack, side, simulate); + if (result.isEmpty() && !simulate) + tunnel.flap(side, true); + return result; + } + + Direction movementFacing = below.getMovementFacing(); + if (side == movementFacing) + if (!Block.hasSolidSide(world.getBlockState(offset), world, offset, side.getOpposite())) { + BeltTileEntity controllerTE = below.getControllerTE(); + if (controllerTE == null) + return stack; + + if (!simulate) { + tunnel.flap(side, true); + ItemStack ejected = stack; + float beltMovementSpeed = below.getDirectionAwareBeltMovementSpeed(); + float movementSpeed = Math.max(Math.abs(beltMovementSpeed), 1 / 8f); + int additionalOffset = beltMovementSpeed > 0 ? 1 : 0; + Vec3d outPos = BeltHelper.getVectorForOffset(controllerTE, below.index + additionalOffset); + Vec3d outMotion = new Vec3d(side.getDirectionVec()).scale(movementSpeed) + .add(0, 1 / 8f, 0); + outPos.add(outMotion.normalize()); + ItemEntity entity = new ItemEntity(world, outPos.x, outPos.y + 6 / 16f, outPos.z, ejected); + entity.setMotion(outMotion); + entity.setDefaultPickupDelay(); + entity.velocityChanged = true; + world.addEntity(entity); + } + + return ItemStack.EMPTY; + } + + return stack; + } + + public boolean testFlapFilter(Direction side, ItemStack stack) { + if (filtering == null) + return false; + if (filtering.get(side) == null) { + FilteringBehaviour adjacentFilter = + TileEntityBehaviour.get(world, pos.offset(side), FilteringBehaviour.TYPE); + if (adjacentFilter == null) + return true; + return adjacentFilter.test(stack); + } + return filtering.test(side, stack); + } @Override public void initialize() { @@ -75,20 +227,26 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity { public boolean canInsert(Direction side, ItemStack stack) { if (filtering != null && !filtering.test(side, stack)) return false; - if (!connectedLeft && !connectedRight) + if (!hasDistributionBehaviour()) return true; if (!stackToDistribute.isEmpty()) return false; return true; } - public boolean onItemInserted(ItemStack stack) { - if (!connectedLeft && !connectedRight) + public boolean hasDistributionBehaviour() { + if (flaps.isEmpty()) return false; - stackToDistribute = stack.copy(); - sendData(); - markDirty(); - return true; + if (connectedLeft || connectedRight) + return true; + BlockState blockState = getBlockState(); + if (!AllBlocks.BRASS_TUNNEL.has(blockState)) + return false; + Axis axis = blockState.get(BrassTunnelBlock.HORIZONTAL_AXIS); + for (Direction direction : flaps.keySet()) + if (direction.getAxis() != axis) + return true; + return false; } private List> gatherValidOutputs() { @@ -112,27 +270,41 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity { BeltTileEntity below = BeltHelper.getSegmentTE(world, tunnelTE.pos.down()); if (below == null) return; - if (below.getSpeed() != 0) { - Direction direction = below.getMovementFacing(); - if (tunnelTE.flaps.containsKey(direction)) - validOutputs.add(Pair.of(tunnelTE, direction)); - } - + Direction movementFacing = below.getMovementFacing(); BlockState blockState = getBlockState(); if (!AllBlocks.BRASS_TUNNEL.has(blockState)) return; - for (boolean left : Iterate.trueAndFalse) { - Axis axis = blockState.get(BrassTunnelBlock.HORIZONTAL_AXIS); - Direction baseDirection = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); - Direction direction = left ? baseDirection.rotateYCCW() : baseDirection.rotateY(); - if (tunnelTE.flaps.containsKey(direction)) { - DirectBeltInputBehaviour inputBehaviour = TileEntityBehaviour.get(world, tunnelTE.pos.down() - .offset(direction), DirectBeltInputBehaviour.TYPE); + + for (Direction direction : Iterate.horizontalDirections) { + if (direction == movementFacing && below.getSpeed() == 0) + continue; + if (tunnelTE.flaps.containsKey(direction) || tunnelTE.hasValidOutputFunnel(direction)) { + BlockPos offset = tunnelTE.pos.down() + .offset(direction); + DirectBeltInputBehaviour inputBehaviour = + TileEntityBehaviour.get(world, offset, DirectBeltInputBehaviour.TYPE); + if (inputBehaviour == null) { + if (direction == movementFacing) + if (!Block.hasSolidSide(world.getBlockState(offset), world, offset, direction.getOpposite())) + validOutputs.add(Pair.of(tunnelTE, direction)); + continue; + } if (inputBehaviour.canInsertFromSide(direction)) validOutputs.add(Pair.of(tunnelTE, direction)); + continue; } } + } + protected boolean hasValidOutputFunnel(Direction side) { + BlockState funnelState = world.getBlockState(getPos().offset(side)); + if (!(funnelState.getBlock() instanceof BeltFunnelBlock)) + return false; + if (funnelState.has(BeltFunnelBlock.POWERED) && funnelState.get(BeltFunnelBlock.POWERED)) + return false; + if (funnelState.get(BeltFunnelBlock.HORIZONTAL_FACING) != side.getOpposite()) + return false; + return !funnelState.get(BeltFunnelBlock.PUSHING); } @Override @@ -270,4 +442,26 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity { return (BrassTunnelTileEntity) adjacentTE; } + @Override + public void remove() { + tunnelCapability.invalidate(); + super.remove(); + } + + @Override + public LazyOptional getCapability(Capability capability, Direction side) { + if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + return tunnelCapability.cast(); + return super.getCapability(capability, side); + } + + public LazyOptional getBeltCapability() { + if (!beltCapability.isPresent()) { + TileEntity tileEntity = world.getTileEntity(pos.down()); + if (tileEntity != null) + beltCapability = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + } + return beltCapability; + } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java index e9fc9ad50..c7e03a2cf 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java @@ -37,12 +37,12 @@ public class ArmRenderer extends KineticTileEntityRenderer { ms.push(); - SuperByteBuffer base = AllBlockPartials.ARM_BASE.renderOn(blockState); - SuperByteBuffer lowerBody = AllBlockPartials.ARM_LOWER_BODY.renderOn(blockState); - SuperByteBuffer upperBody = AllBlockPartials.ARM_UPPER_BODY.renderOn(blockState); - SuperByteBuffer head = AllBlockPartials.ARM_HEAD.renderOn(blockState); - SuperByteBuffer claw = AllBlockPartials.ARM_CLAW_BASE.renderOn(blockState); - SuperByteBuffer clawGrip = AllBlockPartials.ARM_CLAW_GRIP.renderOn(blockState); + SuperByteBuffer base = AllBlockPartials.ARM_BASE.renderOn(blockState).light(light); + SuperByteBuffer lowerBody = AllBlockPartials.ARM_LOWER_BODY.renderOn(blockState).light(light); + SuperByteBuffer upperBody = AllBlockPartials.ARM_UPPER_BODY.renderOn(blockState).light(light); + SuperByteBuffer head = AllBlockPartials.ARM_HEAD.renderOn(blockState).light(light); + SuperByteBuffer claw = AllBlockPartials.ARM_CLAW_BASE.renderOn(blockState).light(light); + SuperByteBuffer clawGrip = AllBlockPartials.ARM_CLAW_GRIP.renderOn(blockState).light(light); msr.centre(); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java index 88a0b9c88..849406f4f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java @@ -186,12 +186,12 @@ public class ArmTileEntity extends KineticTileEntity { protected void collectItem() { ArmInteractionPoint armInteractionPoint = getTargetedInteractionPoint(); - if (armInteractionPoint != null) + if (armInteractionPoint != null) for (int i = 0; i < armInteractionPoint.getSlotCount(world); i++) { int amountExtracted = getDistributableAmount(armInteractionPoint, i); if (amountExtracted == 0) continue; - + heldItem = armInteractionPoint.extract(world, i, amountExtracted, false); phase = Phase.SEARCH_OUTPUTS; chasedPointProgress = 0; @@ -200,7 +200,7 @@ public class ArmTileEntity extends KineticTileEntity { markDirty(); return; } - + phase = Phase.SEARCH_INPUTS; chasedPointProgress = 0; chasedPointIndex = -1; @@ -218,7 +218,7 @@ public class ArmTileEntity extends KineticTileEntity { } protected void initInteractionPoints() { - if (interactionPointTag == null) + if (!updateInteractionPoints || interactionPointTag == null) return; inputs.clear(); outputs.clear(); @@ -231,9 +231,9 @@ public class ArmTileEntity extends KineticTileEntity { if (point.mode == Mode.TAKE) inputs.add(point); } - interactionPointTag = null; - markDirty(); + updateInteractionPoints = false; sendData(); + markDirty(); } @Override @@ -249,7 +249,7 @@ public class ArmTileEntity extends KineticTileEntity { .forEach(pointsNBT::add); NBTHelper.writeEnum(compound, "Phase", phase); - compound.put("InterationPoints", pointsNBT); + compound.put("InteractionPoints", pointsNBT); compound.put("HeldItem", heldItem.serializeNBT()); compound.putInt("TargetPointIndex", chasedPointIndex); compound.putFloat("MovementProgress", chasedPointProgress); @@ -259,8 +259,6 @@ public class ArmTileEntity extends KineticTileEntity { @Override public CompoundNBT writeToClient(CompoundNBT compound) { super.writeToClient(compound); - if (interactionPointTag != null) - compound.put("InitialInterationPoints", interactionPointTag); return compound; } @@ -271,19 +269,19 @@ public class ArmTileEntity extends KineticTileEntity { phase = NBTHelper.readEnum(compound, "Phase", Phase.class); chasedPointIndex = compound.getInt("TargetPointIndex"); chasedPointProgress = compound.getFloat("MovementProgress"); - - if (!hasWorld() || !world.isRemote || updateInteractionPoints) - interactionPointTag = compound.getList("InterationPoints", NBT.TAG_COMPOUND); - updateInteractionPoints = false; + interactionPointTag = compound.getList("InteractionPoints", NBT.TAG_COMPOUND); } @Override public void readClientUpdate(CompoundNBT tag) { int previousIndex = chasedPointIndex; Phase previousPhase = phase; + ListNBT interactionPointTagBefore = interactionPointTag; super.readClientUpdate(tag); + if (interactionPointTagBefore == null || interactionPointTagBefore.size() != interactionPointTag.size()) + updateInteractionPoints = true; if (previousIndex != chasedPointIndex || (previousPhase != phase)) { ArmInteractionPoint previousPoint = null; if (previousPhase == Phase.MOVE_TO_INPUT && previousIndex < inputs.size()) @@ -294,9 +292,6 @@ public class ArmTileEntity extends KineticTileEntity { if (previousPoint != null) previousBaseAngle = previousPoint.getTargetAngles(pos).baseAngle; } - - if (tag.contains("InitialInterationPoints")) - interactionPointTag = tag.getList("InitialInterationPoints", NBT.TAG_COMPOUND); } }