diff options
Diffstat (limited to 'patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch')
-rw-r--r-- | patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch new file mode 100644 index 0000000000..f0e25d5b10 --- /dev/null +++ b/patches/server/0329-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -0,0 +1,252 @@ +From 0000000000000000000000000000000000000000 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 eb44aef0aecf65f5c1b19f42bf85a3a263965a7c..5589ee42959e3665dd5df9049fe108b6f6629608 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -56,6 +56,12 @@ public class PaperWorldConfig { + } + } + ++ 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)); ++ } ++ + private boolean getBoolean(String path, boolean def) { + config.addDefault("world-settings.default." + path, def); + return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index bd8e654c1580a0ac7dd411b9f1dcad4a20d1d3e5..7576047ea9695434ca06ca8fefde0dce68980be8 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -760,35 +760,36 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa + + // CraftBukkit start + public void prepareLevels(ChunkProgressListener worldloadlistener, ServerLevel worldserver) { +- if (!worldserver.getWorld().getKeepSpawnInMemory()) { +- return; +- } ++ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); // Paper + + // WorldServer worldserver = this.overworld(); + this.forceTicks = true; + // CraftBukkit end ++ if (worldserver.getWorld().getKeepSpawnInMemory()) { // Paper + + MinecraftServer.LOGGER.info("Preparing start region for dimension {}", worldserver.dimension().location()); + BlockPos blockposition = worldserver.getSharedSpawnPos(); + + worldloadlistener.updateSpawnPos(new ChunkPos(blockposition)); +- ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); ++ //ChunkProviderServer chunkproviderserver = worldserver.getChunkProvider(); // Paper - move up + + chunkproviderserver.getLightEngine().setTaskPerBatch(500); + this.nextTickTime = Util.getMillis(); +- chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(blockposition), 11, Unit.INSTANCE); +- +- while (chunkproviderserver.getTickingGenerated() != 441) { +- // CraftBukkit start +- // this.nextTickTime = SystemUtils.getMillis() + 10L; +- this.executeModerately(); +- // 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); ++ ++ worldserver.addTicketsForSpawn(radiusBlocks, blockposition); ++ // Paper end + + // CraftBukkit start + // this.nextTickTime = SystemUtils.getMillis() + 10L; + this.executeModerately(); + // Iterator iterator = this.levels.values().iterator(); ++ } + + if (true) { + ServerLevel worldserver1 = worldserver; +@@ -811,7 +812,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa + // this.nextTickTime = SystemUtils.getMillis() + 10L; + this.executeModerately(); + // CraftBukkit end +- worldloadlistener.stop(); ++ if (worldserver.getWorld().getKeepSpawnInMemory()) worldloadlistener.stop(); // Paper + chunkproviderserver.getLightEngine().setTaskPerBatch(5); + // CraftBukkit start + // this.updateMobSpawningFlags(); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 2950ad995f322570cd647d3217f340327cc3e7c8..fef3846a978dcba95c5dbe5c528ac20cb4f56178 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -60,6 +60,7 @@ import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket; + import net.minecraft.network.protocol.game.ClientboundSoundPacket; + import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.resources.ResourceKey; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.ServerScoreboard; + import net.minecraft.server.level.progress.ChunkProgressListener; +@@ -1606,12 +1607,84 @@ public class ServerLevel extends Level implements WorldGenLevel { + return ((MapIndex) this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex::load, MapIndex::new, "idcounts")).getFreeAuxValueForMap(); + } + ++ // Paper start - helper function for configurable spawn radius ++ public void addTicketsForSpawn(int radiusInBlocks, BlockPos 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 ++ ServerChunkCache chunkproviderserver = this.getChunkSource(); ++ 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.addRegionTicket(TicketType.START, new ChunkPos(spawn.offset(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.addRegionTicket(TicketType.START, new ChunkPos(spawn.offset(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32 ++ // bottom ++ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(spawn.offset(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.addRegionTicket(TicketType.START, new ChunkPos(spawn.offset(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 ++ // left ++ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(spawn.offset(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 ++ } ++ } ++ public void removeTicketsForSpawn(int radiusInBlocks, BlockPos 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 ++ ServerChunkCache chunkproviderserver = this.getChunkSource(); ++ 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.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(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.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32 ++ // bottom ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(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.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 ++ // left ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 ++ } ++ } ++ // Paper end ++ + public void setDefaultSpawnPos(BlockPos pos, float angle) { +- ChunkPos chunkcoordintpair = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn())); ++ // Paper - configurable spawn radius ++ BlockPos prevSpawn = this.getSharedSpawnPos(); ++ //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); + + this.levelData.setSpawn(pos, angle); +- this.getChunkSource().removeRegionTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); +- this.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(pos), 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, pos); ++ } + this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(pos, angle)); + } + +diff --git a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java +index 1b565b2809c2d367e21971c5154f35c9763995e6..b0f899835ded29aff108d1674bf4a1a6c89693db 100644 +--- a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java ++++ b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java +@@ -12,4 +12,6 @@ public interface ChunkProgressListener { + void start(); + + void stop(); ++ ++ void setChunkRadius(int radius); // Paper - allow changing chunk radius + } +diff --git a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java +index 4185e6bcf9b2bb65b2a0fa5fcbeb5684615169a7..dbc29442f2b2ad3ea451910f4944e90114a317c7 100644 +--- a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java ++++ b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java +@@ -11,12 +11,19 @@ import org.apache.logging.log4j.Logger; + + public class LoggerChunkProgressListener implements ChunkProgressListener { + private static final Logger LOGGER = LogManager.getLogger(); +- private final int maxCount; ++ private int maxCount; // Paper - remove final + private int count; + private long startTime; + private long nextTickTime = Long.MAX_VALUE; + + public LoggerChunkProgressListener(int radius) { ++ // Paper start - Allow changing radius later for configurable spawn patch ++ this.setChunkRadius(radius); // Move to method ++ } ++ ++ @Override ++ public void setChunkRadius(int radius) { ++ // Paper end + int i = radius * 2 + 1; + this.maxCount = i * i; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 29509d3ae956fd4da2bf12c6a352ab115fc75f5c..255616aa45b06487c67aa6011dbe29e18d82bc68 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1340,15 +1340,21 @@ public class CraftWorld extends CraftRegionAccessor implements World { + + @Override + public void setKeepSpawnInMemory(boolean keepLoaded) { +- world.keepSpawnInMemory = keepLoaded; ++ // Paper start - Configurable spawn radius ++ if (keepLoaded == world.keepSpawnInMemory) { ++ // do nothing, nothing has changed ++ return; ++ } ++ this.world.keepSpawnInMemory = keepLoaded; + // Grab the worlds spawn chunk + BlockPos chunkcoordinates = this.world.getSharedSpawnPos(); + if (keepLoaded) { +- this.world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); ++ this.world.addTicketsForSpawn(this.world.paperConfig.keepLoadedRange, chunkcoordinates); + } else { +- // TODO: doesn't work well if spawn changed.... +- this.world.getChunkSource().removeRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); ++ // TODO: doesn't work well if spawn changed.... // Paper - resolved ++ this.world.removeTicketsForSpawn(this.world.paperConfig.keepLoadedRange, chunkcoordinates); + } ++ // Paper end + } + + @Override |