aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0385-Configurable-Keep-Spawn-Loaded-range-per-world.patch
diff options
context:
space:
mode:
Diffstat (limited to 'Spigot-Server-Patches/0385-Configurable-Keep-Spawn-Loaded-range-per-world.patch')
-rw-r--r--Spigot-Server-Patches/0385-Configurable-Keep-Spawn-Loaded-range-per-world.patch230
1 files changed, 230 insertions, 0 deletions
diff --git a/Spigot-Server-Patches/0385-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/Spigot-Server-Patches/0385-Configurable-Keep-Spawn-Loaded-range-per-world.patch
new file mode 100644
index 0000000000..088374345e
--- /dev/null
+++ b/Spigot-Server-Patches/0385-Configurable-Keep-Spawn-Loaded-range-per-world.patch
@@ -0,0 +1,230 @@
+From b4155a3581c39d61d4eab95e5a6103d77924fe37 Mon Sep 17 00:00:00 2001
+From: Aikar <[email protected]>
+Date: Sat, 13 Sep 2014 23:14:43 -0400
+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
+--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+@@ -483,4 +483,10 @@ public class PaperWorldConfig {
+ break;
+ }
+ }
++
++ public short keepLoadedRange;
++ private void keepLoadedRange() {
++ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
++ log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16));
++ }
+ }
+diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
+index c70ab3caf..c58f6f50d 100644
+--- a/src/main/java/net/minecraft/server/MinecraftServer.java
++++ b/src/main/java/net/minecraft/server/MinecraftServer.java
+@@ -577,6 +577,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
+ this.forceTicks = true;
+ // CraftBukkit end
+
++ // Paper start - configurable spawn reason
++ int radiusBlocks = worldserver.paperConfig.keepLoadedRange;
++ worldloadlistener.setChunkRadius(radiusBlocks / 16);
++ int totalChunks = ((radiusBlocks / 16) * 2 + 1);
++ totalChunks *= totalChunks;
++ // Paper end
++
+ MinecraftServer.LOGGER.info("Preparing start region for dimension '{}'/{}", worldserver.getWorldData().getName(), DimensionManager.a(worldserver.worldProvider.getDimensionManager().getType())); // CraftBukkit
+ BlockPosition blockposition = worldserver.getSpawn();
+
+@@ -585,14 +592,19 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
+
+ chunkproviderserver.getLightEngine().a(500);
+ this.nextTick = SystemUtils.getMonotonicMillis();
+- chunkproviderserver.addTicket(TicketType.START, new ChunkCoordIntPair(blockposition), 11, Unit.INSTANCE);
++ // Paper start - Configurable spawn radius
++ if (worldserver.keepSpawnInMemory) {
++ worldserver.addTicketsForSpawn(radiusBlocks, blockposition);
++ }
+
+- while (chunkproviderserver.b() != 441) {
++ while (worldserver.keepSpawnInMemory && chunkproviderserver.b() != totalChunks) {
++ // Paper end
+ // CraftBukkit start
+ // this.nextTick = SystemUtils.getMonotonicMillis() + 10L;
+ this.executeModerately();
+ // CraftBukkit 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
+--- a/src/main/java/net/minecraft/server/WorldLoadListener.java
++++ b/src/main/java/net/minecraft/server/WorldLoadListener.java
+@@ -9,4 +9,6 @@ public interface WorldLoadListener {
+ void a(ChunkCoordIntPair chunkcoordintpair, @Nullable ChunkStatus chunkstatus);
+
+ void b();
++
++ 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
+--- a/src/main/java/net/minecraft/server/WorldLoadListenerLogger.java
++++ b/src/main/java/net/minecraft/server/WorldLoadListenerLogger.java
+@@ -7,16 +7,24 @@ import org.apache.logging.log4j.Logger;
+ public class WorldLoadListenerLogger implements WorldLoadListener {
+
+ private static final Logger LOGGER = LogManager.getLogger();
+- private final int b;
++ private int b; // Paper - remove final
+ private int c;
+ private long d;
+ private long e = Long.MAX_VALUE;
+
+ public WorldLoadListenerLogger(int i) {
+- int j = i * 2 + 1;
++ // Paper start - Allow changing radius later for configurable spawn patch
++ this.setChunkRadius(i); // Move to method
++ }
++
++ @Override
++ public void setChunkRadius(int radius) {
++ // Paper - copied from above
++ int j = radius * 2 + 1;
+
+ this.b = j * j;
+ }
++ // Paper end
+
+ @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
+--- a/src/main/java/net/minecraft/server/WorldServer.java
++++ b/src/main/java/net/minecraft/server/WorldServer.java
+@@ -1525,13 +1525,85 @@ public class WorldServer extends World {
+ return ((PersistentIdCounts) this.getMinecraftServer().getWorldServer(DimensionManager.OVERWORLD).getWorldPersistentData().a(PersistentIdCounts::new, "idcounts")).a();
+ }
+
++ // Paper start - helper function for configurable spawn radius
++ public void addTicketsForSpawn(int radiusInBlocks, BlockPosition spawn) {
++ // In order to respect vanilla behavior, which is ensuring everything but the spawn border can tick, we add tickets
++ // with level 31 for the non-border spawn chunks
++ ChunkProviderServer chunkproviderserver = this.getChunkProvider();
++ int tickRadius = radiusInBlocks - 16;
++
++ // add ticking chunks
++ for (int x = -tickRadius; x <= tickRadius; x += 16) {
++ for (int z = -tickRadius; z <= tickRadius; z += 16) {
++ // radius of 2 will have the current chunk be level 31
++ chunkproviderserver.addTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, z)), 2, Unit.INSTANCE);
++ }
++ }
++
++ // add border chunks
++
++ // add border along x axis (including corner chunks)
++ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) {
++ // top
++ chunkproviderserver.addTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32
++ // bottom
++ chunkproviderserver.addTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32
++ }
++
++ // add border along z axis (excluding corner chunks)
++ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) {
++ // right
++ chunkproviderserver.addTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32
++ // left
++ chunkproviderserver.addTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32
++ }
++ }
++ public void removeTicketsForSpawn(int radiusInBlocks, BlockPosition spawn) {
++ // In order to respect vanilla behavior, which is ensuring everything but the spawn border can tick, we added tickets
++ // with level 31 for the non-border spawn chunks
++ ChunkProviderServer chunkproviderserver = this.getChunkProvider();
++ int tickRadius = radiusInBlocks - 16;
++
++ // remove ticking chunks
++ for (int x = -tickRadius; x <= tickRadius; x += 16) {
++ for (int z = -tickRadius; z <= tickRadius; z += 16) {
++ // radius of 2 will have the current chunk be level 31
++ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, z)), 2, Unit.INSTANCE);
++ }
++ }
++
++ // remove border chunks
++
++ // remove border along x axis (including corner chunks)
++ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) {
++ // top
++ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32
++ // bottom
++ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32
++ }
++
++ // remove border along z axis (excluding corner chunks)
++ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) {
++ // right
++ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32
++ // left
++ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32
++ }
++ }
++ // Paper end
++
+ @Override
+ public void a_(BlockPosition blockposition) {
+- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.b(), 0, this.worldData.d()));
++ // Paper - configurable spawn radius
++ BlockPosition prevSpawn = this.getSpawn();
+
+ super.a_(blockposition);
+- this.getChunkProvider().removeTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE);
+- this.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(blockposition), 11, Unit.INSTANCE);
++ if (this.keepSpawnInMemory) {
++ // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add
++ this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn);
++ this.addTicketsForSpawn(this.paperConfig.keepLoadedRange, blockposition);
++ }
++ // Paper end
+ }
+
+ 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
+--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+@@ -1853,15 +1853,21 @@ public class CraftWorld implements World {
+
+ @Override
+ public void setKeepSpawnInMemory(boolean keepLoaded) {
++ // Paper start - Configurable spawn radius
++ if (keepLoaded == world.keepSpawnInMemory) {
++ // do nothing, nothing has changed
++ return;
++ }
+ world.keepSpawnInMemory = keepLoaded;
+ // Grab the worlds spawn chunk
+- BlockPosition chunkcoordinates = this.world.getSpawn();
++ BlockPosition prevSpawn = this.world.getSpawn();
+ if (keepLoaded) {
+- world.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE);
++ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn);
+ } else {
+- // TODO: doesn't work well if spawn changed....
+- world.getChunkProvider().removeTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE);
++ // TODO: doesn't work well if spawn changed.... // paper - resolved
++ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn);
+ }
++ // Paper end
+ }
+
+ @Override
+--
+2.23.0
+