Ensure priority updates are determined by current level, not deferred level (#6507)

* Ensure priority updates are determined by current level, not deferred level

Deferral could cause an infinite loop to occur.

Also, re-add the light engine priority logic.

* Rebase

Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
This commit is contained in:
Spottedleaf 2021-08-27 19:20:31 -07:00 committed by GitHub
parent 159112ef41
commit 1c4f87a258
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 35 deletions

View File

@ -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<ChunkHolder, ChunkStatus> neighbors = new java.util.concurrent.ConcurrentHashMap<>();
+ public final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<Integer> 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<ServerPlayer> 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<CompoundTag> 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 {

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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();

View File

@ -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<Void> 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);