diff --git a/patches/server/0487-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/0487-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch index b188f587d4..b9639aed33 100644 --- a/patches/server/0487-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ b/patches/server/0487-Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -80,7 +80,7 @@ index 2d5b8e35d52b0dfd075af81a3a936d8a21053b31..9ddedd310eb0323a5a09f51a61bfb7b3 chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.longKey)); chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d5d5ecf30 100644 +index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..75fbcc3d9b3aca2738df0c7ce8c1a0b157ff375a 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java @@ -60,7 +60,7 @@ public class ChunkHolder { @@ -100,7 +100,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d // Paper start - no-tick view distance public final LevelChunk getSendingChunk() { // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used -@@ -100,6 +101,134 @@ public class ChunkHolder { +@@ -100,6 +101,136 @@ public class ChunkHolder { } // Paper end @@ -109,6 +109,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d + volatile int priorityBoost = 0; + public final java.util.concurrent.ConcurrentHashMap neighbors = new java.util.concurrent.ConcurrentHashMap<>(); + public final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap neighborPriorities = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(); ++ int requestedPriority = ChunkMap.MAX_CHUNK_DISTANCE + 1; // this priority is possible pending, but is used to ensure needless updates are not queued + + private int getDemandedPriority() { + int priority = neighborPriority; // if we have a neighbor priority, use it @@ -170,8 +171,9 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d + + private void setNeighborPriority(ChunkHolder requester, int priority) { + synchronized (neighborPriorities) { -+ neighborPriorities.put(requester.pos.toLong(), Integer.valueOf(priority)); -+ recalcNeighborPriority(); ++ if (!Integer.valueOf(priority).equals(neighborPriorities.put(requester.pos.toLong(), Integer.valueOf(priority)))) { ++ recalcNeighborPriority(); ++ } + } + checkPriority(); + } @@ -189,7 +191,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d + } + } + private void checkPriority() { -+ if (queueLevel != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); ++ if (this.requestedPriority != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); + } + + public final double getDistance(ServerPlayer player) { @@ -235,7 +237,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d // Paper start - optimise isOutsideOfRange // cached here to avoid a map lookup com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInMobSpawnRange; -@@ -470,12 +599,25 @@ public class ChunkHolder { +@@ -470,12 +601,25 @@ public class ChunkHolder { }); } @@ -261,7 +263,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d ChunkStatus chunkstatus = ChunkHolder.getStatus(this.oldTicketLevel); ChunkStatus chunkstatus1 = ChunkHolder.getStatus(this.ticketLevel); boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; -@@ -486,9 +628,22 @@ public class ChunkHolder { +@@ -486,9 +630,22 @@ public class ChunkHolder { // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. if (playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { @@ -285,7 +287,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag. // These actions may however happen deferred, so we manually set the needsSaving flag already here. -@@ -545,12 +700,14 @@ public class ChunkHolder { +@@ -545,12 +702,14 @@ public class ChunkHolder { this.scheduleFullChunkPromotion(chunkStorage, this.fullChunkFuture, executor, ChunkHolder.FullChunkStatus.BORDER); // Paper start - cache ticking ready status this.fullChunkFuture.thenAccept(either -> { @@ -300,7 +302,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d } }); this.updateChunkToSave(this.fullChunkFuture, "full"); -@@ -575,6 +732,7 @@ public class ChunkHolder { +@@ -575,6 +734,7 @@ public class ChunkHolder { this.scheduleFullChunkPromotion(chunkStorage, this.tickingChunkFuture, executor, ChunkHolder.FullChunkStatus.TICKING); // Paper start - cache ticking ready status this.tickingChunkFuture.thenAccept(either -> { @@ -308,7 +310,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d either.ifLeft(chunk -> { // note: Here is a very good place to add callbacks to logic waiting on this. ChunkHolder.this.isTickingReady = true; -@@ -607,6 +765,7 @@ public class ChunkHolder { +@@ -607,6 +767,7 @@ public class ChunkHolder { this.scheduleFullChunkPromotion(chunkStorage, this.entityTickingChunkFuture, executor, ChunkHolder.FullChunkStatus.ENTITY_TICKING); // Paper start - cache ticking ready status this.entityTickingChunkFuture.thenAccept(either -> { @@ -316,7 +318,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d either.ifLeft(chunk -> { ChunkHolder.this.isEntityTickingReady = true; }); -@@ -624,16 +783,42 @@ public class ChunkHolder { +@@ -624,16 +785,44 @@ public class ChunkHolder { this.demoteFullChunk(chunkStorage, playerchunk_state1); } @@ -324,7 +326,9 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d + //this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); + // Paper start - raise IO/load priority if priority changes, use our preferred priority + priorityBoost = chunkMap.distanceManager.getChunkPriority(pos); ++ int currRequestedPriority = this.requestedPriority; + int priority = getDemandedPriority(); ++ int newRequestedPriority = this.requestedPriority = priority; + if (this.queueLevel > priority) { + int ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; + if (priority <= 10) { @@ -334,7 +338,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d + } + chunkMap.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, ioPriority); + } -+ if (this.queueLevel != priority) { ++ if (currRequestedPriority != newRequestedPriority) { + this.onLevelChange.onLevelChange(this.pos, () -> this.queueLevel, priority, p -> this.queueLevel = p); // use preferred priority + int neighborsPriority = getNeighborsPriority(); + this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority)); @@ -363,7 +367,7 @@ index 8245e07f6ecfd9dd997c8525b52c6eadd392e6f1..a0334dde56829fd895323f4cab2ab55d } }).exceptionally((throwable) -> { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 12f9f512dc8b9e094dab2caec7b6ddaf2a378ee9..5b1b91ab4d351f47a05a73cf65539b0bc92df13b 100644 +index 12f9f512dc8b9e094dab2caec7b6ddaf2a378ee9..11b743acfad319f536798204d525cda0813e8987 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -149,6 +149,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -589,7 +593,7 @@ index 12f9f512dc8b9e094dab2caec7b6ddaf2a378ee9..5b1b91ab4d351f47a05a73cf65539b0b CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); + // Paper start + ChunkHolder playerChunk = getUpdatingChunkIfPresent(pos.toLong()); -+ int chunkPriority = playerChunk != null ? playerChunk.queueLevel : 33; ++ int chunkPriority = playerChunk != null ? playerChunk.requestedPriority : 33; + int priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; + + if (chunkPriority <= 10) { @@ -1103,7 +1107,7 @@ index 6d947343b6ff2f86a23ea669e371d5ecd9e903c0..d6f0c82b503a0fa73f6589fc4c331d27 boolean flag1 = this.chunkMap.promoteChunkMap(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index cf09bd17b9d2be04f79edef6debdd815b5f7f86c..6cf83d9b1e43ade17cb67843dbdc11937eda1e08 100644 +index 009b6fe428db1a6e69403d8df32325f78e6b4461..1da049b171e26ac422fa0e56d8772577d5c768fa 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -189,6 +189,14 @@ public class ServerPlayer extends Player { diff --git a/patches/server/0488-Improve-Chunk-Status-Transition-Speed.patch b/patches/server/0488-Improve-Chunk-Status-Transition-Speed.patch index f83c01190e..6007510277 100644 --- a/patches/server/0488-Improve-Chunk-Status-Transition-Speed.patch +++ b/patches/server/0488-Improve-Chunk-Status-Transition-Speed.patch @@ -36,10 +36,10 @@ scenario / path: Previously would have hopped to SERVER around 12+ times there extra. diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index a0334dde56829fd895323f4cab2ab55d5d5ecf30..81696d822c00e506ba2128590e95341994ff93f6 100644 +index 75fbcc3d9b3aca2738df0c7ce8c1a0b157ff375a..0c6d513b6bcbd518fe4beee7acd7b96ce801c78e 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -242,6 +242,13 @@ public class ChunkHolder { +@@ -244,6 +244,13 @@ public class ChunkHolder { // Paper end - optimise isOutsideOfRange long lastAutoSaveTime; // Paper - incremental autosave long inactiveTimeStart; // Paper - incremental autosave @@ -54,7 +54,7 @@ index a0334dde56829fd895323f4cab2ab55d5d5ecf30..81696d822c00e506ba2128590e953419 public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 5b1b91ab4d351f47a05a73cf65539b0bc92df13b..d470fdcbc79c4a491e9a078930b54e8d8949d68c 100644 +index 11b743acfad319f536798204d525cda0813e8987..1de84204656d60e4dc91cc37661cb7c1573a22d2 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -827,7 +827,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider diff --git a/patches/server/0494-Optimize-Light-Engine.patch b/patches/server/0494-Optimize-Light-Engine.patch index b905a4adae..a424b1c7da 100644 --- a/patches/server/0494-Optimize-Light-Engine.patch +++ b/patches/server/0494-Optimize-Light-Engine.patch @@ -25,19 +25,19 @@ Massive update to light to improve performance and chunk loading/generation. 8) Fix NPE risk that crashes server in getting nibble data diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 81696d822c00e506ba2128590e95341994ff93f6..c6c4894427e5e98dccc1506d9d20157e1acbbd21 100644 +index 0c6d513b6bcbd518fe4beee7acd7b96ce801c78e..e6cc5da2fd58bcc2809baeffee01040d0370a92c 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -810,6 +810,7 @@ public class ChunkHolder { +@@ -806,6 +806,7 @@ public class ChunkHolder { + ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; + } + chunkMap.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, ioPriority); ++ chunkMap.level.getChunkSource().getLightEngine().queue.changePriority(pos.toLong(), this.queueLevel, priority); // Paper // Restore this in chunk priority later? } - // Paper end - this.oldTicketLevel = this.ticketLevel; -+ //chunkMap.level.getChunkSource().getLightEngine().queue.changePriority(pos.toLong(), this.queueLevel, priority); // Paper // Restore this in chunk priority later? - // CraftBukkit start - // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. - if (!playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { + if (currRequestedPriority != newRequestedPriority) { + this.onLevelChange.onLevelChange(this.pos, () -> this.queueLevel, priority, p -> this.queueLevel = p); // use preferred priority diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index d470fdcbc79c4a491e9a078930b54e8d8949d68c..1c662deee2a3184c7612cf7de5f798753fbd7381 100644 +index 1de84204656d60e4dc91cc37661cb7c1573a22d2..97bf5120d680ab47778c65e28e2ea2954daac031 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -97,6 +97,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana diff --git a/patches/server/0527-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/0527-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch index dfe38d995f..ec3ee41bb3 100644 --- a/patches/server/0527-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch +++ b/patches/server/0527-Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 6333a310fe32c631be95889f7438414d4a2c03bd..2e983077143a0a7ce6857d5796c9e4f7a4629caf 100644 +index e6cc5da2fd58bcc2809baeffee01040d0370a92c..8d59d735b2862ecc12cbfebc57a02ebbfd1e125e 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -379,6 +379,7 @@ public class ChunkHolder { +@@ -381,6 +381,7 @@ public class ChunkHolder { } public void blockChanged(BlockPos pos) { diff --git a/patches/server/0756-Correctly-handle-recursion-for-chunkholder-updates.patch b/patches/server/0756-Correctly-handle-recursion-for-chunkholder-updates.patch index 89c2fd766a..9ce61f4bf3 100644 --- a/patches/server/0756-Correctly-handle-recursion-for-chunkholder-updates.patch +++ b/patches/server/0756-Correctly-handle-recursion-for-chunkholder-updates.patch @@ -8,10 +8,10 @@ cause a recursive call which would handle the increase but then the caller would think the chunk would be unloaded. diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index e844ac574e4b94580a14027c130374f1287f7324..844a0e1ac3a6480c8d7b49debaada2c698432405 100644 +index 8d59d735b2862ecc12cbfebc57a02ebbfd1e125e..ee71e8678e58441287a9cd6cf00d5635daddc60f 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -624,8 +624,10 @@ public class ChunkHolder { +@@ -626,8 +626,10 @@ public class ChunkHolder { playerchunkmap.onFullChunkStatusChange(this.pos, playerchunk_state); } @@ -22,7 +22,7 @@ index e844ac574e4b94580a14027c130374f1287f7324..844a0e1ac3a6480c8d7b49debaada2c6 ChunkStatus chunkstatus = ChunkHolder.getStatus(this.oldTicketLevel); ChunkStatus chunkstatus1 = ChunkHolder.getStatus(this.ticketLevel); boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; -@@ -667,6 +669,12 @@ public class ChunkHolder { +@@ -669,6 +671,12 @@ public class ChunkHolder { // Run callback right away if the future was already done chunkStorage.callbackExecutor.run(); diff --git a/patches/server/0759-Do-not-allow-ticket-level-changes-when-updating-chun.patch b/patches/server/0759-Do-not-allow-ticket-level-changes-when-updating-chun.patch index 0a3d148f3a..1d432decac 100644 --- a/patches/server/0759-Do-not-allow-ticket-level-changes-when-updating-chun.patch +++ b/patches/server/0759-Do-not-allow-ticket-level-changes-when-updating-chun.patch @@ -8,10 +8,10 @@ This WILL cause state corruption if it happens. So, don't allow it. diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 844a0e1ac3a6480c8d7b49debaada2c698432405..660ec9359cb9fe9cdb54d7ef6139bbbccb91ba16 100644 +index ee71e8678e58441287a9cd6cf00d5635daddc60f..7c0d404e5ac6819326276fb6424e33949c4ee08b 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -597,7 +597,13 @@ public class ChunkHolder { +@@ -599,7 +599,13 @@ public class ChunkHolder { CompletableFuture completablefuture1 = new CompletableFuture(); completablefuture1.thenRunAsync(() -> { @@ -25,7 +25,7 @@ index 844a0e1ac3a6480c8d7b49debaada2c698432405..660ec9359cb9fe9cdb54d7ef6139bbbc }, executor); this.pendingFullStateConfirmation = completablefuture1; completablefuture.thenAccept((either) -> { -@@ -621,7 +627,12 @@ public class ChunkHolder { +@@ -623,7 +629,12 @@ public class ChunkHolder { private void demoteFullChunk(ChunkMap playerchunkmap, ChunkHolder.FullChunkStatus playerchunk_state) { this.pendingFullStateConfirmation.cancel(false);