Implement Chunk Priority / Urgency System for Chunks

Mark chunks that are blocking main thread for world generation as urgent

Implements a general priority system so that chunks that are sorted in
the generator queues can prioritize certain chunks over another.

Urgent chunks will jump to the front of the line, ensuring that a
sync chunk load on an ungenerated chunk does not lag the server for
a long period of time if the servers generator queues are filled with
lots of chunks already.

This massively reduces the lag spikes from sync chunk gens.

Then we further prioritize loading order so nearby chunks have higher
priority than distant chunks, reducing the pressure a high no tick
view distance holds on you.

Chunks in front of the player have higher priority, to help with
fast traveling players keep up with their movement.

This commit also improves single core cpu scenarios in that we will
now automatically disable Async Chunks as well as Minecrafts thread
pool.

It is never recommended to use async chunks on a single CPU as context
switching will be slower than just running it all on main.

This also bumps the number of server worker threads by default too.
Mojang does not utilize the workers in an effecient manner, resulting
in them using barely any sustained CPU.

So give it more workers so more chunks can be processed concurrently

This change also improves urgent chunk loading, so players flying into
unloaded chunks will hurt a little bit less (but still hurt)

Ping #3395 #3363 (Not marking as closed, we need to make prevent moving work)
This commit is contained in:
Aikar 2020-05-19 04:01:53 -04:00
parent c8028d1c76
commit 614a664bd3
No known key found for this signature in database
GPG Key ID: 401ADFC9891FAAFE
36 changed files with 697 additions and 424 deletions

View File

