From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Mon, 17 Apr 2023 19:47:57 -0700 Subject: [PATCH] Prevent block updates in non-loaded or non-owned chunks This is to prevent block physics from tripping thread checks by far exceeding the bounds of the current region. While this does add explicit block update suppression techniques, it's better than the server crashing. diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 2c0ce270c947c7fc1d7e0163a43467129a65f999..38ff839aa25fa2b7397f6fc6e3eadda7ae600d48 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -1762,7 +1762,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { Direction enumdirection = (Direction) iterator.next(); BlockPos blockposition1 = pos.relative(enumdirection); - if (this.hasChunkAt(blockposition1)) { + if (io.papermc.paper.util.TickThread.isTickThreadFor((ServerLevel)this, blockposition1) && this.hasChunkAt(blockposition1)) { // Folia - block updates in unloaded chunks BlockState iblockdata = this.getBlockState(blockposition1); if (iblockdata.is(Blocks.COMPARATOR)) { diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java index 57e542d5c8b887acecedf76c08c8d4379d712c0f..9c0ad01eae1e0d5044669f561587a69b6ca8e237 100644 --- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java @@ -134,9 +134,9 @@ public class DetectorRailBlock extends BaseRailBlock { while (iterator.hasNext()) { BlockPos blockposition1 = (BlockPos) iterator.next(); - BlockState iblockdata1 = world.getBlockState(blockposition1); + BlockState iblockdata1 = !io.papermc.paper.util.TickThread.isTickThreadFor((ServerLevel)world, blockposition1) ? null : world.getBlockStateIfLoaded(blockposition1); // Folia - block updates in unloaded chunks - world.neighborChanged(iblockdata1, blockposition1, iblockdata1.getBlock(), pos, false); + if (iblockdata1 != null) world.neighborChanged(iblockdata1, blockposition1, iblockdata1.getBlock(), pos, false); // Folia - block updates in unloaded chunks } } diff --git a/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java b/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java index b84c48902ef24fdae17578a304e6c93dc20c5dce..218c1954a7922c9e6bf6f34f9497f89ce1207eac 100644 --- a/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java +++ b/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java @@ -104,9 +104,9 @@ public class PoweredRailBlock extends BaseRailBlock { } protected boolean isSameRailWithPower(Level world, BlockPos pos, boolean flag, int distance, RailShape shape) { - BlockState iblockdata = world.getBlockState(pos); + BlockState iblockdata = !io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)world, pos) ? null : world.getBlockStateIfLoaded(pos); // Folia - block updates in unloaded chunks - if (!iblockdata.is((Block) this)) { + if (iblockdata == null || !iblockdata.is((Block) this)) { // Folia - block updates in unloaded chunks return false; } else { RailShape blockpropertytrackposition1 = (RailShape) iblockdata.getValue(PoweredRailBlock.SHAPE); diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java index 7f33db05284a957690eac6eb6f5b3b05586727bb..cdf9434635e6d3d15e003f1f6e6a3be7df3f5b04 100644 --- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java @@ -200,8 +200,9 @@ public class RedStoneWireBlock extends Block { while (iterator.hasNext()) { Direction enumdirection = (Direction) iterator.next(); RedstoneSide blockpropertyredstoneside = (RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection)); + BlockState currState; blockposition_mutableblockposition.setWithOffset(pos, enumdirection); // Folia - block updates in unloaded chunks - if (blockpropertyredstoneside != RedstoneSide.NONE && !world.getBlockState(blockposition_mutableblockposition.setWithOffset(pos, enumdirection)).is((Block) this)) { + if (blockpropertyredstoneside != RedstoneSide.NONE && (currState = (world instanceof net.minecraft.server.level.ServerLevel serverLevel && !io.papermc.paper.util.TickThread.isTickThreadFor(serverLevel, pos) ? null : world.getBlockStateIfLoaded(blockposition_mutableblockposition))) != null && !currState.is((Block) this)) { // Folia - block updates in unloaded chunks blockposition_mutableblockposition.move(Direction.DOWN); BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition); diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java index 67be58de9f684e440b62541365c079cfffe30e51..a6bc5c5053f1fce822166d0cd1ea67dc490dc0af 100644 --- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java +++ b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java @@ -119,7 +119,8 @@ public class CollectingNeighborUpdater implements NeighborUpdater { @Override public boolean runNext(Level world) { BlockPos blockPos = this.sourcePos.relative(NeighborUpdater.UPDATE_ORDER[this.idx++]); - BlockState blockState = world.getBlockState(blockPos); + BlockState blockState = !io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)world, blockPos) ? null : world.getBlockStateIfLoaded(blockPos); // Folia - block updates in unloaded chunks + if (blockState != null) { // Folia - block updates in unloaded chunks // Paper start - Call BlockPhysicsEvent try { org.bukkit.event.block.BlockPhysicsEvent event = new org.bukkit.event.block.BlockPhysicsEvent( @@ -134,6 +135,7 @@ public class CollectingNeighborUpdater implements NeighborUpdater { world.lastPhysicsProblem = blockPos; } // Paper end - Call BlockPhysicsEvent + } // Folia - block updates in unloaded chunks if (this.idx < NeighborUpdater.UPDATE_ORDER.length && NeighborUpdater.UPDATE_ORDER[this.idx] == this.skipDirection) { this.idx++; } @@ -150,7 +152,9 @@ public class CollectingNeighborUpdater implements NeighborUpdater { implements CollectingNeighborUpdater.NeighborUpdates { @Override public boolean runNext(Level world) { + if (io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)world, this.pos) && world.getChunkIfLoaded(this.pos) != null) { // Folia - block updates in unloaded chunks NeighborUpdater.executeShapeUpdate(world, this.direction, this.state, this.pos, this.neighborPos, this.updateFlags, this.updateLimit); + } // Folia - block updates in unloaded chunks return false; } } @@ -158,8 +162,8 @@ public class CollectingNeighborUpdater implements NeighborUpdater { static record SimpleNeighborUpdate(BlockPos pos, Block block, BlockPos neighborPos) implements CollectingNeighborUpdater.NeighborUpdates { @Override public boolean runNext(Level world) { - BlockState blockState = world.getBlockState(this.pos); - NeighborUpdater.executeUpdate(world, blockState, this.pos, this.block, this.neighborPos, false); + BlockState blockState = !io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)world, this.pos) ? null : world.getBlockStateIfLoaded(this.pos); // Folia - block updates in unloaded chunks + if (blockState != null) NeighborUpdater.executeUpdate(world, blockState, this.pos, this.block, this.neighborPos, false); // Folia - block updates in unloaded chunks return false; } }