From 4707f46b253b02767f2796c884507a203624fc9e Mon Sep 17 00:00:00 2001 From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:49:54 -0500 Subject: [PATCH] net/minecraft/world/level/material --- .../level/material/FlowingFluid.java.patch | 137 +++++++++++++++ .../level/material/FluidState.java.patch | 12 +- .../world/level/material/LavaFluid.java.patch | 42 ++--- .../level/material/WaterFluid.java.patch | 20 +-- .../level/material/FlowingFluid.java.patch | 157 ------------------ 5 files changed, 174 insertions(+), 194 deletions(-) create mode 100644 paper-server/patches/sources/net/minecraft/world/level/material/FlowingFluid.java.patch rename paper-server/patches/{unapplied => sources}/net/minecraft/world/level/material/FluidState.java.patch (64%) rename paper-server/patches/{unapplied => sources}/net/minecraft/world/level/material/LavaFluid.java.patch (50%) rename paper-server/patches/{unapplied => sources}/net/minecraft/world/level/material/WaterFluid.java.patch (65%) delete mode 100644 paper-server/patches/unapplied/net/minecraft/world/level/material/FlowingFluid.java.patch diff --git a/paper-server/patches/sources/net/minecraft/world/level/material/FlowingFluid.java.patch b/paper-server/patches/sources/net/minecraft/world/level/material/FlowingFluid.java.patch new file mode 100644 index 0000000000..4ade7f8dfa --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/level/material/FlowingFluid.java.patch @@ -0,0 +1,137 @@ +--- a/net/minecraft/world/level/material/FlowingFluid.java ++++ b/net/minecraft/world/level/material/FlowingFluid.java +@@ -118,6 +_,15 @@ + FluidState newLiquid = this.getNewLiquid(level, blockPos, blockState1); + Fluid type = newLiquid.getType(); + if (fluidState1.canBeReplacedWith(level, blockPos, type, Direction.DOWN) && canHoldSpecificFluid(level, blockPos, blockState1, type)) { ++ // CraftBukkit start ++ org.bukkit.block.Block source = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos); ++ org.bukkit.event.block.BlockFromToEvent event = new org.bukkit.event.block.BlockFromToEvent(source, org.bukkit.block.BlockFace.DOWN); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end + this.spreadTo(level, blockPos, blockState1, Direction.DOWN, newLiquid); + if (this.sourceNeighborCount(level, pos) >= 3) { + this.spreadToSides(level, pos, fluidState, blockState); +@@ -146,7 +_,18 @@ + Direction direction = entry.getKey(); + FluidState fluidState1 = entry.getValue(); + BlockPos blockPos = pos.relative(direction); +- this.spreadTo(level, blockPos, level.getBlockState(blockPos), direction, fluidState1); ++ final BlockState blockStateIfLoaded = level.getBlockStateIfLoaded(blockPos); // Paper - Prevent chunk loading from fluid flowing ++ if (blockStateIfLoaded == null) continue; // Paper - Prevent chunk loading from fluid flowing ++ // CraftBukkit start ++ org.bukkit.block.Block source = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos); ++ org.bukkit.event.block.BlockFromToEvent event = new org.bukkit.event.block.BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(direction)); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end ++ this.spreadTo(level, blockPos, blockStateIfLoaded, direction, fluidState1); // Paper - Prevent chunk loading from fluid flowing + } + } + } +@@ -158,7 +_,8 @@ + + for (Direction direction : Direction.Plane.HORIZONTAL) { + BlockPos blockPos = mutableBlockPos.setWithOffset(pos, direction); +- BlockState blockState = level.getBlockState(blockPos); ++ BlockState blockState = level.getBlockStateIfLoaded(mutableBlockPos); // Paper - Prevent chunk loading from fluid flowing ++ if (blockState == null) continue; // Paper - Prevent chunk loading from fluid flowing + FluidState fluidState = blockState.getFluidState(); + if (fluidState.getType().isSame(this) && canPassThroughWall(direction, level, pos, state, blockPos, blockState)) { + if (fluidState.isSource()) { +@@ -252,13 +_,14 @@ + liquidBlockContainer.placeLiquid(level, pos, blockState, fluidState); + } else { + if (!blockState.isAir()) { +- this.beforeDestroyingBlock(level, pos, blockState); ++ this.beforeDestroyingBlock(level, pos, blockState, pos.relative(direction.getOpposite())); // Paper - Add BlockBreakBlockEvent + } + + level.setBlock(pos, fluidState.createLegacyBlock(), 3); + } + } + ++ protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state, BlockPos source) { beforeDestroyingBlock(world, pos, state); } // Paper - Add BlockBreakBlockEvent + protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state); + + protected int getSlopeDistance(LevelReader level, BlockPos pos, int depth, Direction direction, BlockState state, FlowingFluid.SpreadContext spreadContext) { +@@ -267,7 +_,8 @@ + for (Direction direction1 : Direction.Plane.HORIZONTAL) { + if (direction1 != direction) { + BlockPos blockPos = pos.relative(direction1); +- BlockState blockState = spreadContext.getBlockState(blockPos); ++ BlockState blockState = spreadContext.getBlockStateIfLoaded(blockPos); // Paper - Prevent chunk loading from fluid flowing ++ if (blockState == null) continue; // Paper - Prevent chunk loading from fluid flowing + FluidState fluidState = blockState.getFluidState(); + if (this.canPassThrough(level, this.getFlowing(), pos, state, direction1, blockPos, blockState, fluidState)) { + if (spreadContext.isHole(blockPos)) { +@@ -334,7 +_,8 @@ + + for (Direction direction : Direction.Plane.HORIZONTAL) { + BlockPos blockPos = pos.relative(direction); +- BlockState blockState = level.getBlockState(blockPos); ++ BlockState blockState = level.getBlockStateIfLoaded(blockPos); // Paper - Prevent chunk loading from fluid flowing ++ if (blockState == null) continue; // Paper - Prevent chunk loading from fluid flowing + FluidState fluidState = blockState.getFluidState(); + if (this.canMaybePassThrough(level, pos, state, direction, blockPos, blockState, fluidState)) { + FluidState newLiquid = this.getNewLiquid(level, blockPos, blockState); +@@ -405,10 +_,24 @@ + if (newLiquid.isEmpty()) { + fluidState = newLiquid; + blockState = Blocks.AIR.defaultBlockState(); ++ // CraftBukkit start ++ org.bukkit.event.block.FluidLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFluidLevelChangeEvent(level, pos, blockState); ++ if (event.isCancelled()) { ++ return; ++ } ++ blockState = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getNewData()).getState(); ++ // CraftBukkit end + level.setBlock(pos, blockState, 3); + } else if (!newLiquid.equals(fluidState)) { + fluidState = newLiquid; + blockState = newLiquid.createLegacyBlock(); ++ // CraftBukkit start ++ org.bukkit.event.block.FluidLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFluidLevelChangeEvent(level, pos, blockState); ++ if (event.isCancelled()) { ++ return; ++ } ++ blockState = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getNewData()).getState(); ++ // CraftBukkit end + level.setBlock(pos, blockState, 3); + level.scheduleTick(pos, newLiquid.getType(), spreadDelay); + } +@@ -476,9 +_,26 @@ + public BlockState getBlockState(BlockPos pos) { + return this.getBlockState(pos, this.getCacheKey(pos)); + } ++ // Paper start - Prevent chunk loading from fluid flowing ++ public @javax.annotation.Nullable BlockState getBlockStateIfLoaded(BlockPos pos) { ++ return this.getBlockState(pos, this.getCacheKey(pos), false); ++ } ++ // Paper end - Prevent chunk loading from fluid flowing + + private BlockState getBlockState(BlockPos pos, short cacheKey) { +- return this.stateCache.computeIfAbsent(cacheKey, s -> this.level.getBlockState(pos)); ++ // Paper start - Prevent chunk loading from fluid flowing ++ return getBlockState(pos, cacheKey, true); ++ } ++ private @javax.annotation.Nullable BlockState getBlockState(BlockPos pos, short packed, boolean load) { ++ BlockState blockState = this.stateCache.get(packed); ++ if (blockState == null) { ++ blockState = load ? level.getBlockState(pos) : level.getBlockStateIfLoaded(pos); ++ if (blockState != null) { ++ this.stateCache.put(packed, blockState); ++ } ++ } ++ return blockState; ++ // Paper end - Prevent chunk loading from fluid flowing + } + + public boolean isHole(BlockPos pos) { diff --git a/paper-server/patches/unapplied/net/minecraft/world/level/material/FluidState.java.patch b/paper-server/patches/sources/net/minecraft/world/level/material/FluidState.java.patch similarity index 64% rename from paper-server/patches/unapplied/net/minecraft/world/level/material/FluidState.java.patch rename to paper-server/patches/sources/net/minecraft/world/level/material/FluidState.java.patch index 78b4ee0a64..c37c2e8733 100644 --- a/paper-server/patches/unapplied/net/minecraft/world/level/material/FluidState.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/material/FluidState.java.patch @@ -1,18 +1,18 @@ --- a/net/minecraft/world/level/material/FluidState.java +++ b/net/minecraft/world/level/material/FluidState.java -@@ -26,9 +26,11 @@ +@@ -26,9 +_,11 @@ public static final Codec CODEC = codec(BuiltInRegistries.FLUID.byNameCodec(), Fluid::defaultFluidState).stable(); public static final int AMOUNT_MAX = 9; public static final int AMOUNT_FULL = 8; + protected final boolean isEmpty; // Paper - Perf: moved from isEmpty() - public FluidState(Fluid fluid, Reference2ObjectArrayMap, Comparable> propertyMap, MapCodec codec) { - super(fluid, propertyMap, codec); -+ this.isEmpty = fluid.isEmpty(); // Paper - Perf: moved from isEmpty() + public FluidState(Fluid owner, Reference2ObjectArrayMap, Comparable> values, MapCodec propertiesCodec) { + super(owner, values, propertiesCodec); ++ this.isEmpty = owner.isEmpty(); // Paper - Perf: moved from isEmpty() } public Fluid getType() { -@@ -44,7 +46,7 @@ +@@ -44,7 +_,7 @@ } public boolean isEmpty() { @@ -20,4 +20,4 @@ + return this.isEmpty; // Paper - Perf: moved into constructor } - public float getHeight(BlockGetter world, BlockPos pos) { + public float getHeight(BlockGetter level, BlockPos pos) { diff --git a/paper-server/patches/unapplied/net/minecraft/world/level/material/LavaFluid.java.patch b/paper-server/patches/sources/net/minecraft/world/level/material/LavaFluid.java.patch similarity index 50% rename from paper-server/patches/unapplied/net/minecraft/world/level/material/LavaFluid.java.patch rename to paper-server/patches/sources/net/minecraft/world/level/material/LavaFluid.java.patch index de343949f4..ce90c9af15 100644 --- a/paper-server/patches/unapplied/net/minecraft/world/level/material/LavaFluid.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/material/LavaFluid.java.patch @@ -1,48 +1,48 @@ --- a/net/minecraft/world/level/material/LavaFluid.java +++ b/net/minecraft/world/level/material/LavaFluid.java -@@ -85,6 +85,13 @@ - - if (iblockdata.isAir()) { - if (this.hasFlammableNeighbours(world, blockposition1)) { +@@ -88,6 +_,13 @@ + BlockState blockState = level.getBlockState(blockPos); + if (blockState.isAir()) { + if (this.hasFlammableNeighbours(level, blockPos)) { + // CraftBukkit start - Prevent lava putting something on fire -+ if (world.getBlockState(blockposition1).getBlock() != Blocks.FIRE) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition1, pos).isCancelled()) { ++ if (level.getBlockState(blockPos).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, blockPos, pos).isCancelled()) { + continue; + } + } + // CraftBukkit end - world.setBlockAndUpdate(blockposition1, BaseFireBlock.getState(world, blockposition1)); + level.setBlockAndUpdate(blockPos, BaseFireBlock.getState(level, blockPos)); return; } -@@ -101,6 +108,14 @@ +@@ -103,6 +_,14 @@ } - if (world.isEmptyBlock(blockposition2.above()) && this.isFlammable(world, blockposition2)) { + if (level.isEmptyBlock(blockPos1.above()) && this.isFlammable(level, blockPos1)) { + // CraftBukkit start - Prevent lava putting something on fire -+ BlockPos up = blockposition2.above(); -+ if (world.getBlockState(up).getBlock() != Blocks.FIRE) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, up, pos).isCancelled()) { ++ BlockPos up = blockPos1.above(); ++ if (level.getBlockState(up).getBlock() != Blocks.FIRE) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, up, pos).isCancelled()) { + continue; + } + } + // CraftBukkit end - world.setBlockAndUpdate(blockposition2.above(), BaseFireBlock.getState(world, blockposition2)); + level.setBlockAndUpdate(blockPos1.above(), BaseFireBlock.getState(level, blockPos1)); } } -@@ -196,7 +211,11 @@ - - if (this.is(FluidTags.LAVA) && fluid1.is(FluidTags.WATER)) { - if (state.getBlock() instanceof LiquidBlock) { -- world.setBlock(pos, Blocks.STONE.defaultBlockState(), 3); +@@ -195,7 +_,11 @@ + FluidState fluidState1 = level.getFluidState(pos); + if (this.is(FluidTags.LAVA) && fluidState1.is(FluidTags.WATER)) { + if (blockState.getBlock() instanceof LiquidBlock) { +- level.setBlock(pos, Blocks.STONE.defaultBlockState(), 3); + // CraftBukkit start -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world.getMinecraftWorld(), pos, Blocks.STONE.defaultBlockState(), 3)) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level.getMinecraftWorld(), pos, Blocks.STONE.defaultBlockState(), 3)) { + return; + } + // CraftBukkit end } - this.fizz(world, pos); -@@ -214,7 +233,7 @@ + this.fizz(level, pos); +@@ -213,7 +_,7 @@ @Override protected float getExplosionResistance() { diff --git a/paper-server/patches/unapplied/net/minecraft/world/level/material/WaterFluid.java.patch b/paper-server/patches/sources/net/minecraft/world/level/material/WaterFluid.java.patch similarity index 65% rename from paper-server/patches/unapplied/net/minecraft/world/level/material/WaterFluid.java.patch rename to paper-server/patches/sources/net/minecraft/world/level/material/WaterFluid.java.patch index f615848dea..59826b7446 100644 --- a/paper-server/patches/unapplied/net/minecraft/world/level/material/WaterFluid.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/material/WaterFluid.java.patch @@ -1,21 +1,21 @@ --- a/net/minecraft/world/level/material/WaterFluid.java +++ b/net/minecraft/world/level/material/WaterFluid.java -@@ -81,7 +81,14 @@ - return world.getGameRules().getBoolean(GameRules.RULE_WATER_SOURCE_CONVERSION); +@@ -74,7 +_,13 @@ + protected boolean canConvertToSource(ServerLevel level) { + return level.getGameRules().getBoolean(GameRules.RULE_WATER_SOURCE_CONVERSION); } - +- + // Paper start - Add BlockBreakBlockEvent - @Override -+ protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state, BlockPos source) { ++ @Override ++ protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state, BlockPos source) { + BlockEntity tileentity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null; + Block.dropResources(state, world, pos, tileentity, source); + } + // Paper end - Add BlockBreakBlockEvent -+ @Override - protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state) { - BlockEntity blockEntity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null; - Block.dropResources(state, world, pos, blockEntity); -@@ -119,7 +126,7 @@ + @Override + protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state) { + BlockEntity blockEntity = state.hasBlockEntity() ? level.getBlockEntity(pos) : null; +@@ -113,7 +_,7 @@ @Override protected float getExplosionResistance() { diff --git a/paper-server/patches/unapplied/net/minecraft/world/level/material/FlowingFluid.java.patch b/paper-server/patches/unapplied/net/minecraft/world/level/material/FlowingFluid.java.patch deleted file mode 100644 index cfc052e612..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/world/level/material/FlowingFluid.java.patch +++ /dev/null @@ -1,157 +0,0 @@ ---- a/net/minecraft/world/level/material/FlowingFluid.java -+++ b/net/minecraft/world/level/material/FlowingFluid.java -@@ -31,6 +31,14 @@ - import net.minecraft.world.phys.Vec3; - import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; -+// CraftBukkit start -+import org.bukkit.block.BlockFace; -+import org.bukkit.craftbukkit.block.CraftBlock; -+import org.bukkit.craftbukkit.block.data.CraftBlockData; -+import org.bukkit.craftbukkit.event.CraftEventFactory; -+import org.bukkit.event.block.BlockFromToEvent; -+import org.bukkit.event.block.FluidLevelChangeEvent; -+// CraftBukkit end - - public abstract class FlowingFluid extends Fluid { - -@@ -135,6 +143,15 @@ - Fluid fluidtype = fluid2.getType(); - - if (fluid1.canBeReplacedWith(world, blockposition1, fluidtype, Direction.DOWN) && FlowingFluid.canHoldSpecificFluid(world, blockposition1, iblockdata1, fluidtype)) { -+ // CraftBukkit start -+ org.bukkit.block.Block source = CraftBlock.at(world, fluidPos); -+ BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN); -+ world.getCraftServer().getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ return; -+ } -+ // CraftBukkit end - this.spreadTo(world, blockposition1, iblockdata1, Direction.DOWN, fluid2); - if (this.sourceNeighborCount(world, fluidPos) >= 3) { - this.spreadToSides(world, fluidPos, fluidState, blockState); -@@ -167,8 +184,19 @@ - Direction enumdirection = (Direction) entry.getKey(); - FluidState fluid1 = (FluidState) entry.getValue(); - BlockPos blockposition1 = pos.relative(enumdirection); -+ final BlockState blockStateIfLoaded = world.getBlockStateIfLoaded(blockposition1); // Paper - Prevent chunk loading from fluid flowing -+ if (blockStateIfLoaded == null) continue; // Paper - Prevent chunk loading from fluid flowing - -- this.spreadTo(world, blockposition1, world.getBlockState(blockposition1), enumdirection, fluid1); -+ // CraftBukkit start -+ org.bukkit.block.Block source = CraftBlock.at(world, pos); -+ BlockFromToEvent event = new BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection)); -+ world.getCraftServer().getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ continue; -+ } -+ // CraftBukkit end -+ this.spreadTo(world, blockposition1, blockStateIfLoaded, enumdirection, fluid1); // Paper - Prevent chunk loading from fluid flowing - } - - } -@@ -183,7 +211,8 @@ - while (iterator.hasNext()) { - Direction enumdirection = (Direction) iterator.next(); - BlockPos.MutableBlockPos blockposition_mutableblockposition1 = blockposition_mutableblockposition.setWithOffset(pos, enumdirection); -- BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition1); -+ BlockState iblockdata1 = world.getBlockStateIfLoaded(blockposition_mutableblockposition1); // Paper - Prevent chunk loading from fluid flowing -+ if (iblockdata1 == null) continue; // Paper - Prevent chunk loading from fluid flowing - FluidState fluid = iblockdata1.getFluidState(); - - if (fluid.getType().isSame(this) && FlowingFluid.canPassThroughWall(enumdirection, world, pos, state, blockposition_mutableblockposition1, iblockdata1)) { -@@ -287,7 +316,7 @@ - ifluidcontainer.placeLiquid(world, pos, state, fluidState); - } else { - if (!state.isAir()) { -- this.beforeDestroyingBlock(world, pos, state); -+ this.beforeDestroyingBlock(world, pos, state, pos.relative(direction.getOpposite())); // Paper - Add BlockBreakBlockEvent - } - - world.setBlock(pos, fluidState.createLegacyBlock(), 3); -@@ -295,6 +324,7 @@ - - } - -+ protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state, BlockPos source) { beforeDestroyingBlock(world, pos, state); } // Paper - Add BlockBreakBlockEvent - protected abstract void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state); - - protected int getSlopeDistance(LevelReader world, BlockPos pos, int i, Direction direction, BlockState state, FlowingFluid.SpreadContext spreadCache) { -@@ -306,7 +336,8 @@ - - if (enumdirection1 != direction) { - BlockPos blockposition1 = pos.relative(enumdirection1); -- BlockState iblockdata1 = spreadCache.getBlockState(blockposition1); -+ BlockState iblockdata1 = spreadCache.getBlockStateIfLoaded(blockposition1); // Paper - Prevent chunk loading from fluid flowing -+ if (iblockdata1 == null) continue; // Paper - Prevent chunk loading from fluid flowing - FluidState fluid = iblockdata1.getFluidState(); - - if (this.canPassThrough(world, this.getFlowing(), pos, state, enumdirection1, blockposition1, iblockdata1, fluid)) { -@@ -372,7 +403,8 @@ - while (iterator.hasNext()) { - Direction enumdirection = (Direction) iterator.next(); - BlockPos blockposition1 = pos.relative(enumdirection); -- BlockState iblockdata1 = world.getBlockState(blockposition1); -+ BlockState iblockdata1 = world.getBlockStateIfLoaded(blockposition1); // Paper - Prevent chunk loading from fluid flowing -+ if (iblockdata1 == null) continue; // Paper - Prevent chunk loading from fluid flowing - FluidState fluid = iblockdata1.getFluidState(); - - if (this.canMaybePassThrough(world, pos, state, enumdirection, blockposition1, iblockdata1, fluid)) { -@@ -444,10 +476,24 @@ - if (fluid1.isEmpty()) { - fluidState = fluid1; - blockState = Blocks.AIR.defaultBlockState(); -+ // CraftBukkit start -+ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(world, pos, blockState); -+ if (event.isCancelled()) { -+ return; -+ } -+ blockState = ((CraftBlockData) event.getNewData()).getState(); -+ // CraftBukkit end - world.setBlock(pos, blockState, 3); - } else if (!fluid1.equals(fluidState)) { - fluidState = fluid1; - blockState = fluid1.createLegacyBlock(); -+ // CraftBukkit start -+ FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(world, pos, blockState); -+ if (event.isCancelled()) { -+ return; -+ } -+ blockState = ((CraftBlockData) event.getNewData()).getState(); -+ // CraftBukkit end - world.setBlock(pos, blockState, 3); - world.scheduleTick(pos, fluid1.getType(), i); - } -@@ -524,12 +570,27 @@ - public BlockState getBlockState(BlockPos pos) { - return this.getBlockState(pos, this.getCacheKey(pos)); - } -+ // Paper start - Prevent chunk loading from fluid flowing -+ public @javax.annotation.Nullable BlockState getBlockStateIfLoaded(BlockPos pos) { -+ return this.getBlockState(pos, this.getCacheKey(pos), false); -+ } -+ // Paper end - Prevent chunk loading from fluid flowing - - private BlockState getBlockState(BlockPos pos, short packed) { -- return (BlockState) this.stateCache.computeIfAbsent(packed, (short1) -> { -- return this.level.getBlockState(pos); -- }); -+ // Paper start - Prevent chunk loading from fluid flowing -+ return getBlockState(pos, packed, true); - } -+ private @javax.annotation.Nullable BlockState getBlockState(BlockPos pos, short packed, boolean load) { -+ BlockState blockState = this.stateCache.get(packed); -+ if (blockState == null) { -+ blockState = load ? level.getBlockState(pos) : level.getBlockStateIfLoaded(pos); -+ if (blockState != null) { -+ this.stateCache.put(packed, blockState); -+ } -+ } -+ return blockState; -+ // Paper end - Prevent chunk loading from fluid flowing -+ } - - public boolean isHole(BlockPos pos) { - return this.holeCache.computeIfAbsent(this.getCacheKey(pos), (short0) -> {