#673: Fix Craftworld#isChunkLoaded

The flag for getChunkAt(int, int, ChunkStatus, boolean)
is actually a flag for whether to bring the underlying
PlayerChunk up to the required ticket level to load the
chunk. So, if the chunk is already at the required level,
but has not yet loaded, the call will actually either
start the load if it has not already been started and
block until completion.

This behaviour is not suitable for just
checking if the chunk is loaded.
This commit is contained in:
Spottedleaf 2020-06-06 19:23:46 +10:00 committed by md_5
parent 8637ec008d
commit fad2494af1
2 changed files with 30 additions and 15 deletions

View File

@ -1,6 +1,23 @@
--- a/net/minecraft/server/ChunkProviderServer.java --- a/net/minecraft/server/ChunkProviderServer.java
+++ b/net/minecraft/server/ChunkProviderServer.java +++ b/net/minecraft/server/ChunkProviderServer.java
@@ -95,7 +95,7 @@ @@ -51,6 +51,16 @@
this.clearCache();
}
+ // CraftBukkit start - properly implement isChunkLoaded
+ public boolean isChunkLoaded(int chunkX, int chunkZ) {
+ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(ChunkCoordIntPair.pair(chunkX, chunkZ));
+ if (chunk == null) {
+ return false;
+ }
+ return chunk.getFullChunk() != null;
+ }
+ // CraftBukkit end
+
@Override
public LightEngineThreaded getLightEngine() {
return this.lightEngine;
@@ -95,7 +105,7 @@
for (int l = 0; l < 4; ++l) { for (int l = 0; l < 4; ++l) {
if (k == this.cachePos[l] && chunkstatus == this.cacheStatus[l]) { if (k == this.cachePos[l] && chunkstatus == this.cacheStatus[l]) {
ichunkaccess = this.cacheChunk[l]; ichunkaccess = this.cacheChunk[l];
@ -9,7 +26,7 @@
return ichunkaccess; return ichunkaccess;
} }
} }
@@ -141,12 +141,12 @@ @@ -141,12 +151,12 @@
if (playerchunk == null) { if (playerchunk == null) {
return null; return null;
} else { } else {
@ -24,7 +41,7 @@
if (ichunkaccess1 != null) { if (ichunkaccess1 != null) {
this.a(k, ichunkaccess1, ChunkStatus.FULL); this.a(k, ichunkaccess1, ChunkStatus.FULL);
@@ -173,7 +173,15 @@ @@ -173,7 +183,15 @@
int l = 33 + ChunkStatus.a(chunkstatus); int l = 33 + ChunkStatus.a(chunkstatus);
PlayerChunk playerchunk = this.getChunk(k); PlayerChunk playerchunk = this.getChunk(k);
@ -41,7 +58,7 @@
this.chunkMapDistance.a(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); this.chunkMapDistance.a(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair);
if (this.a(playerchunk, l)) { if (this.a(playerchunk, l)) {
GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler();
@@ -192,7 +200,7 @@ @@ -192,7 +210,7 @@
} }
private boolean a(@Nullable PlayerChunk playerchunk, int i) { private boolean a(@Nullable PlayerChunk playerchunk, int i) {
@ -50,7 +67,7 @@
} }
public boolean isLoaded(int i, int j) { public boolean isLoaded(int i, int j) {
@@ -294,11 +302,31 @@ @@ -294,11 +312,31 @@
@Override @Override
public void close() throws IOException { public void close() throws IOException {
@ -83,7 +100,7 @@
public void tick(BooleanSupplier booleansupplier) { public void tick(BooleanSupplier booleansupplier) {
this.world.getMethodProfiler().enter("purge"); this.world.getMethodProfiler().enter("purge");
this.chunkMapDistance.purgeTickets(); this.chunkMapDistance.purgeTickets();
@@ -318,13 +346,19 @@ @@ -318,13 +356,19 @@
this.lastTickTime = i; this.lastTickTime = i;
WorldData worlddata = this.world.getWorldData(); WorldData worlddata = this.world.getWorldData();
boolean flag = worlddata.getType() == WorldType.DEBUG_ALL_BLOCK_STATES; boolean flag = worlddata.getType() == WorldType.DEBUG_ALL_BLOCK_STATES;
@ -105,7 +122,7 @@
this.world.getMethodProfiler().enter("naturalSpawnCount"); this.world.getMethodProfiler().enter("naturalSpawnCount");
int l = this.chunkMapDistance.b(); int l = this.chunkMapDistance.b();
@@ -353,8 +387,35 @@ @@ -353,8 +397,35 @@
for (int j1 = 0; j1 < i1; ++j1) { for (int j1 = 0; j1 < i1; ++j1) {
EnumCreatureType enumcreaturetype = aenumcreaturetype1[j1]; EnumCreatureType enumcreaturetype = aenumcreaturetype1[j1];
@ -142,7 +159,7 @@
if (object2intmap.getInt(enumcreaturetype) <= k1) { if (object2intmap.getInt(enumcreaturetype) <= k1) {
SpawnerCreature.a(enumcreaturetype, this.world, chunk, blockposition); SpawnerCreature.a(enumcreaturetype, this.world, chunk, blockposition);
@@ -507,12 +568,18 @@ @@ -507,12 +578,18 @@
@Override @Override
protected boolean executeNext() { protected boolean executeNext() {

View File

@ -340,8 +340,7 @@ public class CraftWorld implements World {
@Override @Override
public boolean isChunkLoaded(int x, int z) { public boolean isChunkLoaded(int x, int z) {
net.minecraft.server.Chunk chunk = world.getChunkProvider().getChunkAt(x, z, false); return world.getChunkProvider().isChunkLoaded(x, z);
return chunk != null;
} }
@Override @Override
@ -381,19 +380,18 @@ public class CraftWorld implements World {
@Override @Override
public boolean unloadChunkRequest(int x, int z) { public boolean unloadChunkRequest(int x, int z) {
net.minecraft.server.IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, false); if (isChunkLoaded(x, z)) {
if (chunk != null) { world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE);
world.getChunkProvider().removeTicket(TicketType.PLUGIN, chunk.getPos(), 1, Unit.INSTANCE);
} }
return true; return true;
} }
private boolean unloadChunk0(int x, int z, boolean save) { private boolean unloadChunk0(int x, int z, boolean save) {
net.minecraft.server.Chunk chunk = (net.minecraft.server.Chunk) world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, false); if (!isChunkLoaded(x, z)) {
if (chunk == null) {
return true; return true;
} }
net.minecraft.server.Chunk chunk = world.getChunkAt(x, z);
chunk.mustNotSave = !save; chunk.mustNotSave = !save;
unloadChunkRequest(x, z); unloadChunkRequest(x, z);