summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/java/net/minecraft/server/Chunk.java28
-rw-r--r--src/main/java/net/minecraft/server/ChunkProviderServer.java38
-rw-r--r--src/main/java/net/minecraft/server/World.java14
-rw-r--r--src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java17
4 files changed, 92 insertions, 5 deletions
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index ade0c35b..d770e4e6 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -41,6 +41,34 @@ public class Chunk {
public long s;
private int x;
+ // CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking
+ private int neighbors = 0x1 << 12;
+
+ public boolean areNeighborsLoaded(final int radius) {
+ switch(radius) {
+ case 2:
+ return this.neighbors == Integer.MAX_VALUE >> 6;
+ case 1:
+ final int mask =
+ // x z offset x z offset x z offset
+ ( 0x1 << (1 * 5 + 1 + 12) ) | ( 0x1 << (0 * 5 + 1 + 12) ) | ( 0x1 << (-1 * 5 + 1 + 12) ) |
+ ( 0x1 << (1 * 5 + 0 + 12) ) | ( 0x1 << (0 * 5 + 0 + 12) ) | ( 0x1 << (-1 * 5 + 0 + 12) ) |
+ ( 0x1 << (1 * 5 + -1 + 12) ) | ( 0x1 << (0 * 5 + -1 + 12) ) | ( 0x1 << (-1 * 5 + -1 + 12) );
+ return (this.neighbors & mask) == mask;
+ default:
+ throw new UnsupportedOperationException(String.valueOf(radius));
+ }
+ }
+
+ public void setNeighborLoaded(final int x, final int z) {
+ this.neighbors |= 0x1 << (x * 5 + 12 + z);
+ }
+
+ public void setNeighborUnloaded(final int x, final int z) {
+ this.neighbors &= ~(0x1 << (x * 5 + 12 + z));
+ }
+ // CraftBukkit end
+
public Chunk(World world, int i, int j) {
this.sections = new ChunkSection[16];
this.v = new byte[256];
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 1b22934d..8cc2efd4 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -94,6 +94,10 @@ public class ChunkProviderServer implements IChunkProvider {
}
// CraftBukkit start - Add async variant, provide compatibility
+ public Chunk getChunkIfLoaded(int x, int z) {
+ return this.chunks.get(LongHash.toLong(x, z));
+ }
+
public Chunk getChunkAt(int i, int j) {
return getChunkAt(i, j, null);
}
@@ -166,6 +170,21 @@ public class ChunkProviderServer implements IChunkProvider {
*/
server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(chunk.bukkitChunk, newChunk));
}
+
+ // Update neighbor counts
+ for (int x = -2; x < 3; x++) {
+ for (int z = -2; z < 3; z++) {
+ if (x == 0 && z == 0) {
+ continue;
+ }
+
+ Chunk neighbor = this.getChunkIfLoaded(chunk.locX + x, chunk.locZ + z);
+ if (neighbor != null) {
+ neighbor.setNeighborLoaded(-x, -z);
+ chunk.setNeighborLoaded(x, z);
+ }
+ }
+ }
// CraftBukkit end
chunk.a(this, this, i, j);
}
@@ -327,6 +346,21 @@ public class ChunkProviderServer implements IChunkProvider {
// this.unloadQueue.remove(olong);
// this.chunks.remove(olong.longValue());
+
+ // Update neighbor counts
+ for (int x = -2; x < 3; x++) {
+ for (int z = -2; z < 3; z++) {
+ if (x == 0 && z == 0) {
+ continue;
+ }
+
+ Chunk neighbor = this.getChunkIfLoaded(chunk.locX + x, chunk.locZ + z);
+ if (neighbor != null) {
+ neighbor.setNeighborUnloaded(-x, -z);
+ chunk.setNeighborUnloaded(x, z);
+ }
+ }
+ }
}
}
// CraftBukkit end
@@ -357,8 +391,8 @@ public class ChunkProviderServer implements IChunkProvider {
}
public int getLoadedChunks() {
- // CraftBukkit - this.chunks.count() -> .values().size()
- return this.chunks.values().size();
+ // CraftBukkit - this.chunks.count() -> this.chunks.size()
+ return this.chunks.size();
}
public void recreateStructures(int i, int j) {}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index af7069cb..eb5da2af 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -115,6 +115,10 @@ public abstract class World implements IBlockAccess {
return (CraftServer) Bukkit.getServer();
}
+ public Chunk getChunkIfLoaded(int x, int z) {
+ return ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x, z);
+ }
+
// Changed signature - added gen and env
public World(IDataManager idatamanager, String s, WorldSettings worldsettings, WorldProvider worldprovider, MethodProfiler methodprofiler, ChunkGenerator gen, org.bukkit.World.Environment env) {
this.generator = gen;
@@ -1396,7 +1400,10 @@ public abstract class World implements IBlockAccess {
int j = MathHelper.floor(entity.locZ);
byte b0 = 32;
- if (!flag || this.b(i - b0, 0, j - b0, i + b0, 0, j + b0)) {
+ // CraftBukkit start - Use neighbor cache instead of looking up
+ Chunk startingChunk = this.getChunkIfLoaded(i >> 4, j >> 4);
+ if (!flag || (startingChunk != null && startingChunk.areNeighborsLoaded(2)) /* this.b(i - b0, 0, j - b0, i + b0, 0, j + b0) */) {
+ // CraftBukkit end
entity.S = entity.locX;
entity.T = entity.locY;
entity.U = entity.locZ;
@@ -2165,7 +2172,10 @@ public abstract class World implements IBlockAccess {
}
public boolean c(EnumSkyBlock enumskyblock, int i, int j, int k) {
- if (!this.areChunksLoaded(i, j, k, 17)) {
+ // CraftBukkit start - Use neighbor cache instead of looking up
+ Chunk chunk = this.getChunkIfLoaded(i >> 4, k >> 4);
+ if (chunk == null || !chunk.areNeighborsLoaded(1) /* !this.areChunksLoaded(i, j, k, 17)*/) {
+ // CraftBukkit end
return false;
} else {
int l = 0;
diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
index 8feadd11..1440349b 100644
--- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
+++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
@@ -28,7 +28,7 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu
// sync stuff
public void callStage2(QueuedChunk queuedChunk, Chunk chunk) throws RuntimeException {
- if(chunk == null) {
+ if (chunk == null) {
// If the chunk loading failed just do it synchronously (may generate)
queuedChunk.provider.originalGetChunkAt(queuedChunk.x, queuedChunk.z);
return;
@@ -48,6 +48,21 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu
server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(chunk.bukkitChunk, false));
}
+ // Update neighbor counts
+ for (int x = -2; x < 3; x++) {
+ for (int z = -2; z < 3; z++) {
+ if (x == 0 && z == 0) {
+ continue;
+ }
+
+ Chunk neighbor = queuedChunk.provider.getChunkIfLoaded(chunk.locX + x, chunk.locZ + z);
+ if (neighbor != null) {
+ neighbor.setNeighborLoaded(-x, -z);
+ chunk.setNeighborLoaded(x, z);
+ }
+ }
+ }
+
chunk.a(queuedChunk.provider, queuedChunk.provider, queuedChunk.x, queuedChunk.z);
}