diff --git a/PlotSquared/pom.xml b/PlotSquared/pom.xml
index a6d8e7024..abb846454 100644
--- a/PlotSquared/pom.xml
+++ b/PlotSquared/pom.xml
@@ -8,7 +8,7 @@
 	    UTF-8
 	
     PlotSquared
-    2.9.7
+    2.9.8
     PlotSquared
     jar
     
diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/listeners/ChunkListener.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/listeners/ChunkListener.java
index b40529317..dda9e29fe 100644
--- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/listeners/ChunkListener.java
+++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/listeners/ChunkListener.java
@@ -1,5 +1,6 @@
 package com.intellectualcrafters.plot.listeners;
 
+import org.bukkit.Bukkit;
 import org.bukkit.Chunk;
 import org.bukkit.Material;
 import org.bukkit.block.BlockState;
@@ -11,34 +12,91 @@ import org.bukkit.event.world.ChunkUnloadEvent;
 
 import com.intellectualcrafters.plot.PlotSquared;
 import com.intellectualcrafters.plot.config.Settings;
+import com.intellectualcrafters.plot.util.TaskManager;
 
 public class ChunkListener implements Listener {
     
     @EventHandler
     public void onChunkUnload(ChunkUnloadEvent event) {
-        processChunk(event.getChunk());
+        if (!forceUnload) {
+            if (processChunk(event.getChunk(), true)) {
+                event.setCancelled(true);
+            }
+        }
     }
     
     @EventHandler
     public void onChunkLoad(ChunkLoadEvent event) {
-        processChunk(event.getChunk());
+        processChunk(event.getChunk(), false);
+    }
+
+    public void cleanChunk(final Chunk chunk) {
+        TaskManager.index.increment();
+        final Integer currentIndex = TaskManager.index.toInteger();
+        final Integer task = TaskManager.runTaskRepeat(new Runnable() {
+            @Override
+            public void run() {
+                if (!chunk.isLoaded()) {
+                    Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex));
+                    TaskManager.tasks.remove(currentIndex);
+                    PlotSquared.log("&aSuccessfully processed and unloaded chunk!");
+                    chunk.unload(true, true);
+                    return;
+                }
+                BlockState[] tiles = chunk.getTileEntities();
+                if (tiles.length == 0) {
+                    Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex));
+                    TaskManager.tasks.remove(currentIndex);
+                    PlotSquared.log("&aSuccessfully processed and unloaded chunk!");
+                    chunk.unload(true, true);
+                    return;
+                }
+                long start = System.currentTimeMillis();
+                int i = 0;
+                while (System.currentTimeMillis() - start < 50) {
+                    if (i >= tiles.length) {
+                        Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex));
+                        TaskManager.tasks.remove(currentIndex);
+                        PlotSquared.log("&aSuccessfully processed and unloaded chunk!");
+                        chunk.unload(true, true);
+                        return;
+                    }
+                    tiles[i].getBlock().setType(Material.AIR, false);
+                    i++;
+                }
+            }
+        }, 1);
+        TaskManager.tasks.put(currentIndex, task);
     }
     
-    public void processChunk(Chunk chunk) {
+    private boolean forceUnload = false;
+    
+    public boolean processChunk(Chunk chunk, boolean unload) {
         if (!PlotSquared.isPlotWorld(chunk.getWorld().getName())) {
-            return;
+            return false;
         }
         Entity[] entities = chunk.getEntities();
         BlockState[] tiles = chunk.getTileEntities();
         if (tiles.length > Settings.CHUNK_PROCESSOR_MAX_BLOCKSTATES) {
+            if (unload) {
+                PlotSquared.log("&cPlotSquared detected unsafe chunk: " + (chunk.getX() << 4) + "," + (chunk.getX() << 4));
+                cleanChunk(chunk);
+                return true;
+            }
             for (BlockState tile : tiles) {
                 tile.getBlock().setType(Material.AIR, false);
             }
         }
         if (entities.length > Settings.CHUNK_PROCESSOR_MAX_ENTITIES) {
+            if (unload) {
+                System.out.print("FORCE UNLOAD");
+                chunk.load(true);
+                return false;
+            }
             for (Entity ent : entities) {
                 ent.remove();
             }
         }
+        return false;
     }
 }