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

221 lines
12 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/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 2a56a462ca8bd839bb373789b117945dc6372e03..0e7ca77f5b66fcea190386f49b95e9314dede97c 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
@@ -767,30 +767,33 @@ 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) {
+ ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); // Paper - Configurable Keep Spawn Loaded range per world
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 - Configurable Keep Spawn Loaded range per world
2021-06-11 12:02:28 +00:00
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 - Configurable Keep Spawn Loaded range per world; move up
2021-06-11 12:02:28 +00:00
2023-12-05 22:21:44 +00:00
this.nextTickTimeNanos = Util.getNanos();
- // CraftBukkit start
- if (worldserver.getWorld().getKeepSpawnInMemory()) {
- chunkproviderserver.addRegionTicket(TicketType.START, new ChunkPos(blockposition), 11, Unit.INSTANCE);
+ // Paper start - Configurable Keep Spawn Loaded range per world
+ int radiusBlocks = worldserver.paperConfig().spawn.keepSpawnLoadedRange * 16;
2021-06-11 12:02:28 +00:00
+ int radiusChunks = radiusBlocks / 16 + ((radiusBlocks & 15) != 0 ? 1 : 0);
+ int totalChunks = ((radiusChunks) * 2 + 1);
+ totalChunks *= totalChunks;
+ worldloadlistener.setChunkRadius(radiusBlocks / 16);
- while (chunkproviderserver.getTickingGenerated() != 441) {
- // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS;
- this.executeModerately();
- }
- }
2021-06-11 12:02:28 +00:00
+ worldserver.addTicketsForSpawn(radiusBlocks, blockposition);
+ // Paper end - Configurable Keep Spawn Loaded range per world
2021-06-13 11:40:34 +00:00
2023-12-05 22:21:44 +00:00
// this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS;
2021-06-11 12:02:28 +00:00
this.executeModerately();
2021-11-24 04:25:34 +00:00
// Iterator iterator = this.levels.values().iterator();
+ } // Paper - Configurable Keep Spawn Loaded range per world
2021-06-11 12:02:28 +00:00
if (true) {
ServerLevel worldserver1 = worldserver;
@@ -813,7 +816,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
2023-12-05 22:21:44 +00:00
// this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS;
2021-06-11 12:02:28 +00:00
this.executeModerately();
// CraftBukkit end
- worldloadlistener.stop();
+ if (worldserver.getWorld().getKeepSpawnInMemory()) worldloadlistener.stop(); // Paper - Configurable Keep Spawn Loaded range per world
2021-06-11 12:02:28 +00:00
// CraftBukkit start
2021-11-24 04:25:34 +00:00
// this.updateMobSpawningFlags();
worldserver.setSpawnSettings(this.isSpawningMonsters(), this.isSpawningAnimals());
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 87062f8558518d996b1afaafcd7d9f8d04117e94..5517a1869e9c7a745aeec3bc55722320e1c605c3 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
@@ -1879,12 +1879,84 @@ public class ServerLevel extends Level implements WorldGenLevel {
2023-09-22 02:17:21 +00:00
return ((MapIndex) this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex.factory(), "idcounts")).getFreeAuxValueForMap();
2021-06-11 12:02:28 +00:00
}
+ // Paper start - Configurable Keep Spawn Loaded range per world
2021-06-11 12:02:28 +00:00
+ 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 - Configurable Keep Spawn Loaded range per world
2021-06-11 12:02:28 +00:00
+
public void setDefaultSpawnPos(BlockPos pos, float angle) {
- ChunkPos chunkcoordintpair = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn()));
+ // Paper start - Configurable Keep Spawn Loaded range per world
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().spawn.keepSpawnLoadedRange * 16, prevSpawn);
+ this.addTicketsForSpawn(this.paperConfig().spawn.keepSpawnLoadedRange * 16, pos);
2021-06-11 12:02:28 +00:00
+ }
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..4792eaa30464f4c4ca7f2d6cf20f734beed81f23 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 - Configurable Keep Spawn Loaded range per world
2021-06-11 12:02:28 +00:00
}
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 4d2348df25410a0b5364eec066880326d6667dad..3754cda7e7731935893359d84f3ae06157a347c6 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;
+ 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 - Configurable Keep Spawn Loaded range per world
2021-06-11 12:02:28 +00:00
+ this.setChunkRadius(radius); // Move to method
+ }
+
+ @Override
+ public void setChunkRadius(int radius) {
+ // Paper end - Configurable Keep Spawn Loaded range per world
2021-06-13 11:40:34 +00:00
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 50d0d854159396064ee8ee7de5a7f885d8cc13a4..f72409e92cbf00c5665037bf4916ddbd352d66d5 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
Updated Upstream (Bukkit/CraftBukkit/Spigot) Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: cc9aa21a SPIGOT-6399, SPIGOT-7344: Clarify collidable behavior for player entities f23325b6 Add API for per-world simulation distances 26e1774e Add API for per-world view distances 0b541e60 Add PlayerLoginEvent#getRealAddress 5f027d2d PR-949: Add Vector#fromJOML() overloads for read-only vector types CraftBukkit Changes: bcf56171a PR-1321: Clean up some stuff which got missed during previous PRs 7f833a2d1 SPIGOT-7462: Players no longer drop XP after dying near a Sculk Catalyst 752aac669 Implement APIs for per world view and simulation distances 57d7ef433 Preserve empty enchantment tags for glow effect 465ec3fb4 Remove connected check on setScoreboard f90ce621e Use one PermissibleBase for all command blocks 5876cca44 SPIGOT-7550: Fix creation of Arrow instances f03fc3aa3 SPIGOT-7549: ServerTickManager#setTickRate incorrect Precondition 9d7f49b01 SPIGOT-7548: Fix wrong spawn location for experience orb and dropped item Spigot Changes: ed9ba9a4 Drop no longer required patch ignoring -o option 86b5dd6a SPIGOT-7546: Fix hardcoded check for outdated client message aa7cde7a Remove obsolete APIs for per world view and simulation distances 6dff577e Remove obsolete patch preserving empty `ench` tags a3bf95b8 Remove obsolete PlayerLoginEvent#getRealAddress 1b02f5d6 Remove obsolete connected check on setScoreboard patch acf717eb Remove obsolete command block PermissibleBase patch 053fa2a9 Remove redundant patch dealing with null tile entities
2023-12-25 22:51:56 +00:00
@@ -1407,15 +1407,21 @@ public class CraftWorld extends CraftRegionAccessor implements World {
2021-06-11 12:02:28 +00:00
@Override
public void setKeepSpawnInMemory(boolean keepLoaded) {
+ // Paper start - Configurable spawn radius
2023-10-26 23:34:58 +00:00
+ if (keepLoaded == this.world.keepSpawnInMemory) {
2021-06-11 12:02:28 +00:00
+ // do nothing, nothing has changed
+ return;
+ }
2023-10-26 23:34:58 +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().spawn.keepSpawnLoadedRange * 16, 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
+ this.world.removeTicketsForSpawn(this.world.paperConfig().spawn.keepSpawnLoadedRange * 16, chunkcoordinates);
2021-06-11 12:02:28 +00:00
}
+ // Paper end
}
@Override