@ -1095,10 +1095,10 @@ index 0000000000000000000000000000000000000000..c3b936f54b3fff418c265639ef223292
+}
diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..c71ed11834557f71504de5038d3bb593824f6f95
index 0000000000000000000000000000000000000000..1330df2c1d3c4f52dad0adeb169409eb412814ab
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java
@@ -0,0 +1,439 @@
@@ -0,0 +1,453 @@
+package com.destroystokyo.paper.util.misc;
+
+import com.destroystokyo.paper.util.math.IntegerUtil;
@ -1132,6 +1132,7 @@ index 0000000000000000000000000000000000000000..c71ed11834557f71504de5038d3bb593
+
+ protected final ChangeCallback<E> addCallback;
+ protected final ChangeCallback<E> removeCallback;
+ protected final ChangeSourceCallback<E> changeSourceCallback;
+
+ public AreaMap() {
+ this(new PooledLinkedHashSets<>());
@ -1143,9 +1144,13 @@ index 0000000000000000000000000000000000000000..c71ed11834557f71504de5038d3bb593
+ }
+
+ public AreaMap(final PooledLinkedHashSets<E> pooledHashSets, final ChangeCallback<E> addCallback, final ChangeCallback<E> removeCallback) {
+ this(pooledHashSets, addCallback, removeCallback, null);
+ }
+ public AreaMap(final PooledLinkedHashSets<E> pooledHashSets, final ChangeCallback<E> addCallback, final ChangeCallback<E> removeCallback, final ChangeSourceCallback<E> changeSourceCallback) {
+ this.pooledHashSets = pooledHashSets;
+ this.addCallback = addCallback;
+ this.removeCallback = removeCallback;
+ this.changeSourceCallback = changeSourceCallback;
+ }
+
+ @Nullable
@ -1208,7 +1213,11 @@ index 0000000000000000000000000000000000000000..c71ed11834557f71504de5038d3bb593
+ }
+
+ // called after the distance map updates
+ protected void updateObjectCallback(final E Object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) {}
+ protected void updateObjectCallback(final E Object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) {
+ if (newPosition != oldPosition && this.changeSourceCallback != null) {
+ this.changeSourceCallback.accept(Object, oldPosition, newPosition);
+ }
+ }
+
+ public final boolean add(final E object, final int chunkX, final int chunkZ, final int viewDistance) {
+ final int oldViewDistance = this.objectToViewDistance.putIfAbsent(object, viewDistance);
@ -1537,6 +1546,11 @@ index 0000000000000000000000000000000000000000..c71ed11834557f71504de5038d3bb593
+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<E> newState);
+
+ }
+
+ @FunctionalInterface
+ public static interface ChangeSourceCallback<E> {
+ void accept(final E object, final long prevPos, final long newPos);
+ }
+}
diff --git a/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java
new file mode 100644
@ -1721,10 +1735,10 @@ index 0000000000000000000000000000000000000000..3f86c1ad43782bdc56be6c0eca053311
+}
diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a552a87abf5cc6fc0e10bf93de3cf8168d57cb5
index 0000000000000000000000000000000000000000..b1396f405d041fc3ca1f7ce1e0f884a3cfb8b96e
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java
@@ -0,0 +1,27 @@
@@ -0,0 +1,32 @@
+package com.destroystokyo.paper.util.misc;
+
+import net.minecraft.server.EntityPlayer;
@ -1744,7 +1758,12 @@ index 0000000000000000000000000000000000000000..8a552a87abf5cc6fc0e10bf93de3cf81
+
+ public PlayerAreaMap(final PooledLinkedHashSets<EntityPlayer> pooledHashSets, final ChangeCallback<EntityPlayer> addCallback,
+ final ChangeCallback<EntityPlayer> removeCallback) {
+ super(pooledHashSets, addCallback, removeCallback);
+ this(pooledHashSets, addCallback, removeCallback, null);
+ }
+
+ public PlayerAreaMap(final PooledLinkedHashSets<EntityPlayer> pooledHashSets, final ChangeCallback<EntityPlayer> addCallback,
+ final ChangeCallback<EntityPlayer> removeCallback, final ChangeSourceCallback<EntityPlayer> changeSourceCallback) {
+ super(pooledHashSets, addCallback, removeCallback, changeSourceCallback);
+ }
+
+ @Override
@ -3335,10 +3354,10 @@ 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..7164f46516bdf49ed52062f2d72f33418506bae0
index 0000000000000000000000000000000000000000..b40cd1fad5c9e2f0f85c87a559caf2b780814017
--- /dev/null
+++ b/src/main/java/net/minecraft/server/MCUtil.java
@@ -0,0 +1,473 @@
@@ -0,0 +1,487 @@
+package net.minecraft.server;
+
+import com.destroystokyo.paper.block.TargetBlockInfo;
@ -3467,6 +3486,20 @@ index 0000000000000000000000000000000000000000..7164f46516bdf49ed52062f2d72f3341
+ return x < (double)truncated ? truncated - 1 : truncated;
+ }
+
+ public static float normalizeYaw(float f) {
+ float f1 = f % 360.0F;
+
+ if (f1 >= 180.0F) {
+ f1 -= 360.0F;
+ }
+
+ if (f1 < -180.0F) {
+ f1 += 360.0F;
+ }
+
+ return f1;
+ }
+
+ public static int fastFloor(float x) {
+ int truncated = (int)x;
+ return x < (double)truncated ? truncated - 1 : truncated;

View File

@ -5,7 +5,7 @@ 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 7164f46516bdf49ed52062f2d72f33418506bae0..87bd51ab1b844e05ecd3d9d2555841554976023c 100644
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;
@ -16,7 +16,7 @@ index 7164f46516bdf49ed52062f2d72f33418506bae0..87bd51ab1b844e05ecd3d9d255584155
import org.bukkit.Location;
import org.bukkit.block.BlockFace;
import org.bukkit.craftbukkit.CraftWorld;
@@ -181,6 +182,24 @@ public final class MCUtil {
@@ -195,6 +196,24 @@ public final class MCUtil {
private MCUtil() {}

View File

@ -403,7 +403,7 @@ index 0000000000000000000000000000000000000000..3aceb0ea8a1a3ed94dd8a9e954c52ecd
+ }
+}
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index 87bd51ab1b844e05ecd3d9d2555841554976023c..37b8257552efd0d66a020f0b5007514f2ac890cd 100644
index f9a7a1e9eea67bafb85c0ed88e96abb8e45f6c81..8ca1a4719d934db31d57b34cf7050acc5a1a7048 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/src/main/java/net/minecraft/server/MCUtil.java
@@ -1,7 +1,10 @@
@ -417,7 +417,7 @@ index 87bd51ab1b844e05ecd3d9d2555841554976023c..37b8257552efd0d66a020f0b5007514f
import org.apache.commons.lang.exception.ExceptionUtils;
import org.bukkit.Location;
import org.bukkit.block.BlockFace;
@@ -315,6 +318,10 @@ public final class MCUtil {
@@ -329,6 +332,10 @@ public final class MCUtil {
return run.get();
}

View File

@ -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 37b8257552efd0d66a020f0b5007514f2ac890cd..be20d770df41a656cf2aabfec87e0bdc639053f4 100644
index 8ca1a4719d934db31d57b34cf7050acc5a1a7048..206d04dcce1d7d074cf7151a083bdc626b0b8e07 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/src/main/java/net/minecraft/server/MCUtil.java
@@ -496,4 +496,19 @@ public final class MCUtil {
@@ -510,4 +510,19 @@ public final class MCUtil {
return null;
}
}

View File

@ -5,15 +5,16 @@ Subject: [PATCH] Use more reasonable thread count default for bootstrap
diff --git a/src/main/java/net/minecraft/server/SystemUtils.java b/src/main/java/net/minecraft/server/SystemUtils.java
index 7e224ebeff3bf34270df173a47b08d3290c00670..dc6d030621b66e43edf3a148f0eca43382383705 100644
index 7e224ebeff3bf34270df173a47b08d3290c00670..60d7c06d4c5bd054a411c915af3ae685df24ccd4 100644
--- a/src/main/java/net/minecraft/server/SystemUtils.java
+++ b/src/main/java/net/minecraft/server/SystemUtils.java
@@ -66,7 +66,7 @@ public class SystemUtils {
@@ -66,7 +66,8 @@ public class SystemUtils {
}
private static ExecutorService k() {
- int i = MathHelper.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7);
+ int i = Math.min(6, Math.max(Runtime.getRuntime().availableProcessors() - 2, 2)); // Paper - use more reasonable default - 2 is hard minimum to avoid using unlimited threads
+ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 3)); // Paper - use more reasonable default - 2 is hard minimum to avoid using unlimited threads
+ i = Integer.getInteger("Paper.WorkerThreadCount", i); // Paper - allow overriding
Object object;
if (i <= 0) {

View File

@ -198,7 +198,7 @@ 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 be20d770df41a656cf2aabfec87e0bdc639053f4..de8b8f54cd906c1154a6790b9220d3e0976c74bd 100644
index 206d04dcce1d7d074cf7151a083bdc626b0b8e07..f75f48a3d0b0bc1da3c5ae3b3cf20b64f1e8288a 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;
@ -227,7 +227,7 @@ index be20d770df41a656cf2aabfec87e0bdc639053f4..de8b8f54cd906c1154a6790b9220d3e0
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
@@ -511,4 +520,170 @@ public final class MCUtil {
@@ -525,4 +534,170 @@ public final class MCUtil {
return null;
}

View File

@ -161,7 +161,7 @@ index fa1c920ea6092259149f9e7f9cd7cc1ed27bf338..98acbfa44dd9042b26fdf719d7748f92
public static Timing getTickList(WorldServer worldserver, String timingsType) {
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index dbd14399707cdd43f98af40191be8ff3e76edf43..f4836e2da1061e7aa62ddb01c8ca7b3467b18415 100644
index dbd14399707cdd43f98af40191be8ff3e76edf43..74295466e53db06d0d019a13768f3575ac61d699 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -1,5 +1,6 @@
@ -171,7 +171,7 @@ index dbd14399707cdd43f98af40191be8ff3e76edf43..f4836e2da1061e7aa62ddb01c8ca7b34
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
@@ -367,4 +368,50 @@ public class PaperConfig {
@@ -367,4 +368,54 @@ public class PaperConfig {
maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize);
maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier);
}
@ -202,8 +202,12 @@ index dbd14399707cdd43f98af40191be8ff3e76edf43..f4836e2da1061e7aa62ddb01c8ca7b34
+
+ asyncChunks = getBoolean("settings.async-chunks.enable", true);
+ int threads = getInt("settings.async-chunks.threads", -1);
+ int cpus = Runtime.getRuntime().availableProcessors();
+ if (threads <= 0) {
+ threads = (int) Math.min(Integer.getInteger("paper.maxChunkThreads", 8), Math.max(1, Runtime.getRuntime().availableProcessors() - 1));
+ threads = (int) Math.min(Integer.getInteger("paper.maxChunkThreads", 8), Math.max(1, cpus - 1));
+ }
+ if (cpus == 1 && !Boolean.getBoolean("Paper.allowAsyncChunksSingleCore")) {
+ asyncChunks = false;
+ }
+
+ // Let Shared Host set some limits
@ -2927,10 +2931,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 de8b8f54cd906c1154a6790b9220d3e0976c74bd..f8a1f0b96f2eb8535e3080db979bb383d5a18a11 100644
index f75f48a3d0b0bc1da3c5ae3b3cf20b64f1e8288a..0e01e5c2c008823355e370d0c9ced79130e5fb92 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/src/main/java/net/minecraft/server/MCUtil.java
@@ -686,4 +686,9 @@ public final class MCUtil {
@@ -700,4 +700,9 @@ public final class MCUtil {
out.print(fileData);
}
}
@ -3845,6 +3849,19 @@ index db9f0196bda4c987de6cf63eea437b7154d47b57..a6d8ef5eb44f3f851a3a1be4032ca21a
}
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/server/SystemUtils.java b/src/main/java/net/minecraft/server/SystemUtils.java
index 60d7c06d4c5bd054a411c915af3ae685df24ccd4..47dbcb70a6b41438a5bf3196495cfdaf02bd2b74 100644
--- a/src/main/java/net/minecraft/server/SystemUtils.java
+++ b/src/main/java/net/minecraft/server/SystemUtils.java
@@ -70,7 +70,7 @@ public class SystemUtils {
i = Integer.getInteger("Paper.WorkerThreadCount", i); // Paper - allow overriding
Object object;
- if (i <= 0) {
+ if (i <= 0 || (Runtime.getRuntime().availableProcessors() == 1 && !Boolean.getBoolean("Paper.allowAsyncChunksSingleCore"))) { // Paper - disable server worker queue if single core system
object = MoreExecutors.newDirectExecutorService();
} else {
object = new ForkJoinPool(i, (forkjoinpool) -> {
diff --git a/src/main/java/net/minecraft/server/TicketType.java b/src/main/java/net/minecraft/server/TicketType.java
index 75ab9f185b3231113dfa387c956a707b403bb2db..8055f5998213ab1c6c10d03d88d2b14d220a5e40 100644
--- a/src/main/java/net/minecraft/server/TicketType.java

View File

@ -63,10 +63,10 @@ index fd998e4fb1534690a2ef8c1bca55e0ae9fe855f9..8f849d83d08b39f1cd9184f484a2089a
if (optional.isPresent()) {
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index f8a1f0b96f2eb8535e3080db979bb383d5a18a11..88b41b1d0c2045d01449256a5875ae73765c5595 100644
index 0e01e5c2c008823355e370d0c9ced79130e5fb92..d129c7f54d9f65fff6f512d8ff5f1c3866632603 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/src/main/java/net/minecraft/server/MCUtil.java
@@ -588,7 +588,7 @@ public final class MCUtil {
@@ -602,7 +602,7 @@ public final class MCUtil {
WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle();
PlayerChunkMap chunkMap = world.getChunkProvider().playerChunkMap;

View File

@ -42,10 +42,10 @@ index 223d3b1125d0781758c45c6b469e6cccd13f187a..37341d2d2e7010b403708b6fc52524e8
public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions");
public static final Timing connectionTimer = Timings.ofSafe("Connection Handler");
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 647f6fc8efb350fbd0bc4c40358a998f8b89b96a..9f1662ece533f5ea744662b718e2d89ace3107fb 100644
index f1b41e16c8ce8323a896339c5d822f8ff7d8f7e6..f8f225e18fa38cad917f52a379233e0a7a869b07 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -421,4 +421,9 @@ public class PaperConfig {
@@ -425,4 +425,9 @@ public class PaperConfig {
log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag.");
}
}
@ -56,7 +56,7 @@ index 647f6fc8efb350fbd0bc4c40358a998f8b89b96a..9f1662ece533f5ea744662b718e2d89a
+ }
}
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 8f849d83d08b39f1cd9184f484a2089a7a3124ef..5806ca545191e609bab04e522e358948cf32b21c 100644
index 8f849d83d08b39f1cd9184f484a2089a7a3124ef..377d554553ce81f66207541d963f826867e66592 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -688,6 +688,7 @@ public class ChunkProviderServer extends IChunkProvider {
@ -116,7 +116,7 @@ index 8f849d83d08b39f1cd9184f484a2089a7a3124ef..5806ca545191e609bab04e522e358948
+ //noinspection StatementWithEmptyBody
+ while (pollChunkLoadTasks()) {}
+
+ if (System.nanoTime() - lastMidTickChunkTask < 1000000) {
+ if (System.nanoTime() - lastMidTickChunkTask < 200000) {
+ return;
+ }
+
@ -135,7 +135,7 @@ index 8f849d83d08b39f1cd9184f484a2089a7a3124ef..5806ca545191e609bab04e522e358948
protected boolean executeNext() {
// CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index f9faa30ef914b1dd2dada9b7d89e80b34d2f1d0d..97cca4495a8dab4434e917a5d94192a28581925c 100644
index f9faa30ef914b1dd2dada9b7d89e80b34d2f1d0d..f9694d188cc61f123fca4d54bf14fb7466b06a6c 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -910,6 +910,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@ -163,7 +163,7 @@ index f9faa30ef914b1dd2dada9b7d89e80b34d2f1d0d..97cca4495a8dab4434e917a5d94192a2
+ public int midTickChunksTasksRan = 0;
+ private long midTickLastRan = 0;
+ public void midTickLoadChunks() {
+ if (!isMainThread() || System.nanoTime() - midTickLastRan < 250000) {
+ if (!isMainThread() || System.nanoTime() - midTickLastRan < 200000) {
+ // only check once per 0.25ms incase this code is called in a hot method
+ return;
+ }

View File

@ -1,312 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sat, 11 Apr 2020 03:56:07 -0400
Subject: [PATCH] Implement Chunk Priority / Urgency System for World Gen
Mark chunks that are blocking main thread for world generation as urgent
Implements a general priority system so that chunks that are sorted in
the generator queues can prioritize certain chunks over another.
Urgent chunks will jump to the front of the line, ensuring that a
sync chunk load on an ungenerated chunk does not lag the server for
a long period of time if the servers generator queues are filled with
lots of chunks already.
This massively reduces the lag spikes from sync chunk gens.
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 5806ca545191e609bab04e522e358948cf32b21c..4cef51b68984f83b8153ee1f017a2c597194df19 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -469,6 +469,10 @@ public class ChunkProviderServer extends IChunkProvider {
if (!completablefuture.isDone()) { // Paper
// Paper start - async chunk io/loading
+ PlayerChunk playerChunk = this.getChunk(ChunkCoordIntPair.pair(x, z));
+ if (playerChunk != null) {
+ playerChunk.markChunkUrgent(chunkstatus);
+ }
this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY);
com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z);
// Paper end
@@ -478,6 +482,10 @@ public class ChunkProviderServer extends IChunkProvider {
com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug
this.world.timings.syncChunkLoad.stopTiming(); // Paper
} // Paper
+ PlayerChunk playerChunk = this.getChunk(ChunkCoordIntPair.pair(x, z));
+ if (playerChunk != null) {
+ playerChunk.clearChunkUrgent();
+ }
ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> {
return ichunkaccess1;
}, (playerchunk_failure) -> {
@@ -541,6 +549,11 @@ public class ChunkProviderServer extends IChunkProvider {
}
}
}
+ // Paper start
+ if (playerchunk != null && isUrgent) {
+ playerchunk.markChunkUrgent(chunkstatus);
+ }
+ // Paper end
return this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap);
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 3d610e41969768da0d2848fa1ae195035ccfd660..a6e7bcf79df9f4ad5b0a779f3eecf85f121bedc8 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -43,6 +43,111 @@ public class PlayerChunk {
long lastAutoSaveTime; // Paper - incremental autosave
long inactiveTimeStart; // Paper - incremental autosave
+ // Paper start - Chunk gen/load priority system
+ volatile int chunkPriority = 0;
+ volatile boolean isUrgent = false;
+ final java.util.List<PlayerChunk> urgentNeighbors = new java.util.ArrayList<>();
+ volatile PlayerChunk rootUrgentOriginator;
+ volatile PlayerChunk urgentOriginator;
+ public void onNeighborRequest(PlayerChunk neighbor, ChunkStatus status) {
+ if (isUrgent && !neighbor.isUrgent && !java.util.Objects.equals(neighbor, rootUrgentOriginator) && !java.util.Objects.equals(neighbor, urgentOriginator)) {
+ synchronized (this.urgentNeighbors) {
+ if (!neighbor.isUrgent) {
+ neighbor.markChunkUrgent(status, this.rootUrgentOriginator, this);
+ this.urgentNeighbors.add(neighbor);
+ }
+ }
+ }
+ }
+
+ public void onNeighborsDone() {
+ List<PlayerChunk> urgentNeighbors;
+ synchronized (this.urgentNeighbors) {
+ urgentNeighbors = new java.util.ArrayList<>(this.urgentNeighbors);
+ this.urgentNeighbors.clear();
+ }
+ for (PlayerChunk urgentNeighbor : urgentNeighbors) {
+ if (urgentNeighbor != null) {
+ urgentNeighbor.clearChunkUrgent(this);
+ }
+ }
+ }
+
+ public void clearChunkUrgent() {
+ clearChunkUrgent(this);
+ }
+ public void clearChunkUrgent(PlayerChunk requester) {
+ if (this.isUrgent && java.util.Objects.equals(requester, this.urgentOriginator)) {
+ this.isUrgent = false;
+ this.urgentOriginator = null;
+ this.rootUrgentOriginator = null;
+ this.onNeighborsDone();
+ }
+ }
+
+ public void markChunkUrgent(ChunkStatus targetStatus) {
+ this.markChunkUrgent(targetStatus, this , this);
+ }
+ public void markChunkUrgent(ChunkStatus targetStatus, PlayerChunk rootUrgentOriginator, PlayerChunk urgentOriginator) {
+ if (!this.isUrgent) {
+ this.rootUrgentOriginator = rootUrgentOriginator;
+ this.urgentOriginator = urgentOriginator;
+ this.isUrgent = true;
+ int x = location.x;
+ int z = location.z;
+ IChunkAccess chunk = getAvailableChunkNow();
+ final ChunkStatus chunkCurrentStatus = chunk == null ? null : chunk.getChunkStatus();
+ final ChunkStatus completedStatus = this.getChunkHolderStatus();
+ final ChunkStatus nextStatus = getNextStatus(completedStatus != null ? completedStatus : ChunkStatus.EMPTY);
+
+ if (chunkCurrentStatus == null || completedStatus == null) {
+ this.chunkMap.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY);
+ // next status is empty, empty has no neighbours needing loading
+ return;
+ }
+
+ if (!targetStatus.isAtLeastStatus(nextStatus)) {
+ // we don't want a status greater-than the one we already have, don't prioritise these loads - they will get in the way
+ return;
+ }
+
+ // at this point we want a chunk that has a status higher than the one we have already completed
+
+ // does the next status need neighbours at all?
+ final int requiredNeighbours = nextStatus.getNeighborRadius();
+ if (requiredNeighbours <= 0) {
+ // no it doesn't, we're done here. we've already prioritised this chunk, no neighbours need prioritising
+ return;
+ }
+
+ // even though we might want a higher status than targetFinalStatus, we cannot queue neighbours for it - we
+ // instead use the current chunk status in progress (nextCompletedStatus) to ensure we aren't waiting on
+ // unprioritised logic for the next status to complete
+
+ for (int cx = -requiredNeighbours; cx <= requiredNeighbours; ++cx) {
+ for (int cz = -requiredNeighbours; cz <= requiredNeighbours; ++cz) {
+ if (cx == 0 && cz == 0) {
+ continue;
+ }
+ PlayerChunk neighbor = this.chunkMap.getUpdatingChunk(ChunkCoordIntPair.asLong(x + cz, z + cx));
+ if (neighbor == null) {
+ continue;
+ }
+
+ IChunkAccess neighborChunk = neighbor.getAvailableChunkNow();
+ ChunkStatus neededStatus = this.chunkMap.getNeededStatusByRadius(nextStatus, Math.max(Math.abs(cx), Math.abs(cz)));
+ ChunkStatus neighborCurrentStatus = neighborChunk != null ? neighborChunk.getChunkStatus() : ChunkStatus.EMPTY;
+ if (nextStatus == ChunkStatus.LIGHT || !neighborCurrentStatus.isAtLeastStatus(neededStatus)) {
+ // we don't need to gen neighbours if our current chunk's status has already gone through the gen
+ // light is always an exception, no matter what if we go through light we need its neighbours - the light engine requires them
+ this.onNeighborRequest(neighbor, neededStatus);
+ }
+ }
+ }
+ }
+ }
+ // Paper end
+
public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) {
this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size());
this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
@@ -139,6 +244,12 @@ public class PlayerChunk {
}
return null;
}
+ public static ChunkStatus getNextStatus(ChunkStatus status) {
+ if (status == ChunkStatus.FULL) {
+ return status;
+ }
+ return CHUNK_STATUSES.get(status.getStatusIndex() + 1);
+ }
// Paper end
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFutureUnchecked(ChunkStatus chunkstatus) {
@@ -349,7 +460,7 @@ public class PlayerChunk {
}
public int k() {
- return this.n;
+ return Math.max(1, this.n - this.chunkPriority - (isUrgent ? 20 : 0)); // Paper - allow modifying priority, subtracts 20 if urgent
}
private void d(int i) {
@@ -441,6 +552,7 @@ public class PlayerChunk {
Chunk fullChunk = either.left().get();
PlayerChunk.this.isFullChunkReady = true;
fullChunk.playerChunk = PlayerChunk.this;
+ this.clearChunkUrgent();
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 00f26ae23da65453073fc06ffec8a349ef28dd7e..6c178492b75134ba25b7730273bb550b693a7e4a 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -291,6 +291,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;
+ PlayerChunk requestingNeighbor = this.requestingNeighbor; // Paper
for (int l = -i; l <= i; ++l) {
for (int i1 = -i; i1 <= i; ++i1) {
@@ -308,6 +309,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(j1);
+ if (requestingNeighbor != null) requestingNeighbor.onNeighborRequest(playerchunk, chunkstatus); // Paper
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture = playerchunk.a(chunkstatus, this);
list.add(completablefuture);
@@ -771,23 +773,28 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
};
CompletableFuture<NBTTagCompound> chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z);
+ PlayerChunk playerChunk = getUpdatingChunk(chunkcoordintpair.pair());
+ boolean isBlockingMain = playerChunk != null && playerChunk.isUrgent;
+ int priority = isBlockingMain ? com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY : com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY;
if (chunkSaveFuture != null) {
- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z,
- com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture);
- this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY);
+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isBlockingMain, chunkSaveFuture);
} else {
- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z,
- com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false);
+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isBlockingMain);
}
+ this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, priority);
return ret;
// Paper end
}
+ private PlayerChunk requestingNeighbor; // Paper
private CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> b(PlayerChunk playerchunk, ChunkStatus chunkstatus) {
ChunkCoordIntPair chunkcoordintpair = playerchunk.i();
+ PlayerChunk prevNeighbor = requestingNeighbor; // Paper
+ this.requestingNeighbor = playerchunk; // Paper
CompletableFuture<Either<List<IChunkAccess>, PlayerChunk.Failure>> completablefuture = this.a(chunkcoordintpair, chunkstatus.f(), (i) -> {
return this.a(chunkstatus, i);
});
+ this.requestingNeighbor = prevNeighbor; // Paper
this.world.getMethodProfiler().c(() -> {
return "chunkGenerate " + chunkstatus.d();
@@ -815,6 +822,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return CompletableFuture.completedFuture(Either.right(playerchunk_failure));
});
}, (runnable) -> {
+ playerchunk.onNeighborsDone(); // Paper
this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); // CraftBukkit - decompile error
});
}
@@ -827,6 +835,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}));
}
+ public ChunkStatus getNeededStatusByRadius(ChunkStatus chunkstatus, int i) { return a(chunkstatus, i); } // Paper - OBFHELPER
private ChunkStatus a(ChunkStatus chunkstatus, int i) {
ChunkStatus chunkstatus1;
@@ -951,9 +960,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
public CompletableFuture<Either<Chunk, PlayerChunk.Failure>> a(PlayerChunk playerchunk) {
ChunkCoordIntPair chunkcoordintpair = playerchunk.i();
+ PlayerChunk prevNeighbor = this.requestingNeighbor; // Paper
+ this.requestingNeighbor = playerchunk; // Paper
CompletableFuture<Either<List<IChunkAccess>, PlayerChunk.Failure>> completablefuture = this.a(chunkcoordintpair, 1, (i) -> {
return ChunkStatus.FULL;
});
+ this.requestingNeighbor = prevNeighbor; // Paper
CompletableFuture<Either<Chunk, PlayerChunk.Failure>> completablefuture1 = completablefuture.thenApplyAsync((either) -> {
return either.flatMap((list) -> {
Chunk chunk = (Chunk) list.get(list.size() / 2);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index b184f8ed8ce86965c3ef9aef179126a4d69275e8..64c643aa15d6ea68f9dad3104cc41e412255cee3 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1,5 +1,6 @@
package org.bukkit.craftbukkit;
+import com.destroystokyo.paper.io.PrioritizedTaskQueue;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -2472,10 +2473,15 @@ public class CraftWorld implements World {
}
}
- return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> {
+ CompletableFuture<Chunk> future = this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> {
net.minecraft.server.Chunk chunk = (net.minecraft.server.Chunk) either.left().orElse(null);
return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk());
}, MinecraftServer.getServer());
+ if (urgent) {
+ world.asyncChunkTaskManager.raisePriority(x, z, PrioritizedTaskQueue.HIGHEST_PRIORITY);
+ }
+ return future;
+
}
// Paper end

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Delay unsafe actions until after entity ticking is done
This will help prevent many cases of unregistering entities during entity ticking
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 9b5f24c262edb82a424385f8f3cb6aa506c0dcd9..b3785775ecd8e3c13e7829f641f2c1b5fd0d9d47 100644
index a4a2882d32d0167738f8367209dbfd3ca4f5b953..9e32e2db10f5faaa3c5f4adc5cbc2c1a2e4d3073 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -60,6 +60,16 @@ public class WorldServer extends World {

View File

@ -87,7 +87,7 @@ index cfe43e882e524b6ab3d9702e81269c97e6b75eba..2632c7c3ec77918be7979f2aa49209e5
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 10f7283cbf6f7763186ca0dcc9eb6ba8574264a7..4e9f331975e9f1f754875db25a6c6f99ed099327 100644
index b701db638370c0d07d5be0f61c6cbf19168cde8e..4ea3468614df36e1c148a44bb15d2201da281df3 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -144,6 +144,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@ -211,7 +211,7 @@ index 10f7283cbf6f7763186ca0dcc9eb6ba8574264a7..4e9f331975e9f1f754875db25a6c6f99
}
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index e089e619a9616128c85b67497f6643262d2aeef9..aed1e9b3d0fc270e77d05dcf590683e38459da7e 100644
index ab2831830ad3a4cec0671d189e0534c843b47f5e..78040e83899f1ef1a6d5c456beb9d13959307c18 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -400,7 +400,7 @@ public abstract class PlayerList {
@ -224,10 +224,10 @@ index e089e619a9616128c85b67497f6643262d2aeef9..aed1e9b3d0fc270e77d05dcf590683e3
// Paper start - Remove from collideRule team if needed
diff --git a/src/main/java/net/minecraft/server/SystemUtils.java b/src/main/java/net/minecraft/server/SystemUtils.java
index dc6d030621b66e43edf3a148f0eca43382383705..bc8b9046605657e0be5858ae9cf14d7793256983 100644
index 47dbcb70a6b41438a5bf3196495cfdaf02bd2b74..0d12c3657304ccf7ab25a2614c380ee73fdad1fb 100644
--- a/src/main/java/net/minecraft/server/SystemUtils.java
+++ b/src/main/java/net/minecraft/server/SystemUtils.java
@@ -109,6 +109,7 @@ public class SystemUtils {
@@ -110,6 +110,7 @@ public class SystemUtils {
return SystemUtils.c;
}

View File

@ -9,10 +9,10 @@ so inline where possible, and avoid the abstraction of the
Either class.
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 4cef51b68984f83b8153ee1f017a2c597194df19..fe93e8cd892688a7cb407ef051eb7cac719a7f5b 100644
index 377d554553ce81f66207541d963f826867e66592..9afbec260a1d586152073b2adda32959453ab8c9 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -619,27 +619,37 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -606,27 +606,37 @@ public class ChunkProviderServer extends IChunkProvider {
public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER
@Override public boolean a(Entity entity) {

View File

@ -25,10 +25,10 @@ This successfully fixed a reoccurring and highly reproduceable crash
for heightmaps.
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index fe93e8cd892688a7cb407ef051eb7cac719a7f5b..99be314307071e7b85ba444dcab923dd4edf0ddb 100644
index 9afbec260a1d586152073b2adda32959453ab8c9..e89683b4f1e3cac60b88a5c7317e525c46950b17 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -1052,6 +1052,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -1039,6 +1039,7 @@ public class ChunkProviderServer extends IChunkProvider {
return super.executeNext() || execChunkTask; // Paper
}
} finally {
@ -37,7 +37,7 @@ index fe93e8cd892688a7cb407ef051eb7cac719a7f5b..99be314307071e7b85ba444dcab923dd
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 6c178492b75134ba25b7730273bb550b693a7e4a..79133dd40c465224b1dfa2afaf4c8d3f5a1c2190 100644
index 00f26ae23da65453073fc06ffec8a349ef28dd7e..350ce63eb19b8e999c2da00d8235e1760dc948fc 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -108,6 +108,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -49,7 +49,7 @@ index 6c178492b75134ba25b7730273bb550b693a7e4a..79133dd40c465224b1dfa2afaf4c8d3f
// Paper start - distance maps
private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets<EntityPlayer> pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>();
@@ -974,7 +976,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -962,7 +964,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return Either.left(chunk);
});
}, (runnable) -> {

View File

@ -7,7 +7,7 @@ Subject: [PATCH] Don't crash if player is attempted to be removed from
I suspect it deals with teleporting as it uses players current x/y/z
diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java
index 0244768f76d83af427a07bd235c9bcec8ad5429e..279c7a85fb5b4bff91fba1c9797c902bd68d8539 100644
index 682a64c775adc1254f12d9f93b23375735ed4895..534bb87caf88f0f1bf7988494274b762ab7210e1 100644
--- a/src/main/java/net/minecraft/server/ChunkMapDistance.java
+++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java
@@ -226,6 +226,7 @@ public abstract class ChunkMapDistance {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Broadcast join message to console
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index 62891d2dc6f40bb57e92dfefcbcdf72f89ba5c4f..e79a4d9ff80390a67656d187b1e6ee0a83748918 100644
index 78040e83899f1ef1a6d5c456beb9d13959307c18..c491612267977fb331368825e0d87b2fc297e9c5 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -188,9 +188,9 @@ public abstract class PlayerList {

View File

@ -28,7 +28,7 @@ receives a deterministic result, and should no longer require 1 tick
delays anymore.
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index bf2ba0548d93280651d89c2039a298c56a83b0bf..45df816980cd880b257632f0c4a381d475d2dfbd 100644
index 64e00275edf38739fe6e2d79dbcb93243e765678..a87aa07b17205b52e85f7d082fa4d5169771cbb4 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -100,6 +100,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@ -40,10 +40,10 @@ index bf2ba0548d93280651d89c2039a298c56a83b0bf..45df816980cd880b257632f0c4a381d4
// CraftBukkit end
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 79133dd40c465224b1dfa2afaf4c8d3f5a1c2190..ea0086ceb64ad88a64b8327f055836afb3191a0b 100644
index 350ce63eb19b8e999c2da00d8235e1760dc948fc..047d6ccdc85363b27f9c7d78c4281fdf4ade1087 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -1526,6 +1526,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1514,6 +1514,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
.printStackTrace();
return;
}
@ -52,7 +52,7 @@ index 79133dd40c465224b1dfa2afaf4c8d3f5a1c2190..ea0086ceb64ad88a64b8327f055836af
if (!(entity instanceof EntityComplexPart)) {
if (!(entity instanceof EntityLightning)) {
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index e79a4d9ff80390a67656d187b1e6ee0a83748918..6a4e4f93eb36ca388523a36abf38bcae3ad375e8 100644
index c491612267977fb331368825e0d87b2fc297e9c5..40f5d9fa9069a330b6999eefa50015daa4c19217 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -177,6 +177,12 @@ public abstract class PlayerList {

View File

@ -18,7 +18,7 @@ index f20f798f0f7bb765ffdab8672f4bf77a60fa52d2..9eab570e48817e18d10ddde95b3f80f7
public void setPositionRotation(BlockPosition blockposition, float f, float f1) {
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 45df816980cd880b257632f0c4a381d475d2dfbd..48bbaec4b64bede8d280bd866436f5528578013e 100644
index a87aa07b17205b52e85f7d082fa4d5169771cbb4..79c2187b7383336e7574709e6d4ad805e557976f 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -43,6 +43,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@ -60,7 +60,7 @@ index f1222fcb2bd52b8781d0f92c94e1472fa7b1e493..28f48f22522ef8c3c66381abcf017f08
if (entityplayer != null) {
this.g = LoginListener.EnumProtocolState.DELAY_ACCEPT;
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index f675892e45b033cac5cbb6d86b70ba38bf67ebb3..51d6ef69e7256dda2491837b5edf8f83cd0346ea 100644
index 1673e5b8f13978cd4a47555b9806d801cbbdf3c8..56bace816f5ea5b8b837df7e7707796f68b76f37 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -69,6 +69,7 @@ public class PlayerConnection implements PacketListenerPlayIn {
@ -97,7 +97,7 @@ index f675892e45b033cac5cbb6d86b70ba38bf67ebb3..51d6ef69e7256dda2491837b5edf8f83
this.minecraftServer.getMethodProfiler().enter("keepAlive");
// Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index e5177bb6a20e5f5952b2fcad201a166c2c51510b..9a9c124e6af1fb40255ffaa38d0a4e024ad72436 100644
index 40f5d9fa9069a330b6999eefa50015daa4c19217..60af90bf8c376ab8ab61b16ae38886149faa88cc 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -52,11 +52,12 @@ public abstract class PlayerList {

View File

@ -9,7 +9,7 @@ their position to the ground/exit location when entering the bed, resulting in
the server believing they're still in the air.
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index d77b28ab4a5fc93a325a0d5594f66f4f143bd318..0ad23cd1f79621e64fa25582b36b1b26301e2264 100644
index 56bace816f5ea5b8b837df7e7707796f68b76f37..148cd6a850ef87095558d008fbaf0038d537b78a 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -160,7 +160,7 @@ public class PlayerConnection implements PacketListenerPlayIn {

View File

@ -14,7 +14,7 @@ Use an ArrayDeque to store this Queue
We make sure to also implement a pattern that is recursion safe too.
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index ea0086ceb64ad88a64b8327f055836afb3191a0b..bdf835397aa691c41280f65a7785e777791b2891 100644
index 047d6ccdc85363b27f9c7d78c4281fdf4ade1087..f81eeb7e86018d47312170bda1b4b76697943d69 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -87,24 +87,32 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {

View File

@ -69,7 +69,7 @@ index 0b23a0548d52a30c064d624e39a896a9791aab3b..c988c929f1063b417d10d84b0c131277
public boolean hasPermission(int i) {
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 0deb0c17259d53c12f0e26e19a0a08666e38f871..0fd2c17f8c4b556364e359b72d6e56a5c93d727f 100644
index 148cd6a850ef87095558d008fbaf0038d537b78a..63cbdc3531712b9b63f75789c3481a74a44a0fa7 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -581,8 +581,12 @@ public class PlayerConnection implements PacketListenerPlayIn {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Validate PickItem Packet and kick for invalid
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 0fd2c17f8c4b556364e359b72d6e56a5c93d727f..066438f4ace35310d363e856a22e2f8b48445768 100644
index 63cbdc3531712b9b63f75789c3481a74a44a0fa7..625479b97adf19df67f04dcbe445d78bccb0fc2c 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -696,7 +696,14 @@ public class PlayerConnection implements PacketListenerPlayIn {

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Use distance map to optimise entity tracker
Use the distance map to find candidate players for tracking.
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 6dea557fa32fd44674bf01e2f7429c9691c315b8..c005734f835fd07b121fdb885d981e55f8be81b4 100644
index 32daf027a3575d73aeabf9db14a2e0c74e4cc7e6..b176dc26d15065aebc91c75e8a96745f589c0b87 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -245,6 +245,21 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
@ -44,7 +44,7 @@ index 3a88c9a67062eb73ad8257ea786efca7e7e99f65..6d3b34ead9cc95dcc1152dffa8c6c4a8
List<Entity> list = this.tracker.getPassengers();
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index bdf835397aa691c41280f65a7785e777791b2891..3d31f00a22233bd885496d7aac34eb2b634c40e8 100644
index f81eeb7e86018d47312170bda1b4b76697943d69..c02e127b1e98a8603d426cfb7f46532427227e67 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -120,21 +120,51 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -145,7 +145,7 @@ index bdf835397aa691c41280f65a7785e777791b2891..3d31f00a22233bd885496d7aac34eb2b
}
public void updatePlayerMobTypeMap(Entity entity) {
@@ -1423,17 +1491,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1411,17 +1479,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
public void movePlayer(EntityPlayer entityplayer) {
@ -164,7 +164,7 @@ index bdf835397aa691c41280f65a7785e777791b2891..3d31f00a22233bd885496d7aac34eb2b
int i = MathHelper.floor(entityplayer.locX()) >> 4;
int j = MathHelper.floor(entityplayer.locZ()) >> 4;
@@ -1550,7 +1608,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1538,7 +1596,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker
this.trackedEntities.put(entity.getId(), playerchunkmap_entitytracker);
@ -173,7 +173,7 @@ index bdf835397aa691c41280f65a7785e777791b2891..3d31f00a22233bd885496d7aac34eb2b
if (entity instanceof EntityPlayer) {
EntityPlayer entityplayer = (EntityPlayer) entity;
@@ -1594,7 +1652,37 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1582,7 +1640,37 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
entity.tracker = null; // Paper - We're no longer tracked
}
@ -211,7 +211,7 @@ index bdf835397aa691c41280f65a7785e777791b2891..3d31f00a22233bd885496d7aac34eb2b
List<EntityPlayer> list = Lists.newArrayList();
List<EntityPlayer> list1 = this.world.getPlayers();
@@ -1662,23 +1750,31 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1650,23 +1738,31 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
PacketDebug.a(this.world, chunk.getPos());
List<Entity> list = Lists.newArrayList();
List<Entity> list1 = Lists.newArrayList();
@ -255,7 +255,7 @@ index bdf835397aa691c41280f65a7785e777791b2891..3d31f00a22233bd885496d7aac34eb2b
Iterator iterator;
Entity entity1;
@@ -1716,7 +1812,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1704,7 +1800,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
public class EntityTracker {
@ -264,7 +264,7 @@ index bdf835397aa691c41280f65a7785e777791b2891..3d31f00a22233bd885496d7aac34eb2b
private final Entity tracker;
private final int trackingDistance;
private SectionPosition e;
@@ -1733,6 +1829,42 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1721,6 +1817,42 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.e = SectionPosition.a(entity);
}
@ -307,7 +307,7 @@ index bdf835397aa691c41280f65a7785e777791b2891..3d31f00a22233bd885496d7aac34eb2b
public boolean equals(Object object) {
return object instanceof PlayerChunkMap.EntityTracker ? ((PlayerChunkMap.EntityTracker) object).tracker.getId() == this.tracker.getId() : false;
}
@@ -1829,7 +1961,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1817,7 +1949,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
int j = entity.getEntityType().getChunkRange() * 16;
j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper

View File

@ -77,10 +77,10 @@ index 534bb87caf88f0f1bf7988494274b762ab7210e1..b98abed74f214932b4a226f12645f987
public String c() {
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 99be314307071e7b85ba444dcab923dd4edf0ddb..8ca6adbac2d2e43bf597c405134c1c5c1b430e63 100644
index e89683b4f1e3cac60b88a5c7317e525c46950b17..0a99b347d8497f097ef1da6560a5d0adc1374f25 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -737,6 +737,36 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -724,6 +724,36 @@ public class ChunkProviderServer extends IChunkProvider {
boolean flag1 = this.world.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && !world.getPlayers().isEmpty(); // CraftBukkit
if (!flag) {
@ -117,7 +117,7 @@ index 99be314307071e7b85ba444dcab923dd4edf0ddb..8ca6adbac2d2e43bf597c405134c1c5c
this.world.getMethodProfiler().enter("pollingChunks");
int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED);
BlockPosition blockposition = this.world.getSpawn();
@@ -771,15 +801,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -758,15 +788,7 @@ public class ChunkProviderServer extends IChunkProvider {
this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings
this.world.getMethodProfiler().exit();
@ -134,7 +134,7 @@ index 99be314307071e7b85ba444dcab923dd4edf0ddb..8ca6adbac2d2e43bf597c405134c1c5c
final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping
Optional<Chunk> optional = ((Either) playerchunk.b().getNow(PlayerChunk.UNLOADED_CHUNK)).left();
@@ -793,10 +815,10 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -780,10 +802,10 @@ public class ChunkProviderServer extends IChunkProvider {
this.world.getMethodProfiler().exit();
ChunkCoordIntPair chunkcoordintpair = playerchunk.i();
@ -161,12 +161,12 @@ index 79c2187b7383336e7574709e6d4ad805e557976f..0560eca744cb2032bb6a3faf5aeafa95
super((World) worldserver, gameprofile);
playerinteractmanager.player = this;
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index a6e7bcf79df9f4ad5b0a779f3eecf85f121bedc8..0f303be3c3257548d1888ddbb575ba69ba12d0b8 100644
index 3d610e41969768da0d2848fa1ae195035ccfd660..c4aad20a2952cc34e334ba665a6e0910d5609497 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -148,6 +148,18 @@ public class PlayerChunk {
}
// Paper end
@@ -43,6 +43,18 @@ public class PlayerChunk {
long lastAutoSaveTime; // Paper - incremental autosave
long inactiveTimeStart; // Paper - incremental autosave
+ // Paper start - optimise isOutsideOfRange
+ // cached here to avoid a map lookup
@ -183,7 +183,7 @@ index a6e7bcf79df9f4ad5b0a779f3eecf85f121bedc8..0f303be3c3257548d1888ddbb575ba69
public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) {
this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size());
this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
@@ -164,6 +176,7 @@ public class PlayerChunk {
@@ -59,6 +71,7 @@ public class PlayerChunk {
this.n = this.oldTicketLevel;
this.a(i);
this.chunkMap = (PlayerChunkMap)playerchunk_d; // Paper
@ -192,7 +192,7 @@ index a6e7bcf79df9f4ad5b0a779f3eecf85f121bedc8..0f303be3c3257548d1888ddbb575ba69
// Paper start
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 3d31f00a22233bd885496d7aac34eb2b634c40e8..b3c9cb67664491c3a8c83a67ac0e79d48561f3fe 100644
index c02e127b1e98a8603d426cfb7f46532427227e67..9d414b6bbdda2a4d5a4ecdad6abb7d53860e7e71 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -130,6 +130,17 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -300,7 +300,7 @@ index 3d31f00a22233bd885496d7aac34eb2b634c40e8..b3c9cb67664491c3a8c83a67ac0e79d4
private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) {
double d0 = (double) (chunkcoordintpair.x * 16 + 8);
double d1 = (double) (chunkcoordintpair.z * 16 + 8);
@@ -439,6 +493,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -437,6 +491,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
} else {
if (playerchunk != null) {
playerchunk.a(j);
@ -308,7 +308,7 @@ index 3d31f00a22233bd885496d7aac34eb2b634c40e8..b3c9cb67664491c3a8c83a67ac0e79d4
}
if (playerchunk != null) {
@@ -1420,30 +1475,53 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1408,30 +1463,53 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return isOutsideOfRange(chunkcoordintpair, false);
}

View File

@ -114,10 +114,20 @@ index 0560eca744cb2032bb6a3faf5aeafa95a7a6815e..07a6fc3d88e7d44bfab7f3d6a0eef7dc
super((World) worldserver, gameprofile);
playerinteractmanager.player = this;
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 0f303be3c3257548d1888ddbb575ba69ba12d0b8..7b2a3287ce8d296d29cbef45322a469921cf9944 100644
index c4aad20a2952cc34e334ba665a6e0910d5609497..845e5d2a8ee025ac61cf916de04e0797e32db568 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -160,6 +160,18 @@ public class PlayerChunk {
@@ -47,14 +47,28 @@ public class PlayerChunk {
// cached here to avoid a map lookup
com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> playersInMobSpawnRange;
com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> playersInChunkTickRange;
+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> playersInTickingRange;
void updateRanges() {
long key = net.minecraft.server.MCUtil.getCoordinateKey(this.location);
this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key);
this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
+ this.playersInTickingRange = this.chunkMap.playerViewDistanceTickMap.getObjectsInRange(key);
}
// Paper end - optimise isOutsideOfRange
@ -136,7 +146,7 @@ index 0f303be3c3257548d1888ddbb575ba69ba12d0b8..7b2a3287ce8d296d29cbef45322a4699
public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) {
this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size());
this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
@@ -321,7 +333,7 @@ public class PlayerChunk {
@@ -210,7 +224,7 @@ public class PlayerChunk {
}
public void a(int i, int j, int k) {
@ -145,7 +155,7 @@ index 0f303be3c3257548d1888ddbb575ba69ba12d0b8..7b2a3287ce8d296d29cbef45322a4699
if (chunk != null) {
this.r |= 1 << (j >> 4);
@@ -341,7 +353,7 @@ public class PlayerChunk {
@@ -230,7 +244,7 @@ public class PlayerChunk {
}
public void a(EnumSkyBlock enumskyblock, int i) {
@ -154,7 +164,7 @@ index 0f303be3c3257548d1888ddbb575ba69ba12d0b8..7b2a3287ce8d296d29cbef45322a4699
if (chunk != null) {
chunk.setNeedsSaving(true);
@@ -426,9 +438,48 @@ public class PlayerChunk {
@@ -315,9 +329,48 @@ public class PlayerChunk {
}
private void a(Packet<?> packet, boolean flag) {
@ -207,7 +217,7 @@ index 0f303be3c3257548d1888ddbb575ba69ba12d0b8..7b2a3287ce8d296d29cbef45322a4699
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> a(ChunkStatus chunkstatus, PlayerChunkMap playerchunkmap) {
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096ef319a753 100644
index 9d414b6bbdda2a4d5a4ecdad6abb7d53860e7e71..abfe75750ea564cd56b53d3f09eb247478384e2f 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -71,7 +71,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -340,7 +350,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
}
public void updatePlayerMobTypeMap(Entity entity) {
@@ -1113,15 +1199,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1101,15 +1187,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
completablefuture1.thenAcceptAsync((either) -> {
either.mapLeft((chunk) -> {
this.u.getAndIncrement();
@ -358,7 +368,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
});
return completablefuture1;
}
@@ -1221,32 +1303,38 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1209,32 +1291,38 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
} // Paper
}
@ -412,7 +422,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
protected void sendChunk(EntityPlayer entityplayer, ChunkCoordIntPair chunkcoordintpair, Packet<?>[] apacket, boolean flag, boolean flag1) {
if (entityplayer.world == this.world) {
@@ -1254,7 +1342,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1242,7 +1330,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
PlayerChunk playerchunk = this.getVisibleChunk(chunkcoordintpair.pair());
if (playerchunk != null) {
@ -421,7 +431,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
if (chunk != null) {
this.a(entityplayer, apacket, chunk);
@@ -1523,6 +1611,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1511,6 +1599,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
// Paper end - optimise isOutsideOfRange
@ -429,7 +439,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
private boolean b(EntityPlayer entityplayer) {
return entityplayer.isSpectator() && !this.world.getGameRules().getBoolean(GameRules.SPECTATORS_GENERATE_CHUNKS);
}
@@ -1550,13 +1639,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1538,13 +1627,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.removePlayerFromDistanceMaps(entityplayer); // Paper - distance maps
}
@ -444,7 +454,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
}
@@ -1564,7 +1647,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1552,7 +1635,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
SectionPosition sectionposition = SectionPosition.a((Entity) entityplayer);
entityplayer.a(sectionposition);
@ -453,7 +463,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
return sectionposition;
}
@@ -1609,6 +1692,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1597,6 +1680,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
int k1;
int l1;
@ -461,7 +471,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
if (Math.abs(i1 - i) <= this.viewDistance * 2 && Math.abs(j1 - j) <= this.viewDistance * 2) {
k1 = Math.min(i, i1) - this.viewDistance;
l1 = Math.min(j, j1) - this.viewDistance;
@@ -1646,7 +1730,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1634,7 +1718,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true);
}
}
@ -470,7 +480,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
this.updateMaps(entityplayer); // Paper - distance maps
@@ -1654,11 +1738,46 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1642,11 +1726,46 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@Override
public Stream<EntityPlayer> a(ChunkCoordIntPair chunkcoordintpair, boolean flag) {
@ -521,7 +531,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
}
protected void addEntity(Entity entity) {
@@ -1818,6 +1937,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1806,6 +1925,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
@ -529,7 +539,7 @@ index b3c9cb67664491c3a8c83a67ac0e79d48561f3fe..9071080df09a67a5c07545a426b9096e
private void a(EntityPlayer entityplayer, Packet<?>[] apacket, Chunk chunk) {
if (apacket[0] == null) {
apacket[0] = new PacketPlayOutMapChunk(chunk, 65535);
@@ -2003,7 +2123,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1991,7 +2111,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ);
PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair());
@ -589,10 +599,10 @@ index 899c535c4056cd2375ab8f834f03267d405f4bda..0e6368d0fb3beccb492ae3867fb4e228
if (!this.isClientSide && (i & 1) != 0) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 64c643aa15d6ea68f9dad3104cc41e412255cee3..874240d9dddc3150d65d56d95c459b59f07b8815 100644
index b184f8ed8ce86965c3ef9aef179126a4d69275e8..bbfbfeed12890c9d20d78a9661ab172c901f008c 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -2488,10 +2488,39 @@ public class CraftWorld implements World {
@@ -2482,10 +2482,39 @@ public class CraftWorld implements World {
// Spigot start
@Override
public int getViewDistance() {

View File

@ -122,10 +122,10 @@ index ddb60e9a48e5e7225ad575240b94fda24b6b78ca..beb50f78e8b2f79d45e2e7fdc932e947
if (!SyncLoadFinder.ENABLED) {
sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set.");
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 7b2a3287ce8d296d29cbef45322a469921cf9944..d0085b7459293e3e3460cfda34c67bda6e7bc324 100644
index 845e5d2a8ee025ac61cf916de04e0797e32db568..9e95c6b54f0855ddde6db6bd3e768e87fee6c21a 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -437,6 +437,7 @@ public class PlayerChunk {
@@ -328,6 +328,7 @@ public class PlayerChunk {
}
@ -134,7 +134,7 @@ index 7b2a3287ce8d296d29cbef45322a469921cf9944..d0085b7459293e3e3460cfda34c67bda
// Paper start - per player view distance
// there can be potential desync with player's last mapped section and the view distance map, so use the
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 9071080df09a67a5c07545a426b9096ef319a753..618831289645957a71bad3925c61af9068a05221 100644
index abfe75750ea564cd56b53d3f09eb247478384e2f..430273c306be19d7b5af171f392236f9f0d835a8 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -72,6 +72,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {

View File

@ -11,7 +11,7 @@ This guarantees any time we set the entities position, we also
update their AABB.
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index c005734f835fd07b121fdb885d981e55f8be81b4..c5adac15d726dd03853cef10758a21e5ce690567 100644
index b176dc26d15065aebc91c75e8a96745f589c0b87..c81b9d814d50a026872d2711f76649c00d65888b 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -416,10 +416,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke

View File

@ -10,7 +10,7 @@ Adds a 5 second grace period for any async tasks to finish and warns
if any are still running after that delay just as reload does.
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 1a4bc90435d0a56ab7b607c72f28772fb92049bc..a8bb89111b9ab62f41e02a471518413346d201ac 100644
index 4ea3468614df36e1c148a44bb15d2201da281df3..5b24de6d6071bddee642ddbc00959cf93792051e 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -739,6 +739,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Optimize WorldBorder collision checks and air
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index c5adac15d726dd03853cef10758a21e5ce690567..14b83940080e934dcc3622cc90e623ad48c0b1d1 100644
index c81b9d814d50a026872d2711f76649c00d65888b..e0ab058bf947ea10b37eadf6122292e708bd3809 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -845,7 +845,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke

View File

@ -13,10 +13,10 @@ A config is provided if you rather let players use these exploits, and let
them destroy the worlds End Portals and get on top of the nether easy.
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index e0d7832c3a081b54a0e3a27380015477897fdf6d..699727a79c1733092d010c2d0039fd93455ebc0a 100644
index 3ee7e5671dd2519cec72b81211f1f39176a228ba..cf9b9de8688e3f655631451409096d7ec0471910 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -427,4 +427,10 @@ public class PaperConfig {
@@ -431,4 +431,10 @@ public class PaperConfig {
private static void midTickChunkTasks() {
midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks);
}

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Reduce MutableInt allocations from light engine
diff --git a/src/main/java/net/minecraft/server/LightEngineBlock.java b/src/main/java/net/minecraft/server/LightEngineBlock.java
index 93a972605c26aa757b9c915876f847da04fcb496..c4ba30bd56e2ead6015c0109f8e889388afeb7f2 100644
index 93a972605c26aa757b9c915876f847da04fcb496..c9e91eb4ef538485620aedaee4843b779fede809 100644
--- a/src/main/java/net/minecraft/server/LightEngineBlock.java
+++ b/src/main/java/net/minecraft/server/LightEngineBlock.java
@@ -37,7 +37,10 @@ public final class LightEngineBlock extends LightEngineLayer<LightEngineStorageB
@ -32,7 +32,7 @@ index 93a972605c26aa757b9c915876f847da04fcb496..c4ba30bd56e2ead6015c0109f8e88938
}
}
diff --git a/src/main/java/net/minecraft/server/LightEngineSky.java b/src/main/java/net/minecraft/server/LightEngineSky.java
index 2301a982e17ab9568e3da9ca84c4a024c7c1b214..0b4f4604f4ea444017c021768574646a8d11ba26 100644
index 2301a982e17ab9568e3da9ca84c4a024c7c1b214..57c2880ea23dc7ff55826858240bd13b7d3c24f2 100644
--- a/src/main/java/net/minecraft/server/LightEngineSky.java
+++ b/src/main/java/net/minecraft/server/LightEngineSky.java
@@ -27,7 +27,10 @@ public final class LightEngineSky extends LightEngineLayer<LightEngineStorageSky

View File

@ -39,10 +39,10 @@ index 6d3b34ead9cc95dcc1152dffa8c6c4a8c7f1d58b..5cc89c0cf9e9e632212a9653391437cb
if (!flag4 && this.o <= 400 && !this.q && this.r == this.tracker.onGround) {
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 618831289645957a71bad3925c61af9068a05221..af6d28a99adc94ae425520d7f6c125bb03654212 100644
index 430273c306be19d7b5af171f392236f9f0d835a8..71547b675bfe23c4c4a8acd75f0e26b6023bf132 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -2119,9 +2119,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -2107,9 +2107,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
public void updatePlayer(EntityPlayer entityplayer) {
org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot
if (entityplayer != this.tracker) {

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Add option for console having all permissions
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 699727a79c1733092d010c2d0039fd93455ebc0a..2acfb4052c21bb944785b888511185a2f8aba486 100644
index cf9b9de8688e3f655631451409096d7ec0471910..f0284e81db3ab7c45018de2b446f2d8296df15c3 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -433,4 +433,9 @@ public class PaperConfig {
@@ -437,4 +437,9 @@ public class PaperConfig {
allowBlockPermanentBreakingExploits = getBoolean("allow-perm-block-break-exploits", allowBlockPermanentBreakingExploits);
}

View File

@ -37,7 +37,7 @@ index b7b06e082e59f8518be2036637385c7710d524ea..71da9f00b8a969e84414066fb1852cec
return chunksection == Chunk.a || chunksection.c();
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index af6d28a99adc94ae425520d7f6c125bb03654212..f11ec68a111dae31d0389a2bd09cb0bf7a9b88e3 100644
index 71547b675bfe23c4c4a8acd75f0e26b6023bf132..e772095e1c44842f743661a326c2a9a8a677ab02 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -379,7 +379,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -49,7 +49,7 @@ index af6d28a99adc94ae425520d7f6c125bb03654212..f11ec68a111dae31d0389a2bd09cb0bf
},
(EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ,
com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> newState) -> {
@@ -1944,12 +1944,112 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1932,12 +1932,112 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}

View File

@ -0,0 +1,524 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sat, 11 Apr 2020 03:56:07 -0400
Subject: [PATCH] Implement Chunk Priority / Urgency System for Chunks
Mark chunks that are blocking main thread for world generation as urgent
Implements a general priority system so that chunks that are sorted in
the generator queues can prioritize certain chunks over another.
Urgent chunks will jump to the front of the line, ensuring that a
sync chunk load on an ungenerated chunk does not lag the server for
a long period of time if the servers generator queues are filled with
lots of chunks already.
This massively reduces the lag spikes from sync chunk gens.
Then we further prioritize loading order so nearby chunks have higher
priority than distant chunks, reducing the pressure a high no tick
view distance holds on you.
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/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java
index 716d4eab382244ee9bc4855bf0f026e65ec057d6..20052dcbc71899165ac99801fa9f7753672ba997 100644
--- a/src/main/java/net/minecraft/server/ChunkMapDistance.java
+++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java
@@ -143,7 +143,7 @@ public abstract class ChunkMapDistance {
Ticket<?> ticket1 = (Ticket) arraysetsorted.a(ticket); // CraftBukkit - decompile error
ticket1.a(this.currentTick);
- if (ticket.b() < j) {
+ if (ticket.b() < j || (ticket.getTicketType() == TicketType.PRIORITY && ((Ticket<Integer>) ticket).getObjectReason() < j)) { // Paper - check priority tickets too
this.e.b(i, ticket.b(), true);
}
@@ -171,6 +171,48 @@ public abstract class ChunkMapDistance {
this.addTicketAtLevel(tickettype, chunkcoordintpair, i, t0);
}
+ // Paper start
+ public boolean markUrgent(ChunkCoordIntPair coords) {
+ return this.markHighPriority(coords, 30);
+ }
+ public boolean markHighPriority(ChunkCoordIntPair coords, int priority) {
+ priority = Math.min(30, Math.max(1, priority));
+ Ticket<Integer> ticket = new Ticket<Integer>(TicketType.PRIORITY, 31, priority);
+ return this.addTicket(coords.pair(), ticket);
+ }
+ public int getChunkPriority(ChunkCoordIntPair coords) {
+ int priority = 0;
+ ArraySetSorted<Ticket<?>> tickets = this.tickets.get(coords.pair());
+ if (tickets == null) {
+ return priority;
+ }
+ for (Ticket<?> ticket : tickets) {
+ if (ticket.getTicketType() != TicketType.PRIORITY) {
+ continue;
+ }
+ //noinspection unchecked
+ Ticket<Integer> prioTicket = (Ticket<Integer>) ticket;
+ if (prioTicket.getObjectReason() > priority) {
+ priority = prioTicket.getObjectReason();
+ }
+ }
+ return priority;
+ }
+ public void clearPriorityTickets(ChunkCoordIntPair coords) {
+ ArraySetSorted<Ticket<?>> tickets = this.tickets.get(coords.pair());
+ java.util.List<Ticket<?>> toRemove = new java.util.ArrayList<>();
+ if (tickets == null) return;
+ for (Ticket<?> ticket : tickets) {
+ if (ticket.getTicketType() == TicketType.PRIORITY) {
+ toRemove.add(ticket);
+ }
+ }
+ for (Ticket<?> ticket : toRemove) {
+ this.removeTicket(coords.pair(), ticket);
+ }
+
+ }
+ // 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
@@ -386,7 +428,8 @@ public abstract class ChunkMapDistance {
});
}, i, () -> {
- return j;
+ PlayerChunk chunk = chunkMap.getUpdatingChunk(i); // Paper
+ return chunk != null && chunk.getCurrentPriority() < j ? chunk.getCurrentPriority() : j; // Paper
}));
} else {
ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 0a99b347d8497f097ef1da6560a5d0adc1374f25..d6f629d45e05167c22b6cd08a9709809a32b15a1 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -431,6 +431,16 @@ public class ChunkProviderServer extends IChunkProvider {
public <T> void removeTicketAtLevel(TicketType<T> ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) {
this.chunkMapDistance.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier);
}
+
+ public boolean markUrgent(ChunkCoordIntPair coords) {
+ return chunkMapDistance.markUrgent(coords);
+ }
+ public boolean markHighPriority(ChunkCoordIntPair coords, int priority) {
+ return chunkMapDistance.markHighPriority(coords, priority);
+ }
+ public void clearPriorityTickets(ChunkCoordIntPair coords) {
+ this.chunkMapDistance.clearPriorityTickets(coords);
+ }
// Paper end
@Nullable
@@ -469,6 +479,8 @@ public class ChunkProviderServer extends IChunkProvider {
if (!completablefuture.isDone()) { // Paper
// Paper start - async chunk io/loading
+ ChunkCoordIntPair pair = new ChunkCoordIntPair(x, z);
+ this.markUrgent(pair);
this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY);
com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z);
// Paper end
@@ -477,6 +489,7 @@ public class ChunkProviderServer extends IChunkProvider {
this.serverThreadQueue.awaitTasks(completablefuture::isDone);
com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug
this.world.timings.syncChunkLoad.stopTiming(); // Paper
+ this.clearPriorityTickets(pair); // Paper
} // Paper
ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> {
return ichunkaccess1;
@@ -529,6 +542,7 @@ public class ChunkProviderServer extends IChunkProvider {
if (flag && !currentlyUnloading) {
// CraftBukkit end
this.chunkMapDistance.a(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair);
+ if (isUrgent) this.markUrgent(chunkcoordintpair); // Paper
if (this.a(playerchunk, l)) {
GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler();
@@ -541,8 +555,13 @@ public class ChunkProviderServer extends IChunkProvider {
}
}
}
-
- return this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap);
+ // Paper start
+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> future = this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap);
+ if (isUrgent) {
+ future.thenAccept(either -> this.clearPriorityTickets(chunkcoordintpair));
+ }
+ return future;
+ // Paper end
}
private boolean a(@Nullable PlayerChunk playerchunk, int i) {
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 07a6fc3d88e7d44bfab7f3d6a0eef7dc132ab422..d60f659b368500e3a8c3305f99e60ffc643e2fbd 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -441,6 +441,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
if (valid && (!this.isSpectator() || this.world.isLoaded(new BlockPosition(this)))) { // Paper - don't tick dead players that are not in the world currently (pending respawn)
super.tick();
}
+ if (valid && isAlive() && this.ticksLived % 20 == 0) ((WorldServer)world).getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); // Paper
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
--- 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 {
chunkData.addProperty("x", playerChunk.location.x);
chunkData.addProperty("z", playerChunk.location.z);
chunkData.addProperty("ticket-level", playerChunk.getTicketLevel());
+ chunkData.addProperty("priority", playerChunk.getCurrentPriority());
chunkData.addProperty("state", PlayerChunk.getChunkState(playerChunk.getTicketLevel()).toString());
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 9e95c6b54f0855ddde6db6bd3e768e87fee6c21a..44721a4f446bdd5bf4575e4168a0570afd71c4d4 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -25,7 +25,7 @@ public class PlayerChunk {
private CompletableFuture<IChunkAccess> chunkSave;
public int oldTicketLevel;
private int ticketLevel;
- private int n;
+ private int n; public final int getCurrentPriority() { return n; } // Paper - OBFHELPER
final ChunkCoordIntPair location; // Paper - private -> package
private final short[] dirtyBlocks;
private int dirtyCount;
@@ -68,6 +68,92 @@ public class PlayerChunk {
return null;
}
// Paper end - no-tick view distance
+ // Paper start - Chunk gen/load priority system
+ volatile int neighborPriority = -1;
+ final java.util.concurrent.ConcurrentHashMap<PlayerChunk, Integer> neighbors = new java.util.concurrent.ConcurrentHashMap<>();
+ final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<Integer> neighborPriorities = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>();
+
+ public int getPreferredPriority() {
+ int priority = neighborPriority; // if we have a neighbor priority, use it
+ int priorityBoost = chunkMap.chunkDistanceManager.getChunkPriority(location);
+ int basePriority = ticketLevel - priorityBoost;
+
+ if (priority == -1 || priority > basePriority) {
+ if (priorityBoost > 0) {
+ //System.out.println(location + " boost " + (basePriority) + " = " + ticketLevel + " - " + priorityBoost);
+ }
+ priority = basePriority;
+ if (ticketLevel >= 34 && priorityBoost == 0) {
+ priority += 5;
+ }
+ }
+
+
+ return Math.max(1, Math.min(PlayerChunkMap.GOLDEN_TICKET, priority));
+ }
+ public void onNeighborRequest(PlayerChunk neighbor, ChunkStatus status) {
+ int currentPriority = getCurrentPriority();
+ if (!neighborPriorities.containsKey(neighbor.location.pair()) && (neighbor.neighborPriority == -1 || neighbor.neighborPriority > currentPriority)) {
+ this.neighbors.put(neighbor, currentPriority);
+ neighbor.setNeighborPriority(this, Math.max(1, currentPriority));
+ }
+ }
+
+ private void setNeighborPriority(PlayerChunk requester, int priority) {
+ if (priority < neighborPriority || neighborPriority == -1) {
+ synchronized (neighborPriorities) {
+ if (priority < neighborPriority || neighborPriority == -1) {
+ neighborPriority = priority;
+ neighborPriorities.put(requester.location.pair(), Integer.valueOf(priority));
+ }
+ }
+ }
+ }
+
+ public void onNeighborsDone() {
+ java.util.List<PlayerChunk> neighbors = new java.util.ArrayList<>(this.neighbors.keySet());
+ this.neighbors.clear();
+ for (PlayerChunk neighbor : neighbors) {
+ synchronized (neighbor.neighborPriorities) {
+ neighbor.neighborPriorities.remove(location.pair());
+ neighbor.recalcNeighborPriority();
+ }
+ }
+ }
+
+ private void recalcNeighborPriority() {
+ neighborPriority = -1;
+ if (!neighborPriorities.isEmpty()) {
+ synchronized (neighborPriorities) {
+ for (Integer neighbor : neighborPriorities.values()) {
+ if (neighbor < neighborPriority || neighborPriority == -1) {
+ neighborPriority = neighbor;
+ }
+ }
+ }
+ }
+ }
+
+ public final double getDistanceFromPointInFront(EntityPlayer player, int dist) {
+ int inFront = dist * 16;
+ final float yaw = MCUtil.normalizeYaw(player.yaw);
+ double rads = Math.toRadians(yaw);
+ final double x = player.locX() + inFront * Math.cos(rads);
+ final double z = player.locZ() + inFront * Math.sin(rads);
+ return getDistance(x, z);
+ }
+
+ public final double getDistance(EntityPlayer player) {
+ return getDistance(player.locX(), player.locZ());
+ }
+ public final double getDistance(double blockX, double blockZ) {
+ int cx = MCUtil.fastFloor(blockX) >> 4;
+ int cz = MCUtil.fastFloor(blockZ) >> 4;
+ final double x = location.x - cx;
+ final double z = location.z - cz;
+ return (x * x) + (z * z);
+ }
+ // Paper end
public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) {
this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size());
@@ -166,6 +252,12 @@ public class PlayerChunk {
}
return null;
}
+ public static ChunkStatus getNextStatus(ChunkStatus status) {
+ if (status == ChunkStatus.FULL) {
+ return status;
+ }
+ return CHUNK_STATUSES.get(status.getStatusIndex() + 1);
+ }
// Paper end
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFutureUnchecked(ChunkStatus chunkstatus) {
@@ -419,8 +511,18 @@ public class PlayerChunk {
return this.n;
}
+ private void setPriority(int i) { d(i); } // Paper - OBFHELPER
private void d(int i) {
+ if (i == n) return; // Paper
this.n = i;
+ // Paper start
+ this.neighbors.keySet().forEach(neighbor -> {
+ if (neighbor.getCurrentPriority() > i) {
+ neighbor.setNeighborPriority(this, i);
+ this.w.changePriority(neighbor.location, neighbor::getCurrentPriority, neighbor.getCurrentPriority(), neighbor::setPriority);
+ }
+ });
+ // Paper end
}
public void a(int i) {
@@ -508,6 +610,7 @@ public class PlayerChunk {
Chunk fullChunk = either.left().get();
PlayerChunk.this.isFullChunkReady = true;
fullChunk.playerChunk = PlayerChunk.this;
+ this.chunkMap.chunkDistanceManager.clearPriorityTickets(location);
}
@@ -583,7 +686,7 @@ public class PlayerChunk {
this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
}
- this.w.a(this.location, this::k, this.ticketLevel, this::d);
+ this.w.a(this.location, this::k, getPreferredPriority(), this::d); // Paper - preferred priority
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.
@@ -670,6 +773,7 @@ public class PlayerChunk {
public interface c {
+ default void changePriority(ChunkCoordIntPair chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer) { a(chunkcoordintpair, intsupplier, i, intconsumer); } // Paper - OBFHELPER
void a(ChunkCoordIntPair chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer);
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index e772095e1c44842f743661a326c2a9a8a677ab02..5621416660d2722f26582fcecd5b61a164cd1530 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -352,6 +352,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) -> {
+ checkHighPriorityChunks(player);
if (newState.size() != 1) {
return;
}
@@ -370,7 +371,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
- });
+ PlayerChunkMap.this.world.getChunkProvider().clearPriorityTickets(chunkPos);
+ }, (player, prevPos, newPos) -> checkHighPriorityChunks(player));
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,
@@ -387,6 +389,62 @@ 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 checkHighPriorityChunks(EntityPlayer player) {
+ MCUtil.getSpiralOutChunks(new BlockPosition(player), Math.min(7, getLoadViewDistance())).forEach(coord -> {
+ PlayerChunk chunk = getUpdatingChunk(coord.pair());
+ if (chunk == null || chunk.isFullChunkReady() || chunk.getTicketLevel() >= 34 ||
+ !world.getWorldBorder().isInBounds(coord)
+ ) {
+ return;
+ }
+
+ double dist = chunk.getDistance(player);
+ // Prioritize immediate
+ if (dist <= 5) {
+ chunkDistanceManager.markHighPriority(coord, (int) (29 - dist));
+ return;
+ }
+ boolean hasNeighbor = false;
+ for (int[] matrix : neighborMatrix) {
+ long neighborKey = MCUtil.getCoordinateKey(coord.x + matrix[0], coord.x + matrix[1]);
+ PlayerChunk neighbor = getUpdatingChunk(neighborKey);
+ if (neighbor != null && neighbor.isFullChunkReady()) {
+ hasNeighbor = true;
+ break;
+ }
+ }
+ if (!hasNeighbor) {
+ return;
+ }
+ // Prioritize Frustum near
+ double distFront1 = chunk.getDistanceFromPointInFront(player, 2);
+ if (distFront1 <= (4*4)) {
+ if (distFront1 <= (2 * 2)) {
+ chunkDistanceManager.markHighPriority(coord, 24);
+ } else {
+ chunkDistanceManager.markHighPriority(coord, 22);
+ }
+ return;
+ }
+ // Prioritize Frustum far
+ double distFront2 = chunk.getDistanceFromPointInFront(player, 4);
+ if (distFront2 <= (3*3)) {
+ if (distFront2 <= (2 * 2)) {
+ chunkDistanceManager.markHighPriority(coord, 23);
+ } else {
+ chunkDistanceManager.markHighPriority(coord, 20);
+ }
+ return;
+ }
+ // Prioritize nearby chunks
+ if (dist <= (5*5)) {
+ chunkDistanceManager.markHighPriority(coord, (int) (16 - Math.sqrt(dist*(4D/5D))));
+ }
+ });
+ }
+ // Paper end
public void updatePlayerMobTypeMap(Entity entity) {
if (!this.world.paperConfig.perPlayerMobSpawns) {
@@ -516,6 +574,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;
+ PlayerChunk requestingNeighbor = getUpdatingChunk(chunkcoordintpair.pair()); // Paper
for (int l = -i; l <= i; ++l) {
for (int i1 = -i; i1 <= i; ++i1) {
@@ -533,6 +592,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(j1);
+ if (requestingNeighbor != null && requestingNeighbor != playerchunk) requestingNeighbor.onNeighborRequest(playerchunk, chunkstatus); // Paper
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture = playerchunk.a(chunkstatus, this);
list.add(completablefuture);
@@ -997,14 +1057,22 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
};
CompletableFuture<NBTTagCompound> chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z);
+ PlayerChunk playerChunk = getUpdatingChunk(chunkcoordintpair.pair());
+ int chunkPriority = playerChunk != null ? playerChunk.getCurrentPriority() : 33;
+ int priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY;
+
+ if (chunkPriority <= 10) {
+ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY;
+ } else if (chunkPriority <= 20) {
+ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY;
+ }
+ boolean isHighestPriority = priority == com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY;
if (chunkSaveFuture != null) {
- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z,
- com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture);
- this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY);
+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isHighestPriority, chunkSaveFuture);
} else {
- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z,
- com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false);
+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isHighestPriority);
}
+ this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, priority);
return ret;
// Paper end
}
@@ -1041,6 +1109,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return CompletableFuture.completedFuture(Either.right(playerchunk_failure));
});
}, (runnable) -> {
+ playerchunk.onNeighborsDone(); // Paper
this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); // CraftBukkit - decompile error
});
}
@@ -1133,7 +1202,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
long i = playerchunk.i().pair();
playerchunk.getClass();
- mailbox.a(ChunkTaskQueueSorter.a(runnable, i, playerchunk::getTicketLevel)); // CraftBukkit - decompile error
+ mailbox.a(ChunkTaskQueueSorter.a(runnable, i, playerchunk::getCurrentPriority)); // CraftBukkit - decompile error // Paper - use priority not ticket level....
});
}
diff --git a/src/main/java/net/minecraft/server/TicketType.java b/src/main/java/net/minecraft/server/TicketType.java
index 8055f5998213ab1c6c10d03d88d2b14d220a5e40..4913205c15a2b6d5ea058890b02090b494e9c177 100644
--- a/src/main/java/net/minecraft/server/TicketType.java
+++ b/src/main/java/net/minecraft/server/TicketType.java
@@ -23,6 +23,7 @@ public class TicketType<T> {
public static final TicketType<org.bukkit.plugin.Plugin> PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit
public static final TicketType<Long> FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper
public static final TicketType<Long> ASYNC_LOAD = a("async_load", Long::compareTo); // Paper
+ public static final TicketType<Integer> PRIORITY = a("priority", Integer::compareTo, 300); // Paper
public static <T> TicketType<T> a(String s, Comparator<T> comparator) {
return new TicketType<>(s, comparator, 0L);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index bbfbfeed12890c9d20d78a9661ab172c901f008c..589926d6029ca2a4aeb4f2c7903a5f9517deebef 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -2472,10 +2472,15 @@ public class CraftWorld implements World {
}
}
- return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> {
+ CompletableFuture<Chunk> future = this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> {
net.minecraft.server.Chunk chunk = (net.minecraft.server.Chunk) either.left().orElse(null);
return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk());
}, MinecraftServer.getServer());
+ if (urgent) {
+ world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY);
+ }
+ return future;
+
}
// Paper end