From 6e3ee31336dcec939139cc97cab11d98fb99145d Mon Sep 17 00:00:00 2001
From: Erik Broes <erikbroes@grum.nl>
Date: Sun, 20 Feb 2011 17:09:02 +0100
Subject: [PATCH] Prevent Blocks from getting lost when a chunk reloads

---
 src/main/java/net/minecraft/server/Chunk.java          |  5 ++++-
 .../java/net/minecraft/server/ChunkProviderServer.java |  2 ++
 src/main/java/org/bukkit/craftbukkit/CraftChunk.java   |  6 +++++-
 src/main/java/org/bukkit/craftbukkit/CraftWorld.java   | 10 ++++++++++
 4 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index e37db53fe0..592e34086b 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -44,7 +44,10 @@ public class Chunk {
         }
 
         // CraftBukkit start
-        bukkitChunk = new org.bukkit.craftbukkit.CraftChunk( this );
+        bukkitChunk = ((WorldServer) world).getWorld().popPreservedChunk( i, j );
+        if (bukkitChunk == null) {
+            bukkitChunk = new org.bukkit.craftbukkit.CraftChunk( this );
+        }
     }
 
     public org.bukkit.Chunk bukkitChunk;
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 87beef5755..e6b4be5efd 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -209,6 +209,8 @@ public class ChunkProviderServer implements IChunkProvider
                 ChunkUnloadEvent cue = new ChunkUnloadEvent(Type.CHUNK_UNLOADED, chunk.bukkitChunk);
                 server.getPluginManager().callEvent(cue);
                 if (!cue.isCancelled()) {
+                    g.getWorld().preserveChunk( (CraftChunk) chunk.bukkitChunk );
+
                     chunk.e();
                     this.b(chunk);
                     this.a(chunk);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
index db700abfad..592e12033e 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
@@ -11,7 +11,7 @@ import org.bukkit.block.Block;
 import org.bukkit.craftbukkit.block.CraftBlock;
 
 public class CraftChunk implements Chunk {
-    private final net.minecraft.server.Chunk chunk;
+    private net.minecraft.server.Chunk chunk;
     private final HashMap<Integer, Block> cache = new HashMap<Integer, Block>();
 
     public CraftChunk(net.minecraft.server.Chunk chunk) {
@@ -48,4 +48,8 @@ public class CraftChunk implements Chunk {
         }
         return block;
     }
+
+    public void breakLink() {
+        this.chunk = null;
+    }
 }
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 7be7c4586b..2f3fe70563 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -28,6 +28,7 @@ public class CraftWorld implements World {
     private final Environment environment;
     private final CraftServer server;
     private final ChunkProviderServer provider;
+    private HashMap<Integer,CraftChunk> unloadedChunks = new HashMap<Integer, CraftChunk>();
 
     private static final Random rand = new Random();
 
@@ -45,6 +46,15 @@ public class CraftWorld implements World {
         server.addWorld(this);
     }
 
+    public void preserveChunk( CraftChunk chunk ) {
+        chunk.breakLink();
+        unloadedChunks.put( chunk.getX() << 16 + chunk.getZ(), chunk );
+    }
+
+    public CraftChunk popPreservedChunk( int x, int z ) {
+        return unloadedChunks.remove( x << 16 + z );
+    }
+
     public Block getBlockAt(int x, int y, int z) {
         return getChunkAt(x >> 4, z >> 4).getBlock(x & 0xF, y & 0x7F, z & 0xF);
     }