diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index ace0a25c9..239592c36 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -51,6 +51,7 @@ import com.plotsquared.bukkit.listeners.PlayerEvents_1_9; import com.plotsquared.bukkit.listeners.PlotPlusListener; import com.plotsquared.bukkit.listeners.PlotPlusListener_1_12; import com.plotsquared.bukkit.listeners.PlotPlusListener_Legacy; +import com.plotsquared.bukkit.listeners.SingleWorldListener; import com.plotsquared.bukkit.listeners.WorldEvents; import com.plotsquared.bukkit.titles.DefaultTitle_111; import com.plotsquared.bukkit.util.BukkitChatManager; @@ -158,6 +159,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain private int[] version; private String name; + private SingleWorldListener singleWorldListener; @Override public int[] getServerVersion() { @@ -200,10 +202,19 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain public void run() { unload(); } - }, 5); + }, 20); + try { + singleWorldListener = new SingleWorldListener(this); + } catch (Exception e) { + e.printStackTrace(); + } } } + public SingleWorldListener getSingleWorldListener() { + return singleWorldListener; + } + public void unload() { PlotAreaManager manager = PS.get().getPlotAreaManager(); if (manager instanceof SinglePlotAreaManager) { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java index 747dbec58..ab68c3e32 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java @@ -11,6 +11,7 @@ import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotManager; import com.intellectualcrafters.plot.object.PseudoRandom; import com.intellectualcrafters.plot.object.SetupObject; +import com.intellectualcrafters.plot.object.worlds.SingleWorldGenerator; import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MathMan; @@ -57,9 +58,8 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap if (queue == null) { queue = GlobalBlockQueue.IMP.getNewQueue(world.getName(), false); } - ChunkLoc loc = new ChunkLoc(c.getX(), c.getZ()); - byte[][] resultData; - if (!BukkitPlotGenerator.this.dataMap.containsKey(loc)) { + byte[][] resultData = dataMap.isEmpty() ? null : dataMap.remove(new ChunkLoc(c.getX(), c.getZ())); + if (resultData == null) { GenChunk result = BukkitPlotGenerator.this.chunkSetter; // Set the chunk location result.setChunk(c); @@ -69,10 +69,8 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap result.grid = null; result.cd = null; // Catch any exceptions (as exceptions usually thrown) - generate(world, loc.x, loc.z, result); + generate(world, c.getX(), c.getZ(), result); resultData = result.result_data; - } else { - resultData = BukkitPlotGenerator.this.dataMap.remove(loc); } if (resultData != null) { for (int i = 0; i < resultData.length; i++) { @@ -256,6 +254,9 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap @Override public ChunkData generateChunkData(World world, Random random, int cx, int cz, BiomeGrid grid) { GenChunk result = this.chunkSetter; + if (this.getPlotGenerator() instanceof SingleWorldGenerator) { + if (result.cd != null) return result.cd; + } // Set the chunk location result.setChunk(new ChunkWrapper(world.getName(), cx, cz)); // Set the result data @@ -318,8 +319,12 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap return this.platformGenerator.generateExtBlockSections(world, r, cx, cz, grid); } else { generate(world, cx, cz, result); - this.dataMap.put(new ChunkLoc(cx, cz), result.result_data); - + for (int i = 0; i < result.result_data.length; i++) { + if (result.result_data[i] != null) { + this.dataMap.put(new ChunkLoc(cx, cz), result.result_data); + break; + } + } } } catch (Throwable e) { e.printStackTrace(); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listeners/ChunkListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listeners/ChunkListener.java index e2ecb41ea..ca0dc871e 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listeners/ChunkListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listeners/ChunkListener.java @@ -38,7 +38,6 @@ public class ChunkListener implements Listener { private RefField mustSave; private Chunk lastChunk; - public ChunkListener() { if (Settings.Chunk_Processor.AUTO_TRIM) { try { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listeners/SingleWorldListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listeners/SingleWorldListener.java new file mode 100644 index 000000000..146d30f53 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listeners/SingleWorldListener.java @@ -0,0 +1,101 @@ +package com.plotsquared.bukkit.listeners; + +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.object.worlds.PlotAreaManager; +import com.intellectualcrafters.plot.object.worlds.SinglePlotAreaManager; +import com.intellectualcrafters.plot.util.ReflectionUtils; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.world.ChunkEvent; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.plugin.Plugin; + + +import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass; + +public class SingleWorldListener implements Listener { + + private Method methodGetHandleChunk; + private Field mustSave, done, lit, s; + + public SingleWorldListener(Plugin plugin) throws Exception { + ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk"); + ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); + this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle").getRealMethod(); + this.mustSave = classChunk.getField("mustSave").getRealField(); + try { + this.done = classChunk.getField("done").getRealField(); + this.lit = classChunk.getField("lit").getRealField(); + this.s = classChunk.getField("s").getRealField(); + } catch (Throwable ignore) { + ignore.printStackTrace(); + } + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + public void markChunkAsClean(Chunk chunk) { + try { + Object nmsChunk = methodGetHandleChunk.invoke(chunk); + if (done != null) this.done.set(nmsChunk, true); + if (mustSave != null) this.mustSave.set(nmsChunk, false); + if (lit != null) this.lit.set(nmsChunk, false); + if (s != null) this.s.set(nmsChunk, false); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + private void handle(ChunkEvent event) { + World world = event.getWorld(); + String name = world.getName(); + PlotAreaManager man = PS.get().getPlotAreaManager(); + if (!(man instanceof SinglePlotAreaManager)) return; + if (!isPlotId(name)) return; + + markChunkAsClean(event.getChunk()); + } + +// @EventHandler +// public void onPopulate(ChunkPopulateEvent event) { +// handle(event); +// } + + @EventHandler(priority = EventPriority.LOWEST) + public void onChunkLoad(ChunkLoadEvent event) { + handle(event); + } + + private boolean isPlotId(String worldName) { + int len = worldName.length(); + int separator = 0; + for (int i = 0; i < len; i++) { + switch (worldName.charAt(i)) { + case ',': + case ';': + separator++; + break; + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + break; + default: + return false; + } + } + return separator == 1; + } +} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index a401cf037..83511ac0a 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -187,7 +187,7 @@ public class BukkitUtil extends WorldUtil { if (block != null) { Material type = block.getType(); if (type.isSolid()) { - if (air > 1) return y + 1; + if (air > 1) return y; air = 0; } else { switch (type) { @@ -201,7 +201,7 @@ public class BukkitUtil extends WorldUtil { } } } - return bukkitWorld.getMaxHeight(); + return bukkitWorld.getMaxHeight() - 1; } @Override diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/block/GenChunk.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/block/GenChunk.java index 7a7df59f8..414239c9d 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/block/GenChunk.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/block/GenChunk.java @@ -6,6 +6,7 @@ import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue; import com.plotsquared.bukkit.util.BukkitUtil; +import java.util.Arrays; import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.block.Biome; @@ -72,6 +73,24 @@ public class GenChunk extends ScopedLocalBlockQueue { } } + @Override + public void setCuboid(Location pos1, Location pos2, PlotBlock block) { + if (block.data == 0 && result != null && pos1.getX() == 0 && pos1.getZ() == 0 && pos2.getX() == 15 && pos2.getZ() == 15) { + for (int y = pos1.getY(); y <= pos2.getY(); y++) { + int layer = y >> 4; + short[] data = result[layer]; + if (data == null) { + result[layer] = data = new short[4096]; + } + int start = y << 8; + int end = start + 256; + Arrays.fill(data, start, end, block.id); + } + } else { + super.setCuboid(pos1, pos2, block); + } + } + @Override public boolean setBiome(int x, int z, String biome) { return setBiome(x, z, Biome.valueOf(biome.toUpperCase())); diff --git a/Core/src/main/java/com/intellectualcrafters/plot/commands/Area.java b/Core/src/main/java/com/intellectualcrafters/plot/commands/Area.java index 16fbf5b8d..a9b2c58cb 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/commands/Area.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/commands/Area.java @@ -442,7 +442,7 @@ public class Area extends SubCommand { RegionWrapper region = area.getRegion(); center = new Location(area.worldname, region.minX + (region.maxX - region.minX) / 2, 0, region.minZ + (region.maxZ - region.minZ) / 2); - center.setY(WorldUtil.IMP.getHighestBlock(area.worldname, center.getX(), center.getZ())); + center.setY(1 + WorldUtil.IMP.getHighestBlock(area.worldname, center.getX(), center.getZ())); } player.teleport(center); return true; diff --git a/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java b/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java index d413c582a..6bf0918da 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotWorld.java @@ -54,7 +54,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { Location bot = plot.getBottomAbs(); if (SIGN_LOCATION == null) { bot.setY(ROAD_HEIGHT + 1); - return bot.add(-1, ROAD_HEIGHT, -2); + return bot.add(-1, 1, -2); } else { bot.setY(0); Location loc = bot.add(SIGN_LOCATION.getX(), SIGN_LOCATION.getY(), SIGN_LOCATION.getZ()); diff --git a/Core/src/main/java/com/intellectualcrafters/plot/object/Plot.java b/Core/src/main/java/com/intellectualcrafters/plot/object/Plot.java index 9999da990..771c5cdbf 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/object/Plot.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/object/Plot.java @@ -1134,8 +1134,8 @@ public class Plot { int z = largest.minZ - 1; PlotManager manager = getManager(); int y = isLoaded() ? WorldUtil.IMP.getHighestBlock(getWorldName(), x, z) : 64; - if (area.ALLOW_SIGNS) { - y = Math.max(y, manager.getSignLoc(area, this).getY()); + if (area.ALLOW_SIGNS && (y <= 0 || y >= 255)) { + y = Math.max(y, manager.getSignLoc(area, this).getY() - 1); } return new Location(getWorldName(), x, y + 1, z); } @@ -1147,13 +1147,15 @@ public class Plot { public Location getHome() { BlockLoc home = this.getPosition(); if (home == null || home.x == 0 && home.z == 0) { + System.out.println("Default"); return this.getDefaultHome(true); } else { + System.out.println("Custom"); Location bot = this.getBottomAbs(); Location loc = new Location(bot.getWorld(), bot.getX() + home.x, bot.getY() + home.y, bot.getZ() + home.z, home.yaw, home.pitch); if (!isLoaded()) return loc; if (WorldUtil.IMP.getBlock(loc).id != 0) { - loc.setY(Math.max(WorldUtil.IMP.getHighestBlock(this.getWorldName(), loc.getX(), loc.getZ()), bot.getY())); + loc.setY(Math.max(1 + WorldUtil.IMP.getHighestBlock(this.getWorldName(), loc.getX(), loc.getZ()), bot.getY())); } return loc; } diff --git a/Core/src/main/java/com/intellectualcrafters/plot/object/PlotCluster.java b/Core/src/main/java/com/intellectualcrafters/plot/object/PlotCluster.java index e84b47f8d..8101a7ec3 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/object/PlotCluster.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/object/PlotCluster.java @@ -139,7 +139,7 @@ public class PlotCluster { } int max = MainUtil.getHeighestBlock(this.area.worldname, toReturn.getX(), toReturn.getZ()); if (max > toReturn.getY()) { - toReturn.setY(max); + toReturn.setY(1 + max); } return toReturn; } diff --git a/Core/src/main/java/com/intellectualcrafters/plot/object/worlds/SinglePlotManager.java b/Core/src/main/java/com/intellectualcrafters/plot/object/worlds/SinglePlotManager.java index a94d4d087..7044b6692 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/object/worlds/SinglePlotManager.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/object/worlds/SinglePlotManager.java @@ -9,6 +9,7 @@ import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotManager; import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.SetupUtils; +import com.intellectualcrafters.plot.util.TaskManager; import java.io.File; import java.util.ArrayList; @@ -34,11 +35,16 @@ public class SinglePlotManager extends PlotManager { } @Override - public boolean clearPlot(PlotArea plotArea, Plot plot, Runnable whenDone) { + public boolean clearPlot(PlotArea plotArea, Plot plot, final Runnable whenDone) { SetupUtils.manager.unload(plot.getWorldName(), false); - File worldFolder = new File(PS.get().IMP.getWorldContainer(), plot.getWorldName()); - MainUtil.deleteDirectory(worldFolder); - if (whenDone != null) whenDone.run(); + final File worldFolder = new File(PS.get().IMP.getWorldContainer(), plot.getWorldName()); + TaskManager.IMP.taskAsync(new Runnable() { + @Override + public void run() { + MainUtil.deleteDirectory(worldFolder); + if (whenDone != null) whenDone.run(); + } + }); return true; } diff --git a/Core/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java b/Core/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java index 49f12f3c0..eb9129196 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java @@ -565,7 +565,7 @@ public class MainUtil { public static int getHeighestBlock(String world, int x, int z) { int result = WorldUtil.IMP.getHighestBlock(world, x, z); if (result == 0) { - return 64; + return 63; } return result; } diff --git a/Core/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java b/Core/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java index 45bc34577..19bed84bb 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/util/SchematicHandler.java @@ -183,7 +183,7 @@ public abstract class SchematicHandler { if (pw instanceof ClassicPlotWorld) { y_offset_actual = yOffset + ((ClassicPlotWorld) pw).PLOT_HEIGHT; } else { - y_offset_actual = yOffset + MainUtil.getHeighestBlock(plot.getWorldName(), region.minX + 1, region.minZ + 1); + y_offset_actual = yOffset + 1 + MainUtil.getHeighestBlock(plot.getWorldName(), region.minX + 1, region.minZ + 1); } } } diff --git a/Core/src/main/java/com/intellectualcrafters/plot/util/block/LocalBlockQueue.java b/Core/src/main/java/com/intellectualcrafters/plot/util/block/LocalBlockQueue.java index ff02a4279..f37e18591 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/util/block/LocalBlockQueue.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/util/block/LocalBlockQueue.java @@ -90,7 +90,7 @@ public abstract class LocalBlockQueue { GlobalBlockQueue.IMP.enqueue(this); } - public final void setCuboid(Location pos1, Location pos2, PlotBlock block) { + public void setCuboid(Location pos1, Location pos2, PlotBlock block) { for (int y = pos1.getY(); y <= Math.min(255, pos2.getY()); y++) { for (int x = pos1.getX(); x <= pos2.getX(); x++) { for (int z = pos1.getZ(); z <= pos2.getZ(); z++) { @@ -100,7 +100,7 @@ public abstract class LocalBlockQueue { } } - public final void setCuboid(Location pos1, Location pos2, PlotBlock[] blocks) { + public void setCuboid(Location pos1, Location pos2, PlotBlock[] blocks) { for (int y = pos1.getY(); y <= Math.min(255, pos2.getY()); y++) { for (int x = pos1.getX(); x <= pos2.getX(); x++) { for (int z = pos1.getZ(); z <= pos2.getZ(); z++) { diff --git a/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java b/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java index 1ec24af0a..a96647a1d 100644 --- a/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java +++ b/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java @@ -332,7 +332,7 @@ public class SpongeUtil extends WorldUtil { @Override public Location getSpawn(String world) { Location result = SpongeUtil.getLocation(world, SpongeUtil.getWorld(world).getSpawnLocation()); - result.setY(getHighestBlock(world, result.getX(), result.getZ())); + result.setY(1 + getHighestBlock(world, result.getX(), result.getZ())); return result; } @@ -392,15 +392,15 @@ public class SpongeUtil extends WorldUtil { public int getHighestBlock(String worldName, int x, int z) { World world = SpongeUtil.getWorld(worldName); if (world == null) { - return 64; + return 63; } for (int y = 255; y > 0; y--) { BlockState block = world.getBlock(x, y, z); if (block.getType() != BlockTypes.AIR) { - return y + 1; + return y; } } - return 64; + return 63; } @Override