More Improvements to Chunks
Fixed issues where urgent and prioritized chunks didn't actually always get their priority boosted correctly.... Properly deprioritize non ticking chunks. Limit recursion on watchdog prints to stop flooding as much Remove neighbor priorities from watchdog to reduce information reduce synchronization duration so that watch dog won't block main should main actually wake up probably fixed a deadlock risk in watchdog printing also that was leading to crashes fixed chunk holder enqueues not being processed correctly added async catchers in some locations that should not be ran async Fixed upstream bug where VITAL callbacks that must run on main actually could sometimes run on the server thread pool causing alot of these nasty bugs we've seen lately! This build will provide massive improvements to stability as well as even faster sync chunk load/gens now that priority is correctly set. Fixes #3435
Dieser Commit ist enthalten in:
Ursprung
e1c451968c
Commit
7c001d64a5
@ -3265,14 +3265,15 @@ index 75308712d0642d5ab168de653023349df8aee5ed..aa7501d366b15e7f7f64b7d98a1dccff
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b40cd1fad5c9e2f0f85c87a559caf2b780814017
|
||||
index 0000000000000000000000000000000000000000..aaa6e33b0e5df2549e4f989501bacfd1ab4ad063
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -0,0 +1,487 @@
|
||||
@@ -0,0 +1,532 @@
|
||||
+package net.minecraft.server;
|
||||
+
|
||||
+import com.destroystokyo.paper.block.TargetBlockInfo;
|
||||
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
+import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.block.BlockFace;
|
||||
+import org.bukkit.craftbukkit.CraftWorld;
|
||||
@ -3290,6 +3291,7 @@ index 0000000000000000000000000000000000000000..b40cd1fad5c9e2f0f85c87a559caf2b7
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
+import java.util.concurrent.TimeoutException;
|
||||
+import java.util.concurrent.atomic.AtomicBoolean;
|
||||
+import java.util.function.BiConsumer;
|
||||
+import java.util.function.Consumer;
|
||||
+import java.util.function.Supplier;
|
||||
+
|
||||
@ -3317,6 +3319,12 @@ index 0000000000000000000000000000000000000000..b40cd1fad5c9e2f0f85c87a559caf2b7
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ public static <T> Runnable once(List<T> list, Consumer<T> cb) {
|
||||
+ return once(() -> {
|
||||
+ list.forEach(cb);
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ private static Runnable makeCleanerCallback(Runnable run) {
|
||||
+ return once(() -> cleanerExecutor.execute(run));
|
||||
+ }
|
||||
@ -3384,19 +3392,16 @@ index 0000000000000000000000000000000000000000..b40cd1fad5c9e2f0f85c87a559caf2b7
|
||||
+ return list;
|
||||
+ }
|
||||
+
|
||||
+ public static long getCoordinateKey(final BlockPosition blockPos) {
|
||||
+ return ((long)(blockPos.getZ() >> 4) << 32) | ((blockPos.getX() >> 4) & 0xFFFFFFFFL);
|
||||
+ }
|
||||
+
|
||||
+ public static long getCoordinateKey(final Entity entity) {
|
||||
+ return ((long)(MCUtil.fastFloor(entity.locZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.locX()) >> 4) & 0xFFFFFFFFL);
|
||||
+ }
|
||||
+
|
||||
+ public static int fastFloor(double x) {
|
||||
+ int truncated = (int)x;
|
||||
+ return x < (double)truncated ? truncated - 1 : truncated;
|
||||
+ }
|
||||
+
|
||||
+ public static int fastFloor(float x) {
|
||||
+ int truncated = (int)x;
|
||||
+ return x < (double)truncated ? truncated - 1 : truncated;
|
||||
+ }
|
||||
+
|
||||
+ public static float normalizeYaw(float f) {
|
||||
+ float f1 = f % 360.0F;
|
||||
+
|
||||
@ -3411,9 +3416,31 @@ index 0000000000000000000000000000000000000000..b40cd1fad5c9e2f0f85c87a559caf2b7
|
||||
+ return f1;
|
||||
+ }
|
||||
+
|
||||
+ public static int fastFloor(float x) {
|
||||
+ int truncated = (int)x;
|
||||
+ return x < (double)truncated ? truncated - 1 : truncated;
|
||||
+ /**
|
||||
+ * Quickly generate a stack trace for current location
|
||||
+ *
|
||||
+ * @return Stacktrace
|
||||
+ */
|
||||
+ public static String stack() {
|
||||
+ return ExceptionUtils.getFullStackTrace(new Throwable());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Quickly generate a stack trace for current location with message
|
||||
+ *
|
||||
+ * @param str
|
||||
+ * @return Stacktrace
|
||||
+ */
|
||||
+ public static String stack(String str) {
|
||||
+ return ExceptionUtils.getFullStackTrace(new Throwable(str));
|
||||
+ }
|
||||
+
|
||||
+ public static long getCoordinateKey(final BlockPosition blockPos) {
|
||||
+ return ((long)(blockPos.getZ() >> 4) << 32) | ((blockPos.getX() >> 4) & 0xFFFFFFFFL);
|
||||
+ }
|
||||
+
|
||||
+ public static long getCoordinateKey(final Entity entity) {
|
||||
+ return ((long)(MCUtil.fastFloor(entity.locZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.locX()) >> 4) & 0xFFFFFFFFL);
|
||||
+ }
|
||||
+
|
||||
+ public static long getCoordinateKey(final ChunkCoordIntPair pair) {
|
||||
@ -3466,6 +3493,24 @@ index 0000000000000000000000000000000000000000..b40cd1fad5c9e2f0f85c87a559caf2b7
|
||||
+
|
||||
+ private MCUtil() {}
|
||||
+
|
||||
+ public static final java.util.concurrent.Executor MAIN_EXECUTOR = (run) -> {
|
||||
+ if (!isMainThread()) {
|
||||
+ MinecraftServer.getServer().execute(run);
|
||||
+ } else {
|
||||
+ run.run();
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ public static <T> CompletableFuture<T> ensureMain(CompletableFuture<T> future) {
|
||||
+ return future.thenApplyAsync(r -> r, MAIN_EXECUTOR);
|
||||
+ }
|
||||
+
|
||||
+ public static <T> void thenOnMain(CompletableFuture<T> future, Consumer<T> consumer) {
|
||||
+ future.thenAcceptAsync(consumer, MAIN_EXECUTOR);
|
||||
+ }
|
||||
+ public static <T> void thenOnMain(CompletableFuture<T> future, BiConsumer<T, Throwable> consumer) {
|
||||
+ future.whenCompleteAsync(consumer, MAIN_EXECUTOR);
|
||||
+ }
|
||||
+
|
||||
+ public static boolean isMainThread() {
|
||||
+ return MinecraftServer.getServer().isMainThread();
|
||||
|
@ -4,43 +4,6 @@ Date: Tue, 27 Dec 2016 15:02:42 -0500
|
||||
Subject: [PATCH] String based Action Bar API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
index b40cd1fad5c9e2f0f85c87a559caf2b780814017..f9a7a1e9eea67bafb85c0ed88e96abb8e45f6c81 100644
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -2,6 +2,7 @@ package net.minecraft.server;
|
||||
|
||||
import com.destroystokyo.paper.block.TargetBlockInfo;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
+import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
@@ -195,6 +196,24 @@ public final class MCUtil {
|
||||
|
||||
private MCUtil() {}
|
||||
|
||||
+ /**
|
||||
+ * Quickly generate a stack trace for current location
|
||||
+ *
|
||||
+ * @return Stacktrace
|
||||
+ */
|
||||
+ public static String stack() {
|
||||
+ return ExceptionUtils.getFullStackTrace(new Throwable());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Quickly generate a stack trace for current location with message
|
||||
+ *
|
||||
+ * @param str
|
||||
+ * @return Stacktrace
|
||||
+ */
|
||||
+ public static String stack(String str) {
|
||||
+ return ExceptionUtils.getFullStackTrace(new Throwable(str));
|
||||
+ }
|
||||
|
||||
public static boolean isMainThread() {
|
||||
return MinecraftServer.getServer().isMainThread();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 764a8ef952b6f3a38ae8430c0648ad1694aa89b9..d349f0c87bfad19cf0bddb4709f1d7b0dd4b4a36 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
|
@ -403,21 +403,22 @@ index 0000000000000000000000000000000000000000..3aceb0ea8a1a3ed94dd8a9e954c52ecd
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
index f9a7a1e9eea67bafb85c0ed88e96abb8e45f6c81..8ca1a4719d934db31d57b34cf7050acc5a1a7048 100644
|
||||
index aaa6e33b0e5df2549e4f989501bacfd1ab4ad063..8ebe5a2e2678fccb17aced57f6fd1e52c17935db 100644
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -1,7 +1,10 @@
|
||||
@@ -1,8 +1,11 @@
|
||||
package net.minecraft.server;
|
||||
|
||||
import com.destroystokyo.paper.block.TargetBlockInfo;
|
||||
+import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
+import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
+import com.mojang.authlib.GameProfile;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
@@ -329,6 +332,10 @@ public final class MCUtil {
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
@@ -355,6 +358,10 @@ public final class MCUtil {
|
||||
return run.get();
|
||||
}
|
||||
|
||||
|
@ -39,10 +39,10 @@ index 0f74ec89b3e85c918c95f9d8fef6d68403ed1107..4609e402b419ed21e17ad34d02dca55b
|
||||
|
||||
this.setCustomNameVisible(nbttagcompound.getBoolean("CustomNameVisible"));
|
||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
index 8ca1a4719d934db31d57b34cf7050acc5a1a7048..206d04dcce1d7d074cf7151a083bdc626b0b8e07 100644
|
||||
index 8ebe5a2e2678fccb17aced57f6fd1e52c17935db..45179aec0d91149ba9cc4d95e65c489ce695053d 100644
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -510,4 +510,19 @@ public final class MCUtil {
|
||||
@@ -536,4 +536,19 @@ public final class MCUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -198,13 +198,13 @@ index 8c6550433c20c54cbe390219821ce393c5720da8..e6d08756f76360b29b29f18305e5ec84
|
||||
public final ChunkGenerator<?> chunkGenerator;
|
||||
private final WorldServer world;
|
||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
index 206d04dcce1d7d074cf7151a083bdc626b0b8e07..f75f48a3d0b0bc1da3c5ae3b3cf20b64f1e8288a 100644
|
||||
index 45179aec0d91149ba9cc4d95e65c489ce695053d..20f54baacebe98435539d4cbef41f182040db2e9 100644
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -4,7 +4,13 @@ import com.destroystokyo.paper.block.TargetBlockInfo;
|
||||
import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
@@ -5,7 +5,13 @@ import com.destroystokyo.paper.profile.CraftPlayerProfile;
|
||||
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
+import com.google.gson.JsonArray;
|
||||
+import com.google.gson.JsonObject;
|
||||
+import com.google.gson.internal.Streams;
|
||||
@ -212,9 +212,9 @@ index 206d04dcce1d7d074cf7151a083bdc626b0b8e07..f75f48a3d0b0bc1da3c5ae3b3cf20b64
|
||||
import com.mojang.authlib.GameProfile;
|
||||
+import com.mojang.datafixers.util.Either;
|
||||
+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
@@ -14,8 +20,11 @@ import org.spigotmc.AsyncCatcher;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -227,7 +227,7 @@ index 206d04dcce1d7d074cf7151a083bdc626b0b8e07..f75f48a3d0b0bc1da3c5ae3b3cf20b64
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
@@ -525,4 +534,170 @@ public final class MCUtil {
|
||||
@@ -551,4 +560,170 @@ public final class MCUtil {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -1847,10 +1847,10 @@ index 0000000000000000000000000000000000000000..1dfa8abfd869ca97e4cc566d44e509b4
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a5f4cdaf06bfbb0dd957db9a1335c17b073d646d
|
||||
index 0000000000000000000000000000000000000000..b5c2e1f4a2b5fdcaa6bb01f4b3b6847cd5b73ae8
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java
|
||||
@@ -0,0 +1,509 @@
|
||||
@@ -0,0 +1,511 @@
|
||||
+package com.destroystokyo.paper.io.chunk;
|
||||
+
|
||||
+import com.destroystokyo.paper.io.PaperFileIOThread;
|
||||
@ -1929,22 +1929,20 @@ index 0000000000000000000000000000000000000000..a5f4cdaf06bfbb0dd957db9a1335c17b
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static String getChunkWaitInfo() {
|
||||
+ private static ChunkInfo[] getChunkInfos() {
|
||||
+ ChunkInfo[] chunks;
|
||||
+ synchronized (WAITING_CHUNKS) {
|
||||
+ return WAITING_CHUNKS.toString();
|
||||
+ chunks = WAITING_CHUNKS.toArray(new ChunkInfo[0]);
|
||||
+ }
|
||||
+ return chunks;
|
||||
+ }
|
||||
+
|
||||
+ public static void dumpAllChunkLoadInfo() {
|
||||
+ synchronized (WAITING_CHUNKS) {
|
||||
+ if (WAITING_CHUNKS.isEmpty()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ChunkInfo[] chunks = getChunkInfos();
|
||||
+ if (chunks.length > 0) {
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk wait task info below: ");
|
||||
+ Set<PlayerChunk> seenChunks = new HashSet<>();
|
||||
+
|
||||
+ for (final ChunkInfo chunkInfo : WAITING_CHUNKS) {
|
||||
+ for (final ChunkInfo chunkInfo : chunks) {
|
||||
+ final long key = IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ);
|
||||
+ final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(key);
|
||||
+ final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(key);
|
||||
@ -1955,18 +1953,22 @@ index 0000000000000000000000000000000000000000..a5f4cdaf06bfbb0dd957db9a1335c17b
|
||||
+ // log current status of chunk to indicate whether we're waiting on generation or loading
|
||||
+ net.minecraft.server.PlayerChunk chunkHolder = chunkInfo.world.getChunkProvider().playerChunkMap.getVisibleChunk(key);
|
||||
+
|
||||
+ dumpChunkInfo(seenChunks, chunkHolder, chunkInfo.chunkX, chunkInfo.chunkZ);
|
||||
+ dumpChunkInfo(new HashSet<>(), chunkHolder, chunkInfo.chunkX, chunkInfo.chunkZ);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ static void dumpChunkInfo(Set<PlayerChunk> seenChunks, PlayerChunk chunkHolder, int x, int z) {
|
||||
+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0);
|
||||
+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1);
|
||||
+ }
|
||||
+ static void dumpChunkInfo(Set<PlayerChunk> seenChunks, PlayerChunk chunkHolder, int x, int z, int indent) {
|
||||
+
|
||||
+ static void dumpChunkInfo(Set<PlayerChunk> seenChunks, PlayerChunk chunkHolder, int x, int z, int indent, int maxDepth) {
|
||||
+ if (seenChunks.contains(chunkHolder)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (indent > maxDepth) {
|
||||
+ return;
|
||||
+ }
|
||||
+ seenChunks.add(chunkHolder);
|
||||
+ String indentStr = StringUtils.repeat(" ", indent);
|
||||
+ if (chunkHolder == null) {
|
||||
@ -2987,10 +2989,10 @@ index 2f95174fcc467908808ed3f2dc956bdcafdc3558..134c76065bf382912e6c28d15449db3f
|
||||
+// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
index f75f48a3d0b0bc1da3c5ae3b3cf20b64f1e8288a..0e01e5c2c008823355e370d0c9ced79130e5fb92 100644
|
||||
index 20f54baacebe98435539d4cbef41f182040db2e9..9f8c0e10e42d233a8b74ee5a71fb8fb6ea8e7480 100644
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -700,4 +700,9 @@ public final class MCUtil {
|
||||
@@ -726,4 +726,9 @@ public final class MCUtil {
|
||||
out.print(fileData);
|
||||
}
|
||||
}
|
||||
|
@ -70,10 +70,10 @@ index d53b34ba552771bf271131ce0a56ebb992ccc84c..a1b5e6b90fc93f83186cf3ebf3e15876
|
||||
|
||||
if (optional.isPresent()) {
|
||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
index 0e01e5c2c008823355e370d0c9ced79130e5fb92..d129c7f54d9f65fff6f512d8ff5f1c3866632603 100644
|
||||
index 9f8c0e10e42d233a8b74ee5a71fb8fb6ea8e7480..0d1065688b19ceca9440bc8bf2bf65910f03fa46 100644
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -602,7 +602,7 @@ public final class MCUtil {
|
||||
@@ -628,7 +628,7 @@ public final class MCUtil {
|
||||
|
||||
WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle();
|
||||
PlayerChunkMap chunkMap = world.getChunkProvider().playerChunkMap;
|
||||
|
@ -23,7 +23,7 @@ Chunks in front of the player have higher priority, to help with
|
||||
fast traveling players keep up with their movement.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java
|
||||
index a5f4cdaf06bfbb0dd957db9a1335c17b073d646d..3a4e7d8ce0a4591f56ec08ebe1c3bbb4f046b128 100644
|
||||
index b5c2e1f4a2b5fdcaa6bb01f4b3b6847cd5b73ae8..6209b33d8497ec56bbde507e523db0649c66f590 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java
|
||||
@@ -4,7 +4,10 @@ import com.destroystokyo.paper.io.PaperFileIOThread;
|
||||
@ -37,45 +37,48 @@ index a5f4cdaf06bfbb0dd957db9a1335c17b073d646d..3a4e7d8ce0a4591f56ec08ebe1c3bbb4
|
||||
import net.minecraft.server.IAsyncTaskHandler;
|
||||
import net.minecraft.server.IChunkAccess;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -125,6 +128,36 @@ public final class ChunkTaskManager {
|
||||
@@ -106,7 +109,7 @@ public final class ChunkTaskManager {
|
||||
}
|
||||
|
||||
static void dumpChunkInfo(Set<PlayerChunk> seenChunks, PlayerChunk chunkHolder, int x, int z) {
|
||||
- dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1);
|
||||
+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 4);
|
||||
}
|
||||
|
||||
static void dumpChunkInfo(Set<PlayerChunk> seenChunks, PlayerChunk chunkHolder, int x, int z, int indent, int maxDepth) {
|
||||
@@ -127,6 +130,30 @@ public final class ChunkTaskManager {
|
||||
PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getChunkStatus().toString()));
|
||||
PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + PlayerChunk.getChunkStatus(chunkHolder.getTicketLevel()));
|
||||
PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString()));
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.getCurrentPriority());
|
||||
+ synchronized (chunkHolder.neighborPriorities) {
|
||||
+ if (!chunkHolder.neighborPriorities.isEmpty()) {
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Neighbors Requested Priority: ");
|
||||
+ for (Long2ObjectMap.Entry<Integer> entry : chunkHolder.neighborPriorities.long2ObjectEntrySet()) {
|
||||
+ ChunkCoordIntPair r = new ChunkCoordIntPair(entry.getLongKey());
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " (" + r.x + "," + r.z + "): " + entry.getValue());
|
||||
+
|
||||
+ if (!chunkHolder.neighbors.isEmpty()) {
|
||||
+ if (indent >= maxDepth) {
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: (Can't show, too deeply nested)");
|
||||
+ return;
|
||||
+ }
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: ");
|
||||
+ for (PlayerChunk neighbor : chunkHolder.neighbors.keySet()) {
|
||||
+ ChunkStatus status = neighbor.getChunkHolderStatus();
|
||||
+ if (status != null && status.isAtLeastStatus(PlayerChunk.getChunkStatus(neighbor.getTicketLevel()))) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ int nx = neighbor.location.x;
|
||||
+ int nz = neighbor.location.z;
|
||||
+ if (seenChunks.contains(neighbor)) {
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)");
|
||||
+ continue;
|
||||
+ }
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":");
|
||||
+ dumpChunkInfo(seenChunks, neighbor, nx, nz, indent + 1, maxDepth);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ synchronized (chunkHolder.neighbors) {
|
||||
+ if (!chunkHolder.neighbors.isEmpty()) {
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: ");
|
||||
+ for (PlayerChunk neighbor : chunkHolder.neighbors.keySet()) {
|
||||
+ ChunkStatus status = neighbor.getChunkHolderStatus();
|
||||
+ if (status != null && status.isAtLeastStatus(PlayerChunk.getChunkStatus(neighbor.getTicketLevel()))) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ int nx = neighbor.location.x;
|
||||
+ int nz = neighbor.location.z;
|
||||
+ if (seenChunks.contains(neighbor)) {
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)");
|
||||
+ continue;
|
||||
+ }
|
||||
+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":");
|
||||
+ dumpChunkInfo(seenChunks, neighbor, nx, nz, indent + 1);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java
|
||||
index 586a20fe5c77c2ad5fa26f337a94a16e21d8b5e2..6e422836f5a013d946965a2bb807c862cfc53912 100644
|
||||
index 586a20fe5c77c2ad5fa26f337a94a16e21d8b5e2..771d879711988bbece02c8b375db786b733925b5 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkMapDistance.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java
|
||||
@@ -23,6 +23,7 @@ import java.util.concurrent.Executor;
|
||||
@ -94,7 +97,15 @@ index 586a20fe5c77c2ad5fa26f337a94a16e21d8b5e2..6e422836f5a013d946965a2bb807c862
|
||||
return !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.b()).b() : PlayerChunkMap.GOLDEN_TICKET + 1;
|
||||
}
|
||||
|
||||
@@ -107,11 +109,13 @@ public abstract class ChunkMapDistance {
|
||||
@@ -97,6 +99,7 @@ public abstract class ChunkMapDistance {
|
||||
|
||||
public boolean a(PlayerChunkMap playerchunkmap) {
|
||||
//this.f.a(); // Paper - no longer used
|
||||
+ AsyncCatcher.catchOp("DistanceManagerTick");
|
||||
this.g.a();
|
||||
int i = Integer.MAX_VALUE - this.e.a(Integer.MAX_VALUE);
|
||||
boolean flag = i != 0;
|
||||
@@ -107,11 +110,13 @@ public abstract class ChunkMapDistance {
|
||||
|
||||
// Paper start
|
||||
if (!this.pendingChunkUpdates.isEmpty()) {
|
||||
@ -108,7 +119,7 @@ index 586a20fe5c77c2ad5fa26f337a94a16e21d8b5e2..6e422836f5a013d946965a2bb807c862
|
||||
// Paper end
|
||||
return true;
|
||||
} else {
|
||||
@@ -147,14 +151,16 @@ public abstract class ChunkMapDistance {
|
||||
@@ -147,14 +152,16 @@ public abstract class ChunkMapDistance {
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
@ -126,7 +137,7 @@ index 586a20fe5c77c2ad5fa26f337a94a16e21d8b5e2..6e422836f5a013d946965a2bb807c862
|
||||
this.e.b(i, ticket.b(), true);
|
||||
}
|
||||
|
||||
@@ -162,6 +168,7 @@ public abstract class ChunkMapDistance {
|
||||
@@ -162,6 +169,7 @@ public abstract class ChunkMapDistance {
|
||||
}
|
||||
|
||||
private boolean removeTicket(long i, Ticket<?> ticket) { // CraftBukkit - void -> boolean
|
||||
@ -134,11 +145,12 @@ index 586a20fe5c77c2ad5fa26f337a94a16e21d8b5e2..6e422836f5a013d946965a2bb807c862
|
||||
ArraySetSorted<Ticket<?>> arraysetsorted = this.e(i);
|
||||
|
||||
boolean removed = false; // CraftBukkit
|
||||
@@ -182,6 +189,59 @@ public abstract class ChunkMapDistance {
|
||||
@@ -182,6 +190,82 @@ public abstract class ChunkMapDistance {
|
||||
this.addTicketAtLevel(tickettype, chunkcoordintpair, i, t0);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public static final int PRIORITY_TICKET_LEVEL = 33;
|
||||
+ public boolean markUrgent(ChunkCoordIntPair coords) {
|
||||
+ return addPriorityTicket(coords, TicketType.URGENT, 30);
|
||||
+ }
|
||||
@ -150,16 +162,38 @@ index 586a20fe5c77c2ad5fa26f337a94a16e21d8b5e2..6e422836f5a013d946965a2bb807c862
|
||||
+ private boolean addPriorityTicket(ChunkCoordIntPair coords, TicketType<ChunkCoordIntPair> ticketType, int priority) {
|
||||
+ AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket");
|
||||
+ long pair = coords.pair();
|
||||
+ Ticket<ChunkCoordIntPair> ticket = new Ticket<ChunkCoordIntPair>(ticketType, 34, coords);
|
||||
+ ticket.priority = priority;
|
||||
+
|
||||
+ this.removeTicket(pair, ticket);
|
||||
+ boolean added = this.addTicket(pair, ticket);
|
||||
+ PlayerChunk updatingChunk = chunkMap.getUpdatingChunk(pair);
|
||||
+ if (updatingChunk != null) {
|
||||
+ chunkMap.queueHolderUpdate(updatingChunk);
|
||||
+ boolean success;
|
||||
+ if (!(success = updatePriorityTicket(coords, ticketType, priority))) {
|
||||
+ Ticket<ChunkCoordIntPair> ticket = new Ticket<ChunkCoordIntPair>(ticketType, PRIORITY_TICKET_LEVEL, coords);
|
||||
+ ticket.priority = priority;
|
||||
+ success = this.addTicket(pair, ticket);
|
||||
+ }
|
||||
+ return added;
|
||||
+
|
||||
+ chunkMap.world.getChunkProvider().tickDistanceManager();
|
||||
+ PlayerChunk updatingChunk = chunkMap.getUpdatingChunk(pair);
|
||||
+ if (updatingChunk != null && updatingChunk.priorityBoost < priority) {
|
||||
+ // May not be enqueued, enqueue it if not and tick distance manager
|
||||
+ chunkMap.queueHolderUpdate(updatingChunk);
|
||||
+ chunkMap.world.getChunkProvider().tickDistanceManager();
|
||||
+ }
|
||||
+ return success;
|
||||
+ }
|
||||
+
|
||||
+ private boolean updatePriorityTicket(ChunkCoordIntPair coords, TicketType<ChunkCoordIntPair> type, int priority) {
|
||||
+ ArraySetSorted<Ticket<?>> tickets = this.tickets.get(coords.pair());
|
||||
+ if (tickets == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ for (Ticket<?> ticket : tickets) {
|
||||
+ if (ticket.getTicketType() == type) {
|
||||
+ // We only support increasing, not decreasing, too complicated
|
||||
+ ticket.priority = Math.max(ticket.priority, priority);
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public int getChunkPriority(ChunkCoordIntPair coords) {
|
||||
@ -183,18 +217,18 @@ index 586a20fe5c77c2ad5fa26f337a94a16e21d8b5e2..6e422836f5a013d946965a2bb807c862
|
||||
+
|
||||
+ public void clearPriorityTickets(ChunkCoordIntPair coords) {
|
||||
+ AsyncCatcher.catchOp("ChunkMapDistance::clearPriority");
|
||||
+ this.removeTicket(coords.pair(), new Ticket<ChunkCoordIntPair>(TicketType.PRIORITY, 34, coords));
|
||||
+ this.removeTicket(coords.pair(), new Ticket<ChunkCoordIntPair>(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords));
|
||||
+ }
|
||||
+
|
||||
+ public void clearUrgent(ChunkCoordIntPair coords) {
|
||||
+ AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent");
|
||||
+ this.removeTicket(coords.pair(), new Ticket<ChunkCoordIntPair>(TicketType.URGENT, 34, coords));
|
||||
+ this.removeTicket(coords.pair(), new Ticket<ChunkCoordIntPair>(TicketType.URGENT, PRIORITY_TICKET_LEVEL, coords));
|
||||
+ }
|
||||
+ // Paper end
|
||||
public <T> boolean addTicketAtLevel(TicketType<T> ticketType, ChunkCoordIntPair chunkcoordintpair, int level, T identifier) {
|
||||
return this.addTicket(chunkcoordintpair.pair(), new Ticket<>(ticketType, level, identifier));
|
||||
// CraftBukkit end
|
||||
@@ -397,12 +457,14 @@ public abstract class ChunkMapDistance {
|
||||
@@ -397,12 +481,14 @@ public abstract class ChunkMapDistance {
|
||||
|
||||
});
|
||||
}, i, () -> {
|
||||
@ -297,10 +331,10 @@ index 07a6fc3d88e7d44bfab7f3d6a0eef7dc132ab422..d60f659b368500e3a8c3305f99e60ffc
|
||||
for (int i = 0; i < this.inventory.getSize(); ++i) {
|
||||
ItemStack itemstack = this.inventory.getItem(i);
|
||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
index d129c7f54d9f65fff6f512d8ff5f1c3866632603..9b9536fba4a62c0153b921e678e6a9683bf2e37f 100644
|
||||
index 0d1065688b19ceca9440bc8bf2bf65910f03fa46..8a349964578e07e5ed13f801c57de68459220da9 100644
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -658,6 +658,7 @@ public final class MCUtil {
|
||||
@@ -684,6 +684,7 @@ public final class MCUtil {
|
||||
chunkData.addProperty("x", playerChunk.location.x);
|
||||
chunkData.addProperty("z", playerChunk.location.z);
|
||||
chunkData.addProperty("ticket-level", playerChunk.getTicketLevel());
|
||||
@ -309,7 +343,7 @@ index d129c7f54d9f65fff6f512d8ff5f1c3866632603..9b9536fba4a62c0153b921e678e6a968
|
||||
chunkData.addProperty("queued-for-unload", chunkMap.unloadQueue.contains(playerChunk.location.pair()));
|
||||
chunkData.addProperty("status", status == null ? "unloaded" : status.toString());
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..ee70efd4910fbbc489d4eb41342ece44f898c284 100644
|
||||
index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..b8fe42e8123e972b1ec97b048c35d90118076e66 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
@@ -26,8 +26,8 @@ public class PlayerChunk {
|
||||
@ -345,7 +379,7 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..ee70efd4910fbbc489d4eb41342ece44
|
||||
+ int priority = neighborPriority; // if we have a neighbor priority, use it
|
||||
+ int myPriority = getMyPriority();
|
||||
+
|
||||
+ if (priority == -1 || priority > myPriority) {
|
||||
+ if (priority == -1 || (ticketLevel <= 33 && priority > myPriority)) {
|
||||
+ priority = myPriority;
|
||||
+ }
|
||||
+
|
||||
@ -357,7 +391,7 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..ee70efd4910fbbc489d4eb41342ece44
|
||||
+ return 1; // Urgent - ticket level isn't always 31 so 33-30 = 3
|
||||
+ }
|
||||
+ int basePriority = ticketLevel - priorityBoost;
|
||||
+ if (ticketLevel >= 34 && priorityBoost == 0 && neighborPriorities.isEmpty()) {
|
||||
+ if (ticketLevel >= 33 && priorityBoost == 0 && (neighborPriority >= 34 || neighborPriorities.isEmpty())) {
|
||||
+ basePriority += 5;
|
||||
+ }
|
||||
+ return basePriority;
|
||||
@ -460,7 +494,7 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..ee70efd4910fbbc489d4eb41342ece44
|
||||
|
||||
public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) {
|
||||
this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size());
|
||||
@@ -165,6 +288,12 @@ public class PlayerChunk {
|
||||
@@ -165,6 +288,15 @@ public class PlayerChunk {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -469,11 +503,14 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..ee70efd4910fbbc489d4eb41342ece44
|
||||
+ return status;
|
||||
+ }
|
||||
+ return CHUNK_STATUSES.get(status.getStatusIndex() + 1);
|
||||
+ }
|
||||
+ public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) {
|
||||
+ return MCUtil.ensureMain(getStatusFutureUnchecked(chunkstatus));
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFutureUnchecked(ChunkStatus chunkstatus) {
|
||||
@@ -418,6 +547,7 @@ public class PlayerChunk {
|
||||
@@ -418,6 +550,7 @@ public class PlayerChunk {
|
||||
return this.n;
|
||||
}
|
||||
|
||||
@ -481,7 +518,23 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..ee70efd4910fbbc489d4eb41342ece44
|
||||
private void d(int i) {
|
||||
this.n = i;
|
||||
}
|
||||
@@ -507,6 +637,7 @@ public class PlayerChunk {
|
||||
@@ -436,7 +569,7 @@ public class PlayerChunk {
|
||||
// CraftBukkit start
|
||||
// ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
|
||||
if (playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && !playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) {
|
||||
- this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
||||
+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main
|
||||
Chunk chunk = (Chunk)either.left().orElse(null);
|
||||
if (chunk != null) {
|
||||
playerchunkmap.callbackExecutor.execute(() -> {
|
||||
@@ -501,12 +634,13 @@ public class PlayerChunk {
|
||||
if (!flag2 && flag3) {
|
||||
// Paper start - cache ticking ready status
|
||||
int expectCreateCount = ++this.fullChunkCreateCount;
|
||||
- this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> {
|
||||
+ this.fullChunkFuture = playerchunkmap.b(this); MCUtil.ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main
|
||||
if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) {
|
||||
// note: Here is a very good place to add callbacks to logic waiting on this.
|
||||
Chunk fullChunk = either.left().get();
|
||||
PlayerChunk.this.isFullChunkReady = true;
|
||||
fullChunk.playerChunk = PlayerChunk.this;
|
||||
@ -489,7 +542,25 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..ee70efd4910fbbc489d4eb41342ece44
|
||||
|
||||
|
||||
}
|
||||
@@ -581,8 +712,22 @@ public class PlayerChunk {
|
||||
@@ -531,7 +665,7 @@ public class PlayerChunk {
|
||||
|
||||
if (!flag4 && flag5) {
|
||||
// Paper start - cache ticking ready status
|
||||
- this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> {
|
||||
+ this.tickingFuture = playerchunkmap.a(this); MCUtil.ensureMain(this.tickingFuture).thenAccept((either) -> { // Paper - ensure main
|
||||
if (either.left().isPresent()) {
|
||||
// note: Here is a very good place to add callbacks to logic waiting on this.
|
||||
Chunk tickingChunk = either.left().get();
|
||||
@@ -562,7 +696,7 @@ public class PlayerChunk {
|
||||
}
|
||||
|
||||
// Paper start - cache ticking ready status
|
||||
- this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> {
|
||||
+ this.entityTickingFuture = playerchunkmap.b(this.location); MCUtil.ensureMain(this.entityTickingFuture).thenAccept((either) -> { // Paper ensureMain
|
||||
if (either.left().isPresent()) {
|
||||
// note: Here is a very good place to add callbacks to logic waiting on this.
|
||||
Chunk entityTickingChunk = either.left().get();
|
||||
@@ -581,13 +715,29 @@ public class PlayerChunk {
|
||||
this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage
|
||||
this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
|
||||
}
|
||||
@ -507,14 +578,22 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..ee70efd4910fbbc489d4eb41342ece44
|
||||
+ }
|
||||
+ chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority);
|
||||
+ }
|
||||
+ this.w.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority
|
||||
+ int neighborsPriority = getNeighborsPriority();
|
||||
+ this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority));
|
||||
+ if (getCurrentPriority() != priority) {
|
||||
+ this.w.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority
|
||||
+ int neighborsPriority = getNeighborsPriority();
|
||||
+ this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority));
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.oldTicketLevel = this.ticketLevel;
|
||||
// CraftBukkit start
|
||||
// ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins.
|
||||
@@ -669,6 +814,7 @@ public class PlayerChunk {
|
||||
if (!playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) {
|
||||
- this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
||||
+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main
|
||||
Chunk chunk = (Chunk)either.left().orElse(null);
|
||||
if (chunk != null) {
|
||||
playerchunkmap.callbackExecutor.execute(() -> {
|
||||
@@ -669,6 +819,7 @@ public class PlayerChunk {
|
||||
|
||||
public interface c {
|
||||
|
||||
@ -523,10 +602,34 @@ index aeca6b2b9d5d73aeb6dc639b5cad2f2533a2de44..ee70efd4910fbbc489d4eb41342ece44
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
index f1c3cb3ff8961bc688a1d38cd79b999e539cf866..7b4700bdef3a4dc89fd8ba0c98d76c63ad18d5de 100644
|
||||
index f1c3cb3ff8961bc688a1d38cd79b999e539cf866..8fa1d5f7af6920a5fc63347c3a5dcfc5948d50c4 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -375,6 +375,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
@@ -50,6 +50,7 @@ import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bukkit.entity.Player; // CraftBukkit
|
||||
+import org.spigotmc.AsyncCatcher;
|
||||
|
||||
public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
||||
@@ -123,6 +124,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
+ AsyncCatcher.catchOp("Callback Executor execute");
|
||||
if (queued == null) {
|
||||
queued = new java.util.ArrayDeque<>();
|
||||
}
|
||||
@@ -131,6 +133,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
+ AsyncCatcher.catchOp("Callback Executor run");
|
||||
if (queued == null) {
|
||||
return;
|
||||
}
|
||||
@@ -375,6 +378,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
|
||||
(EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
|
||||
com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> newState) -> {
|
||||
@ -534,7 +637,7 @@ index f1c3cb3ff8961bc688a1d38cd79b999e539cf866..7b4700bdef3a4dc89fd8ba0c98d76c63
|
||||
if (newState.size() != 1) {
|
||||
return;
|
||||
}
|
||||
@@ -393,7 +394,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
@@ -393,7 +397,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
}
|
||||
ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ);
|
||||
PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update
|
||||
@ -544,20 +647,28 @@ index f1c3cb3ff8961bc688a1d38cd79b999e539cf866..7b4700bdef3a4dc89fd8ba0c98d76c63
|
||||
this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets);
|
||||
this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
|
||||
(EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
|
||||
@@ -410,6 +412,77 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
@@ -410,6 +415,85 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
});
|
||||
// Paper end - no-tick view distance
|
||||
}
|
||||
+ // Paper start - Chunk Prioritization
|
||||
+ private static final int[][] neighborMatrix = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
|
||||
+ public void queueHolderUpdate(PlayerChunk playerchunk) {
|
||||
+ executor.execute(() -> {
|
||||
+ if (isUnloading(playerchunk)) return; // unloaded
|
||||
+ Runnable runnable = () -> {
|
||||
+ if (isUnloading(playerchunk)) {
|
||||
+ return; // unloaded
|
||||
+ }
|
||||
+ chunkDistanceManager.pendingChunkUpdates.add(playerchunk);
|
||||
+ if (!chunkDistanceManager.pollingPendingChunkUpdates) {
|
||||
+ world.getChunkProvider().tickDistanceManager();
|
||||
+ }
|
||||
+ });
|
||||
+ };
|
||||
+ if (MCUtil.isMainThread()) {
|
||||
+ // We can't use executor here because it will not execute tasks if its currently in the middle of executing tasks...
|
||||
+ runnable.run();
|
||||
+ } else {
|
||||
+ executor.execute(runnable);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public boolean isUnloading(PlayerChunk playerchunk) {
|
||||
@ -622,7 +733,7 @@ index f1c3cb3ff8961bc688a1d38cd79b999e539cf866..7b4700bdef3a4dc89fd8ba0c98d76c63
|
||||
|
||||
public void updatePlayerMobTypeMap(Entity entity) {
|
||||
if (!this.world.paperConfig.perPlayerMobSpawns) {
|
||||
@@ -539,6 +612,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
@@ -539,6 +623,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
List<CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>>> list = Lists.newArrayList();
|
||||
int j = chunkcoordintpair.x;
|
||||
int k = chunkcoordintpair.z;
|
||||
@ -630,7 +741,7 @@ index f1c3cb3ff8961bc688a1d38cd79b999e539cf866..7b4700bdef3a4dc89fd8ba0c98d76c63
|
||||
|
||||
for (int l = -i; l <= i; ++l) {
|
||||
for (int i1 = -i; i1 <= i; ++i1) {
|
||||
@@ -557,6 +631,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
@@ -557,6 +642,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
||||
ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(j1);
|
||||
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture = playerchunk.a(chunkstatus, this);
|
||||
@ -645,7 +756,7 @@ index f1c3cb3ff8961bc688a1d38cd79b999e539cf866..7b4700bdef3a4dc89fd8ba0c98d76c63
|
||||
|
||||
list.add(completablefuture);
|
||||
}
|
||||
@@ -1020,14 +1102,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
@@ -1020,14 +1113,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
};
|
||||
|
||||
CompletableFuture<NBTTagCompound> chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z);
|
||||
@ -673,7 +784,7 @@ index f1c3cb3ff8961bc688a1d38cd79b999e539cf866..7b4700bdef3a4dc89fd8ba0c98d76c63
|
||||
return ret;
|
||||
// Paper end
|
||||
}
|
||||
@@ -1156,7 +1246,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
@@ -1156,7 +1257,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
long i = playerchunk.i().pair();
|
||||
|
||||
playerchunk.getClass();
|
In neuem Issue referenzieren
Einen Benutzer sperren