mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-18 07:53:07 +01:00
Global Storage
- Carriages now track stored items and fluids - Fixed a number of inconsistencies in the new PSI behaviour - Fixed several issues with portal cut-off - PSIs can no longer interface with carriage contraptions that are located in two dimensions
This commit is contained in:
parent
d63b12554a
commit
f291dbc03a
21 changed files with 450 additions and 277 deletions
|
@ -24,7 +24,7 @@ public class PortableFluidInterfaceTileEntity extends PortableStorageInterfaceTi
|
|||
@Override
|
||||
public void startTransferringTo(Contraption contraption, float distance) {
|
||||
LazyOptional<IFluidHandler> oldcap = capability;
|
||||
capability = LazyOptional.of(() -> new InterfaceFluidHandler(contraption.fluidInventory));
|
||||
capability = LazyOptional.of(() -> new InterfaceFluidHandler(contraption.getSharedFluidTanks()));
|
||||
oldcap.invalidate();
|
||||
super.startTransferringTo(contraption, distance);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public class PortableItemInterfaceTileEntity extends PortableStorageInterfaceTil
|
|||
@Override
|
||||
public void startTransferringTo(Contraption contraption, float distance) {
|
||||
LazyOptional<IItemHandlerModifiable> oldCap = capability;
|
||||
capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.inventory));
|
||||
capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.getSharedInventory()));
|
||||
oldCap.invalidate();
|
||||
super.startTransferringTo(contraption, distance);
|
||||
}
|
||||
|
|
|
@ -61,24 +61,26 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour {
|
|||
|
||||
@Override
|
||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||
boolean onCarriage = context.contraption instanceof CarriageContraption;
|
||||
if (onCarriage && context.motion.length() > 1 / 4f)
|
||||
return;
|
||||
if (!findInterface(context, pos))
|
||||
context.data.remove(_workingPos_);
|
||||
// if (findInterface(context, pos))
|
||||
// context.stall = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(MovementContext context) {
|
||||
if (context.world.isClientSide) {
|
||||
if (context.world.isClientSide)
|
||||
getAnimation(context).tickChaser();
|
||||
|
||||
boolean onCarriage = context.contraption instanceof CarriageContraption;
|
||||
if (onCarriage && context.motion.length() > 1 / 4f)
|
||||
return;
|
||||
|
||||
if (context.world.isClientSide) {
|
||||
BlockPos pos = new BlockPos(context.position);
|
||||
findInterface(context, pos);
|
||||
if (!context.data.contains(_clientPrevPos_)
|
||||
|| !NbtUtils.readBlockPos(context.data.getCompound(_clientPrevPos_))
|
||||
.equals(pos)) {
|
||||
if (!findInterface(context, pos))
|
||||
reset(context);
|
||||
}
|
||||
if (!findInterface(context, pos))
|
||||
reset(context);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -88,7 +90,7 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour {
|
|||
BlockPos pos = NbtUtils.readBlockPos(context.data.getCompound(_workingPos_));
|
||||
Vec3 target = VecHelper.getCenterOf(pos);
|
||||
|
||||
if (!context.stall
|
||||
if (!context.stall && !onCarriage
|
||||
&& context.position.closerThan(target, target.distanceTo(context.position.add(context.motion))))
|
||||
context.stall = true;
|
||||
|
||||
|
@ -114,6 +116,8 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour {
|
|||
}
|
||||
|
||||
protected boolean findInterface(MovementContext context, BlockPos pos) {
|
||||
if (context.contraption instanceof CarriageContraption cc && !cc.notInPortal())
|
||||
return false;
|
||||
Optional<Direction> currentFacingIfValid = getCurrentFacingIfValid(context);
|
||||
if (!currentFacingIfValid.isPresent())
|
||||
return false;
|
||||
|
@ -121,9 +125,10 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour {
|
|||
Direction currentFacing = currentFacingIfValid.get();
|
||||
PortableStorageInterfaceTileEntity psi =
|
||||
findStationaryInterface(context.world, pos, context.state, currentFacing);
|
||||
|
||||
if (psi == null)
|
||||
return false;
|
||||
if ((psi.isTransferring() || psi.isPowered()) && !context.world.isClientSide)
|
||||
if (psi.isPowered())
|
||||
return false;
|
||||
|
||||
context.data.put(_workingPos_, NbtUtils.writeBlockPos(psi.getBlockPos()));
|
||||
|
@ -170,14 +175,16 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour {
|
|||
private PortableStorageInterfaceTileEntity getStationaryInterfaceAt(Level world, BlockPos pos, BlockState state,
|
||||
Direction facing) {
|
||||
BlockEntity te = world.getBlockEntity(pos);
|
||||
if (!(te instanceof PortableStorageInterfaceTileEntity))
|
||||
if (!(te instanceof PortableStorageInterfaceTileEntity psi))
|
||||
return null;
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
if (blockState.getBlock() != state.getBlock())
|
||||
return null;
|
||||
if (blockState.getValue(PortableStorageInterfaceBlock.FACING) != facing.getOpposite())
|
||||
return null;
|
||||
return (PortableStorageInterfaceTileEntity) te;
|
||||
if (psi.isPowered())
|
||||
return null;
|
||||
return psi;
|
||||
}
|
||||
|
||||
private Optional<Direction> getCurrentFacingIfValid(MovementContext context) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.actors;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
|
@ -52,6 +53,14 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity
|
|||
return connectedEntity != null && isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
powered = level.hasNeighborSignal(worldPosition);
|
||||
if (!powered)
|
||||
notifyContraptions();
|
||||
}
|
||||
|
||||
protected abstract void invalidateCapability();
|
||||
|
||||
@Override
|
||||
|
@ -109,7 +118,10 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity
|
|||
super.read(compound, clientPacket);
|
||||
transferTimer = compound.getInt("Timer");
|
||||
distance = compound.getFloat("Distance");
|
||||
boolean poweredPreviously = powered;
|
||||
powered = compound.getBoolean("Powered");
|
||||
if (clientPacket && powered != poweredPreviously && !powered)
|
||||
notifyContraptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -125,9 +137,18 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity
|
|||
if (isBlockPowered == powered)
|
||||
return;
|
||||
powered = isBlockPowered;
|
||||
if (!powered)
|
||||
notifyContraptions();
|
||||
if (powered)
|
||||
stopTransferring();
|
||||
sendData();
|
||||
}
|
||||
|
||||
private void notifyContraptions() {
|
||||
level.getEntitiesOfClass(AbstractContraptionEntity.class, new AABB(worldPosition).inflate(3))
|
||||
.forEach(AbstractContraptionEntity::refreshPSIs);
|
||||
}
|
||||
|
||||
public boolean isPowered() {
|
||||
return powered;
|
||||
}
|
||||
|
|
|
@ -36,17 +36,21 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
|
|||
|
||||
@Override
|
||||
public Vec3 getActiveAreaOffset(MovementContext context) {
|
||||
return Vec3.atLowerCornerOf(context.state.getValue(SawBlock.FACING).getNormal()).scale(.65f);
|
||||
return Vec3.atLowerCornerOf(context.state.getValue(SawBlock.FACING)
|
||||
.getNormal())
|
||||
.scale(.65f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||
super.visitNewPosition(context, pos);
|
||||
Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(SawBlock.FACING).getNormal());
|
||||
Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(SawBlock.FACING)
|
||||
.getNormal());
|
||||
facingVec = context.rotation.apply(facingVec);
|
||||
|
||||
Direction closestToFacing = Direction.getNearest(facingVec.x, facingVec.y, facingVec.z);
|
||||
if(closestToFacing.getAxis().isVertical() && context.data.contains("BreakingPos")) {
|
||||
if (closestToFacing.getAxis()
|
||||
.isVertical() && context.data.contains("BreakingPos")) {
|
||||
context.data.remove("BreakingPos");
|
||||
context.stall = false;
|
||||
}
|
||||
|
@ -64,15 +68,17 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
|
|||
|
||||
Optional<AbstractBlockBreakQueue> dynamicTree = TreeCutter.findDynamicTree(brokenState.getBlock(), pos);
|
||||
if (dynamicTree.isPresent()) {
|
||||
dynamicTree.get().destroyBlocks(context.world, null, (stack, dropPos) -> dropItemFromCutTree(context, stack, dropPos));
|
||||
dynamicTree.get()
|
||||
.destroyBlocks(context.world, null, (stack, dropPos) -> dropItemFromCutTree(context, stack, dropPos));
|
||||
return;
|
||||
}
|
||||
|
||||
TreeCutter.findTree(context.world, pos).destroyBlocks(context.world, null, (stack, dropPos) -> dropItemFromCutTree(context, stack, dropPos));
|
||||
TreeCutter.findTree(context.world, pos)
|
||||
.destroyBlocks(context.world, null, (stack, dropPos) -> dropItemFromCutTree(context, stack, dropPos));
|
||||
}
|
||||
|
||||
public void dropItemFromCutTree(MovementContext context, BlockPos pos, ItemStack stack) {
|
||||
ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, stack, false);
|
||||
ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), stack, false);
|
||||
if (remainder.isEmpty())
|
||||
return;
|
||||
|
||||
|
@ -87,7 +93,7 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
|
|||
@Override
|
||||
@OnlyIn(value = Dist.CLIENT)
|
||||
public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
|
||||
ContraptionMatrices matrices, MultiBufferSource buffer) {
|
||||
ContraptionMatrices matrices, MultiBufferSource buffer) {
|
||||
SawRenderer.renderInContraption(context, renderWorld, matrices, buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@ import net.minecraft.world.item.ItemStack;
|
|||
import net.minecraft.world.item.Items;
|
||||
|
||||
public class DropperMovementBehaviour implements MovementBehaviour {
|
||||
protected static final MovedDefaultDispenseItemBehaviour DEFAULT_BEHAVIOUR = new MovedDefaultDispenseItemBehaviour();
|
||||
protected static final MovedDefaultDispenseItemBehaviour DEFAULT_BEHAVIOUR =
|
||||
new MovedDefaultDispenseItemBehaviour();
|
||||
private static final Random RNG = new Random();
|
||||
|
||||
protected void activate(MovementContext context, BlockPos pos) {
|
||||
|
@ -23,7 +24,8 @@ public class DropperMovementBehaviour implements MovementBehaviour {
|
|||
if (location.isEmpty()) {
|
||||
context.world.levelEvent(1001, pos, 0);
|
||||
} else {
|
||||
setItemStackAt(location, DEFAULT_BEHAVIOUR.dispense(getItemStackAt(location, context), context, pos), context);
|
||||
setItemStackAt(location, DEFAULT_BEHAVIOUR.dispense(getItemStackAt(location, context), context, pos),
|
||||
context);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,8 +38,13 @@ public class DropperMovementBehaviour implements MovementBehaviour {
|
|||
}
|
||||
|
||||
private void collectItems(MovementContext context) {
|
||||
getStacks(context).stream().filter(itemStack -> !itemStack.isEmpty() && itemStack.getItem() != Items.AIR && itemStack.getMaxStackSize() > itemStack.getCount()).forEach(itemStack -> itemStack.grow(
|
||||
ItemHelper.extract(context.contraption.inventory, itemStack::sameItem, ItemHelper.ExtractionCountMode.UPTO, itemStack.getMaxStackSize() - itemStack.getCount(), false).getCount()));
|
||||
getStacks(context).stream()
|
||||
.filter(itemStack -> !itemStack.isEmpty() && itemStack.getItem() != Items.AIR
|
||||
&& itemStack.getMaxStackSize() > itemStack.getCount())
|
||||
.forEach(itemStack -> itemStack.grow(ItemHelper
|
||||
.extract(context.contraption.getSharedInventory(), itemStack::sameItem,
|
||||
ItemHelper.ExtractionCountMode.UPTO, itemStack.getMaxStackSize() - itemStack.getCount(), false)
|
||||
.getCount()));
|
||||
}
|
||||
|
||||
private void updateTemporaryData(MovementContext context) {
|
||||
|
@ -62,7 +69,8 @@ public class DropperMovementBehaviour implements MovementBehaviour {
|
|||
if (testStack == null || testStack.isEmpty())
|
||||
continue;
|
||||
if (testStack.getMaxStackSize() == 1) {
|
||||
location = new DispenseItemLocation(false, ItemHelper.findFirstMatchingSlotIndex(context.contraption.inventory, testStack::sameItem));
|
||||
location = new DispenseItemLocation(false, ItemHelper
|
||||
.findFirstMatchingSlotIndex(context.contraption.getSharedInventory(), testStack::sameItem));
|
||||
if (!getItemStackAt(location, context).isEmpty())
|
||||
useable.add(location);
|
||||
} else if (testStack.getCount() >= 2)
|
||||
|
@ -104,7 +112,8 @@ public class DropperMovementBehaviour implements MovementBehaviour {
|
|||
if (location.isInternal()) {
|
||||
return getStacks(context).get(location.getSlot());
|
||||
} else {
|
||||
return context.contraption.inventory.getStackInSlot(location.getSlot());
|
||||
return context.contraption.getSharedInventory()
|
||||
.getStackInSlot(location.getSlot());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +121,8 @@ public class DropperMovementBehaviour implements MovementBehaviour {
|
|||
if (location.isInternal()) {
|
||||
getStacks(context).set(location.getSlot(), stack);
|
||||
} else {
|
||||
context.contraption.inventory.setStackInSlot(location.getSlot(), stack);
|
||||
context.contraption.getSharedInventory()
|
||||
.setStackInSlot(location.getSlot(), stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,11 +17,13 @@ import net.minecraftforge.items.ItemHandlerHelper;
|
|||
public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBehaviour {
|
||||
private static final MovedDefaultDispenseItemBehaviour DEFAULT_INSTANCE = new MovedDefaultDispenseItemBehaviour();
|
||||
|
||||
public static void doDispense(Level p_82486_0_, ItemStack p_82486_1_, int p_82486_2_, Vec3 facing, BlockPos p_82486_4_, MovementContext context) {
|
||||
public static void doDispense(Level p_82486_0_, ItemStack p_82486_1_, int p_82486_2_, Vec3 facing,
|
||||
BlockPos p_82486_4_, MovementContext context) {
|
||||
double d0 = p_82486_4_.getX() + facing.x + .5;
|
||||
double d1 = p_82486_4_.getY() + facing.y + .5;
|
||||
double d2 = p_82486_4_.getZ() + facing.z + .5;
|
||||
if (Direction.getNearest(facing.x, facing.y, facing.z).getAxis() == Direction.Axis.Y) {
|
||||
if (Direction.getNearest(facing.x, facing.y, facing.z)
|
||||
.getAxis() == Direction.Axis.Y) {
|
||||
d1 = d1 - 0.125D;
|
||||
} else {
|
||||
d1 = d1 - 0.15625D;
|
||||
|
@ -29,13 +31,20 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha
|
|||
|
||||
ItemEntity itementity = new ItemEntity(p_82486_0_, d0, d1, d2, p_82486_1_);
|
||||
double d3 = p_82486_0_.random.nextDouble() * 0.1D + 0.2D;
|
||||
itementity.setDeltaMovement(p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.x() * d3 + context.motion.x, p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.y() * d3 + context.motion.y, p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.z() * d3 + context.motion.z);
|
||||
itementity.setDeltaMovement(
|
||||
p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.x() * d3
|
||||
+ context.motion.x,
|
||||
p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.y() * d3
|
||||
+ context.motion.y,
|
||||
p_82486_0_.random.nextGaussian() * (double) 0.0075F * (double) p_82486_2_ + facing.z() * d3
|
||||
+ context.motion.z);
|
||||
p_82486_0_.addFreshEntity(itementity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack dispense(ItemStack itemStack, MovementContext context, BlockPos pos) {
|
||||
Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(DispenserBlock.FACING).getNormal());
|
||||
Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(DispenserBlock.FACING)
|
||||
.getNormal());
|
||||
facingVec = context.rotation.apply(facingVec);
|
||||
facingVec.normalize();
|
||||
|
||||
|
@ -46,7 +55,9 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha
|
|||
this.spawnDispenseParticles(context.world, pos, closestToFacing);
|
||||
return this.dispenseStack(itemStack, context, pos, facingVec);
|
||||
} else {
|
||||
if (HopperBlockEntity.addItem(null, iinventory, itemStack.copy().split(1), closestToFacing.getOpposite()).isEmpty())
|
||||
if (HopperBlockEntity.addItem(null, iinventory, itemStack.copy()
|
||||
.split(1), closestToFacing.getOpposite())
|
||||
.isEmpty())
|
||||
itemStack.shrink(1);
|
||||
return itemStack;
|
||||
}
|
||||
|
@ -69,7 +80,8 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha
|
|||
}
|
||||
|
||||
/**
|
||||
* Order clients to display dispense particles from the specified block and facing.
|
||||
* Order clients to display dispense particles from the specified block and
|
||||
* facing.
|
||||
*/
|
||||
protected void spawnDispenseParticles(LevelAccessor world, BlockPos pos, Vec3 facing) {
|
||||
spawnDispenseParticles(world, pos, getClosestFacingDirection(facing));
|
||||
|
@ -83,9 +95,11 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha
|
|||
return Direction.getNearest(exactFacing.x, exactFacing.y, exactFacing.z);
|
||||
}
|
||||
|
||||
protected ItemStack placeItemInInventory(ItemStack consumedFrom, ItemStack output, MovementContext context, BlockPos pos, Vec3 facing) {
|
||||
protected ItemStack placeItemInInventory(ItemStack consumedFrom, ItemStack output, MovementContext context,
|
||||
BlockPos pos, Vec3 facing) {
|
||||
consumedFrom.shrink(1);
|
||||
ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, output.copy(), false);
|
||||
ItemStack remainder =
|
||||
ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), output.copy(), false);
|
||||
if (!remainder.isEmpty())
|
||||
DEFAULT_INSTANCE.dispenseStack(output, context, pos, facing);
|
||||
return consumedFrom;
|
||||
|
|
|
@ -123,7 +123,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
|
|||
ItemStack firstRequired = requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).item;
|
||||
|
||||
if (!context.contraption.hasUniversalCreativeCrate) {
|
||||
IItemHandler iItemHandler = context.contraption.inventory;
|
||||
IItemHandler iItemHandler = context.contraption.getSharedInventory();
|
||||
for (ItemRequirement.StackRequirement required : requiredItems) {
|
||||
int amountFound = ItemHelper
|
||||
.extract(iItemHandler, s -> ItemRequirement.validate(required.item, s), ExtractionCountMode.UPTO,
|
||||
|
@ -202,7 +202,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
|
|||
ItemStack filter = getFilter(context);
|
||||
if (AllItems.SCHEMATIC.isIn(filter))
|
||||
return;
|
||||
ItemStack held = ItemHelper.extract(context.contraption.inventory,
|
||||
ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(),
|
||||
stack -> FilterItem.test(context.world, stack, filter), 1, false);
|
||||
player.setItemInHand(InteractionHand.MAIN_HAND, held);
|
||||
}
|
||||
|
|
|
@ -21,12 +21,14 @@ import com.simibubi.create.AllItems;
|
|||
import com.simibubi.create.AllMovementBehaviours;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceMovement;
|
||||
import com.simibubi.create.content.contraptions.components.actors.SeatBlock;
|
||||
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsStopControllingPacket;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket;
|
||||
import com.simibubi.create.content.logistics.trains.entity.CarriageContraption;
|
||||
import com.simibubi.create.foundation.collision.Matrix3d;
|
||||
import com.simibubi.create.foundation.mixin.accessor.ServerLevelAccessor;
|
||||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
|
@ -294,7 +296,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
|||
|
||||
if (!initialized)
|
||||
contraptionInitialize();
|
||||
contraption.onEntityTick(level);
|
||||
|
||||
contraption.storage.entityTick(this);
|
||||
tickContraption();
|
||||
super.tick();
|
||||
|
||||
|
@ -353,6 +356,9 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
|||
StructureBlockInfo blockInfo = pair.left;
|
||||
MovementBehaviour actor = AllMovementBehaviours.of(blockInfo.state);
|
||||
|
||||
if (actor == null)
|
||||
continue;
|
||||
|
||||
Vec3 oldMotion = context.motion;
|
||||
Vec3 actorPosition = toGlobalVector(VecHelper.getCenterOf(blockInfo.pos)
|
||||
.add(actor.getActiveAreaOffset(context)), 1);
|
||||
|
@ -408,6 +414,16 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
|||
contraption.stalled = isStalled();
|
||||
}
|
||||
|
||||
public void refreshPSIs() {
|
||||
for (MutablePair<StructureBlockInfo, MovementContext> pair : contraption.getActors()) {
|
||||
MovementContext context = pair.right;
|
||||
StructureBlockInfo blockInfo = pair.left;
|
||||
MovementBehaviour actor = AllMovementBehaviours.of(blockInfo.state);
|
||||
if (actor instanceof PortableStorageInterfaceMovement && isActorActive(context, actor))
|
||||
actor.visitNewPosition(context, new BlockPos(context.position));
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isActorActive(MovementContext context, MovementBehaviour actor) {
|
||||
return actor.isActive(context);
|
||||
}
|
||||
|
@ -428,7 +444,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
|||
relativeMotion = reverseRotation(relativeMotion, 1);
|
||||
context.relativeMotion = relativeMotion;
|
||||
return !new BlockPos(previousPosition).equals(gridPosition)
|
||||
|| context.relativeMotion.length() > 0 && context.firstMovement;
|
||||
|| (context.relativeMotion.length() > 0 || context.contraption instanceof CarriageContraption)
|
||||
&& context.firstMovement;
|
||||
}
|
||||
|
||||
public void move(double x, double y, double z) {
|
||||
|
|
|
@ -4,7 +4,6 @@ import static com.simibubi.create.content.contraptions.components.structureMovem
|
|||
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -19,7 +18,6 @@ import java.util.Set;
|
|||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -63,7 +61,6 @@ import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock
|
|||
import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity;
|
||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
||||
import com.simibubi.create.foundation.tileEntity.IMultiTileContainer;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||
import com.simibubi.create.foundation.utility.BlockFace;
|
||||
|
@ -85,7 +82,6 @@ import net.minecraft.network.protocol.game.DebugPackets;
|
|||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.ai.village.poi.PoiType;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
@ -114,10 +110,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
|
|||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.IFluidTank;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
|
||||
import net.minecraftforge.fluids.capability.templates.FluidTank;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||
import net.minecraftforge.registries.GameData;
|
||||
|
@ -126,22 +119,20 @@ public abstract class Contraption {
|
|||
|
||||
public Optional<List<AABB>> simplifiedEntityColliders;
|
||||
public AbstractContraptionEntity entity;
|
||||
public ContraptionInvWrapper inventory;
|
||||
public CombinedTankWrapper fluidInventory;
|
||||
|
||||
public AABB bounds;
|
||||
public BlockPos anchor;
|
||||
public boolean stalled;
|
||||
public boolean hasUniversalCreativeCrate;
|
||||
|
||||
protected Map<BlockPos, StructureBlockInfo> blocks;
|
||||
protected Map<BlockPos, MountedStorage> storage;
|
||||
protected Map<BlockPos, MountedFluidStorage> fluidStorage;
|
||||
protected List<MutablePair<StructureBlockInfo, MovementContext>> actors;
|
||||
protected Map<BlockPos, MovingInteractionBehaviour> interactors;
|
||||
protected List<AABB> superglue;
|
||||
protected List<BlockPos> seats;
|
||||
protected Map<UUID, Integer> seatMapping;
|
||||
protected Map<UUID, BlockFace> stabilizedSubContraptions;
|
||||
protected MountedStorageManager storage;
|
||||
|
||||
private Set<SuperGlueEntity> glueToRemove;
|
||||
private Map<BlockPos, Entity> initialPassengers;
|
||||
|
@ -158,13 +149,11 @@ public abstract class Contraption {
|
|||
|
||||
public Contraption() {
|
||||
blocks = new HashMap<>();
|
||||
storage = new HashMap<>();
|
||||
seats = new ArrayList<>();
|
||||
actors = new ArrayList<>();
|
||||
interactors = new HashMap<>();
|
||||
superglue = new ArrayList<>();
|
||||
seatMapping = new HashMap<>();
|
||||
fluidStorage = new HashMap<>();
|
||||
glueToRemove = new HashSet<>();
|
||||
initialPassengers = new HashMap<>();
|
||||
presentTileEntities = new HashMap<>();
|
||||
|
@ -173,6 +162,7 @@ public abstract class Contraption {
|
|||
pendingSubContraptions = new ArrayList<>();
|
||||
stabilizedSubContraptions = new HashMap<>();
|
||||
simplifiedEntityColliders = Optional.empty();
|
||||
storage = new MountedStorageManager();
|
||||
}
|
||||
|
||||
public ContraptionWorld getContraptionWorld() {
|
||||
|
@ -255,20 +245,7 @@ public abstract class Contraption {
|
|||
stabilizedSubContraptions.put(movedContraption.getUUID(), new BlockFace(toLocalPos(pos), face));
|
||||
}
|
||||
|
||||
// Gather itemhandlers of mounted storage
|
||||
List<IItemHandlerModifiable> list = storage.values()
|
||||
.stream()
|
||||
.map(MountedStorage::getItemHandler)
|
||||
.collect(Collectors.toList());
|
||||
inventory =
|
||||
new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
|
||||
|
||||
List<IFluidHandler> fluidHandlers = fluidStorage.values()
|
||||
.stream()
|
||||
.map(MountedFluidStorage::getFluidHandler)
|
||||
.collect(Collectors.toList());
|
||||
fluidInventory = new CombinedTankWrapper(
|
||||
Arrays.copyOf(fluidHandlers.toArray(), fluidHandlers.size(), IFluidHandler[].class));
|
||||
storage.createHandlers();
|
||||
gatherBBsOffThread();
|
||||
}
|
||||
|
||||
|
@ -300,10 +277,6 @@ public abstract class Contraption {
|
|||
}
|
||||
}
|
||||
|
||||
public void onEntityTick(Level world) {
|
||||
fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, world.isClientSide));
|
||||
}
|
||||
|
||||
/** move the first block in frontier queue */
|
||||
protected boolean moveBlock(Level world, @Nullable Direction forcedDirection, Queue<BlockPos> frontier,
|
||||
Set<BlockPos> visited) throws AssemblyException {
|
||||
|
@ -642,10 +615,7 @@ public abstract class Contraption {
|
|||
bounds = bounds.minmax(new AABB(localPos));
|
||||
|
||||
BlockEntity te = pair.getValue();
|
||||
if (te != null && MountedStorage.canUseAsStorage(te))
|
||||
storage.put(localPos, new MountedStorage(te));
|
||||
if (te != null && MountedFluidStorage.canUseAsStorage(te))
|
||||
fluidStorage.put(localPos, new MountedFluidStorage(te));
|
||||
storage.addBlock(localPos, te);
|
||||
if (AllMovementBehaviours.contains(captured.state.getBlock()))
|
||||
actors.add(MutablePair.of(StructureBlockInfo, null));
|
||||
if (AllInteractionBehaviours.contains(captured.state.getBlock()))
|
||||
|
@ -722,14 +692,6 @@ public abstract class Contraption {
|
|||
NBTHelper.iterateCompoundList(nbt.getList("SubContraptions", Tag.TAG_COMPOUND),
|
||||
c -> stabilizedSubContraptions.put(c.getUUID("Id"), BlockFace.fromNBT(c.getCompound("Location"))));
|
||||
|
||||
storage.clear();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("Storage", Tag.TAG_COMPOUND), c -> storage
|
||||
.put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data"))));
|
||||
|
||||
fluidStorage.clear();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", Tag.TAG_COMPOUND), c -> fluidStorage
|
||||
.put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data"))));
|
||||
|
||||
interactors.clear();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("Interactors", Tag.TAG_COMPOUND), c -> {
|
||||
BlockPos pos = NbtUtils.readBlockPos(c.getCompound("Pos"));
|
||||
|
@ -738,32 +700,7 @@ public abstract class Contraption {
|
|||
interactors.put(pos, behaviour);
|
||||
});
|
||||
|
||||
if (spawnData)
|
||||
fluidStorage.forEach((pos, mfs) -> {
|
||||
BlockEntity tileEntity = presentTileEntities.get(pos);
|
||||
if (!(tileEntity instanceof FluidTankTileEntity))
|
||||
return;
|
||||
FluidTankTileEntity tank = (FluidTankTileEntity) tileEntity;
|
||||
IFluidTank tankInventory = tank.getTankInventory();
|
||||
if (tankInventory instanceof FluidTank)
|
||||
((FluidTank) tankInventory).setFluid(mfs.tank.getFluid());
|
||||
tank.getFluidLevel()
|
||||
.startWithValue(tank.getFillState());
|
||||
mfs.assignTileEntity(tank);
|
||||
});
|
||||
|
||||
IItemHandlerModifiable[] handlers = new IItemHandlerModifiable[storage.size()];
|
||||
int index = 0;
|
||||
for (MountedStorage mountedStorage : storage.values())
|
||||
handlers[index++] = mountedStorage.getItemHandler();
|
||||
|
||||
IFluidHandler[] fluidHandlers = new IFluidHandler[fluidStorage.size()];
|
||||
index = 0;
|
||||
for (MountedFluidStorage mountedStorage : fluidStorage.values())
|
||||
fluidHandlers[index++] = mountedStorage.getFluidHandler();
|
||||
|
||||
inventory = new ContraptionInvWrapper(handlers);
|
||||
fluidInventory = new CombinedTankWrapper(fluidHandlers);
|
||||
storage.read(nbt, presentTileEntities, spawnData);
|
||||
|
||||
if (nbt.contains("BoundsFront"))
|
||||
bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", 5));
|
||||
|
@ -790,35 +727,15 @@ public abstract class Contraption {
|
|||
}
|
||||
|
||||
ListTag superglueNBT = new ListTag();
|
||||
ListTag storageNBT = new ListTag();
|
||||
if (!spawnPacket) {
|
||||
for (AABB glueEntry : superglue) {
|
||||
CompoundTag c = new CompoundTag();
|
||||
SuperGlueEntity.writeBoundingBox(c, glueEntry);
|
||||
superglueNBT.add(c);
|
||||
}
|
||||
|
||||
for (BlockPos pos : storage.keySet()) {
|
||||
CompoundTag c = new CompoundTag();
|
||||
MountedStorage mountedStorage = storage.get(pos);
|
||||
if (!mountedStorage.isValid())
|
||||
continue;
|
||||
c.put("Pos", NbtUtils.writeBlockPos(pos));
|
||||
c.put("Data", mountedStorage.serialize());
|
||||
storageNBT.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
ListTag fluidStorageNBT = new ListTag();
|
||||
for (BlockPos pos : fluidStorage.keySet()) {
|
||||
CompoundTag c = new CompoundTag();
|
||||
MountedFluidStorage mountedStorage = fluidStorage.get(pos);
|
||||
if (!mountedStorage.isValid())
|
||||
continue;
|
||||
c.put("Pos", NbtUtils.writeBlockPos(pos));
|
||||
c.put("Data", mountedStorage.serialize());
|
||||
fluidStorageNBT.add(c);
|
||||
}
|
||||
storage.write(nbt, spawnPacket);
|
||||
|
||||
ListTag interactorNBT = new ListTag();
|
||||
for (BlockPos pos : interactors.keySet()) {
|
||||
|
@ -847,8 +764,6 @@ public abstract class Contraption {
|
|||
nbt.put("Actors", actorsNBT);
|
||||
nbt.put("Interactors", interactorNBT);
|
||||
nbt.put("Superglue", superglueNBT);
|
||||
nbt.put("Storage", storageNBT);
|
||||
nbt.put("FluidStorage", fluidStorageNBT);
|
||||
nbt.put("Anchor", NbtUtils.writeBlockPos(anchor));
|
||||
nbt.putBoolean("Stalled", stalled);
|
||||
nbt.putBoolean("BottomlessSupply", hasUniversalCreativeCrate);
|
||||
|
@ -962,10 +877,7 @@ public abstract class Contraption {
|
|||
}
|
||||
|
||||
public void removeBlocksFromWorld(Level world, BlockPos offset) {
|
||||
storage.values()
|
||||
.forEach(MountedStorage::removeStorageFromWorld);
|
||||
fluidStorage.values()
|
||||
.forEach(MountedFluidStorage::removeStorageFromWorld);
|
||||
storage.removeStorageFromWorld();
|
||||
|
||||
glueToRemove.forEach(glue -> {
|
||||
superglue.add(glue.getBoundingBox()
|
||||
|
@ -1125,23 +1037,13 @@ public abstract class Contraption {
|
|||
tag.put("LastKnownPos", NbtUtils.writeBlockPos(BlockPos.ZERO.below(Integer.MAX_VALUE - 1)));
|
||||
|
||||
tileEntity.load(tag);
|
||||
|
||||
if (storage.containsKey(block.pos)) {
|
||||
MountedStorage mountedStorage = storage.get(block.pos);
|
||||
if (mountedStorage.isValid())
|
||||
mountedStorage.addStorageToWorld(tileEntity);
|
||||
}
|
||||
|
||||
if (fluidStorage.containsKey(block.pos)) {
|
||||
MountedFluidStorage mountedStorage = fluidStorage.get(block.pos);
|
||||
if (mountedStorage.isValid())
|
||||
mountedStorage.addStorageToWorld(tileEntity);
|
||||
}
|
||||
storage.addStorageToWorld(block, tileEntity);
|
||||
}
|
||||
|
||||
transform.apply(tileEntity);
|
||||
}
|
||||
}
|
||||
|
||||
for (StructureBlockInfo block : blocks.values()) {
|
||||
if (!shouldUpdateAfterMovement(block))
|
||||
continue;
|
||||
|
@ -1150,19 +1052,14 @@ public abstract class Contraption {
|
|||
Block.UPDATE_MOVE_BY_PISTON | Block.UPDATE_ALL, 512);
|
||||
}
|
||||
|
||||
for (int i = 0; i < inventory.getSlots(); i++) {
|
||||
if (!inventory.isSlotExternal(i))
|
||||
inventory.setStackInSlot(i, ItemStack.EMPTY);
|
||||
}
|
||||
for (int i = 0; i < fluidInventory.getTanks(); i++)
|
||||
fluidInventory.drain(fluidInventory.getFluidInTank(i), FluidAction.EXECUTE);
|
||||
|
||||
for (AABB box : superglue) {
|
||||
box = new AABB(transform.apply(new Vec3(box.minX, box.minY, box.minZ)),
|
||||
transform.apply(new Vec3(box.maxX, box.maxY, box.maxZ)));
|
||||
if (!world.isClientSide)
|
||||
world.addFreshEntity(new SuperGlueEntity(world, box));
|
||||
}
|
||||
|
||||
storage.clear();
|
||||
}
|
||||
|
||||
public void addPassengersToWorld(Level world, StructureTransform transform, List<Entity> seatedEntities) {
|
||||
|
@ -1240,8 +1137,6 @@ public abstract class Contraption {
|
|||
bounds = new AABB(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
public void addExtraInventories(Entity entity) {}
|
||||
|
||||
public Map<UUID, Integer> getSeatMapping() {
|
||||
return seatMapping;
|
||||
}
|
||||
|
@ -1282,12 +1177,6 @@ public abstract class Contraption {
|
|||
return interactors;
|
||||
}
|
||||
|
||||
public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) {
|
||||
MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos);
|
||||
if (mountedFluidStorage != null)
|
||||
mountedFluidStorage.updateFluid(containedFluid);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public ContraptionLighter<?> makeLighter() {
|
||||
// TODO: move lighters to registry
|
||||
|
@ -1349,30 +1238,13 @@ public abstract class Contraption {
|
|||
return maxDistSq;
|
||||
}
|
||||
|
||||
// TODO: unused?
|
||||
// private static class ContraptionTileWorld extends WrappedWorld implements IFlywheelWorld {
|
||||
//
|
||||
// private final BlockEntity te;
|
||||
// private final StructureBlockInfo info;
|
||||
//
|
||||
// public ContraptionTileWorld(Level world, BlockEntity te, StructureBlockInfo info) {
|
||||
// super(world);
|
||||
// this.te = te;
|
||||
// this.info = info;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public BlockState getBlockState(BlockPos pos) {
|
||||
// if (!pos.equals(te.getBlockPos()))
|
||||
// return Blocks.AIR.defaultBlockState();
|
||||
// return info.state;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isLoaded(BlockPos pos) {
|
||||
// return pos.equals(te.getBlockPos());
|
||||
// }
|
||||
// }
|
||||
public IItemHandlerModifiable getSharedInventory() {
|
||||
return storage.getItems();
|
||||
}
|
||||
|
||||
public IFluidHandler getSharedFluidTanks() {
|
||||
return storage.getFluids();
|
||||
}
|
||||
|
||||
public Collection<StructureBlockInfo> getRenderedBlocks() {
|
||||
return blocks.values();
|
||||
|
@ -1390,6 +1262,10 @@ public abstract class Contraption {
|
|||
return simplifiedEntityColliders;
|
||||
}
|
||||
|
||||
public void handleContraptionFluidPacket(BlockPos localPos, FluidStack containedFluid) {
|
||||
storage.updateContainedFluid(localPos, containedFluid);
|
||||
}
|
||||
|
||||
public static class ContraptionInvWrapper extends CombinedInvWrapper {
|
||||
protected final boolean isExternal;
|
||||
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption.ContraptionInvWrapper;
|
||||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity;
|
||||
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.IFluidTank;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
|
||||
import net.minecraftforge.fluids.capability.templates.FluidTank;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
|
||||
public class MountedStorageManager {
|
||||
|
||||
private ContraptionInvWrapper inventory;
|
||||
private CombinedTankWrapper fluidInventory;
|
||||
private Map<BlockPos, MountedStorage> storage;
|
||||
private Map<BlockPos, MountedFluidStorage> fluidStorage;
|
||||
|
||||
public MountedStorageManager() {
|
||||
storage = new HashMap<>();
|
||||
fluidStorage = new HashMap<>();
|
||||
}
|
||||
|
||||
public void entityTick(AbstractContraptionEntity entity) {
|
||||
fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, entity.level.isClientSide));
|
||||
}
|
||||
|
||||
public void createHandlers() {
|
||||
List<IItemHandlerModifiable> list = storage.values()
|
||||
.stream()
|
||||
.map(MountedStorage::getItemHandler)
|
||||
.collect(Collectors.toList());
|
||||
inventory =
|
||||
new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
|
||||
|
||||
List<IFluidHandler> fluidHandlers = fluidStorage.values()
|
||||
.stream()
|
||||
.map(MountedFluidStorage::getFluidHandler)
|
||||
.collect(Collectors.toList());
|
||||
fluidInventory = new CombinedTankWrapper(
|
||||
Arrays.copyOf(fluidHandlers.toArray(), fluidHandlers.size(), IFluidHandler[].class));
|
||||
}
|
||||
|
||||
public void addBlock(BlockPos localPos, BlockEntity te) {
|
||||
if (te != null && MountedStorage.canUseAsStorage(te))
|
||||
storage.put(localPos, new MountedStorage(te));
|
||||
if (te != null && MountedFluidStorage.canUseAsStorage(te))
|
||||
fluidStorage.put(localPos, new MountedFluidStorage(te));
|
||||
}
|
||||
|
||||
public void read(CompoundTag nbt, Map<BlockPos, BlockEntity> presentTileEntities, boolean clientPacket) {
|
||||
storage.clear();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("Storage", Tag.TAG_COMPOUND), c -> storage
|
||||
.put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data"))));
|
||||
|
||||
fluidStorage.clear();
|
||||
NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", Tag.TAG_COMPOUND), c -> fluidStorage
|
||||
.put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data"))));
|
||||
|
||||
if (clientPacket && presentTileEntities != null)
|
||||
fluidStorage.forEach((pos, mfs) -> {
|
||||
BlockEntity tileEntity = presentTileEntities.get(pos);
|
||||
if (!(tileEntity instanceof FluidTankTileEntity))
|
||||
return;
|
||||
FluidTankTileEntity tank = (FluidTankTileEntity) tileEntity;
|
||||
IFluidTank tankInventory = tank.getTankInventory();
|
||||
if (tankInventory instanceof FluidTank)
|
||||
((FluidTank) tankInventory).setFluid(mfs.tank.getFluid());
|
||||
tank.getFluidLevel()
|
||||
.startWithValue(tank.getFillState());
|
||||
mfs.assignTileEntity(tank);
|
||||
});
|
||||
|
||||
IItemHandlerModifiable[] handlers = new IItemHandlerModifiable[storage.size()];
|
||||
int index = 0;
|
||||
for (MountedStorage mountedStorage : storage.values())
|
||||
handlers[index++] = mountedStorage.getItemHandler();
|
||||
|
||||
IFluidHandler[] fluidHandlers = new IFluidHandler[fluidStorage.size()];
|
||||
index = 0;
|
||||
for (MountedFluidStorage mountedStorage : fluidStorage.values())
|
||||
fluidHandlers[index++] = mountedStorage.getFluidHandler();
|
||||
|
||||
inventory = new ContraptionInvWrapper(handlers);
|
||||
fluidInventory = new CombinedTankWrapper(fluidHandlers);
|
||||
}
|
||||
|
||||
public void write(CompoundTag nbt, boolean clientPacket) {
|
||||
ListTag storageNBT = new ListTag();
|
||||
if (!clientPacket)
|
||||
for (BlockPos pos : storage.keySet()) {
|
||||
CompoundTag c = new CompoundTag();
|
||||
MountedStorage mountedStorage = storage.get(pos);
|
||||
if (!mountedStorage.isValid())
|
||||
continue;
|
||||
c.put("Pos", NbtUtils.writeBlockPos(pos));
|
||||
c.put("Data", mountedStorage.serialize());
|
||||
storageNBT.add(c);
|
||||
}
|
||||
|
||||
ListTag fluidStorageNBT = new ListTag();
|
||||
for (BlockPos pos : fluidStorage.keySet()) {
|
||||
CompoundTag c = new CompoundTag();
|
||||
MountedFluidStorage mountedStorage = fluidStorage.get(pos);
|
||||
if (!mountedStorage.isValid())
|
||||
continue;
|
||||
c.put("Pos", NbtUtils.writeBlockPos(pos));
|
||||
c.put("Data", mountedStorage.serialize());
|
||||
fluidStorageNBT.add(c);
|
||||
}
|
||||
|
||||
nbt.put("Storage", storageNBT);
|
||||
nbt.put("FluidStorage", fluidStorageNBT);
|
||||
}
|
||||
|
||||
public void removeStorageFromWorld() {
|
||||
storage.values()
|
||||
.forEach(MountedStorage::removeStorageFromWorld);
|
||||
fluidStorage.values()
|
||||
.forEach(MountedFluidStorage::removeStorageFromWorld);
|
||||
}
|
||||
|
||||
public void addStorageToWorld(StructureBlockInfo block, BlockEntity tileEntity) {
|
||||
if (storage.containsKey(block.pos)) {
|
||||
MountedStorage mountedStorage = storage.get(block.pos);
|
||||
if (mountedStorage.isValid())
|
||||
mountedStorage.addStorageToWorld(tileEntity);
|
||||
}
|
||||
|
||||
if (fluidStorage.containsKey(block.pos)) {
|
||||
MountedFluidStorage mountedStorage = fluidStorage.get(block.pos);
|
||||
if (mountedStorage.isValid())
|
||||
mountedStorage.addStorageToWorld(tileEntity);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
for (int i = 0; i < inventory.getSlots(); i++)
|
||||
if (!inventory.isSlotExternal(i))
|
||||
inventory.setStackInSlot(i, ItemStack.EMPTY);
|
||||
for (int i = 0; i < fluidInventory.getTanks(); i++)
|
||||
fluidInventory.drain(fluidInventory.getFluidInTank(i), FluidAction.EXECUTE);
|
||||
}
|
||||
|
||||
public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) {
|
||||
MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos);
|
||||
if (mountedFluidStorage != null)
|
||||
mountedFluidStorage.updateFluid(containedFluid);
|
||||
}
|
||||
|
||||
public void attachExternal(IItemHandlerModifiable externalStorage) {
|
||||
inventory = new ContraptionInvWrapper(externalStorage, inventory);
|
||||
}
|
||||
|
||||
public IItemHandlerModifiable getItems() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public IFluidHandler getFluids() {
|
||||
return fluidInventory;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,14 +23,11 @@ public interface MovementBehaviour {
|
|||
return true;
|
||||
}
|
||||
|
||||
default void tick(MovementContext context) {
|
||||
}
|
||||
default void tick(MovementContext context) {}
|
||||
|
||||
default void startMoving(MovementContext context) {
|
||||
}
|
||||
default void startMoving(MovementContext context) {}
|
||||
|
||||
default void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||
}
|
||||
default void visitNewPosition(MovementContext context, BlockPos pos) {}
|
||||
|
||||
default Vec3 getActiveAreaOffset(MovementContext context) {
|
||||
return Vec3.ZERO;
|
||||
|
@ -39,7 +36,7 @@ public interface MovementBehaviour {
|
|||
default void dropItem(MovementContext context, ItemStack stack) {
|
||||
ItemStack remainder;
|
||||
if (AllConfigs.SERVER.kinetics.moveItemsToStorage.get())
|
||||
remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, stack, false);
|
||||
remainder = ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), stack, false);
|
||||
else
|
||||
remainder = stack;
|
||||
if (remainder.isEmpty())
|
||||
|
@ -52,14 +49,11 @@ public interface MovementBehaviour {
|
|||
context.world.addFreshEntity(itemEntity);
|
||||
}
|
||||
|
||||
default void onSpeedChanged(MovementContext context, Vec3 oldMotion, Vec3 motion) {
|
||||
}
|
||||
default void onSpeedChanged(MovementContext context, Vec3 oldMotion, Vec3 motion) {}
|
||||
|
||||
default void stopMoving(MovementContext context) {
|
||||
}
|
||||
default void stopMoving(MovementContext context) {}
|
||||
|
||||
default void writeExtraData(MovementContext context) {
|
||||
}
|
||||
default void writeExtraData(MovementContext context) {}
|
||||
|
||||
default boolean renderAsNormalTileEntity() {
|
||||
return false;
|
||||
|
@ -71,12 +65,12 @@ public interface MovementBehaviour {
|
|||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
default void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld,
|
||||
ContraptionMatrices matrices, MultiBufferSource buffer) {
|
||||
}
|
||||
ContraptionMatrices matrices, MultiBufferSource buffer) {}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@Nullable
|
||||
default ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, MovementContext context) {
|
||||
default ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld,
|
||||
MovementContext context) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -428,7 +428,7 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
|
|||
.normalize()
|
||||
.scale(1));
|
||||
if (fuel < 5 && contraption != null) {
|
||||
ItemStack coal = ItemHelper.extract(contraption.inventory, FUEL_ITEMS, 1, false);
|
||||
ItemStack coal = ItemHelper.extract(contraption.getSharedInventory(), FUEL_ITEMS, 1, false);
|
||||
if (!coal.isEmpty())
|
||||
fuel += 3600;
|
||||
}
|
||||
|
@ -457,15 +457,17 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
|
|||
}
|
||||
|
||||
protected void attachInventoriesFromRidingCarts(Entity riding, boolean isOnCoupling, UUID couplingId) {
|
||||
if (isOnCoupling) {
|
||||
Couple<MinecartController> coupledCarts = getCoupledCartsIfPresent();
|
||||
if (coupledCarts == null)
|
||||
return;
|
||||
coupledCarts.map(MinecartController::cart)
|
||||
.forEach(contraption::addExtraInventories);
|
||||
if (!(contraption instanceof MountedContraption mc))
|
||||
return;
|
||||
if (!isOnCoupling) {
|
||||
mc.addExtraInventories(riding);
|
||||
return;
|
||||
}
|
||||
contraption.addExtraInventories(riding);
|
||||
Couple<MinecartController> coupledCarts = getCoupledCartsIfPresent();
|
||||
if (coupledCarts == null)
|
||||
return;
|
||||
coupledCarts.map(MinecartController::cart)
|
||||
.forEach(mc::addExtraInventories);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,7 +34,6 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
|||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
import net.minecraftforge.items.wrapper.InvWrapper;
|
||||
|
||||
public class MountedContraption extends Contraption {
|
||||
|
@ -95,8 +94,8 @@ public class MountedContraption extends Contraption {
|
|||
for (Axis axis : Iterate.axes) {
|
||||
if (axis.isVertical() || !VecHelper.onSameAxis(anchor, pos, axis))
|
||||
continue;
|
||||
for (AbstractMinecart abstractMinecartEntity : world
|
||||
.getEntitiesOfClass(AbstractMinecart.class, new AABB(pos))) {
|
||||
for (AbstractMinecart abstractMinecartEntity : world.getEntitiesOfClass(AbstractMinecart.class,
|
||||
new AABB(pos))) {
|
||||
if (!CartAssemblerBlock.canAssembleTo(abstractMinecartEntity))
|
||||
break;
|
||||
connectedCart = abstractMinecartEntity;
|
||||
|
@ -118,8 +117,8 @@ public class MountedContraption extends Contraption {
|
|||
for (Axis axis : Iterate.axes) {
|
||||
if (axis.isVertical() || !VecHelper.onSameAxis(anchor, pos, axis))
|
||||
continue;
|
||||
for (AbstractMinecart abstractMinecartEntity : world
|
||||
.getEntitiesOfClass(AbstractMinecart.class, new AABB(pos))) {
|
||||
for (AbstractMinecart abstractMinecartEntity : world.getEntitiesOfClass(AbstractMinecart.class,
|
||||
new AABB(pos))) {
|
||||
if (!CartAssemblerBlock.canAssembleTo(abstractMinecartEntity))
|
||||
break;
|
||||
return true;
|
||||
|
@ -156,12 +155,9 @@ public class MountedContraption extends Contraption {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addExtraInventories(Entity cart) {
|
||||
if (!(cart instanceof Container))
|
||||
return;
|
||||
IItemHandlerModifiable handlerFromInv = new ContraptionInvWrapper(true, new InvWrapper((Container) cart));
|
||||
inventory = new ContraptionInvWrapper(handlerFromInv, inventory);
|
||||
if (cart instanceof Container container)
|
||||
storage.attachExternal(new ContraptionInvWrapper(true, new InvWrapper(container)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -45,7 +45,7 @@ public class ContraptionFluidPacket extends SimplePacketBase {
|
|||
if (!(entityByID instanceof AbstractContraptionEntity))
|
||||
return;
|
||||
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
|
||||
contraptionEntity.getContraption().updateContainedFluid(localPos, containedFluid);
|
||||
contraptionEntity.getContraption().handleContraptionFluidPacket(localPos, containedFluid);
|
||||
});
|
||||
context.get()
|
||||
.setPacketHandled(true);
|
||||
|
|
|
@ -54,7 +54,6 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
|
|||
else
|
||||
succ(context, pos);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void extract(MovementContext context, BlockPos pos) {
|
||||
|
@ -64,23 +63,22 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
|
|||
if (context.state.getValue(FunnelBlock.FACING) != Direction.DOWN)
|
||||
entityPos = entityPos.add(0, -.5f, 0);
|
||||
|
||||
if (!world.getBlockState(pos).getCollisionShape(world, pos).isEmpty())
|
||||
return;//only drop items if the target block is a empty space
|
||||
if (!world.getBlockState(pos)
|
||||
.getCollisionShape(world, pos)
|
||||
.isEmpty())
|
||||
return;
|
||||
|
||||
if (!world.getEntitiesOfClass(ItemEntity.class, new AABB(new BlockPos(entityPos))).isEmpty())
|
||||
return;//don't drop items if there already are any in the target block space
|
||||
if (!world.getEntitiesOfClass(ItemEntity.class, new AABB(new BlockPos(entityPos)))
|
||||
.isEmpty())
|
||||
return;
|
||||
|
||||
ItemStack filter = getFilter(context);
|
||||
int filterAmount = context.tileData.getInt("FilterAmount");
|
||||
if (filterAmount <= 0)
|
||||
filterAmount = hasFilter ? AllConfigs.SERVER.logistics.defaultExtractionLimit.get() : 1;
|
||||
|
||||
ItemStack extract = ItemHelper.extract(
|
||||
context.contraption.inventory,
|
||||
s -> FilterItem.test(world, s, filter),
|
||||
ItemHelper.ExtractionCountMode.UPTO,
|
||||
filterAmount,
|
||||
false);
|
||||
ItemStack extract = ItemHelper.extract(context.contraption.getSharedInventory(),
|
||||
s -> FilterItem.test(world, s, filter), ItemHelper.ExtractionCountMode.UPTO, filterAmount, false);
|
||||
|
||||
if (extract.isEmpty())
|
||||
return;
|
||||
|
@ -88,12 +86,10 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
|
|||
if (world.isClientSide)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
ItemEntity entity = new ItemEntity(world, entityPos.x, entityPos.y, entityPos.z, extract);
|
||||
entity.setDeltaMovement(Vec3.ZERO);
|
||||
entity.setPickUpDelay(5);
|
||||
world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.BLOCKS, 1/16f, .1f);
|
||||
world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.BLOCKS, 1 / 16f, .1f);
|
||||
world.addFreshEntity(entity);
|
||||
}
|
||||
|
||||
|
@ -108,7 +104,8 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
|
|||
ItemStack toInsert = item.getItem();
|
||||
if (!filter.isEmpty() && !FilterItem.test(context.world, toInsert, filter))
|
||||
continue;
|
||||
ItemStack remainder = ItemHandlerHelper.insertItemStacked(context.contraption.inventory, toInsert, false);
|
||||
ItemStack remainder =
|
||||
ItemHandlerHelper.insertItemStacked(context.contraption.getSharedInventory(), toInsert, false);
|
||||
if (remainder.getCount() == toInsert.getCount())
|
||||
continue;
|
||||
if (remainder.isEmpty()) {
|
||||
|
|
|
@ -55,10 +55,14 @@ public class TrackNodeLocation extends Vec3i {
|
|||
|
||||
@Override
|
||||
public boolean equals(Object pOther) {
|
||||
return super.equals(pOther) && pOther instanceof TrackNodeLocation tnl
|
||||
return equalsIgnoreDim(pOther) && pOther instanceof TrackNodeLocation tnl
|
||||
&& Objects.equals(tnl.dimension, dimension);
|
||||
}
|
||||
|
||||
public boolean equalsIgnoreDim(Object pOther) {
|
||||
return super.equals(pOther);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (this.getY() + (this.getZ() * 31 + dimension.hashCode()) * 31) * 31 + this.getX();
|
||||
|
|
|
@ -20,6 +20,7 @@ import javax.annotation.Nullable;
|
|||
import org.apache.commons.lang3.mutable.MutableDouble;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MountedStorageManager;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||
import com.simibubi.create.content.logistics.trains.DimensionPalette;
|
||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||
|
@ -60,6 +61,7 @@ public class Carriage {
|
|||
|
||||
public int bogeySpacing;
|
||||
public Couple<CarriageBogey> bogeys;
|
||||
public MountedStorageManager storage;
|
||||
|
||||
CompoundTag serialisedEntity;
|
||||
Map<Integer, CompoundTag> serialisedPassengers;
|
||||
|
@ -76,6 +78,7 @@ public class Carriage {
|
|||
this.presentConductors = Couple.create(false, false);
|
||||
this.serialisedPassengers = new HashMap<>();
|
||||
this.entities = new HashMap<>();
|
||||
this.storage = new MountedStorageManager();
|
||||
|
||||
bogey1.setLeading();
|
||||
bogey1.carriage = this;
|
||||
|
@ -92,6 +95,7 @@ public class Carriage {
|
|||
}
|
||||
|
||||
public void setContraption(Level level, CarriageContraption contraption) {
|
||||
this.storage = null;
|
||||
CarriageContraptionEntity entity = CarriageContraptionEntity.create(level, contraption);
|
||||
entity.setCarriage(this);
|
||||
contraption.startMoving(level);
|
||||
|
@ -177,7 +181,7 @@ public class Carriage {
|
|||
|
||||
double moved = point.travel(graph, toMove, trackSelector, signalListener, point.ignoreTurns(), c -> {
|
||||
for (DimensionalCarriageEntity dce : entities.values())
|
||||
if (c.either(tnl -> tnl.equals(dce.pivot)))
|
||||
if (c.either(tnl -> tnl.equalsIgnoreDim(dce.pivot)))
|
||||
return false;
|
||||
if (entities.size() > 1) {
|
||||
train.status.doublePortal();
|
||||
|
@ -220,7 +224,7 @@ public class Carriage {
|
|||
}
|
||||
|
||||
public void updateConductors() {
|
||||
if (anyAvailableEntity() == null || entities.size() > 1)
|
||||
if (anyAvailableEntity() == null || entities.size() > 1 || serialisedPassengers.size() > 0)
|
||||
return;
|
||||
presentConductors.replace($ -> false);
|
||||
for (DimensionalCarriageEntity dimensionalCarriageEntity : entities.values()) {
|
||||
|
@ -321,15 +325,6 @@ public class Carriage {
|
|||
: pivoted(dce, dimension, point,
|
||||
leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2);
|
||||
|
||||
int prevmin = dce.minAllowedLocalCoord();
|
||||
int prevmax = dce.maxAllowedLocalCoord();
|
||||
|
||||
dce.updateCutoff(leading);
|
||||
if (prevmin != dce.minAllowedLocalCoord() || prevmax != dce.maxAllowedLocalCoord()) {
|
||||
dce.updateRenderedCutoff();
|
||||
dce.updatePassengerLoadout();
|
||||
}
|
||||
|
||||
if (isOnTwoBogeys()) {
|
||||
dce.rotationAnchors.setFirst(dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition()
|
||||
: pivoted(dce, dimension, point,
|
||||
|
@ -337,18 +332,27 @@ public class Carriage {
|
|||
dce.rotationAnchors.setSecond(dimension.equals(trailingBogeyDim) ? trailingBogey.getAnchorPosition()
|
||||
: pivoted(dce, dimension, point,
|
||||
leading ? leadingWheelSpacing / 2 + bogeySpacing : trailingWheelSpacing / 2));
|
||||
continue;
|
||||
|
||||
} else {
|
||||
if (dimension.equals(otherDimension)) {
|
||||
dce.rotationAnchors = leadingBogey.points.map(TravellingPoint::getPosition);
|
||||
} else {
|
||||
dce.rotationAnchors.setFirst(leadingBogey.points.getFirst() == point ? point.getPosition()
|
||||
: pivoted(dce, dimension, point, leadingWheelSpacing));
|
||||
dce.rotationAnchors.setSecond(leadingBogey.points.getSecond() == point ? point.getPosition()
|
||||
: pivoted(dce, dimension, point, leadingWheelSpacing));
|
||||
}
|
||||
}
|
||||
|
||||
if (dimension.equals(otherDimension)) {
|
||||
dce.rotationAnchors = leadingBogey.points.map(TravellingPoint::getPosition);
|
||||
continue;
|
||||
}
|
||||
int prevmin = dce.minAllowedLocalCoord();
|
||||
int prevmax = dce.maxAllowedLocalCoord();
|
||||
|
||||
dce.rotationAnchors.setFirst(leadingBogey.points.getFirst() == point ? point.getPosition()
|
||||
: pivoted(dce, dimension, point, leadingWheelSpacing));
|
||||
dce.rotationAnchors.setSecond(leadingBogey.points.getSecond() == point ? point.getPosition()
|
||||
: pivoted(dce, dimension, point, leadingWheelSpacing));
|
||||
dce.updateCutoff(leading);
|
||||
|
||||
if (prevmin != dce.minAllowedLocalCoord() || prevmax != dce.maxAllowedLocalCoord()) {
|
||||
dce.updateRenderedCutoff();
|
||||
dce.updatePassengerLoadout();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -595,6 +599,7 @@ public class Carriage {
|
|||
CompoundTag tag = new CompoundTag();
|
||||
tag.putFloat("Cutoff", cutoff);
|
||||
tag.putInt("DiscardTicks", discardTicks);
|
||||
storage.write(tag, false);
|
||||
if (pivot != null)
|
||||
tag.put("Pivot", pivot.write(null));
|
||||
if (positionAnchor != null)
|
||||
|
@ -607,6 +612,7 @@ public class Carriage {
|
|||
public void read(CompoundTag tag) {
|
||||
cutoff = tag.getFloat("Cutoff");
|
||||
discardTicks = tag.getInt("DiscardTicks");
|
||||
storage.read(tag, null, false);
|
||||
if (tag.contains("Pivot"))
|
||||
pivot = TrackNodeLocation.read(tag.getCompound("Pivot"), null);
|
||||
if (positionAnchor != null)
|
||||
|
@ -749,13 +755,13 @@ public class Carriage {
|
|||
Entity entity = this.entity.get();
|
||||
if (!(entity instanceof CarriageContraptionEntity cce))
|
||||
return;
|
||||
if (!entity.level.isClientSide())
|
||||
return;
|
||||
Contraption contraption = cce.getContraption();
|
||||
if (!(contraption instanceof CarriageContraption cc))
|
||||
return;
|
||||
cc.portalCutoffMin = minAllowedLocalCoord();
|
||||
cc.portalCutoffMax = maxAllowedLocalCoord();
|
||||
if (!entity.level.isClientSide())
|
||||
return;
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> invalidate(cce));
|
||||
}
|
||||
|
||||
|
@ -776,12 +782,12 @@ public class Carriage {
|
|||
return;
|
||||
}
|
||||
|
||||
this.entity = new WeakReference<>(cce);
|
||||
|
||||
cce.setGraph(train.graph == null ? null : train.graph.id);
|
||||
cce.setCarriage(Carriage.this);
|
||||
cce.syncCarriage();
|
||||
|
||||
this.entity = new WeakReference<>(cce);
|
||||
|
||||
if (level instanceof ServerLevel sl)
|
||||
sl.tryAddFreshEntityWithPassengers(entity);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.simibubi.create.AllBlocks;
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MountedStorageManager;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter;
|
||||
|
@ -41,16 +42,21 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
|||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
|
||||
public class CarriageContraption extends Contraption {
|
||||
|
||||
private Direction assemblyDirection;
|
||||
private boolean forwardControls;
|
||||
private boolean backwardControls;
|
||||
|
||||
public Couple<Boolean> blazeBurnerConductors;
|
||||
public Map<BlockPos, Couple<Boolean>> conductorSeats;
|
||||
public ArrivalSoundQueue soundQueue;
|
||||
|
||||
protected MountedStorageManager storageProxy;
|
||||
|
||||
// during assembly only
|
||||
private int bogeys;
|
||||
private boolean sidewaysControls;
|
||||
|
@ -116,6 +122,21 @@ public class CarriageContraption extends Contraption {
|
|||
return info.state.getValue(ControlsBlock.FACING) == direction.getOpposite();
|
||||
}
|
||||
|
||||
public void swapStorageAfterAssembly(CarriageContraptionEntity cce) {
|
||||
// Ensure that the entity does not hold its inventory data, because the global
|
||||
// carriage manages it instead
|
||||
Carriage carriage = cce.getCarriage();
|
||||
if (carriage.storage == null) {
|
||||
carriage.storage = storage;
|
||||
storage = new MountedStorageManager();
|
||||
}
|
||||
storageProxy = carriage.storage;
|
||||
}
|
||||
|
||||
public void returnStorageForDisassembly(MountedStorageManager storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAnchoringBlockAt(BlockPos pos) {
|
||||
return false;
|
||||
|
@ -272,7 +293,7 @@ public class CarriageContraption extends Contraption {
|
|||
return !withinVisible(localPos) || atSeam(localPos);
|
||||
}
|
||||
|
||||
private boolean notInPortal() {
|
||||
public boolean notInPortal() {
|
||||
return portalCutoffMin == Integer.MIN_VALUE && portalCutoffMax == Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
|
@ -294,4 +315,15 @@ public class CarriageContraption extends Contraption {
|
|||
return coord > portalCutoffMin && coord < portalCutoffMax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemHandlerModifiable getSharedInventory() {
|
||||
return storageProxy.getItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFluidHandler getSharedFluidTanks() {
|
||||
return storageProxy.getFluids();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -186,6 +186,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
dimensional.entity = new WeakReference<>(this);
|
||||
dimensional.pivot = null;
|
||||
carriage.updateContraptionAnchors();
|
||||
dimensional.updateRenderedCutoff();
|
||||
}
|
||||
updateTrackGraph();
|
||||
} else
|
||||
|
@ -316,7 +317,8 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
|
||||
@Override
|
||||
protected boolean isActorActive(MovementContext context, MovementBehaviour actor) {
|
||||
return !getContraption().isHiddenInPortal(context.localPos) && super.isActorActive(context, actor);
|
||||
return (contraption instanceof CarriageContraption cc) && (cc.notInPortal() || level.isClientSide())
|
||||
&& super.isActorActive(context, actor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -605,6 +607,13 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
|
|||
this.carriage = carriage;
|
||||
this.trainId = carriage.train.id;
|
||||
this.carriageIndex = carriage.train.carriages.indexOf(carriage);
|
||||
if (contraption instanceof CarriageContraption cc)
|
||||
cc.swapStorageAfterAssembly(this);
|
||||
|
||||
DimensionalCarriageEntity dimensional = carriage.getDimensional(level);
|
||||
dimensional.pivot = null;
|
||||
carriage.updateContraptionAnchors();
|
||||
dimensional.updateRenderedCutoff();
|
||||
}
|
||||
|
||||
public void setGraph(@Nullable UUID graphId) {
|
||||
|
|
|
@ -541,6 +541,8 @@ public class Train {
|
|||
if (entity == null)
|
||||
return false;
|
||||
|
||||
if (entity.getContraption() instanceof CarriageContraption cc)
|
||||
cc.returnStorageForDisassembly(carriage.storage);
|
||||
entity.setPos(Vec3
|
||||
.atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset)));
|
||||
entity.disassemble();
|
||||
|
|
Loading…
Reference in a new issue