mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-28 16:06:48 +01:00
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
This commit is contained in:
parent
26112ddc93
commit
16e08a0693
9 changed files with 393 additions and 91 deletions
|
@ -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<BeltTileEnt
|
|||
return slope != BeltSlope.VERTICAL && slope != BeltSlope.SIDEWAYS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
|
||||
updateNeighbouringTunnel(worldIn, pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand handIn,
|
||||
BlockRayTraceResult hit) {
|
||||
|
@ -476,9 +472,6 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
|
|||
return;
|
||||
if (state.getBlock() == newState.getBlock())
|
||||
return;
|
||||
|
||||
updateNeighbouringTunnel(world, pos, state);
|
||||
|
||||
if (isMoving)
|
||||
return;
|
||||
TileEntity belt = world.getTileEntity(pos);
|
||||
|
@ -512,17 +505,19 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
|
|||
world.playEvent(2001, currentPos, Block.getStateId(currentState));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState updatePostPlacement(BlockState state, Direction side, BlockState p_196271_3_,
|
||||
IWorld world, BlockPos pos, BlockPos p_196271_6_) {
|
||||
if (side.getAxis().isHorizontal())
|
||||
updateTunnelConnections(world, pos.up());
|
||||
return state;
|
||||
}
|
||||
|
||||
private void updateNeighbouringTunnel(World world, BlockPos pos, BlockState beltState) {
|
||||
boolean isEnd = beltState.get(PART) != BeltPart.END;
|
||||
if (isEnd && beltState.get(PART) != BeltPart.START)
|
||||
return;
|
||||
int offset = isEnd ? -1 : 1;
|
||||
BlockPos tunnelPos = pos.offset(beltState.get(HORIZONTAL_FACING), offset)
|
||||
.up();
|
||||
Block adjacent = world.getBlockState(tunnelPos).getBlock();
|
||||
if (adjacent instanceof BeltTunnelBlock)
|
||||
((BeltTunnelBlock) adjacent).updateTunnel(world, tunnelPos);
|
||||
private void updateTunnelConnections(IWorld world, BlockPos pos) {
|
||||
Block tunnelBlock = world.getBlockState(pos).getBlock();
|
||||
if (tunnelBlock instanceof BeltTunnelBlock)
|
||||
((BeltTunnelBlock) tunnelBlock).updateTunnel(world, pos);
|
||||
}
|
||||
|
||||
public static List<BlockPos> getBeltChain(World world, BlockPos controllerPos) {
|
||||
|
|
|
@ -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<TileEntityBehaviour> 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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<BeltTunnelTileEntity>,
|
|||
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<BeltTunnelTileEntity>,
|
|||
// 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<BeltTunnelTileEntity>,
|
|||
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))
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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<IItemHandler> 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<IItemHandler> 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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<IItemHandler> beltCapability;
|
||||
private LazyOptional<IItemHandler> tunnelCapability;
|
||||
|
||||
public BrassTunnelTileEntity(TileEntityType<? extends BeltTunnelTileEntity> 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<BrassTunnelTileEntity, Direction> 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<BrassTunnelTileEntity, Direction> 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<Pair<BrassTunnelTileEntity, Direction>> validTargets = new ArrayList<>();
|
||||
for (Pair<BlockPos, Direction> 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<BrassTunnelTileEntity, Direction> 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<Pair<BrassTunnelTileEntity, Direction>> 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 <T> LazyOptional<T> getCapability(Capability<T> capability, Direction side) {
|
||||
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
|
||||
return tunnelCapability.cast();
|
||||
return super.getCapability(capability, side);
|
||||
}
|
||||
|
||||
public LazyOptional<IItemHandler> getBeltCapability() {
|
||||
if (!beltCapability.isPresent()) {
|
||||
TileEntity tileEntity = world.getTileEntity(pos.down());
|
||||
if (tileEntity != null)
|
||||
beltCapability = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
|
||||
}
|
||||
return beltCapability;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue