PaperMC/Spigot-Server-Patches/0581-Only-consider-chunks-Loaded-if-at-BORDER-status.patch
Aikar 9efe071062 Only consider chunks Loaded if at BORDER status
This greatly improves performance as it drastically reduces the amount
of Entities and Tile Entities that are "registered" into the world, as
purely "cached" chunks will no longer have their entities hanging out in the world.

Additionally this fixes our Entity Add To World and Entity Remove From World events

Those events have not been firing correctly since MC changed how chunks work here.

Now the server will only consider a chunk "loaded" if it's got a ticket putting
it at level 33 or lower, which matches the public Bukkit API.
2020-09-19 12:54:05 -04:00

156 lines
7.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sat, 12 Sep 2020 22:20:55 -0400
Subject: [PATCH] Only consider chunks Loaded if at BORDER status
This greatly improves performance as it drastically reduces the amount
of Entities and Tile Entities that are "registered" into the world, as
purely "cached" chunks will no longer have their entities hanging out in the world.
Additionally this fixes our Entity Add To World and Entity Remove From World events
Those events have not been firing correctly since MC changed how chunks work here.
Now the server will only consider a chunk "loaded" if it's got a ticket putting
it at level 33 or lower, which matches the public Bukkit API.
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 299d7d7a55532930e2d4340a6cfe77a5fd8a0a0c..15c0a06139bffc6a7f83a1d47f2a708f14d264ec 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -791,6 +791,7 @@ public class Chunk implements IChunkAccess {
int chunkX = this.loc.x;
int chunkZ = this.loc.z;
ChunkProviderServer chunkProvider = ((WorldServer)this.world).getChunkProvider();
+ chunkProvider.playerChunkMap.loadChunk(this); // Paper - move load logic from the entering full status to when it enters border status instead
for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) {
for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) {
Chunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz);
@@ -862,6 +863,11 @@ public class Chunk implements IChunkAccess {
this.loadedTicketLevel = false;
this.resetNeighbours();
// Paper end
+ // Paper start - move unload logic from the actual full unload to be when it leaves border status
+ chunkProvider.playerChunkMap.loadedChunks.remove(loc.longKey);
+ setLoaded(false);
+ this.world.unloadChunk(this);
+ // Paper end
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 45c142c227bc258bbd5c8c03c6012663dccf8f3f..de5c45ec773474ad6a7b572e9a248c8f8ee0f94f 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -19,6 +19,7 @@ import java.util.function.Supplier;
import javax.annotation.Nullable;
import com.destroystokyo.paper.exception.ServerInternalException;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper
+import it.unimi.dsi.fastutil.longs.LongIterator; // Paper
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -822,7 +823,10 @@ public class ChunkProviderServer extends IChunkProvider {
//List<PlayerChunk> list = Lists.newArrayList(this.playerChunkMap.f()); // Paper
//Collections.shuffle(list); // Paper
// Paper - moved up
- final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping
+ final int[] chunksTicked = {0};
+ this.playerChunkMap.forEachVisibleChunk((playerchunk) -> {
+ //for (LongIterator iterator = this.playerChunkMap.loadedChunks.iterator() ; iterator.hasNext() ; ) { // Paper - iterate only loaded chunks
+ //PlayerChunk playerchunk = this.playerChunkMap.getVisibleChunk(iterator.nextLong());// Paper - iterate only loaded chunks
Optional<Chunk> optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left();
if (optional.isPresent()) {
@@ -850,7 +854,7 @@ public class ChunkProviderServer extends IChunkProvider {
}
}
}
- });
+ });// Paper - use for instead of forEachVisibleChunk
this.world.getMethodProfiler().enter("customSpawners");
if (flag1) {
try (co.aikar.timings.Timing ignored = this.world.timings.miscMobSpawning.startTiming()) { // Paper - timings
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index fcd3388d88aad6e897b73e2c823267ada327cbda..5d3322f9f068fa74a000d58990dec6001f8ad1ab 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -1021,16 +1021,18 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.a(i, playerchunk);
} else {
if (this.pendingUnload.remove(i, playerchunk) && ichunkaccess != null) {
+ // Paper start - coment out and move to ChunkUnloadEvent
if (ichunkaccess instanceof Chunk) {
- ((Chunk) ichunkaccess).setLoaded(false);
+ //((Chunk) ichunkaccess).setLoaded(false);
}
//this.saveChunk(ichunkaccess);// Paper - delay
- if (this.loadedChunks.remove(i) && ichunkaccess instanceof Chunk) {
- Chunk chunk = (Chunk) ichunkaccess;
-
- this.world.unloadChunk(chunk);
- }
+// if (this.loadedChunks.remove(i) && ichunkaccess instanceof Chunk) {
+// Chunk chunk = (Chunk) ichunkaccess;
+//
+// this.world.unloadChunk(chunk);
+// }
+ // Paper end
this.autoSaveQueue.remove(playerchunk); // Paper
try {
@@ -1293,6 +1295,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return PlayerChunk.getChunkState(playerchunk.getTicketLevel());
});
chunk.addEntities();
+ // Paper start
+ return chunk;
+ } // Paper
+ });
+ }, (runnable) -> {
+
+ this.mailboxMain.a(ChunkTaskQueueSorter.a(runnable, playerchunk.i().pair(), () -> 1)); // Paper - final loads are always urgent!
+ });
+ }
+ public void loadChunk(Chunk chunk) {
+ if (true) {
+ if (true) {
+ ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
+ // Paper end
if (this.loadedChunks.add(chunkcoordintpair.pair())) {
chunk.setLoaded(true);
this.world.a(chunk.getTileEntities().values());
@@ -1328,17 +1344,21 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
list.forEach(chunk::b);
}
}
-
- return chunk;
- } // Paper
- });
- }, (runnable) -> {
- Mailbox mailbox = this.mailboxMain;
- long i = playerchunk.i().pair();
-
- playerchunk.getClass();
- mailbox.a(ChunkTaskQueueSorter.a(runnable, i, () -> 1)); // Paper - final loads are always urgent!
- });
+ // Paper start
+ }
+ }
+ // Move code up
+// return chunk;
+// } // Paper
+// });
+// }, (runnable) -> {
+// Mailbox mailbox = this.mailboxMain;
+// long i = playerchunk.i().pair();
+//
+// playerchunk.getClass();
+// mailbox.a(ChunkTaskQueueSorter.a(runnable, i, () -> 1)); // Paper - final loads are always urgent!
+// });
+ // Paper end
}
// Paper start