diff --git a/src/main/java/com/intellectualcrafters/plot/commands/DebugExec.java b/src/main/java/com/intellectualcrafters/plot/commands/DebugExec.java index 1aa762434..0cdfb02a2 100644 --- a/src/main/java/com/intellectualcrafters/plot/commands/DebugExec.java +++ b/src/main/java/com/intellectualcrafters/plot/commands/DebugExec.java @@ -241,20 +241,12 @@ public class DebugExec extends SubCommand { return true; } case "stop-rgar": { - if (((BukkitHybridUtils)(HybridUtils.manager)).task == 0) { + if (!HybridUtils.UPDATE) { MainUtil.sendMessage(player, "&cTASK NOT RUNNING!"); return false; } - ((BukkitHybridUtils)(HybridUtils.manager)).task = 0; - PS.get().TASK.cancelTask(((BukkitHybridUtils)(HybridUtils.manager)).task); - MainUtil.sendMessage(player, "&cCancelling task..."); - while (BukkitHybridUtils.chunks.size() > 0) { - ChunkLoc chunk = BukkitHybridUtils.chunks.get(0); - BukkitHybridUtils.chunks.remove(0); - HybridUtils.manager.regenerateRoad(BukkitHybridUtils.world, chunk, 0); - ChunkManager.manager.unloadChunk(BukkitHybridUtils.world, chunk, true, true); - } - MainUtil.sendMessage(player, "&cCancelled!"); + HybridUtils.UPDATE = false; + MainUtil.sendMessage(player, "&cCancelling task... (please wait)"); return true; } case "start-expire": { diff --git a/src/main/java/com/intellectualcrafters/plot/generator/HybridUtils.java b/src/main/java/com/intellectualcrafters/plot/generator/HybridUtils.java index d56f502cf..9485714ce 100644 --- a/src/main/java/com/intellectualcrafters/plot/generator/HybridUtils.java +++ b/src/main/java/com/intellectualcrafters/plot/generator/HybridUtils.java @@ -1,10 +1,14 @@ package com.intellectualcrafters.plot.generator; import java.io.File; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import com.intellectualcrafters.jnbt.CompoundTag; import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.object.ChunkLoc; import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Plot; @@ -13,22 +17,192 @@ import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotLoc; import com.intellectualcrafters.plot.object.PlotManager; +import com.intellectualcrafters.plot.object.PlotWorld; import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.util.BlockManager; import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.SchematicHandler; +import com.intellectualcrafters.plot.util.SetBlockQueue; +import com.intellectualcrafters.plot.util.TaskManager; public abstract class HybridUtils { public static HybridUtils manager; - public abstract void checkModified(final Plot plot, final RunnableVal whenDone); - public abstract void analyzePlot(final Plot plot, final RunnableVal whenDone); public abstract int checkModified(final String world, final int x1, final int x2, final int y1, final int y2, final int z1, final int z2, final PlotBlock[] blocks); + public static List regions; + public static List chunks = new ArrayList<>(); + public static String world; + public static boolean UPDATE = false; + + public final ArrayList getChunks(ChunkLoc region) { + ArrayList chunks = new ArrayList(); + final int sx = region.x << 5; + final int sz = region.z << 5; + for (int x = sx; x < (sx + 32); x++) { + for (int z = sz; z < (sz + 32); z++) { + chunks.add(new ChunkLoc(x, z)); + } + } + return chunks; + } + + public void checkModified(final Plot plot, final RunnableVal whenDone) { + if (whenDone == null) { + return; + } + final Location pos1 = MainUtil.getPlotBottomLoc(plot.world, plot.id).add(1, 0, 1); + final Location pos2 = MainUtil.getPlotTopLoc(plot.world, plot.id); + final PlotWorld plotworld = PS.get().getPlotWorld(plot.world); + if (!(plotworld instanceof ClassicPlotWorld)) { + whenDone.value = -1; + TaskManager.runTask(whenDone); + return; + } + whenDone.value = 0; + final ClassicPlotWorld cpw = (ClassicPlotWorld) plotworld; + ChunkManager.chunkTask(pos1, pos2, new RunnableVal() { + @Override + public void run() { + ChunkLoc loc = new ChunkLoc(value[0], value[1]); + ChunkManager.manager.loadChunk(plot.world, loc, false); + int bx = value[2]; + int bz = value[3]; + int ex = value[4]; + int ez = value[5]; + whenDone.value += checkModified(plot.world, bx, ex, 1, cpw.PLOT_HEIGHT - 1, bz, ez, cpw.MAIN_BLOCK); + whenDone.value += checkModified(plot.world, bx, ex, cpw.PLOT_HEIGHT, cpw.PLOT_HEIGHT, bz, ez, cpw.TOP_BLOCK); + whenDone.value += checkModified(plot.world, bx, ex, cpw.PLOT_HEIGHT + 1, 255, bz, ez, new PlotBlock[] { new PlotBlock((short) 0, (byte) 0) }); + } + }, new Runnable() { + @Override + public void run() { + TaskManager.runTask(whenDone); + } + }, 5); + } + + public boolean scheduleRoadUpdate(final String world, int extend) { + if (HybridUtils.UPDATE) { + return false; + } + HybridUtils.UPDATE = true; + final List regions = ChunkManager.manager.getChunkChunks(world); + return scheduleRoadUpdate(world, regions, extend); + } + + public boolean scheduleRoadUpdate(final String world, final List rgs, final int extend) { + HybridUtils.regions = rgs; + HybridUtils.world = world; + chunks = new ArrayList(); + final AtomicInteger count = new AtomicInteger(0); + final long baseTime = System.currentTimeMillis(); + final AtomicInteger last = new AtomicInteger(); + TaskManager.runTask(new Runnable() { + @Override + public void run() { + if (UPDATE == false) { + last.set(0); + while (chunks.size() > 0) { + ChunkLoc chunk = chunks.get(0); + chunks.remove(0); + regenerateRoad(world, chunk, extend); + ChunkManager.manager.unloadChunk(world, chunk, true, true); + } + PS.debug("&cCancelled road task"); + return; + } + count.incrementAndGet(); + if (count.intValue() % 20 == 0) { + PS.debug("PROGRESS: " + ((100 * (2048 - chunks.size())) / 2048) + "%"); + } + if (regions.size() == 0 && chunks.size() == 0) { + HybridUtils.UPDATE = false; + PS.debug(C.PREFIX.s() + "Finished road conversion"); + // CANCEL TASK + return; + } else { + final Runnable task = this; + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + try { + if (last.get() == 0) { + last.set((int) (System.currentTimeMillis() - baseTime)); + } + if (chunks.size() < 1024) { + if (regions.size() > 0) { + final ChunkLoc loc = regions.get(0); + PS.debug("&3Updating .mcr: " + loc.x + ", " + loc.z + " (aprrox 1024 chunks)"); + PS.debug(" - Remaining: " + regions.size()); + chunks.addAll(getChunks(loc)); + regions.remove(0); + System.gc(); + } + } + if (chunks.size() > 0) { + long diff = System.currentTimeMillis() + 1; + if (System.currentTimeMillis() - baseTime - last.get() > 2000 && last.get() != 0) { + last.set(0); + PS.debug(C.PREFIX.s() + "Detected low TPS. Rescheduling in 30s"); + final ChunkLoc chunk = chunks.get(0); + chunks.remove(0); + TaskManager.runTask(new Runnable() { + @Override + public void run() { + regenerateRoad(world, chunk, extend); + } + }); + // DELAY TASK + TaskManager.runTaskLater(task, 600); + return; + } + if ((System.currentTimeMillis() - baseTime) - last.get() < 1500 && last.get() != 0) { + while (System.currentTimeMillis() < diff && chunks.size() > 0) { + final ChunkLoc chunk = chunks.get(0); + chunks.remove(0); + TaskManager.runTask(new Runnable() { + @Override + public void run() { + regenerateRoad(world, chunk, extend); + } + }); + } + } + last.set((int) (System.currentTimeMillis() - baseTime)); + } + } catch (final Exception e) { + e.printStackTrace(); + final ChunkLoc loc = regions.get(0); + PS.debug("&c[ERROR]&7 Could not update '" + world + "/region/r." + loc.x + "." + loc.z + ".mca' (Corrupt chunk?)"); + final int sx = loc.x << 5; + final int sz = loc.z << 5; + for (int x = sx; x < (sx + 32); x++) { + for (int z = sz; z < (sz + 32); z++) { + ChunkManager.manager.unloadChunk(world, new ChunkLoc(x, z), true, true); + } + } + PS.debug("&d - Potentially skipping 1024 chunks"); + PS.debug("&d - TODO: recommend chunkster if corrupt"); + } + SetBlockQueue.addNotify(new Runnable() { + @Override + public void run() { + TaskManager.runTaskLater(task, 20); + } + }); + } + }); + } + } + }); + return true; + } + public boolean setupRoadSchematic(final Plot plot) { final String world = plot.world; final Location bot = MainUtil.getPlotBottomLoc(world, plot.id); @@ -70,8 +244,6 @@ public abstract class HybridUtils { public abstract int get_ey(final String world, final int sx, final int ex, final int sz, final int ez, final int sy); - public abstract boolean scheduleRoadUpdate(final String world, int extend); - public boolean regenerateRoad(final String world, final ChunkLoc chunk, int extend) { final int x = chunk.x << 4; final int z = chunk.z << 4; @@ -138,13 +310,13 @@ public abstract class HybridUtils { final PlotLoc loc = new PlotLoc(absX, absZ); final HashMap blocks = plotworld.G_SCH.get(loc); for (short y = (short) (plotworld.ROAD_HEIGHT); y <= (plotworld.ROAD_HEIGHT + plotworld.SCHEMATIC_HEIGHT + extend); y++) { - BlockManager.manager.functionSetBlock(world, x + X, y, z + Z, 0, (byte) 0); + SetBlockQueue.setBlock(world, x + X, y, z + Z, 0); } if (blocks != null) { final HashMap datas = plotworld.G_SCH_DATA.get(loc); if (datas == null) { for (final Short y : blocks.keySet()) { - BlockManager.manager.functionSetBlock(world, x + X, sy + y, z + Z, blocks.get(y), (byte) 0); + SetBlockQueue.setBlock(world, x + X, sy + y, z + Z, blocks.get(y)); } } else { for (final Short y : blocks.keySet()) { @@ -152,13 +324,19 @@ public abstract class HybridUtils { if (data == null) { data = 0; } - BlockManager.manager.functionSetBlock(world, x + X, sy + y, z + Z, blocks.get(y), data); + SetBlockQueue.setBlock(world, x + X, sy + y, z + Z, new PlotBlock(blocks.get(y), data)); } } } } } } + SetBlockQueue.addNotify(new Runnable() { + @Override + public void run() { + ChunkManager.manager.unloadChunk(world, chunk, true, true); + } + }); return true; } } diff --git a/src/main/java/com/intellectualcrafters/plot/util/TaskManager.java b/src/main/java/com/intellectualcrafters/plot/util/TaskManager.java index ec83706bd..5a8156823 100644 --- a/src/main/java/com/intellectualcrafters/plot/util/TaskManager.java +++ b/src/main/java/com/intellectualcrafters/plot/util/TaskManager.java @@ -18,6 +18,13 @@ public abstract class TaskManager { } return -1; } + + public static int runTaskRepeatAsync(final Runnable r, final int interval) { + if (r != null) { + return PS.get().TASK.taskRepeat(r, interval); + } + return -1; + } public static void runTaskAsync(final Runnable r) { if (r != null) { @@ -49,6 +56,8 @@ public abstract class TaskManager { } public abstract int taskRepeat(final Runnable r, int interval); + + public abstract int taskRepeatAsync(final Runnable r, int interval); public abstract void taskAsync(final Runnable r); diff --git a/src/main/java/com/plotsquared/bukkit/util/BukkitCommand.java b/src/main/java/com/plotsquared/bukkit/util/BukkitCommand.java index 37970df66..29d53f6f2 100644 --- a/src/main/java/com/plotsquared/bukkit/util/BukkitCommand.java +++ b/src/main/java/com/plotsquared/bukkit/util/BukkitCommand.java @@ -60,8 +60,6 @@ public class BukkitCommand implements CommandExecutor, TabCompleter { return null; } final Set tabOptions = new HashSet<>(); - System.out.print(MainCommand.getInstance() + " mc"); - System.out.print(MainCommand.getInstance().getCommands() + " gc"); ArrayList> commands = MainCommand.getInstance().getCommands(); String best = new StringComparison(strings[0], commands).getBestMatch(); tabOptions.add(best); diff --git a/src/main/java/com/plotsquared/bukkit/util/BukkitHybridUtils.java b/src/main/java/com/plotsquared/bukkit/util/BukkitHybridUtils.java index 51dc67f50..7f3980b46 100644 --- a/src/main/java/com/plotsquared/bukkit/util/BukkitHybridUtils.java +++ b/src/main/java/com/plotsquared/bukkit/util/BukkitHybridUtils.java @@ -2,10 +2,8 @@ package com.plotsquared.bukkit.util; import java.util.ArrayList; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Random; -import java.util.concurrent.atomic.AtomicInteger; import org.bukkit.Bukkit; import org.bukkit.Chunk; @@ -17,39 +15,25 @@ import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator.BiomeGrid; import org.bukkit.material.Directional; import org.bukkit.material.MaterialData; -import org.bukkit.plugin.Plugin; import com.intellectualcrafters.plot.PS; -import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.flag.Flag; import com.intellectualcrafters.plot.flag.FlagManager; -import com.intellectualcrafters.plot.generator.ClassicPlotWorld; import com.intellectualcrafters.plot.generator.HybridUtils; import com.intellectualcrafters.plot.object.ChunkLoc; import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.PlotAnalysis; import com.intellectualcrafters.plot.object.PlotBlock; -import com.intellectualcrafters.plot.object.PlotWorld; import com.intellectualcrafters.plot.object.RunnableVal; -import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MathMan; import com.intellectualcrafters.plot.util.TaskManager; -import com.plotsquared.bukkit.BukkitMain; public class BukkitHybridUtils extends HybridUtils { - public static List regions; - public static List chunks = new ArrayList<>(); - public static String world; - private static boolean UPDATE = false; - public int task; - private long last; - @Override public void analyzePlot(final Plot plot, final RunnableVal whenDone) { - // TODO Auto-generated method stub // int diff, int variety, int verticies, int rotation, int height_sd /* @@ -267,60 +251,6 @@ public class BukkitHybridUtils extends HybridUtils { TaskManager.tasks.put(currentIndex, task); } - public void checkModified(final Plot plot, final RunnableVal whenDone) { - TaskManager.index.incrementAndGet(); - final Location bot = MainUtil.getPlotBottomLoc(plot.world, plot.id).add(1, 0, 1); - final Location top = MainUtil.getPlotTopLoc(plot.world, plot.id); - int bx = bot.getX() >> 4; - int bz = bot.getZ() >> 4; - int tx = top.getX() >> 4; - int tz = top.getZ() >> 4; - World world = BukkitUtil.getWorld(plot.world); - final HashSet chunks = new HashSet<>(); - for (int X = bx; X <= tx; X++) { - for (int Z = bz; Z <= tz; Z++) { - chunks.add(world.getChunkAt(X,Z)); - } - } - PlotWorld plotworld = PS.get().getPlotWorld(plot.world); - if (!(plotworld instanceof ClassicPlotWorld)) { - whenDone.value = -1; - TaskManager.runTaskLater(whenDone, 1); - return; - } - - final ClassicPlotWorld cpw = (ClassicPlotWorld) plotworld; - - final AtomicInteger count = new AtomicInteger(0); - - final Integer currentIndex = TaskManager.index.get(); - final Integer task = TaskManager.runTaskRepeat(new Runnable() { - @Override - public void run() { - if (chunks.size() == 0) { - whenDone.value = count.intValue(); - TaskManager.runTaskLater(whenDone, 1); - Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex)); - TaskManager.tasks.remove(currentIndex); - return; - } - Iterator iter = chunks.iterator(); - final Chunk chunk = iter.next(); - iter.remove(); - int bx = Math.max(chunk.getX() << 4, bot.getX()); - int bz = Math.max(chunk.getZ() << 4, bot.getZ()); - int ex = Math.min((chunk.getX() << 4) + 15, top.getX()); - int ez = Math.min((chunk.getZ() << 4) + 15, top.getZ()); - // count changes - count.addAndGet(checkModified(plot.world, bx, ex, 1, cpw.PLOT_HEIGHT - 1, bz, ez, cpw.MAIN_BLOCK)); - count.addAndGet(checkModified(plot.world, bx, ex, cpw.PLOT_HEIGHT, cpw.PLOT_HEIGHT, bz, ez, cpw.TOP_BLOCK)); - count.addAndGet(checkModified(plot.world, bx, ex, cpw.PLOT_HEIGHT + 1, 255, bz, ez, new PlotBlock[] { new PlotBlock((short) 0, (byte) 0) })); - } - }, 1); - TaskManager.tasks.put(currentIndex, task); - - } - @Override public int checkModified(final String worldname, final int x1, final int x2, final int y1, final int y2, final int z1, final int z2, final PlotBlock[] blocks) { final World world = BukkitUtil.getWorld(worldname); @@ -365,127 +295,4 @@ public class BukkitHybridUtils extends HybridUtils { } return ey; } - - public void regenerateChunkChunk(final String worldname, final ChunkLoc loc) { - final World world = BukkitUtil.getWorld(worldname); - final int sx = loc.x << 5; - final int sz = loc.z << 5; - for (int x = sx; x < (sx + 32); x++) { - for (int z = sz; z < (sz + 32); z++) { - final Chunk chunk = world.getChunkAt(x, z); - chunk.load(false); - } - } - final ArrayList chunks2 = new ArrayList<>(); - for (int x = sx; x < (sx + 32); x++) { - for (int z = sz; z < (sz + 32); z++) { - final Chunk chunk = world.getChunkAt(x, z); - chunks2.add(chunk); - regenerateRoad(worldname, new ChunkLoc(x, z), 0); - MainUtil.update(world.getName(), new ChunkLoc(chunk.getX(), chunk.getZ())); - } - } - } - - public final ArrayList getChunks(ChunkLoc region) { - ArrayList chunks = new ArrayList(); - final int sx = region.x << 5; - final int sz = region.z << 5; - for (int x = sx; x < (sx + 32); x++) { - for (int z = sz; z < (sz + 32); z++) { - chunks.add(new ChunkLoc(x, z)); - } - } - return chunks; - } - - @Override - public boolean scheduleRoadUpdate(final String world, int extend) { - if (BukkitHybridUtils.UPDATE) { - return false; - } - BukkitHybridUtils.UPDATE = true; - final List regions = ChunkManager.manager.getChunkChunks(world); - return scheduleRoadUpdate(world, regions, extend); - } - - public boolean scheduleRoadUpdate(final String world, final List rgs, final int extend) { - BukkitHybridUtils.regions = rgs; - BukkitHybridUtils.world = world; - chunks = new ArrayList(); - final Plugin plugin = BukkitMain.THIS; - final AtomicInteger count = new AtomicInteger(0); - this.task = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() { - @Override - public void run() { - count.incrementAndGet(); - if (count.intValue() % 20 == 0) { - PS.debug("PROGRESS: " + ((100 * (2048 - chunks.size())) / 2048) + "%"); - } - if (regions.size() == 0 && chunks.size() == 0) { - BukkitHybridUtils.UPDATE = false; - PS.debug(C.PREFIX.s() + "Finished road conversion"); - Bukkit.getScheduler().cancelTask(BukkitHybridUtils.this.task); - return; - } else { - try { - if (chunks.size() < 1024) { - if (regions.size() > 0) { - final ChunkLoc loc = regions.get(0); - PS.debug("&3Updating .mcr: " + loc.x + ", " + loc.z + " (aprrox 1024 chunks)"); - PS.debug(" - Remaining: " + regions.size()); - chunks.addAll(getChunks(loc)); - regions.remove(0); - System.gc(); - } - } - if (chunks.size() > 0) { - long diff = System.currentTimeMillis() + 25; - if (System.currentTimeMillis() - last > 1200 && last != 0) { - last = 0; - PS.debug(C.PREFIX.s() + "Detected low TPS. Rescheduling in 30s"); - while (chunks.size() > 0) { - ChunkLoc chunk = chunks.get(0); - chunks.remove(0); - regenerateRoad(world, chunk, extend); - ChunkManager.manager.unloadChunk(world, chunk, true, true); - } - Bukkit.getScheduler().cancelTask(BukkitHybridUtils.this.task); - TaskManager.runTaskLater(new Runnable() { - @Override - public void run() { - scheduleRoadUpdate(world, regions, extend); - } - }, 600); - return; - } - if (System.currentTimeMillis() - last < 1000) { - while (System.currentTimeMillis() < diff && chunks.size() > 0) { - ChunkLoc chunk = chunks.get(0); - chunks.remove(0); - regenerateRoad(world, chunk, extend); - ChunkManager.manager.unloadChunk(world, chunk, true, true); - } - } - last = System.currentTimeMillis(); - } - } catch (final Exception e) { - e.printStackTrace(); - final ChunkLoc loc = regions.get(0); - PS.debug("&c[ERROR]&7 Could not update '" + world + "/region/r." + loc.x + "." + loc.z + ".mca' (Corrupt chunk?)"); - final int sx = loc.x << 5; - final int sz = loc.z << 5; - for (int x = sx; x < (sx + 32); x++) { - for (int z = sz; z < (sz + 32); z++) { - ChunkManager.manager.unloadChunk(world, new ChunkLoc(x, z), true, true); - } - } - PS.debug("&d - Potentially skipping 1024 chunks"); - PS.debug("&d - TODO: recommend chunkster if corrupt"); - } - } - } - }, 20, 20); - return true; - } } diff --git a/src/main/java/com/plotsquared/bukkit/util/BukkitTaskManager.java b/src/main/java/com/plotsquared/bukkit/util/BukkitTaskManager.java index 4e2194b02..a7812275c 100644 --- a/src/main/java/com/plotsquared/bukkit/util/BukkitTaskManager.java +++ b/src/main/java/com/plotsquared/bukkit/util/BukkitTaskManager.java @@ -10,6 +10,11 @@ public class BukkitTaskManager extends TaskManager { public int taskRepeat(final Runnable r, final int interval) { return BukkitMain.THIS.getServer().getScheduler().scheduleSyncRepeatingTask(BukkitMain.THIS, r, interval, interval); } + + @Override + public int taskRepeatAsync(final Runnable r, final int interval) { + return BukkitMain.THIS.getServer().getScheduler().scheduleAsyncRepeatingTask(BukkitMain.THIS, r, interval, interval); + } @Override public void taskAsync(final Runnable r) { diff --git a/src/main/java/com/plotsquared/sponge/SpongeHybridUtils.java b/src/main/java/com/plotsquared/sponge/SpongeHybridUtils.java new file mode 100644 index 000000000..758744087 --- /dev/null +++ b/src/main/java/com/plotsquared/sponge/SpongeHybridUtils.java @@ -0,0 +1,73 @@ +package com.plotsquared.sponge; + +import org.bukkit.block.Block; +import org.spongepowered.api.block.BlockState; +import org.spongepowered.api.block.BlockTypes; +import org.spongepowered.api.world.World; + +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.generator.HybridUtils; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotAnalysis; +import com.intellectualcrafters.plot.object.PlotBlock; +import com.intellectualcrafters.plot.object.RunnableVal; +import com.plotsquared.bukkit.util.BukkitUtil; +import com.plotsquared.sponge.util.SpongeUtil; + +public class SpongeHybridUtils extends HybridUtils { + + @Override + public void analyzePlot(Plot plot, RunnableVal whenDone) { + // TODO Auto-generated method stub + PS.debug("analyzePlot is not implemented"); + if (whenDone != null) { + whenDone.run(); + } + } + + @Override + public int checkModified(String worldname, int x1, int x2, int y1, int y2, int z1, int z2, PlotBlock[] blocks) { + PS.debug("checkModified is not implemented"); + final World world = SpongeUtil.getWorld(worldname); + int count = 0; + for (int y = y1; y <= y2; y++) { + for (int x = x1; x <= x2; x++) { + for (int z = z1; z <= z2; z++) { + BlockState state = world.getBlock(x, y, z); + PlotBlock block = SpongeMain.THIS.getPlotBlock(state); + boolean same = false; + for (final PlotBlock p : blocks) { + if (block.id == p.id) { + same = true; + break; + } + } + if (!same) { + count++; + } + } + } + } + return count; + } + + @Override + public int get_ey(String worldname, int sx, int ex, int sz, int ez, int sy) { + final World world = SpongeUtil.getWorld(worldname); + int ey = sy; + for (int x = sx; x <= ex; x++) { + for (int z = sz; z <= ez; z++) { + for (int y = sy; y < 256; y++) { + if (y > ey) { + BlockState state = world.getBlock(x, y, z); + if (state != null && state.getType() != BlockTypes.AIR) { + ey = y; + } + } + } + } + } + return ey; + } + +} diff --git a/src/main/java/com/plotsquared/sponge/SpongeMain.java b/src/main/java/com/plotsquared/sponge/SpongeMain.java index 3a1f16f4f..88850a406 100644 --- a/src/main/java/com/plotsquared/sponge/SpongeMain.java +++ b/src/main/java/com/plotsquared/sponge/SpongeMain.java @@ -471,15 +471,13 @@ public class SpongeMain implements IPlotMain, PluginContainer { @Override public HybridUtils initHybridUtils() { - // TODO Auto-generated method stub - return null; + return new SpongeHybridUtils(); } @Override public SchematicHandler initSchematicHandler() { - // TODO Auto-generated method stub - return null; + return new SpongeSchematicHandler(); } @Override diff --git a/src/main/java/com/plotsquared/sponge/SpongeSchematicHandler.java b/src/main/java/com/plotsquared/sponge/SpongeSchematicHandler.java new file mode 100644 index 000000000..bb9204054 --- /dev/null +++ b/src/main/java/com/plotsquared/sponge/SpongeSchematicHandler.java @@ -0,0 +1,272 @@ +package com.plotsquared.sponge; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.spongepowered.api.block.BlockState; +import org.spongepowered.api.world.World; + +import com.intellectualcrafters.jnbt.ByteArrayTag; +import com.intellectualcrafters.jnbt.CompoundTag; +import com.intellectualcrafters.jnbt.IntTag; +import com.intellectualcrafters.jnbt.ListTag; +import com.intellectualcrafters.jnbt.ShortTag; +import com.intellectualcrafters.jnbt.StringTag; +import com.intellectualcrafters.jnbt.Tag; +import com.intellectualcrafters.plot.object.ChunkLoc; +import com.intellectualcrafters.plot.object.Location; +import com.intellectualcrafters.plot.object.PlotBlock; +import com.intellectualcrafters.plot.object.RunnableVal; +import com.intellectualcrafters.plot.util.SchematicHandler; +import com.intellectualcrafters.plot.util.TaskManager; +import com.plotsquared.sponge.util.SpongeUtil; + +public class SpongeSchematicHandler extends SchematicHandler { + + @Override + public void getCompoundTag(final String world, final Location pos1, final Location pos2, final RunnableVal whenDone) { + + // async + TaskManager.runTaskAsync(new Runnable() { + + @Override + public void run() { + // Main positions + final int p1x = pos1.getX(); + final int p1z = pos1.getZ(); + final int p2x = pos2.getX(); + final int p2z = pos2.getZ(); + final int bcx = p1x >> 4; + final int bcz = p1z >> 4; + final int tcx = p2x >> 4; + final int tcz = p2z >> 4; + final int sy = pos1.getY(); + final int ey = pos2.getY(); + + final int width = (pos2.getX() - pos1.getX()) + 1; + final int height = (pos2.getY() - pos1.getY()) + 1; + final int length = (pos2.getZ() - pos1.getZ()) + 1; + + // Main Schematic tag + final HashMap schematic = new HashMap<>(); + + schematic.put("Width", new ShortTag("Width", (short) width)); + schematic.put("Length", new ShortTag("Length", (short) length)); + schematic.put("Height", new ShortTag("Height", (short) height)); + schematic.put("Materials", new StringTag("Materials", "Alpha")); + schematic.put("WEOriginX", new IntTag("WEOriginX", 0)); + schematic.put("WEOriginY", new IntTag("WEOriginY", 0)); + schematic.put("WEOriginZ", new IntTag("WEOriginZ", 0)); + schematic.put("WEOffsetX", new IntTag("WEOffsetX", 0)); + schematic.put("WEOffsetY", new IntTag("WEOffsetY", 0)); + schematic.put("WEOffsetZ", new IntTag("WEOffsetZ", 0)); + + // Arrays of data types + final List tileEntities = new ArrayList(); + final byte[] blocks = new byte[width * height * length]; + final byte[] blockData = new byte[width * height * length]; + + // Generate list of chunks + final ArrayList chunks = new ArrayList(); + for (int x = bcx; x <= tcx; x++) { + for (int z = bcz; z <= tcz; z++) { + chunks.add(new ChunkLoc(x, z)); + } + } + + final World worldObj = SpongeUtil.getWorld(world); + // Main thread + TaskManager.runTask(new Runnable() { + @Override + public void run() { + long start = System.currentTimeMillis(); + while (chunks.size() > 0 && System.currentTimeMillis() - start < 20) { + // save schematics + ChunkLoc chunk = chunks.remove(0); + + if (!worldObj.loadChunk(chunk.x << 4, 0, chunk.z << 4, false).isPresent()) { + continue; + } + + int X = chunk.x; + int Z = chunk.z; + int xxb = X << 4; + int zzb = Z << 4; + int xxt = xxb + 15; + int zzt = zzb + 15; + + if (X == bcx) { + xxb = p1x; + } + if (X == tcx) { + xxt = p2x; + } + if (Z == bcz) { + zzb = p1z; + } + if (Z == tcz) { + zzt = p2z; + } + for (int y = sy; y <= Math.min(255, ey); y++) { + int ry = y - sy; + int i1 = (ry * width * length); + for (int z = zzb; z <= zzt; z++) { + int rz = z - p1z; + int i2 = i1 + (rz * width); + for (int x = xxb; x <= xxt; x++) { + int rx = x - p1x; + final int index = i2 + rx; + + BlockState state = worldObj.getBlock(x, y, z); + PlotBlock block = SpongeMain.THIS.getPlotBlock(state); + if (block == null) { + block = SpongeMain.THIS.registerBlock(state); + } + int id = block.id; + switch (id) { + case 0: + case 2: + case 4: + case 13: + case 14: + case 15: + case 20: + case 21: + case 22: + case 24: + case 30: + case 32: + case 37: + case 39: + case 40: + case 41: + case 42: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 55: + case 56: + case 57: + case 58: + case 60: + case 7: + case 8: + case 9: + case 10: + case 11: + case 73: + case 74: + case 75: + case 76: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 85: + case 87: + case 88: + case 101: + case 102: + case 103: + case 110: + case 112: + case 113: + case 121: + case 122: + case 129: + case 133: + case 165: + case 166: + case 169: + case 170: + case 172: + case 173: + case 174: + case 181: + case 182: + case 188: + case 189: + case 190: + case 191: + case 192: { + break; + } + case 54: + case 130: + case 142: + case 27: + case 137: + case 52: + case 154: + case 84: + case 25: + case 144: + case 138: + case 176: + case 177: + case 63: + case 68: + case 323: + case 117: + case 116: + case 28: + case 66: + case 157: + case 61: + case 62: + case 140: + case 146: + case 149: + case 150: + case 158: + case 23: + case 123: + case 124: + case 29: + case 33: + case 151: + case 178: { + // TODO wrap block state... + // TODO add block state to map + } + default: { + blockData[index] = block.data; + } + } + blocks[index] = (byte) id; + } + } + } + + } + if (chunks.size() != 0) { + TaskManager.runTaskLater(this, 1); + } else { + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + schematic.put("Blocks", new ByteArrayTag("Blocks", blocks)); + schematic.put("Data", new ByteArrayTag("Data", blockData)); + schematic.put("Entities", new ListTag("Entities", CompoundTag.class, new ArrayList())); + schematic.put("TileEntities", new ListTag("TileEntities", CompoundTag.class, tileEntities)); + whenDone.value = new CompoundTag("Schematic", schematic); + TaskManager.runTask(whenDone); + System.gc(); + System.gc(); + } + }); + } + } + }); + } + }); + } + +} diff --git a/src/main/java/com/plotsquared/sponge/listener/MainListener.java b/src/main/java/com/plotsquared/sponge/listener/MainListener.java index d7334129f..c63205677 100644 --- a/src/main/java/com/plotsquared/sponge/listener/MainListener.java +++ b/src/main/java/com/plotsquared/sponge/listener/MainListener.java @@ -20,6 +20,7 @@ import java.util.UUID; import org.spongepowered.api.block.BlockState; import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.entity.EntityType; import org.spongepowered.api.entity.EntityTypes; import org.spongepowered.api.entity.player.Player; import org.spongepowered.api.event.Subscribe; @@ -125,6 +126,13 @@ public class MainListener { // TODO selectively cancel depending on spawn reason // - Not sure if possible to get spawn reason (since there are no callbacks) + if (entity.getType() == EntityTypes.DROPPED_ITEM) { + if (FlagManager.isPlotFlagFalse(plot, "item-drop")) { + event.setCancelled(true); + } + return; + } + event.setCancelled(true); } diff --git a/src/main/java/com/plotsquared/sponge/util/SpongeTaskManager.java b/src/main/java/com/plotsquared/sponge/util/SpongeTaskManager.java index 199518a12..1e4837554 100644 --- a/src/main/java/com/plotsquared/sponge/util/SpongeTaskManager.java +++ b/src/main/java/com/plotsquared/sponge/util/SpongeTaskManager.java @@ -24,6 +24,16 @@ public class SpongeTaskManager extends TaskManager { tasks.put(val, task); return val; } + + @Override + public int taskRepeatAsync(Runnable r, int interval) { + int val = i.incrementAndGet(); + TaskBuilder builder = SpongeMain.THIS.getGame().getScheduler().getTaskBuilder(); + TaskBuilder built = builder.delay(interval).async().interval(interval).execute(r); + Task task = built.submit(SpongeMain.THIS.getPlugin()); + tasks.put(val, task); + return val; + } @Override public void taskAsync(Runnable r) {