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