--- a/net/minecraft/server/PlayerChunkMap.java +++ b/net/minecraft/server/PlayerChunkMap.java @@ -15,6 +15,10 @@ import java.util.function.Predicate; import javax.annotation.Nullable; +// CraftBukkit start +import java.util.LinkedList; +// CraftBukkit end + public class PlayerChunkMap { private static final Predicate a = (entityplayer) -> { @@ -34,6 +38,7 @@ private long k; private boolean l = true; private boolean m = true; + private boolean wasNotEmpty; // CraftBukkit - add field public PlayerChunkMap(WorldServer worldserver) { this.world = worldserver; @@ -107,16 +112,18 @@ if (this.l && i % 4L == 0L) { this.l = false; - Collections.sort(this.h, (playerchunk, playerchunk1) -> { - return ComparisonChain.start().compare(playerchunk.g(), playerchunk1.g()).result(); + // CraftBukkit start + Collections.sort(this.h, (playerchunkx, playerchunk1x) -> { + return ComparisonChain.start().compare(playerchunkx.g(), playerchunk1x.g()).result(); }); } if (this.m && i % 4L == 2L) { this.m = false; - Collections.sort(this.g, (playerchunk, playerchunk1) -> { - return ComparisonChain.start().compare(playerchunk.g(), playerchunk1.g()).result(); + Collections.sort(this.g, (playerchunkx, playerchunk1x) -> { + return ComparisonChain.start().compare(playerchunkx.g(), playerchunk1x.g()).result(); }); + // CraftBukkit end } if (!this.h.isEmpty()) { @@ -141,7 +148,11 @@ break; } } + // CraftBukkit start - SPIGOT-2891: remove once chunk has been provided + } else { + iterator1.remove(); } + // CraftBukkit end } } @@ -203,6 +214,16 @@ return playerchunk; } + // CraftBukkit start - add method + public final boolean isChunkInUse(int x, int z) { + PlayerChunk pi = getChunk(x, z); + if (pi != null) { + return (pi.c.size() > 0); + } + return false; + } + // CraftBukkit end + public void flagDirty(BlockPosition blockposition) { int i = blockposition.getX() >> 4; int j = blockposition.getZ() >> 4; @@ -221,12 +242,22 @@ entityplayer.d = entityplayer.locX; entityplayer.e = entityplayer.locZ; + + // CraftBukkit start - Load nearby chunks first + List chunkList = new LinkedList(); + for (int k = i - this.j; k <= i + this.j; ++k) { for (int l = j - this.j; l <= j + this.j; ++l) { - this.c(k, l).a(entityplayer); + chunkList.add(new ChunkCoordIntPair(k, l)); } } + Collections.sort(chunkList, new ChunkCoordComparator(entityplayer)); + for (ChunkCoordIntPair pair : chunkList) { + this.c(pair.x, pair.z).a(entityplayer); + } + // CraftBukkit end + this.managedPlayers.add(entityplayer); this.e(); } @@ -270,11 +301,14 @@ int j1 = i - k; int k1 = j - l; + List chunksToLoad = new LinkedList(); // CraftBukkit + if (j1 != 0 || k1 != 0) { for (int l1 = i - i1; l1 <= i + i1; ++l1) { for (int i2 = j - i1; i2 <= j + i1; ++i2) { if (!this.a(l1, i2, k, l, i1)) { - this.c(l1, i2).a(entityplayer); + // this.c(l1, i2).a(entityplayer); + chunksToLoad.add(new ChunkCoordIntPair(l1, i2)); // CraftBukkit } if (!this.a(l1 - j1, i2 - k1, i, j, i1)) { @@ -290,6 +324,13 @@ entityplayer.d = entityplayer.locX; entityplayer.e = entityplayer.locZ; this.e(); + + // CraftBukkit start - send nearest chunks first + Collections.sort(chunksToLoad, new ChunkCoordComparator(entityplayer)); + for (ChunkCoordIntPair pair : chunksToLoad) { + this.c(pair.x, pair.z).a(entityplayer); + } + // CraftBukkit end } } } @@ -374,4 +415,47 @@ } } + + // CraftBukkit start - Sorter to load nearby chunks first + private static class ChunkCoordComparator implements java.util.Comparator { + private int x; + private int z; + + public ChunkCoordComparator (EntityPlayer entityplayer) { + x = (int) entityplayer.locX >> 4; + z = (int) entityplayer.locZ >> 4; + } + + public int compare(ChunkCoordIntPair a, ChunkCoordIntPair b) { + if (a.equals(b)) { + return 0; + } + + // Subtract current position to set center point + int ax = a.x - this.x; + int az = a.z - this.z; + int bx = b.x - this.x; + int bz = b.z - this.z; + + int result = ((ax - bx) * (ax + bx)) + ((az - bz) * (az + bz)); + if (result != 0) { + return result; + } + + if (ax < 0) { + if (bx < 0) { + return bz - az; + } else { + return -1; + } + } else { + if (bx < 0) { + return 1; + } else { + return az - bz; + } + } + } + } + // CraftBukkit end }