diff --git a/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/bukkit/DebugSetBlockQueue.java b/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/bukkit/DebugSetBlockQueue.java index fc0d3e192..8cc2317e7 100644 --- a/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/bukkit/DebugSetBlockQueue.java +++ b/PlotSquared/src/main/java/com/intellectualcrafters/plot/util/bukkit/DebugSetBlockQueue.java @@ -1,84 +1,166 @@ package com.intellectualcrafters.plot.util.bukkit; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Map.Entry; import org.bukkit.Bukkit; -import org.bukkit.Chunk; import org.bukkit.World; import com.intellectualcrafters.plot.util.TaskManager; public class DebugSetBlockQueue { - private HashMap blocks; - private int allocate = 100; + private volatile static HashMap blocks; + private volatile static int allocate = 50; + private volatile static boolean running = false; + private volatile static boolean locked = false; + private volatile static HashSet runnables; - public void allocate(int t) { - this.allocate = t; + public synchronized static void allocate(int t) { + allocate = t; } - public DebugSetBlockQueue(final Runnable whenDone) { - blocks = new HashMap<>(); - TaskManager.index.increment(); - final int current = TaskManager.index.intValue(); - int task = TaskManager.runTaskRepeat(new Runnable() { - @Override - public void run() { - if (blocks.size() == 0) { - blocks = null; - Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(current)); - TaskManager.runTask(whenDone); - return; - } - long start = System.currentTimeMillis() + allocate; - Iterator> i = blocks.entrySet().iterator(); - while (System.currentTimeMillis() < start && i.hasNext()) { - Entry n = i.next(); - i.remove(); - Chunk chunk = n.getKey(); - int X = chunk.getX() << 4; - int Z = chunk.getZ() << 4; - short[][] blocks = n.getValue(); - World world = chunk.getWorld(); - for (int j = 0; j < blocks.length; j++) { - short[] blocksj = blocks[j]; - if (blocksj != null) { - for (int k = 0; k < blocksj.length; k++) { - short id = blocksj[k]; - if (id != 0) { - final int y = (j << 4) + (k >> 8); - final int a = (k - ((y & 0xF) << 8)); - final int z = (a >> 4); - final int x = a - (z << 4); - BukkitSetBlockManager.setBlockManager.set(world, X + x, y, Z + z, id, (byte) 0); + public synchronized static void addNotify(Runnable whenDone) { + if (runnables == null) { + TaskManager.runTask(whenDone); + } + else { + runnables.add(whenDone); + } + } + + public synchronized static void init() { + if (blocks == null) { + blocks = new HashMap<>(); + runnables = new HashSet<>(); + } + if (!running) { + TaskManager.index.increment(); + final int current = TaskManager.index.intValue(); + int task = TaskManager.runTaskRepeat(new Runnable() { + @Override + public void run() { + if (locked) { + return; + } + if (blocks.size() == 0) { + Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(current)); + for (Runnable runnable : runnables) { + TaskManager.runTask(runnable); + } + runnables = null; + blocks = null; + running = false; + return; + } + long start = System.currentTimeMillis() + allocate; + Iterator> i = blocks.entrySet().iterator(); + while (System.currentTimeMillis() < start && i.hasNext()) { + if (locked) { + return; + } + Entry n = i.next(); + i.remove(); + ChunkWrapper chunk = n.getKey(); + int X = chunk.x << 4; + int Z = chunk.z << 4; + short[][] blocks = n.getValue(); + World world = chunk.world; + for (int j = 0; j < blocks.length; j++) { + short[] blocksj = blocks[j]; + if (blocksj != null) { + for (int k = 0; k < blocksj.length; k++) { + short id = blocksj[k]; + if (id != 0) { + final int y = (j << 4) + (k >> 8); + final int a = (k - ((y & 0xF) << 8)); + final int z = (a >> 4); + final int x = a - (z << 4); + BukkitSetBlockManager.setBlockManager.set(world, X + x, y, Z + z, id, (byte) 0); + } } } } } } - } - }, 20); - TaskManager.tasks.put(current, task); + }, 5); + TaskManager.tasks.put(current, task); + running = true; + } } - - - - public void setBlock(final World world, int x, final int y, int z, final short blkid) { + + public static void setBlock(final World world, int x, final int y, int z, final short blkid) { + locked = true; + if (!running) { + init(); + } int X = x >> 4; int Z = z >> 4; x -= X << 4; z -= Z << 4; - Chunk chunk = world.getChunkAt(X, Z); - short[][] result = blocks.get(chunk); - if (!blocks.containsKey(chunk)) { + + ChunkWrapper wrap = new ChunkWrapper(world, X, Z); + short[][] result = blocks.get(wrap); + if (!blocks.containsKey(wrap)) { result = new short[16][]; - blocks.put(chunk, result); + blocks.put(wrap, result); } if (result[y >> 4] == null) { result[y >> 4] = new short[4096]; } result[y >> 4][((y & 0xF) << 8) | (z << 4) | x] = blkid; + locked = false; + } + + public static class ChunkWrapper { + final int x; + final int z; + final World world; + + public ChunkWrapper(World world, int x, int z) { + this.world = world; + this.x = x; + this.z = z; + } + + @Override + public int hashCode() { + int result; + if (this.x >= 0) { + if (this.z >= 0) { + result = (this.x * this.x) + (3 * this.x) + (2 * this.x * this.z) + this.z + (this.z * this.z); + } else { + final int y1 = -this.z; + result = (this.x * this.x) + (3 * this.x) + (2 * this.x * y1) + y1 + (y1 * y1) + 1; + } + } else { + final int x1 = -this.x; + if (this.z >= 0) { + result = -((x1 * x1) + (3 * x1) + (2 * x1 * this.z) + this.z + (this.z * this.z)); + } else { + final int y1 = -this.z; + result = -((x1 * x1) + (3 * x1) + (2 * x1 * y1) + y1 + (y1 * y1) + 1); + } + } + result = result * 31 + world.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final ChunkWrapper other = (ChunkWrapper) obj; + return ((this.x == other.x) && (this.z == other.z) && (this.world.equals(other.world))); + } } }