From 43af1526416c581895b4d02a5ab7fe3eb5dfb123 Mon Sep 17 00:00:00 2001 From: Talrey Date: Thu, 12 May 2022 13:45:04 -0700 Subject: [PATCH 1/7] found a typo in OUTPUT --- .../tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java index b6682cbdd..565518ec4 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java @@ -24,7 +24,7 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { public static final BehaviourType - TYPE = new BehaviourType<>(), INPUT = new BehaviourType<>("Input"), oOUTPUT = new BehaviourType<>("Output"); + TYPE = new BehaviourType<>(), INPUT = new BehaviourType<>("Input"), OUTPUT = new BehaviourType<>("Output"); private static final int SYNC_RATE = 8; From 71af8410469714799597a127d79425ad874d00a8 Mon Sep 17 00:00:00 2001 From: Talrey Date: Fri, 13 May 2022 12:37:15 -0700 Subject: [PATCH 2/7] world of fluidtanks --- .../api/connectivity/ConnectivityHandler.java | 372 ++++++++++++++++++ .../BlockMovementChecks.java | 5 +- .../fluids/tank/FluidTankBlock.java | 12 +- .../fluids/tank/FluidTankCTBehaviour.java | 3 +- .../fluids/tank/FluidTankItem.java | 5 +- .../fluids/tank/FluidTankModel.java | 9 +- .../fluids/tank/FluidTankTileEntity.java | 89 ++++- .../tileEntity/IMultiTileContainer.java | 67 +++- 8 files changed, 540 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java diff --git a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java new file mode 100644 index 000000000..b1801c729 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java @@ -0,0 +1,372 @@ +package com.simibubi.create.api.connectivity; + +import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity; +import com.simibubi.create.foundation.tileEntity.IMultiTileContainer; + +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; + +import net.minecraftforge.fluids.capability.IFluidHandler; + +import net.minecraftforge.items.CapabilityItemHandler; + +import org.apache.commons.lang3.tuple.Pair; + +import javax.annotation.Nullable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.PriorityQueue; +import java.util.Set; + +public class ConnectivityHandler { + + public static void formMulti (T be) { + SearchCache cache = new SearchCache<>(); + List frontier = new ArrayList<>(); + frontier.add(be); + formMulti(be.getType(), be.getLevel(), cache, frontier); + } + + private static void formMulti (BlockEntityType type, BlockGetter level, SearchCache cache, List frontier) { + PriorityQueue> creationQueue = makeCreationQueue(); + Set visited = new HashSet<>(); + Direction.Axis mainAxis = frontier.get(0).getMainConnectionAxis(); + + // essentially, if it's a vertical multi then the search won't be restricted by Y + // alternately, a horizontal multi search shouldn't be restricted by X or Z + int minX = (mainAxis == Direction.Axis.Y ? Integer.MAX_VALUE : Integer.MIN_VALUE); + int minY = (mainAxis != Direction.Axis.Y ? Integer.MAX_VALUE : Integer.MIN_VALUE); + int minZ = (mainAxis == Direction.Axis.Y ? Integer.MAX_VALUE : Integer.MIN_VALUE); + + for (T be : frontier) { + BlockPos pos = be.getBlockPos(); + minX = Math.min(pos.getX(), minX); + minY = Math.min(pos.getY(), minY); + minZ = Math.min(pos.getZ(), minZ); + } + if (mainAxis == Direction.Axis.Y) minX -= frontier.get(0).getMaxWidth(); + if (mainAxis != Direction.Axis.Y) minY -= frontier.get(0).getMaxWidth(); + if (mainAxis == Direction.Axis.Y) minZ -= frontier.get(0).getMaxWidth(); + + while (!frontier.isEmpty()) { + T part = frontier.remove(0); + BlockPos partPos = part.getBlockPos(); + if (visited.contains(partPos)) continue; + + visited.add(partPos); + + int amount = tryToFormNewMulti(part, cache, true); + if (amount > 1) { + creationQueue.add(Pair.of(amount, part)); + } + + for (Direction.Axis axis : Iterate.axes) { + Direction dir = Direction.get(Direction.AxisDirection.NEGATIVE, axis); + BlockPos next = partPos.relative(dir); + + if (next.getX() <= minX || next.getY() <= minY || next.getZ() <= minZ) continue; + if (visited.contains(next)) continue; + T nextBe = partAt(type, level, next); + if (nextBe == null) continue; + if (nextBe.isRemoved()) continue; + frontier.add(nextBe); + } + } + visited.clear(); + + while (!creationQueue.isEmpty()) { + Pair next = creationQueue.poll(); + T toCreate = next.getValue(); + if (visited.contains(toCreate.getBlockPos())) continue; + + visited.add(toCreate.getBlockPos()); + tryToFormNewMulti(toCreate, cache, false); + } + } + + private static int tryToFormNewMulti (T be, SearchCache cache, boolean simulate) { + int bestWidth = 1; + int bestAmount = -1; + if (!be.isController()) return 0; + + int radius = be.getMaxWidth(); + for (int w = 1; w <= radius; w++) { + int amount = tryToFormNewMultiOfWidth(be, w, cache, true); + if (amount < bestAmount) continue; + bestWidth = w; + bestAmount = amount; + } + + if (!simulate) { + int beWidth = be.getWidth(); + if (beWidth == bestWidth && beWidth*beWidth * be.getHeight() == bestAmount) return bestAmount; + + splitMultiAndInvalidate(be, cache, false); + if (be.hasFluid()) be.setTankSize(0, bestAmount); + + tryToFormNewMultiOfWidth(be, bestWidth, cache, false); + + be.preventConnectivityUpdate(); + be.setWidth(bestWidth); + be.setHeight(bestAmount / bestWidth / bestWidth); + be.notifyMultiUpdated(); + } + return bestAmount; + } + + private static int tryToFormNewMultiOfWidth (T be, int width, SearchCache cache, boolean simulate) { + int amount = 0; + int height = 0; + BlockEntityType type = be.getType(); + Level level = be.getLevel(); + if (level == null) return 0; + BlockPos origin = be.getBlockPos(); + + // optional fluid handling + IFluidTank beTank = null; + FluidStack fluid = FluidStack.EMPTY; + if (be.hasFluid()) { + beTank = be.getTank(0); + fluid = beTank.getFluid(); + } + Direction.Axis axis = be.getMainConnectionAxis(); + + Search: + for (int yOffset = 0; yOffset < be.getMaxLength(axis, width); yOffset++) { + for (int xOffset = 0; xOffset < width; xOffset++) { + for (int zOffset = 0; zOffset < width; zOffset++) { + BlockPos pos = switch (axis) { + case X -> origin.offset(yOffset, xOffset, zOffset); + case Y -> origin.offset(xOffset, yOffset, zOffset); + case Z -> origin.offset(xOffset, zOffset, yOffset); + }; + Optional part = cache.getOrCache(type, level, pos); + if (part.isEmpty()) break Search; + + T controller = part.get(); + int otherWidth = controller.getWidth(); + if (otherWidth > width) break Search; + if (otherWidth == width && controller.getHeight() == be.getMaxLength(axis, width)) break Search; + + Direction.Axis conAxis = controller.getMainConnectionAxis(); + if (axis != conAxis) break Search; + + BlockPos conPos = controller.getBlockPos(); + if (!conPos.equals(origin)) { + if (axis == Direction.Axis.Y) { // vertical multi, like a FluidTank + if (conPos.getX() < origin.getX()) break Search; + if (conPos.getZ() < origin.getZ()) break Search; + if (conPos.getX() + otherWidth > origin.getX() + width) break Search; + if (conPos.getZ() + otherWidth > origin.getZ() + width) break Search; + } else { // horizontal multi, like an ItemVault + if (axis == Direction.Axis.Z && conPos.getX() < origin.getX()) break Search; + if (conPos.getY() < origin.getY()) break Search; + if (axis == Direction.Axis.X && conPos.getZ() < origin.getZ()) break Search; + if (axis == Direction.Axis.Z && conPos.getX() + otherWidth > origin.getX() + width) break Search; + if (conPos.getY() + otherWidth > origin.getY() + width) break Search; + if (axis == Direction.Axis.X && conPos.getZ() + otherWidth > origin.getZ() + width) break Search; + } + } + FluidStack otherFluid = controller.getFluid(0); + if (!fluid.isEmpty() && !otherFluid.isEmpty() && !fluid.isFluidEqual(otherFluid)) break Search; + } + } + amount += width * width; + height++; + } + + if (simulate) return amount; + + Object extraData = be.getExtraData(); + + for (int yOffset = 0; yOffset < height; yOffset++) { + for (int xOffset = 0; xOffset < width; xOffset++) { + for (int zOffset = 0; zOffset < width; zOffset++) { + BlockPos pos = switch (axis) { + case X -> origin.offset(yOffset, xOffset, zOffset); + case Y -> origin.offset(xOffset, yOffset, zOffset); + case Z -> origin.offset(xOffset, zOffset, yOffset); + }; + T part = partAt(type, level, pos); + if (part == null) continue; + if (part == be) continue; + + extraData = be.modifyExtraData(extraData); + + if (part.hasFluid()) { + IFluidTank tankAt = part.getTank(0); + FluidStack fluidAt = tankAt.getFluid(); + if (!fluidAt.isEmpty()) { + // making this generic would be a rather large mess, unfortunately + if (beTank != null && fluid.isEmpty() && beTank instanceof CreativeFluidTankTileEntity.CreativeSmartFluidTank) { + ((CreativeFluidTankTileEntity.CreativeSmartFluidTank)beTank).setContainedFluid(fluidAt); + } + } + tankAt.drain(tankAt.getCapacity(), IFluidHandler.FluidAction.EXECUTE); + } + + splitMultiAndInvalidate(part, cache, false); + part.setController(origin); + part.preventConnectivityUpdate(); + cache.put(pos, be); + part.setHeight(height); + part.notifyMultiUpdated(); + } + } + } + be.setExtraData(extraData); + be.notifyMultiUpdated(); + return amount; + } + + public static void splitMulti (T be) { + splitMultiAndInvalidate(be, null, false); + } + + // tryReconnect helps whenever only a few tanks have been removed + private static void splitMultiAndInvalidate (T be, @Nullable SearchCache cache, boolean tryReconnect) { + Level level = be.getLevel(); + if (level == null) return; + + be = be.getControllerTE(); + if (be == null) return; + + int height = be.getHeight(); + int width = be.getWidth(); + if (width == 1 && height == 1) return; + + BlockPos origin = be.getBlockPos(); + List frontier = new ArrayList<>(); + Direction.Axis axis = be.getMainConnectionAxis(); + + // fluid handling, if present + FluidStack toDistribute = FluidStack.EMPTY; + int maxCapacity = 0; + if (be.hasFluid()) { + toDistribute = be.getFluid(0); + maxCapacity = be.getTankSize(0); + if (!toDistribute.isEmpty() && !be.isRemoved()) toDistribute.shrink(maxCapacity); + be.setTankSize(0, 1); + } + + for (int yOffset = 0; yOffset < height; yOffset++) { + for (int xOffset = 0; xOffset < width; xOffset++) { + for (int zOffset = 0; zOffset < width; zOffset++) { + BlockPos pos = switch (axis) { + case X -> origin.offset(yOffset, xOffset, zOffset); + case Y -> origin.offset(xOffset, yOffset, zOffset); + case Z -> origin.offset(xOffset, zOffset, yOffset); + }; + T partAt = partAt(be.getType(), level, pos); + if (partAt == null) continue; + if (!partAt.getController().equals(origin)) continue; + + T controllerBE = partAt.getControllerTE(); + partAt.setExtraData ( (controllerBE == null ? null : controllerBE.getExtraData())); + partAt.removeController(true); + + if (!toDistribute.isEmpty() && partAt != be) { + FluidStack copy = toDistribute.copy(); + IFluidTank tank = partAt.getTank(0); + // making this generic would be a rather large mess, unfortunately + if (tank instanceof CreativeFluidTankTileEntity.CreativeSmartFluidTank creativeTank) { + if (creativeTank.isEmpty()) creativeTank.setContainedFluid(toDistribute); + } + else { + int split = Math.min(maxCapacity, toDistribute.getAmount()); + copy.setAmount(split); + toDistribute.shrink(split); + tank.fill(copy, IFluidHandler.FluidAction.EXECUTE); + } + } + if (tryReconnect) { + frontier.add(partAt); + partAt.preventConnectivityUpdate(); + } + if (cache != null) { + cache.put(pos, partAt); + } + } + } + } + if (be.hasItems()) { + be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).invalidate(); + } + if (be.hasFluid()) { + be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY).invalidate(); + } + if (tryReconnect) { + formMulti(be.getType(), level, cache == null ? new SearchCache<>() : cache, frontier); + } + } + + private static PriorityQueue> makeCreationQueue () { + return new PriorityQueue<>((one, two) -> two.getKey() - one.getKey()); + } + + @Nullable + public static T partAt (BlockEntityType type, BlockGetter level, BlockPos pos) { + BlockEntity be = level.getBlockEntity(pos); + if (be != null && be.getType() == type) return checked(be); + + return null; + } + + public static boolean isConnected (BlockGetter level, BlockPos pos, BlockPos other) { + T one = checked(level.getBlockEntity(pos)); + T two = checked(level.getBlockEntity(other)); + if (one == null || two == null) return false; + return one.getController().equals(two.getController()); + } + + @Nullable + @SuppressWarnings("unchecked") + private static T checked (BlockEntity be) { + if (be instanceof IMultiTileContainer) return (T)be; + return null; + } + + private static class SearchCache { + Map> controllerMap; + + public SearchCache () { controllerMap = new HashMap<>(); } + + void put (BlockPos pos, T target) { controllerMap.put(pos, Optional.of(target)); } + + void putEmpty (BlockPos pos) { controllerMap.put(pos, Optional.empty()); } + + boolean hasVisited (BlockPos pos) { return controllerMap.containsKey(pos); } + + Optional getOrCache (BlockEntityType type, BlockGetter level, BlockPos pos) { + if (hasVisited(pos)) return controllerMap.get(pos); + + T partAt = partAt(type, level, pos); + if (partAt == null) { + putEmpty(pos); + return Optional.empty(); + } + T controller = checked(level.getBlockEntity(partAt.getController())); + if (controller == null) { + putEmpty(pos); + return Optional.empty(); + } + put(pos, controller); + return Optional.of(controller); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java index 1e9819474..18e989689 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java @@ -5,6 +5,7 @@ import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.api.connectivity.ConnectivityHandler; import com.simibubi.create.content.contraptions.components.actors.AttachedActorBlock; import com.simibubi.create.content.contraptions.components.actors.HarvesterBlock; import com.simibubi.create.content.contraptions.components.actors.PloughBlock; @@ -330,7 +331,7 @@ public class BlockMovementChecks { return direction.getAxis() != state.getValue(SailBlock.FACING) .getAxis(); if (state.getBlock() instanceof FluidTankBlock) - return FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(direction)); + return ConnectivityHandler.isConnected(world, pos, pos.relative(direction)); //FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(direction)); if (state.getBlock() instanceof ItemVaultBlock) return ItemVaultConnectivityHandler.isConnected(world, pos, pos.relative(direction)); if (AllBlocks.STICKER.has(state) && state.getValue(StickerBlock.EXTENDED)) { @@ -349,7 +350,7 @@ public class BlockMovementChecks { return state.getValue(HarvesterBlock.FACING) == facing; if (AllBlocks.MECHANICAL_PLOUGH.has(state)) return state.getValue(PloughBlock.FACING) == facing; - + if (AllBlocks.CART_ASSEMBLER.has(state)) return Direction.DOWN == facing; if (AllBlocks.MECHANICAL_SAW.has(state)) diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java index f128fba7a..920d78f34 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.fluids.tank; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.api.connectivity.ConnectivityHandler; import com.simibubi.create.content.contraptions.fluids.actors.GenericItemFilling; import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity.CreativeSmartFluidTank; import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; @@ -90,10 +91,10 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE p_206840_1_) { p_206840_1_.add(TOP, BOTTOM, SHAPE); } - + @Override public int getLightEmission(BlockState state, BlockGetter world, BlockPos pos) { - FluidTankTileEntity tankAt = FluidTankConnectivityHandler.anyTankAt(world, pos); + FluidTankTileEntity tankAt = ConnectivityHandler.partAt(getTileEntityType(), world, pos); //FluidTankConnectivityHandler.anyTankAt(world, pos); if (tankAt == null) return 0; FluidTankTileEntity controllerTE = tankAt.getControllerTE(); @@ -120,7 +121,7 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE getTileEntityClass() { return FluidTankTileEntity.class; } - + @Override public BlockEntityType getTileEntityType() { return creative ? AllTileEntities.CREATIVE_FLUID_TANK.get() : AllTileEntities.FLUID_TANK.get(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankCTBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankCTBehaviour.java index 283981a69..0e9843af9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankCTBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankCTBehaviour.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.fluids.tank; +import com.simibubi.create.api.connectivity.ConnectivityHandler; import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour; @@ -21,6 +22,6 @@ public class FluidTankCTBehaviour extends HorizontalCTBehaviour { @Override public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos, Direction face) { - return state.getBlock() == other.getBlock() && FluidTankConnectivityHandler.isConnected(reader, pos, otherPos); + return state.getBlock() == other.getBlock() && ConnectivityHandler.isConnected(reader, pos, otherPos); //FluidTankConnectivityHandler.isConnected(reader, pos, otherPos); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java index b2697c105..80745e342 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java @@ -1,5 +1,8 @@ package com.simibubi.create.content.contraptions.fluids.tank; +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.api.connectivity.ConnectivityHandler; + import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -71,7 +74,7 @@ public class FluidTankItem extends BlockItem { if (!FluidTankBlock.isTank(placedOnState)) return; - FluidTankTileEntity tankAt = FluidTankConnectivityHandler.anyTankAt(world, placedOnPos); + FluidTankTileEntity tankAt = ConnectivityHandler.partAt(AllTileEntities.FLUID_TANK.get(), world, placedOnPos); //FluidTankConnectivityHandler.anyTankAt(world, placedOnPos); if (tankAt == null) return; FluidTankTileEntity controllerTE = tankAt.getControllerTE(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java index 34a326704..5796a7e59 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Random; import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.api.connectivity.ConnectivityHandler; import com.simibubi.create.foundation.block.connected.CTModel; import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; import com.simibubi.create.foundation.utility.Iterate; @@ -28,20 +29,20 @@ public class FluidTankModel extends CTModel { public static FluidTankModel standard(BakedModel originalModel) { return new FluidTankModel(originalModel, AllSpriteShifts.FLUID_TANK, AllSpriteShifts.COPPER_CASING); } - + public static FluidTankModel creative(BakedModel originalModel) { return new FluidTankModel(originalModel, AllSpriteShifts.CREATIVE_FLUID_TANK, AllSpriteShifts.CREATIVE_CASING); } - + private FluidTankModel(BakedModel originalModel, CTSpriteShiftEntry side, CTSpriteShiftEntry top) { super(originalModel, new FluidTankCTBehaviour(side, top)); } - + @Override protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state) { CullData cullData = new CullData(); for (Direction d : Iterate.horizontalDirections) - cullData.setCulled(d, FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(d))); + cullData.setCulled(d, ConnectivityHandler.isConnected(world, pos, pos.relative(d))); //FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(d))); return super.gatherModelData(builder, world, pos, state).withInitial(CULL_PROPERTY, cullData); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java index d1eed27d2..d4f0d71c3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java @@ -7,6 +7,8 @@ import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import com.simibubi.create.Create; +import com.simibubi.create.api.connectivity.ConnectivityHandler; import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock.Shape; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.foundation.config.AllConfigs; @@ -79,7 +81,8 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI return; if (!isController()) return; - FluidTankConnectivityHandler.formTanks(this); + //FluidTankConnectivityHandler.formTanks(this); + ConnectivityHandler.formMulti(this); } @Override @@ -103,7 +106,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI if (fluidLevel != null) fluidLevel.tick(); } - + @Override public BlockPos getLastKnownPos() { return lastKnownPos; @@ -145,7 +148,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset); - FluidTankTileEntity tankAt = FluidTankConnectivityHandler.anyTankAt(level, pos); + FluidTankTileEntity tankAt = ConnectivityHandler.partAt(getType(), level, pos); //FluidTankConnectivityHandler.anyTankAt(level, pos); if (tankAt == null) continue; level.updateNeighbourForOutputSignal(pos, tankAt.getBlockState() @@ -161,7 +164,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI setChanged(); sendData(); } - + if (isVirtual()) { if (fluidLevel == null) fluidLevel = new InterpolatedChasingValue().start(getFillState()); @@ -462,4 +465,82 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI this.fluidLevel = fluidLevel; } + @Override + public void preventConnectivityUpdate() { updateConnectivity = false; } + + @Override + public void notifyMultiUpdated () { + BlockState state = this.getBlockState(); + if (FluidTankBlock.isTank(state)) { // safety + state = state.setValue(FluidTankBlock.BOTTOM, getController().getY() == getBlockPos().getY()); + state = state.setValue(FluidTankBlock.TOP, getController().getY() + height - 1 == getBlockPos().getY()); + level.setBlock(getBlockPos(), state, 22); + } + setWindows(window); + onFluidStackChanged(tankInventory.getFluid()); + setChanged(); + } + + @Override + public void setExtraData (@Nullable Object data) { + if (data instanceof Boolean) window = (boolean)data; + } + + @Override + @Nullable + public Object getExtraData () { return window; } + + @Override + public Object modifyExtraData (Object data) { + if (data instanceof Boolean windows) { + windows |= window; + return windows; + } + return data; + } + + @Override + public Direction.Axis getMainConnectionAxis() { return Direction.Axis.Y; } + + @Override + public int getMaxLength (Direction.Axis longAxis, int width) { + if (longAxis == Direction.Axis.Y) return getMaxHeight(); + return getMaxWidth(); + } + + @Override + public int getMaxWidth () { return MAX_SIZE; } + + @Override + public int getHeight () { return height; } + + @Override + public void setHeight (int height) { this.height = height; } + + @Override + public int getWidth () { return width; } + + @Override + public void setWidth (int width) { this.width = width; } + + @Override + public boolean hasFluid () { return true; } + + @Override + public int getTankSize (int tank) { return getCapacityMultiplier(); } + + @Override + public void setTankSize (int tank, int blocks) { + applyFluidTankSize(blocks); + } + + @Override + public IFluidTank getTank (int tank) { + return tankInventory; + } + + @Override + public FluidStack getFluid (int tank) { + return tankInventory.getFluid().copy(); + } } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/IMultiTileContainer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/IMultiTileContainer.java index 77a1161e8..68d3eaa6d 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/IMultiTileContainer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/IMultiTileContainer.java @@ -1,12 +1,69 @@ package com.simibubi.create.foundation.tileEntity; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; + +import javax.annotation.Nullable; public interface IMultiTileContainer { - - public BlockPos getController(); - public boolean isController(); - public void setController(BlockPos pos); - public BlockPos getLastKnownPos(); + BlockPos getController(); + T getControllerTE (); + boolean isController(); + void setController(BlockPos pos); + void removeController (boolean keepContents); + BlockPos getLastKnownPos(); + + void preventConnectivityUpdate (); + void notifyMultiUpdated (); + + // only used for FluidTank windows at present. Might be useful for similar properties on other things? + default void setExtraData (@Nullable Object data) {} + @Nullable + default Object getExtraData () { return null; } + default Object modifyExtraData (Object data) { return data; } + + // multiblock structural information + Direction.Axis getMainConnectionAxis(); + default Direction.Axis getMainAxisOf (BlockEntity be) { // this feels redundant, but it gives us a default to use when defining ::getMainConnectionAxis + BlockState state = be.getBlockState(); + + Direction.Axis axis; + if (state.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { + axis = state.getValue(BlockStateProperties.HORIZONTAL_AXIS); + } + else if (state.hasProperty(BlockStateProperties.FACING)) { + axis = state.getValue(BlockStateProperties.FACING).getAxis(); + } + else if (state.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) { + axis = state.getValue(BlockStateProperties.HORIZONTAL_FACING).getAxis(); + } + else axis = Direction.Axis.Y; + + return axis; + } + + int getMaxLength (Direction.Axis longAxis, int width); + int getMaxWidth (); + + int getHeight (); + void setHeight (int height); + int getWidth (); + void setWidth (int width); + + // optional item handling + default boolean hasItems () { return false; } + + // optional fluid handling + // done here rather than through the Capability to allow greater flexibility + default boolean hasFluid () { return false; } + default int getTankSize (int tank) { return 0; } + default void setTankSize (int tank, int blocks) {} + default IFluidTank getTank (int tank) { return null; } + default FluidStack getFluid (int tank) { return FluidStack.EMPTY; } } From 5ca51bd58c3d7dfd74b23f779e23ce121af8920c Mon Sep 17 00:00:00 2001 From: Talrey Date: Fri, 13 May 2022 13:01:29 -0700 Subject: [PATCH 3/7] itemvault hunters --- .../api/connectivity/ConnectivityHandler.java | 1 + .../BlockMovementChecks.java | 2 +- .../logistics/block/vault/ItemVaultBlock.java | 11 ++-- .../block/vault/ItemVaultCTBehaviour.java | 3 +- .../logistics/block/vault/ItemVaultItem.java | 4 +- .../block/vault/ItemVaultTileEntity.java | 58 ++++++++++++++++--- 6 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java index b1801c729..747e4bff8 100644 --- a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java +++ b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java @@ -225,6 +225,7 @@ public class ConnectivityHandler { part.preventConnectivityUpdate(); cache.put(pos, be); part.setHeight(height); + part.setWidth(width); part.notifyMultiUpdated(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java index 18e989689..5832da41a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java @@ -333,7 +333,7 @@ public class BlockMovementChecks { if (state.getBlock() instanceof FluidTankBlock) return ConnectivityHandler.isConnected(world, pos, pos.relative(direction)); //FluidTankConnectivityHandler.isConnected(world, pos, pos.relative(direction)); if (state.getBlock() instanceof ItemVaultBlock) - return ItemVaultConnectivityHandler.isConnected(world, pos, pos.relative(direction)); + return ConnectivityHandler.isConnected(world, pos, pos.relative(direction)); //ItemVaultConnectivityHandler.isConnected(world, pos, pos.relative(direction)); if (AllBlocks.STICKER.has(state) && state.getValue(StickerBlock.EXTENDED)) { return direction == state.getValue(StickerBlock.FACING) && !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite()); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java index e8fb413b8..34bbde3e7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java @@ -4,6 +4,7 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.api.connectivity.ConnectivityHandler; import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.item.ItemHelper; @@ -85,7 +86,8 @@ public class ItemVaultBlock extends Block implements IWrenchable, ITE 2), 22); + } + itemCapability.invalidate(); + setChanged(); + } + + @Override + public Direction.Axis getMainConnectionAxis() { return getMainAxisOf(this); } + + @Override + public int getMaxLength (Direction.Axis longAxis, int width) { + if (longAxis == Direction.Axis.Y) return getMaxWidth(); + return getMaxLength(width); + } + + @Override + public int getMaxWidth () { + return 3; + } + + @Override + public int getHeight () { return length; } + + @Override + public int getWidth () { return radius; } + + @Override + public void setHeight (int height) { this.length = height; } + + @Override + public void setWidth (int width) { this.radius = width; } + + @Override + public boolean hasItems () { return true; } } From b1f8b1293f94f362a4fb770e00aa873a5995a91d Mon Sep 17 00:00:00 2001 From: Talrey Date: Fri, 13 May 2022 14:20:25 -0700 Subject: [PATCH 4/7] getting creative --- .../content/contraptions/fluids/tank/FluidTankItem.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java index 80745e342..43bb3b288 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.fluids.tank; +import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; import com.simibubi.create.api.connectivity.ConnectivityHandler; @@ -74,7 +75,11 @@ public class FluidTankItem extends BlockItem { if (!FluidTankBlock.isTank(placedOnState)) return; - FluidTankTileEntity tankAt = ConnectivityHandler.partAt(AllTileEntities.FLUID_TANK.get(), world, placedOnPos); //FluidTankConnectivityHandler.anyTankAt(world, placedOnPos); + boolean creative = getBlock().equals(AllBlocks.CREATIVE_FLUID_TANK.get()); + FluidTankTileEntity tankAt = ConnectivityHandler.partAt( + creative ? AllTileEntities.CREATIVE_FLUID_TANK.get() : AllTileEntities.FLUID_TANK.get(), world, placedOnPos + ); + //FluidTankConnectivityHandler.anyTankAt(world, placedOnPos); if (tankAt == null) return; FluidTankTileEntity controllerTE = tankAt.getControllerTE(); From 2ad8ffe0edf86359410aae41d14572e4bd555ff2 Mon Sep 17 00:00:00 2001 From: Talrey Date: Fri, 13 May 2022 14:36:26 -0700 Subject: [PATCH 5/7] tanks for the fill up --- .../simibubi/create/api/connectivity/ConnectivityHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java index 747e4bff8..d98ac5e58 100644 --- a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java +++ b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java @@ -216,6 +216,7 @@ public class ConnectivityHandler { if (beTank != null && fluid.isEmpty() && beTank instanceof CreativeFluidTankTileEntity.CreativeSmartFluidTank) { ((CreativeFluidTankTileEntity.CreativeSmartFluidTank)beTank).setContainedFluid(fluidAt); } + if (be.hasFluid() && beTank != null) beTank.fill(fluidAt, IFluidHandler.FluidAction.EXECUTE); } tankAt.drain(tankAt.getCapacity(), IFluidHandler.FluidAction.EXECUTE); } From b088843aa174f91698137481688b10806fc7e156 Mon Sep 17 00:00:00 2001 From: Talrey Date: Fri, 13 May 2022 15:20:13 -0700 Subject: [PATCH 6/7] cleanup and style --- .../api/connectivity/ConnectivityHandler.java | 32 +- .../fluids/tank/FluidTankBlock.java | 5 +- .../tank/FluidTankConnectivityHandler.java | 381 ------------------ .../fluids/tank/FluidTankItem.java | 1 - .../fluids/tank/FluidTankTileEntity.java | 34 +- .../logistics/block/vault/ItemVaultBlock.java | 2 - .../vault/ItemVaultConnectivityHandler.java | 329 --------------- .../logistics/block/vault/ItemVaultItem.java | 1 - .../block/vault/ItemVaultTileEntity.java | 18 +- 9 files changed, 42 insertions(+), 761 deletions(-) delete mode 100644 src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankConnectivityHandler.java delete mode 100644 src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultConnectivityHandler.java diff --git a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java index d98ac5e58..9dd41c073 100644 --- a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java +++ b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java @@ -35,14 +35,14 @@ import java.util.Set; public class ConnectivityHandler { - public static void formMulti (T be) { + public static void formMulti(T be) { SearchCache cache = new SearchCache<>(); List frontier = new ArrayList<>(); frontier.add(be); formMulti(be.getType(), be.getLevel(), cache, frontier); } - private static void formMulti (BlockEntityType type, BlockGetter level, SearchCache cache, List frontier) { + private static void formMulti(BlockEntityType type, BlockGetter level, SearchCache cache, List frontier) { PriorityQueue> creationQueue = makeCreationQueue(); Set visited = new HashSet<>(); Direction.Axis mainAxis = frontier.get(0).getMainConnectionAxis(); @@ -99,7 +99,7 @@ public class ConnectivityHandler { } } - private static int tryToFormNewMulti (T be, SearchCache cache, boolean simulate) { + private static int tryToFormNewMulti(T be, SearchCache cache, boolean simulate) { int bestWidth = 1; int bestAmount = -1; if (!be.isController()) return 0; @@ -129,7 +129,7 @@ public class ConnectivityHandler { return bestAmount; } - private static int tryToFormNewMultiOfWidth (T be, int width, SearchCache cache, boolean simulate) { + private static int tryToFormNewMultiOfWidth(T be, int width, SearchCache cache, boolean simulate) { int amount = 0; int height = 0; BlockEntityType type = be.getType(); @@ -236,12 +236,12 @@ public class ConnectivityHandler { return amount; } - public static void splitMulti (T be) { + public static void splitMulti(T be) { splitMultiAndInvalidate(be, null, false); } // tryReconnect helps whenever only a few tanks have been removed - private static void splitMultiAndInvalidate (T be, @Nullable SearchCache cache, boolean tryReconnect) { + private static void splitMultiAndInvalidate(T be, @Nullable SearchCache cache, boolean tryReconnect) { Level level = be.getLevel(); if (level == null) return; @@ -279,7 +279,7 @@ public class ConnectivityHandler { if (!partAt.getController().equals(origin)) continue; T controllerBE = partAt.getControllerTE(); - partAt.setExtraData ( (controllerBE == null ? null : controllerBE.getExtraData())); + partAt.setExtraData((controllerBE == null ? null : controllerBE.getExtraData())); partAt.removeController(true); if (!toDistribute.isEmpty() && partAt != be) { @@ -317,19 +317,19 @@ public class ConnectivityHandler { } } - private static PriorityQueue> makeCreationQueue () { + private static PriorityQueue> makeCreationQueue() { return new PriorityQueue<>((one, two) -> two.getKey() - one.getKey()); } @Nullable - public static T partAt (BlockEntityType type, BlockGetter level, BlockPos pos) { + public static T partAt(BlockEntityType type, BlockGetter level, BlockPos pos) { BlockEntity be = level.getBlockEntity(pos); if (be != null && be.getType() == type) return checked(be); return null; } - public static boolean isConnected (BlockGetter level, BlockPos pos, BlockPos other) { + public static boolean isConnected(BlockGetter level, BlockPos pos, BlockPos other) { T one = checked(level.getBlockEntity(pos)); T two = checked(level.getBlockEntity(other)); if (one == null || two == null) return false; @@ -338,7 +338,7 @@ public class ConnectivityHandler { @Nullable @SuppressWarnings("unchecked") - private static T checked (BlockEntity be) { + private static T checked(BlockEntity be) { if (be instanceof IMultiTileContainer) return (T)be; return null; } @@ -346,15 +346,15 @@ public class ConnectivityHandler { private static class SearchCache { Map> controllerMap; - public SearchCache () { controllerMap = new HashMap<>(); } + public SearchCache() { controllerMap = new HashMap<>(); } - void put (BlockPos pos, T target) { controllerMap.put(pos, Optional.of(target)); } + void put(BlockPos pos, T target) { controllerMap.put(pos, Optional.of(target)); } - void putEmpty (BlockPos pos) { controllerMap.put(pos, Optional.empty()); } + void putEmpty(BlockPos pos) { controllerMap.put(pos, Optional.empty()); } - boolean hasVisited (BlockPos pos) { return controllerMap.containsKey(pos); } + boolean hasVisited(BlockPos pos) { return controllerMap.containsKey(pos); } - Optional getOrCache (BlockEntityType type, BlockGetter level, BlockPos pos) { + Optional getOrCache(BlockEntityType type, BlockGetter level, BlockPos pos) { if (hasVisited(pos)) return controllerMap.get(pos); T partAt = partAt(type, level, pos); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java index 920d78f34..d649dca3a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java @@ -94,7 +94,7 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE frontier = new ArrayList<>(); - frontier.add(te); - formTanks(te.getType(), te.getLevel(), cache, frontier); - } - - private static void formTanks(BlockEntityType type, BlockGetter world, TankSearchCache cache, - List frontier) { - PriorityQueue> creationQueue = makeCreationQueue(); - Set visited = new HashSet<>(); - - int minX = Integer.MAX_VALUE; - int minZ = Integer.MAX_VALUE; - for (FluidTankTileEntity fluidTankTileEntity : frontier) { - BlockPos pos = fluidTankTileEntity.getBlockPos(); - minX = Math.min(pos.getX(), minX); - minZ = Math.min(pos.getZ(), minZ); - } - minX -= FluidTankTileEntity.getMaxSize(); - minZ -= FluidTankTileEntity.getMaxSize(); - - while (!frontier.isEmpty()) { - FluidTankTileEntity tank = frontier.remove(0); - BlockPos tankPos = tank.getBlockPos(); - if (visited.contains(tankPos)) - continue; - - visited.add(tankPos); - - int amount = tryToFormNewTank(tank, cache, true); - if (amount > 1) - creationQueue.add(Pair.of(amount, tank)); - - for (Axis axis : Iterate.axes) { - Direction d = Direction.get(AxisDirection.NEGATIVE, axis); - BlockPos next = tankPos.relative(d); - - if (next.getX() <= minX || next.getZ() <= minZ) - continue; - if (visited.contains(next)) - continue; - FluidTankTileEntity nextTank = tankAt(type, world, next); - if (nextTank == null) - continue; - if (nextTank.isRemoved()) - continue; - frontier.add(nextTank); - } - } - - visited.clear(); - - while (!creationQueue.isEmpty()) { - Pair next = creationQueue.poll(); - FluidTankTileEntity toCreate = next.getValue(); - if (visited.contains(toCreate.getBlockPos())) - continue; - visited.add(toCreate.getBlockPos()); - tryToFormNewTank(toCreate, cache, false); - } - - } - - public static void splitTank(FluidTankTileEntity te) { - splitTankAndInvalidate(te, null, false); - } - - private static int tryToFormNewTank(FluidTankTileEntity te, TankSearchCache cache, boolean simulate) { - int bestWidth = 1; - int bestAmount = -1; - - if (!te.isController()) - return 0; - - for (int w = 1; w <= FluidTankTileEntity.getMaxSize(); w++) { - int amount = tryToFormNewTankOfWidth(te, w, cache, true); - if (amount < bestAmount) - continue; - bestWidth = w; - bestAmount = amount; - } - - if (!simulate) { - if (te.width == bestWidth && te.width * te.width * te.height == bestAmount) - return bestAmount; - - splitTankAndInvalidate(te, cache, false); - te.applyFluidTankSize(bestAmount); - tryToFormNewTankOfWidth(te, bestWidth, cache, simulate); - te.updateConnectivity = false; - te.width = bestWidth; - te.height = bestAmount / bestWidth / bestWidth; - - BlockState state = te.getBlockState(); - if (FluidTankBlock.isTank(state)) { - state = state.setValue(FluidTankBlock.BOTTOM, true); - state = state.setValue(FluidTankBlock.TOP, te.height == 1); - te.getLevel() - .setBlock(te.getBlockPos(), state, 22); - } - - te.setWindows(te.window); - te.onFluidStackChanged(te.tankInventory.getFluid()); - te.setChanged(); - } - - return bestAmount; - } - - private static int tryToFormNewTankOfWidth(FluidTankTileEntity te, int width, TankSearchCache cache, - boolean simulate) { - int amount = 0; - int height = 0; - BlockEntityType type = te.getType(); - Level world = te.getLevel(); - BlockPos origin = te.getBlockPos(); - LazyOptional capability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); - FluidTank teTank = (FluidTank) capability.orElse(null); - FluidStack fluid = capability.map(ifh -> ifh.getFluidInTank(0)) - .orElse(FluidStack.EMPTY); - - Search: - - for (int yOffset = 0; yOffset < FluidTankTileEntity.getMaxHeight(); yOffset++) { - for (int xOffset = 0; xOffset < width; xOffset++) { - for (int zOffset = 0; zOffset < width; zOffset++) { - - BlockPos pos = origin.offset(xOffset, yOffset, zOffset); - Optional tank = cache.getOrCache(type, world, pos); - if (!tank.isPresent()) - break Search; - - FluidTankTileEntity controller = tank.get(); - int otherWidth = controller.width; - if (otherWidth > width) - break Search; - - BlockPos controllerPos = controller.getBlockPos(); - if (!controllerPos.equals(origin)) { - if (controllerPos.getX() < origin.getX()) - break Search; - if (controllerPos.getZ() < origin.getZ()) - break Search; - if (controllerPos.getX() + otherWidth > origin.getX() + width) - break Search; - if (controllerPos.getZ() + otherWidth > origin.getZ() + width) - break Search; - } - - FluidStack otherFluid = controller.getTankInventory() - .getFluid(); - if (!fluid.isEmpty() && !otherFluid.isEmpty() && !fluid.isFluidEqual(otherFluid)) - break Search; - - } - } - - amount += width * width; - height++; - } - - if (simulate) - return amount; - - boolean opaque = false; - - for (int yOffset = 0; yOffset < height; yOffset++) { - for (int xOffset = 0; xOffset < width; xOffset++) { - for (int zOffset = 0; zOffset < width; zOffset++) { - BlockPos pos = origin.offset(xOffset, yOffset, zOffset); - FluidTankTileEntity tank = tankAt(type, world, pos); - if (tank == te) - continue; - - opaque |= !tank.window; - FluidTank tankTank = tank.tankInventory; - FluidStack fluidInTank = tankTank.getFluid(); - if (!fluidInTank.isEmpty()) { - if (teTank.isEmpty() && teTank instanceof CreativeSmartFluidTank) - ((CreativeSmartFluidTank) teTank).setContainedFluid(fluidInTank); - teTank.fill(fluidInTank, FluidAction.EXECUTE); - } - tankTank.setFluid(FluidStack.EMPTY); - - splitTankAndInvalidate(tank, cache, false); - tank.setController(origin); - tank.updateConnectivity = false; - cache.put(pos, te); - - BlockState state = world.getBlockState(pos); - if (!FluidTankBlock.isTank(state)) - continue; - state = state.setValue(FluidTankBlock.BOTTOM, yOffset == 0); - state = state.setValue(FluidTankBlock.TOP, yOffset == height - 1); - world.setBlock(pos, state, 22); - } - } - } - - te.setWindows(!opaque); - - return amount; - } - - private static void splitTankAndInvalidate(FluidTankTileEntity te, @Nullable TankSearchCache cache, - boolean tryReconnect) { - // tryReconnect helps whenever only few tanks have been removed - - te = te.getControllerTE(); - if (te == null) - return; - - int height = te.height; - int width = te.width; - if (width == 1 && height == 1) - return; - - Level world = te.getLevel(); - BlockPos origin = te.getBlockPos(); - List frontier = new ArrayList<>(); - FluidStack toDistribute = te.tankInventory.getFluid() - .copy(); - int maxCapacity = FluidTankTileEntity.getCapacityMultiplier(); - if (!toDistribute.isEmpty() && !te.isRemoved()) - toDistribute.shrink(maxCapacity); - te.applyFluidTankSize(1); - - for (int yOffset = 0; yOffset < height; yOffset++) { - for (int xOffset = 0; xOffset < width; xOffset++) { - for (int zOffset = 0; zOffset < width; zOffset++) { - - BlockPos pos = origin.offset(xOffset, yOffset, zOffset); - FluidTankTileEntity tankAt = tankAt(te.getType(), world, pos); - if (tankAt == null) - continue; - if (!tankAt.getController() - .equals(origin)) - continue; - FluidTankTileEntity controllerTE = tankAt.getControllerTE(); - tankAt.window = controllerTE == null || controllerTE.window; - tankAt.removeController(true); - - if (!toDistribute.isEmpty() && tankAt != te) { - FluidStack copy = toDistribute.copy(); - FluidTank tankInventory = tankAt.tankInventory; - if (tankInventory.isEmpty() && tankInventory instanceof CreativeSmartFluidTank) - ((CreativeSmartFluidTank) tankInventory).setContainedFluid(toDistribute); - else { - int split = Math.min(maxCapacity, toDistribute.getAmount()); - copy.setAmount(split); - toDistribute.shrink(split); - tankInventory.fill(copy, FluidAction.EXECUTE); - } - } - - if (tryReconnect) { - frontier.add(tankAt); - tankAt.updateConnectivity = false; - } - if (cache != null) - cache.put(pos, tankAt); - } - } - } - - te.fluidCapability.invalidate(); - if (tryReconnect) - formTanks(te.getType(), world, cache == null ? new TankSearchCache() : cache, frontier); - } - - private static PriorityQueue> makeCreationQueue() { - return new PriorityQueue<>(new Comparator>() { - @Override - public int compare(Pair o1, Pair o2) { - return o2.getKey() - o1.getKey(); - } - }); - } - - @Nullable - public static FluidTankTileEntity tankAt(BlockEntityType type, BlockGetter world, BlockPos pos) { - BlockEntity te = world.getBlockEntity(pos); - if (te instanceof FluidTankTileEntity && te.getType() == type) - return (FluidTankTileEntity) te; - return null; - } - - @Nullable - public static FluidTankTileEntity anyTankAt(BlockGetter world, BlockPos pos) { - BlockEntity te = world.getBlockEntity(pos); - if (te instanceof FluidTankTileEntity) - return (FluidTankTileEntity) te; - return null; - } - - private static class TankSearchCache { - Map> controllerMap; - - public TankSearchCache() { - controllerMap = new HashMap<>(); - } - - void put(BlockPos pos, FluidTankTileEntity target) { - controllerMap.put(pos, Optional.of(target)); - } - - void putEmpty(BlockPos pos) { - controllerMap.put(pos, Optional.empty()); - } - - boolean hasVisited(BlockPos pos) { - return controllerMap.containsKey(pos); - } - - Optional getOrCache(BlockEntityType type, BlockGetter world, BlockPos pos) { - if (hasVisited(pos)) - return controllerMap.get(pos); - FluidTankTileEntity tankAt = tankAt(type, world, pos); - if (tankAt == null) { - putEmpty(pos); - return Optional.empty(); - } - FluidTankTileEntity controller = tankAt.getControllerTE(); - if (controller == null) { - putEmpty(pos); - return Optional.empty(); - } - put(pos, controller); - return Optional.of(controller); - } - - } - - public static boolean isConnected(BlockGetter world, BlockPos tankPos, BlockPos otherTankPos) { - BlockEntity te1 = world.getBlockEntity(tankPos); - BlockEntity te2 = world.getBlockEntity(otherTankPos); - if (!(te1 instanceof FluidTankTileEntity) || !(te2 instanceof FluidTankTileEntity)) - return false; - return ((FluidTankTileEntity) te1).getController() - .equals(((FluidTankTileEntity) te2).getController()); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java index 43bb3b288..22fb7387e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java @@ -79,7 +79,6 @@ public class FluidTankItem extends BlockItem { FluidTankTileEntity tankAt = ConnectivityHandler.partAt( creative ? AllTileEntities.CREATIVE_FLUID_TANK.get() : AllTileEntities.FLUID_TANK.get(), world, placedOnPos ); - //FluidTankConnectivityHandler.anyTankAt(world, placedOnPos); if (tankAt == null) return; FluidTankTileEntity controllerTE = tankAt.getControllerTE(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java index d4f0d71c3..01973135d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java @@ -7,7 +7,6 @@ import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import com.simibubi.create.Create; import com.simibubi.create.api.connectivity.ConnectivityHandler; import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock.Shape; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; @@ -81,7 +80,6 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI return; if (!isController()) return; - //FluidTankConnectivityHandler.formTanks(this); ConnectivityHandler.formMulti(this); } @@ -148,7 +146,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI for (int xOffset = 0; xOffset < width; xOffset++) { for (int zOffset = 0; zOffset < width; zOffset++) { BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset); - FluidTankTileEntity tankAt = ConnectivityHandler.partAt(getType(), level, pos); //FluidTankConnectivityHandler.anyTankAt(level, pos); + FluidTankTileEntity tankAt = ConnectivityHandler.partAt(getType(), level, pos); if (tankAt == null) continue; level.updateNeighbourForOutputSignal(pos, tankAt.getBlockState() @@ -469,7 +467,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI public void preventConnectivityUpdate() { updateConnectivity = false; } @Override - public void notifyMultiUpdated () { + public void notifyMultiUpdated() { BlockState state = this.getBlockState(); if (FluidTankBlock.isTank(state)) { // safety state = state.setValue(FluidTankBlock.BOTTOM, getController().getY() == getBlockPos().getY()); @@ -482,16 +480,16 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI } @Override - public void setExtraData (@Nullable Object data) { + public void setExtraData(@Nullable Object data) { if (data instanceof Boolean) window = (boolean)data; } @Override @Nullable - public Object getExtraData () { return window; } + public Object getExtraData() { return window; } @Override - public Object modifyExtraData (Object data) { + public Object modifyExtraData(Object data) { if (data instanceof Boolean windows) { windows |= window; return windows; @@ -503,44 +501,44 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI public Direction.Axis getMainConnectionAxis() { return Direction.Axis.Y; } @Override - public int getMaxLength (Direction.Axis longAxis, int width) { + public int getMaxLength(Direction.Axis longAxis, int width) { if (longAxis == Direction.Axis.Y) return getMaxHeight(); return getMaxWidth(); } @Override - public int getMaxWidth () { return MAX_SIZE; } + public int getMaxWidth() { return MAX_SIZE; } @Override - public int getHeight () { return height; } + public int getHeight() { return height; } @Override - public void setHeight (int height) { this.height = height; } + public void setHeight(int height) { this.height = height; } @Override - public int getWidth () { return width; } + public int getWidth() { return width; } @Override - public void setWidth (int width) { this.width = width; } + public void setWidth(int width) { this.width = width; } @Override - public boolean hasFluid () { return true; } + public boolean hasFluid() { return true; } @Override - public int getTankSize (int tank) { return getCapacityMultiplier(); } + public int getTankSize(int tank) { return getCapacityMultiplier(); } @Override - public void setTankSize (int tank, int blocks) { + public void setTankSize(int tank, int blocks) { applyFluidTankSize(blocks); } @Override - public IFluidTank getTank (int tank) { + public IFluidTank getTank(int tank) { return tankInventory; } @Override - public FluidStack getFluid (int tank) { + public FluidStack getFluid(int tank) { return tankInventory.getFluid().copy(); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java index 34bbde3e7..f7cdb74ea 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java @@ -87,7 +87,6 @@ public class ItemVaultBlock extends Block implements IWrenchable, ITE frontier = new ArrayList<>(); - frontier.add(te); - formVaults(te.getType(), te.getLevel(), cache, frontier); - } - - private static void formVaults(BlockEntityType type, BlockGetter world, VaultSearchCache cache, - List frontier) { - PriorityQueue> creationQueue = makeCreationQueue(); - Set visited = new HashSet<>(); - - int minY = Integer.MAX_VALUE; - for (ItemVaultTileEntity fluidTankTileEntity : frontier) { - BlockPos pos = fluidTankTileEntity.getBlockPos(); - minY = Math.min(pos.getY(), minY); - } - - minY -= 3; - - while (!frontier.isEmpty()) { - ItemVaultTileEntity tank = frontier.remove(0); - BlockPos tankPos = tank.getBlockPos(); - if (visited.contains(tankPos)) - continue; - - visited.add(tankPos); - - int amount = tryToFormNewVault(tank, cache, true); - if (amount > 1) - creationQueue.add(Pair.of(amount, tank)); - - for (Axis axis : Iterate.axes) { - Direction d = Direction.fromAxisAndDirection(axis, AxisDirection.NEGATIVE); - BlockPos next = tankPos.relative(d); - - if (next.getY() <= minY) - continue; - if (visited.contains(next)) - continue; - ItemVaultTileEntity nextTank = vaultAt(type, world, next); - if (nextTank == null) - continue; - if (nextTank.isRemoved()) - continue; - frontier.add(nextTank); - } - } - - visited.clear(); - - while (!creationQueue.isEmpty()) { - Pair next = creationQueue.poll(); - ItemVaultTileEntity toCreate = next.getValue(); - if (visited.contains(toCreate.getBlockPos())) - continue; - visited.add(toCreate.getBlockPos()); - tryToFormNewVault(toCreate, cache, false); - } - - } - - public static void splitVault(ItemVaultTileEntity te) { - splitVaultAndInvalidate(te, null, false); - } - - private static int tryToFormNewVault(ItemVaultTileEntity te, VaultSearchCache cache, boolean simulate) { - int bestWidth = 1; - int bestAmount = -1; - - if (!te.isController()) - return 0; - - for (int w = 1; w <= 3; w++) { - int amount = tryToFormNewVaultOfRadius(te, w, cache, true); - if (amount < bestAmount) - continue; - bestWidth = w; - bestAmount = amount; - } - - if (!simulate) { - if (te.radius == bestWidth && te.radius * te.radius * te.length == bestAmount) - return bestAmount; - - splitVaultAndInvalidate(te, cache, false); - tryToFormNewVaultOfRadius(te, bestWidth, cache, simulate); - te.updateConnectivity = false; - te.radius = bestWidth; - te.length = bestAmount / bestWidth / bestWidth; - - BlockState state = te.getBlockState(); - if (ItemVaultBlock.isVault(state)) - te.getLevel() - .setBlock(te.getBlockPos(), state.setValue(ItemVaultBlock.LARGE, te.radius > 2), 22); - - te.itemCapability.invalidate(); - te.setChanged(); - } - - return bestAmount; - } - - private static int tryToFormNewVaultOfRadius(ItemVaultTileEntity te, int width, VaultSearchCache cache, - boolean simulate) { - int amount = 0; - int height = 0; - BlockEntityType type = te.getType(); - Level world = te.getLevel(); - BlockPos origin = te.getBlockPos(); - boolean alongZ = ItemVaultBlock.getVaultBlockAxis(te.getBlockState()) == Axis.Z; - - Search: - - for (int yOffset = 0; yOffset < ItemVaultTileEntity.getMaxLength(width); yOffset++) { - for (int xOffset = 0; xOffset < width; xOffset++) { - for (int zOffset = 0; zOffset < width; zOffset++) { - - BlockPos pos = - alongZ ? origin.offset(xOffset, zOffset, yOffset) : origin.offset(yOffset, xOffset, zOffset); - Optional tank = cache.getOrCache(type, world, pos); - if (!tank.isPresent()) - break Search; - - ItemVaultTileEntity controller = tank.get(); - int otherWidth = controller.radius; - if (otherWidth > width) - break Search; - if (otherWidth == width && controller.length == ItemVaultTileEntity.getMaxLength(width)) - break Search; - if ((ItemVaultBlock.getVaultBlockAxis(controller.getBlockState()) == Axis.Z) != alongZ) - break Search; - - BlockPos controllerPos = controller.getBlockPos(); - if (!controllerPos.equals(origin)) { - if (alongZ && controllerPos.getX() < origin.getX()) - break Search; - if (controllerPos.getY() < origin.getY()) - break Search; - if (!alongZ && controllerPos.getZ() < origin.getZ()) - break Search; - if (alongZ && controllerPos.getX() + otherWidth > origin.getX() + width) - break Search; - if (controllerPos.getY() + otherWidth > origin.getY() + width) - break Search; - if (!alongZ && controllerPos.getZ() + otherWidth > origin.getZ() + width) - break Search; - } - - } - } - - amount += width * width; - height++; - } - - if (simulate) - return amount; - - for (int yOffset = 0; yOffset < height; yOffset++) { - for (int xOffset = 0; xOffset < width; xOffset++) { - for (int zOffset = 0; zOffset < width; zOffset++) { - BlockPos pos = - alongZ ? origin.offset(xOffset, zOffset, yOffset) : origin.offset(yOffset, xOffset, zOffset); - ItemVaultTileEntity tank = vaultAt(type, world, pos); - if (tank == te) - continue; - - splitVaultAndInvalidate(tank, cache, false); - tank.setController(origin); - tank.updateConnectivity = false; - cache.put(pos, te); - - BlockState state = world.getBlockState(pos); - if (!ItemVaultBlock.isVault(state)) - continue; - state = state.setValue(ItemVaultBlock.LARGE, width > 2); - world.setBlock(pos, state, 22); - } - } - } - - return amount; - } - - private static void splitVaultAndInvalidate(ItemVaultTileEntity te, @Nullable VaultSearchCache cache, - boolean tryReconnect) { - // tryReconnect helps whenever only few tanks have been removed - - te = te.getControllerTE(); - if (te == null) - return; - - int height = te.length; - int width = te.radius; - BlockState state = te.getBlockState(); - boolean alongZ = ItemVaultBlock.getVaultBlockAxis(state) == Axis.Z; - if (width == 1 && height == 1) - return; - - Level world = te.getLevel(); - BlockPos origin = te.getBlockPos(); - List frontier = new ArrayList<>(); - - for (int yOffset = 0; yOffset < height; yOffset++) { - for (int xOffset = 0; xOffset < width; xOffset++) { - for (int zOffset = 0; zOffset < width; zOffset++) { - - BlockPos pos = - alongZ ? origin.offset(xOffset, zOffset, yOffset) : origin.offset(yOffset, xOffset, zOffset); - ItemVaultTileEntity tankAt = vaultAt(te.getType(), world, pos); - if (tankAt == null) - continue; - if (!tankAt.getController() - .equals(origin)) - continue; - - tankAt.removeController(true); - - if (tryReconnect) { - frontier.add(tankAt); - tankAt.updateConnectivity = false; - } - if (cache != null) - cache.put(pos, tankAt); - } - } - } - - te.itemCapability.invalidate(); - if (tryReconnect) - formVaults(te.getType(), world, cache == null ? new VaultSearchCache() : cache, frontier); - } - - private static PriorityQueue> makeCreationQueue() { - return new PriorityQueue<>(new Comparator>() { - @Override - public int compare(Pair o1, Pair o2) { - return o2.getKey() - o1.getKey(); - } - }); - } - - @Nullable - public static ItemVaultTileEntity vaultAt(BlockEntityType type, BlockGetter world, BlockPos pos) { - BlockEntity te = world.getBlockEntity(pos); - if (te instanceof ItemVaultTileEntity && te.getType() == type) - return (ItemVaultTileEntity) te; - return null; - } - - private static class VaultSearchCache { - Map> controllerMap; - - public VaultSearchCache() { - controllerMap = new HashMap<>(); - } - - void put(BlockPos pos, ItemVaultTileEntity target) { - controllerMap.put(pos, Optional.of(target)); - } - - void putEmpty(BlockPos pos) { - controllerMap.put(pos, Optional.empty()); - } - - boolean hasVisited(BlockPos pos) { - return controllerMap.containsKey(pos); - } - - Optional getOrCache(BlockEntityType type, BlockGetter world, BlockPos pos) { - if (hasVisited(pos)) - return controllerMap.get(pos); - ItemVaultTileEntity tankAt = vaultAt(type, world, pos); - if (tankAt == null) { - putEmpty(pos); - return Optional.empty(); - } - ItemVaultTileEntity controller = tankAt.getControllerTE(); - if (controller == null) { - putEmpty(pos); - return Optional.empty(); - } - put(pos, controller); - return Optional.of(controller); - } - - } - - public static boolean isConnected(BlockGetter world, BlockPos tankPos, BlockPos otherTankPos) { - BlockEntity te1 = world.getBlockEntity(tankPos); - BlockEntity te2 = world.getBlockEntity(otherTankPos); - if (!(te1 instanceof ItemVaultTileEntity) || !(te2 instanceof ItemVaultTileEntity)) - return false; - return ((ItemVaultTileEntity) te1).getController() - .equals(((ItemVaultTileEntity) te2).getController()); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultItem.java b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultItem.java index 935a3e7d2..fdd76e9bd 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultItem.java @@ -66,7 +66,6 @@ public class ItemVaultItem extends BlockItem { if (!ItemVaultBlock.isVault(placedOnState)) return; ItemVaultTileEntity tankAt = ConnectivityHandler.partAt(AllTileEntities.ITEM_VAULT.get(), world, placedOnPos); - //ItemVaultConnectivityHandler.vaultAt(AllTileEntities.ITEM_VAULT.get(), world, placedOnPos); if (tankAt == null) return; ItemVaultTileEntity controllerTE = tankAt.getControllerTE(); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java index 11fd2ac49..bc774e1e0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java @@ -63,7 +63,6 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo return; if (!isController()) return; - //ItemVaultConnectivityHandler.formVaults(this); ConnectivityHandler.formMulti(this); } @@ -250,7 +249,6 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo BlockPos vaultPos = alongZ ? worldPosition.offset(xOffset, zOffset, yOffset) : worldPosition.offset(yOffset, xOffset, zOffset); ItemVaultTileEntity vaultAt = - //ItemVaultConnectivityHandler.vaultAt(AllTileEntities.ITEM_VAULT.get(), level, vaultPos); ConnectivityHandler.partAt(AllTileEntities.ITEM_VAULT.get(), level, vaultPos); invs[yOffset * radius * radius + xOffset * radius + zOffset] = vaultAt != null ? vaultAt.inventory : new ItemStackHandler(); @@ -270,7 +268,7 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo public void preventConnectivityUpdate() { updateConnectivity = false; } @Override - public void notifyMultiUpdated () { + public void notifyMultiUpdated() { BlockState state = this.getBlockState(); if (ItemVaultBlock.isVault(state)) { // safety level.setBlock(getBlockPos(), state.setValue(ItemVaultBlock.LARGE, radius > 2), 22); @@ -283,28 +281,28 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo public Direction.Axis getMainConnectionAxis() { return getMainAxisOf(this); } @Override - public int getMaxLength (Direction.Axis longAxis, int width) { + public int getMaxLength(Direction.Axis longAxis, int width) { if (longAxis == Direction.Axis.Y) return getMaxWidth(); return getMaxLength(width); } @Override - public int getMaxWidth () { + public int getMaxWidth() { return 3; } @Override - public int getHeight () { return length; } + public int getHeight() { return length; } @Override - public int getWidth () { return radius; } + public int getWidth() { return radius; } @Override - public void setHeight (int height) { this.length = height; } + public void setHeight(int height) { this.length = height; } @Override - public void setWidth (int width) { this.radius = width; } + public void setWidth(int width) { this.radius = width; } @Override - public boolean hasItems () { return true; } + public boolean hasItems() { return true; } } From 964704675381256e0db4674580dee80b18b7077b Mon Sep 17 00:00:00 2001 From: Talrey Date: Fri, 13 May 2022 15:32:05 -0700 Subject: [PATCH 7/7] items and fluids should be sub-interfaces --- .../api/connectivity/ConnectivityHandler.java | 36 ++++++++++--------- .../fluids/tank/FluidTankTileEntity.java | 4 +-- .../block/vault/ItemVaultTileEntity.java | 4 +-- .../tileEntity/IMultiTileContainer.java | 24 ++++++++----- 4 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java index 9dd41c073..fbf9c4dc3 100644 --- a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java +++ b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java @@ -117,7 +117,7 @@ public class ConnectivityHandler { if (beWidth == bestWidth && beWidth*beWidth * be.getHeight() == bestAmount) return bestAmount; splitMultiAndInvalidate(be, cache, false); - if (be.hasFluid()) be.setTankSize(0, bestAmount); + if (be instanceof IMultiTileContainer.Fluid ifluid && ifluid.hasTank()) ifluid.setTankSize(0, bestAmount); tryToFormNewMultiOfWidth(be, bestWidth, cache, false); @@ -140,8 +140,8 @@ public class ConnectivityHandler { // optional fluid handling IFluidTank beTank = null; FluidStack fluid = FluidStack.EMPTY; - if (be.hasFluid()) { - beTank = be.getTank(0); + if (be instanceof IMultiTileContainer.Fluid ifluid && ifluid.hasTank()) { + beTank = ifluid.getTank(0); fluid = beTank.getFluid(); } Direction.Axis axis = be.getMainConnectionAxis(); @@ -182,8 +182,10 @@ public class ConnectivityHandler { if (axis == Direction.Axis.X && conPos.getZ() + otherWidth > origin.getZ() + width) break Search; } } - FluidStack otherFluid = controller.getFluid(0); - if (!fluid.isEmpty() && !otherFluid.isEmpty() && !fluid.isFluidEqual(otherFluid)) break Search; + if (controller instanceof IMultiTileContainer.Fluid ifluidCon && ifluidCon.hasTank()) { + FluidStack otherFluid = ifluidCon.getFluid(0); + if (!fluid.isEmpty() && !otherFluid.isEmpty() && !fluid.isFluidEqual(otherFluid)) break Search; + } } } amount += width * width; @@ -208,15 +210,17 @@ public class ConnectivityHandler { extraData = be.modifyExtraData(extraData); - if (part.hasFluid()) { - IFluidTank tankAt = part.getTank(0); + if (part instanceof IMultiTileContainer.Fluid ifluidPart && ifluidPart.hasTank()) { + IFluidTank tankAt = ifluidPart.getTank(0); FluidStack fluidAt = tankAt.getFluid(); if (!fluidAt.isEmpty()) { // making this generic would be a rather large mess, unfortunately if (beTank != null && fluid.isEmpty() && beTank instanceof CreativeFluidTankTileEntity.CreativeSmartFluidTank) { ((CreativeFluidTankTileEntity.CreativeSmartFluidTank)beTank).setContainedFluid(fluidAt); } - if (be.hasFluid() && beTank != null) beTank.fill(fluidAt, IFluidHandler.FluidAction.EXECUTE); + if (be instanceof IMultiTileContainer.Fluid ifluidBE && ifluidBE.hasTank() && beTank != null) { + beTank.fill(fluidAt, IFluidHandler.FluidAction.EXECUTE); + } } tankAt.drain(tankAt.getCapacity(), IFluidHandler.FluidAction.EXECUTE); } @@ -259,11 +263,11 @@ public class ConnectivityHandler { // fluid handling, if present FluidStack toDistribute = FluidStack.EMPTY; int maxCapacity = 0; - if (be.hasFluid()) { - toDistribute = be.getFluid(0); - maxCapacity = be.getTankSize(0); + if (be instanceof IMultiTileContainer.Fluid ifluidBE && ifluidBE.hasTank()) { + toDistribute = ifluidBE.getFluid(0); + maxCapacity = ifluidBE.getTankSize(0); if (!toDistribute.isEmpty() && !be.isRemoved()) toDistribute.shrink(maxCapacity); - be.setTankSize(0, 1); + ifluidBE.setTankSize(0, 1); } for (int yOffset = 0; yOffset < height; yOffset++) { @@ -284,7 +288,7 @@ public class ConnectivityHandler { if (!toDistribute.isEmpty() && partAt != be) { FluidStack copy = toDistribute.copy(); - IFluidTank tank = partAt.getTank(0); + IFluidTank tank = (partAt instanceof IMultiTileContainer.Fluid ifluidPart ? ifluidPart.getTank(0) : null); // making this generic would be a rather large mess, unfortunately if (tank instanceof CreativeFluidTankTileEntity.CreativeSmartFluidTank creativeTank) { if (creativeTank.isEmpty()) creativeTank.setContainedFluid(toDistribute); @@ -293,7 +297,7 @@ public class ConnectivityHandler { int split = Math.min(maxCapacity, toDistribute.getAmount()); copy.setAmount(split); toDistribute.shrink(split); - tank.fill(copy, IFluidHandler.FluidAction.EXECUTE); + if (tank != null) tank.fill(copy, IFluidHandler.FluidAction.EXECUTE); } } if (tryReconnect) { @@ -306,10 +310,10 @@ public class ConnectivityHandler { } } } - if (be.hasItems()) { + if (be instanceof IMultiTileContainer.Inventory iinv && iinv.hasInventory()) { be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).invalidate(); } - if (be.hasFluid()) { + if (be instanceof IMultiTileContainer.Fluid ifluid && ifluid.hasTank()) { be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY).invalidate(); } if (tryReconnect) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java index 01973135d..b92e7ab30 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java @@ -36,7 +36,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; import net.minecraftforge.fluids.capability.templates.FluidTank; -public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleInformation, IMultiTileContainer { +public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleInformation, IMultiTileContainer.Fluid { private static final int MAX_SIZE = 3; @@ -522,7 +522,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI public void setWidth(int width) { this.width = width; } @Override - public boolean hasFluid() { return true; } + public boolean hasTank() { return true; } @Override public int getTankSize(int tank) { return getCapacityMultiplier(); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java index bc774e1e0..fefba7a4a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java @@ -26,7 +26,7 @@ import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.wrapper.CombinedInvWrapper; -public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileContainer { +public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileContainer.Inventory { protected LazyOptional itemCapability; @@ -304,5 +304,5 @@ public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileCo public void setWidth(int width) { this.radius = width; } @Override - public boolean hasItems() { return true; } + public boolean hasInventory() { return true; } } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/IMultiTileContainer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/IMultiTileContainer.java index 68d3eaa6d..f51bd0e53 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/IMultiTileContainer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/IMultiTileContainer.java @@ -56,14 +56,20 @@ public interface IMultiTileContainer { int getWidth (); void setWidth (int width); - // optional item handling - default boolean hasItems () { return false; } + public interface Inventory extends IMultiTileContainer { + default boolean hasInventory() { return false; } + } - // optional fluid handling - // done here rather than through the Capability to allow greater flexibility - default boolean hasFluid () { return false; } - default int getTankSize (int tank) { return 0; } - default void setTankSize (int tank, int blocks) {} - default IFluidTank getTank (int tank) { return null; } - default FluidStack getFluid (int tank) { return FluidStack.EMPTY; } + public interface Fluid extends IMultiTileContainer { + // done here rather than through the Capability to allow greater flexibility + default boolean hasTank() { return false; } + + default int getTankSize(int tank) { return 0; } + + default void setTankSize(int tank, int blocks) {} + + default IFluidTank getTank(int tank) { return null; } + + default FluidStack getFluid(int tank) { return FluidStack.EMPTY; } + } }