Improve spawn loading and debug output for waiting on a chunk (#2595)

Spawn loading has been changed to use getChunkAt calls to manually
load chunks since watchdog can watch these calls and so we guard
against plugins/players changing the radius of a spawn while it's
loading

Debug output has been improved to note the status of the currently
waiting chunk
This commit is contained in:
Spottedleaf 2019-09-29 18:23:09 -07:00
parent fe0c5d9dc6
commit b0601574e0
3 changed files with 55 additions and 23 deletions

View File

@ -1901,7 +1901,7 @@ index 0000000000..1dfa8abfd8
+}
diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java
new file mode 100644
index 0000000000..1d69715e26
index 0000000000..59d73bfad7
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java
@@ -0,0 +0,0 @@
@ -1992,12 +1992,24 @@ index 0000000000..1d69715e26
+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk wait task info below: ");
+
+ for (final ChunkInfo chunkInfo : WAITING_CHUNKS) {
+ final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ));
+ final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ));
+ final long key = IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ);
+ final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(key);
+ final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(key);
+
+ PaperFileIOThread.LOGGER.log(Level.ERROR, chunkInfo.chunkX + "," + chunkInfo.chunkZ + " in '" + chunkInfo.world.getWorld().getName() + ":");
+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Load Task - " + (loadTask == null ? "none" : loadTask.toString()));
+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Save Task - " + (saveTask == null ? "none" : saveTask.toString()));
+ // log current status of chunk to indicate whether we're waiting on generation or loading
+ net.minecraft.server.PlayerChunk chunkHolder = chunkInfo.world.getChunkProvider().playerChunkMap.getVisibleChunk(key);
+
+ if (chunkHolder == null) {
+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk Holder - null");
+ } else {
+ IChunkAccess chunk = chunkHolder.getAvailableChunkNow();
+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk Holder - non-null");
+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getChunkStatus().toString()));
+ }
+
+ }
+ }
+ }
@ -2897,7 +2909,7 @@ index 23d1935dd5..14f8b61042 100644
+ }
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index ccf359dff1..a256f043ad 100644
index 5238a1a7ca..0b00581382 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@ -2947,7 +2959,7 @@ index af934ef8bc..34d0ab0d5e 100644
completablefuture = (CompletableFuture) this.statusFutures.get(i);
if (completablefuture != null) {
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index fd0d2b6e67..9daf64bad4 100644
index fd0d2b6e67..31d106f951 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -2977,6 +2989,15 @@ index fd0d2b6e67..9daf64bad4 100644
this.setViewDistance(i);
}
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
@Nullable
- protected PlayerChunk getVisibleChunk(long i) {
+ public PlayerChunk getVisibleChunk(long i) { // Paper - protected -> public
return (PlayerChunk) this.visibleChunks.get(i);
}
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@Override
public void close() throws IOException {

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Configurable Keep Spawn Loaded range per world
This lets you disable it for some worlds and lower it for others.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index d8bb13693..de11a91af 100644
index d8bb13693d..de11a91af6 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
@ -21,7 +21,7 @@ index d8bb13693..de11a91af 100644
+ }
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index c70ab3caf..c58f6f50d 100644
index ee02001700..a6f112bd0f 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@ -30,9 +30,10 @@ index c70ab3caf..c58f6f50d 100644
+ // Paper start - configurable spawn reason
+ int radiusBlocks = worldserver.paperConfig.keepLoadedRange;
+ worldloadlistener.setChunkRadius(radiusBlocks / 16);
+ int totalChunks = ((radiusBlocks / 16) * 2 + 1);
+ int radiusChunks = radiusBlocks / 16 + ((radiusBlocks & 15) != 0 ? 1 : 0);
+ int totalChunks = ((radiusChunks) * 2 + 1);
+ totalChunks *= totalChunks;
+ worldloadlistener.setChunkRadius(radiusBlocks / 16);
+ // Paper end
+
MinecraftServer.LOGGER.info("Preparing start region for dimension '{}'/{}", worldserver.getWorldData().getName(), DimensionManager.a(worldserver.worldProvider.getDimensionManager().getType())); // CraftBukkit
@ -43,25 +44,35 @@ index c70ab3caf..c58f6f50d 100644
chunkproviderserver.getLightEngine().a(500);
this.nextTick = SystemUtils.getMonotonicMillis();
- chunkproviderserver.addTicket(TicketType.START, new ChunkCoordIntPair(blockposition), 11, Unit.INSTANCE);
-
- while (chunkproviderserver.b() != 441) {
- // CraftBukkit start
- // this.nextTick = SystemUtils.getMonotonicMillis() + 10L;
- this.executeModerately();
- // CraftBukkit end
+ // Paper start - Configurable spawn radius
+ if (worldserver.keepSpawnInMemory) {
+ worldserver.addTicketsForSpawn(radiusBlocks, blockposition);
+
+ // we use a getChunk loop since we don't need to worry about what some plugin does to keepSpawnInMemory
+ // or the spawn radius while we are loading
+ // just keep in mind too that executeModerately will handle player network queue (i.e commands)
+ int centerX = blockposition.getX() >> 4;
+ int centerZ = blockposition.getZ() >> 4;
+ radiusChunks += 2; // we need to load radius +2 to get the chunks in ticking level
+ for (int xoff = -radiusChunks; xoff <= radiusChunks; ++xoff) {
+ for (int zoff = -radiusChunks; zoff <= radiusChunks; ++zoff) {
+ worldserver.getChunkAt(centerX + xoff, centerZ + zoff);
+ }
+ }
- while (chunkproviderserver.b() != 441) {
+ while (worldserver.keepSpawnInMemory && chunkproviderserver.b() != totalChunks) {
+ // Paper end
// CraftBukkit start
// this.nextTick = SystemUtils.getMonotonicMillis() + 10L;
this.executeModerately();
// CraftBukkit end
}
+ // Paper end
+ LOGGER.info("Loaded " + chunkproviderserver.b() + " spawn chunks for world " + worldserver.getWorldData().getName()); // Paper
// CraftBukkit start
// this.nextTick = SystemUtils.getMonotonicMillis() + 10L;
diff --git a/src/main/java/net/minecraft/server/WorldLoadListener.java b/src/main/java/net/minecraft/server/WorldLoadListener.java
index d6762d385..7b6f5b2da 100644
index d6762d3853..7b6f5b2da0 100644
--- a/src/main/java/net/minecraft/server/WorldLoadListener.java
+++ b/src/main/java/net/minecraft/server/WorldLoadListener.java
@@ -0,0 +0,0 @@ public interface WorldLoadListener {
@ -72,7 +83,7 @@ index d6762d385..7b6f5b2da 100644
+ void setChunkRadius(int radius); // Paper - allow changing chunk radius
}
diff --git a/src/main/java/net/minecraft/server/WorldLoadListenerLogger.java b/src/main/java/net/minecraft/server/WorldLoadListenerLogger.java
index 3868572ae..ae77805f7 100644
index 3868572aed..ae77805f71 100644
--- a/src/main/java/net/minecraft/server/WorldLoadListenerLogger.java
+++ b/src/main/java/net/minecraft/server/WorldLoadListenerLogger.java
@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
@ -103,7 +114,7 @@ index 3868572ae..ae77805f7 100644
@Override
public void a(ChunkCoordIntPair chunkcoordintpair) {
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 0f8f54d8e..8a3124fed 100644
index 0f8f54d8e9..8a3124fed4 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World {
@ -196,7 +207,7 @@ index 0f8f54d8e..8a3124fed 100644
public LongSet getForceLoadedChunks() {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 38939ce81..0c31c349a 100644
index 38939ce81e..0c31c349ab 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -0,0 +0,0 @@ public class CraftWorld implements World {

View File

@ -62,7 +62,7 @@ index 02dfd91c5e..8689e0f9f0 100644
public void close() throws IOException {
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 098b3e5355..7e49d21625 100644
index a6f112bd0f..5238a1a7ca 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas