summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nms-patches/Chunk.patch64
-rw-r--r--nms-patches/ChunkProviderServer.patch124
-rw-r--r--src/main/java/org/bukkit/craftbukkit/CraftWorld.java88
-rw-r--r--src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java22
4 files changed, 135 insertions, 163 deletions
diff --git a/nms-patches/Chunk.patch b/nms-patches/Chunk.patch
index 3c963755..5a5ad49b 100644
--- a/nms-patches/Chunk.patch
+++ b/nms-patches/Chunk.patch
@@ -5,17 +5,18 @@
import org.apache.logging.log4j.Logger;
+import com.google.common.collect.Lists; // CraftBukkit
-+import org.bukkit.Bukkit; // CraftBukkit
++import org.bukkit.Server; // CraftBukkit
+
public class Chunk {
private static final Logger e = LogManager.getLogger();
-@@ -42,6 +45,34 @@
+@@ -42,6 +45,35 @@
private ConcurrentLinkedQueue<BlockPosition> y;
public boolean d;
+ // CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking
+ private int neighbors = 0x1 << 12;
++ public long chunkKey;
+
+ public boolean areNeighborsLoaded(final int radius) {
+ switch (radius) {
@@ -45,12 +46,13 @@
public Chunk(World world, int i, int j) {
this.sections = new ChunkSection[16];
this.g = new byte[256];
-@@ -62,8 +93,14 @@
+@@ -62,8 +94,15 @@
Arrays.fill(this.h, -999);
Arrays.fill(this.g, (byte) -1);
+ // CraftBukkit start
+ this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
++ this.chunkKey = ChunkCoordIntPair.a(this.locX, this.locZ);
}
+ public org.bukkit.Chunk bukkitChunk;
@@ -60,7 +62,7 @@
public Chunk(World world, ChunkSnapshot chunksnapshot, int i, int j) {
this(world, i, j);
boolean flag = true;
-@@ -467,7 +504,8 @@
+@@ -467,7 +506,8 @@
}
}
@@ -70,7 +72,7 @@
block.onPlace(this.world, blockposition, iblockdata);
}
-@@ -604,7 +642,15 @@
+@@ -604,7 +644,15 @@
@Nullable
public TileEntity a(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) {
@@ -87,7 +89,7 @@
if (tileentity == null) {
if (chunk_enumtileentitystate == Chunk.EnumTileEntityState.IMMEDIATE) {
-@@ -639,6 +685,13 @@
+@@ -639,6 +687,13 @@
tileentity.z();
this.tileEntities.put(blockposition, tileentity);
@@ -101,7 +103,7 @@
}
}
-@@ -681,9 +734,21 @@
+@@ -681,9 +736,21 @@
int i = aentityslice.length;
for (int j = 0; j < i; ++j) {
@@ -111,21 +113,21 @@
+ java.util.Iterator<Entity> iter = newList.iterator();
+ while (iter.hasNext()) {
+ Entity entity = iter.next();
-
-- this.world.c((Collection) entityslice);
++
+ // Do not pass along players, as doing so can get them stuck outside of time.
+ // (which for example disables inventory icon updates and prevents block breaking)
+ if (entity instanceof EntityPlayer) {
+ iter.remove();
+ }
+ }
-+
-+ this.world.c((Collection) newList);
+
+- this.world.c((Collection) entityslice);
++ this.world.c(newList);
+ // CraftBukkit end
}
}
-@@ -745,8 +810,8 @@
+@@ -745,8 +812,8 @@
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
@@ -136,7 +138,43 @@
}
}
}
-@@ -809,6 +874,29 @@
+@@ -773,7 +840,34 @@
+ return false;
+ }
+
+- public void loadNearby(IChunkProvider ichunkprovider, ChunkGenerator chunkgenerator) {
++ // CraftBukkit start
++ public void loadNearby(IChunkProvider ichunkprovider, ChunkGenerator chunkgenerator, boolean newChunk) {
++ Server server = world.getServer();
++ if (server != null) {
++ /*
++ * If it's a new world, the first few chunks are generated inside
++ * the World constructor. We can't reliably alter that, so we have
++ * no way of creating a CraftWorld/CraftServer at that point.
++ */
++ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(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 = getWorld().getChunkIfLoaded(locX + x, locZ + z);
++ if (neighbor != null) {
++ neighbor.setNeighborLoaded(-x, -z);
++ setNeighborLoaded(x, z);
++ }
++ }
++ }
++ // CraftBukkit end
++
+ Chunk chunk = ichunkprovider.getLoadedChunkAt(this.locX, this.locZ - 1);
+ Chunk chunk1 = ichunkprovider.getLoadedChunkAt(this.locX + 1, this.locZ);
+ Chunk chunk2 = ichunkprovider.getLoadedChunkAt(this.locX, this.locZ + 1);
+@@ -809,6 +903,29 @@
} else {
this.o();
chunkgenerator.recreateStructures(this.locX, this.locZ);
diff --git a/nms-patches/ChunkProviderServer.patch b/nms-patches/ChunkProviderServer.patch
index f6fa24c8..bb34c203 100644
--- a/nms-patches/ChunkProviderServer.patch
+++ b/nms-patches/ChunkProviderServer.patch
@@ -1,11 +1,10 @@
--- a/net/minecraft/server/ChunkProviderServer.java
+++ b/net/minecraft/server/ChunkProviderServer.java
-@@ -14,6 +14,12 @@
+@@ -14,6 +14,11 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+// CraftBukkit start
-+import org.bukkit.Server;
+import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor;
+import org.bukkit.event.world.ChunkUnloadEvent;
+// CraftBukkit end
@@ -13,7 +12,7 @@
public class ChunkProviderServer implements IChunkProvider {
private static final Logger a = LogManager.getLogger();
-@@ -69,6 +75,26 @@
+@@ -69,19 +74,82 @@
Chunk chunk = this.getLoadedChunkAt(i, j);
if (chunk == null) {
@@ -40,7 +39,12 @@
chunk = this.loadChunk(i, j);
if (chunk != null) {
this.chunks.put(ChunkCoordIntPair.a(i, j), chunk);
-@@ -80,8 +106,52 @@
+ chunk.addEntities();
+- chunk.loadNearby(this, this.chunkGenerator);
++ chunk.loadNearby(this, this.chunkGenerator, false); // CraftBukkit
+ }
+ }
+
return chunk;
}
@@ -89,50 +93,21 @@
+
+ public Chunk originalGetChunkAt(int i, int j) {
+ Chunk chunk = this.originalGetOrLoadChunkAt(i, j);
-+ boolean newChunk = false;
+ // CraftBukkit end
if (chunk == null) {
long k = ChunkCoordIntPair.a(i, j);
-@@ -97,9 +167,37 @@
- crashreportsystemdetails.a("Generator", (Object) this.chunkGenerator);
- throw new ReportedException(crashreport);
- }
-+ newChunk = true; // CraftBukkit
+@@ -100,7 +168,8 @@
this.chunks.put(k, chunk);
chunk.addEntities();
+- chunk.loadNearby(this, this.chunkGenerator);
+
-+ // CraftBukkit start
-+ Server server = world.getServer();
-+ if (server != null) {
-+ /*
-+ * If it's a new world, the first few chunks are generated inside
-+ * the World constructor. We can't reliably alter that, so we have
-+ * no way of creating a CraftWorld/CraftServer at that point.
-+ */
-+ 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.loadNearby(this, this.chunkGenerator);
++ chunk.loadNearby(this, this.chunkGenerator, true); // CraftBukkit
}
-@@ -146,10 +244,12 @@
+ return chunk;
+@@ -146,10 +215,12 @@
public boolean a(boolean flag) {
int i = 0;
@@ -148,33 +123,60 @@
if (flag) {
this.saveChunkNOP(chunk);
-@@ -182,6 +282,29 @@
+@@ -182,10 +253,12 @@
Chunk chunk = (Chunk) this.chunks.get(olong);
if (chunk != null && chunk.d) {
-+ // CraftBukkit start
-+ ChunkUnloadEvent event = new ChunkUnloadEvent(chunk.bukkitChunk);
-+ this.world.getServer().getPluginManager().callEvent(event);
-+ if (event.isCancelled()) {
+- chunk.removeEntities();
+- this.saveChunk(chunk);
+- this.saveChunkNOP(chunk);
+- this.chunks.remove(olong);
++ // CraftBukkit start - move unload logic to own method
++ if (!unloadChunk(chunk, true)) {
+ continue;
+ }
-+
-+ // 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
+
- chunk.removeEntities();
- this.saveChunk(chunk);
- this.saveChunkNOP(chunk);
+ ++i;
+ }
+ }
+@@ -197,6 +270,39 @@
+ return false;
+ }
+
++ // CraftBukkit start
++ public boolean unloadChunk(Chunk chunk, boolean save) {
++ ChunkUnloadEvent event = new ChunkUnloadEvent(chunk.bukkitChunk);
++ this.world.getServer().getPluginManager().callEvent(event);
++ if (event.isCancelled()) {
++ return 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 = this.getChunkIfLoaded(chunk.locX + x, chunk.locZ + z);
++ if (neighbor != null) {
++ neighbor.setNeighborUnloaded(-x, -z);
++ chunk.setNeighborUnloaded(x, z);
++ }
++ }
++ }
++ // Moved from unloadChunks above
++ chunk.removeEntities();
++ if (save) {
++ this.saveChunk(chunk);
++ this.saveChunkNOP(chunk);
++ }
++ this.chunks.remove(chunk.chunkKey);
++ return true;
++ }
++ // CraftBukkit end
++
+ public boolean e() {
+ return !this.world.savingDisabled;
+ }
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 3ee0b91e..2fe3eae8 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -187,47 +187,26 @@ public class CraftWorld implements World {
return false;
}
- return unloadChunk0(x, z, save, safe);
+ return unloadChunk0(x, z, save);
}
- private boolean unloadChunk0(int x, int z, boolean save, boolean safe) {
- net.minecraft.server.Chunk chunk = world.getChunkProviderServer().getChunkAt(x, z);
- if (chunk.mustSave) { // If chunk had previously been queued to save, must do save to avoid loss of that data
- save = true;
- }
-
- chunk.removeEntities(); // Always remove entities - even if discarding, need to get them out of world table
-
- if (save) {
- world.getChunkProviderServer().saveChunk(chunk);
- world.getChunkProviderServer().saveChunkNOP(chunk);
- }
-
- world.getChunkProviderServer().unloadQueue.remove(ChunkCoordIntPair.a(x, z));
- world.getChunkProviderServer().chunks.remove(ChunkCoordIntPair.a(x, z));
-
- // Update neighbor counts
- for (int xx = -2; xx < 3; xx++) {
- for (int zz = -2; zz < 3; zz++) {
- if (xx == 0 && zz == 0) {
- continue;
- }
-
- net.minecraft.server.Chunk neighbor = world.getChunkProviderServer().getChunkIfLoaded(chunk.locX + x, chunk.locZ + z);
- if (neighbor != null) {
- neighbor.setNeighborUnloaded(-xx, -zz);
- chunk.setNeighborUnloaded(xx, zz);
- }
- }
+ private boolean unloadChunk0(int x, int z, boolean save) {
+ net.minecraft.server.Chunk chunk = world.getChunkProviderServer().getChunkIfLoaded(x, z);
+ if (chunk == null) {
+ return true;
}
- return true;
+ // If chunk had previously been queued to save, must do save to avoid loss of that data
+ return world.getChunkProviderServer().unloadChunk(chunk, chunk.mustSave || save);
}
public boolean regenerateChunk(int x, int z) {
- unloadChunk0(x, z, false, false);
+ if (!unloadChunk0(x, z, false)) {
+ return false;
+ }
- world.getChunkProviderServer().unloadQueue.remove(ChunkCoordIntPair.a(x, z));
+ final long chunkKey = ChunkCoordIntPair.a(x, z);
+ world.getChunkProviderServer().unloadQueue.remove(chunkKey);
net.minecraft.server.Chunk chunk = null;
@@ -237,9 +216,14 @@ public class CraftWorld implements World {
playerChunk.chunk = chunk;
}
- chunkLoadPostProcess(chunk, x, z);
+ if (chunk != null) {
+ world.getChunkProviderServer().chunks.put(chunkKey, chunk);
- refreshChunk(x, z);
+ chunk.addEntities();
+ chunk.loadNearby(world.getChunkProviderServer(), world.getChunkProviderServer().chunkGenerator, true);
+
+ refreshChunk(x, z);
+ }
return chunk != null;
}
@@ -275,39 +259,7 @@ public class CraftWorld implements World {
return world.getChunkProviderServer().getChunkAt(x, z) != null;
}
- world.getChunkProviderServer().unloadQueue.remove(ChunkCoordIntPair.a(x, z));
- net.minecraft.server.Chunk chunk = world.getChunkProviderServer().chunks.get(ChunkCoordIntPair.a(x, z));
-
- if (chunk == null) {
- chunk = world.getChunkProviderServer().getOrLoadChunkAt(x, z);
- }
- return chunk != null;
- }
-
- private void chunkLoadPostProcess(net.minecraft.server.Chunk chunk, int cx, int cz) {
- if (chunk != null) {
- world.getChunkProviderServer().chunks.put(ChunkCoordIntPair.a(cx, cz), chunk);
-
- chunk.addEntities();
-
- // Update neighbor counts
- for (int x = -2; x < 3; x++) {
- for (int z = -2; z < 3; z++) {
- if (x == 0 && z == 0) {
- continue;
- }
-
- net.minecraft.server.Chunk neighbor = world.getChunkProviderServer().getLoadedChunkAt(chunk.locX + x, chunk.locZ + z);
- if (neighbor != null) {
- neighbor.setNeighborLoaded(-x, -z);
- chunk.setNeighborLoaded(x, z);
- }
- }
- }
- // CraftBukkit end
-
- chunk.loadNearby(world.getChunkProviderServer(), world.getChunkProviderServer().chunkGenerator);
- }
+ return world.getChunkProviderServer().getOrLoadChunkAt(x, z) != null;
}
public boolean isChunkLoaded(Chunk chunk) {
diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
index 1632f136..f1c1dc49 100644
--- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
+++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
@@ -48,27 +48,7 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu
queuedChunk.provider.chunkGenerator.recreateStructures(chunk, queuedChunk.x, queuedChunk.z);
}
- Server server = queuedChunk.provider.world.getServer();
- if (server != null) {
- 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.getLoadedChunkAt(chunk.locX + x, chunk.locZ + z);
- if (neighbor != null) {
- neighbor.setNeighborLoaded(-x, -z);
- chunk.setNeighborLoaded(x, z);
- }
- }
- }
-
- chunk.loadNearby(queuedChunk.provider, queuedChunk.provider.chunkGenerator);
+ chunk.loadNearby(queuedChunk.provider, queuedChunk.provider.chunkGenerator, false);
}
public void callStage3(QueuedChunk queuedChunk, Chunk chunk, Runnable runnable) throws RuntimeException {