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