mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-06 00:07:56 +01:00
Another attempt at unload queue, including EAR improvements.
should be fully working now as I pretty much fell back to existing methods so anything touching the unloadQueue set should behave correctly. And maintained NMS Reflection safe change too
This commit is contained in:
parent
4646f9b68f
commit
ae95189944
@ -20,6 +20,8 @@ We mark the chunk as active in many places that notify it is still being used, s
|
|||||||
when the chunk unload queue reaches that chunk, and sees the chunk became active again,
|
when the chunk unload queue reaches that chunk, and sees the chunk became active again,
|
||||||
it will skip it and move to next.
|
it will skip it and move to next.
|
||||||
|
|
||||||
|
Also optimize EAR to use these methods.
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/net/minecraft/server/Chunk.java
|
--- a/src/main/java/net/minecraft/server/Chunk.java
|
||||||
@ -33,22 +35,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
// Paper end
|
// Paper end
|
||||||
|
|
||||||
// CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking
|
// CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking
|
||||||
@@ -0,0 +0,0 @@ public class Chunk {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addEntities() {
|
|
||||||
+ isChunkActive = true; // Paper
|
|
||||||
this.i = true;
|
|
||||||
this.world.b(this.tileEntities.values());
|
|
||||||
|
|
||||||
@@ -0,0 +0,0 @@ public class Chunk {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeEntities() {
|
|
||||||
+ isChunkActive = false; // Paper
|
|
||||||
this.i = false;
|
|
||||||
Iterator iterator = this.tileEntities.values().iterator();
|
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||||
@ -63,45 +49,65 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
private final IChunkLoader chunkLoader;
|
private final IChunkLoader chunkLoader;
|
||||||
public LongObjectHashMap<Chunk> chunks = new LongObjectHashMap<Chunk>(); // CraftBukkit
|
public LongObjectHashMap<Chunk> chunks = new LongObjectHashMap<Chunk>(); // CraftBukkit
|
||||||
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||||
|
return (chunk == null) ? getChunkAt(x, z) : chunk;
|
||||||
|
}
|
||||||
|
|
||||||
// CraftBukkit start - Add async variant, provide compatibility
|
- public Chunk getChunkIfLoaded(int x, int z) {
|
||||||
public Chunk getOrCreateChunkFast(int x, int z) {
|
- return chunks.get(LongHash.toLong(x, z));
|
||||||
- Chunk chunk = chunks.get(LongHash.toLong(x, z));
|
|
||||||
- return (chunk == null) ? getChunkAt(x, z) : chunk;
|
|
||||||
+ return getChunkAt(x, z); // Paper
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // Paper start
|
+ // Paper start
|
||||||
+ public Chunk getLoadedChunkAtWithoutMarkingActive(int i, int j) {
|
+ public Chunk getLoadedChunkAtWithoutMarkingActive(int i, int j) {
|
||||||
+ return chunks.get(LongHash.toLong(i, j));
|
+ return chunks.get(LongHash.toLong(i, j));
|
||||||
}
|
}
|
||||||
|
|
||||||
- public Chunk getChunkIfLoaded(int x, int z) {
|
|
||||||
- return chunks.get(LongHash.toLong(x, z));
|
|
||||||
+ // getChunkIfLoaded -> getChunkIfActive
|
+ // getChunkIfLoaded -> getChunkIfActive
|
||||||
+ // this is only used by CraftBukkit now, and plugins shouldnt mark things active
|
+ // this is only used by CraftBukkit now, and plugins shouldnt mark things active
|
||||||
+ public Chunk getChunkIfActive(int x, int z) {
|
+ public Chunk getChunkIfActive(int x, int z) {
|
||||||
+ Chunk chunk = chunks.get(LongHash.toLong(x, z));
|
+ Chunk chunk = chunks.get(LongHash.toLong(x, z));
|
||||||
+ return (chunk != null && chunk.isChunkActive) ? chunk : null;
|
+ return (chunk != null && chunk.isChunkActive) ? chunk : null;
|
||||||
}
|
+ }
|
||||||
+ // Paper end
|
+ // Paper end
|
||||||
|
+
|
||||||
public Chunk getLoadedChunkAt(int i, int j) {
|
public Chunk getLoadedChunkAt(int i, int j) {
|
||||||
Chunk chunk = chunks.get(LongHash.toLong(i, j)); // CraftBukkit
|
Chunk chunk = chunks.get(LongHash.toLong(i, j)); // CraftBukkit
|
||||||
|
|
||||||
this.unloadQueue.remove(i, j); // CraftBukkit
|
- this.unloadQueue.remove(i, j); // CraftBukkit
|
||||||
+ if (chunk != null) { chunk.isChunkActive = true; }// Paper
|
+ //this.unloadQueue.remove(i, j); // CraftBukkit // Paper
|
||||||
|
+ markChunkActive(chunk); // Paper
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||||
runnable.run();
|
// CraftBukkit end
|
||||||
}
|
}
|
||||||
|
|
||||||
+ chunk.isChunkActive = true; // Paper
|
+ markChunkActive(chunk); // Paper
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chunk getChunkAt(int i, int j, Runnable runnable) {
|
||||||
|
- unloadQueue.remove(i, j);
|
||||||
|
+ //unloadQueue.remove(i, j); // Paper
|
||||||
|
Chunk chunk = chunks.get(LongHash.toLong(i, j));
|
||||||
|
ChunkRegionLoader loader = null;
|
||||||
|
|
||||||
|
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||||
|
if (runnable != null) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
+ markChunkActive(chunk); // Paper
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chunk originalGetChunkAt(int i, int j) {
|
||||||
|
- this.unloadQueue.remove(i, j);
|
||||||
|
+ //this.unloadQueue.remove(i, j); // Paper
|
||||||
|
Chunk chunk = this.chunks.get(LongHash.toLong(i, j));
|
||||||
|
boolean newChunk = false;
|
||||||
|
// CraftBukkit end
|
||||||
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -111,6 +117,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
if (neighbor != null) {
|
if (neighbor != null) {
|
||||||
neighbor.setNeighborLoaded(-x, -z);
|
neighbor.setNeighborLoaded(-x, -z);
|
||||||
chunk.setNeighborLoaded(x, z);
|
chunk.setNeighborLoaded(x, z);
|
||||||
|
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||||
|
chunk.loadNearby(this, this.chunkGenerator);
|
||||||
|
world.timings.syncChunkLoadTimer.stopTiming(); // Spigot
|
||||||
|
}
|
||||||
|
+ markChunkActive(chunk); // Paper
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||||
if (!this.world.savingDisabled) {
|
if (!this.world.savingDisabled) {
|
||||||
// CraftBukkit start
|
// CraftBukkit start
|
||||||
@ -148,19 +162,66 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
}
|
}
|
||||||
+
|
+
|
||||||
+ // Paper start
|
+ // Paper start
|
||||||
+ public class ChunkUnloadQueue extends java.util.LinkedList<Chunk> {
|
+ public static void markChunkActive(Chunk chunk) {
|
||||||
+ public void remove(int x, int z) {
|
+ if (chunk != null) {
|
||||||
+ // nothing! Just to reduce diff
|
+ chunk.isChunkActive = true;
|
||||||
+ }
|
+ }
|
||||||
+ public void add(int x, int z) {
|
+ }
|
||||||
|
+ public class ChunkUnloadQueue extends LongHashSet { // Provide compat with NMS plugins
|
||||||
|
+ private java.util.LinkedList<Chunk> unloadQueue = new java.util.LinkedList<Chunk>();
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean isEmpty() {
|
||||||
|
+ return unloadQueue.isEmpty();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean contains(long value) {
|
||||||
|
+ throw new UnsupportedOperationException("contains on unload queue");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean add(long value) {
|
||||||
|
+ throw new UnsupportedOperationException("add on unload queue");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean remove(long value) {
|
||||||
|
+ throw new UnsupportedOperationException("remove on unload queue");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public int size() {
|
||||||
|
+ return unloadQueue.size();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Iterator iterator() {
|
||||||
|
+ return unloadQueue.iterator();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean contains(int x, int z) {
|
||||||
|
+ final Chunk chunk = chunks.get(LongHash.toLong(x, z));
|
||||||
|
+ return (chunk != null && chunk.isInUnloadQueue);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public void remove(int x, int z) {
|
||||||
|
+ final Chunk chunk = chunks.get(LongHash.toLong(x, z));
|
||||||
|
+ if (chunk != null) {
|
||||||
|
+ chunk.isChunkActive = true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ public boolean add(int x, int z) {
|
||||||
+ final Chunk chunk = chunks.get(LongHash.toLong(x, z));
|
+ final Chunk chunk = chunks.get(LongHash.toLong(x, z));
|
||||||
+ if (chunk != null) {
|
+ if (chunk != null) {
|
||||||
+ chunk.isChunkActive = false;
|
+ chunk.isChunkActive = false;
|
||||||
+ if (!chunk.isInUnloadQueue) {
|
+ if (!chunk.isInUnloadQueue) {
|
||||||
+ chunk.isInUnloadQueue = true;
|
+ chunk.isInUnloadQueue = true;
|
||||||
+ add(chunk);
|
+ return unloadQueue.add(chunk);
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
|
+ return false;
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ // Paper end
|
+ // Paper end
|
||||||
@ -183,7 +244,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
--- a/src/main/java/net/minecraft/server/World.java
|
--- a/src/main/java/net/minecraft/server/World.java
|
||||||
+++ b/src/main/java/net/minecraft/server/World.java
|
+++ b/src/main/java/net/minecraft/server/World.java
|
||||||
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
|
||||||
}
|
// Paper end
|
||||||
|
|
||||||
public Chunk getChunkIfLoaded(int x, int z) {
|
public Chunk getChunkIfLoaded(int x, int z) {
|
||||||
- return ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x, z);
|
- return ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x, z);
|
||||||
@ -222,14 +283,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
neighbor.setNeighborUnloaded(-xx, -zz);
|
neighbor.setNeighborUnloaded(-xx, -zz);
|
||||||
chunk.setNeighborUnloaded(xx, zz);
|
chunk.setNeighborUnloaded(xx, zz);
|
||||||
@@ -0,0 +0,0 @@ public class CraftWorld implements World {
|
@@ -0,0 +0,0 @@ public class CraftWorld implements World {
|
||||||
world.timings.syncChunkLoadTimer.startTiming(); // Spigot
|
// Use the default variant of loadChunk when generate == true.
|
||||||
chunk = world.getChunkProviderServer().getOrLoadChunkAt(x, z);
|
return world.getChunkProviderServer().getChunkAt(x, z) != null;
|
||||||
world.timings.syncChunkLoadTimer.stopTiming(); // Spigot
|
}
|
||||||
- }
|
+ if (true) { return world.getChunkProviderServer().getOrLoadChunkAt(x, z) != null; } // Paper
|
||||||
+ } else { chunk.isChunkActive = true; } // Paper
|
|
||||||
return chunk != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
world.getChunkProviderServer().unloadQueue.remove(x, z);
|
||||||
|
net.minecraft.server.Chunk chunk = world.getChunkProviderServer().chunks.get(LongHash.toLong(x, z));
|
||||||
@@ -0,0 +0,0 @@ public class CraftWorld implements World {
|
@@ -0,0 +0,0 @@ public class CraftWorld implements World {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -244,7 +304,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||||||
|
|
||||||
// Already unloading?
|
// Already unloading?
|
||||||
- if (cps.unloadQueue.contains(chunk.locX, chunk.locZ)) {
|
- if (cps.unloadQueue.contains(chunk.locX, chunk.locZ)) {
|
||||||
+ if (!chunk.isChunkActive) { // Paper
|
+ if (chunk.isInUnloadQueue) { // Paper
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,12 +325,25 @@ diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org
|
|||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
||||||
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
||||||
|
@@ -0,0 +0,0 @@ public class ActivationRange
|
||||||
|
{
|
||||||
|
for ( int j1 = k; j1 <= l; ++j1 )
|
||||||
|
{
|
||||||
|
- if ( world.getWorld().isChunkLoaded( i1, j1 ) )
|
||||||
|
- {
|
||||||
|
- activateChunkEntities( world.getChunkAt( i1, j1 ) );
|
||||||
|
+ Chunk chunk = world.getChunkIfActive(i1, j1); // Paper
|
||||||
|
+ if (chunk != null) { // Paper
|
||||||
|
+ activateChunkEntities( chunk ); // Paper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +0,0 @@ public class ActivationRange
|
@@ -0,0 +0,0 @@ public class ActivationRange
|
||||||
int x = MathHelper.floor( entity.locX );
|
int x = MathHelper.floor( entity.locX );
|
||||||
int z = MathHelper.floor( entity.locZ );
|
int z = MathHelper.floor( entity.locZ );
|
||||||
// Make sure not on edge of unloaded chunk
|
// Make sure not on edge of unloaded chunk
|
||||||
- Chunk chunk = entity.world.getChunkIfLoaded( x >> 4, z >> 4 );
|
- Chunk chunk = entity.world.getChunkIfLoaded( x >> 4, z >> 4 );
|
||||||
+ Chunk chunk = entity.world.getChunkIfActive( x >> 4, z >> 4 ); // Paper
|
+ Chunk chunk = isActive ? entity.world.getChunkIfActive( x >> 4, z >> 4 ) : null; // Paper
|
||||||
if ( isActive && !( chunk != null && chunk.areNeighborsLoaded( 1 ) ) )
|
if ( isActive && !( chunk != null && chunk.areNeighborsLoaded( 1 ) ) )
|
||||||
{
|
{
|
||||||
isActive = false;
|
isActive = false;
|
Loading…
Reference in New Issue
Block a user