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;
}
}