diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java index 916eb54af..25c459399 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java @@ -86,7 +86,7 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { while (!queue.isEmpty()) { // Dont dequeue here, so we can decide not to dequeue a valid entry when // simulating - BlockPos currentPos = queue.first().pos; + BlockPos currentPos = queue.first().pos(); BlockState blockState = world.getBlockState(currentPos); BlockState emptied = blockState; Fluid fluid = Fluids.EMPTY; @@ -262,10 +262,15 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { } private void continueSearch() { - fluid = search(fluid, frontier, visited, (e, d) -> { - queue.enqueue(new BlockPosEntry(e, d)); - validationSet.add(e); - }, false); + try { + fluid = search(fluid, frontier, visited, (e, d) -> { + queue.enqueue(new BlockPosEntry(e, d)); + validationSet.add(e); + }, false); + } catch (ChunkNotLoadedException e) { + tileEntity.sendData(); + visited.clear(); + } Level world = getWorld(); int maxBlocks = maxBlocks(); @@ -273,14 +278,14 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { infinite = true; // Find first block with valid fluid while (true) { - BlockPos first = queue.first().pos; + BlockPos first = queue.first().pos(); if (canPullFluidsFrom(world.getBlockState(first), first) != FluidBlockType.SOURCE) { queue.dequeue(); continue; } break; } - BlockPos firstValid = queue.first().pos; + BlockPos firstValid = queue.first().pos(); frontier.clear(); visited.clear(); queue.clear(); @@ -297,7 +302,13 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { } private void continueValidation() { - search(fluid, validationFrontier, validationVisited, (e, d) -> newValidationSet.add(e), false); + try { + search(fluid, validationFrontier, validationVisited, (e, d) -> newValidationSet.add(e), false); + } catch (ChunkNotLoadedException e) { + validationFrontier.clear(); + setLongValidationTimer(); + return; + } int maxBlocks = maxBlocks(); if (validationVisited.size() > maxBlocks && canDrainInfinitely(fluid)) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java index afdb10379..075f31d80 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java @@ -71,8 +71,15 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { } protected void continueValidation(Fluid fluid) { - search(fluid, infinityCheckFrontier, infinityCheckVisited, - (p, d) -> infinityCheckFrontier.add(new BlockPosEntry(p, d)), true); + try { + search(fluid, infinityCheckFrontier, infinityCheckVisited, + (p, d) -> infinityCheckFrontier.add(new BlockPosEntry(p, d)), true); + } catch (ChunkNotLoadedException e) { + infinityCheckFrontier.clear(); + setLongValidationTimer(); + return; + } + int maxBlocks = maxBlocks(); if (infinityCheckVisited.size() > maxBlocks && maxBlocks != -1 && !fillInfinite()) { @@ -154,7 +161,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { boolean success = false; for (int i = 0; !success && !queue.isEmpty() && i < searchedPerTick; i++) { BlockPosEntry entry = queue.first(); - BlockPos currentPos = entry.pos; + BlockPos currentPos = entry.pos(); if (visited.contains(currentPos)) { queue.dequeue(); @@ -223,7 +230,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { SpaceType nextSpaceType = getAtPos(world, offsetPos, fluid); if (nextSpaceType != SpaceType.BLOCKING) - queue.enqueue(new BlockPosEntry(offsetPos, entry.distance + 1)); + queue.enqueue(new BlockPosEntry(offsetPos, entry.distance() + 1)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java index ccab2acf8..1d2df5e65 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java @@ -14,6 +14,7 @@ import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; @@ -35,23 +36,20 @@ import net.minecraftforge.fluids.FluidStack; public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { - protected static class BlockPosEntry { - public BlockPos pos; - public int distance; - - public BlockPosEntry(BlockPos pos, int distance) { - this.pos = pos; - this.distance = distance; - } + public static record BlockPosEntry(BlockPos pos, int distance) { + }; + + public static class ChunkNotLoadedException extends Exception { + private static final long serialVersionUID = 1L; } - + BoundingBox affectedArea; BlockPos rootPos; boolean infinite; protected boolean counterpartActed; // Search - static final int searchedPerTick = 256; + static final int searchedPerTick = 1024; static final int validationTimerMin = 160; List frontier; Set visited; @@ -143,7 +141,7 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { } protected Fluid search(Fluid fluid, List frontier, Set visited, - BiConsumer add, boolean searchDownward) { + BiConsumer add, boolean searchDownward) throws ChunkNotLoadedException { Level world = getWorld(); int maxBlocks = maxBlocks(); int maxRange = canDrainInfinitely(fluid) ? maxRange() : maxRange() / 2; @@ -158,6 +156,9 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { continue; visited.add(currentPos); + if (!world.isLoaded(currentPos)) + throw new ChunkNotLoadedException(); + FluidState fluidState = world.getFluidState(currentPos); if (fluidState.isEmpty()) continue; @@ -175,6 +176,8 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { continue; BlockPos offsetPos = currentPos.relative(side); + if (!world.isLoaded(offsetPos)) + throw new ChunkNotLoadedException(); if (visited.contains(offsetPos)) continue; if (offsetPos.distSqr(rootPos) > maxRangeSq) @@ -221,6 +224,8 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { @Override public void write(CompoundTag nbt, boolean clientPacket) { + if (infinite) + NBTHelper.putMarker(nbt, "Infinite"); if (rootPos != null) nbt.put("LastPos", NbtUtils.writeBlockPos(rootPos)); if (affectedArea != null) { @@ -234,6 +239,7 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { @Override public void read(CompoundTag nbt, boolean clientPacket) { + infinite = nbt.contains("Infinite"); if (nbt.contains("LastPos")) rootPos = NbtUtils.readBlockPos(nbt.getCompound("LastPos")); if (nbt.contains("AffectedAreaFrom") && nbt.contains("AffectedAreaTo")) diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java index e466e72fd..35a1b105e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java @@ -147,6 +147,8 @@ public class HosePulleyTileEntity extends KineticTileEntity { @Override protected void write(CompoundTag compound, boolean clientPacket) { + if (clientPacket) + offset.forceNextSync(); compound.put("Offset", offset.writeNBT()); compound.put("Tank", internalTank.writeToNBT(new CompoundTag())); super.write(compound, clientPacket);