From 8fcf959ee3318c5d7d14ad0af051094532a11ab6 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Mon, 6 Mar 2023 14:27:02 -0800 Subject: [PATCH] Fix various World chunk methods - Add thread check for loadChunk - Make isChunkGenerated use the region task queue to schedule to "main" - Don't complete async chunk future if not in the owning thread for the chunk --- patches/server/0004-Threaded-Regions.patch | 42 ++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/patches/server/0004-Threaded-Regions.patch b/patches/server/0004-Threaded-Regions.patch index 6958674..ba78d03 100644 --- a/patches/server/0004-Threaded-Regions.patch +++ b/patches/server/0004-Threaded-Regions.patch @@ -21859,7 +21859,7 @@ index 2ea3778ee1348e5d06b15a2c5dc5d9bd4136dbe3..72a8e27c5ff6063d2e2b3590390b24a1 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index d33476ffa49d7f6388bb227f8a57cf115a74698f..ddb59118551449b4c8855cdeaabedb08af148fff 100644 +index d33476ffa49d7f6388bb227f8a57cf115a74698f..673b5dabaf3b22ea6cd31591027efc0118a44947 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -180,7 +180,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @@ -21871,7 +21871,28 @@ index d33476ffa49d7f6388bb227f8a57cf115a74698f..ddb59118551449b4c8855cdeaabedb08 } @Override -@@ -788,13 +788,14 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -361,10 +361,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { + @Override + public boolean isChunkGenerated(int x, int z) { + // Paper start - Fix this method +- if (!Bukkit.isPrimaryThread()) { ++ if (!io.papermc.paper.util.TickThread.isTickThreadFor(this.getHandle(), x, z)) { // Folia - region threading + return java.util.concurrent.CompletableFuture.supplyAsync(() -> { + return CraftWorld.this.isChunkGenerated(x, z); +- }, world.getChunkSource().mainThreadProcessor).join(); ++ }, (run) -> { io.papermc.paper.threadedregions.RegionisedServer.getInstance().taskQueue.queueChunkTask(this.getHandle(), x, z, run);}).join(); // Folia - region threading + } + ChunkAccess chunk = world.getChunkSource().getChunkAtImmediately(x, z); + if (chunk == null) { +@@ -530,6 +530,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { + + @Override + public boolean loadChunk(int x, int z, boolean generate) { ++ io.papermc.paper.util.TickThread.ensureTickThread(this.getHandle(), x, z, "May not sync load chunks asynchronously"); // Folia - region threading + org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot + warnUnsafeChunk("loading a faraway chunk", x, z); // Paper + // Paper start - Optimize this method +@@ -788,13 +789,14 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) { @@ -21891,7 +21912,7 @@ index d33476ffa49d7f6388bb227f8a57cf115a74698f..ddb59118551449b4c8855cdeaabedb08 BlockPos position = ((CraftBlockState) blockstate).getPosition(); net.minecraft.world.level.block.state.BlockState oldBlock = this.world.getBlockState(position); int flag = ((CraftBlockState) blockstate).getFlag(); -@@ -802,10 +803,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -802,10 +804,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { net.minecraft.world.level.block.state.BlockState newBlock = this.world.getBlockState(position); this.world.notifyAndUpdatePhysics(position, null, oldBlock, newBlock, newBlock, flag, 512); } @@ -21904,7 +21925,7 @@ index d33476ffa49d7f6388bb227f8a57cf115a74698f..ddb59118551449b4c8855cdeaabedb08 return false; } } -@@ -878,7 +879,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -878,7 +880,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public long getGameTime() { @@ -21913,7 +21934,7 @@ index d33476ffa49d7f6388bb227f8a57cf115a74698f..ddb59118551449b4c8855cdeaabedb08 } @Override -@@ -1853,7 +1854,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1853,7 +1855,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { if (!(entity instanceof CraftEntity craftEntity) || entity.getWorld() != this || sound == null || category == null) return; ClientboundSoundEntityPacket packet = new ClientboundSoundEntityPacket(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(CraftSound.getSoundEffect(sound)), net.minecraft.sounds.SoundSource.valueOf(category.name()), craftEntity.getHandle(), volume, pitch, this.getHandle().getRandom().nextLong()); @@ -21922,7 +21943,16 @@ index d33476ffa49d7f6388bb227f8a57cf115a74698f..ddb59118551449b4c8855cdeaabedb08 if (entityTracker != null) { entityTracker.broadcastAndSend(packet); } -@@ -2356,7 +2357,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2339,7 +2341,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { + // Paper start + public java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { + warnUnsafeChunk("getting a faraway chunk async", x, z); // Paper +- if (Bukkit.isPrimaryThread()) { ++ if (io.papermc.paper.util.TickThread.isTickThreadFor(this.getHandle(), x, z)) { // Folia - region threading + net.minecraft.world.level.chunk.LevelChunk immediate = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); + if (immediate != null) { + return java.util.concurrent.CompletableFuture.completedFuture(immediate.getBukkitChunk()); +@@ -2356,7 +2358,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { java.util.concurrent.CompletableFuture ret = new java.util.concurrent.CompletableFuture<>(); io.papermc.paper.chunk.system.ChunkSystem.scheduleChunkLoad(this.getHandle(), x, z, gen, ChunkStatus.FULL, true, priority, (c) -> {