papermc/patches/server/0328-Configurable-Keep-Spawn-Loaded-range-per-world.patch

253 lines
13 KiB
Diff
Raw Normal View History

2021-06-11 12:02:28 +00:00
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 eb44aef0aecf65f5c1b19f42bf85a3a263965a7c..5589ee42959e3665dd5df9049fe108b6f6629608 100644
2021-06-11 12:02:28 +00:00
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
2021-11-24 17:58:26 +00:00
@@ -56,6 +56,12 @@ public class PaperWorldConfig {
2021-06-11 12:02:28 +00:00
}
}
2021-06-13 11:40:34 +00:00
2021-06-11 12:02:28 +00:00
+ 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));
+ }
2021-06-13 11:40:34 +00:00
+
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));
2021-06-11 12:02:28 +00:00
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
2022-03-01 05:43:03 +00:00
index b24064e5f5029b0c42ea0083533eb581cad01528..e60e4f3693314adb7763c440036f0c80d15f349a 100644
2021-06-11 12:02:28 +00:00
--- 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
2021-06-11 12:02:28 +00:00
// CraftBukkit start
2021-11-24 04:25:34 +00:00
public void prepareLevels(ChunkProgressListener worldloadlistener, ServerLevel worldserver) {
2021-06-11 12:02:28 +00:00
- if (!worldserver.getWorld().getKeepSpawnInMemory()) {
- return;
- }
+ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); // Paper
2021-11-24 04:25:34 +00:00
// WorldServer worldserver = this.overworld();
2021-06-11 12:02:28 +00:00
this.forceTicks = true;
// CraftBukkit end
+ if (worldserver.getWorld().getKeepSpawnInMemory()) { // Paper
MinecraftServer.LOGGER.info("Preparing start region for dimension {}", worldserver.dimension().location());
2021-06-13 11:40:34 +00:00
BlockPos blockposition = worldserver.getSharedSpawnPos();
2021-06-11 12:02:28 +00:00
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
2021-11-24 04:25:34 +00:00
- // this.nextTickTime = SystemUtils.getMillis() + 10L;
2021-06-11 12:02:28 +00:00
- 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
2021-06-13 11:40:34 +00:00
2021-06-11 12:02:28 +00:00
// CraftBukkit start
2021-11-24 04:25:34 +00:00
// this.nextTickTime = SystemUtils.getMillis() + 10L;
2021-06-11 12:02:28 +00:00
this.executeModerately();
2021-11-24 04:25:34 +00:00
// Iterator iterator = this.levels.values().iterator();
2021-06-11 12:02:28 +00:00
+ }
if (true) {
ServerLevel worldserver1 = worldserver;
@@ -811,7 +812,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
2021-11-24 04:25:34 +00:00
// this.nextTickTime = SystemUtils.getMillis() + 10L;
2021-06-11 12:02:28 +00:00
this.executeModerately();
// CraftBukkit end
- worldloadlistener.stop();
+ if (worldserver.getWorld().getKeepSpawnInMemory()) worldloadlistener.stop(); // Paper
chunkproviderserver.getLightEngine().setTaskPerBatch(5);
// CraftBukkit start
2021-11-24 04:25:34 +00:00
// this.updateMobSpawningFlags();
2021-06-11 12:02:28 +00:00
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index ebaa49c99eb797dfefe401731884f70a841904ad..704d5fd4038cd6913e0804b66da920cd661e93ee 100644
2021-06-11 12:02:28 +00:00
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
2022-03-01 05:43:03 +00:00
@@ -63,6 +63,7 @@ import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket;
2021-06-13 11:40:34 +00:00
import net.minecraft.network.protocol.game.ClientboundSoundPacket;
2021-06-11 12:02:28 +00:00
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;
2022-03-01 05:43:03 +00:00
@@ -1614,12 +1615,84 @@ public class ServerLevel extends Level implements WorldGenLevel {
2021-06-13 11:40:34 +00:00
return ((MapIndex) this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex::load, MapIndex::new, "idcounts")).getFreeAuxValueForMap();
2021-06-11 12:02:28 +00:00
}
+ // 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
2021-06-17 17:11:00 +00:00
+ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(spawn.offset(x, 0, z)), 2, Unit.INSTANCE);
2021-06-11 12:02:28 +00:00
+ }
+ }
+
+ // add border chunks
+
+ // add border along x axis (including corner chunks)
+ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) {
+ // top
2021-06-17 17:11:00 +00:00
+ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(spawn.offset(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32
2021-06-11 12:02:28 +00:00
+ // bottom
2021-06-17 17:11:00 +00:00
+ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(spawn.offset(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32
2021-06-11 12:02:28 +00:00
+ }
+
+ // add border along z axis (excluding corner chunks)
+ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) {
+ // right
2021-06-17 17:11:00 +00:00
+ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(spawn.offset(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32
2021-06-11 12:02:28 +00:00
+ // left
2021-06-17 17:11:00 +00:00
+ chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(spawn.offset(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32
2021-06-11 12:02:28 +00:00
+ }
+ }
+ 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
2021-06-17 17:11:00 +00:00
+ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(x, 0, z)), 2, Unit.INSTANCE);
2021-06-11 12:02:28 +00:00
+ }
+ }
+
+ // remove border chunks
+
+ // remove border along x axis (including corner chunks)
+ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) {
+ // top
2021-06-17 17:11:00 +00:00
+ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32
2021-06-11 12:02:28 +00:00
+ // bottom
2021-06-17 17:11:00 +00:00
+ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32
2021-06-11 12:02:28 +00:00
+ }
+
+ // remove border along z axis (excluding corner chunks)
+ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) {
+ // right
2021-06-17 17:11:00 +00:00
+ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32
2021-06-11 12:02:28 +00:00
+ // left
2021-06-17 17:11:00 +00:00
+ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32
2021-06-11 12:02:28 +00:00
+ }
+ }
+ // 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
2021-06-13 12:43:56 +00:00
+ BlockPos prevSpawn = this.getSharedSpawnPos();
2021-06-11 12:02:28 +00:00
+ //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
2021-06-13 11:40:34 +00:00
index 1b565b2809c2d367e21971c5154f35c9763995e6..b0f899835ded29aff108d1674bf4a1a6c89693db 100644
2021-06-11 12:02:28 +00:00
--- a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java
+++ b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java
2021-06-13 11:40:34 +00:00
@@ -12,4 +12,6 @@ public interface ChunkProgressListener {
void start();
2021-06-11 12:02:28 +00:00
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
2022-03-01 05:43:03 +00:00
index 1fdb4242784e55d5bb6102deb150a57a156aacd3..419e1c4db73631de3d65d8a0e7d5eb080b2e3935 100644
2021-06-11 12:02:28 +00:00
--- a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java
+++ b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java
2022-03-01 05:43:03 +00:00
@@ -11,12 +11,19 @@ import org.slf4j.Logger;
2021-06-11 12:02:28 +00:00
2021-06-13 11:40:34 +00:00
public class LoggerChunkProgressListener implements ChunkProgressListener {
2022-03-01 05:43:03 +00:00
private static final Logger LOGGER = LogUtils.getLogger();
2021-06-11 12:02:28 +00:00
- private final int maxCount;
2022-03-01 05:43:03 +00:00
+ private int maxCount;// Paper - remove final
2021-06-11 12:02:28 +00:00
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) {
2021-06-13 11:40:34 +00:00
+ // Paper end
int i = radius * 2 + 1;
this.maxCount = i * i;
2021-06-11 12:02:28 +00:00
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index be2790a12ec37267418b77569ceb7dec54d7c282..b3bdfe375a42c5b4bb7b2a3c79678ca57419d179 100644
2021-06-11 12:02:28 +00:00
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
2022-03-01 05:43:03 +00:00
@@ -1349,15 +1349,21 @@ public class CraftWorld extends CraftRegionAccessor implements World {
2021-06-11 12:02:28 +00:00
@Override
public void setKeepSpawnInMemory(boolean keepLoaded) {
2021-06-13 11:40:34 +00:00
- world.keepSpawnInMemory = keepLoaded;
2021-06-11 12:02:28 +00:00
+ // Paper start - Configurable spawn radius
+ if (keepLoaded == world.keepSpawnInMemory) {
+ // do nothing, nothing has changed
+ return;
+ }
2021-06-13 11:40:34 +00:00
+ this.world.keepSpawnInMemory = keepLoaded;
2021-06-11 12:02:28 +00:00
// Grab the worlds spawn chunk
2021-06-13 11:40:34 +00:00
BlockPos chunkcoordinates = this.world.getSharedSpawnPos();
2021-06-11 12:02:28 +00:00
if (keepLoaded) {
2021-06-13 11:40:34 +00:00
- this.world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE);
+ this.world.addTicketsForSpawn(this.world.paperConfig.keepLoadedRange, chunkcoordinates);
2021-06-11 12:02:28 +00:00
} else {
- // TODO: doesn't work well if spawn changed....
2021-06-13 11:40:34 +00:00
- this.world.getChunkSource().removeRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE);
+ // TODO: doesn't work well if spawn changed.... // Paper - resolved
2021-06-13 11:40:34 +00:00
+ this.world.removeTicketsForSpawn(this.world.paperConfig.keepLoadedRange, chunkcoordinates);
2021-06-11 12:02:28 +00:00
}
+ // Paper end
}
@Override