3
0
Mirror von https://github.com/PaperMC/Paper.git synchronisiert 2024-12-16 19:40:07 +01:00
Paper/Spigot-Server-Patches/0373-Configurable-Keep-Spawn-Loaded-range-per-world.patch

231 Zeilen
12 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
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 572679e4d1ca0d84a08a5c48542fa40d426461e5..071e5e7f729d6c3ffb70506e7ef32eebee1e9118 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -481,4 +481,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 45882ee30f52067909d55bca9202df66a9a48677..0ee1d8e4869bfd0ccba21a227e115a36ff027984 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -586,6 +586,14 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
this.forceTicks = true;
// CraftBukkit end
+ // Paper start - configurable spawn reason
+ int radiusBlocks = worldserver.paperConfig.keepLoadedRange;
+ 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
BlockPosition blockposition = worldserver.getSpawn();
@@ -594,14 +602,12 @@ 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);
-
- 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);
}
+ // 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 d6762d3853b55b639047f455351150a1cbc9399a..7b6f5b2da0a76661a0e047ee7002aa07cdd4a8b1 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 3868572aed50c8bffd93727a139a3fbb8dc19688..ae77805f71c6c574d92f39c51b1e48f2138e9ab6 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 081df240f3066008e7aebee92c6b78487ecda377..ce506e0e1293343ce5f9b6fbb71ef593abaf515b 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1596,13 +1596,89 @@ 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
+ }
+
+ MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> {
+ getChunkProvider().getChunkAtMainThread(pair.x, pair.z);
+ });
+ }
+ 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 5ea7b0b25ae837645f690443d674ce7eb48c1692..8f8c18c5a4f483acee0d61a8007577ac8193bef9 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1932,15 +1932,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