diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java index a2e6a6cb9..ab1894a9d 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java @@ -134,7 +134,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain private final BlockRegistry blockRegistry = new BukkitBlockRegistry(Material.values()); private int[] version; - @Getter private String pluginName; + private String pluginName; @Getter private SingleWorldListener singleWorldListener; private Method methodUnloadChunk0; private boolean methodUnloadSetup = false; @@ -165,9 +165,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain return Bukkit.getVersion(); } + @Override public void onEnable() { this.pluginName = getDescription().getName(); - getServer().getName(); PlotPlayer.registerConverter(Player.class, BukkitUtil::getPlayer); @@ -319,6 +319,11 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain return getDescription().getVersion(); } + @Override + public String getPluginName() { + return pluginName; + } + @Override public void registerCommands() { final BukkitCommand bukkitCommand = new BukkitCommand(); final PluginCommand plotCommand = getCommand("plots"); @@ -586,6 +591,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain @Override @Nullable public final ChunkGenerator getDefaultWorldGenerator(final String world, final String id) { + PlotSquared.log("DEFAULT WORLD GENERATOR RUN"); final IndependentPlotGenerator result; if (id != null && id.equalsIgnoreCase("single")) { result = new SingleWorldGenerator(); @@ -802,7 +808,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain } ChunkGenerator gen = world.getGenerator(); if (gen instanceof BukkitPlotGenerator) { - PlotSquared.get().loadWorld(worldName, (BukkitPlotGenerator) gen); + PlotSquared.get().loadWorld(worldName, (GeneratorWrapper) gen); } else if (gen != null) { PlotSquared.get().loadWorld(worldName, new BukkitPlotGenerator(worldName, gen)); } else if (PlotSquared.get().worlds.contains("worlds." + worldName)) { diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/chat/FancyMessage.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/chat/FancyMessage.java index 41ec91e49..69b168b3d 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/chat/FancyMessage.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/chat/FancyMessage.java @@ -320,34 +320,6 @@ public class FancyMessage return this; } - /** - * Set the behavior of the current editing component to display information about an achievement when the client hovers over the text. - *

Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.

- * - * @param which The achievement to display. - * @return This builder instance. - */ - public FancyMessage achievementTooltip(final Achievement which) { - try { - Object achievement = Reflection - .getMethod(Reflection.getOBCClass("CraftStatistic"), "getNMSAchievement", - Achievement.class).invoke(null, which); - return achievementTooltip( - (String) Reflection.getField(Reflection.getNMSClass("Achievement"), "name") - .get(achievement)); - } catch (IllegalAccessException e) { - Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e); - return this; - } catch (IllegalArgumentException e) { - Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e); - return this; - } catch (InvocationTargetException e) { - Bukkit.getLogger() - .log(Level.WARNING, "A error has occurred during invoking of method.", e); - return this; - } - } - /** * Set the behavior of the current editing component to display information about a parameterless statistic when the client hovers over the text. *

Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.

diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/events/ClusterFlagRemoveEvent.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/events/ClusterFlagRemoveEvent.java deleted file mode 100644 index 40acef111..000000000 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/events/ClusterFlagRemoveEvent.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.github.intellectualsites.plotsquared.bukkit.events; - -import com.github.intellectualsites.plotsquared.plot.flag.Flag; -import com.github.intellectualsites.plotsquared.plot.object.PlotCluster; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * Called when a flag is removed from a plot. - */ -public class ClusterFlagRemoveEvent extends Event implements Cancellable { - - private static final HandlerList handlers = new HandlerList(); - private final PlotCluster cluster; - private final Flag flag; - private boolean cancelled; - - /** - * PlotFlagRemoveEvent: Called when a flag is removed from a plot. - * - * @param flag Flag that was removed - * @param cluster PlotCluster from which the flag was removed - */ - public ClusterFlagRemoveEvent(Flag flag, PlotCluster cluster) { - this.cluster = cluster; - this.flag = flag; - } - - public static HandlerList getHandlerList() { - return handlers; - } - - /** - * Get the cluster involved. - * - * @return PlotCluster - */ - public PlotCluster getCluster() { - return this.cluster; - } - - /** - * Get the flag involved. - * - * @return Flag - */ - public Flag getFlag() { - return this.flag; - } - - @Override public HandlerList getHandlers() { - return handlers; - } - - @Override public boolean isCancelled() { - return this.cancelled; - } - - @Override public void setCancelled(boolean b) { - this.cancelled = b; - } -} diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/ChunkListener.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/ChunkListener.java index da1bb49c3..7b56cabfd 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/ChunkListener.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/ChunkListener.java @@ -1,5 +1,7 @@ package com.github.intellectualsites.plotsquared.bukkit.listeners; +import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getRefClass; + import com.github.intellectualsites.plotsquared.plot.PlotSquared; import com.github.intellectualsites.plotsquared.plot.config.C; import com.github.intellectualsites.plotsquared.plot.config.Settings; @@ -9,6 +11,8 @@ import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefCla import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefField; import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefMethod; import com.github.intellectualsites.plotsquared.plot.util.TaskManager; +import java.lang.reflect.Method; +import java.util.HashSet; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Material; @@ -27,11 +31,6 @@ import org.bukkit.event.entity.ItemSpawnEvent; import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkUnloadEvent; -import java.lang.reflect.Method; -import java.util.HashSet; - -import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getRefClass; - @SuppressWarnings("unused") public class ChunkListener implements Listener { @@ -60,48 +59,46 @@ public class ChunkListener implements Listener { for (World world : Bukkit.getWorlds()) { world.setAutoSave(false); } - TaskManager.runTaskRepeat(new Runnable() { - @Override public void run() { - try { - HashSet toUnload = new HashSet<>(); - for (World world : Bukkit.getWorlds()) { - String worldName = world.getName(); - if (!PlotSquared.get().hasPlotArea(worldName)) { + TaskManager.runTaskRepeat(() -> { + try { + HashSet toUnload = new HashSet<>(); + for (World world : Bukkit.getWorlds()) { + String worldName = world.getName(); + if (!PlotSquared.get().hasPlotArea(worldName)) { + continue; + } + Object w = world.getClass().getDeclaredMethod("getHandle").invoke(world); + Object chunkMap = + w.getClass().getDeclaredMethod("getPlayerChunkMap").invoke(w); + Method methodIsChunkInUse = chunkMap.getClass() + .getDeclaredMethod("isChunkInUse", int.class, int.class); + Chunk[] chunks = world.getLoadedChunks(); + for (Chunk chunk : chunks) { + if ((boolean) methodIsChunkInUse + .invoke(chunkMap, chunk.getX(), chunk.getZ())) { continue; } - Object w = world.getClass().getDeclaredMethod("getHandle").invoke(world); - Object chunkMap = - w.getClass().getDeclaredMethod("getPlayerChunkMap").invoke(w); - Method methodIsChunkInUse = chunkMap.getClass() - .getDeclaredMethod("isChunkInUse", int.class, int.class); - Chunk[] chunks = world.getLoadedChunks(); - for (Chunk chunk : chunks) { - if ((boolean) methodIsChunkInUse - .invoke(chunkMap, chunk.getX(), chunk.getZ())) { - continue; - } - int x = chunk.getX(); - int z = chunk.getZ(); - if (!shouldSave(worldName, x, z)) { - unloadChunk(worldName, chunk, false); - continue; - } - toUnload.add(chunk); + int x = chunk.getX(); + int z = chunk.getZ(); + if (!shouldSave(worldName, x, z)) { + unloadChunk(worldName, chunk, false); + continue; } + toUnload.add(chunk); } - if (toUnload.isEmpty()) { + } + if (toUnload.isEmpty()) { + return; + } + long start = System.currentTimeMillis(); + for (Chunk chunk : toUnload) { + if (System.currentTimeMillis() - start > 5) { return; } - long start = System.currentTimeMillis(); - for (Chunk chunk : toUnload) { - if (System.currentTimeMillis() - start > 5) { - return; - } - chunk.unload(true, false); - } - } catch (Throwable e) { - e.printStackTrace(); + chunk.unload(true, false); } + } catch (Throwable e) { + e.printStackTrace(); } }, 1); } @@ -112,7 +109,7 @@ public class ChunkListener implements Listener { } Object c = this.methodGetHandleChunk.of(chunk).call(); RefField.RefExecutor field = this.mustSave.of(c); - if ((Boolean) field.get() == true) { + if ((Boolean) field.get()) { field.set(false); if (chunk.isLoaded()) { ignoreUnload = true; @@ -226,18 +223,28 @@ public class ChunkListener implements Listener { private void cleanChunk(final Chunk chunk) { TaskManager.index.incrementAndGet(); final Integer currentIndex = TaskManager.index.get(); - 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 - .debug(C.PREFIX.s() + "&aSuccessfully processed and unloaded chunk!"); - chunk.unload(true, true); - return; - } - BlockState[] tiles = chunk.getTileEntities(); - if (tiles.length == 0) { + Integer task = TaskManager.runTaskRepeat(() -> { + if (!chunk.isLoaded()) { + Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex)); + TaskManager.tasks.remove(currentIndex); + PlotSquared + .debug(C.PREFIX.s() + "&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 + .debug(C.PREFIX.s() + "&aSuccessfully processed and unloaded chunk!"); + chunk.unload(true, true); + return; + } + long start = System.currentTimeMillis(); + int i = 0; + while (System.currentTimeMillis() - start < 250) { + if (i >= tiles.length) { Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex)); TaskManager.tasks.remove(currentIndex); PlotSquared @@ -245,20 +252,8 @@ public class ChunkListener implements Listener { chunk.unload(true, true); return; } - long start = System.currentTimeMillis(); - int i = 0; - while (System.currentTimeMillis() - start < 250) { - if (i >= tiles.length) { - Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex)); - TaskManager.tasks.remove(currentIndex); - PlotSquared - .debug(C.PREFIX.s() + "&aSuccessfully processed and unloaded chunk!"); - chunk.unload(true, true); - return; - } - tiles[i].getBlock().setType(Material.AIR, false); - i++; - } + tiles[i].getBlock().setType(Material.AIR, false); + i++; } }, 5); TaskManager.tasks.put(currentIndex, task); diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/ForceFieldListener.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/ForceFieldListener.java index 97d1bb7d7..bf33577a1 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/ForceFieldListener.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/ForceFieldListener.java @@ -16,89 +16,90 @@ import java.util.HashSet; import java.util.Set; import java.util.UUID; -@SuppressWarnings("unused") public class ForceFieldListener { +@SuppressWarnings("unused") +public class ForceFieldListener { - private static Set getNearbyPlayers(Player player, Plot plot) { - Set players = new HashSet<>(); - for (Player nearPlayer : Iterables - .filter(player.getNearbyEntities(5d, 5d, 5d), Player.class)) { - PlotPlayer plotPlayer; - if ((plotPlayer = BukkitUtil.getPlayer(nearPlayer)) == null || !plot - .equals(plotPlayer.getCurrentPlot())) { - continue; - } - if (!plot.isAdded(plotPlayer.getUUID())) { - players.add(plotPlayer); - } - } - return players; + private static Set getNearbyPlayers(Player player, Plot plot) { + Set players = new HashSet<>(); + for (Player nearPlayer : Iterables + .filter(player.getNearbyEntities(5d, 5d, 5d), Player.class)) { + PlotPlayer plotPlayer; + if ((plotPlayer = BukkitUtil.getPlayer(nearPlayer)) == null || !plot + .equals(plotPlayer.getCurrentPlot())) { + continue; + } + if (!plot.isAdded(plotPlayer.getUUID())) { + players.add(plotPlayer); + } } + return players; + } - private static PlotPlayer hasNearbyPermitted(Player player, Plot plot) { - for (Player nearPlayer : Iterables - .filter(player.getNearbyEntities(5d, 5d, 5d), Player.class)) { - PlotPlayer plotPlayer; - if ((plotPlayer = BukkitUtil.getPlayer(nearPlayer)) == null || !plot - .equals(plotPlayer.getCurrentPlot())) { - continue; - } - if (plot.isAdded(plotPlayer.getUUID())) { - return plotPlayer; - } - } - return null; + private static PlotPlayer hasNearbyPermitted(Player player, Plot plot) { + for (Player nearPlayer : Iterables + .filter(player.getNearbyEntities(5d, 5d, 5d), Player.class)) { + PlotPlayer plotPlayer; + if ((plotPlayer = BukkitUtil.getPlayer(nearPlayer)) == null || !plot + .equals(plotPlayer.getCurrentPlot())) { + continue; + } + if (plot.isAdded(plotPlayer.getUUID())) { + return plotPlayer; + } } + return null; + } - private static Vector calculateVelocity(PlotPlayer player, PlotPlayer e) { - Location playerLocation = player.getLocationFull(); - Location oPlayerLocation = e.getLocation(); - double playerX = playerLocation.getX(); - double playerY = playerLocation.getY(); - double playerZ = playerLocation.getZ(); - double oPlayerX = oPlayerLocation.getX(); - double oPlayerY = oPlayerLocation.getY(); - double oPlayerZ = oPlayerLocation.getZ(); - double x = 0d; - if (playerX < oPlayerX) { - x = 1.0d; - } else if (playerX > oPlayerX) { - x = -1.0d; - } - double y = 0d; - if (playerY < oPlayerY) { - y = 0.5d; - } else if (playerY > oPlayerY) { - y = -0.5d; - } - double z = 0d; - if (playerZ < oPlayerZ) { - z = 1.0d; - } else if (playerZ > oPlayerZ) { - z = -1.0d; - } - return new Vector(x, y, z); + private static Vector calculateVelocity(PlotPlayer player, PlotPlayer e) { + Location playerLocation = player.getLocationFull(); + Location oPlayerLocation = e.getLocation(); + double playerX = playerLocation.getX(); + double playerY = playerLocation.getY(); + double playerZ = playerLocation.getZ(); + double oPlayerX = oPlayerLocation.getX(); + double oPlayerY = oPlayerLocation.getY(); + double oPlayerZ = oPlayerLocation.getZ(); + double x = 0d; + if (playerX < oPlayerX) { + x = 1.0d; + } else if (playerX > oPlayerX) { + x = -1.0d; } + double y = 0d; + if (playerY < oPlayerY) { + y = 0.5d; + } else if (playerY > oPlayerY) { + y = -0.5d; + } + double z = 0d; + if (playerZ < oPlayerZ) { + z = 1.0d; + } else if (playerZ > oPlayerZ) { + z = -1.0d; + } + return new Vector(x, y, z); + } - public static void handleForcefield(Player player, PlotPlayer plotPlayer, Plot plot) { - if (Flags.FORCEFIELD.isTrue(plot)) { - UUID uuid = plotPlayer.getUUID(); - if (plot.isAdded(uuid)) { - Set players = getNearbyPlayers(player, plot); - for (PlotPlayer oPlayer : players) { - if (!Permissions.hasPermission(oPlayer, C.PERMISSION_ADMIN_ENTRY_FORCEFIELD)) { - ((BukkitPlayer) oPlayer).player - .setVelocity(calculateVelocity(plotPlayer, oPlayer)); - } - } - } else { - PlotPlayer oPlayer = hasNearbyPermitted(player, plot); - if (oPlayer == null) { - return; - } - if (!Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_ENTRY_FORCEFIELD)) { - player.setVelocity(calculateVelocity(oPlayer, plotPlayer)); - } - } + public static void handleForcefield(Player player, PlotPlayer plotPlayer, Plot plot) { + if (Flags.FORCEFIELD.isTrue(plot)) { + UUID uuid = plotPlayer.getUUID(); + if (plot.isAdded(uuid)) { + Set players = getNearbyPlayers(player, plot); + for (PlotPlayer oPlayer : players) { + if (!Permissions.hasPermission(oPlayer, C.PERMISSION_ADMIN_ENTRY_FORCEFIELD)) { + ((BukkitPlayer) oPlayer).player + .setVelocity(calculateVelocity(plotPlayer, oPlayer)); + } } + } else { + PlotPlayer oPlayer = hasNearbyPermitted(player, plot); + if (oPlayer == null) { + return; + } + if (!Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_ENTRY_FORCEFIELD)) { + player.setVelocity(calculateVelocity(oPlayer, plotPlayer)); + } + } } + } } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlayerEvents.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlayerEvents.java index 6b172f49e..ecb6b50ef 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlayerEvents.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlayerEvents.java @@ -42,6 +42,7 @@ import org.bukkit.help.HelpTopic; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.material.Directional; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.metadata.MetadataValue; import org.bukkit.plugin.Plugin; @@ -57,186 +58,188 @@ import java.util.regex.Pattern; /** * Player Events involving plots. */ -@SuppressWarnings("unused") public class PlayerEvents extends PlotListener implements Listener { +@SuppressWarnings("unused") +public class PlayerEvents extends PlotListener implements Listener { - private boolean pistonBlocks = true; - private float lastRadius; - // To prevent recursion - private boolean tmpTeleport = true; - private Field fieldPlayer; - private PlayerMoveEvent moveTmp; + private boolean pistonBlocks = true; + private float lastRadius; + // To prevent recursion + private boolean tmpTeleport = true; + private Field fieldPlayer; + private PlayerMoveEvent moveTmp; - { - try { - fieldPlayer = PlayerEvent.class.getDeclaredField("player"); - fieldPlayer.setAccessible(true); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } + { + try { + fieldPlayer = PlayerEvent.class.getDeclaredField("player"); + fieldPlayer.setAccessible(true); + } catch (NoSuchFieldException e) { + e.printStackTrace(); } + } - public static void sendBlockChange(final org.bukkit.Location bloc, final BlockData data) { - TaskManager.runTaskLater(() -> { - String world = bloc.getWorld().getName(); - int x = bloc.getBlockX(); - int z = bloc.getBlockZ(); - int distance = Bukkit.getViewDistance() * 16; - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer player = entry.getValue(); - Location loc = player.getLocation(); - if (loc.getWorld().equals(world)) { - if (16 * Math.abs(loc.getX() - x) / 16 > distance - || 16 * Math.abs(loc.getZ() - z) / 16 > distance) { - continue; - } - ((BukkitPlayer) player).player.sendBlockChange(bloc, data); - } - } - }, 3); - } - - public static boolean checkEntity(Entity entity, Plot plot) { - if (plot == null || !plot.hasOwner() || plot.getFlags().isEmpty() && plot - .getArea().DEFAULT_FLAGS.isEmpty()) { - return false; + public static void sendBlockChange(final org.bukkit.Location bloc, final BlockData data) { + TaskManager.runTaskLater(() -> { + String world = bloc.getWorld().getName(); + int x = bloc.getBlockX(); + int z = bloc.getBlockZ(); + int distance = Bukkit.getViewDistance() * 16; + for (Entry entry : UUIDHandler.getPlayers().entrySet()) { + PlotPlayer player = entry.getValue(); + Location loc = player.getLocation(); + if (loc.getWorld().equals(world)) { + if (16 * Math.abs(loc.getX() - x) / 16 > distance + || 16 * Math.abs(loc.getZ() - z) / 16 > distance) { + continue; + } + ((BukkitPlayer) player).player.sendBlockChange(bloc, data); } - switch (entity.getType()) { - case PLAYER: - return false; - case ARROW: - case DRAGON_FIREBALL: - case DROPPED_ITEM: - case EGG: - case ENDER_PEARL: - case FIREBALL: - case LINGERING_POTION: - case LLAMA_SPIT: - case SHULKER_BULLET: - case SMALL_FIREBALL: - case SNOWBALL: - case SPECTRAL_ARROW: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case TIPPED_ARROW: - // projectile - case FALLING_BLOCK: - case PRIMED_TNT: - // Block entities - case AREA_EFFECT_CLOUD: - case COMPLEX_PART: - case ENDER_CRYSTAL: - case ENDER_SIGNAL: - case EVOKER_FANGS: - case EXPERIENCE_ORB: - case FIREWORK: - case FISHING_HOOK: - case LEASH_HITCH: - case LIGHTNING: - case UNKNOWN: - case WEATHER: - case WITHER_SKULL: - // non moving / unmovable - return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP); - case ARMOR_STAND: - case ITEM_FRAME: - case PAINTING: - return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP, Flags.MISC_CAP); - // misc - case BOAT: - case MINECART: - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP, Flags.VEHICLE_CAP); - case BAT: - case CHICKEN: - case COD: - case COW: - case DOLPHIN: - case DONKEY: - case HORSE: - case IRON_GOLEM: - case LLAMA: - case MULE: - case MUSHROOM_COW: - case OCELOT: - case PARROT: - case PIG: - case POLAR_BEAR: - case PUFFERFISH: - case RABBIT: - case SALMON: - case SHEEP: - case SKELETON_HORSE: - case SNOWMAN: - case SQUID: - case TROPICAL_FISH: - case TURTLE: - case VILLAGER: - case WOLF: - case ZOMBIE_HORSE: - // animal - return EntityUtil - .checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.ANIMAL_CAP); - case BLAZE: - case CAVE_SPIDER: - case CREEPER: - case DROWNED: - case ELDER_GUARDIAN: - case ENDERMAN: - case ENDERMITE: - case ENDER_DRAGON: - case EVOKER: - case GHAST: - case GIANT: - case GUARDIAN: - case HUSK: - case ILLUSIONER: - case MAGMA_CUBE: - case PIG_ZOMBIE: - case SHULKER: - case SILVERFISH: - case SKELETON: - case SLIME: - case SPIDER: - case STRAY: - case VEX: - case VINDICATOR: - case WITCH: - case WITHER: - case WITHER_SKELETON: - case ZOMBIE: - case ZOMBIE_VILLAGER: - // monster - return EntityUtil - .checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.HOSTILE_CAP); - default: - if (entity instanceof LivingEntity) { - if (entity instanceof Animals || entity instanceof WaterMob) { - return EntityUtil - .checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.ANIMAL_CAP); - } else if (entity instanceof Monster) { - return EntityUtil - .checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.HOSTILE_CAP); - } else { - return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP); - } - } - if (entity instanceof Vehicle) { - return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP, Flags.VEHICLE_CAP); - } - if (entity instanceof Hanging) { - return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP, Flags.MISC_CAP); - } - return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP); - } - } + } + }, 3); + } - @EventHandler public void onRedstoneEvent(BlockRedstoneEvent event) { - Block block = event.getBlock(); + public static boolean checkEntity(Entity entity, Plot plot) { + if (plot == null || !plot.hasOwner() || plot.getFlags().isEmpty() && plot + .getArea().DEFAULT_FLAGS.isEmpty()) { + return false; + } + switch (entity.getType()) { + case PLAYER: + return false; + case ARROW: + case DRAGON_FIREBALL: + case DROPPED_ITEM: + case EGG: + case ENDER_PEARL: + case FIREBALL: + case LINGERING_POTION: + case LLAMA_SPIT: + case SHULKER_BULLET: + case SMALL_FIREBALL: + case SNOWBALL: + case SPECTRAL_ARROW: + case SPLASH_POTION: + case THROWN_EXP_BOTTLE: + case TIPPED_ARROW: + // projectile + case FALLING_BLOCK: + case PRIMED_TNT: + // Block entities + case AREA_EFFECT_CLOUD: + case COMPLEX_PART: + case ENDER_CRYSTAL: + case ENDER_SIGNAL: + case EVOKER_FANGS: + case EXPERIENCE_ORB: + case FIREWORK: + case FISHING_HOOK: + case LEASH_HITCH: + case LIGHTNING: + case UNKNOWN: + case WEATHER: + case WITHER_SKULL: + // non moving / unmovable + return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP); + case ARMOR_STAND: + case ITEM_FRAME: + case PAINTING: + return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP, Flags.MISC_CAP); + // misc + case BOAT: + case MINECART: + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP, Flags.VEHICLE_CAP); + case BAT: + case CHICKEN: + case COD: + case COW: + case DOLPHIN: + case DONKEY: + case HORSE: + case IRON_GOLEM: + case LLAMA: + case MULE: + case MUSHROOM_COW: + case OCELOT: + case PARROT: + case PIG: + case POLAR_BEAR: + case PUFFERFISH: + case RABBIT: + case SALMON: + case SHEEP: + case SKELETON_HORSE: + case SNOWMAN: + case SQUID: + case TROPICAL_FISH: + case TURTLE: + case VILLAGER: + case WOLF: + case ZOMBIE_HORSE: + // animal + return EntityUtil + .checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.ANIMAL_CAP); + case BLAZE: + case CAVE_SPIDER: + case CREEPER: + case DROWNED: + case ELDER_GUARDIAN: + case ENDERMAN: + case ENDERMITE: + case ENDER_DRAGON: + case EVOKER: + case GHAST: + case GIANT: + case GUARDIAN: + case HUSK: + case ILLUSIONER: + case MAGMA_CUBE: + case PIG_ZOMBIE: + case SHULKER: + case SILVERFISH: + case SKELETON: + case SLIME: + case SPIDER: + case STRAY: + case VEX: + case VINDICATOR: + case WITCH: + case WITHER: + case WITHER_SKELETON: + case ZOMBIE: + case ZOMBIE_VILLAGER: + // monster + return EntityUtil + .checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.HOSTILE_CAP); + default: + if (entity instanceof LivingEntity) { + if (entity instanceof Animals || entity instanceof WaterMob) { + return EntityUtil + .checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.ANIMAL_CAP); + } else if (entity instanceof Monster) { + return EntityUtil + .checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.HOSTILE_CAP); + } else { + return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP); + } + } + if (entity instanceof Vehicle) { + return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP, Flags.VEHICLE_CAP); + } + if (entity instanceof Hanging) { + return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP, Flags.MISC_CAP); + } + return EntityUtil.checkEntity(plot, Flags.ENTITY_CAP); + } + } + + @EventHandler + public void onRedstoneEvent(BlockRedstoneEvent event) { + Block block = event.getBlock(); /* switch (block.getType()) { case OBSERVER: case REDSTONE: @@ -284,2561 +287,2575 @@ import java.util.regex.Pattern; case POWERED_RAIL: return; default:*/ + Location loc = BukkitUtil.getLocation(block.getLocation()); + PlotArea area = loc.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlot(loc); + if (plot == null) { + return; + } + if (Flags.REDSTONE.isFalse(plot)) { + event.setNewCurrent(0); + return; + } + if (Settings.Redstone.DISABLE_OFFLINE) { + boolean disable; + if (plot.isMerged()) { + disable = true; + for (UUID owner : plot.getOwners()) { + if (UUIDHandler.getPlayer(owner) != null) { + disable = false; + break; + } + } + } else { + disable = UUIDHandler.getPlayer(plot.guessOwner()) == null; + } + if (disable) { + for (UUID trusted : plot.getTrusted()) { + if (UUIDHandler.getPlayer(trusted) != null) { + disable = false; + break; + } + } + if (disable) { + event.setNewCurrent(0); + return; + } + } + } + if (Settings.Redstone.DISABLE_UNOCCUPIED) { + for (Entry entry : UUIDHandler.getPlayers().entrySet()) { + if (plot.equals(entry.getValue().getCurrentPlot())) { + return; + } + } + event.setNewCurrent(0); + } + //} + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onPhysicsEvent(BlockPhysicsEvent event) { + switch (event.getChangedType()) { + case COMPARATOR: { + Block block = event.getBlock(); Location loc = BukkitUtil.getLocation(block.getLocation()); PlotArea area = loc.getPlotArea(); if (area == null) { - return; + return; } - Plot plot = area.getOwnedPlot(loc); + Plot plot = area.getOwnedPlotAbs(loc); if (plot == null) { - return; + return; } if (Flags.REDSTONE.isFalse(plot)) { - event.setNewCurrent(0); - return; - } - if (Settings.Redstone.DISABLE_OFFLINE) { - boolean disable; - if (plot.isMerged()) { - disable = true; - for (UUID owner : plot.getOwners()) { - if (UUIDHandler.getPlayer(owner) != null) { - disable = false; - break; - } - } - } else { - disable = UUIDHandler.getPlayer(plot.guessOwner()) == null; - } - if (disable) { - for (UUID trusted : plot.getTrusted()) { - if (UUIDHandler.getPlayer(trusted) != null) { - disable = false; - break; - } - } - if (disable) { - event.setNewCurrent(0); - return; - } - } - } - if (Settings.Redstone.DISABLE_UNOCCUPIED) { - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - if (plot.equals(entry.getValue().getCurrentPlot())) { - return; - } - } - event.setNewCurrent(0); - } - //} - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void onPhysicsEvent(BlockPhysicsEvent event) { - switch (event.getChangedType()) { - case COMPARATOR: { - Block block = event.getBlock(); - Location loc = BukkitUtil.getLocation(block.getLocation()); - PlotArea area = loc.getPlotArea(); - if (area == null) { - return; - } - Plot plot = area.getOwnedPlotAbs(loc); - if (plot == null) { - return; - } - if (Flags.REDSTONE.isFalse(plot)) { - event.setCancelled(true); - } - return; - } - case ANVIL: - case DRAGON_EGG: - case GRAVEL: - case SAND: - case TURTLE_EGG: - case TURTLE_HELMET: - case TURTLE_SPAWN_EGG: { - Block block = event.getBlock(); - Location loc = BukkitUtil.getLocation(block.getLocation()); - PlotArea area = loc.getPlotArea(); - if (area == null) { - return; - } - Plot plot = area.getOwnedPlotAbs(loc); - if (plot == null) { - return; - } - if (Flags.DISABLE_PHYSICS.isFalse(plot)) { - event.setCancelled(true); - } - return; - } - default: - if (Settings.Redstone.DETECT_INVALID_EDGE_PISTONS) { - Block block = event.getBlock(); - switch (block.getType()) { - case PISTON: - case STICKY_PISTON: - Piston piston = (Piston) block.getBlockData(); - Location loc = BukkitUtil.getLocation(block.getLocation()); - PlotArea area = loc.getPlotArea(); - if (area == null) { - return; - } - Plot plot = area.getOwnedPlotAbs(loc); - if (plot == null) { - return; - } - switch (piston.getFacing()) { - case EAST: - loc.setX(loc.getX() + 1); - break; - case SOUTH: - loc.setX(loc.getX() - 1); - break; - case WEST: - loc.setZ(loc.getZ() + 1); - break; - case NORTH: - loc.setZ(loc.getZ() - 1); - break; - } - Plot newPlot = area.getOwnedPlotAbs(loc); - if (!plot.equals(newPlot)) { - event.setCancelled(true); - return; - } - } - } - break; - } - } - - @EventHandler public void onProjectileLaunch(ProjectileLaunchEvent event) { - Projectile entity = event.getEntity(); - if (!(entity instanceof ThrownPotion)) { - return; - } - ProjectileSource shooter = entity.getShooter(); - if (!(shooter instanceof Player)) { - return; - } - Location l = BukkitUtil.getLocation(entity); - if (!PlotSquared.get().hasPlotArea(l.getWorld())) { - return; - } - PlotPlayer pp = BukkitUtil.getPlayer((Player) shooter); - Plot plot = l.getOwnedPlot(); - if (plot != null && !plot.isAdded(pp.getUUID())) { - entity.remove(); - event.setCancelled(true); - } - } - - @EventHandler public boolean onProjectileHit(ProjectileHitEvent event) { - Projectile entity = event.getEntity(); - Location loc = BukkitUtil.getLocation(entity); - if (!PlotSquared.get().hasPlotArea(loc.getWorld())) { - return true; + event.setCancelled(true); } + return; + } + case ANVIL: + case DRAGON_EGG: + case GRAVEL: + case SAND: + case TURTLE_EGG: + case TURTLE_HELMET: + case TURTLE_SPAWN_EGG: { + Block block = event.getBlock(); + Location loc = BukkitUtil.getLocation(block.getLocation()); PlotArea area = loc.getPlotArea(); if (area == null) { - return true; + return; } - Plot plot = area.getPlot(loc); - ProjectileSource shooter = entity.getShooter(); - if (shooter instanceof Player) { - PlotPlayer pp = BukkitUtil.getPlayer((Player) shooter); - if (plot == null) { - if (!Permissions.hasPermission(pp, C.PERMISSION_PROJECTILE_UNOWNED)) { - entity.remove(); - return false; - } - return true; - } - if (plot.isAdded(pp.getUUID()) || Permissions - .hasPermission(pp, C.PERMISSION_PROJECTILE_OTHER)) { - return true; - } - entity.remove(); - return false; + Plot plot = area.getOwnedPlotAbs(loc); + if (plot == null) { + return; } - if (!(shooter instanceof Entity) && shooter != null) { - if (plot == null) { - entity.remove(); - return false; - } - Location sLoc = - BukkitUtil.getLocation(((BlockProjectileSource) shooter).getBlock().getLocation()); - if (!area.contains(sLoc.getX(), sLoc.getZ())) { - entity.remove(); - return false; - } - Plot sPlot = area.getOwnedPlotAbs(sLoc); - if (sPlot == null || !PlotHandler.sameOwners(plot, sPlot)) { - entity.remove(); - return false; - } + if (Flags.DISABLE_PHYSICS.isFalse(plot)) { + event.setCancelled(true); + } + return; + } + default: + if (Settings.Redstone.DETECT_INVALID_EDGE_PISTONS) { + Block block = event.getBlock(); + switch (block.getType()) { + case PISTON: + case STICKY_PISTON: + Piston piston = (Piston) block.getBlockData(); + Location loc = BukkitUtil.getLocation(block.getLocation()); + PlotArea area = loc.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlotAbs(loc); + if (plot == null) { + return; + } + switch (piston.getFacing()) { + case EAST: + loc.setX(loc.getX() + 1); + break; + case SOUTH: + loc.setX(loc.getX() - 1); + break; + case WEST: + loc.setZ(loc.getZ() + 1); + break; + case NORTH: + loc.setZ(loc.getZ() - 1); + break; + } + Plot newPlot = area.getOwnedPlotAbs(loc); + if (!plot.equals(newPlot)) { + event.setCancelled(true); + return; + } + } + } + break; + } + } + + @EventHandler + public void onProjectileLaunch(ProjectileLaunchEvent event) { + Projectile entity = event.getEntity(); + if (!(entity instanceof ThrownPotion)) { + return; + } + ProjectileSource shooter = entity.getShooter(); + if (!(shooter instanceof Player)) { + return; + } + Location l = BukkitUtil.getLocation(entity); + if (!PlotSquared.get().hasPlotArea(l.getWorld())) { + return; + } + PlotPlayer pp = BukkitUtil.getPlayer((Player) shooter); + Plot plot = l.getOwnedPlot(); + if (plot != null && !plot.isAdded(pp.getUUID())) { + entity.remove(); + event.setCancelled(true); + } + } + + @EventHandler + public boolean onProjectileHit(ProjectileHitEvent event) { + Projectile entity = event.getEntity(); + Location loc = BukkitUtil.getLocation(entity); + if (!PlotSquared.get().hasPlotArea(loc.getWorld())) { + return true; + } + PlotArea area = loc.getPlotArea(); + if (area == null) { + return true; + } + Plot plot = area.getPlot(loc); + ProjectileSource shooter = entity.getShooter(); + if (shooter instanceof Player) { + PlotPlayer pp = BukkitUtil.getPlayer((Player) shooter); + if (plot == null) { + if (!Permissions.hasPermission(pp, C.PERMISSION_PROJECTILE_UNOWNED)) { + entity.remove(); + return false; } return true; + } + if (plot.isAdded(pp.getUUID()) || Permissions + .hasPermission(pp, C.PERMISSION_PROJECTILE_OTHER)) { + return true; + } + entity.remove(); + return false; } + if (!(shooter instanceof Entity) && shooter != null) { + if (plot == null) { + entity.remove(); + return false; + } + Location sLoc = + BukkitUtil.getLocation(((BlockProjectileSource) shooter).getBlock().getLocation()); + if (!area.contains(sLoc.getX(), sLoc.getZ())) { + entity.remove(); + return false; + } + Plot sPlot = area.getOwnedPlotAbs(sLoc); + if (sPlot == null || !PlotHandler.sameOwners(plot, sPlot)) { + entity.remove(); + return false; + } + } + return true; + } - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void playerCommand(PlayerCommandPreprocessEvent event) { - String msg = event.getMessage().toLowerCase().replaceAll("/", "").trim(); - if (msg.isEmpty()) { + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void playerCommand(PlayerCommandPreprocessEvent event) { + String msg = event.getMessage().toLowerCase().replaceAll("/", "").trim(); + if (msg.isEmpty()) { + return; + } + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + Location loc = pp.getLocation(); + PlotArea area = loc.getPlotArea(); + if (area == null) { + return; + } + String[] parts = msg.split(" "); + Plot plot = pp.getCurrentPlot(); + if (BukkitMain.getWorldEdit() != null) { // Check WorldEdit + switch (parts[0].toLowerCase()) { + case "up": + case "/up": + case "worldedit:up": + case "worldedit:/up": + if (plot == null || (!plot.isAdded(pp.getUUID()) && !Permissions + .hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER, true))) { + event.setCancelled(true); return; + } + } + } + if (plot == null) { + return; + } + Optional> flag = plot.getFlag(Flags.BLOCKED_CMDS); + if (flag.isPresent() && !Permissions + .hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_BLOCKED_CMDS)) { + List blocked_cmds = flag.get(); + String c = parts[0]; + if (parts[0].contains(":")) { + c = parts[0].split(":")[1]; + msg = msg.replace(parts[0].split(":")[0] + ':', ""); + } + String l = c; + List aliases = new ArrayList<>(); + for (HelpTopic cmdLabel : Bukkit.getServer().getHelpMap().getHelpTopics()) { + if (c.equals(cmdLabel.getName())) { + break; } + String label = cmdLabel.getName().replaceFirst("/", ""); + if (aliases.contains(label)) { + continue; + } + PluginCommand p; + if ((p = Bukkit.getPluginCommand(label)) != null) { + for (String a : p.getAliases()) { + if (aliases.contains(a)) { + continue; + } + aliases.add(a); + a = a.replaceFirst("/", ""); + if (!a.equals(label) && a.equals(c)) { + c = label; + break; + } + } + } + } + if (!l.equals(c)) { + msg = msg.replace(l, c); + } + for (String s : blocked_cmds) { + Pattern pattern; + if (!RegExUtil.compiledPatterns.containsKey(s)) { + RegExUtil.compiledPatterns.put(s, pattern = Pattern.compile(s)); + } else { + pattern = RegExUtil.compiledPatterns.get(s); + } + if (pattern.matcher(msg).matches()) { + String perm; + if (plot.isAdded(pp.getUUID())) { + perm = "plots.admin.command.blocked-cmds.shared"; + } else { + perm = "plots.admin.command.blocked-cmds.other"; + } + if (!Permissions.hasPermission(pp, perm)) { + MainUtil.sendMessage(pp, C.COMMAND_BLOCKED); + event.setCancelled(true); + } + return; + } + } + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onConnect(PlayerJoinEvent event) { + final Player player = event.getPlayer(); + UUIDHandler.getPlayers().remove(player.getName()); + BukkitUtil.removePlayer(player.getName()); + final PlotPlayer pp = BukkitUtil.getPlayer(player); + // Now + String name = pp.getName(); + StringWrapper sw = new StringWrapper(name); + UUID uuid = pp.getUUID(); + UUIDHandler.add(sw, uuid); + + Location loc = pp.getLocation(); + PlotArea area = loc.getPlotArea(); + if (area != null) { + Plot plot = area.getPlot(loc); + if (plot != null) { + plotEntry(pp, plot); + } + } + // Delayed + + // Async + TaskManager.runTaskLaterAsync(() -> { + if (!player.hasPlayedBefore() && player.isOnline()) { + player.saveData(); + } + EventUtil.manager.doJoinTask(pp); + }, 20); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void playerRespawn(PlayerRespawnEvent event) { + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + EventUtil.manager.doRespawnTask(pp); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onTeleport(PlayerTeleportEvent event) { + if (event.getTo() == null || event.getFrom() == null || !event.getFrom().getWorld() + .equals(event.getTo().getWorld())) { + final Object lastLoc = BukkitUtil.getPlayer(event.getPlayer()) + .deleteMeta(PlotPlayer.META_LOCATION); + final Object lastPlot = BukkitUtil.getPlayer(event.getPlayer()) + .deleteMeta(PlotPlayer.META_LAST_PLOT); + org.bukkit.Location to = event.getTo(); + if (to != null) { Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); - Location loc = pp.getLocation(); - PlotArea area = loc.getPlotArea(); - if (area == null) { - return; - } - String[] parts = msg.split(" "); - Plot plot = pp.getCurrentPlot(); - if (BukkitMain.getWorldEdit() != null) { // Check WorldEdit - switch (parts[0].toLowerCase()) { - case "up": - case "/up": - case "worldedit:up": - case "worldedit:/up": - if (plot == null || (!plot.isAdded(pp.getUUID()) && !Permissions - .hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER, true))) { - event.setCancelled(true); - return; - } - } - } - if (plot == null) { - return; - } - Optional> flag = plot.getFlag(Flags.BLOCKED_CMDS); - if (flag.isPresent() && !Permissions - .hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_BLOCKED_CMDS)) { - List blocked_cmds = flag.get(); - String c = parts[0]; - if (parts[0].contains(":")) { - c = parts[0].split(":")[1]; - msg = msg.replace(parts[0].split(":")[0] + ':', ""); - } - String l = c; - List aliases = new ArrayList<>(); - for (HelpTopic cmdLabel : Bukkit.getServer().getHelpMap().getHelpTopics()) { - if (c.equals(cmdLabel.getName())) { - break; - } - String label = cmdLabel.getName().replaceFirst("/", ""); - if (aliases.contains(label)) { - continue; - } - PluginCommand p; - if ((p = Bukkit.getPluginCommand(label)) != null) { - for (String a : p.getAliases()) { - if (aliases.contains(a)) { - continue; - } - aliases.add(a); - a = a.replaceFirst("/", ""); - if (!a.equals(label) && a.equals(c)) { - c = label; - break; - } - } - } - } - if (!l.equals(c)) { - msg = msg.replace(l, c); - } - for (String s : blocked_cmds) { - Pattern pattern; - if (!RegExUtil.compiledPatterns.containsKey(s)) { - RegExUtil.compiledPatterns.put(s, pattern = Pattern.compile(s)); - } else { - pattern = RegExUtil.compiledPatterns.get(s); - } - if (pattern.matcher(msg).matches()) { - String perm; - if (plot.isAdded(pp.getUUID())) { - perm = "plots.admin.command.blocked-cmds.shared"; - } else { - perm = "plots.admin.command.blocked-cmds.other"; - } - if (!Permissions.hasPermission(pp, perm)) { - MainUtil.sendMessage(pp, C.COMMAND_BLOCKED); - event.setCancelled(true); - } - return; - } - } - } - } - - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void onConnect(PlayerJoinEvent event) { - final Player player = event.getPlayer(); - UUIDHandler.getPlayers().remove(player.getName()); - BukkitUtil.removePlayer(player.getName()); - final PlotPlayer pp = BukkitUtil.getPlayer(player); - // Now - String name = pp.getName(); - StringWrapper sw = new StringWrapper(name); - UUID uuid = pp.getUUID(); - UUIDHandler.add(sw, uuid); - - Location loc = pp.getLocation(); - PlotArea area = loc.getPlotArea(); - if (area != null) { - Plot plot = area.getPlot(loc); - if (plot != null) { - plotEntry(pp, plot); - } - } - // Delayed - - // Async - TaskManager.runTaskLaterAsync(() -> { - if (!player.hasPlayedBefore() && player.isOnline()) { - player.saveData(); - } - EventUtil.manager.doJoinTask(pp); - }, 20); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void playerRespawn(PlayerRespawnEvent event) { - Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); - EventUtil.manager.doRespawnTask(pp); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onTeleport(PlayerTeleportEvent event) { - if (event.getTo() == null || event.getFrom() == null || !event.getFrom().getWorld() - .equals(event.getTo().getWorld())) { - final Object lastLoc = BukkitUtil.getPlayer(event.getPlayer()).deleteMeta(PlotPlayer.META_LOCATION); - final Object lastPlot = BukkitUtil.getPlayer(event.getPlayer()).deleteMeta(PlotPlayer.META_LAST_PLOT); - org.bukkit.Location to = event.getTo(); - if (to != null) { - Player player = event.getPlayer(); - PlotPlayer pp = PlotPlayer.wrap(player); - Location loc = BukkitUtil.getLocation(to); - PlotArea area = PlotSquared.get().getPlotAreaAbs(loc); - if (area == null) { - return; - } - Plot plot = area.getPlot(loc); - if (plot != null) { - final boolean result = Flags.DENY_TELEPORT.allowsTeleport(pp, plot); - if (!result) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_ENTRY_DENIED); - event.setCancelled(true); - if (lastLoc != null) { - pp.setMeta(PlotPlayer.META_LOCATION, lastLoc); - } - if (lastPlot != null) { - pp.setMeta(PlotPlayer.META_LAST_PLOT, lastPlot); - } - } else { - plotEntry(pp, plot); - } - } - } - return; - } - playerMove(event); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void vehicleMove(VehicleMoveEvent event) throws IllegalAccessException { - final org.bukkit.Location from = event.getFrom(); - final org.bukkit.Location to = event.getTo(); - - int toX, toZ; - if ((toX = MathMan.roundInt(to.getX())) != MathMan.roundInt(from.getX()) - | (toZ = MathMan.roundInt(to.getZ())) != MathMan.roundInt(from.getZ())) { - Vehicle vehicle = event.getVehicle(); - - // Check allowed - if (!vehicle.getPassengers().isEmpty()) { - Entity passenger = vehicle.getPassengers().get(0); - - if (passenger instanceof Player) { - final Player player = (Player) passenger; - // reset - if (moveTmp == null) - moveTmp = new PlayerMoveEvent(null, from, to); - moveTmp.setFrom(from); - moveTmp.setTo(to); - moveTmp.setCancelled(false); - fieldPlayer.set(moveTmp, player); - - List passengers = vehicle.getPassengers(); - - this.playerMove(moveTmp); - org.bukkit.Location dest; - if (moveTmp.isCancelled()) { - dest = from; - } else if (MathMan.roundInt(moveTmp.getTo().getX()) != toX - || MathMan.roundInt(moveTmp.getTo().getZ()) != toZ) { - dest = to; - } else { - dest = null; - } - if (dest != null) { - if (passengers != null) { - vehicle.eject(); - vehicle.setVelocity(new Vector(0d, 0d, 0d)); - vehicle.teleport(dest); - passengers.forEach(vehicle::addPassenger); - } else { - vehicle.eject(); - vehicle.setVelocity(new Vector(0d, 0d, 0d)); - vehicle.teleport(dest); - vehicle.setPassenger(player); - } - return; - } - } - if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) { - switch (vehicle.getType()) { - case BOAT: - case ENDER_CRYSTAL: - case MINECART: - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: { - List meta = vehicle.getMetadata("plot"); - Plot toPlot = BukkitUtil.getLocation(to).getPlot(); - if (!meta.isEmpty()) { - Plot origin = (Plot) meta.get(0).value(); - if (!origin.getBasePlot(false).equals(toPlot)) { - vehicle.remove(); - } - } else if (toPlot != null) { - vehicle.setMetadata("plot", - new FixedMetadataValue((Plugin) PlotSquared.get().IMP, toPlot)); - } - } - } - } - } - - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void playerMove(PlayerMoveEvent event) { - org.bukkit.Location from = event.getFrom(); - org.bukkit.Location to = event.getTo(); - int x2; - if (MathMan.roundInt(from.getX()) != (x2 = MathMan.roundInt(to.getX()))) { - Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); - // Cancel teleport - TaskManager.TELEPORT_QUEUE.remove(pp.getName()); - // Set last location - Location loc = BukkitUtil.getLocation(to); - pp.setMeta(PlotPlayer.META_LOCATION, loc); - PlotArea area = loc.getPlotArea(); - if (area == null) { - pp.deleteMeta(PlotPlayer.META_LAST_PLOT); - return; - } - Plot now = area.getPlot(loc); - Plot lastPlot = pp.getMeta(PlotPlayer.META_LAST_PLOT); - if (now == null) { - if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport && !pp - .getMeta("kick", false)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_EXIT_DENIED); - this.tmpTeleport = false; - if (lastPlot.equals(BukkitUtil.getLocation(from).getPlot())) { - player.teleport(from); - } else { - player.teleport(player.getWorld().getSpawnLocation()); - } - this.tmpTeleport = true; - event.setCancelled(true); - return; - } - } else if (now.equals(lastPlot)) { - ForceFieldListener.handleForcefield(player, pp, now); - return; - } else if (!plotEntry(pp, now) && this.tmpTeleport) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_ENTRY_DENIED); - this.tmpTeleport = false; - to.setX(from.getBlockX()); - to.setY(from.getBlockY()); - to.setZ(from.getBlockZ()); - player.teleport(event.getTo()); - this.tmpTeleport = true; - return; - } - Integer border = area.getBorder(); - if (x2 > border && this.tmpTeleport) { - to.setX(x2 - 1); - this.tmpTeleport = false; - player.teleport(event.getTo()); - this.tmpTeleport = true; - MainUtil.sendMessage(pp, C.BORDER); - return; - } - if (x2 < -border && this.tmpTeleport) { - to.setX(x2 + 1); - this.tmpTeleport = false; - player.teleport(event.getTo()); - this.tmpTeleport = true; - MainUtil.sendMessage(pp, C.BORDER); - return; - } - return; - } - int z2; - if (MathMan.roundInt(from.getZ()) != (z2 = MathMan.roundInt(to.getZ()))) { - Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); - // Cancel teleport - TaskManager.TELEPORT_QUEUE.remove(pp.getName()); - // Set last location - Location loc = BukkitUtil.getLocation(to); - pp.setMeta(PlotPlayer.META_LOCATION, loc); - PlotArea area = loc.getPlotArea(); - if (area == null) { - pp.deleteMeta(PlotPlayer.META_LAST_PLOT); - return; - } - Plot now = area.getPlot(loc); - Plot lastPlot = pp.getMeta(PlotPlayer.META_LAST_PLOT); - if (now == null) { - if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport && !pp - .getMeta("kick", false)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_EXIT_DENIED); - this.tmpTeleport = false; - if (lastPlot.equals(BukkitUtil.getLocation(from).getPlot())) { - player.teleport(from); - } else { - player.teleport(player.getWorld().getSpawnLocation()); - } - this.tmpTeleport = true; - event.setCancelled(true); - return; - } - } else if (now.equals(lastPlot)) { - ForceFieldListener.handleForcefield(player, pp, now); - return; - } else if (!plotEntry(pp, now) && this.tmpTeleport) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_ENTRY_DENIED); - this.tmpTeleport = false; - player.teleport(from); - to.setX(from.getBlockX()); - to.setY(from.getBlockY()); - to.setZ(from.getBlockZ()); - player.teleport(event.getTo()); - this.tmpTeleport = true; - return; - } - Integer border = area.getBorder(); - if (z2 > border && this.tmpTeleport) { - to.setZ(z2 - 1); - this.tmpTeleport = false; - player.teleport(event.getTo()); - this.tmpTeleport = true; - MainUtil.sendMessage(pp, C.BORDER); - } else if (z2 < -border && this.tmpTeleport) { - to.setZ(z2 + 1); - this.tmpTeleport = false; - player.teleport(event.getTo()); - this.tmpTeleport = true; - MainUtil.sendMessage(pp, C.BORDER); - } - } - } - - @EventHandler(priority = EventPriority.LOW) public void onChat(AsyncPlayerChatEvent event) { - if (event.isCancelled()) - return; - - PlotPlayer plotPlayer = BukkitUtil.getPlayer(event.getPlayer()); - Location location = plotPlayer.getLocation(); - PlotArea area = location.getPlotArea(); - if (area == null || (area.PLOT_CHAT == plotPlayer.getAttribute("chat"))) { - return; - } - Plot plot = area.getPlot(location); - if (plot == null) { - return; - } - event.setCancelled(true); - String message = event.getMessage(); - String format = C.PLOT_CHAT_FORMAT.s(); - String sender = event.getPlayer().getDisplayName(); - PlotId id = plot.getId(); - Set recipients = event.getRecipients(); - Set spies = new HashSet<>(); - recipients.clear(); - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer pp = entry.getValue(); - if (pp.getAttribute("chatspy")) { - spies.add(((BukkitPlayer) pp).player); - } else { - Plot current = pp.getCurrentPlot(); - if (current != null && current.getBasePlot(false).equals(plot)) { - recipients.add(((BukkitPlayer) pp).player); - } - } - } - String partial = ChatColor.translateAlternateColorCodes('&', - format.replace("%plot_id%", id.x + ";" + id.y).replace("%sender%", sender)); - if (plotPlayer.hasPermission("plots.chat.color")) { - message = C.color(message); - } - String full = partial.replace("%msg%", message); - for (Player receiver : recipients) { - receiver.sendMessage(full); - } - if (!spies.isEmpty()) { - String spyMessage = C.PLOT_CHAT_SPY_FORMAT.s().replace("%plot_id%", id.x + ";" + id.y) - .replace("%sender%", sender).replace("%msg%", message); - for (Player player : spies) { - player.sendMessage(spyMessage); - } - } - PlotSquared.debug(full); - } - - @EventHandler(priority = EventPriority.LOWEST) public void blockDestroy(BlockBreakEvent event) { - Player player = event.getPlayer(); - Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - Plot plot = area.getPlot(location); - if (plot != null) { - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); - if (event.getBlock().getY() == 0) { - if (!Permissions - .hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL)) { - MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, - C.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL); - event.setCancelled(true); - return; - } - } else if ( - (location.getY() > area.MAX_BUILD_HEIGHT || location.getY() < area.MIN_BUILD_HEIGHT) - && !Permissions - .hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_HEIGHTLIMIT)) { - event.setCancelled(true); - MainUtil.sendMessage(plotPlayer, - C.HEIGHT_LIMIT.s().replace("{limit}", String.valueOf(area.MAX_BUILD_HEIGHT))); - } - if (!plot.hasOwner()) { - if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_UNOWNED)) { - return; - } - MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, - C.PERMISSION_ADMIN_DESTROY_UNOWNED); - event.setCancelled(true); - return; - } - if (!plot.isAdded(plotPlayer.getUUID())) { - Optional> destroy = plot.getFlag(Flags.BREAK); - Block block = event.getBlock(); - if (destroy.isPresent() && destroy.get() - .contains(PlotBlock.get(block.getType().name()))) { - return; - } - if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_OTHER)) { - return; - } - MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, - C.PERMISSION_ADMIN_DESTROY_OTHER); - event.setCancelled(true); - } else if (Settings.Done.RESTRICT_BUILDING && plot.getFlags().containsKey(Flags.DONE)) { - if (!Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_OTHER)) { - MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, - C.PERMISSION_ADMIN_BUILD_OTHER); - event.setCancelled(true); - return; - } - } - return; - } - PlotPlayer pp = BukkitUtil.getPlayer(player); - if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_DESTROY_ROAD)) { - return; - } - if (PlotSquared.get().worldedit != null && pp.getAttribute("worldedit")) { - if (player.getInventory().getItemInMainHand().getType() == Material - .getMaterial(PlotSquared.get().worldedit.getConfiguration().wandItem)) { - return; - } - } - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_ROAD); - event.setCancelled(true); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBigBoom(EntityExplodeEvent event) { - Location location = BukkitUtil.getLocation(event.getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - if (!PlotSquared.get().hasPlotArea(location.getWorld())) { - return; - } - Iterator iterator = event.blockList().iterator(); - while (iterator.hasNext()) { - iterator.next(); - if (location.getPlotArea() != null) { - iterator.remove(); - } - } - return; - } - Plot plot = area.getOwnedPlot(location); - if (plot != null) { - if (Flags.EXPLOSION.isTrue(plot)) { - List meta = event.getEntity().getMetadata("plot"); - Plot origin; - if (meta.isEmpty()) { - origin = plot; - } else { - origin = (Plot) meta.get(0).value(); - } - if (this.lastRadius != 0) { - List nearby = event.getEntity() - .getNearbyEntities(this.lastRadius, this.lastRadius, this.lastRadius); - for (Entity near : nearby) { - if (near instanceof TNTPrimed || near.getType() - .equals(EntityType.MINECART_TNT)) { - if (!near.hasMetadata("plot")) { - near.setMetadata("plot", - new FixedMetadataValue((Plugin) PlotSquared.get().IMP, plot)); - } - } - } - this.lastRadius = 0; - } - Iterator iterator = event.blockList().iterator(); - while (iterator.hasNext()) { - Block block = iterator.next(); - location = BukkitUtil.getLocation(block.getLocation()); - if (!area.contains(location.getX(), location.getZ()) || !origin - .equals(area.getOwnedPlot(location))) { - iterator.remove(); - } - } - return; - } - } - event.setCancelled(true); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onWorldChanged(PlayerChangedWorldEvent event) { - Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); - // Delete last location - pp.deleteMeta(PlotPlayer.META_LOCATION); - Plot plot = (Plot) pp.deleteMeta(PlotPlayer.META_LAST_PLOT); - if (plot != null) { - plotExit(pp, plot); - } - if (PlotSquared.get().worldedit != null) { - if (!Permissions.hasPermission(pp, C.PERMISSION_WORLDEDIT_BYPASS)) { - if (pp.getAttribute("worldedit")) { - pp.removeAttribute("worldedit"); - } - } - } - if (Settings.Enabled_Components.PERMISSION_CACHE) { - pp.deleteMeta("perm"); - } - Location loc = pp.getLocation(); + PlotPlayer pp = PlotPlayer.wrap(player); + Location loc = BukkitUtil.getLocation(to); PlotArea area = PlotSquared.get().getPlotAreaAbs(loc); if (area == null) { - return; + return; } - plot = area.getPlot(loc); + Plot plot = area.getPlot(loc); if (plot != null) { + final boolean result = Flags.DENY_TELEPORT.allowsTeleport(pp, plot); + if (!result) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_ENTRY_DENIED); + event.setCancelled(true); + if (lastLoc != null) { + pp.setMeta(PlotPlayer.META_LOCATION, lastLoc); + } + if (lastPlot != null) { + pp.setMeta(PlotPlayer.META_LAST_PLOT, lastPlot); + } + } else { plotEntry(pp, plot); + } } + } + return; } + playerMove(event); + } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPeskyMobsChangeTheWorldLikeWTFEvent(EntityChangeBlockEvent event) { - Entity e = event.getEntity(); - if (!(e instanceof FallingBlock)) { - Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); - PlotArea area = location.getPlotArea(); - if (area != null) { - Plot plot = area.getOwnedPlot(location); - if (plot != null && Flags.MOB_BREAK.isTrue(plot)) - return; - event.setCancelled(true); + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void vehicleMove(VehicleMoveEvent event) throws IllegalAccessException { + final org.bukkit.Location from = event.getFrom(); + final org.bukkit.Location to = event.getTo(); + + int toX, toZ; + if ((toX = MathMan.roundInt(to.getX())) != MathMan.roundInt(from.getX()) + | (toZ = MathMan.roundInt(to.getZ())) != MathMan.roundInt(from.getZ())) { + Vehicle vehicle = event.getVehicle(); + + // Check allowed + if (!vehicle.getPassengers().isEmpty()) { + Entity passenger = vehicle.getPassengers().get(0); + + if (passenger instanceof Player) { + final Player player = (Player) passenger; + // reset + if (moveTmp == null) { + moveTmp = new PlayerMoveEvent(null, from, to); + } + moveTmp.setFrom(from); + moveTmp.setTo(to); + moveTmp.setCancelled(false); + fieldPlayer.set(moveTmp, player); + + List passengers = vehicle.getPassengers(); + + this.playerMove(moveTmp); + org.bukkit.Location dest; + if (moveTmp.isCancelled()) { + dest = from; + } else if (MathMan.roundInt(moveTmp.getTo().getX()) != toX + || MathMan.roundInt(moveTmp.getTo().getZ()) != toZ) { + dest = to; + } else { + dest = null; + } + if (dest != null) { + if (passengers != null) { + vehicle.eject(); + vehicle.setVelocity(new Vector(0d, 0d, 0d)); + vehicle.teleport(dest); + passengers.forEach(vehicle::addPassenger); + } else { + vehicle.eject(); + vehicle.setVelocity(new Vector(0d, 0d, 0d)); + vehicle.teleport(dest); + vehicle.addPassenger(player); } - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onEntityBlockForm(EntityBlockFormEvent event) { - String world = event.getBlock().getWorld().getName(); - if (!PlotSquared.get().hasPlotArea(world)) { return; + } } - Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - Plot plot = area.getOwnedPlot(location); - if (plot == null) { - event.setCancelled(true); - return; - } - Entity entity = event.getEntity(); - if (entity instanceof Player) { - Player player = (Player) entity; - if (!plot.hasOwner()) { - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); - if (Flags.ICE_FORM.isTrue(plot)) { - return; + if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) { + switch (vehicle.getType()) { + case BOAT: + case ENDER_CRYSTAL: + case MINECART: + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: { + List meta = vehicle.getMetadata("plot"); + Plot toPlot = BukkitUtil.getLocation(to).getPlot(); + if (!meta.isEmpty()) { + Plot origin = (Plot) meta.get(0).value(); + if (!origin.getBasePlot(false).equals(toPlot)) { + vehicle.remove(); } - event.setCancelled(true); - return; + } else if (toPlot != null) { + vehicle.setMetadata("plot", + new FixedMetadataValue((Plugin) PlotSquared.get().IMP, toPlot)); + } } - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); - if (!plot.isAdded(plotPlayer.getUUID())) { - if (Flags.ICE_FORM.isTrue(plot)) { - return; - } - event.setCancelled(true); - return; - } - return; + } } - if (!Flags.ICE_FORM.isTrue(plot)) { - event.setCancelled(true); + } + + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void playerMove(PlayerMoveEvent event) { + org.bukkit.Location from = event.getFrom(); + org.bukkit.Location to = event.getTo(); + int x2; + if (MathMan.roundInt(from.getX()) != (x2 = MathMan.roundInt(to.getX()))) { + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + // Cancel teleport + TaskManager.TELEPORT_QUEUE.remove(pp.getName()); + // Set last location + Location loc = BukkitUtil.getLocation(to); + pp.setMeta(PlotPlayer.META_LOCATION, loc); + PlotArea area = loc.getPlotArea(); + if (area == null) { + pp.deleteMeta(PlotPlayer.META_LAST_PLOT); + return; + } + Plot now = area.getPlot(loc); + Plot lastPlot = pp.getMeta(PlotPlayer.META_LAST_PLOT); + if (now == null) { + if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport && !pp + .getMeta("kick", false)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_EXIT_DENIED); + this.tmpTeleport = false; + if (lastPlot.equals(BukkitUtil.getLocation(from).getPlot())) { + player.teleport(from); + } else { + player.teleport(player.getWorld().getSpawnLocation()); + } + this.tmpTeleport = true; + event.setCancelled(true); + return; } + } else if (now.equals(lastPlot)) { + ForceFieldListener.handleForcefield(player, pp, now); + return; + } else if (!plotEntry(pp, now) && this.tmpTeleport) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_ENTRY_DENIED); + this.tmpTeleport = false; + to.setX(from.getBlockX()); + to.setY(from.getBlockY()); + to.setZ(from.getBlockZ()); + player.teleport(event.getTo()); + this.tmpTeleport = true; + return; + } + int border = area.getBorder(); + if (x2 > border && this.tmpTeleport) { + to.setX(x2 - 1); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + return; + } + if (x2 < -border && this.tmpTeleport) { + to.setX(x2 + 1); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + return; + } + return; + } + int z2; + if (MathMan.roundInt(from.getZ()) != (z2 = MathMan.roundInt(to.getZ()))) { + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + // Cancel teleport + TaskManager.TELEPORT_QUEUE.remove(pp.getName()); + // Set last location + Location loc = BukkitUtil.getLocation(to); + pp.setMeta(PlotPlayer.META_LOCATION, loc); + PlotArea area = loc.getPlotArea(); + if (area == null) { + pp.deleteMeta(PlotPlayer.META_LAST_PLOT); + return; + } + Plot now = area.getPlot(loc); + Plot lastPlot = pp.getMeta(PlotPlayer.META_LAST_PLOT); + if (now == null) { + if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport && !pp + .getMeta("kick", false)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_EXIT_DENIED); + this.tmpTeleport = false; + if (lastPlot.equals(BukkitUtil.getLocation(from).getPlot())) { + player.teleport(from); + } else { + player.teleport(player.getWorld().getSpawnLocation()); + } + this.tmpTeleport = true; + event.setCancelled(true); + return; + } + } else if (now.equals(lastPlot)) { + ForceFieldListener.handleForcefield(player, pp, now); + return; + } else if (!plotEntry(pp, now) && this.tmpTeleport) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_ENTRY_DENIED); + this.tmpTeleport = false; + player.teleport(from); + to.setX(from.getBlockX()); + to.setY(from.getBlockY()); + to.setZ(from.getBlockZ()); + player.teleport(event.getTo()); + this.tmpTeleport = true; + return; + } + int border = area.getBorder(); + if (z2 > border && this.tmpTeleport) { + to.setZ(z2 - 1); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + } else if (z2 < -border && this.tmpTeleport) { + to.setZ(z2 + 1); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + } + } + } + + @EventHandler(priority = EventPriority.LOW) + public void onChat(AsyncPlayerChatEvent event) { + if (event.isCancelled()) { + return; } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBlockSpread(BlockSpreadEvent event) { + PlotPlayer plotPlayer = BukkitUtil.getPlayer(event.getPlayer()); + Location location = plotPlayer.getLocation(); + PlotArea area = location.getPlotArea(); + if (area == null || (area.PLOT_CHAT == plotPlayer.getAttribute("chat"))) { + return; + } + Plot plot = area.getPlot(location); + if (plot == null) { + return; + } + event.setCancelled(true); + String message = event.getMessage(); + String format = C.PLOT_CHAT_FORMAT.s(); + String sender = event.getPlayer().getDisplayName(); + PlotId id = plot.getId(); + Set recipients = event.getRecipients(); + Set spies = new HashSet<>(); + recipients.clear(); + for (Entry entry : UUIDHandler.getPlayers().entrySet()) { + PlotPlayer pp = entry.getValue(); + if (pp.getAttribute("chatspy")) { + spies.add(((BukkitPlayer) pp).player); + } else { + Plot current = pp.getCurrentPlot(); + if (current != null && current.getBasePlot(false).equals(plot)) { + recipients.add(((BukkitPlayer) pp).player); + } + } + } + String partial = ChatColor.translateAlternateColorCodes('&', + format.replace("%plot_id%", id.x + ";" + id.y).replace("%sender%", sender)); + if (plotPlayer.hasPermission("plots.chat.color")) { + message = C.color(message); + } + String full = partial.replace("%msg%", message); + for (Player receiver : recipients) { + receiver.sendMessage(full); + } + if (!spies.isEmpty()) { + String spyMessage = C.PLOT_CHAT_SPY_FORMAT.s().replace("%plot_id%", id.x + ";" + id.y) + .replace("%sender%", sender).replace("%msg%", message); + for (Player player : spies) { + player.sendMessage(spyMessage); + } + } + PlotSquared.debug(full); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void blockDestroy(BlockBreakEvent event) { + Player player = event.getPlayer(); + Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getPlot(location); + if (plot != null) { + PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + if (event.getBlock().getY() == 0) { + if (!Permissions + .hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, + C.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL); + event.setCancelled(true); + return; + } + } else if ( + (location.getY() > area.MAX_BUILD_HEIGHT || location.getY() < area.MIN_BUILD_HEIGHT) + && !Permissions + .hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_HEIGHTLIMIT)) { + event.setCancelled(true); + MainUtil.sendMessage(plotPlayer, + C.HEIGHT_LIMIT.s().replace("{limit}", String.valueOf(area.MAX_BUILD_HEIGHT))); + } + if (!plot.hasOwner()) { + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_UNOWNED)) { + return; + } + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, + C.PERMISSION_ADMIN_DESTROY_UNOWNED); + event.setCancelled(true); + return; + } + if (!plot.isAdded(plotPlayer.getUUID())) { + Optional> destroy = plot.getFlag(Flags.BREAK); Block block = event.getBlock(); - Location location = BukkitUtil.getLocation(block.getLocation()); - if (location.isPlotRoad()) { - event.setCancelled(true); - return; + if (destroy.isPresent() && destroy.get() + .contains(PlotBlock.get(block.getType().name()))) { + return; } - PlotArea area = location.getPlotArea(); - if (area == null) { - return; + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_OTHER)) { + return; } - Plot plot = area.getOwnedPlot(location); - if (plot == null) { - return; - } - switch (event.getSource().getType()) { - case GRASS: - if (Flags.GRASS_GROW.isFalse(plot)) { - event.setCancelled(true); - } - break; - case MYCELIUM: - if (Flags.MYCEL_GROW.isFalse(plot)) { - event.setCancelled(true); - } - break; - case VINE: - if (Flags.VINE_GROW.isFalse(plot)) { - event.setCancelled(true); - } - break; + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, + C.PERMISSION_ADMIN_DESTROY_OTHER); + event.setCancelled(true); + } else if (Settings.Done.RESTRICT_BUILDING && plot.getFlags().containsKey(Flags.DONE)) { + if (!Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_OTHER)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, + C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + return; } + } + return; } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBlockForm(BlockFormEvent event) { - Block block = event.getBlock(); - Location location = BukkitUtil.getLocation(block.getLocation()); - if (location.isPlotRoad()) { - event.setCancelled(true); - return; - } - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - Plot plot = area.getOwnedPlot(location); - if (plot == null) { - return; - } - switch (event.getNewState().getType()) { - case SNOW: - case SNOW_BLOCK: - if (Flags.SNOW_FORM.isFalse(plot)) { - event.setCancelled(true); - } - return; - case ICE: - case FROSTED_ICE: - case PACKED_ICE: - if (Flags.ICE_FORM.isFalse(plot)) { - event.setCancelled(true); - } - return; - case STONE: - case OBSIDIAN: - case COBBLESTONE: - // TODO event ? - return; - } + PlotPlayer pp = BukkitUtil.getPlayer(player); + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_DESTROY_ROAD)) { + return; } + if (PlotSquared.get().worldedit != null && pp.getAttribute("worldedit")) { + if (player.getInventory().getItemInMainHand().getType() == Material + .getMaterial(PlotSquared.get().worldedit.getConfiguration().wandItem)) { + return; + } + } + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_ROAD); + event.setCancelled(true); + } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBlockDamage(BlockDamageEvent event) { - Player player = event.getPlayer(); - Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); - if (player == null) { - if (location.isPlotRoad()) { - event.setCancelled(true); - return; - } + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBigBoom(EntityExplodeEvent event) { + Location location = BukkitUtil.getLocation(event.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + if (!PlotSquared.get().hasPlotArea(location.getWorld())) { + return; + } + Iterator iterator = event.blockList().iterator(); + while (iterator.hasNext()) { + iterator.next(); + if (location.getPlotArea() != null) { + iterator.remove(); } - PlotArea area = location.getPlotArea(); - if (area == null) { - return; + } + return; + } + Plot plot = area.getOwnedPlot(location); + if (plot != null) { + if (Flags.EXPLOSION.isTrue(plot)) { + List meta = event.getEntity().getMetadata("plot"); + Plot origin; + if (meta.isEmpty()) { + origin = plot; + } else { + origin = (Plot) meta.get(0).value(); } - Plot plot = area.getPlot(location); - if (plot != null) { - if (location.getY() == 0) { - event.setCancelled(true); - return; + if (this.lastRadius != 0) { + List nearby = event.getEntity() + .getNearbyEntities(this.lastRadius, this.lastRadius, this.lastRadius); + for (Entity near : nearby) { + if (near instanceof TNTPrimed || near.getType() + .equals(EntityType.MINECART_TNT)) { + if (!near.hasMetadata("plot")) { + near.setMetadata("plot", + new FixedMetadataValue((Plugin) PlotSquared.get().IMP, plot)); + } } - if (!plot.hasOwner()) { - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); - if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_UNOWNED)) { - return; - } - event.setCancelled(true); - return; - } - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); - if (!plot.isAdded(plotPlayer.getUUID())) { - Optional> destroy = plot.getFlag(Flags.BREAK); - Block block = event.getBlock(); - if (destroy.isPresent() && destroy.get() - .contains(PlotBlock.get(block.getType().name())) || Permissions - .hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_OTHER)) { - return; - } - event.setCancelled(true); - return; - } - return; + } + this.lastRadius = 0; } - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); - if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_ROAD)) { - return; + Iterator iterator = event.blockList().iterator(); + while (iterator.hasNext()) { + Block block = iterator.next(); + location = BukkitUtil.getLocation(block.getLocation()); + if (!area.contains(location.getX(), location.getZ()) || !origin + .equals(area.getOwnedPlot(location))) { + iterator.remove(); + } + } + return; + } + } + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onWorldChanged(PlayerChangedWorldEvent event) { + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + // Delete last location + pp.deleteMeta(PlotPlayer.META_LOCATION); + Plot plot = (Plot) pp.deleteMeta(PlotPlayer.META_LAST_PLOT); + if (plot != null) { + plotExit(pp, plot); + } + if (PlotSquared.get().worldedit != null) { + if (!Permissions.hasPermission(pp, C.PERMISSION_WORLDEDIT_BYPASS)) { + if (pp.getAttribute("worldedit")) { + pp.removeAttribute("worldedit"); + } + } + } + if (Settings.Enabled_Components.PERMISSION_CACHE) { + pp.deleteMeta("perm"); + } + Location loc = pp.getLocation(); + PlotArea area = PlotSquared.get().getPlotAreaAbs(loc); + if (area == null) { + return; + } + plot = area.getPlot(loc); + if (plot != null) { + plotEntry(pp, plot); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPeskyMobsChangeTheWorldLikeWTFEvent(EntityChangeBlockEvent event) { + Entity e = event.getEntity(); + if (!(e instanceof FallingBlock)) { + Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); + PlotArea area = location.getPlotArea(); + if (area != null) { + Plot plot = area.getOwnedPlot(location); + if (plot != null && Flags.MOB_BREAK.isTrue(plot)) { + return; } event.setCancelled(true); + } } + } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onFade(BlockFadeEvent event) { - Block b = event.getBlock(); - Location location = BukkitUtil.getLocation(b.getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - Plot plot = area.getOwnedPlot(location); - if (plot == null) { - event.setCancelled(true); - return; - } - switch (b.getType()) { - case ICE: - if (Flags.ICE_MELT.isFalse(plot)) { - event.setCancelled(true); - } - break; - case SNOW: - if (Flags.SNOW_MELT.isFalse(plot)) { - event.setCancelled(true); - } - break; - case FARMLAND: - if (Flags.SOIL_DRY.isFalse(plot)) { - event.setCancelled(true); - } - break; - } + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onEntityBlockForm(EntityBlockFormEvent event) { + String world = event.getBlock().getWorld().getName(); + if (!PlotSquared.get().hasPlotArea(world)) { + return; } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onChange(BlockFromToEvent event) { - Block from = event.getBlock(); - Block to = event.getToBlock(); - Location tLocation = BukkitUtil.getLocation(to.getLocation()); - PlotArea area = tLocation.getPlotArea(); - if (area == null) { - return; - } - Plot plot = area.getOwnedPlot(tLocation); - Location fLocation = BukkitUtil.getLocation(from.getLocation()); - if (plot != null) { - if (Flags.DISABLE_PHYSICS.isFalse(plot)) { - event.setCancelled(true); - return; - } else if (!area.contains(fLocation.getX(), fLocation.getZ()) || !Objects - .equals(plot, area.getOwnedPlot(fLocation))) { - event.setCancelled(true); - return; - } - if (Flags.LIQUID_FLOW.isFalse(plot)) { - switch (to.getType()) { - case WATER: - case LAVA: - event.setCancelled(true); - } - } - } else if (!area.contains(fLocation.getX(), fLocation.getZ()) || !Objects - .equals(null, area.getOwnedPlot(fLocation))) { - event.setCancelled(true); - } + Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onGrow(BlockGrowEvent event) { - Block b = event.getBlock(); - Location location = BukkitUtil.getLocation(b.getLocation()); - if (location.isUnownedPlotArea()) { - event.setCancelled(true); - } + Plot plot = area.getOwnedPlot(location); + if (plot == null) { + event.setCancelled(true); + return; } + Entity entity = event.getEntity(); + if (entity instanceof Player) { + Player player = (Player) entity; + if (!plot.hasOwner()) { + PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + if (Flags.ICE_FORM.isTrue(plot)) { + return; + } + event.setCancelled(true); + return; + } + PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + if (!plot.isAdded(plotPlayer.getUUID())) { + if (Flags.ICE_FORM.isTrue(plot)) { + return; + } + event.setCancelled(true); + return; + } + return; + } + if (!Flags.ICE_FORM.isTrue(plot)) { + event.setCancelled(true); + } + } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBlockPistonExtend(BlockPistonExtendEvent event) { + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockSpread(BlockSpreadEvent event) { + Block block = event.getBlock(); + Location location = BukkitUtil.getLocation(block.getLocation()); + if (location.isPlotRoad()) { + event.setCancelled(true); + return; + } + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlot(location); + if (plot == null) { + return; + } + switch (event.getSource().getType()) { + case GRASS: + if (Flags.GRASS_GROW.isFalse(plot)) { + event.setCancelled(true); + } + break; + case MYCELIUM: + if (Flags.MYCEL_GROW.isFalse(plot)) { + event.setCancelled(true); + } + break; + case VINE: + if (Flags.VINE_GROW.isFalse(plot)) { + event.setCancelled(true); + } + break; + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockForm(BlockFormEvent event) { + Block block = event.getBlock(); + Location location = BukkitUtil.getLocation(block.getLocation()); + if (location.isPlotRoad()) { + event.setCancelled(true); + return; + } + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlot(location); + if (plot == null) { + return; + } + switch (event.getNewState().getType()) { + case SNOW: + case SNOW_BLOCK: + if (Flags.SNOW_FORM.isFalse(plot)) { + event.setCancelled(true); + } + return; + case ICE: + case FROSTED_ICE: + case PACKED_ICE: + if (Flags.ICE_FORM.isFalse(plot)) { + event.setCancelled(true); + } + return; + case STONE: + case OBSIDIAN: + case COBBLESTONE: + // TODO event ? + return; + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockDamage(BlockDamageEvent event) { + Player player = event.getPlayer(); + Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); + if (player == null) { + if (location.isPlotRoad()) { + event.setCancelled(true); + return; + } + } + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getPlot(location); + if (plot != null) { + if (location.getY() == 0) { + event.setCancelled(true); + return; + } + if (!plot.hasOwner()) { + PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_UNOWNED)) { + return; + } + event.setCancelled(true); + return; + } + PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + if (!plot.isAdded(plotPlayer.getUUID())) { + Optional> destroy = plot.getFlag(Flags.BREAK); Block block = event.getBlock(); - Location location = BukkitUtil.getLocation(block.getLocation()); - BlockFace face = event.getDirection(); - Vector relative = new Vector(face.getModX(), face.getModY(), face.getModZ()); - PlotArea area = location.getPlotArea(); - if (area == null) { - if (!PlotSquared.get().hasPlotArea(location.getWorld())) { - return; - } - for (Block b : event.getBlocks()) { - if (BukkitUtil.getLocation(b.getLocation().add(relative)).getPlotArea() != null) { - event.setCancelled(true); - return; - } - } - return; - } - Plot plot = area.getOwnedPlot(location); - if (plot == null) { - event.setCancelled(true); - return; - } - List blocks = event.getBlocks(); - for (Block b : blocks) { - Location bloc = BukkitUtil.getLocation(b.getLocation()); - if (!area.contains(bloc.getX(), bloc.getZ()) || !area - .contains(bloc.getX() + relative.getBlockX(), bloc.getZ() + relative.getBlockZ())) { - event.setCancelled(true); - return; - } - if (!plot.equals(area.getOwnedPlot(bloc)) || !plot.equals(area.getOwnedPlot( - bloc.add(relative.getBlockX(), relative.getBlockY(), relative.getBlockZ())))) { - event.setCancelled(true); - return; - } + if (destroy.isPresent() && destroy.get() + .contains(PlotBlock.get(block.getType().name())) || Permissions + .hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_OTHER)) { + return; } + event.setCancelled(true); + return; + } + return; } + PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_ROAD)) { + return; + } + event.setCancelled(true); + } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBlockPistonRetract(BlockPistonRetractEvent event) { - Block block = event.getBlock(); - Location location = BukkitUtil.getLocation(block.getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - if (!PlotSquared.get().hasPlotArea(location.getWorld())) { - return; - } - if (this.pistonBlocks) { - try { - for (Block pulled : event.getBlocks()) { - location = BukkitUtil.getLocation(pulled.getLocation()); - if (location.getPlotArea() != null) { - event.setCancelled(true); - return; - } - } - } catch (Throwable ignored) { - this.pistonBlocks = false; - } - } - if (!this.pistonBlocks && !block.getType().toString().contains("PISTON")) { - BlockFace dir = event.getDirection(); - location = BukkitUtil.getLocation(block.getLocation() - .add(dir.getModX() * 2, dir.getModY() * 2, dir.getModZ() * 2)); - if (location.getPlotArea() != null) { - event.setCancelled(true); - return; - } - } - return; + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onFade(BlockFadeEvent event) { + Block b = event.getBlock(); + Location location = BukkitUtil.getLocation(b.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlot(location); + if (plot == null) { + event.setCancelled(true); + return; + } + switch (b.getType()) { + case ICE: + if (Flags.ICE_MELT.isFalse(plot)) { + event.setCancelled(true); } - Plot plot = area.getOwnedPlot(location); + break; + case SNOW: + if (Flags.SNOW_MELT.isFalse(plot)) { + event.setCancelled(true); + } + break; + case FARMLAND: + if (Flags.SOIL_DRY.isFalse(plot)) { + event.setCancelled(true); + } + break; + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onChange(BlockFromToEvent event) { + Block from = event.getBlock(); + Block to = event.getToBlock(); + Location tLocation = BukkitUtil.getLocation(to.getLocation()); + PlotArea area = tLocation.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlot(tLocation); + Location fLocation = BukkitUtil.getLocation(from.getLocation()); + if (plot != null) { + if (Flags.DISABLE_PHYSICS.isFalse(plot)) { + event.setCancelled(true); + return; + } else if (!area.contains(fLocation.getX(), fLocation.getZ()) || !Objects + .equals(plot, area.getOwnedPlot(fLocation))) { + event.setCancelled(true); + return; + } + if (Flags.LIQUID_FLOW.isFalse(plot)) { + switch (to.getType()) { + case WATER: + case LAVA: + event.setCancelled(true); + } + } + } else if (!area.contains(fLocation.getX(), fLocation.getZ()) || !Objects + .equals(null, area.getOwnedPlot(fLocation))) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onGrow(BlockGrowEvent event) { + Block b = event.getBlock(); + Location location = BukkitUtil.getLocation(b.getLocation()); + if (location.isUnownedPlotArea()) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockPistonExtend(BlockPistonExtendEvent event) { + Block block = event.getBlock(); + Location location = BukkitUtil.getLocation(block.getLocation()); + BlockFace face = event.getDirection(); + Vector relative = new Vector(face.getModX(), face.getModY(), face.getModZ()); + PlotArea area = location.getPlotArea(); + if (area == null) { + if (!PlotSquared.get().hasPlotArea(location.getWorld())) { + return; + } + for (Block b : event.getBlocks()) { + if (BukkitUtil.getLocation(b.getLocation().add(relative)).getPlotArea() != null) { + event.setCancelled(true); + return; + } + } + return; + } + Plot plot = area.getOwnedPlot(location); + if (plot == null) { + event.setCancelled(true); + return; + } + List blocks = event.getBlocks(); + for (Block b : blocks) { + Location bloc = BukkitUtil.getLocation(b.getLocation()); + if (!area.contains(bloc.getX(), bloc.getZ()) || !area + .contains(bloc.getX() + relative.getBlockX(), bloc.getZ() + relative.getBlockZ())) { + event.setCancelled(true); + return; + } + if (!plot.equals(area.getOwnedPlot(bloc)) || !plot.equals(area.getOwnedPlot( + bloc.add(relative.getBlockX(), relative.getBlockY(), relative.getBlockZ())))) { + event.setCancelled(true); + return; + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockPistonRetract(BlockPistonRetractEvent event) { + Block block = event.getBlock(); + Location location = BukkitUtil.getLocation(block.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + if (!PlotSquared.get().hasPlotArea(location.getWorld())) { + return; + } + if (this.pistonBlocks) { + try { + for (Block pulled : event.getBlocks()) { + location = BukkitUtil.getLocation(pulled.getLocation()); + if (location.getPlotArea() != null) { + event.setCancelled(true); + return; + } + } + } catch (Throwable ignored) { + this.pistonBlocks = false; + } + } + if (!this.pistonBlocks && !block.getType().toString().contains("PISTON")) { BlockFace dir = event.getDirection(); - // Location head = location.add(-dir.getModX(), -dir.getModY(), -dir.getModZ()); - // - // if (!Objects.equals(plot, area.getOwnedPlot(head))) { - // // FIXME: cancelling the event doesn't work here. See issue #1484 - // event.setCancelled(true); - // return; - // } - if (this.pistonBlocks) { - try { - for (Block pulled : event.getBlocks()) { - Location from = BukkitUtil.getLocation( - pulled.getLocation().add(dir.getModX(), dir.getModY(), dir.getModZ())); - Location to = BukkitUtil.getLocation(pulled.getLocation()); - if (!area.contains(to.getX(), to.getZ())) { - event.setCancelled(true); - return; - } - Plot fromPlot = area.getOwnedPlot(from); - Plot toPlot = area.getOwnedPlot(to); - if (!Objects.equals(fromPlot, toPlot)) { - event.setCancelled(true); - return; - } - } - } catch (Throwable ignored) { - this.pistonBlocks = false; - } - } - if (!this.pistonBlocks && !block.getType().toString().contains("PISTON")) { - location = BukkitUtil.getLocation( - block.getLocation().add(dir.getModX() * 2, dir.getModY() * 2, dir.getModZ() * 2)); - if (!area.contains(location)) { - event.setCancelled(true); - return; - } - Plot newPlot = area.getOwnedPlot(location); - if (!Objects.equals(plot, newPlot)) { - event.setCancelled(true); - } + location = BukkitUtil.getLocation(block.getLocation() + .add(dir.getModX() * 2, dir.getModY() * 2, dir.getModZ() * 2)); + if (location.getPlotArea() != null) { + event.setCancelled(true); + return; } + } + return; } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBlockDispense(BlockDispenseEvent event) { - Material type = event.getItem().getType(); - switch (type) { - case WATER_BUCKET: - case LAVA_BUCKET: { - if (event.getBlock().getType() == Material.DROPPER) - return; - BlockFace targetFace = - ((org.bukkit.material.Dispenser) event.getBlock().getState().getData()) - .getFacing(); - Location location = - BukkitUtil.getLocation(event.getBlock().getRelative(targetFace).getLocation()); - if (location.isPlotRoad()) { - event.setCancelled(true); - } - } - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onStructureGrow(StructureGrowEvent event) { - if (!PlotSquared.get().hasPlotArea(event.getWorld().getName())) { - return; - } - List blocks = event.getBlocks(); - if (blocks.isEmpty()) { - return; - } - Location location = BukkitUtil.getLocation(blocks.get(0).getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - for (int i = blocks.size() - 1; i >= 0; i--) { - location = BukkitUtil.getLocation(blocks.get(i).getLocation()); - if (location.getPlotArea() != null) { - blocks.remove(i); - } - } - return; - } else { - Plot origin = area.getOwnedPlot(location); - if (origin == null) { - event.setCancelled(true); - return; - } - for (int i = blocks.size() - 1; i >= 0; i--) { - location = BukkitUtil.getLocation(blocks.get(i).getLocation()); - if (!area.contains(location.getX(), location.getZ())) { - blocks.remove(i); - continue; - } - Plot plot = area.getOwnedPlot(location); - if (!Objects.equals(plot, origin)) { - event.getBlocks().remove(i); - } - } - } - Plot origin = area.getPlot(location); - if (origin == null) { + Plot plot = area.getOwnedPlot(location); + BlockFace dir = event.getDirection(); + // Location head = location.add(-dir.getModX(), -dir.getModY(), -dir.getModZ()); + // + // if (!Objects.equals(plot, area.getOwnedPlot(head))) { + // // FIXME: cancelling the event doesn't work here. See issue #1484 + // event.setCancelled(true); + // return; + // } + if (this.pistonBlocks) { + try { + for (Block pulled : event.getBlocks()) { + Location from = BukkitUtil.getLocation( + pulled.getLocation().add(dir.getModX(), dir.getModY(), dir.getModZ())); + Location to = BukkitUtil.getLocation(pulled.getLocation()); + if (!area.contains(to.getX(), to.getZ())) { event.setCancelled(true); return; + } + Plot fromPlot = area.getOwnedPlot(from); + Plot toPlot = area.getOwnedPlot(to); + if (!Objects.equals(fromPlot, toPlot)) { + event.setCancelled(true); + return; + } } - for (int i = blocks.size() - 1; i >= 0; i--) { - location = BukkitUtil.getLocation(blocks.get(i).getLocation()); - Plot plot = area.getOwnedPlot(location); - /* - * plot -> the base plot of the merged area - * origin -> the plot where the event gets called - */ - - // Are plot and origin not the same AND are both plots merged - if (!Objects.equals(plot, origin) && (!plot.isMerged() && !origin.isMerged())) { - event.getBlocks().remove(i); - } - } + } catch (Throwable ignored) { + this.pistonBlocks = false; + } } + if (!this.pistonBlocks && !block.getType().toString().contains("PISTON")) { + location = BukkitUtil.getLocation( + block.getLocation().add(dir.getModX() * 2, dir.getModY() * 2, dir.getModZ() * 2)); + if (!area.contains(location)) { + event.setCancelled(true); + return; + } + Plot newPlot = area.getOwnedPlot(location); + if (!Objects.equals(plot, newPlot)) { + event.setCancelled(true); + } + } + } - @SuppressWarnings("deprecation") - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onInventoryClick(InventoryClickEvent event) { + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockDispense(BlockDispenseEvent event) { + Material type = event.getItem().getType(); + switch (type) { + case WATER_BUCKET: + case LAVA_BUCKET: { + if (event.getBlock().getType() == Material.DROPPER) { + return; + } + BlockFace targetFace = + ((Directional) event.getBlock().getState().getData()).getFacing(); + Location location = + BukkitUtil.getLocation(event.getBlock().getRelative(targetFace).getLocation()); + if (location.isPlotRoad()) { + event.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onStructureGrow(StructureGrowEvent event) { + if (!PlotSquared.get().hasPlotArea(event.getWorld().getName())) { + return; + } + List blocks = event.getBlocks(); + if (blocks.isEmpty()) { + return; + } + Location location = BukkitUtil.getLocation(blocks.get(0).getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + for (int i = blocks.size() - 1; i >= 0; i--) { + location = BukkitUtil.getLocation(blocks.get(i).getLocation()); + if (location.getPlotArea() != null) { + blocks.remove(i); + } + } + return; + } else { + Plot origin = area.getOwnedPlot(location); + if (origin == null) { + event.setCancelled(true); + return; + } + for (int i = blocks.size() - 1; i >= 0; i--) { + location = BukkitUtil.getLocation(blocks.get(i).getLocation()); + if (!area.contains(location.getX(), location.getZ())) { + blocks.remove(i); + continue; + } + Plot plot = area.getOwnedPlot(location); + if (!Objects.equals(plot, origin)) { + event.getBlocks().remove(i); + } + } + } + Plot origin = area.getPlot(location); + if (origin == null) { + event.setCancelled(true); + return; + } + for (int i = blocks.size() - 1; i >= 0; i--) { + location = BukkitUtil.getLocation(blocks.get(i).getLocation()); + Plot plot = area.getOwnedPlot(location); + /* + * plot -> the base plot of the merged area + * origin -> the plot where the event gets called + */ + + // Are plot and origin not the same AND are both plots merged + if (!Objects.equals(plot, origin) && (!plot.isMerged() && !origin.isMerged())) { + event.getBlocks().remove(i); + } + } + } + + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onInventoryClick(InventoryClickEvent event) { /*if (!event.isLeftClick() || (event.getAction() != InventoryAction.PLACE_ALL) || event .isShiftClick()) { return; }*/ - HumanEntity entity = event.getWhoClicked(); - if (!(entity instanceof Player) || !PlotSquared.get() - .hasPlotArea(entity.getWorld().getName())) { - return; - } + HumanEntity entity = event.getWhoClicked(); + if (!(entity instanceof Player) || !PlotSquared.get() + .hasPlotArea(entity.getWorld().getName())) { + return; + } - HumanEntity clicker = event.getWhoClicked(); - if (!(clicker instanceof Player)) { - return; + HumanEntity clicker = event.getWhoClicked(); + if (!(clicker instanceof Player)) { + return; + } + Player player = (Player) clicker; + PlotPlayer pp = BukkitUtil.getPlayer(player); + final PlotInventory inventory = PlotInventory.getOpenPlotInventory(pp); + if (inventory != null && event.getRawSlot() == event.getSlot()) { + if (!inventory.onClick(event.getSlot())) { + event.setResult(Event.Result.DENY); + event.setCancelled(true); + inventory.close(); + } + } + PlayerInventory inv = player.getInventory(); + int slot = inv.getHeldItemSlot(); + if ((slot > 8) || !event.getEventName().equals("InventoryCreativeEvent")) { + return; + } + ItemStack current = inv.getItemInHand(); + ItemStack newItem = event.getCursor(); + ItemMeta newMeta = newItem.getItemMeta(); + ItemMeta oldMeta = newItem.getItemMeta(); + String newLore = ""; + if (newMeta != null) { + List lore = newMeta.getLore(); + if (lore != null) { + newLore = lore.toString(); + } + } + String oldLore = ""; + if (oldMeta != null) { + List lore = oldMeta.getLore(); + if (lore != null) { + oldLore = lore.toString(); + } + } + if (!"[(+NBT)]".equals(newLore) || (current.equals(newItem) && newLore.equals(oldLore))) { + switch (newItem.getType()) { + case LEGACY_BANNER: + case PLAYER_HEAD: + if (newMeta != null) { + break; + } + default: + return; + } + } + Block block = player.getTargetBlock(null, 7); + BlockState state = block.getState(); + if (state == null) { + return; + } + Material stateType = state.getType(); + Material itemType = newItem.getType(); + if (stateType != itemType) { + switch (stateType) { + case LEGACY_STANDING_BANNER: + case LEGACY_WALL_BANNER: + if (itemType == Material.LEGACY_BANNER) { + break; + } + case LEGACY_SKULL: + if (itemType == Material.LEGACY_SKULL_ITEM) { + break; + } + default: + return; + } + } + Location l = BukkitUtil.getLocation(state.getLocation()); + PlotArea area = l.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getPlotAbs(l); + boolean cancelled = false; + if (plot == null) { + if (!Permissions.hasPermission(pp, "plots.admin.interact.road")) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.road"); + cancelled = true; + } + } else if (!plot.hasOwner()) { + if (!Permissions.hasPermission(pp, "plots.admin.interact.unowned")) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.unowned"); + cancelled = true; + } + } else { + UUID uuid = pp.getUUID(); + if (!plot.isAdded(uuid)) { + if (!Permissions.hasPermission(pp, "plots.admin.interact.other")) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.other"); + cancelled = true; } - Player player = (Player) clicker; - PlotPlayer pp = BukkitUtil.getPlayer(player); - final PlotInventory inventory = PlotInventory.getOpenPlotInventory(pp); - if (inventory != null && event.getRawSlot() == event.getSlot()) { - if (!inventory.onClick(event.getSlot())) { - event.setResult(Event.Result.DENY); - event.setCancelled(true); - inventory.close(); + } + } + if (cancelled) { + if ((current.getType() == newItem.getType()) && (current.getDurability() == newItem + .getDurability())) { + event.setCursor( + new ItemStack(newItem.getType(), newItem.getAmount(), newItem.getDurability())); + event.setCancelled(true); + return; + } + event.setCursor( + new ItemStack(newItem.getType(), newItem.getAmount(), newItem.getDurability())); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPotionSplash(LingeringPotionSplashEvent event) { + LingeringPotion entity = event.getEntity(); + Location l = BukkitUtil.getLocation(entity); + if (!PlotSquared.get().hasPlotArea(l.getWorld())) { + return; + } + if (!this.onProjectileHit(event)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onInteract(PlayerInteractAtEntityEvent e) { + Entity entity = e.getRightClicked(); + if (!(entity instanceof ArmorStand)) { + return; + } + Location l = BukkitUtil.getLocation(e.getRightClicked().getLocation()); + PlotArea area = l.getPlotArea(); + if (area == null) { + return; + } + + EntitySpawnListener.test(entity); + + Plot plot = area.getPlotAbs(l); + PlotPlayer pp = BukkitUtil.getPlayer(e.getPlayer()); + if (plot == null) { + if (!Permissions.hasPermission(pp, "plots.admin.interact.road")) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.road"); + e.setCancelled(true); + } + } else if (!plot.hasOwner()) { + if (!Permissions.hasPermission(pp, "plots.admin.interact.unowned")) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.unowned"); + e.setCancelled(true); + } + } else { + UUID uuid = pp.getUUID(); + if (!plot.isAdded(uuid)) { + if (Flags.MISC_INTERACT.isTrue(plot)) { + return; + } + if (!Permissions.hasPermission(pp, "plots.admin.interact.other")) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.other"); + e.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBigBoom(BlockExplodeEvent event) { + Block block = event.getBlock(); + Location location = BukkitUtil.getLocation(block.getLocation()); + String world = location.getWorld(); + if (!PlotSquared.get().hasPlotArea(world)) { + return; + } + PlotArea area = location.getPlotArea(); + if (area == null) { + Iterator iterator = event.blockList().iterator(); + while (iterator.hasNext()) { + location = BukkitUtil.getLocation(iterator.next().getLocation()); + if (location.getPlotArea() != null) { + iterator.remove(); + } + } + return; + } + Plot plot = area.getOwnedPlot(location); + if (plot == null || !plot.getFlag(Flags.EXPLOSION).orElse(false)) { + event.setCancelled(true); + } + event.blockList().removeIf( + b -> !plot.equals(area.getOwnedPlot(BukkitUtil.getLocation(b.getLocation())))); + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + PlotArea area = pp.getPlotAreaAbs(); + if (area == null) { + return; + } + PlayerBlockEventType eventType = null; + BukkitLazyBlock lb; + Location location; + Action action = event.getAction(); + switch (action) { + case PHYSICAL: { + eventType = PlayerBlockEventType.TRIGGER_PHYSICAL; + Block block = event.getClickedBlock(); + lb = new BukkitLazyBlock(block); + location = BukkitUtil.getLocation(block.getLocation()); + break; + } + case RIGHT_CLICK_BLOCK: { + Block block = event.getClickedBlock(); + location = BukkitUtil.getLocation(block.getLocation()); + Material blockType = block.getType(); + switch (blockType) { + case ACACIA_DOOR: + case BIRCH_DOOR: + case DARK_OAK_DOOR: + case IRON_DOOR: + case JUNGLE_DOOR: + case OAK_DOOR: + case SPRUCE_DOOR: + + case ACACIA_TRAPDOOR: + case BIRCH_TRAPDOOR: + case DARK_OAK_TRAPDOOR: + case IRON_TRAPDOOR: + case JUNGLE_TRAPDOOR: + case OAK_TRAPDOOR: + case SPRUCE_TRAPDOOR: + + case CHEST: + case ENDER_CHEST: + case TRAPPED_CHEST: + + case ACACIA_FENCE_GATE: + case BIRCH_FENCE_GATE: + case DARK_OAK_FENCE_GATE: + case OAK_FENCE_GATE: + case JUNGLE_FENCE_GATE: + case SPRUCE_FENCE_GATE: + + case ACACIA_BUTTON: + case BIRCH_BUTTON: + case DARK_OAK_BUTTON: + case JUNGLE_BUTTON: + case OAK_BUTTON: + case SPRUCE_BUTTON: + case STONE_BUTTON: + + case BLACK_BED: + case BLUE_BED: + case BROWN_BED: + case CYAN_BED: + case GRAY_BED: + case GREEN_BED: + case LIGHT_BLUE_BED: + case LIGHT_GRAY_BED: + case LIME_BED: + case MAGENTA_BED: + case ORANGE_BED: + case PINK_BED: + case PURPLE_BED: + case RED_BED: + case WHITE_BED: + case YELLOW_BED: + + case BLACK_BANNER: + case BLACK_WALL_BANNER: + case BLUE_BANNER: + case BLUE_WALL_BANNER: + case BROWN_BANNER: + case BROWN_WALL_BANNER: + case CYAN_BANNER: + case CYAN_WALL_BANNER: + case GRAY_BANNER: + case GRAY_WALL_BANNER: + case GREEN_BANNER: + case GREEN_WALL_BANNER: + case LIGHT_BLUE_BANNER: + case LIGHT_BLUE_WALL_BANNER: + case LIGHT_GRAY_BANNER: + case LIGHT_GRAY_WALL_BANNER: + case LIME_BANNER: + case LIME_WALL_BANNER: + case MAGENTA_BANNER: + case MAGENTA_WALL_BANNER: + case ORANGE_BANNER: + case ORANGE_WALL_BANNER: + case PINK_BANNER: + case PINK_WALL_BANNER: + case PURPLE_BANNER: + case PURPLE_WALL_BANNER: + case RED_BANNER: + case RED_WALL_BANNER: + case WHITE_BANNER: + case WHITE_WALL_BANNER: + case YELLOW_BANNER: + case YELLOW_WALL_BANNER: + + case BLACK_SHULKER_BOX: + case BLUE_SHULKER_BOX: + case BROWN_SHULKER_BOX: + case CYAN_SHULKER_BOX: + case GRAY_SHULKER_BOX: + case GREEN_SHULKER_BOX: + case LIGHT_BLUE_SHULKER_BOX: + case LIGHT_GRAY_SHULKER_BOX: + case LIME_SHULKER_BOX: + case MAGENTA_SHULKER_BOX: + case ORANGE_SHULKER_BOX: + case PINK_SHULKER_BOX: + case PURPLE_SHULKER_BOX: + case RED_SHULKER_BOX: + case WHITE_SHULKER_BOX: + case YELLOW_SHULKER_BOX: + + case CHAIN_COMMAND_BLOCK: + case REPEATING_COMMAND_BLOCK: + + case SIGN: + case WALL_SIGN: + + case REDSTONE_TORCH: + case REDSTONE_WALL_TORCH: + + case TURTLE_EGG: + case TURTLE_HELMET: + case TURTLE_SPAWN_EGG: + + case ANVIL: + case BEACON: + case BREWING_STAND: + case CAKE: + case COMMAND_BLOCK: + case COMPARATOR: + case CRAFTING_TABLE: + case DISPENSER: + case DROPPER: + case ENCHANTING_TABLE: + case FURNACE: + case HOPPER: + case JUKEBOX: + case LEVER: + case NOTE_BLOCK: + case REDSTONE_ORE: + eventType = PlayerBlockEventType.INTERACT_BLOCK; + break; + case DRAGON_EGG: + eventType = PlayerBlockEventType.TELEPORT_OBJECT; + break; + default: + int blockId = ((LegacyPlotBlock) PlotSquared.get().IMP.getLegacyMappings() + .fromStringToLegacy(blockType.name())).id; + if (blockId > 197) { + eventType = PlayerBlockEventType.INTERACT_BLOCK; } + break; } - PlayerInventory inv = player.getInventory(); - int slot = inv.getHeldItemSlot(); - if ((slot > 8) || !event.getEventName().equals("InventoryCreativeEvent")) { - return; + lb = new BukkitLazyBlock(PlotBlock.get(block.getType().toString())); + ItemStack hand = player.getInventory().getItemInMainHand(); + if (eventType != null && (eventType != PlayerBlockEventType.INTERACT_BLOCK + || !player.isSneaking())) { + break; } - ItemStack current = inv.getItemInHand(); - ItemStack newItem = event.getCursor(); - ItemMeta newMeta = newItem.getItemMeta(); - ItemMeta oldMeta = newItem.getItemMeta(); - String newLore = ""; - if (newMeta != null) { - List lore = newMeta.getLore(); - if (lore != null) { - newLore = lore.toString(); - } + Material type = (hand == null) ? null : hand.getType(); + if (type == Material.AIR) { + eventType = PlayerBlockEventType.INTERACT_BLOCK; + break; } - String oldLore = ""; - if (oldMeta != null) { - List lore = oldMeta.getLore(); - if (lore != null) { - oldLore = lore.toString(); - } + if (type == null || type.isBlock()) { + location = BukkitUtil + .getLocation(block.getRelative(event.getBlockFace()).getLocation()); + eventType = PlayerBlockEventType.PLACE_BLOCK; + break; } - if (!"[(+NBT)]".equals(newLore) || (current.equals(newItem) && newLore.equals(oldLore))) { - switch (newItem.getType()) { - case LEGACY_BANNER: - case PLAYER_HEAD: - if (newMeta != null) - break; - default: - return; - } - } - Block block = player.getTargetBlock(null, 7); - BlockState state = block.getState(); - if (state == null) { - return; - } - Material stateType = state.getType(); - Material itemType = newItem.getType(); - if (stateType != itemType) { - switch (stateType) { - case LEGACY_STANDING_BANNER: - case LEGACY_WALL_BANNER: - if (itemType == Material.LEGACY_BANNER) - break; - case LEGACY_SKULL: - if (itemType == Material.LEGACY_SKULL_ITEM) - break; - default: - return; - } - } - Location l = BukkitUtil.getLocation(state.getLocation()); - PlotArea area = l.getPlotArea(); - if (area == null) { - return; - } - Plot plot = area.getPlotAbs(l); - boolean cancelled = false; - if (plot == null) { - if (!Permissions.hasPermission(pp, "plots.admin.interact.road")) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.road"); - cancelled = true; - } - } else if (!plot.hasOwner()) { - if (!Permissions.hasPermission(pp, "plots.admin.interact.unowned")) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.unowned"); - cancelled = true; - } + Material handType = hand.getType(); + lb = new BukkitLazyBlock(PlotBlock.get(handType.toString())); + if (handType.toString().endsWith("egg")) { + eventType = PlayerBlockEventType.SPAWN_MOB; } else { - UUID uuid = pp.getUUID(); - if (!plot.isAdded(uuid)) { - if (!Permissions.hasPermission(pp, "plots.admin.interact.other")) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.other"); - cancelled = true; - } - } - } - if (cancelled) { - if ((current.getType() == newItem.getType()) && (current.getDurability() == newItem - .getDurability())) { - event.setCursor( - new ItemStack(newItem.getType(), newItem.getAmount(), newItem.getDurability())); - event.setCancelled(true); - return; - } - event.setCursor( - new ItemStack(newItem.getType(), newItem.getAmount(), newItem.getDurability())); - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPotionSplash(LingeringPotionSplashEvent event) { - LingeringPotion entity = event.getEntity(); - Location l = BukkitUtil.getLocation(entity); - if (!PlotSquared.get().hasPlotArea(l.getWorld())) { - return; - } - if (!this.onProjectileHit(event)) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onInteract(PlayerInteractAtEntityEvent e) { - Entity entity = e.getRightClicked(); - if (!(entity instanceof ArmorStand)) { - return; - } - Location l = BukkitUtil.getLocation(e.getRightClicked().getLocation()); - PlotArea area = l.getPlotArea(); - if (area == null) { - return; - } - - EntitySpawnListener.test(entity); - - Plot plot = area.getPlotAbs(l); - PlotPlayer pp = BukkitUtil.getPlayer(e.getPlayer()); - if (plot == null) { - if (!Permissions.hasPermission(pp, "plots.admin.interact.road")) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.road"); - e.setCancelled(true); - } - } else if (!plot.hasOwner()) { - if (!Permissions.hasPermission(pp, "plots.admin.interact.unowned")) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.unowned"); - e.setCancelled(true); - } - } else { - UUID uuid = pp.getUUID(); - if (!plot.isAdded(uuid)) { - if (Flags.MISC_INTERACT.isTrue(plot)) { - return; - } - if (!Permissions.hasPermission(pp, "plots.admin.interact.other")) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.other"); - e.setCancelled(true); - } - } - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBigBoom(BlockExplodeEvent event) { - Block block = event.getBlock(); - Location location = BukkitUtil.getLocation(block.getLocation()); - String world = location.getWorld(); - if (!PlotSquared.get().hasPlotArea(world)) { - return; - } - PlotArea area = location.getPlotArea(); - if (area == null) { - Iterator iterator = event.blockList().iterator(); - while (iterator.hasNext()) { - location = BukkitUtil.getLocation(iterator.next().getLocation()); - if (location.getPlotArea() != null) { - iterator.remove(); - } - } - return; - } - Plot plot = area.getOwnedPlot(location); - if (plot == null || !plot.getFlag(Flags.EXPLOSION).orElse(false)) { - event.setCancelled(true); - } - event.blockList().removeIf( - b -> !plot.equals(area.getOwnedPlot(BukkitUtil.getLocation(b.getLocation())))); - } - - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onInteract(PlayerInteractEvent event) { - Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); - PlotArea area = pp.getPlotAreaAbs(); - if (area == null) { - return; - } - PlayerBlockEventType eventType = null; - BukkitLazyBlock lb; - Location location; - Action action = event.getAction(); - switch (action) { - case PHYSICAL: { - eventType = PlayerBlockEventType.TRIGGER_PHYSICAL; - Block block = event.getClickedBlock(); - lb = new BukkitLazyBlock(block); - location = BukkitUtil.getLocation(block.getLocation()); - break; - } - case RIGHT_CLICK_BLOCK: { - Block block = event.getClickedBlock(); - location = BukkitUtil.getLocation(block.getLocation()); - Material blockType = block.getType(); - switch (blockType) { - case ACACIA_DOOR: - case BIRCH_DOOR: - case DARK_OAK_DOOR: - case IRON_DOOR: - case JUNGLE_DOOR: - case OAK_DOOR: - case SPRUCE_DOOR: - - case ACACIA_TRAPDOOR: - case BIRCH_TRAPDOOR: - case DARK_OAK_TRAPDOOR: - case IRON_TRAPDOOR: - case JUNGLE_TRAPDOOR: - case OAK_TRAPDOOR: - case SPRUCE_TRAPDOOR: - - case CHEST: - case ENDER_CHEST: - case TRAPPED_CHEST: - - case ACACIA_FENCE_GATE: - case BIRCH_FENCE_GATE: - case DARK_OAK_FENCE_GATE: - case OAK_FENCE_GATE: - case JUNGLE_FENCE_GATE: - case SPRUCE_FENCE_GATE: - - case ACACIA_BUTTON: - case BIRCH_BUTTON: - case DARK_OAK_BUTTON: - case JUNGLE_BUTTON: - case OAK_BUTTON: - case SPRUCE_BUTTON: - case STONE_BUTTON: - - case BLACK_BED: - case BLUE_BED: - case BROWN_BED: - case CYAN_BED: - case GRAY_BED: - case GREEN_BED: - case LIGHT_BLUE_BED: - case LIGHT_GRAY_BED: - case LIME_BED: - case MAGENTA_BED: - case ORANGE_BED: - case PINK_BED: - case PURPLE_BED: - case RED_BED: - case WHITE_BED: - case YELLOW_BED: - - case BLACK_BANNER: - case BLACK_WALL_BANNER: - case BLUE_BANNER: - case BLUE_WALL_BANNER: - case BROWN_BANNER: - case BROWN_WALL_BANNER: - case CYAN_BANNER: - case CYAN_WALL_BANNER: - case GRAY_BANNER: - case GRAY_WALL_BANNER: - case GREEN_BANNER: - case GREEN_WALL_BANNER: - case LIGHT_BLUE_BANNER: - case LIGHT_BLUE_WALL_BANNER: - case LIGHT_GRAY_BANNER: - case LIGHT_GRAY_WALL_BANNER: - case LIME_BANNER: - case LIME_WALL_BANNER: - case MAGENTA_BANNER: - case MAGENTA_WALL_BANNER: - case ORANGE_BANNER: - case ORANGE_WALL_BANNER: - case PINK_BANNER: - case PINK_WALL_BANNER: - case PURPLE_BANNER: - case PURPLE_WALL_BANNER: - case RED_BANNER: - case RED_WALL_BANNER: - case WHITE_BANNER: - case WHITE_WALL_BANNER: - case YELLOW_BANNER: - case YELLOW_WALL_BANNER: - - case BLACK_SHULKER_BOX: - case BLUE_SHULKER_BOX: - case BROWN_SHULKER_BOX: - case CYAN_SHULKER_BOX: - case GRAY_SHULKER_BOX: - case GREEN_SHULKER_BOX: - case LIGHT_BLUE_SHULKER_BOX: - case LIGHT_GRAY_SHULKER_BOX: - case LIME_SHULKER_BOX: - case MAGENTA_SHULKER_BOX: - case ORANGE_SHULKER_BOX: - case PINK_SHULKER_BOX: - case PURPLE_SHULKER_BOX: - case RED_SHULKER_BOX: - case WHITE_SHULKER_BOX: - case YELLOW_SHULKER_BOX: - - case CHAIN_COMMAND_BLOCK: - case REPEATING_COMMAND_BLOCK: - - case SIGN: - case WALL_SIGN: - - case REDSTONE_TORCH: - case REDSTONE_WALL_TORCH: - - case TURTLE_EGG: - case TURTLE_HELMET: - case TURTLE_SPAWN_EGG: - - case ANVIL: - case BEACON: - case BREWING_STAND: - case CAKE: - case COMMAND_BLOCK: - case COMPARATOR: - case CRAFTING_TABLE: - case DISPENSER: - case DROPPER: - case ENCHANTING_TABLE: - case FURNACE: - case HOPPER: - case JUKEBOX: - case LEVER: - case NOTE_BLOCK: - case REDSTONE_ORE: - eventType = PlayerBlockEventType.INTERACT_BLOCK; - break; - case DRAGON_EGG: - eventType = PlayerBlockEventType.TELEPORT_OBJECT; - break; - default: - int blockId = ((LegacyPlotBlock) PlotSquared.get().IMP.getLegacyMappings() - .fromStringToLegacy(blockType.name())).id; - if (blockId > 197) { - eventType = PlayerBlockEventType.INTERACT_BLOCK; - } - break; - } - lb = new BukkitLazyBlock(PlotBlock.get(block.getType().toString())); - ItemStack hand = player.getInventory().getItemInMainHand(); - if (eventType != null && (eventType != PlayerBlockEventType.INTERACT_BLOCK - || !player.isSneaking())) { - break; - } - Material type = (hand == null) ? null : hand.getType(); - if (type == Material.AIR) { - eventType = PlayerBlockEventType.INTERACT_BLOCK; - break; - } - if (type == null || type.isBlock()) { - location = BukkitUtil - .getLocation(block.getRelative(event.getBlockFace()).getLocation()); - eventType = PlayerBlockEventType.PLACE_BLOCK; - break; - } - Material handType = hand.getType(); - lb = new BukkitLazyBlock(PlotBlock.get(handType.toString())); - if (handType.toString().endsWith("egg")) { - eventType = PlayerBlockEventType.SPAWN_MOB; - } else { - switch (handType) { - case FIREWORK_ROCKET: - case FIREWORK_STAR: - eventType = PlayerBlockEventType.SPAWN_MOB; - break; - case ARMOR_STAND: - location = BukkitUtil - .getLocation(block.getRelative(event.getBlockFace()).getLocation()); - eventType = PlayerBlockEventType.PLACE_MISC; - break; - case BOOK: - case ENCHANTED_BOOK: - case KNOWLEDGE_BOOK: - case WRITABLE_BOOK: - case WRITTEN_BOOK: - eventType = PlayerBlockEventType.READ; - break; - case APPLE: - case BAKED_POTATO: - case BEEF: - case BREAD: - case CARROT: - case CHICKEN: - case COD: - case COOKED_BEEF: - case COOKED_CHICKEN: - case COOKED_COD: - case COOKED_MUTTON: - case COOKED_PORKCHOP: - case COOKED_RABBIT: - case COOKED_SALMON: - case COOKIE: - case GOLDEN_CARROT: - case MUSHROOM_STEW: - case MUTTON: - case POISONOUS_POTATO: - case PORKCHOP: - case POTATO: - case POTION: - case PUFFERFISH: - case PUMPKIN_PIE: - case RABBIT: - case RABBIT_FOOT: - case RABBIT_STEW: - case SALMON: - case TROPICAL_FISH: - eventType = PlayerBlockEventType.EAT; - break; - case ACACIA_BOAT: - case BIRCH_BOAT: - case CHEST_MINECART: - case COMMAND_BLOCK_MINECART: - case DARK_OAK_BOAT: - case FURNACE_MINECART: - case HOPPER_MINECART: - case JUNGLE_BOAT: - case MINECART: - case OAK_BOAT: - case SPRUCE_BOAT: - case TNT_MINECART: - eventType = PlayerBlockEventType.PLACE_VEHICLE; - break; - case ITEM_FRAME: - case PAINTING: - location = BukkitUtil - .getLocation(block.getRelative(event.getBlockFace()).getLocation()); - eventType = PlayerBlockEventType.PLACE_HANGING; - break; - default: - eventType = PlayerBlockEventType.INTERACT_BLOCK; - break; - } - } - break; - } - case LEFT_CLICK_BLOCK: - Block block = event.getClickedBlock(); - location = BukkitUtil.getLocation(block.getLocation()); - eventType = PlayerBlockEventType.BREAK_BLOCK; - lb = new BukkitLazyBlock(block); - break; + switch (handType) { + case FIREWORK_ROCKET: + case FIREWORK_STAR: + eventType = PlayerBlockEventType.SPAWN_MOB; + break; + case ARMOR_STAND: + location = BukkitUtil + .getLocation(block.getRelative(event.getBlockFace()).getLocation()); + eventType = PlayerBlockEventType.PLACE_MISC; + break; + case BOOK: + case ENCHANTED_BOOK: + case KNOWLEDGE_BOOK: + case WRITABLE_BOOK: + case WRITTEN_BOOK: + eventType = PlayerBlockEventType.READ; + break; + case APPLE: + case BAKED_POTATO: + case BEEF: + case BREAD: + case CARROT: + case CHICKEN: + case COD: + case COOKED_BEEF: + case COOKED_CHICKEN: + case COOKED_COD: + case COOKED_MUTTON: + case COOKED_PORKCHOP: + case COOKED_RABBIT: + case COOKED_SALMON: + case COOKIE: + case GOLDEN_CARROT: + case MUSHROOM_STEW: + case MUTTON: + case POISONOUS_POTATO: + case PORKCHOP: + case POTATO: + case POTION: + case PUFFERFISH: + case PUMPKIN_PIE: + case RABBIT: + case RABBIT_FOOT: + case RABBIT_STEW: + case SALMON: + case TROPICAL_FISH: + eventType = PlayerBlockEventType.EAT; + break; + case ACACIA_BOAT: + case BIRCH_BOAT: + case CHEST_MINECART: + case COMMAND_BLOCK_MINECART: + case DARK_OAK_BOAT: + case FURNACE_MINECART: + case HOPPER_MINECART: + case JUNGLE_BOAT: + case MINECART: + case OAK_BOAT: + case SPRUCE_BOAT: + case TNT_MINECART: + eventType = PlayerBlockEventType.PLACE_VEHICLE; + break; + case ITEM_FRAME: + case PAINTING: + location = BukkitUtil + .getLocation(block.getRelative(event.getBlockFace()).getLocation()); + eventType = PlayerBlockEventType.PLACE_HANGING; + break; default: - return; + eventType = PlayerBlockEventType.INTERACT_BLOCK; + break; + } } - if (PlotSquared.get().worldedit != null && pp.getAttribute("worldedit")) { - if (player.getInventory().getItemInMainHand().getType() == Material - .getMaterial(PlotSquared.get().worldedit.getConfiguration().wandItem)) { - return; - } + break; + } + case LEFT_CLICK_BLOCK: + Block block = event.getClickedBlock(); + location = BukkitUtil.getLocation(block.getLocation()); + eventType = PlayerBlockEventType.BREAK_BLOCK; + lb = new BukkitLazyBlock(block); + break; + default: + return; + } + if (PlotSquared.get().worldedit != null && pp.getAttribute("worldedit")) { + if (player.getInventory().getItemInMainHand().getType() == Material + .getMaterial(PlotSquared.get().worldedit.getConfiguration().wandItem)) { + return; + } + } + if (!EventUtil.manager.checkPlayerBlockEvent(pp, eventType, location, lb, true)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void creatureSpawnEvent(CreatureSpawnEvent event) { + Entity entity = event.getEntity(); + Location location = BukkitUtil.getLocation(entity.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + CreatureSpawnEvent.SpawnReason reason = event.getSpawnReason(); + //TODO needs an overhaul for the increased number of spawn reasons added to this event. + //I can't believe they waited so damn long to expand this API set. + switch (reason) { + case DISPENSE_EGG: + case EGG: + case OCELOT_BABY: + case SPAWNER_EGG: + if (!area.SPAWN_EGGS) { + event.setCancelled(true); + return; } - if (!EventUtil.manager.checkPlayerBlockEvent(pp, eventType, location, lb, true)) { - event.setCancelled(true); + break; + case REINFORCEMENTS: + case NATURAL: + case CHUNK_GEN: + if (!area.MOB_SPAWNING) { + event.setCancelled(true); + return; } + case BREEDING: + if (!area.SPAWN_BREEDING) { + event.setCancelled(true); + return; + } + break; + case BUILD_IRONGOLEM: + case BUILD_SNOWMAN: + case BUILD_WITHER: + case CUSTOM: + if (!area.SPAWN_CUSTOM && entity.getType() != EntityType.ARMOR_STAND) { + event.setCancelled(true); + return; + } + break; + case SPAWNER: + if (!area.MOB_SPAWNER_SPAWNING) { + event.setCancelled(true); + return; + } + break; + } + Plot plot = area.getOwnedPlotAbs(location); + if (plot == null) { + if (!area.MOB_SPAWNING) { + event.setCancelled(true); + } + return; + } + if (checkEntity(entity, plot)) { + event.setCancelled(true); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onEntityFall(EntityChangeBlockEvent event) { + if (event.getEntityType() != EntityType.FALLING_BLOCK) { + return; + } + Block block = event.getBlock(); + World world = block.getWorld(); + String worldName = world.getName(); + if (!PlotSquared.get().hasPlotArea(worldName)) { + return; + } + Location location = BukkitUtil.getLocation(block.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlotAbs(location); + if (plot == null || plot.getFlag(Flags.DISABLE_PHYSICS, false)) { + event.setCancelled(true); + return; + } + if (event.getTo().hasGravity()) { + Entity entity = event.getEntity(); + List meta = entity.getMetadata("plot"); + if (meta.isEmpty()) { + return; + } + Plot origin = (Plot) meta.get(0).value(); + if (origin != null && !origin.equals(plot)) { + event.setCancelled(true); + entity.remove(); + } + } else if (event.getTo() == Material.AIR) { + event.getEntity() + .setMetadata("plot", new FixedMetadataValue((Plugin) PlotSquared.get().IMP, plot)); + } + } + + @EventHandler + public void onPrime(ExplosionPrimeEvent event) { + this.lastRadius = event.getRadius() + 1; + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockBurn(BlockBurnEvent event) { + Block b = event.getBlock(); + Location location = BukkitUtil.getLocation(b.getLocation()); + + PlotArea area = location.getPlotArea(); + if (area == null) { + return; } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void creatureSpawnEvent(CreatureSpawnEvent event) { - Entity entity = event.getEntity(); - Location location = BukkitUtil.getLocation(entity.getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - CreatureSpawnEvent.SpawnReason reason = event.getSpawnReason(); - //TODO needs an overhaul for the increased number of spawn reasons added to this event. - //I can't believe they waited so damn long to expand this API set. - switch (reason) { - case DISPENSE_EGG: - case EGG: - case OCELOT_BABY: - case SPAWNER_EGG: - if (!area.SPAWN_EGGS) { - event.setCancelled(true); - return; - } - break; - case REINFORCEMENTS: - case NATURAL: - case CHUNK_GEN: - if (!area.MOB_SPAWNING) { - event.setCancelled(true); - return; - } - case BREEDING: - if (!area.SPAWN_BREEDING) { - event.setCancelled(true); - return; - } - break; - case BUILD_IRONGOLEM: - case BUILD_SNOWMAN: - case BUILD_WITHER: - case CUSTOM: - if (!area.SPAWN_CUSTOM && entity.getType() != EntityType.ARMOR_STAND) { - event.setCancelled(true); - return; - } - break; - case SPAWNER: - if (!area.MOB_SPAWNER_SPAWNING) { - event.setCancelled(true); - return; - } - break; - } - Plot plot = area.getOwnedPlotAbs(location); - if (plot == null) { - if (!area.MOB_SPAWNING) { - event.setCancelled(true); - } - return; - } - if (checkEntity(entity, plot)) { - event.setCancelled(true); - } + Plot plot = location.getOwnedPlot(); + if (plot == null || !plot.getFlag(Flags.BLOCK_BURN, false)) { + event.setCancelled(true); + return; } - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void onEntityFall(EntityChangeBlockEvent event) { - if (event.getEntityType() != EntityType.FALLING_BLOCK) { - return; - } - Block block = event.getBlock(); - World world = block.getWorld(); - String worldName = world.getName(); - if (!PlotSquared.get().hasPlotArea(worldName)) { - return; - } - Location location = BukkitUtil.getLocation(block.getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - Plot plot = area.getOwnedPlotAbs(location); - if (plot == null || plot.getFlag(Flags.DISABLE_PHYSICS, false)) { - event.setCancelled(true); - return; - } - if (event.getTo().hasGravity()) { - Entity entity = event.getEntity(); - List meta = entity.getMetadata("plot"); - if (meta.isEmpty()) { - return; - } - Plot origin = (Plot) meta.get(0).value(); - if (origin != null && !origin.equals(plot)) { - event.setCancelled(true); - entity.remove(); - } - } else if (event.getTo() == Material.AIR) { - event.getEntity() - .setMetadata("plot", new FixedMetadataValue((Plugin) PlotSquared.get().IMP, plot)); - } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockIgnite(BlockIgniteEvent event) { + Player player = event.getPlayer(); + Entity ignitingEntity = event.getIgnitingEntity(); + Block block = event.getBlock(); + BlockIgniteEvent.IgniteCause igniteCause = event.getCause(); + Location loc; + if (block != null) { + loc = BukkitUtil.getLocation(block.getLocation()); + } else if (ignitingEntity != null) { + loc = BukkitUtil.getLocation(ignitingEntity); + } else if (player != null) { + loc = BukkitUtil.getLocation(player); + } else { + return; + } + PlotArea area = loc.getPlotArea(); + if (area == null) { + return; + } + if (igniteCause == BlockIgniteEvent.IgniteCause.LIGHTNING) { + event.setCancelled(true); + return; } - @EventHandler public void onPrime(ExplosionPrimeEvent event) { - this.lastRadius = event.getRadius() + 1; + Plot plot = area.getOwnedPlotAbs(loc); + if (player != null) { + PlotPlayer pp = BukkitUtil.getPlayer(player); + if (plot == null) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_ROAD)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); + event.setCancelled(true); + } + } else if (!plot.hasOwner()) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { + MainUtil + .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); + event.setCancelled(true); + } + } else if (!plot.isAdded(pp.getUUID())) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + } + } else if (Flags.BLOCK_IGNITION.isFalse(plot)) { + event.setCancelled(true); + } + } else { + if (plot == null) { + event.setCancelled(true); + return; + } + if (ignitingEntity != null) { + if (!plot.getFlag(Flags.BLOCK_IGNITION, false)) { + event.setCancelled(true); + return; + } + if (igniteCause == BlockIgniteEvent.IgniteCause.FIREBALL) { + if (ignitingEntity instanceof Fireball) { + Projectile fireball = (Projectile) ignitingEntity; + Location location = null; + if (fireball.getShooter() instanceof Entity) { + Entity shooter = (Entity) fireball.getShooter(); + location = BukkitUtil.getLocation(shooter.getLocation()); + } else if (fireball.getShooter() instanceof BlockProjectileSource) { + Block shooter = + ((BlockProjectileSource) fireball.getShooter()).getBlock(); + location = BukkitUtil.getLocation(shooter.getLocation()); + } + if (location != null && !plot.equals(location.getPlot())) { + event.setCancelled(true); + } + } + } + + } else if (event.getIgnitingBlock() != null) { + Block ignitingBlock = event.getIgnitingBlock(); + Plot plotIgnited = BukkitUtil.getLocation(ignitingBlock.getLocation()).getPlot(); + if (igniteCause == BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL && ( + !plot.getFlag(Flags.BLOCK_IGNITION, false) || plotIgnited == null + || !plotIgnited.equals(plot)) || + (igniteCause == BlockIgniteEvent.IgniteCause.SPREAD + || igniteCause == BlockIgniteEvent.IgniteCause.LAVA) && ( + !plot.getFlag(Flags.BLOCK_IGNITION).orElse(false) || plotIgnited == null + || !plotIgnited.equals(plot))) { + event.setCancelled(true); + } + } } + } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBlockBurn(BlockBurnEvent event) { - Block b = event.getBlock(); - Location location = BukkitUtil.getLocation(b.getLocation()); - - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - - Plot plot = location.getOwnedPlot(); - if (plot == null || !plot.getFlag(Flags.BLOCK_BURN, false)) { - event.setCancelled(true); - return; - } - + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBucketEmpty(PlayerBucketEmptyEvent event) { + BlockFace bf = event.getBlockFace(); + Block b = + event.getBlockClicked().getLocation().add(bf.getModX(), bf.getModY(), bf.getModZ()) + .getBlock(); + Location location = BukkitUtil.getLocation(b.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBlockIgnite(BlockIgniteEvent event) { - Player player = event.getPlayer(); - Entity ignitingEntity = event.getIgnitingEntity(); - Block block = event.getBlock(); - BlockIgniteEvent.IgniteCause igniteCause = event.getCause(); - Location loc; - if (block != null) { - loc = BukkitUtil.getLocation(block.getLocation()); - } else if (ignitingEntity != null) { - loc = BukkitUtil.getLocation(ignitingEntity); - } else if (player != null) { - loc = BukkitUtil.getLocation(player); - } else { - return; - } - PlotArea area = loc.getPlotArea(); - if (area == null) { - return; - } - if (igniteCause == BlockIgniteEvent.IgniteCause.LIGHTNING) { - event.setCancelled(true); - return; - } - - Plot plot = area.getOwnedPlotAbs(loc); - if (player != null) { - PlotPlayer pp = BukkitUtil.getPlayer(player); - if (plot == null) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_ROAD)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); - event.setCancelled(true); - } - } else if (!plot.hasOwner()) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { - MainUtil - .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); - event.setCancelled(true); - } - } else if (!plot.isAdded(pp.getUUID())) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); - event.setCancelled(true); - } - } else if (Flags.BLOCK_IGNITION.isFalse(plot)) { - event.setCancelled(true); - } - } else { - if (plot == null) { - event.setCancelled(true); - return; - } - if (ignitingEntity != null) { - if (!plot.getFlag(Flags.BLOCK_IGNITION, false)) { - event.setCancelled(true); - return; - } - if (igniteCause == BlockIgniteEvent.IgniteCause.FIREBALL) { - if (ignitingEntity instanceof Fireball) { - Projectile fireball = (Projectile) ignitingEntity; - Location location = null; - if (fireball.getShooter() instanceof Entity) { - Entity shooter = (Entity) fireball.getShooter(); - location = BukkitUtil.getLocation(shooter.getLocation()); - } else if (fireball.getShooter() instanceof BlockProjectileSource) { - Block shooter = - ((BlockProjectileSource) fireball.getShooter()).getBlock(); - location = BukkitUtil.getLocation(shooter.getLocation()); - } - if (location != null && !plot.equals(location.getPlot())) { - event.setCancelled(true); - } - } - } - - } else if (event.getIgnitingBlock() != null) { - Block ignitingBlock = event.getIgnitingBlock(); - Plot plotIgnited = BukkitUtil.getLocation(ignitingBlock.getLocation()).getPlot(); - if (igniteCause == BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL && ( - !plot.getFlag(Flags.BLOCK_IGNITION, false) || plotIgnited == null - || !plotIgnited.equals(plot)) || - (igniteCause == BlockIgniteEvent.IgniteCause.SPREAD - || igniteCause == BlockIgniteEvent.IgniteCause.LAVA) && ( - !plot.getFlag(Flags.BLOCK_IGNITION).orElse(false) || plotIgnited == null - || !plotIgnited.equals(plot))) { - event.setCancelled(true); - } - } - } + PlotPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); + Plot plot = area.getPlot(location); + if (plot == null) { + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_ROAD)) { + return; + } + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); + event.setCancelled(true); + } else if (!plot.hasOwner()) { + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { + return; + } + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); + event.setCancelled(true); + } else if (!plot.isAdded(pp.getUUID())) { + if (Flags.USE.contains(plot, PlotBlock.get(event.getBucket().getId(), 0))) { + return; + } + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { + return; + } + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + } else if (Settings.Done.RESTRICT_BUILDING && plot.getFlags().containsKey(Flags.DONE)) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + } } + } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBucketEmpty(PlayerBucketEmptyEvent event) { - BlockFace bf = event.getBlockFace(); - Block b = - event.getBlockClicked().getLocation().add(bf.getModX(), bf.getModY(), bf.getModZ()) - .getBlock(); - Location location = BukkitUtil.getLocation(b.getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - PlotPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); - Plot plot = area.getPlot(location); - if (plot == null) { - if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_ROAD)) { - return; - } - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); - event.setCancelled(true); - } else if (!plot.hasOwner()) { - if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { - return; - } - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); - event.setCancelled(true); - } else if (!plot.isAdded(pp.getUUID())) { - if (Flags.USE.contains(plot, PlotBlock.get(event.getBucket().getId(), 0))) { - return; - } - if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { - return; - } - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); - event.setCancelled(true); - } else if (Settings.Done.RESTRICT_BUILDING && plot.getFlags().containsKey(Flags.DONE)) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); - event.setCancelled(true); - } - } + @EventHandler(priority = EventPriority.HIGHEST) + public void onInventoryClose(InventoryCloseEvent event) { + HumanEntity closer = event.getPlayer(); + if (!(closer instanceof Player)) { + return; } + Player player = (Player) closer; + PlotInventory.removePlotInventoryOpen(BukkitUtil.getPlayer(player)); + } - @EventHandler(priority = EventPriority.HIGHEST) - public void onInventoryClose(InventoryCloseEvent event) { - HumanEntity closer = event.getPlayer(); - if (!(closer instanceof Player)) { - return; - } - Player player = (Player) closer; - PlotInventory.removePlotInventoryOpen(BukkitUtil.getPlayer(player)); + @EventHandler(priority = EventPriority.MONITOR) + public void onLeave(PlayerQuitEvent event) { + TaskManager.TELEPORT_QUEUE.remove(event.getPlayer().getName()); + PlotPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); + pp.unregister(); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBucketFill(PlayerBucketFillEvent event) { + Block b = event.getBlockClicked(); + Location location = BukkitUtil.getLocation(b.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; } - - @EventHandler(priority = EventPriority.MONITOR) public void onLeave(PlayerQuitEvent event) { - TaskManager.TELEPORT_QUEUE.remove(event.getPlayer().getName()); - PlotPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); - pp.unregister(); + Player player = event.getPlayer(); + PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + Plot plot = area.getPlot(location); + if (plot == null) { + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_ROAD)) { + return; + } + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); + event.setCancelled(true); + } else if (!plot.hasOwner()) { + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { + return; + } + MainUtil + .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); + event.setCancelled(true); + } else if (!plot.isAdded(plotPlayer.getUUID())) { + Optional> use = plot.getFlag(Flags.USE); + Block block = event.getBlockClicked(); + if (use.isPresent() && use.get().contains(PlotBlock.get(block.getType().name()))) { + return; + } + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_OTHER)) { + return; + } + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + } else if (Settings.Done.RESTRICT_BUILDING && plot.getFlags().containsKey(Flags.DONE)) { + if (!Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_OTHER)) { + MainUtil + .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + } } + } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBucketFill(PlayerBucketFillEvent event) { - Block b = event.getBlockClicked(); - Location location = BukkitUtil.getLocation(b.getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onVehicleCreate(VehicleCreateEvent event) { + Vehicle entity = event.getVehicle(); + Location location = BukkitUtil.getLocation(entity); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlotAbs(location); + if (plot == null || checkEntity(entity, plot)) { + entity.remove(); + return; + } + if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) { + entity + .setMetadata("plot", new FixedMetadataValue((Plugin) PlotSquared.get().IMP, plot)); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onHangingPlace(HangingPlaceEvent event) { + Block b = event.getBlock().getRelative(event.getBlockFace()); + Location location = BukkitUtil.getLocation(b.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Player p = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(p); + Plot plot = area.getPlot(location); + if (plot == null) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_ROAD)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); + event.setCancelled(true); + } + } else { + if (!plot.hasOwner()) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { + MainUtil + .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); + event.setCancelled(true); } - Player player = event.getPlayer(); - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); - Plot plot = area.getPlot(location); - if (plot == null) { - if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_ROAD)) { - return; - } - MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); - event.setCancelled(true); - } else if (!plot.hasOwner()) { - if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { - return; - } + return; + } + if (!plot.isAdded(pp.getUUID())) { + if (!plot.getFlag(Flags.HANGING_PLACE, false)) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { MainUtil - .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); + .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); event.setCancelled(true); - } else if (!plot.isAdded(plotPlayer.getUUID())) { - Optional> use = plot.getFlag(Flags.USE); - Block block = event.getBlockClicked(); - if (use.isPresent() && use.get().contains(PlotBlock.get(block.getType().name()))) { - return; - } - if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_OTHER)) { - return; - } - MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); - event.setCancelled(true); - } else if (Settings.Done.RESTRICT_BUILDING && plot.getFlags().containsKey(Flags.DONE)) { - if (!Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_OTHER)) { - MainUtil - .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); - event.setCancelled(true); - } + } + return; } - } + } + if (checkEntity(event.getEntity(), plot)) { + event.setCancelled(true); + } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onVehicleCreate(VehicleCreateEvent event) { - Vehicle entity = event.getVehicle(); - Location location = BukkitUtil.getLocation(entity); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onHangingBreakByEntity(HangingBreakByEntityEvent event) { + Entity remover = event.getRemover(); + if (remover instanceof Player) { + Player p = (Player) remover; + Location location = BukkitUtil.getLocation(event.getEntity()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + PlotPlayer pp = BukkitUtil.getPlayer(p); + Plot plot = area.getPlot(location); + if (plot == null) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_DESTROY_ROAD)) { + MainUtil + .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_ROAD); + event.setCancelled(true); + } + } else if (!plot.hasOwner()) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_DESTROY_UNOWNED)) { + MainUtil + .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_UNOWNED); + event.setCancelled(true); + } + } else if (!plot.isAdded(pp.getUUID())) { + if (plot.getFlag(Flags.HANGING_BREAK, false)) { + return; + } + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_DESTROY_OTHER)) { + MainUtil + .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_OTHER); + event.setCancelled(true); + } + } + } else if (remover instanceof Projectile) { + Projectile p = (Projectile) remover; + if (p.getShooter() instanceof Player) { + Player shooter = (Player) p.getShooter(); + Location location = BukkitUtil.getLocation(event.getEntity()); PlotArea area = location.getPlotArea(); if (area == null) { - return; + return; } - Plot plot = area.getOwnedPlotAbs(location); - if (plot == null || checkEntity(entity, plot)) { - entity.remove(); - return; - } - if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) { - entity - .setMetadata("plot", new FixedMetadataValue((Plugin) PlotSquared.get().IMP, plot)); - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onHangingPlace(HangingPlaceEvent event) { - Block b = event.getBlock().getRelative(event.getBlockFace()); - Location location = BukkitUtil.getLocation(b.getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - Player p = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(p); - Plot plot = area.getPlot(location); - if (plot == null) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_ROAD)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); - event.setCancelled(true); - } - } else { - if (!plot.hasOwner()) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { - MainUtil - .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); - event.setCancelled(true); - } - return; - } - if (!plot.isAdded(pp.getUUID())) { - if (!plot.getFlag(Flags.HANGING_PLACE, false)) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { - MainUtil - .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); - event.setCancelled(true); - } - return; - } - } - if (checkEntity(event.getEntity(), plot)) { - event.setCancelled(true); - } - - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onHangingBreakByEntity(HangingBreakByEntityEvent event) { - Entity remover = event.getRemover(); - if (remover instanceof Player) { - Player p = (Player) remover; - Location location = BukkitUtil.getLocation(event.getEntity()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - PlotPlayer pp = BukkitUtil.getPlayer(p); - Plot plot = area.getPlot(location); - if (plot == null) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_DESTROY_ROAD)) { - MainUtil - .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_ROAD); - event.setCancelled(true); - } - } else if (!plot.hasOwner()) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_DESTROY_UNOWNED)) { - MainUtil - .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_UNOWNED); - event.setCancelled(true); - } - } else if (!plot.isAdded(pp.getUUID())) { - if (plot.getFlag(Flags.HANGING_BREAK, false)) { - return; - } - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_DESTROY_OTHER)) { - MainUtil - .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_OTHER); - event.setCancelled(true); - } - } - } else if (remover instanceof Projectile) { - Projectile p = (Projectile) remover; - if (p.getShooter() instanceof Player) { - Player shooter = (Player) p.getShooter(); - Location location = BukkitUtil.getLocation(event.getEntity()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - PlotPlayer player = BukkitUtil.getPlayer(shooter); - Plot plot = area.getPlot(BukkitUtil.getLocation(event.getEntity())); - if (plot != null) { - if (!plot.hasOwner()) { - if (!Permissions - .hasPermission(player, C.PERMISSION_ADMIN_DESTROY_UNOWNED)) { - MainUtil.sendMessage(player, C.NO_PERMISSION_EVENT, - C.PERMISSION_ADMIN_DESTROY_UNOWNED); - event.setCancelled(true); - } - } else if (!plot.isAdded(player.getUUID())) { - if (!plot.getFlag(Flags.HANGING_BREAK, false)) { - if (!Permissions - .hasPermission(player, C.PERMISSION_ADMIN_DESTROY_OTHER)) { - MainUtil.sendMessage(player, C.NO_PERMISSION_EVENT, - C.PERMISSION_ADMIN_DESTROY_OTHER); - event.setCancelled(true); - } - } - } - } - } - } else { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { - Location location = BukkitUtil.getLocation(event.getRightClicked().getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - Player p = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(p); - Plot plot = area.getPlot(location); - if (plot == null) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_ROAD)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_INTERACT_ROAD); - event.setCancelled(true); - } - } else if (!plot.hasOwner()) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_UNOWNED)) { - MainUtil - .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_INTERACT_UNOWNED); - event.setCancelled(true); - } - } else if (!plot.isAdded(pp.getUUID())) { - Entity entity = event.getRightClicked(); - if (entity instanceof Monster && plot.getFlag(Flags.HOSTILE_INTERACT, false)) { - return; - } - if (entity instanceof Animals && plot.getFlag(Flags.ANIMAL_INTERACT, false)) { - return; - } - if (entity instanceof Tameable && ((Tameable) entity).isTamed() && plot - .getFlag(Flags.TAMED_INTERACT, false)) { - return; - } - if (entity instanceof Vehicle && plot.getFlag(Flags.VEHICLE_USE, false)) { - return; - } - if (entity instanceof Player && plot.getFlag(Flags.PLAYER_INTERACT, false)) { - return; - } - if (entity instanceof Villager && plot.getFlag(Flags.VILLAGER_INTERACT, false)) { - return; - } - if (entity instanceof ItemFrame && plot.getFlag(Flags.MISC_INTERACT, false)) { - return; - } - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_OTHER)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_INTERACT_OTHER); - event.setCancelled(true); - } - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onVehicleDestroy(VehicleDestroyEvent event) { - Location l = BukkitUtil.getLocation(event.getVehicle()); - PlotArea area = l.getPlotArea(); - if (area == null) { - return; - } - Entity d = event.getAttacker(); - if (d instanceof Player) { - Player p = (Player) d; - PlotPlayer pp = BukkitUtil.getPlayer(p); - Plot plot = area.getPlot(l); - if (plot == null) { - if (!Permissions.hasPermission(pp, "plots.admin.vehicle.break.road")) { - MainUtil - .sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.vehicle.break.road"); - event.setCancelled(true); - } - } else { - if (!plot.hasOwner()) { - if (!Permissions.hasPermission(pp, "plots.admin.vehicle.break.unowned")) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, - "plots.admin.vehicle.break.unowned"); - event.setCancelled(true); - return; - } - return; - } - if (!plot.isAdded(pp.getUUID())) { - if (plot.getFlag(Flags.VEHICLE_BREAK, false)) { - return; - } - if (!Permissions.hasPermission(pp, "plots.admin.vehicle.break.other")) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, - "plots.admin.vehicle.break.other"); - event.setCancelled(true); - } - } - } - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPotionSplash(PotionSplashEvent event) { - ThrownPotion damager = event.getPotion(); - Location l = BukkitUtil.getLocation(damager); - if (!PlotSquared.get().hasPlotArea(l.getWorld())) { - return; - } - int count = 0; - for (LivingEntity victim : event.getAffectedEntities()) { - if (!entityDamage(damager, victim)) { - event.setIntensity(victim, 0); - count++; - } - } - if ((count > 0 && count == event.getAffectedEntities().size()) || !onProjectileHit(event)) { - event.setCancelled(true); - } - } - - @SuppressWarnings("deprecation") @EventHandler(priority = EventPriority.HIGHEST) - public void onEntityCombustByEntity(EntityCombustByEntityEvent event) { - EntityDamageByEntityEvent eventChange = null; - eventChange = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), - EntityDamageEvent.DamageCause.FIRE_TICK, (double) event.getDuration()); - onEntityDamageByEntityEvent(eventChange); - if (eventChange.isCancelled()) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) { - Entity damager = event.getDamager(); - Location l = BukkitUtil.getLocation(damager); - if (!PlotSquared.get().hasPlotArea(l.getWorld())) { - return; - } - Entity victim = event.getEntity(); - if (!entityDamage(damager, victim)) { - if (event.isCancelled()) { - if (victim instanceof Ageable) { - Ageable ageable = (Ageable) victim; - if (ageable.getAge() == -24000) { - ageable.setAge(0); - ageable.setAdult(); - } - } - } - event.setCancelled(true); - } - } - - public boolean entityDamage(Entity damager, Entity victim) { - Location dloc = BukkitUtil.getLocation(damager); - Location vloc = BukkitUtil.getLocation(victim); - PlotArea dArea = dloc.getPlotArea(); - PlotArea vArea = - dArea != null && dArea.contains(vloc.getX(), vloc.getZ()) ? dArea : vloc.getPlotArea(); - if (dArea == null && vArea == null) { - return true; - } - - Plot dplot = dArea != null ? dArea.getPlot(dloc) : null; - Plot vplot = vArea != null ? vArea.getPlot(vloc) : null; - - Plot plot; - String stub; - if (dplot == null && vplot == null) { - if (dArea == null) { - return true; - } - plot = null; - stub = "road"; - } else { - // Prioritize plots for close to seamless pvp zones - if (victim.getTicksLived() > damager.getTicksLived()) { - if (dplot == null || !(victim instanceof Player)) { - if (vplot == null) { - plot = dplot; - } else { - plot = vplot; - } - } else { - plot = dplot; - } - } else if (dplot == null || !(victim instanceof Player)) { - if (vplot == null) { - plot = dplot; - } else { - plot = vplot; - } - } else if (vplot == null) { - plot = dplot; - } else { - plot = vplot; - } - if (plot.hasOwner()) { - stub = "other"; - } else { - stub = "unowned"; - } - } - - Player player; - if (damager instanceof Player) { // attacker is player - player = (Player) damager; - } else if (damager instanceof Projectile) { - Projectile projectile = (Projectile) damager; - ProjectileSource shooter = projectile.getShooter(); - if (shooter instanceof Player) { // shooter is player - player = (Player) shooter; - } else { // shooter is not player - if (shooter instanceof BlockProjectileSource) { - Location sLoc = BukkitUtil - .getLocation(((BlockProjectileSource) shooter).getBlock().getLocation()); - dplot = dArea.getPlot(sLoc); - } - player = null; - } - } else { // Attacker is not player - player = null; - } - if (player != null) { - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); - if (victim instanceof Hanging) { // hanging - if (plot != null && (plot.getFlag(Flags.HANGING_BREAK, false) || plot - .isAdded(plotPlayer.getUUID()))) { - return true; - } - if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) { - MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, - "plots.admin.destroy." + stub); - return false; - } - } else if (victim.getEntityId() == 30) { - if (plot != null && (plot.getFlag(Flags.MISC_BREAK, false) || plot - .isAdded(plotPlayer.getUUID()))) { - return true; - } - if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) { - MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, - "plots.admin.destroy." + stub); - return false; - } - } else if (victim instanceof Monster - || victim instanceof EnderDragon) { // victim is monster - if (plot != null && (plot.getFlag(Flags.HOSTILE_ATTACK, false) || plot - .getFlag(Flags.PVE, false) || plot.isAdded(plotPlayer.getUUID()))) { - return true; - } - if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { - MainUtil - .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); - return false; - } - } else if (victim instanceof Tameable) { // victim is tameable - if (plot != null && (plot.getFlag(Flags.TAMED_ATTACK, false) || plot - .getFlag(Flags.PVE, false) || plot.isAdded(plotPlayer.getUUID()))) { - return true; - } - if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { - MainUtil - .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); - return false; - } - } else if (victim instanceof Player) { - if (plot != null) { - if (Flags.PVP.isFalse(plot) && !Permissions - .hasPermission(plotPlayer, "plots.admin.pvp." + stub)) { - MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, - "plots.admin.pvp." + stub); - return false; - } else { - return true; - } - } - if (!Permissions.hasPermission(plotPlayer, "plots.admin.pvp." + stub)) { - MainUtil - .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pvp." + stub); - return false; - } - } else if (victim instanceof Creature) { // victim is animal - if (plot != null && (plot.getFlag(Flags.ANIMAL_ATTACK, false) || plot - .getFlag(Flags.PVE, false) || plot.isAdded(plotPlayer.getUUID()))) { - return true; - } - if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { - MainUtil - .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); - return false; - } - } else if (victim instanceof Vehicle) { // Vehicles are managed in vehicle destroy event - return true; - } else { // victim is something else - if (plot != null && (plot.getFlag(Flags.PVE, false) || plot - .isAdded(plotPlayer.getUUID()))) { - return true; - } - if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { - MainUtil - .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); - return false; - } - } - return true; - } else if (dplot != null && (!dplot.equals(vplot) || Objects - .equals(dplot.guessOwner(), vplot.guessOwner()))) { - return vplot != null && Flags.PVE.isTrue(vplot); - } - return ((vplot != null && Flags.PVE.isTrue(vplot)) || !(damager instanceof Arrow - && !(victim instanceof Creature))); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPlayerEggThrow(PlayerEggThrowEvent event) { - Location l = BukkitUtil.getLocation(event.getEgg().getLocation()); - PlotArea area = l.getPlotArea(); - if (area == null) { - return; - } - Player player = event.getPlayer(); - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); - Plot plot = area.getPlot(l); - if (plot == null) { - if (!Permissions.hasPermission(plotPlayer, "plots.admin.projectile.road")) { - MainUtil - .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.projectile.road"); - event.setHatching(false); - } - } else if (!plot.hasOwner()) { - if (!Permissions.hasPermission(plotPlayer, "plots.admin.projectile.unowned")) { - MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, - "plots.admin.projectile.unowned"); - event.setHatching(false); - } - } else if (!plot.isAdded(plotPlayer.getUUID())) { - if (!Permissions.hasPermission(plotPlayer, "plots.admin.projectile.other")) { - MainUtil - .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.projectile.other"); - event.setHatching(false); - } - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void blockCreate(BlockPlaceEvent event) { - Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); - PlotArea area = location.getPlotArea(); - if (area == null) { - return; - } - Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); - Plot plot = area.getPlot(location); + PlotPlayer player = BukkitUtil.getPlayer(shooter); + Plot plot = area.getPlot(BukkitUtil.getLocation(event.getEntity())); if (plot != null) { - if ((location.getY() > area.MAX_BUILD_HEIGHT || location.getY() < area.MIN_BUILD_HEIGHT) - && !Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_HEIGHTLIMIT)) { + if (!plot.hasOwner()) { + if (!Permissions + .hasPermission(player, C.PERMISSION_ADMIN_DESTROY_UNOWNED)) { + MainUtil.sendMessage(player, C.NO_PERMISSION_EVENT, + C.PERMISSION_ADMIN_DESTROY_UNOWNED); + event.setCancelled(true); + } + } else if (!plot.isAdded(player.getUUID())) { + if (!plot.getFlag(Flags.HANGING_BREAK, false)) { + if (!Permissions + .hasPermission(player, C.PERMISSION_ADMIN_DESTROY_OTHER)) { + MainUtil.sendMessage(player, C.NO_PERMISSION_EVENT, + C.PERMISSION_ADMIN_DESTROY_OTHER); event.setCancelled(true); - MainUtil.sendMessage(pp, - C.HEIGHT_LIMIT.s().replace("{limit}", String.valueOf(area.MAX_BUILD_HEIGHT))); + } } - if (!plot.hasOwner()) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { - MainUtil - .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); - event.setCancelled(true); - return; - } - } else if (!plot.isAdded(pp.getUUID())) { - Set place = plot.getFlag(Flags.PLACE, null); - if (place != null) { - Block block = event.getBlock(); - if (place.contains(PlotBlock.get(block.getType().name()))) { - return; - } - } - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); - event.setCancelled(true); - return; - } - } else if (Settings.Done.RESTRICT_BUILDING && plot.getFlags().containsKey(Flags.DONE)) { - if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); - event.setCancelled(true); - return; - } - } - if (plot.getFlag(Flags.DISABLE_PHYSICS, false)) { - Block block = event.getBlockPlaced(); - if (block.getType().hasGravity()) { - sendBlockChange(block.getLocation(), block.getBlockData()); - } - } - } else if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_ROAD)) { - MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); - event.setCancelled(true); + } } + } + } else { + event.setCancelled(true); } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { + Location location = BukkitUtil.getLocation(event.getRightClicked().getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Player p = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(p); + Plot plot = area.getPlot(location); + if (plot == null) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_ROAD)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_INTERACT_ROAD); + event.setCancelled(true); + } + } else if (!plot.hasOwner()) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_UNOWNED)) { + MainUtil + .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_INTERACT_UNOWNED); + event.setCancelled(true); + } + } else if (!plot.isAdded(pp.getUUID())) { + Entity entity = event.getRightClicked(); + if (entity instanceof Monster && plot.getFlag(Flags.HOSTILE_INTERACT, false)) { + return; + } + if (entity instanceof Animals && plot.getFlag(Flags.ANIMAL_INTERACT, false)) { + return; + } + if (entity instanceof Tameable && ((Tameable) entity).isTamed() && plot + .getFlag(Flags.TAMED_INTERACT, false)) { + return; + } + if (entity instanceof Vehicle && plot.getFlag(Flags.VEHICLE_USE, false)) { + return; + } + if (entity instanceof Player && plot.getFlag(Flags.PLAYER_INTERACT, false)) { + return; + } + if (entity instanceof Villager && plot.getFlag(Flags.VILLAGER_INTERACT, false)) { + return; + } + if (entity instanceof ItemFrame && plot.getFlag(Flags.MISC_INTERACT, false)) { + return; + } + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_OTHER)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_INTERACT_OTHER); + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onVehicleDestroy(VehicleDestroyEvent event) { + Location l = BukkitUtil.getLocation(event.getVehicle()); + PlotArea area = l.getPlotArea(); + if (area == null) { + return; + } + Entity d = event.getAttacker(); + if (d instanceof Player) { + Player p = (Player) d; + PlotPlayer pp = BukkitUtil.getPlayer(p); + Plot plot = area.getPlot(l); + if (plot == null) { + if (!Permissions.hasPermission(pp, "plots.admin.vehicle.break.road")) { + MainUtil + .sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.vehicle.break.road"); + event.setCancelled(true); + } + } else { + if (!plot.hasOwner()) { + if (!Permissions.hasPermission(pp, "plots.admin.vehicle.break.unowned")) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, + "plots.admin.vehicle.break.unowned"); + event.setCancelled(true); + return; + } + return; + } + if (!plot.isAdded(pp.getUUID())) { + if (plot.getFlag(Flags.VEHICLE_BREAK, false)) { + return; + } + if (!Permissions.hasPermission(pp, "plots.admin.vehicle.break.other")) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, + "plots.admin.vehicle.break.other"); + event.setCancelled(true); + } + } + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPotionSplash(PotionSplashEvent event) { + ThrownPotion damager = event.getPotion(); + Location l = BukkitUtil.getLocation(damager); + if (!PlotSquared.get().hasPlotArea(l.getWorld())) { + return; + } + int count = 0; + for (LivingEntity victim : event.getAffectedEntities()) { + if (!entityDamage(damager, victim)) { + event.setIntensity(victim, 0); + count++; + } + } + if ((count > 0 && count == event.getAffectedEntities().size()) || !onProjectileHit(event)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onEntityCombustByEntity(EntityCombustByEntityEvent event) { + EntityDamageByEntityEvent eventChange = new EntityDamageByEntityEvent(event.getCombuster(), + event.getEntity(), + EntityDamageEvent.DamageCause.FIRE_TICK, (double) event.getDuration()); + onEntityDamageByEntityEvent(eventChange); + if (eventChange.isCancelled()) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) { + Entity damager = event.getDamager(); + Location l = BukkitUtil.getLocation(damager); + if (!PlotSquared.get().hasPlotArea(l.getWorld())) { + return; + } + Entity victim = event.getEntity(); + if (!entityDamage(damager, victim)) { + if (event.isCancelled()) { + if (victim instanceof Ageable) { + Ageable ageable = (Ageable) victim; + if (ageable.getAge() == -24000) { + ageable.setAge(0); + ageable.setAdult(); + } + } + } + event.setCancelled(true); + } + } + + public boolean entityDamage(Entity damager, Entity victim) { + Location dloc = BukkitUtil.getLocation(damager); + Location vloc = BukkitUtil.getLocation(victim); + PlotArea dArea = dloc.getPlotArea(); + PlotArea vArea = + dArea != null && dArea.contains(vloc.getX(), vloc.getZ()) ? dArea : vloc.getPlotArea(); + if (dArea == null && vArea == null) { + return true; + } + + Plot dplot = dArea != null ? dArea.getPlot(dloc) : null; + Plot vplot = vArea != null ? vArea.getPlot(vloc) : null; + + Plot plot; + String stub; + if (dplot == null && vplot == null) { + if (dArea == null) { + return true; + } + plot = null; + stub = "road"; + } else { + // Prioritize plots for close to seamless pvp zones + if (victim.getTicksLived() > damager.getTicksLived()) { + if (dplot == null || !(victim instanceof Player)) { + if (vplot == null) { + plot = dplot; + } else { + plot = vplot; + } + } else { + plot = dplot; + } + } else if (dplot == null || !(victim instanceof Player)) { + if (vplot == null) { + plot = dplot; + } else { + plot = vplot; + } + } else if (vplot == null) { + plot = dplot; + } else { + plot = vplot; + } + if (plot.hasOwner()) { + stub = "other"; + } else { + stub = "unowned"; + } + } + + Player player; + if (damager instanceof Player) { // attacker is player + player = (Player) damager; + } else if (damager instanceof Projectile) { + Projectile projectile = (Projectile) damager; + ProjectileSource shooter = projectile.getShooter(); + if (shooter instanceof Player) { // shooter is player + player = (Player) shooter; + } else { // shooter is not player + if (shooter instanceof BlockProjectileSource) { + Location sLoc = BukkitUtil + .getLocation(((BlockProjectileSource) shooter).getBlock().getLocation()); + dplot = dArea.getPlot(sLoc); + } + player = null; + } + } else { // Attacker is not player + player = null; + } + if (player != null) { + PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + if (victim instanceof Hanging) { // hanging + if (plot != null && (plot.getFlag(Flags.HANGING_BREAK, false) || plot + .isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, + "plots.admin.destroy." + stub); + return false; + } + } else if (victim.getEntityId() == 30) { + if (plot != null && (plot.getFlag(Flags.MISC_BREAK, false) || plot + .isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, + "plots.admin.destroy." + stub); + return false; + } + } else if (victim instanceof Monster + || victim instanceof EnderDragon) { // victim is monster + if (plot != null && (plot.getFlag(Flags.HOSTILE_ATTACK, false) || plot + .getFlag(Flags.PVE, false) || plot.isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { + MainUtil + .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + return false; + } + } else if (victim instanceof Tameable) { // victim is tameable + if (plot != null && (plot.getFlag(Flags.TAMED_ATTACK, false) || plot + .getFlag(Flags.PVE, false) || plot.isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { + MainUtil + .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + return false; + } + } else if (victim instanceof Player) { + if (plot != null) { + if (Flags.PVP.isFalse(plot) && !Permissions + .hasPermission(plotPlayer, "plots.admin.pvp." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, + "plots.admin.pvp." + stub); + return false; + } else { + return true; + } + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.pvp." + stub)) { + MainUtil + .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pvp." + stub); + return false; + } + } else if (victim instanceof Creature) { // victim is animal + if (plot != null && (plot.getFlag(Flags.ANIMAL_ATTACK, false) || plot + .getFlag(Flags.PVE, false) || plot.isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { + MainUtil + .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + return false; + } + } else if (victim instanceof Vehicle) { // Vehicles are managed in vehicle destroy event + return true; + } else { // victim is something else + if (plot != null && (plot.getFlag(Flags.PVE, false) || plot + .isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { + MainUtil + .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + return false; + } + } + return true; + } else if (dplot != null && (!dplot.equals(vplot) || Objects + .equals(dplot.guessOwner(), vplot.guessOwner()))) { + return vplot != null && Flags.PVE.isTrue(vplot); + } + return ((vplot != null && Flags.PVE.isTrue(vplot)) || !(damager instanceof Arrow + && !(victim instanceof Creature))); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerEggThrow(PlayerEggThrowEvent event) { + Location l = BukkitUtil.getLocation(event.getEgg().getLocation()); + PlotArea area = l.getPlotArea(); + if (area == null) { + return; + } + Player player = event.getPlayer(); + PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + Plot plot = area.getPlot(l); + if (plot == null) { + if (!Permissions.hasPermission(plotPlayer, "plots.admin.projectile.road")) { + MainUtil + .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.projectile.road"); + event.setHatching(false); + } + } else if (!plot.hasOwner()) { + if (!Permissions.hasPermission(plotPlayer, "plots.admin.projectile.unowned")) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, + "plots.admin.projectile.unowned"); + event.setHatching(false); + } + } else if (!plot.isAdded(plotPlayer.getUUID())) { + if (!Permissions.hasPermission(plotPlayer, "plots.admin.projectile.other")) { + MainUtil + .sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.projectile.other"); + event.setHatching(false); + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void blockCreate(BlockPlaceEvent event) { + Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Player player = event.getPlayer(); + PlotPlayer pp = BukkitUtil.getPlayer(player); + Plot plot = area.getPlot(location); + if (plot != null) { + if ((location.getY() > area.MAX_BUILD_HEIGHT || location.getY() < area.MIN_BUILD_HEIGHT) + && !Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_HEIGHTLIMIT)) { + event.setCancelled(true); + MainUtil.sendMessage(pp, + C.HEIGHT_LIMIT.s().replace("{limit}", String.valueOf(area.MAX_BUILD_HEIGHT))); + } + if (!plot.hasOwner()) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { + MainUtil + .sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); + event.setCancelled(true); + return; + } + } else if (!plot.isAdded(pp.getUUID())) { + Set place = plot.getFlag(Flags.PLACE, null); + if (place != null) { + Block block = event.getBlock(); + if (place.contains(PlotBlock.get(block.getType().name()))) { + return; + } + } + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + return; + } + } else if (Settings.Done.RESTRICT_BUILDING && plot.getFlags().containsKey(Flags.DONE)) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + return; + } + } + if (plot.getFlag(Flags.DISABLE_PHYSICS, false)) { + Block block = event.getBlockPlaced(); + if (block.getType().hasGravity()) { + sendBlockChange(block.getLocation(), block.getBlockData()); + } + } + } else if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_ROAD)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); + event.setCancelled(true); + } + } } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlotPlusListener.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlotPlusListener.java index a4df7c6b3..19cd4c554 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlotPlusListener.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlotPlusListener.java @@ -10,6 +10,7 @@ import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.block.Block; +import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -37,45 +38,43 @@ public class PlotPlusListener extends PlotListener implements Listener { private static final HashMap healRunnable = new HashMap<>(); public static void startRunnable(JavaPlugin plugin) { - plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() { - @Override public void run() { - if (!healRunnable.isEmpty()) { - for (Iterator> iterator = - healRunnable.entrySet().iterator(); iterator.hasNext(); ) { - Entry entry = iterator.next(); - Interval value = entry.getValue(); - ++value.count; - if (value.count == value.interval) { - value.count = 0; - Player player = Bukkit.getPlayer(entry.getKey()); - if (player == null) { - iterator.remove(); - continue; - } - double level = player.getHealth(); - if (level != value.max) { - player.setHealth(Math.min(level + value.amount, value.max)); - } + plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, () -> { + if (!healRunnable.isEmpty()) { + for (Iterator> iterator = + healRunnable.entrySet().iterator(); iterator.hasNext(); ) { + Entry entry = iterator.next(); + Interval value = entry.getValue(); + ++value.count; + if (value.count == value.interval) { + value.count = 0; + Player player = Bukkit.getPlayer(entry.getKey()); + if (player == null) { + iterator.remove(); + continue; + } + double level = player.getHealth(); + if (level != value.max) { + player.setHealth(Math.min(level + value.amount, value.max)); } } } - if (!feedRunnable.isEmpty()) { - for (Iterator> iterator = - feedRunnable.entrySet().iterator(); iterator.hasNext(); ) { - Entry entry = iterator.next(); - Interval value = entry.getValue(); - ++value.count; - if (value.count == value.interval) { - value.count = 0; - Player player = Bukkit.getPlayer(entry.getKey()); - if (player == null) { - iterator.remove(); - continue; - } - int level = player.getFoodLevel(); - if (level != value.max) { - player.setFoodLevel(Math.min(level + value.amount, value.max)); - } + } + if (!feedRunnable.isEmpty()) { + for (Iterator> iterator = + feedRunnable.entrySet().iterator(); iterator.hasNext(); ) { + Entry entry = iterator.next(); + Interval value = entry.getValue(); + ++value.count; + if (value.count == value.interval) { + value.count = 0; + Player player = Bukkit.getPlayer(entry.getKey()); + if (player == null) { + iterator.remove(); + continue; + } + int level = player.getFoodLevel(); + if (level != value.max) { + player.setFoodLevel(Math.min(level + value.amount, value.max)); } } } @@ -108,7 +107,7 @@ public class PlotPlusListener extends PlotListener implements Listener { if (event.getEntityType() != EntityType.PLAYER) { return; } - Player player = (Player) event.getEntity(); + Entity player = event.getEntity(); Plot plot = BukkitUtil.getLocation(player).getOwnedPlot(); if (plot == null) { return; diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/SingleWorldListener.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/SingleWorldListener.java index 6a3e26d59..321dde939 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/SingleWorldListener.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/SingleWorldListener.java @@ -1,9 +1,13 @@ package com.github.intellectualsites.plotsquared.bukkit.listeners; +import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getRefClass; + import com.github.intellectualsites.plotsquared.plot.PlotSquared; import com.github.intellectualsites.plotsquared.plot.object.worlds.PlotAreaManager; import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager; import com.github.intellectualsites.plotsquared.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; @@ -14,11 +18,6 @@ import org.bukkit.event.world.ChunkEvent; import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.plugin.Plugin; -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getRefClass; - @SuppressWarnings("unused") public class SingleWorldListener implements Listener { private Method methodGetHandleChunk; @@ -33,8 +32,8 @@ import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils this.done = classChunk.getField("done").getRealField(); this.lit = classChunk.getField("lit").getRealField(); this.s = classChunk.getField("s").getRealField(); - } catch (Throwable ignore) { - ignore.printStackTrace(); + } catch (NoSuchFieldException exception) { + exception.printStackTrace(); } Bukkit.getPluginManager().registerEvents(this, plugin); } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/ReplicatingEntityWrapper.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/ReplicatingEntityWrapper.java index e71373771..c06b66b71 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/ReplicatingEntityWrapper.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/entity/ReplicatingEntityWrapper.java @@ -12,685 +12,697 @@ import org.bukkit.util.Vector; public final class ReplicatingEntityWrapper extends EntityWrapper { - private final short depth; - private final int hash; - private final EntityBaseStats base = new EntityBaseStats(); + private final short depth; + private final int hash; + private final EntityBaseStats base = new EntityBaseStats(); - public ItemStack[] inventory; - // Extended - private ItemStack stack; - private byte dataByte; - private byte dataByte2; - private String dataString; - private LivingEntityStats lived; - private AgeableStats aged; - private TameableStats tamed; - private ArmorStandStats stand; - private HorseStats horse; - private boolean noGravity; + public ItemStack[] inventory; + // Extended + private ItemStack stack; + private byte dataByte; + private byte dataByte2; + private String dataString; + private LivingEntityStats lived; + private AgeableStats aged; + private TameableStats tamed; + private ArmorStandStats stand; + private HorseStats horse; + private boolean noGravity; - public ReplicatingEntityWrapper(Entity entity, short depth) { - super(entity); + public ReplicatingEntityWrapper(Entity entity, short depth) { + super(entity); - this.hash = entity.getEntityId(); - this.depth = depth; + this.hash = entity.getEntityId(); + this.depth = depth; - if (depth == 0) { - return; - } - Entity passenger = entity.getPassenger(); - if (passenger != null) { - this.base.passenger = new ReplicatingEntityWrapper(passenger, depth); - } - this.base.fall = entity.getFallDistance(); - this.base.fire = (short) entity.getFireTicks(); - this.base.age = entity.getTicksLived(); - Vector velocity = entity.getVelocity(); - this.base.vX = velocity.getX(); - this.base.vY = velocity.getY(); - this.base.vZ = velocity.getZ(); - if (depth == 1) { - return; - } - if (!entity.hasGravity()) { - this.noGravity = true; - } - switch (entity.getType()) { - case BOAT: - Boat boat = (Boat) entity; - this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType()); - return; - case ARROW: - case COMPLEX_PART: - case EGG: - case ENDER_CRYSTAL: - case ENDER_PEARL: - case ENDER_SIGNAL: - case EXPERIENCE_ORB: - case FALLING_BLOCK: - case FIREBALL: - case FIREWORK: - case FISHING_HOOK: - case LEASH_HITCH: - case LIGHTNING: - case MINECART: - case MINECART_COMMAND: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - case PLAYER: - case PRIMED_TNT: - case SLIME: - case SMALL_FIREBALL: - case SNOWBALL: - case MINECART_FURNACE: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case WEATHER: - case WITHER_SKULL: - case UNKNOWN: - case TIPPED_ARROW: - case SPECTRAL_ARROW: - case SHULKER_BULLET: - case DRAGON_FIREBALL: - case LINGERING_POTION: - case AREA_EFFECT_CLOUD: - // Do this stuff later - return; - // MISC // - case DROPPED_ITEM: - Item item = (Item) entity; - this.stack = item.getItemStack(); - return; - case ITEM_FRAME: - this.x = Math.floor(this.x); - this.y = Math.floor(this.y); - this.z = Math.floor(this.z); - ItemFrame itemFrame = (ItemFrame) entity; - this.dataByte = getOrdinal(Rotation.values(), itemFrame.getRotation()); - this.stack = itemFrame.getItem().clone(); - return; - case PAINTING: - this.x = Math.floor(this.x); - this.y = Math.floor(this.y); - this.z = Math.floor(this.z); - Painting painting = (Painting) entity; - Art art = painting.getArt(); - this.dataByte = getOrdinal(BlockFace.values(), painting.getFacing()); - int h = art.getBlockHeight(); - if (h % 2 == 0) { - this.y -= 1; - } - this.dataString = art.name(); - return; - // END MISC // - // INVENTORY HOLDER // - case MINECART_CHEST: - case MINECART_HOPPER: - storeInventory((InventoryHolder) entity); - return; - // START LIVING ENTITY // - // START AGEABLE // - // START TAMEABLE // - case HORSE: - Horse horse = (Horse) entity; - this.horse = new HorseStats(); - this.horse.jump = horse.getJumpStrength(); - this.horse.chest = horse.isCarryingChest(); - this.horse.variant = horse.getVariant(); - this.horse.style = horse.getStyle(); - this.horse.color = horse.getColor(); - storeTameable(horse); - storeAgeable(horse); - storeLiving(horse); - storeInventory(horse); - return; - // END INVENTORY HOLDER // - case WOLF: - case OCELOT: - storeTameable((Tameable) entity); - storeAgeable((Ageable) entity); - storeLiving((LivingEntity) entity); - return; - // END TAMEABLE // - case SHEEP: - Sheep sheep = (Sheep) entity; - this.dataByte = (byte) (sheep.isSheared() ? 1 : 0); - this.dataByte2 = sheep.getColor().getDyeData(); - storeAgeable(sheep); - storeLiving(sheep); - return; - case VILLAGER: - case CHICKEN: - case COW: - case MUSHROOM_COW: - case PIG: - case POLAR_BEAR: - storeAgeable((Ageable) entity); - storeLiving((LivingEntity) entity); - return; - case RABBIT: - this.dataByte = getOrdinal(Rabbit.Type.values(), ((Rabbit) entity).getRabbitType()); - storeAgeable((Ageable) entity); - storeLiving((LivingEntity) entity); - return; - // END AGEABLE // - case GUARDIAN: - this.dataByte = (byte) (((Guardian) entity).isElder() ? 1 : 0); - storeLiving((LivingEntity) entity); - return; - case SKELETON: - this.dataByte = getOrdinal(Skeleton.SkeletonType.values(), - ((Skeleton) entity).getSkeletonType()); - storeLiving((LivingEntity) entity); - return; - case ARMOR_STAND: - ArmorStand stand = (ArmorStand) entity; - this.inventory = - new ItemStack[] {stand.getItemInHand().clone(), stand.getHelmet().clone(), - stand.getChestplate().clone(), stand.getLeggings().clone(), - stand.getBoots().clone()}; - storeLiving(stand); - this.stand = new ArmorStandStats(); - - EulerAngle head = stand.getHeadPose(); - this.stand.head[0] = (float) head.getX(); - this.stand.head[1] = (float) head.getY(); - this.stand.head[2] = (float) head.getZ(); - - EulerAngle body = stand.getBodyPose(); - this.stand.body[0] = (float) body.getX(); - this.stand.body[1] = (float) body.getY(); - this.stand.body[2] = (float) body.getZ(); - - EulerAngle leftLeg = stand.getLeftLegPose(); - this.stand.leftLeg[0] = (float) leftLeg.getX(); - this.stand.leftLeg[1] = (float) leftLeg.getY(); - this.stand.leftLeg[2] = (float) leftLeg.getZ(); - - EulerAngle rightLeg = stand.getRightLegPose(); - this.stand.rightLeg[0] = (float) rightLeg.getX(); - this.stand.rightLeg[1] = (float) rightLeg.getY(); - this.stand.rightLeg[2] = (float) rightLeg.getZ(); - - EulerAngle leftArm = stand.getLeftArmPose(); - this.stand.leftArm[0] = (float) leftArm.getX(); - this.stand.leftArm[1] = (float) leftArm.getY(); - this.stand.leftArm[2] = (float) leftArm.getZ(); - - EulerAngle rightArm = stand.getRightArmPose(); - this.stand.rightArm[0] = (float) rightArm.getX(); - this.stand.rightArm[1] = (float) rightArm.getY(); - this.stand.rightArm[2] = (float) rightArm.getZ(); - - if (stand.hasArms()) { - this.stand.arms = true; - } - if (!stand.hasBasePlate()) { - this.stand.noPlate = true; - } - if (!stand.isVisible()) { - this.stand.invisible = true; - } - if (stand.isSmall()) { - this.stand.small = true; - } - return; - case ENDERMITE: - return; - case BAT: - if (((Bat) entity).isAwake()) { - this.dataByte = (byte) 1; - } else { - this.dataByte = (byte) 0; - } - return; - case ENDER_DRAGON: - EnderDragon entity1 = (EnderDragon) entity; - this.dataByte = (byte) entity1.getPhase().ordinal(); - return; - case GHAST: - case MAGMA_CUBE: - case SQUID: - case PIG_ZOMBIE: - case ZOMBIE: - case WITHER: - case WITCH: - case SPIDER: - case CAVE_SPIDER: - case SILVERFISH: - case GIANT: - case ENDERMAN: - case CREEPER: - case BLAZE: - case SHULKER: - case SNOWMAN: - storeLiving((LivingEntity) entity); - return; - case IRON_GOLEM: - if (((IronGolem) entity).isPlayerCreated()) { - this.dataByte = (byte) 1; - } else { - this.dataByte = (byte) 0; - } - storeLiving((LivingEntity) entity); - // END LIVING // - default: - PlotSquared.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType()); - } + if (depth == 0) { + return; } - - @Override public boolean equals(Object obj) { - return this.hash == obj.hashCode(); + Entity passenger = entity.getPassenger(); + if (passenger != null) { + this.base.passenger = new ReplicatingEntityWrapper(passenger, depth); } - - @Override public int hashCode() { - return this.hash; + this.base.fall = entity.getFallDistance(); + this.base.fire = (short) entity.getFireTicks(); + this.base.age = entity.getTicksLived(); + Vector velocity = entity.getVelocity(); + this.base.vX = velocity.getX(); + this.base.vY = velocity.getY(); + this.base.vZ = velocity.getZ(); + if (depth == 1) { + return; } - - public void storeInventory(InventoryHolder held) { - this.inventory = held.getInventory().getContents().clone(); + if (!entity.hasGravity()) { + this.noGravity = true; } + switch (entity.getType()) { + case BOAT: + Boat boat = (Boat) entity; + this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType()); + return; + case ARROW: + case COMPLEX_PART: + case EGG: + case ENDER_CRYSTAL: + case ENDER_PEARL: + case ENDER_SIGNAL: + case EXPERIENCE_ORB: + case FALLING_BLOCK: + case FIREBALL: + case FIREWORK: + case FISHING_HOOK: + case LEASH_HITCH: + case LIGHTNING: + case MINECART: + case MINECART_COMMAND: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + case PLAYER: + case PRIMED_TNT: + case SLIME: + case SMALL_FIREBALL: + case SNOWBALL: + case MINECART_FURNACE: + case SPLASH_POTION: + case THROWN_EXP_BOTTLE: + case WEATHER: + case WITHER_SKULL: + case UNKNOWN: + case TIPPED_ARROW: + case SPECTRAL_ARROW: + case SHULKER_BULLET: + case DRAGON_FIREBALL: + case LINGERING_POTION: + case AREA_EFFECT_CLOUD: + // Do this stuff later + return; + // MISC // + case DROPPED_ITEM: + Item item = (Item) entity; + this.stack = item.getItemStack(); + return; + case ITEM_FRAME: + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + ItemFrame itemFrame = (ItemFrame) entity; + this.dataByte = getOrdinal(Rotation.values(), itemFrame.getRotation()); + this.stack = itemFrame.getItem().clone(); + return; + case PAINTING: + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + Painting painting = (Painting) entity; + Art art = painting.getArt(); + this.dataByte = getOrdinal(BlockFace.values(), painting.getFacing()); + int h = art.getBlockHeight(); + if (h % 2 == 0) { + this.y -= 1; + } + this.dataString = art.name(); + return; + // END MISC // + // INVENTORY HOLDER // + case MINECART_CHEST: + case MINECART_HOPPER: + storeInventory((InventoryHolder) entity); + return; + // START LIVING ENTITY // + // START AGEABLE // + // START TAMEABLE // + case HORSE: + Horse horse = (Horse) entity; + this.horse = new HorseStats(); + this.horse.jump = horse.getJumpStrength(); + if (horse instanceof ChestedHorse) { + this.horse.chest = ((ChestedHorse) horse).isCarryingChest(); + } else { + this.horse.chest = false; + } + this.horse.variant = horse.getVariant(); + this.horse.style = horse.getStyle(); + this.horse.color = horse.getColor(); + storeTameable(horse); + storeAgeable(horse); + storeLiving(horse); + storeInventory(horse); + return; + // END INVENTORY HOLDER // + case WOLF: + case OCELOT: + storeTameable((Tameable) entity); + storeAgeable((Ageable) entity); + storeLiving((LivingEntity) entity); + return; + // END TAMEABLE // + case SHEEP: + Sheep sheep = (Sheep) entity; + this.dataByte = (byte) (sheep.isSheared() ? 1 : 0); + this.dataByte2 = sheep.getColor().getDyeData(); + storeAgeable(sheep); + storeLiving(sheep); + return; + case VILLAGER: + case CHICKEN: + case COW: + case MUSHROOM_COW: + case PIG: + case POLAR_BEAR: + storeAgeable((Ageable) entity); + storeLiving((LivingEntity) entity); + return; + case RABBIT: + this.dataByte = getOrdinal(Rabbit.Type.values(), ((Rabbit) entity).getRabbitType()); + storeAgeable((Ageable) entity); + storeLiving((LivingEntity) entity); + return; + // END AGEABLE // + case GUARDIAN: + //todo no longer works (possible exception thrown) + this.dataByte = (byte) (((Guardian) entity).isElder() ? 1 : 0); + storeLiving((LivingEntity) entity); + return; + case SKELETON: + //todo no longer works (possible exception thrown) + this.dataByte = getOrdinal(Skeleton.SkeletonType.values(), + ((Skeleton) entity).getSkeletonType()); + storeLiving((LivingEntity) entity); + return; + case ARMOR_STAND: + ArmorStand stand = (ArmorStand) entity; + this.inventory = + new ItemStack[]{stand.getItemInHand().clone(), stand.getHelmet().clone(), + stand.getChestplate().clone(), stand.getLeggings().clone(), + stand.getBoots().clone()}; + storeLiving(stand); + this.stand = new ArmorStandStats(); - void restoreLiving(LivingEntity entity) { - entity.setCanPickupItems(this.lived.loot); - if (this.lived.name != null) { - entity.setCustomName(this.lived.name); - entity.setCustomNameVisible(this.lived.visible); - } - if (this.lived.potions != null && !this.lived.potions.isEmpty()) { - entity.addPotionEffects(this.lived.potions); - } - entity.setRemainingAir(this.lived.air); - entity.setRemoveWhenFarAway(this.lived.persistent); - if (this.lived.equipped) { - this.restoreEquipment(entity); - } - if (this.lived.leashed) { - // TODO leashes - // World world = entity.getWorld(); - // Entity leash = world.spawnEntity(new Location(world, Math.floor(x) + lived.leashX, Math.floor(y) + lived.leashY, Math - // .floor(z) + lived.leashZ), EntityType.LEASH_HITCH); - // entity.setLeashHolder(leash); - } - } + EulerAngle head = stand.getHeadPose(); + this.stand.head[0] = (float) head.getX(); + this.stand.head[1] = (float) head.getY(); + this.stand.head[2] = (float) head.getZ(); - void restoreEquipment(LivingEntity entity) { - EntityEquipment equipment = entity.getEquipment(); - equipment.setItemInMainHand(this.lived.mainHand); - equipment.setItemInOffHand(this.lived.offHand); - equipment.setHelmet(this.lived.helmet); - equipment.setChestplate(this.lived.chestplate); - equipment.setLeggings(this.lived.leggings); - equipment.setBoots(this.lived.boots); - } + EulerAngle body = stand.getBodyPose(); + this.stand.body[0] = (float) body.getX(); + this.stand.body[1] = (float) body.getY(); + this.stand.body[2] = (float) body.getZ(); - private void restoreInventory(InventoryHolder entity) { - try { - entity.getInventory().setContents(this.inventory); - } catch (IllegalArgumentException e) { - PlotSquared.debug("&c[WARN] Failed to restore inventory.\n Reason: " + e.getMessage()); - } - } + EulerAngle leftLeg = stand.getLeftLegPose(); + this.stand.leftLeg[0] = (float) leftLeg.getX(); + this.stand.leftLeg[1] = (float) leftLeg.getY(); + this.stand.leftLeg[2] = (float) leftLeg.getZ(); - public void storeLiving(LivingEntity lived) { - this.lived = new LivingEntityStats(); - this.lived.potions = lived.getActivePotionEffects(); - this.lived.loot = lived.getCanPickupItems(); - this.lived.name = lived.getCustomName(); - this.lived.visible = lived.isCustomNameVisible(); - this.lived.health = (float) lived.getHealth(); - this.lived.air = (short) lived.getRemainingAir(); - this.lived.persistent = lived.getRemoveWhenFarAway(); - this.lived.leashed = lived.isLeashed(); - if (this.lived.leashed) { - Location location = lived.getLeashHolder().getLocation(); - this.lived.leashX = (short) (this.x - location.getBlockX()); - this.lived.leashY = (short) (this.y - location.getBlockY()); - this.lived.leashZ = (short) (this.z - location.getBlockZ()); - } - EntityEquipment equipment = lived.getEquipment(); - this.lived.equipped = equipment != null; - if (this.lived.equipped) { - storeEquipment(equipment); - } - } + EulerAngle rightLeg = stand.getRightLegPose(); + this.stand.rightLeg[0] = (float) rightLeg.getX(); + this.stand.rightLeg[1] = (float) rightLeg.getY(); + this.stand.rightLeg[2] = (float) rightLeg.getZ(); - void storeEquipment(EntityEquipment equipment) { - this.lived.mainHand = equipment.getItemInMainHand().clone(); - this.lived.offHand = equipment.getItemInOffHand().clone(); - this.lived.boots = equipment.getBoots().clone(); - this.lived.leggings = equipment.getLeggings().clone(); - this.lived.chestplate = equipment.getChestplate().clone(); - this.lived.helmet = equipment.getHelmet().clone(); - } + EulerAngle leftArm = stand.getLeftArmPose(); + this.stand.leftArm[0] = (float) leftArm.getX(); + this.stand.leftArm[1] = (float) leftArm.getY(); + this.stand.leftArm[2] = (float) leftArm.getZ(); - private void restoreTameable(Tameable entity) { - if (this.tamed.tamed) { - if (this.tamed.owner != null) { - entity.setTamed(true); - entity.setOwner(this.tamed.owner); - } - } - } + EulerAngle rightArm = stand.getRightArmPose(); + this.stand.rightArm[0] = (float) rightArm.getX(); + this.stand.rightArm[1] = (float) rightArm.getY(); + this.stand.rightArm[2] = (float) rightArm.getZ(); - private void restoreAgeable(Ageable entity) { - if (!this.aged.adult) { - entity.setBaby(); + if (stand.hasArms()) { + this.stand.arms = true; } - entity.setAgeLock(this.aged.locked); - if (this.aged.age > 0) { - entity.setAge(this.aged.age); + if (!stand.hasBasePlate()) { + this.stand.noPlate = true; } + if (!stand.isVisible()) { + this.stand.invisible = true; + } + if (stand.isSmall()) { + this.stand.small = true; + } + return; + case ENDERMITE: + return; + case BAT: + if (((Bat) entity).isAwake()) { + this.dataByte = (byte) 1; + } else { + this.dataByte = (byte) 0; + } + return; + case ENDER_DRAGON: + EnderDragon entity1 = (EnderDragon) entity; + this.dataByte = (byte) entity1.getPhase().ordinal(); + return; + case GHAST: + case MAGMA_CUBE: + case SQUID: + case PIG_ZOMBIE: + case ZOMBIE: + case WITHER: + case WITCH: + case SPIDER: + case CAVE_SPIDER: + case SILVERFISH: + case GIANT: + case ENDERMAN: + case CREEPER: + case BLAZE: + case SHULKER: + case SNOWMAN: + storeLiving((LivingEntity) entity); + return; + case IRON_GOLEM: + if (((IronGolem) entity).isPlayerCreated()) { + this.dataByte = (byte) 1; + } else { + this.dataByte = (byte) 0; + } + storeLiving((LivingEntity) entity); + // END LIVING // + default: + PlotSquared.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType()); } + } - public void storeAgeable(Ageable aged) { - this.aged = new AgeableStats(); - this.aged.age = aged.getAge(); - this.aged.locked = aged.getAgeLock(); - this.aged.adult = aged.isAdult(); - } + @Override + public boolean equals(Object obj) { + return this.hash == obj.hashCode(); + } - public void storeTameable(Tameable tamed) { - this.tamed = new TameableStats(); - this.tamed.owner = tamed.getOwner(); - this.tamed.tamed = tamed.isTamed(); - } + @Override + public int hashCode() { + return this.hash; + } - @Override public Entity spawn(World world, int xOffset, int zOffset) { - Location location = new Location(world, this.x + xOffset, this.y, this.z + zOffset); - location.setYaw(this.yaw); - location.setPitch(this.pitch); - if (!this.getType().isSpawnable()) { - return null; - } - Entity entity; - switch (this.getType()) { - case DROPPED_ITEM: - return world.dropItem(location, this.stack); - case PLAYER: - case LEASH_HITCH: - return null; - case ITEM_FRAME: - entity = world.spawn(location, ItemFrame.class); - break; - case PAINTING: - entity = world.spawn(location, Painting.class); - break; - default: - entity = world.spawnEntity(location, this.getType()); - break; - } - if (this.depth == 0) { - return entity; - } - if (this.base.passenger != null) { - try { - entity.setPassenger(this.base.passenger.spawn(world, xOffset, zOffset)); - } catch (Exception ignored) { - } - } - if (this.base.fall != 0) { - entity.setFallDistance(this.base.fall); - } - if (this.base.fire != 0) { - entity.setFireTicks(this.base.fire); - } - if (this.base.age != 0) { - entity.setTicksLived(this.base.age); - } - entity.setVelocity(new Vector(this.base.vX, this.base.vY, this.base.vZ)); - if (this.depth == 1) { - return entity; - } - if (this.noGravity) { - entity.setGravity(false); - } - switch (entity.getType()) { - case BOAT: - Boat boat = (Boat) entity; - boat.setWoodType(TreeSpecies.values()[dataByte]); - return entity; - case SLIME: - ((Slime) entity).setSize(this.dataByte); - return entity; - case ARROW: - case COMPLEX_PART: - case EGG: - case ENDER_CRYSTAL: - case ENDER_PEARL: - case ENDER_SIGNAL: - case DROPPED_ITEM: - case EXPERIENCE_ORB: - case FALLING_BLOCK: - case FIREBALL: - case FIREWORK: - case FISHING_HOOK: - case LEASH_HITCH: - case LIGHTNING: - case MINECART: - case MINECART_COMMAND: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - case PLAYER: - case PRIMED_TNT: - case SMALL_FIREBALL: - case SNOWBALL: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case WEATHER: - case TIPPED_ARROW: - case SPECTRAL_ARROW: - case SHULKER_BULLET: - case LINGERING_POTION: - case AREA_EFFECT_CLOUD: - case DRAGON_FIREBALL: - case WITHER_SKULL: - case MINECART_FURNACE: - case UNKNOWN: - // Do this stuff later - return entity; - // MISC // - case ITEM_FRAME: - ItemFrame itemframe = (ItemFrame) entity; - itemframe.setRotation(Rotation.values()[this.dataByte]); - itemframe.setItem(this.stack); - return entity; - case PAINTING: - Painting painting = (Painting) entity; - painting.setFacingDirection(BlockFace.values()[this.dataByte], true); - painting.setArt(Art.getByName(this.dataString), true); - return entity; - // END MISC // - // INVENTORY HOLDER // - case MINECART_CHEST: - case MINECART_HOPPER: - restoreInventory((InventoryHolder) entity); - return entity; - // START LIVING ENTITY // - // START AGEABLE // - // START TAMEABLE // - case HORSE: - Horse horse = (Horse) entity; - horse.setJumpStrength(this.horse.jump); - horse.setCarryingChest(this.horse.chest); - horse.setVariant(this.horse.variant); - horse.setStyle(this.horse.style); - horse.setColor(this.horse.color); - restoreTameable(horse); - restoreAgeable(horse); - restoreLiving(horse); - restoreInventory(horse); - return entity; - // END INVENTORY HOLDER // - case WOLF: - case OCELOT: - restoreTameable((Tameable) entity); - restoreAgeable((Ageable) entity); - restoreLiving((LivingEntity) entity); - return entity; - // END AGEABLE // - case SHEEP: - Sheep sheep = (Sheep) entity; - if (this.dataByte == 1) { - sheep.setSheared(true); - } - if (this.dataByte2 != 0) { - sheep.setColor(DyeColor.getByDyeData(this.dataByte2)); - } - restoreAgeable(sheep); - restoreLiving(sheep); - return sheep; - case VILLAGER: - case CHICKEN: - case COW: - case POLAR_BEAR: - case MUSHROOM_COW: - case PIG: - restoreAgeable((Ageable) entity); - restoreLiving((LivingEntity) entity); - return entity; - // END AGEABLE // - case RABBIT: - if (this.dataByte != 0) { - ((Rabbit) entity).setRabbitType(Rabbit.Type.values()[this.dataByte]); - } - restoreAgeable((Ageable) entity); - restoreLiving((LivingEntity) entity); - return entity; - case GUARDIAN: - if (this.dataByte != 0) { - ((Guardian) entity).setElder(true); - } - restoreLiving((LivingEntity) entity); - return entity; - case SKELETON: - if (this.dataByte != 0) { - ((Skeleton) entity) - .setSkeletonType(Skeleton.SkeletonType.values()[this.dataByte]); - } - storeLiving((LivingEntity) entity); - return entity; - case ARMOR_STAND: - // CHECK positions - ArmorStand stand = (ArmorStand) entity; - if (this.inventory[0] != null) { - stand.setItemInHand(this.inventory[0]); - } - if (this.inventory[1] != null) { - stand.setHelmet(this.inventory[1]); - } - if (this.inventory[2] != null) { - stand.setChestplate(this.inventory[2]); - } - if (this.inventory[3] != null) { - stand.setLeggings(this.inventory[3]); - } - if (this.inventory[4] != null) { - stand.setBoots(this.inventory[4]); - } - if (this.stand.head[0] != 0 || this.stand.head[1] != 0 || this.stand.head[2] != 0) { - EulerAngle pose = - new EulerAngle(this.stand.head[0], this.stand.head[1], this.stand.head[2]); - stand.setHeadPose(pose); - } - if (this.stand.body[0] != 0 || this.stand.body[1] != 0 || this.stand.body[2] != 0) { - EulerAngle pose = - new EulerAngle(this.stand.body[0], this.stand.body[1], this.stand.body[2]); - stand.setBodyPose(pose); - } - if (this.stand.leftLeg[0] != 0 || this.stand.leftLeg[1] != 0 - || this.stand.leftLeg[2] != 0) { - EulerAngle pose = new EulerAngle(this.stand.leftLeg[0], this.stand.leftLeg[1], - this.stand.leftLeg[2]); - stand.setLeftLegPose(pose); - } - if (this.stand.rightLeg[0] != 0 || this.stand.rightLeg[1] != 0 - || this.stand.rightLeg[2] != 0) { - EulerAngle pose = new EulerAngle(this.stand.rightLeg[0], this.stand.rightLeg[1], - this.stand.rightLeg[2]); - stand.setRightLegPose(pose); - } - if (this.stand.leftArm[0] != 0 || this.stand.leftArm[1] != 0 - || this.stand.leftArm[2] != 0) { - EulerAngle pose = new EulerAngle(this.stand.leftArm[0], this.stand.leftArm[1], - this.stand.leftArm[2]); - stand.setLeftArmPose(pose); - } - if (this.stand.rightArm[0] != 0 || this.stand.rightArm[1] != 0 - || this.stand.rightArm[2] != 0) { - EulerAngle pose = new EulerAngle(this.stand.rightArm[0], this.stand.rightArm[1], - this.stand.rightArm[2]); - stand.setRightArmPose(pose); - } - if (this.stand.invisible) { - stand.setVisible(false); - } - if (this.stand.arms) { - stand.setArms(true); - } - if (this.stand.noPlate) { - stand.setBasePlate(false); - } - if (this.stand.small) { - stand.setSmall(true); - } - restoreLiving(stand); - return stand; - case BAT: - if (this.dataByte != 0) { - ((Bat) entity).setAwake(true); - } - restoreLiving((LivingEntity) entity); - return entity; - case ENDER_DRAGON: - if (this.dataByte != 0) { - ((EnderDragon) entity).setPhase(EnderDragon.Phase.values()[this.dataByte]); - } - restoreLiving((LivingEntity) entity); - return entity; - case ENDERMITE: - case GHAST: - case MAGMA_CUBE: - case SQUID: - case PIG_ZOMBIE: - case ZOMBIE: - case WITHER: - case WITCH: - case SPIDER: - case CAVE_SPIDER: - case SILVERFISH: - case GIANT: - case ENDERMAN: - case CREEPER: - case BLAZE: - case SNOWMAN: - case SHULKER: - restoreLiving((LivingEntity) entity); - return entity; - case IRON_GOLEM: - if (this.dataByte != 0) { - ((IronGolem) entity).setPlayerCreated(true); - } - restoreLiving((LivingEntity) entity); - return entity; - default: - PlotSquared.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType()); - return entity; - // END LIVING - } - } + public void storeInventory(InventoryHolder held) { + this.inventory = held.getInventory().getContents().clone(); + } - public void saveEntity() { + void restoreLiving(LivingEntity entity) { + entity.setCanPickupItems(this.lived.loot); + if (this.lived.name != null) { + entity.setCustomName(this.lived.name); + entity.setCustomNameVisible(this.lived.visible); } + if (this.lived.potions != null && !this.lived.potions.isEmpty()) { + entity.addPotionEffects(this.lived.potions); + } + entity.setRemainingAir(this.lived.air); + entity.setRemoveWhenFarAway(this.lived.persistent); + if (this.lived.equipped) { + this.restoreEquipment(entity); + } + if (this.lived.leashed) { + // TODO leashes + // World world = entity.getWorld(); + // Entity leash = world.spawnEntity(new Location(world, Math.floor(x) + lived.leashX, Math.floor(y) + lived.leashY, Math + // .floor(z) + lived.leashZ), EntityType.LEASH_HITCH); + // entity.setLeashHolder(leash); + } + } - private byte getOrdinal(Object[] list, Object value) { - for (byte i = 0; i < list.length; i++) { - if (list[i].equals(value)) { - return i; - } - } - return 0; + void restoreEquipment(LivingEntity entity) { + EntityEquipment equipment = entity.getEquipment(); + equipment.setItemInMainHand(this.lived.mainHand); + equipment.setItemInOffHand(this.lived.offHand); + equipment.setHelmet(this.lived.helmet); + equipment.setChestplate(this.lived.chestplate); + equipment.setLeggings(this.lived.leggings); + equipment.setBoots(this.lived.boots); + } + + private void restoreInventory(InventoryHolder entity) { + try { + entity.getInventory().setContents(this.inventory); + } catch (IllegalArgumentException e) { + PlotSquared.debug("&c[WARN] Failed to restore inventory.\n Reason: " + e.getMessage()); } + } + + public void storeLiving(LivingEntity lived) { + this.lived = new LivingEntityStats(); + this.lived.potions = lived.getActivePotionEffects(); + this.lived.loot = lived.getCanPickupItems(); + this.lived.name = lived.getCustomName(); + this.lived.visible = lived.isCustomNameVisible(); + this.lived.health = (float) lived.getHealth(); + this.lived.air = (short) lived.getRemainingAir(); + this.lived.persistent = lived.getRemoveWhenFarAway(); + this.lived.leashed = lived.isLeashed(); + if (this.lived.leashed) { + Location location = lived.getLeashHolder().getLocation(); + this.lived.leashX = (short) (this.x - location.getBlockX()); + this.lived.leashY = (short) (this.y - location.getBlockY()); + this.lived.leashZ = (short) (this.z - location.getBlockZ()); + } + EntityEquipment equipment = lived.getEquipment(); + this.lived.equipped = equipment != null; + if (this.lived.equipped) { + storeEquipment(equipment); + } + } + + void storeEquipment(EntityEquipment equipment) { + this.lived.mainHand = equipment.getItemInMainHand().clone(); + this.lived.offHand = equipment.getItemInOffHand().clone(); + this.lived.boots = equipment.getBoots().clone(); + this.lived.leggings = equipment.getLeggings().clone(); + this.lived.chestplate = equipment.getChestplate().clone(); + this.lived.helmet = equipment.getHelmet().clone(); + } + + private void restoreTameable(Tameable entity) { + if (this.tamed.tamed) { + if (this.tamed.owner != null) { + entity.setTamed(true); + entity.setOwner(this.tamed.owner); + } + } + } + + private void restoreAgeable(Ageable entity) { + if (!this.aged.adult) { + entity.setBaby(); + } + entity.setAgeLock(this.aged.locked); + if (this.aged.age > 0) { + entity.setAge(this.aged.age); + } + } + + public void storeAgeable(Ageable aged) { + this.aged = new AgeableStats(); + this.aged.age = aged.getAge(); + this.aged.locked = aged.getAgeLock(); + this.aged.adult = aged.isAdult(); + } + + public void storeTameable(Tameable tamed) { + this.tamed = new TameableStats(); + this.tamed.owner = tamed.getOwner(); + this.tamed.tamed = tamed.isTamed(); + } + + @Override + public Entity spawn(World world, int xOffset, int zOffset) { + Location location = new Location(world, this.x + xOffset, this.y, this.z + zOffset); + location.setYaw(this.yaw); + location.setPitch(this.pitch); + if (!this.getType().isSpawnable()) { + return null; + } + Entity entity; + switch (this.getType()) { + case DROPPED_ITEM: + return world.dropItem(location, this.stack); + case PLAYER: + case LEASH_HITCH: + return null; + case ITEM_FRAME: + entity = world.spawn(location, ItemFrame.class); + break; + case PAINTING: + entity = world.spawn(location, Painting.class); + break; + default: + entity = world.spawnEntity(location, this.getType()); + break; + } + if (this.depth == 0) { + return entity; + } + if (this.base.passenger != null) { + entity.addPassenger(this.base.passenger.spawn(world, xOffset, zOffset)); + } + if (this.base.fall != 0) { + entity.setFallDistance(this.base.fall); + } + if (this.base.fire != 0) { + entity.setFireTicks(this.base.fire); + } + if (this.base.age != 0) { + entity.setTicksLived(this.base.age); + } + entity.setVelocity(new Vector(this.base.vX, this.base.vY, this.base.vZ)); + if (this.depth == 1) { + return entity; + } + if (this.noGravity) { + entity.setGravity(false); + } + switch (entity.getType()) { + case BOAT: + Boat boat = (Boat) entity; + boat.setWoodType(TreeSpecies.values()[dataByte]); + return entity; + case SLIME: + ((Slime) entity).setSize(this.dataByte); + return entity; + case ARROW: + case COMPLEX_PART: + case EGG: + case ENDER_CRYSTAL: + case ENDER_PEARL: + case ENDER_SIGNAL: + case DROPPED_ITEM: + case EXPERIENCE_ORB: + case FALLING_BLOCK: + case FIREBALL: + case FIREWORK: + case FISHING_HOOK: + case LEASH_HITCH: + case LIGHTNING: + case MINECART: + case MINECART_COMMAND: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + case PLAYER: + case PRIMED_TNT: + case SMALL_FIREBALL: + case SNOWBALL: + case SPLASH_POTION: + case THROWN_EXP_BOTTLE: + case WEATHER: + case TIPPED_ARROW: + case SPECTRAL_ARROW: + case SHULKER_BULLET: + case LINGERING_POTION: + case AREA_EFFECT_CLOUD: + case DRAGON_FIREBALL: + case WITHER_SKULL: + case MINECART_FURNACE: + case UNKNOWN: + // Do this stuff later + return entity; + // MISC // + case ITEM_FRAME: + ItemFrame itemframe = (ItemFrame) entity; + itemframe.setRotation(Rotation.values()[this.dataByte]); + itemframe.setItem(this.stack); + return entity; + case PAINTING: + Painting painting = (Painting) entity; + painting.setFacingDirection(BlockFace.values()[this.dataByte], true); + painting.setArt(Art.getByName(this.dataString), true); + return entity; + // END MISC // + // INVENTORY HOLDER // + case MINECART_CHEST: + case MINECART_HOPPER: + restoreInventory((InventoryHolder) entity); + return entity; + // START LIVING ENTITY // + // START AGEABLE // + // START TAMEABLE // + case HORSE: + Horse horse = (Horse) entity; + horse.setJumpStrength(this.horse.jump); + if (horse instanceof ChestedHorse && this.horse.chest) { + ((ChestedHorse) horse).setCarryingChest(true); + } + //todo broken in 1.13 possible exception thrown + horse.setVariant(this.horse.variant); + horse.setStyle(this.horse.style); + horse.setColor(this.horse.color); + restoreTameable(horse); + restoreAgeable(horse); + restoreLiving(horse); + restoreInventory(horse); + return entity; + // END INVENTORY HOLDER // + case WOLF: + case OCELOT: + restoreTameable((Tameable) entity); + restoreAgeable((Ageable) entity); + restoreLiving((LivingEntity) entity); + return entity; + // END AGEABLE // + case SHEEP: + Sheep sheep = (Sheep) entity; + if (this.dataByte == 1) { + sheep.setSheared(true); + } + if (this.dataByte2 != 0) { + sheep.setColor(DyeColor.getByDyeData(this.dataByte2)); + } + restoreAgeable(sheep); + restoreLiving(sheep); + return sheep; + case VILLAGER: + case CHICKEN: + case COW: + case POLAR_BEAR: + case MUSHROOM_COW: + case PIG: + restoreAgeable((Ageable) entity); + restoreLiving((LivingEntity) entity); + return entity; + // END AGEABLE // + case RABBIT: + if (this.dataByte != 0) { + ((Rabbit) entity).setRabbitType(Rabbit.Type.values()[this.dataByte]); + } + restoreAgeable((Ageable) entity); + restoreLiving((LivingEntity) entity); + return entity; + case GUARDIAN: + if (this.dataByte != 0) { + //todo broken in 1.13 possible exception thrown + + ((Guardian) entity).setElder(true); + } + restoreLiving((LivingEntity) entity); + return entity; + case SKELETON: + if (this.dataByte != 0) { + //todo broken in 1.13 possible exception thrown + ((Skeleton) entity) + .setSkeletonType(Skeleton.SkeletonType.values()[this.dataByte]); + } + storeLiving((LivingEntity) entity); + return entity; + case ARMOR_STAND: + // CHECK positions + ArmorStand stand = (ArmorStand) entity; + if (this.inventory[0] != null) { + stand.setItemInHand(this.inventory[0]); + } + if (this.inventory[1] != null) { + stand.setHelmet(this.inventory[1]); + } + if (this.inventory[2] != null) { + stand.setChestplate(this.inventory[2]); + } + if (this.inventory[3] != null) { + stand.setLeggings(this.inventory[3]); + } + if (this.inventory[4] != null) { + stand.setBoots(this.inventory[4]); + } + if (this.stand.head[0] != 0 || this.stand.head[1] != 0 || this.stand.head[2] != 0) { + EulerAngle pose = + new EulerAngle(this.stand.head[0], this.stand.head[1], this.stand.head[2]); + stand.setHeadPose(pose); + } + if (this.stand.body[0] != 0 || this.stand.body[1] != 0 || this.stand.body[2] != 0) { + EulerAngle pose = + new EulerAngle(this.stand.body[0], this.stand.body[1], this.stand.body[2]); + stand.setBodyPose(pose); + } + if (this.stand.leftLeg[0] != 0 || this.stand.leftLeg[1] != 0 + || this.stand.leftLeg[2] != 0) { + EulerAngle pose = new EulerAngle(this.stand.leftLeg[0], this.stand.leftLeg[1], + this.stand.leftLeg[2]); + stand.setLeftLegPose(pose); + } + if (this.stand.rightLeg[0] != 0 || this.stand.rightLeg[1] != 0 + || this.stand.rightLeg[2] != 0) { + EulerAngle pose = new EulerAngle(this.stand.rightLeg[0], this.stand.rightLeg[1], + this.stand.rightLeg[2]); + stand.setRightLegPose(pose); + } + if (this.stand.leftArm[0] != 0 || this.stand.leftArm[1] != 0 + || this.stand.leftArm[2] != 0) { + EulerAngle pose = new EulerAngle(this.stand.leftArm[0], this.stand.leftArm[1], + this.stand.leftArm[2]); + stand.setLeftArmPose(pose); + } + if (this.stand.rightArm[0] != 0 || this.stand.rightArm[1] != 0 + || this.stand.rightArm[2] != 0) { + EulerAngle pose = new EulerAngle(this.stand.rightArm[0], this.stand.rightArm[1], + this.stand.rightArm[2]); + stand.setRightArmPose(pose); + } + if (this.stand.invisible) { + stand.setVisible(false); + } + if (this.stand.arms) { + stand.setArms(true); + } + if (this.stand.noPlate) { + stand.setBasePlate(false); + } + if (this.stand.small) { + stand.setSmall(true); + } + restoreLiving(stand); + return stand; + case BAT: + if (this.dataByte != 0) { + ((Bat) entity).setAwake(true); + } + restoreLiving((LivingEntity) entity); + return entity; + case ENDER_DRAGON: + if (this.dataByte != 0) { + ((EnderDragon) entity).setPhase(EnderDragon.Phase.values()[this.dataByte]); + } + restoreLiving((LivingEntity) entity); + return entity; + case ENDERMITE: + case GHAST: + case MAGMA_CUBE: + case SQUID: + case PIG_ZOMBIE: + case ZOMBIE: + case WITHER: + case WITCH: + case SPIDER: + case CAVE_SPIDER: + case SILVERFISH: + case GIANT: + case ENDERMAN: + case CREEPER: + case BLAZE: + case SNOWMAN: + case SHULKER: + restoreLiving((LivingEntity) entity); + return entity; + case IRON_GOLEM: + if (this.dataByte != 0) { + ((IronGolem) entity).setPlayerCreated(true); + } + restoreLiving((LivingEntity) entity); + return entity; + default: + PlotSquared.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType()); + return entity; + // END LIVING + } + } + + public void saveEntity() { + } + + private byte getOrdinal(Object[] list, Object value) { + for (byte i = 0; i < list.length; i++) { + if (list[i].equals(value)) { + return i; + } + } + return 0; + } } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/schematic/StateWrapper.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/schematic/StateWrapper.java index 3557f33af..d1eaa9081 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/schematic/StateWrapper.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/object/schematic/StateWrapper.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import org.bukkit.inventory.meta.Damageable; public class StateWrapper { @@ -241,7 +242,7 @@ public class StateWrapper { public Map serializeItem(ItemStack item) { Map data = new HashMap<>(); data.put("id", new StringTag(item.getType().name())); - data.put("Damage", new ShortTag(item.getDurability())); + data.put("Damage", new ShortTag((short) ((Damageable)item.getItemMeta()).getDamage())); data.put("Count", new ByteTag((byte) item.getAmount())); if (!item.getEnchantments().isEmpty()) { List enchantmentList = new ArrayList<>(); diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/titles/TitleManager.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/titles/TitleManager.java index f4c249f97..df16d07a2 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/titles/TitleManager.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/titles/TitleManager.java @@ -187,11 +187,7 @@ public abstract class TitleManager { throws IllegalArgumentException, ReflectiveOperationException, SecurityException; private Class getPrimitiveType(Class clazz) { - if (CORRESPONDING_TYPES.containsKey(clazz)) { - return CORRESPONDING_TYPES.get(clazz); - } else { - return clazz; - } + return CORRESPONDING_TYPES.getOrDefault(clazz, clazz); } private Class[] toPrimitiveTypeArray(Class[] classes) { diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/titles/TitleManager_1_11.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/titles/TitleManager_1_11.java index 92155ba45..817417087 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/titles/TitleManager_1_11.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/titles/TitleManager_1_11.java @@ -335,7 +335,7 @@ public class TitleManager_1_11 { } private Class getPrimitiveType(Class clazz) { - return CORRESPONDING_TYPES.containsKey(clazz) ? CORRESPONDING_TYPES.get(clazz) : clazz; + return CORRESPONDING_TYPES.getOrDefault(clazz, clazz); } private Class[] toPrimitiveTypeArray(Class[] classes) { diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitEventUtil.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitEventUtil.java index 808dabb7a..34e392a27 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitEventUtil.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitEventUtil.java @@ -99,10 +99,6 @@ public final class BukkitEventUtil extends EventUtil { new PlotChangeOwnerEvent(getPlayer(initiator), plot, oldOwner, newOwner, hasOldOwner)); } - @Override public boolean callFlagRemove(Flag flag, Object object, PlotCluster cluster) { - return callEvent(new ClusterFlagRemoveEvent(flag, cluster)); - } - @Override @Nullable public Rating callRating(PlotPlayer player, Plot plot, Rating rating) { PlotRateEvent event = new PlotRateEvent(player, rating, plot); Bukkit.getServer().getPluginManager().callEvent(event); diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitInventoryUtil.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitInventoryUtil.java index c40e13d09..d855f9e39 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitInventoryUtil.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitInventoryUtil.java @@ -83,7 +83,7 @@ public class BukkitInventoryUtil extends InventoryUtil { } // int id = item.getTypeId(); Material id = item.getType(); - short data = item.getDurability(); + //short data = item.getDurability(); int amount = item.getAmount(); String name = null; String[] lore = null; @@ -94,7 +94,7 @@ public class BukkitInventoryUtil extends InventoryUtil { } if (meta.hasLore()) { List itemLore = meta.getLore(); - lore = itemLore.toArray(new String[itemLore.size()]); + lore = itemLore.toArray(new String[0]); } } return new PlotItemStack(id.name(), amount, name, lore); diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/SendChunk.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/SendChunk.java index f0987b219..41e515cc7 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/SendChunk.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/SendChunk.java @@ -1,5 +1,7 @@ package com.github.intellectualsites.plotsquared.bukkit.util; +import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getRefClass; + import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer; import com.github.intellectualsites.plotsquared.plot.PlotSquared; import com.github.intellectualsites.plotsquared.plot.object.ChunkLoc; @@ -12,52 +14,49 @@ import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefFie import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefMethod; import com.github.intellectualsites.plotsquared.plot.util.TaskManager; import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.entity.Player; - import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map.Entry; - -import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getRefClass; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.entity.Player; /** - * An utility that can be used to send chunks, rather than using bukkit code - * to do so (uses heavy NMS). + * An utility that can be used to send chunks, rather than using bukkit code to do so (uses heavy + * NMS). */ public class SendChunk { - private final RefMethod methodGetHandlePlayer; - private final RefMethod methodGetHandleChunk; - private final RefConstructor mapChunk; - private final RefField connection; - private final RefMethod send; - private final RefMethod methodInitLighting; + private final RefMethod methodGetHandlePlayer; + private final RefMethod methodGetHandleChunk; + private final RefConstructor mapChunk; + private final RefField connection; + private final RefMethod send; + private final RefMethod methodInitLighting; - /** - * Constructor. - */ - public SendChunk() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException { - RefConstructor tempMapChunk; - RefClass classCraftPlayer = getRefClass("{cb}.entity.CraftPlayer"); - this.methodGetHandlePlayer = classCraftPlayer.getMethod("getHandle"); - RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); - this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle"); - RefClass classChunk = getRefClass("{nms}.Chunk"); - this.methodInitLighting = classChunk.getMethod("initLighting"); - RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk"); - tempMapChunk = classMapChunk.getConstructor(classChunk.getRealClass(), int.class); - this.mapChunk = tempMapChunk; - RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer"); - this.connection = classEntityPlayer.getField("playerConnection"); - RefClass classPacket = getRefClass("{nms}.Packet"); - RefClass classConnection = getRefClass("{nms}.PlayerConnection"); - this.send = classConnection.getMethod("sendPacket", classPacket.getRealClass()); - } + /** + * Constructor. + */ + public SendChunk() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException { + RefConstructor tempMapChunk; + RefClass classCraftPlayer = getRefClass("{cb}.entity.CraftPlayer"); + this.methodGetHandlePlayer = classCraftPlayer.getMethod("getHandle"); + RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); + this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle"); + RefClass classChunk = getRefClass("{nms}.Chunk"); + this.methodInitLighting = classChunk.getMethod("initLighting"); + RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk"); + tempMapChunk = classMapChunk.getConstructor(classChunk.getRealClass(), int.class); + this.mapChunk = tempMapChunk; + RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer"); + this.connection = classEntityPlayer.getField("playerConnection"); + RefClass classPacket = getRefClass("{nms}.Packet"); + RefClass classConnection = getRefClass("{nms}.PlayerConnection"); + this.send = classConnection.getMethod("sendPacket", classPacket.getRealClass()); + } public void sendChunk(Collection input) { HashSet chunks = new HashSet<>(input); @@ -97,54 +96,52 @@ public class SendChunk { Player player = ((BukkitPlayer) pp).player; Object entity = this.methodGetHandlePlayer.of(player).call(); - for (Chunk chunk : list) { - int dx = Math.abs(cx - chunk.getX()); - int dz = Math.abs(cz - chunk.getZ()); - if ((dx > view) || (dz > view)) { - continue; - } - Object c = this.methodGetHandleChunk.of(chunk).call(); - chunks.remove(chunk); - Object con = this.connection.of(entity).get(); - Object packet = null; - try { - packet = this.mapChunk.create(c, 65535); - } catch (Exception ignored) { - } - if (packet == null) { - PlotSquared.debug("Error with PacketPlayOutMapChunk reflection."); - } - this.send.of(con).call(packet); - } + for (Chunk chunk : list) { + int dx = Math.abs(cx - chunk.getX()); + int dz = Math.abs(cz - chunk.getZ()); + if ((dx > view) || (dz > view)) { + continue; } - for (final Chunk chunk : chunks) { - TaskManager.runTask(new Runnable() { - @Override public void run() { - try { - chunk.unload(true, false); - } catch (Throwable ignored) { - String worldName = chunk.getWorld().getName(); - PlotSquared.debug( - "$4Could not save chunk: " + worldName + ';' + chunk.getX() + ";" - + chunk.getZ()); - PlotSquared - .debug("$3 - $4File may be open in another process (e.g. MCEdit)"); - PlotSquared.debug("$3 - $4" + worldName + "/level.dat or " + worldName - + "/level_old.dat may be corrupt (try repairing or removing these)"); - } - } - }); + Object c = this.methodGetHandleChunk.of(chunk).call(); + chunks.remove(chunk); + Object con = this.connection.of(entity).get(); + Object packet = null; + try { + packet = this.mapChunk.create(c, 65535); + } catch (Exception ignored) { } + if (packet == null) { + PlotSquared.debug("Error with PacketPlayOutMapChunk reflection."); + } + this.send.of(con).call(packet); + } } + for (final Chunk chunk : chunks) { + TaskManager.runTask(() -> { + try { + chunk.unload(true, false); + } catch (Throwable ignored) { + String worldName = chunk.getWorld().getName(); + PlotSquared.debug( + "$4Could not save chunk: " + worldName + ';' + chunk.getX() + ";" + + chunk.getZ()); + PlotSquared + .debug("$3 - $4File may be open in another process (e.g. MCEdit)"); + PlotSquared.debug("$3 - $4" + worldName + "/level.dat or " + worldName + + "/level_old.dat may be corrupt (try repairing or removing these)"); + } + }); + } + } - public void sendChunk(String worldName, Collection chunkLocations) { - World myWorld = Bukkit.getWorld(worldName); - ArrayList chunks = new ArrayList<>(); - for (ChunkLoc loc : chunkLocations) { - if (myWorld.isChunkLoaded(loc.x, loc.z)) { - chunks.add(myWorld.getChunkAt(loc.x, loc.z)); - } - } - sendChunk(chunks); + public void sendChunk(String worldName, Collection chunkLocations) { + World myWorld = Bukkit.getWorld(worldName); + ArrayList chunks = new ArrayList<>(); + for (ChunkLoc loc : chunkLocations) { + if (myWorld.isChunkLoaded(loc.x, loc.z)) { + chunks.add(myWorld.getChunkAt(loc.x, loc.z)); + } } + sendChunk(chunks); + } } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/block/BukkitLocalQueue.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/block/BukkitLocalQueue.java index 77518690d..eee467db1 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/block/BukkitLocalQueue.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/block/BukkitLocalQueue.java @@ -192,8 +192,7 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue { for (int x = 0; x < lc.biomes.length; x++) { String[] biomes2 = lc.biomes[x]; if (biomes2 != null) { - for (int y = 0; y < biomes2.length; y++) { - String biomeStr = biomes2[y]; + for (String biomeStr : biomes2) { if (biomeStr != null) { if (last == null || !StringMan.isEqual(last, biomeStr)) { biome = Biome.valueOf(biomeStr.toUpperCase()); diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/DefaultUUIDWrapper.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/DefaultUUIDWrapper.java index 3660bef92..aaa94dbeb 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/DefaultUUIDWrapper.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/DefaultUUIDWrapper.java @@ -5,12 +5,13 @@ import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer; import com.github.intellectualsites.plotsquared.plot.object.OfflinePlotPlayer; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper; +import java.util.Arrays; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import java.util.UUID; -public class DefaultUUIDWrapper extends UUIDWrapper { +public class DefaultUUIDWrapper implements UUIDWrapper { @Override public UUID getUUID(PlotPlayer player) { return ((BukkitPlayer) player).player.getUniqueId(); @@ -30,11 +31,8 @@ public class DefaultUUIDWrapper extends UUIDWrapper { @Override public OfflinePlotPlayer[] getOfflinePlayers() { OfflinePlayer[] ops = Bukkit.getOfflinePlayers(); - BukkitOfflinePlayer[] toReturn = new BukkitOfflinePlayer[ops.length]; - for (int i = 0; i < ops.length; i++) { - toReturn[i] = new BukkitOfflinePlayer(ops[i]); - } - return toReturn; + return Arrays.stream(ops).map(BukkitOfflinePlayer::new) + .toArray(BukkitOfflinePlayer[]::new); } @Override public OfflinePlotPlayer getOfflinePlayer(String name) { diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/FileUUIDHandler.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/FileUUIDHandler.java index 2223feceb..a8e2278b4 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/FileUUIDHandler.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/FileUUIDHandler.java @@ -47,204 +47,200 @@ public class FileUUIDHandler extends UUIDHandlerImplementation { } else { world = worlds.get(0).getName(); } - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - PlotSquared.debug(C.PREFIX + "&6Starting player data caching for: " + world); - File uuidFile = new File(PlotSquared.get().IMP.getDirectory(), "uuids.txt"); - if (uuidFile.exists()) { - try { - List lines = - Files.readAllLines(uuidFile.toPath(), StandardCharsets.UTF_8); - for (String line : lines) { - try { - line = line.trim(); - if (line.isEmpty()) { - continue; - } - line = line.replaceAll("[\\|][0-9]+[\\|][0-9]+[\\|]", ""); - String[] split = line.split("\\|"); - String name = split[0]; - if (name.isEmpty() || (name.length() > 16) || !StringMan - .isAlphanumericUnd(name)) { - continue; - } - UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); - if (uuid == null) { - continue; - } - UUIDHandler.add(new StringWrapper(name), uuid); - } catch (Exception e2) { - e2.printStackTrace(); + TaskManager.runTaskAsync(() -> { + PlotSquared.debug(C.PREFIX + "&6Starting player data caching for: " + world); + File uuidFile = new File(PlotSquared.get().IMP.getDirectory(), "uuids.txt"); + if (uuidFile.exists()) { + try { + List lines = + Files.readAllLines(uuidFile.toPath(), StandardCharsets.UTF_8); + for (String line : lines) { + try { + line = line.trim(); + if (line.isEmpty()) { + continue; } + line = line.replaceAll("[\\|][0-9]+[\\|][0-9]+[\\|]", ""); + String[] split = line.split("\\|"); + String name = split[0]; + if (name.isEmpty() || (name.length() > 16) || !StringMan + .isAlphanumericUnd(name)) { + continue; + } + UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); + if (uuid == null) { + continue; + } + UUIDHandler.add(new StringWrapper(name), uuid); + } catch (Exception e2) { + e2.printStackTrace(); } - } catch (IOException e) { - e.printStackTrace(); } + } catch (IOException e) { + e.printStackTrace(); } - HashBiMap toAdd = - HashBiMap.create(new HashMap()); - if (Settings.UUID.NATIVE_UUID_PROVIDER) { - HashSet all = UUIDHandler.getAllUUIDS(); - PlotSquared.debug("&aFast mode UUID caching enabled!"); - File playerDataFolder = - new File(container, world + File.separator + "playerdata"); - String[] dat = playerDataFolder.list(new DatFileFilter()); - boolean check = all.isEmpty(); - if (dat != null) { - for (String current : dat) { - String s = current.replaceAll(".dat$", ""); - try { - UUID uuid = UUID.fromString(s); - if (check || all.remove(uuid)) { - File file = new File(playerDataFolder, current); - NbtFactory.NbtCompound compound = NbtFactory - .fromStream(new FileInputStream(file), - NbtFactory.StreamOptions.GZIP_COMPRESSION); - if (!compound.containsKey("bukkit")) { - PlotSquared.debug("ERROR: Player data (" + uuid.toString() - + ".dat) does not contain the the key \"bukkit\""); - } else { - NbtFactory.NbtCompound bukkit = - (NbtFactory.NbtCompound) compound.get("bukkit"); - String name = (String) bukkit.get("lastKnownName"); - long last = (long) bukkit.get("lastPlayed"); - long first = (long) bukkit.get("firstPlayed"); - if (ExpireManager.IMP != null) { - ExpireManager.IMP.storeDate(uuid, last); - ExpireManager.IMP.storeAccountAge(uuid, last - first); - } - toAdd.put(new StringWrapper(name), uuid); + } + HashBiMap toAdd = + HashBiMap.create(new HashMap<>()); + if (Settings.UUID.NATIVE_UUID_PROVIDER) { + HashSet all = UUIDHandler.getAllUUIDS(); + PlotSquared.debug("&aFast mode UUID caching enabled!"); + File playerDataFolder = + new File(container, world + File.separator + "playerdata"); + String[] dat = playerDataFolder.list(new DatFileFilter()); + boolean check = all.isEmpty(); + if (dat != null) { + for (String current : dat) { + String s = current.replaceAll(".dat$", ""); + try { + UUID uuid = UUID.fromString(s); + if (check || all.remove(uuid)) { + File file = new File(playerDataFolder, current); + NbtFactory.NbtCompound compound = NbtFactory + .fromStream(new FileInputStream(file), + NbtFactory.StreamOptions.GZIP_COMPRESSION); + if (!compound.containsKey("bukkit")) { + PlotSquared.debug("ERROR: Player data (" + uuid.toString() + + ".dat) does not contain the the key \"bukkit\""); + } else { + NbtFactory.NbtCompound bukkit = + (NbtFactory.NbtCompound) compound.get("bukkit"); + String name = (String) bukkit.get("lastKnownName"); + long last = (long) bukkit.get("lastPlayed"); + long first = (long) bukkit.get("firstPlayed"); + if (ExpireManager.IMP != null) { + ExpireManager.IMP.storeDate(uuid, last); + ExpireManager.IMP.storeAccountAge(uuid, last - first); } - } - } catch (Exception e) { - e.printStackTrace(); - PlotSquared.debug(C.PREFIX + "Invalid playerdata: " + current); - } - } - } - add(toAdd); - if (all.isEmpty()) { - if (whenDone != null) { - whenDone.run(); - } - return; - } else { - PlotSquared.debug("Failed to cache: " + all.size() - + " uuids - slowly processing all files"); - } - } - HashSet worlds = Sets.newHashSet(world, "world"); - HashSet uuids = new HashSet<>(); - HashSet names = new HashSet<>(); - File playerDataFolder = null; - for (String worldName : worlds) { - // Getting UUIDs - playerDataFolder = - new File(container, worldName + File.separator + "playerdata"); - String[] dat = playerDataFolder.list(new DatFileFilter()); - if ((dat != null) && (dat.length != 0)) { - for (String current : dat) { - String s = current.replaceAll(".dat$", ""); - try { - UUID uuid = UUID.fromString(s); - uuids.add(uuid); - } catch (Exception ignored) { - PlotSquared.debug(C.PREFIX + "Invalid PlayerData: " + current); - } - } - break; - } - // Getting names - File playersFolder = new File(worldName + File.separator + "players"); - dat = playersFolder.list(new DatFileFilter()); - if ((dat != null) && (dat.length != 0)) { - for (String current : dat) { - names.add(current.replaceAll(".dat$", "")); - } - break; - } - } - for (UUID uuid : uuids) { - try { - File file = - new File(playerDataFolder + File.separator + uuid.toString() + ".dat"); - if (!file.exists()) { - continue; - } - NbtFactory.NbtCompound compound = NbtFactory - .fromStream(new FileInputStream(file), - NbtFactory.StreamOptions.GZIP_COMPRESSION); - if (!compound.containsKey("bukkit")) { - PlotSquared.debug("ERROR: Player data (" + uuid.toString() - + ".dat) does not contain the the key \"bukkit\""); - } else { - NbtFactory.NbtCompound bukkit = - (NbtFactory.NbtCompound) compound.get("bukkit"); - String name = (String) bukkit.get("lastKnownName"); - StringWrapper wrap = new StringWrapper(name); - if (!toAdd.containsKey(wrap)) { - long last = (long) bukkit.get("lastPlayed"); - long first = (long) bukkit.get("firstPlayed"); - if (Settings.UUID.OFFLINE) { - if (Settings.UUID.FORCE_LOWERCASE && !name.toLowerCase() - .equals(name)) { - uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); - } else { - long most = (long) compound.get("UUIDMost"); - long least = (long) compound.get("UUIDLeast"); - uuid = new UUID(most, least); - } - } - if (ExpireManager.IMP != null) { - ExpireManager.IMP.storeDate(uuid, last); - ExpireManager.IMP.storeAccountAge(uuid, last - first); - } - toAdd.put(wrap, uuid); - } - } - } catch (Exception ignored) { - PlotSquared - .debug(C.PREFIX + "&6Invalid PlayerData: " + uuid.toString() + ".dat"); - } - } - for (String name : names) { - UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); - StringWrapper nameWrap = new StringWrapper(name); - toAdd.put(nameWrap, uuid); - } - - if (getUUIDMap().isEmpty()) { - for (OfflinePlotPlayer op : FileUUIDHandler.this.uuidWrapper - .getOfflinePlayers()) { - long last = op.getLastPlayed(); - if (last != 0) { - String name = op.getName(); - StringWrapper wrap = new StringWrapper(name); - if (!toAdd.containsKey(wrap)) { - UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(op); - toAdd.put(wrap, uuid); - if (ExpireManager.IMP != null) { - ExpireManager.IMP.storeDate(uuid, last); + toAdd.put(new StringWrapper(name), uuid); } } + } catch (Exception e) { + e.printStackTrace(); + PlotSquared.debug(C.PREFIX + "Invalid playerdata: " + current); } } } add(toAdd); - if (whenDone != null) { - whenDone.run(); + if (all.isEmpty()) { + if (whenDone != null) { + whenDone.run(); + } + return; + } else { + PlotSquared.debug("Failed to cache: " + all.size() + + " uuids - slowly processing all files"); } } + HashSet worlds1 = Sets.newHashSet(world, "world"); + HashSet uuids = new HashSet<>(); + HashSet names = new HashSet<>(); + File playerDataFolder = null; + for (String worldName : worlds1) { + // Getting UUIDs + playerDataFolder = + new File(container, worldName + File.separator + "playerdata"); + String[] dat = playerDataFolder.list(new DatFileFilter()); + if ((dat != null) && (dat.length != 0)) { + for (String current : dat) { + String s = current.replaceAll(".dat$", ""); + try { + UUID uuid = UUID.fromString(s); + uuids.add(uuid); + } catch (Exception ignored) { + PlotSquared.debug(C.PREFIX + "Invalid PlayerData: " + current); + } + } + break; + } + // Getting names + File playersFolder = new File(worldName + File.separator + "players"); + dat = playersFolder.list(new DatFileFilter()); + if ((dat != null) && (dat.length != 0)) { + for (String current : dat) { + names.add(current.replaceAll(".dat$", "")); + } + break; + } + } + for (UUID uuid : uuids) { + try { + File file = + new File(playerDataFolder + File.separator + uuid.toString() + ".dat"); + if (!file.exists()) { + continue; + } + NbtFactory.NbtCompound compound = NbtFactory + .fromStream(new FileInputStream(file), + NbtFactory.StreamOptions.GZIP_COMPRESSION); + if (!compound.containsKey("bukkit")) { + PlotSquared.debug("ERROR: Player data (" + uuid.toString() + + ".dat) does not contain the the key \"bukkit\""); + } else { + NbtFactory.NbtCompound bukkit = + (NbtFactory.NbtCompound) compound.get("bukkit"); + String name = (String) bukkit.get("lastKnownName"); + StringWrapper wrap = new StringWrapper(name); + if (!toAdd.containsKey(wrap)) { + long last = (long) bukkit.get("lastPlayed"); + long first = (long) bukkit.get("firstPlayed"); + if (Settings.UUID.OFFLINE) { + if (Settings.UUID.FORCE_LOWERCASE && !name.toLowerCase() + .equals(name)) { + uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); + } else { + long most = (long) compound.get("UUIDMost"); + long least = (long) compound.get("UUIDLeast"); + uuid = new UUID(most, least); + } + } + if (ExpireManager.IMP != null) { + ExpireManager.IMP.storeDate(uuid, last); + ExpireManager.IMP.storeAccountAge(uuid, last - first); + } + toAdd.put(wrap, uuid); + } + } + } catch (Exception ignored) { + PlotSquared + .debug(C.PREFIX + "&6Invalid PlayerData: " + uuid.toString() + ".dat"); + } + } + for (String name : names) { + UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); + StringWrapper nameWrap = new StringWrapper(name); + toAdd.put(nameWrap, uuid); + } + + if (getUUIDMap().isEmpty()) { + for (OfflinePlotPlayer op : FileUUIDHandler.this.uuidWrapper + .getOfflinePlayers()) { + long last = op.getLastPlayed(); + if (last != 0) { + String name = op.getName(); + StringWrapper wrap = new StringWrapper(name); + if (!toAdd.containsKey(wrap)) { + UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(op); + toAdd.put(wrap, uuid); + if (ExpireManager.IMP != null) { + ExpireManager.IMP.storeDate(uuid, last); + } + } + } + } + } + add(toAdd); + if (whenDone != null) { + whenDone.run(); + } }); return true; } @Override public void fetchUUID(final String name, final RunnableVal ifFetch) { - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - ifFetch.value = FileUUIDHandler.this.uuidWrapper.getUUID(name); - TaskManager.runTask(ifFetch); - } + TaskManager.runTaskAsync(() -> { + ifFetch.value = FileUUIDHandler.this.uuidWrapper.getUUID(name); + TaskManager.runTask(ifFetch); }); } } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/OfflineUUIDWrapper.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/OfflineUUIDWrapper.java index c44fa6e72..c06c7a3cc 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/OfflineUUIDWrapper.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/OfflineUUIDWrapper.java @@ -9,6 +9,7 @@ import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler; import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper; import com.google.common.base.Charsets; import com.google.common.collect.BiMap; +import java.util.Arrays; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.Server; @@ -19,7 +20,7 @@ import java.lang.reflect.Method; import java.util.Collection; import java.util.UUID; -public class OfflineUUIDWrapper extends UUIDWrapper { +public class OfflineUUIDWrapper implements UUIDWrapper { private final Object[] arg = new Object[0]; private Method getOnline = null; @@ -59,18 +60,15 @@ public class OfflineUUIDWrapper extends UUIDWrapper { return new BukkitOfflinePlayer(op); } } - for (OfflinePlayer player : Bukkit.getOfflinePlayers()) { - if (getUUID(player).equals(uuid)) { - return new BukkitOfflinePlayer(player); - } - } - return null; + return Arrays.stream(Bukkit.getOfflinePlayers()) + .filter(player -> getUUID(player).equals(uuid)).findFirst() + .map(BukkitOfflinePlayer::new).orElse(null); } public Player[] getOnlinePlayers() { if (this.getOnline == null) { Collection onlinePlayers = Bukkit.getOnlinePlayers(); - return onlinePlayers.toArray(new Player[onlinePlayers.size()]); + return onlinePlayers.toArray(new Player[0]); } try { Object players = this.getOnline.invoke(Bukkit.getServer(), this.arg); @@ -79,13 +77,13 @@ public class OfflineUUIDWrapper extends UUIDWrapper { } else { @SuppressWarnings("unchecked") Collection p = (Collection) players; - return p.toArray(new Player[p.size()]); + return p.toArray(new Player[0]); } } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException ignored) { PlotSquared.debug("Failed to resolve online players"); this.getOnline = null; Collection onlinePlayers = Bukkit.getOnlinePlayers(); - return onlinePlayers.toArray(new Player[onlinePlayers.size()]); + return onlinePlayers.toArray(new Player[0]); } } @@ -95,11 +93,8 @@ public class OfflineUUIDWrapper extends UUIDWrapper { @Override public OfflinePlotPlayer[] getOfflinePlayers() { OfflinePlayer[] ops = Bukkit.getOfflinePlayers(); - BukkitOfflinePlayer[] toReturn = new BukkitOfflinePlayer[ops.length]; - for (int i = 0; i < ops.length; i++) { - toReturn[i] = new BukkitOfflinePlayer(ops[i]); - } - return toReturn; + return Arrays.stream(ops).map(BukkitOfflinePlayer::new) + .toArray(BukkitOfflinePlayer[]::new); } @Override public OfflinePlotPlayer getOfflinePlayer(String name) { diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/SQLUUIDHandler.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/SQLUUIDHandler.java index 1c9a30bba..04f0b146c 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/SQLUUIDHandler.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/uuid/SQLUUIDHandler.java @@ -71,96 +71,90 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation { if (!super.startCaching(whenDone)) { return false; } - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - try { - HashBiMap toAdd = - HashBiMap.create(new HashMap()); - try (PreparedStatement statement = getConnection() - .prepareStatement("SELECT `uuid`, `username` FROM `usercache`"); - ResultSet resultSet = statement.executeQuery()) { - while (resultSet.next()) { - StringWrapper username = - new StringWrapper(resultSet.getString("username")); - UUID uuid = UUID.fromString(resultSet.getString("uuid")); - toAdd.put(new StringWrapper(username.value), uuid); - } + TaskManager.runTaskAsync(() -> { + try { + HashBiMap toAdd = + HashBiMap.create(new HashMap<>()); + try (PreparedStatement statement = getConnection() + .prepareStatement("SELECT `uuid`, `username` FROM `usercache`"); + ResultSet resultSet = statement.executeQuery()) { + while (resultSet.next()) { + StringWrapper username = + new StringWrapper(resultSet.getString("username")); + UUID uuid = UUID.fromString(resultSet.getString("uuid")); + toAdd.put(new StringWrapper(username.value), uuid); } - add(toAdd); - // This should be called as long as there are some unknown plots - final ArrayDeque toFetch = new ArrayDeque<>(); - for (UUID u : UUIDHandler.getAllUUIDS()) { - if (!uuidExists(u)) { - toFetch.add(u); - } + } + add(toAdd); + // This should be called as long as there are some unknown plots + final ArrayDeque toFetch = new ArrayDeque<>(); + for (UUID u : UUIDHandler.getAllUUIDS()) { + if (!uuidExists(u)) { + toFetch.add(u); } - if (toFetch.isEmpty()) { + } + if (toFetch.isEmpty()) { + if (whenDone != null) { + whenDone.run(); + } + return; + } + FileUUIDHandler fileHandler = + new FileUUIDHandler(SQLUUIDHandler.this.uuidWrapper); + fileHandler.startCaching(() -> { + // If the file based UUID handler didn't cache it, then we can't cache offline mode + // Also, trying to cache based on files again, is useless as that's what the file based uuid cacher does + if (Settings.UUID.OFFLINE) { if (whenDone != null) { whenDone.run(); } return; } - FileUUIDHandler fileHandler = - new FileUUIDHandler(SQLUUIDHandler.this.uuidWrapper); - fileHandler.startCaching(new Runnable() { - @Override public void run() { - // If the file based UUID handler didn't cache it, then we can't cache offline mode - // Also, trying to cache based on files again, is useless as that's what the file based uuid cacher does - if (Settings.UUID.OFFLINE) { - if (whenDone != null) { - whenDone.run(); - } - return; - } - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - while (!toFetch.isEmpty()) { - try { - for (int i = 0; - i < Math.min(500, toFetch.size()); i++) { - UUID uuid = toFetch.pop(); - HttpURLConnection connection = - (HttpURLConnection) new URL( - SQLUUIDHandler.this.PROFILE_URL + uuid - .toString().replace("-", "")) - .openConnection(); - try (InputStream con = connection - .getInputStream()) { - InputStreamReader reader = - new InputStreamReader(con); - JSONObject response = - (JSONObject) SQLUUIDHandler.this.jsonParser - .parse(reader); - String name = (String) response.get("name"); - if (name != null) { - add(new StringWrapper(name), uuid); - } - } - connection.disconnect(); - } - } catch (IOException | ParseException e) { - PlotSquared.debug( - "Invalid response from Mojang: Some UUIDs will be cached later. (`unknown` until then or player joins)"); - } - try { - Thread.sleep(INTERVAL * 50); - } catch (InterruptedException e) { - e.printStackTrace(); - break; + TaskManager.runTaskAsync(() -> { + while (!toFetch.isEmpty()) { + try { + for (int i = 0; + i < Math.min(500, toFetch.size()); i++) { + UUID uuid = toFetch.pop(); + HttpURLConnection connection = + (HttpURLConnection) new URL( + SQLUUIDHandler.this.PROFILE_URL + uuid + .toString().replace("-", "")) + .openConnection(); + try (InputStream con = connection + .getInputStream()) { + InputStreamReader reader = + new InputStreamReader(con); + JSONObject response = + (JSONObject) SQLUUIDHandler.this.jsonParser + .parse(reader); + String name = (String) response.get("name"); + if (name != null) { + add(new StringWrapper(name), uuid); } } - if (whenDone != null) { - whenDone.run(); - } - return; + connection.disconnect(); } - }); + } catch (IOException | ParseException e) { + PlotSquared.debug( + "Invalid response from Mojang: Some UUIDs will be cached later. (`unknown` until then or player joins)"); + } + try { + Thread.sleep(INTERVAL * 50); + } catch (InterruptedException e) { + e.printStackTrace(); + break; + } } + if (whenDone != null) { + whenDone.run(); + } + return; }); - } catch (SQLException e) { - throw new SQLUUIDHandlerException("Couldn't select :s", e); - } + }); + } catch (SQLException e) { + throw new SQLUUIDHandlerException("Couldn't select :s", e); } }); return true; @@ -172,34 +166,32 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation { if (ifFetch == null) { return; } - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - try { - URL url = new URL(SQLUUIDHandler.this.PROFILE_URL); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setUseCaches(false); - connection.setDoInput(true); - connection.setDoOutput(true); - String body = JSONArray.toJSONString(Collections.singletonList(name)); - OutputStream stream = connection.getOutputStream(); - stream.write(body.getBytes()); - stream.flush(); - stream.close(); - JSONArray array = (JSONArray) SQLUUIDHandler.this.jsonParser - .parse(new InputStreamReader(connection.getInputStream())); - JSONObject jsonProfile = (JSONObject) array.get(0); - String id = (String) jsonProfile.get("id"); - String name = (String) jsonProfile.get("name"); - ifFetch.value = UUID.fromString( - id.substring(0, 8) + '-' + id.substring(8, 12) + '-' + id.substring(12, 16) - + '-' + id.substring(16, 20) + '-' + id.substring(20, 32)); - } catch (IOException | ParseException e) { - e.printStackTrace(); - } - TaskManager.runTask(ifFetch); + TaskManager.runTaskAsync(() -> { + try { + URL url = new URL(SQLUUIDHandler.this.PROFILE_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setUseCaches(false); + connection.setDoInput(true); + connection.setDoOutput(true); + String body = JSONArray.toJSONString(Collections.singletonList(name)); + OutputStream stream = connection.getOutputStream(); + stream.write(body.getBytes()); + stream.flush(); + stream.close(); + JSONArray array = (JSONArray) SQLUUIDHandler.this.jsonParser + .parse(new InputStreamReader(connection.getInputStream())); + JSONObject jsonProfile = (JSONObject) array.get(0); + String id = (String) jsonProfile.get("id"); + String name1 = (String) jsonProfile.get("name"); + ifFetch.value = UUID.fromString( + id.substring(0, 8) + '-' + id.substring(8, 12) + '-' + id.substring(12, 16) + + '-' + id.substring(16, 20) + '-' + id.substring(20, 32)); + } catch (IOException | ParseException e) { + e.printStackTrace(); } + TaskManager.runTask(ifFetch); }); } @@ -215,18 +207,16 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation { @Override public boolean add(final StringWrapper name, final UUID uuid) { // Ignoring duplicates if (super.add(name, uuid)) { - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - try (PreparedStatement statement = getConnection().prepareStatement( - "REPLACE INTO usercache (`uuid`, `username`) VALUES(?, ?)")) { - statement.setString(1, uuid.toString()); - statement.setString(2, name.toString()); - statement.execute(); - PlotSquared - .debug(C.PREFIX + "&cAdded '&6" + uuid + "&c' - '&6" + name + "&c'"); - } catch (SQLException e) { - e.printStackTrace(); - } + TaskManager.runTaskAsync(() -> { + try (PreparedStatement statement = getConnection().prepareStatement( + "REPLACE INTO usercache (`uuid`, `username`) VALUES(?, ?)")) { + statement.setString(1, uuid.toString()); + statement.setString(2, name.toString()); + statement.execute(); + PlotSquared + .debug(C.PREFIX + "&cAdded '&6" + uuid + "&c' - '&6" + name + "&c'"); + } catch (SQLException e) { + e.printStackTrace(); } }); return true; @@ -239,18 +229,16 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation { */ @Override public void rename(final UUID uuid, final StringWrapper name) { super.rename(uuid, name); - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - try (PreparedStatement statement = getConnection() - .prepareStatement("UPDATE usercache SET `username`=? WHERE `uuid`=?")) { - statement.setString(1, name.value); - statement.setString(2, uuid.toString()); - statement.execute(); - PlotSquared.debug( - C.PREFIX + "Name change for '" + uuid + "' to '" + name.value + '\''); - } catch (SQLException e) { - e.printStackTrace(); - } + TaskManager.runTaskAsync(() -> { + try (PreparedStatement statement = getConnection() + .prepareStatement("UPDATE usercache SET `username`=? WHERE `uuid`=?")) { + statement.setString(1, name.value); + statement.setString(2, uuid.toString()); + statement.execute(); + PlotSquared.debug( + C.PREFIX + "Name change for '" + uuid + "' to '" + name.value + '\''); + } catch (SQLException e) { + e.printStackTrace(); } }); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/Configuration.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/Configuration.java index c2b4b4d95..8f3446487 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/Configuration.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/Configuration.java @@ -1,6 +1,7 @@ package com.github.intellectualsites.plotsquared.configuration; import java.util.Map; +import javax.annotation.Nonnull; /** * Represents a source of configurable options and settings. @@ -20,7 +21,7 @@ public interface Configuration extends ConfigurationSection { * @param value Value to set the default to. * @throws IllegalArgumentException Thrown if path is null. */ - @Override void addDefault(String path, Object value); + @Override void addDefault(@Nonnull String path, Object value); /** * Sets the default values of the given paths as provided. diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/ConfigurationOptions.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/ConfigurationOptions.java index 5d13920e4..f86016031 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/ConfigurationOptions.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/ConfigurationOptions.java @@ -31,7 +31,7 @@ class ConfigurationOptions { * * @return Path separator */ - public char pathSeparator() { + char pathSeparator() { return pathSeparator; } @@ -64,7 +64,7 @@ class ConfigurationOptions { * * @return Whether or not defaults are directly copied */ - public boolean copyDefaults() { + boolean copyDefaults() { return copyDefaults; } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/ConfigurationSection.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/ConfigurationSection.java index 0752dfb57..ac9d2d536 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/ConfigurationSection.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/ConfigurationSection.java @@ -3,6 +3,7 @@ package com.github.intellectualsites.plotsquared.configuration; import java.util.List; import java.util.Map; import java.util.Set; +import javax.annotation.Nonnull; /** * Represents a section of a {@link Configuration}. @@ -52,7 +53,7 @@ public interface ConfigurationSection { * default or being set. * @throws IllegalArgumentException Thrown when path is {@code null}. */ - boolean contains(String path); + boolean contains(@Nonnull String path); /** * Checks if this {@link ConfigurationSection} has a value set for the @@ -66,7 +67,7 @@ public interface ConfigurationSection { * having a default. * @throws IllegalArgumentException Thrown when path is {@code null}. */ - boolean isSet(String path); + boolean isSet(@Nonnull String path); /** * Gets the path of this {@link ConfigurationSection} from its root {@link @@ -151,7 +152,7 @@ public interface ConfigurationSection { * @param defaultValue The default value to return if the path is not found. * @return Requested Object. */ - Object get(String path, Object defaultValue); + Object getOrDefault(@Nonnull String path, Object defaultValue); /** * Sets the specified path to the given value. @@ -644,5 +645,5 @@ public interface ConfigurationSection { * @param value Value to set the default to * @throws IllegalArgumentException Thrown if path is {@code null} */ - void addDefault(String path, Object value); + void addDefault(@Nonnull String path, Object value); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/MemoryConfiguration.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/MemoryConfiguration.java index 20131cbe1..d44c0f3b2 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/MemoryConfiguration.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/MemoryConfiguration.java @@ -1,6 +1,7 @@ package com.github.intellectualsites.plotsquared.configuration; import java.util.Map; +import javax.annotation.Nonnull; /** * This is a {@link Configuration} implementation that does not save or load @@ -28,7 +29,7 @@ public class MemoryConfiguration extends MemorySection implements Configuration this.defaults = defaults; } - @Override public void addDefault(String path, Object value) { + @Override public void addDefault(@Nonnull String path, Object value) { if (this.defaults == null) { this.defaults = new MemoryConfiguration(); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/MemorySection.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/MemorySection.java index 0f87931f4..73f50476d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/MemorySection.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/MemorySection.java @@ -1,777 +1,817 @@ package com.github.intellectualsites.plotsquared.configuration; import java.util.*; +import javax.annotation.Nonnull; /** * A type of {@link ConfigurationSection} that is stored in memory. */ public class MemorySection implements ConfigurationSection { - protected final Map map = new LinkedHashMap<>(); - private final Configuration root; - private final ConfigurationSection parent; - private final String path; - private final String fullPath; + protected final Map map = new LinkedHashMap<>(); + private final Configuration root; + private final ConfigurationSection parent; + private final String path; + private final String fullPath; - /** - * Creates an empty MemorySection for use as a root {@link Configuration} - * section. - * - *

Note that calling this without being yourself a {@link Configuration} - * will throw an exception! - * - * @throws IllegalStateException Thrown if this is not a {@link - * Configuration} root. - */ - protected MemorySection() { - if (!(this instanceof Configuration)) { - throw new IllegalStateException( - "Cannot construct a root MemorySection when not a Configuration"); - } - - this.path = ""; - this.fullPath = ""; - this.parent = null; - this.root = (Configuration) this; + /** + * Creates an empty MemorySection for use as a root {@link Configuration} section. + * + *

Note that calling this without being yourself a {@link Configuration} + * will throw an exception! + * + * @throws IllegalStateException Thrown if this is not a {@link Configuration} root. + */ + protected MemorySection() { + if (!(this instanceof Configuration)) { + throw new IllegalStateException( + "Cannot construct a root MemorySection when not a Configuration"); } - /** - * Creates an empty MemorySection with the specified parent and path. - * - * @param parent Parent section that contains this own section. - * @param path Path that you may access this section from via the root - * {@link Configuration}. - * @throws IllegalArgumentException Thrown is parent or path is null, or - * if parent contains no root Configuration. - */ - protected MemorySection(ConfigurationSection parent, String path) { - this.path = path; - this.parent = parent; - this.root = parent.getRoot(); + this.path = ""; + this.fullPath = ""; + this.parent = null; + this.root = (Configuration) this; + } - if (this.root == null) { - throw new NullPointerException("Path may not be orphaned"); - } + /** + * Creates an empty MemorySection with the specified parent and path. + * + * @param parent Parent section that contains this own section. + * @param path Path that you may access this section from via the root {@link Configuration}. + * @throws IllegalArgumentException Thrown is parent or path is null, or if parent contains no + * root Configuration. + */ + protected MemorySection(ConfigurationSection parent, String path) { + this.path = path; + this.parent = parent; + this.root = parent.getRoot(); - this.fullPath = createPath(parent, path); + if (this.root == null) { + throw new NullPointerException("Path may not be orphaned"); } - public static double toDouble(Object obj, double def) { - if (obj instanceof Number) { - return ((Number) obj).doubleValue(); - } - if (obj instanceof String) { - try { - return Double.parseDouble((String) obj); - } catch (NumberFormatException ignored) { - } - } else if (obj instanceof List) { - List val = (List) obj; - if (!val.isEmpty()) { - return toDouble(val.get(0), def); - } - } - return def; + this.fullPath = createPath(parent, path); + } + + public static double toDouble(Object obj, double def) { + if (obj instanceof Number) { + return ((Number) obj).doubleValue(); + } + if (obj instanceof String) { + try { + return Double.parseDouble((String) obj); + } catch (NumberFormatException ignored) { + } + } else if (obj instanceof List) { + List val = (List) obj; + if (!val.isEmpty()) { + return toDouble(val.get(0), def); + } + } + return def; + } + + public static int toInt(Object obj, int def) { + if (obj instanceof Number) { + return ((Number) obj).intValue(); + } + if (obj instanceof String) { + try { + return Integer.parseInt((String) obj); + } catch (NumberFormatException ignored) { + } + } else if (obj instanceof List) { + List val = (List) obj; + if (!val.isEmpty()) { + return toInt(val.get(0), def); + } + } + return def; + } + + public static long toLong(Object obj, long def) { + if (obj instanceof Number) { + return ((Number) obj).longValue(); + } + if (obj instanceof String) { + try { + return Long.parseLong((String) obj); + } catch (NumberFormatException ignored) { + } + } else if (obj instanceof List) { + List val = (List) obj; + if (!val.isEmpty()) { + return toLong(val.get(0), def); + } + } + return def; + } + + /** + * Creates a full path to the given {@link ConfigurationSection} from its root {@link + * Configuration}. + * + *

You may use this method for any given {@link ConfigurationSection}, not + * only {@link MemorySection}. + * + * @param section Section to create a path for. + * @param key Name of the specified section. + * @return Full path of the section from its root. + */ + public static String createPath(ConfigurationSection section, String key) { + return createPath(section, key, section.getRoot()); + } + + /** + * Creates a relative path to the given {@link ConfigurationSection} from the given relative + * section. + * + *

You may use this method for any given {@link ConfigurationSection}, not + * only {@link MemorySection}. + * + * @param section Section to create a path for. + * @param key Name of the specified section. + * @param relativeTo Section to create the path relative to. + * @return Full path of the section from its root. + */ + public static String createPath(ConfigurationSection section, String key, + ConfigurationSection relativeTo) { + Configuration root = section.getRoot(); + if (root == null) { + throw new IllegalStateException("Cannot create path without a root"); + } + char separator = root.options().pathSeparator(); + + StringBuilder builder = new StringBuilder(); + for (ConfigurationSection parent = section; + (parent != null) && (parent != relativeTo); parent = parent.getParent()) { + if (builder.length() > 0) { + builder.insert(0, separator); + } + + builder.insert(0, parent.getName()); } - public static int toInt(Object obj, int def) { - if (obj instanceof Number) { - return ((Number) obj).intValue(); - } - if (obj instanceof String) { - try { - return Integer.parseInt((String) obj); - } catch (NumberFormatException ignored) { - } - } else if (obj instanceof List) { - List val = (List) obj; - if (!val.isEmpty()) { - return toInt(val.get(0), def); - } - } - return def; + if ((key != null) && !key.isEmpty()) { + if (builder.length() > 0) { + builder.append(separator); + } + + builder.append(key); } - public static long toLong(Object obj, long def) { - if (obj instanceof Number) { - return ((Number) obj).longValue(); - } - if (obj instanceof String) { - try { - return Long.parseLong((String) obj); - } catch (NumberFormatException ignored) { - } - } else if (obj instanceof List) { - List val = (List) obj; - if (!val.isEmpty()) { - return toLong(val.get(0), def); - } - } - return def; + return builder.toString(); + } + + @Override + public Set getKeys(boolean deep) { + Set result = new LinkedHashSet<>(); + + Configuration root = getRoot(); + if ((root != null) && root.options().copyDefaults()) { + ConfigurationSection defaults = getDefaultSection(); + + if (defaults != null) { + result.addAll(defaults.getKeys(deep)); + } } - /** - * Creates a full path to the given {@link ConfigurationSection} from its - * root {@link Configuration}. - * - *

You may use this method for any given {@link ConfigurationSection}, not - * only {@link MemorySection}. - * - * @param section Section to create a path for. - * @param key Name of the specified section. - * @return Full path of the section from its root. - */ - public static String createPath(ConfigurationSection section, String key) { - return createPath(section, key, section.getRoot()); + mapChildrenKeys(result, this, deep); + + return result; + } + + @Override + public Map getValues(boolean deep) { + Map result = new LinkedHashMap<>(); + + Configuration root = getRoot(); + if ((root != null) && root.options().copyDefaults()) { + ConfigurationSection defaults = getDefaultSection(); + + if (defaults != null) { + result.putAll(defaults.getValues(deep)); + } } - /** - * Creates a relative path to the given {@link ConfigurationSection} from - * the given relative section. - * - *

You may use this method for any given {@link ConfigurationSection}, not - * only {@link MemorySection}. - * - * @param section Section to create a path for. - * @param key Name of the specified section. - * @param relativeTo Section to create the path relative to. - * @return Full path of the section from its root. - */ - public static String createPath(ConfigurationSection section, String key, - ConfigurationSection relativeTo) { - Configuration root = section.getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot create path without a root"); - } - char separator = root.options().pathSeparator(); + mapChildrenValues(result, this, deep); - StringBuilder builder = new StringBuilder(); - for (ConfigurationSection parent = section; - (parent != null) && (parent != relativeTo); parent = parent.getParent()) { - if (builder.length() > 0) { - builder.insert(0, separator); - } + return result; + } - builder.insert(0, parent.getName()); - } + @Override + public boolean contains(@Nonnull String path) { + return get(path) != null; + } - if ((key != null) && !key.isEmpty()) { - if (builder.length() > 0) { - builder.append(separator); - } + @Override + public boolean isSet(@Nonnull String path) { + Configuration root = getRoot(); + if (root == null) { + return false; + } + if (root.options().copyDefaults()) { + return contains(path); + } + return getOrDefault(path, null) != null; + } - builder.append(key); - } + @Override + public String getCurrentPath() { + return this.fullPath; + } - return builder.toString(); + @Override + public String getName() { + return this.path; + } + + @Override + public Configuration getRoot() { + return this.root; + } + + @Override + public ConfigurationSection getParent() { + return this.parent; + } + + @Override + public void addDefault(@Nonnull String path, Object value) { + Configuration root = getRoot(); + if (root == null) { + throw new IllegalStateException("Cannot add default without root"); + } + if (root == this) { + throw new UnsupportedOperationException( + "Unsupported addDefault(String, Object) implementation"); + } + root.addDefault(createPath(this, path), value); + } + + @Override + public ConfigurationSection getDefaultSection() { + Configuration root = getRoot(); + Configuration defaults = root == null ? null : root.getDefaults(); + + if (defaults != null) { + if (defaults.isConfigurationSection(getCurrentPath())) { + return defaults.getConfigurationSection(getCurrentPath()); + } } - @Override public Set getKeys(boolean deep) { - Set result = new LinkedHashSet<>(); + return null; + } - Configuration root = getRoot(); - if ((root != null) && root.options().copyDefaults()) { - ConfigurationSection defaults = getDefaultSection(); + @Override + public void set(String path, Object value) { + Configuration root = getRoot(); + if (root == null) { + throw new IllegalStateException("Cannot use section without a root"); + } - if (defaults != null) { - result.addAll(defaults.getKeys(deep)); - } - } + char separator = root.options().pathSeparator(); + // i1 is the leading (higher) index + // i2 is the trailing (lower) index + int i1 = -1; + int i2; + ConfigurationSection section = this; + while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { + String node = path.substring(i2, i1); + ConfigurationSection subSection = section.getConfigurationSection(node); + if (subSection == null) { + section = section.createSection(node); + } else { + section = subSection; + } + } - mapChildrenKeys(result, this, deep); + String key = path.substring(i2); + if (section == this) { + if (value == null) { + this.map.remove(key); + } else { + this.map.put(key, value); + } + } else { + section.set(key, value); + } + } + @Override + public Object get(String path) { + return getOrDefault(path, getDefault(path)); + } + + @Override + public Object getOrDefault(@Nonnull String path, Object defaultValue) { + if (path.isEmpty()) { + return this; + } + + Configuration root = getRoot(); + if (root == null) { + throw new IllegalStateException("Cannot access section without a root"); + } + + char separator = root.options().pathSeparator(); + // i1 is the leading (higher) index + // i2 is the trailing (lower) index + int i1 = -1; + int i2; + ConfigurationSection section = this; + while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { + section = section.getConfigurationSection(path.substring(i2, i1)); + if (section == null) { + return defaultValue; + } + } + + String key = path.substring(i2); + if (section == this) { + Object result = this.map.get(key); + if (result == null) { + return defaultValue; + } else { return result; + } + } + return section.getOrDefault(key, defaultValue); + } + + @Override + public ConfigurationSection createSection(String path) { + Configuration root = getRoot(); + if (root == null) { + throw new IllegalStateException("Cannot create section without a root"); } - @Override public Map getValues(boolean deep) { - Map result = new LinkedHashMap<>(); + char separator = root.options().pathSeparator(); + // i1 is the leading (higher) index + // i2 is the trailing (lower) index + int i1 = -1; + int i2; + ConfigurationSection section = this; + while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { + String node = path.substring(i2, i1); + ConfigurationSection subSection = section.getConfigurationSection(node); + if (subSection == null) { + section = section.createSection(node); + } else { + section = subSection; + } + } - Configuration root = getRoot(); - if ((root != null) && root.options().copyDefaults()) { - ConfigurationSection defaults = getDefaultSection(); + String key = path.substring(i2); + if (section == this) { + ConfigurationSection result = new MemorySection(this, key); + this.map.put(key, result); + return result; + } + return section.createSection(key); + } - if (defaults != null) { - result.putAll(defaults.getValues(deep)); - } + @Override + public ConfigurationSection createSection(String path, Map map) { + ConfigurationSection section = createSection(path); + + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() instanceof Map) { + section.createSection(entry.getKey().toString(), (Map) entry.getValue()); + } else { + section.set(entry.getKey().toString(), entry.getValue()); + } + } + + return section; + } + + // Primitives + @Override + public String getString(String path) { + Object def = getDefault(path); + return getString(path, def != null ? def.toString() : null); + } + + @Override + public String getString(String path, String def) { + Object val = getOrDefault(path, def); + if (val != null) { + return val.toString(); + } else { + return def; + } + } + + @Override + public boolean isString(String path) { + Object val = get(path); + return val instanceof String; + } + + @Override + public int getInt(String path) { + Object def = getDefault(path); + return getInt(path, toInt(def, 0)); + } + + @Override + public int getInt(String path, int def) { + Object val = getOrDefault(path, def); + return toInt(val, def); + } + + @Override + public boolean isInt(String path) { + Object val = get(path); + return val instanceof Integer; + } + + @Override + public boolean getBoolean(String path) { + Object def = getDefault(path); + if (def instanceof Boolean) { + return getBoolean(path, (Boolean) def); + } else { + return getBoolean(path, false); + } + } + + @Override + public boolean getBoolean(String path, boolean defaultValue) { + Object val = getOrDefault(path, defaultValue); + if (val instanceof Boolean) { + return (Boolean) val; + } else { + return defaultValue; + } + } + + @Override + public boolean isBoolean(String path) { + Object val = get(path); + return val instanceof Boolean; + } + + @Override + public double getDouble(String path) { + Object def = getDefault(path); + return getDouble(path, toDouble(def, 0)); + } + + @Override + public double getDouble(String path, double defaultValue) { + Object val = getOrDefault(path, defaultValue); + return toDouble(val, defaultValue); + } + + @Override + public boolean isDouble(String path) { + Object val = get(path); + return val instanceof Double; + } + + @Override + public long getLong(String path) { + Object def = getDefault(path); + return getLong(path, toLong(def, 0)); + } + + @Override + public long getLong(String path, long def) { + Object val = getOrDefault(path, def); + return toLong(val, def); + } + + @Override + public boolean isLong(String path) { + Object val = get(path); + return val instanceof Long; + } + + // Java + @Override + public List getList(String path) { + Object def = getDefault(path); + return getList(path, def instanceof List ? (List) def : null); + } + + @Override + public List getList(String path, List def) { + Object val = getOrDefault(path, def); + return (List) ((val instanceof List) ? val : def); + } + + @Override + public boolean isList(String path) { + Object val = get(path); + return val instanceof List; + } + + @Override + public List getStringList(String path) { + List list = getList(path); + + if (list == null) { + return new ArrayList<>(0); + } + + List result = new ArrayList<>(); + + for (Object object : list) { + if ((object instanceof String) || isPrimitiveWrapper(object)) { + result.add(String.valueOf(object)); + } + } + + return result; + } + + @Override + public List getIntegerList(String path) { + List list = getList(path); + + List result = new ArrayList<>(); + + for (Object object : list) { + if (object instanceof Integer) { + result.add((Integer) object); + } else if (object instanceof String) { + try { + result.add(Integer.valueOf((String) object)); + } catch (NumberFormatException ignored) { } - - mapChildrenValues(result, this, deep); - - return result; + } else if (object instanceof Character) { + result.add((int) (Character) object); + } else if (object instanceof Number) { + result.add(((Number) object).intValue()); + } } - @Override public boolean contains(String path) { - return get(path) != null; - } + return result; + } - @Override public boolean isSet(String path) { - Configuration root = getRoot(); - if (root == null) { - return false; + @Override + public List getBooleanList(String path) { + List list = getList(path); + + List result = new ArrayList<>(); + + for (Object object : list) { + if (object instanceof Boolean) { + result.add((Boolean) object); + } else if (object instanceof String) { + if (Boolean.TRUE.toString().equals(object)) { + result.add(true); + } else if (Boolean.FALSE.toString().equals(object)) { + result.add(false); } - if (root.options().copyDefaults()) { - return contains(path); + } + } + + return result; + } + + @Override + public List getDoubleList(String path) { + List list = getList(path); + + List result = new ArrayList<>(); + + for (Object object : list) { + if (object instanceof Double) { + result.add((Double) object); + } else if (object instanceof String) { + try { + result.add(Double.valueOf((String) object)); + } catch (NumberFormatException ignored) { } - return get(path, null) != null; + } else if (object instanceof Character) { + result.add((double) (Character) object); + } else if (object instanceof Number) { + result.add(((Number) object).doubleValue()); + } } - @Override public String getCurrentPath() { - return this.fullPath; - } + return result; + } - @Override public String getName() { - return this.path; - } + @Override + public List getFloatList(String path) { + List list = getList(path); - @Override public Configuration getRoot() { - return this.root; - } + List result = new ArrayList<>(); - @Override public ConfigurationSection getParent() { - return this.parent; - } - - @Override public void addDefault(String path, Object value) { - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot add default without root"); + for (Object object : list) { + if (object instanceof Float) { + result.add((Float) object); + } else if (object instanceof String) { + try { + result.add(Float.valueOf((String) object)); + } catch (NumberFormatException ignored) { } - if (root == this) { - throw new UnsupportedOperationException( - "Unsupported addDefault(String, Object) implementation"); + } else if (object instanceof Character) { + result.add((float) (Character) object); + } else if (object instanceof Number) { + result.add(((Number) object).floatValue()); + } + } + + return result; + } + + @Override + public List getLongList(String path) { + List list = getList(path); + + List result = new ArrayList<>(); + + for (Object object : list) { + if (object instanceof Long) { + result.add((Long) object); + } else if (object instanceof String) { + try { + result.add(Long.valueOf((String) object)); + } catch (NumberFormatException ignored) { } - root.addDefault(createPath(this, path), value); + } else if (object instanceof Character) { + result.add((long) (Character) object); + } else if (object instanceof Number) { + result.add(((Number) object).longValue()); + } } - @Override public ConfigurationSection getDefaultSection() { - Configuration root = getRoot(); - Configuration defaults = root == null ? null : root.getDefaults(); + return result; + } - if (defaults != null) { - if (defaults.isConfigurationSection(getCurrentPath())) { - return defaults.getConfigurationSection(getCurrentPath()); - } + @Override + public List getByteList(String path) { + List list = getList(path); + + List result = new ArrayList<>(); + + for (Object object : list) { + if (object instanceof Byte) { + result.add((Byte) object); + } else if (object instanceof String) { + try { + result.add(Byte.valueOf((String) object)); + } catch (NumberFormatException ignored) { } - - return null; + } else if (object instanceof Character) { + result.add((byte) ((Character) object).charValue()); + } else if (object instanceof Number) { + result.add(((Number) object).byteValue()); + } } - @Override public void set(String path, Object value) { - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot use section without a root"); + return result; + } + + @Override + public List getCharacterList(String path) { + List list = getList(path); + + List result = new ArrayList<>(); + + for (Object object : list) { + if (object instanceof Character) { + result.add((Character) object); + } else if (object instanceof String) { + String str = (String) object; + + if (str.length() == 1) { + result.add(str.charAt(0)); } + } else if (object instanceof Number) { + result.add((char) ((Number) object).intValue()); + } + } - char separator = root.options().pathSeparator(); - // i1 is the leading (higher) index - // i2 is the trailing (lower) index - int i1 = -1; - int i2; - ConfigurationSection section = this; - while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { - String node = path.substring(i2, i1); - ConfigurationSection subSection = section.getConfigurationSection(node); - if (subSection == null) { - section = section.createSection(node); - } else { - section = subSection; - } + return result; + } + + @Override + public List getShortList(String path) { + List list = getList(path); + + List result = new ArrayList<>(); + + for (Object object : list) { + if (object instanceof Short) { + result.add((Short) object); + } else if (object instanceof String) { + try { + result.add(Short.valueOf((String) object)); + } catch (NumberFormatException ignored) { } + } else if (object instanceof Character) { + result.add((short) ((Character) object).charValue()); + } else if (object instanceof Number) { + result.add(((Number) object).shortValue()); + } + } - String key = path.substring(i2); - if (section == this) { - if (value == null) { - this.map.remove(key); - } else { - this.map.put(key, value); - } - } else { - section.set(key, value); + return result; + } + + @Override + public List> getMapList(String path) { + List list = getList(path); + List> result = new ArrayList<>(); + + for (Object object : list) { + if (object instanceof Map) { + result.add((Map) object); + } + } + + return result; + } + + @Override + public ConfigurationSection getConfigurationSection(String path) { + Object val = getOrDefault(path, null); + if (val != null) { + return (val instanceof ConfigurationSection) ? (ConfigurationSection) val : null; + } + + val = getOrDefault(path, getDefault(path)); + return (val instanceof ConfigurationSection) ? createSection(path) : null; + } + + @Override + public boolean isConfigurationSection(String path) { + Object val = get(path); + return val instanceof ConfigurationSection; + } + + protected boolean isPrimitiveWrapper(Object input) { + return (input instanceof Integer) || (input instanceof Boolean) + || (input instanceof Character) || (input instanceof Byte) || (input instanceof Short) + || (input instanceof Double) || (input instanceof Long) || (input instanceof Float); + } + + protected Object getDefault(String path) { + Configuration root = getRoot(); + Configuration defaults = root == null ? null : root.getDefaults(); + return (defaults == null) ? null : defaults.get(createPath(this, path)); + } + + protected void mapChildrenKeys(Set output, ConfigurationSection section, boolean deep) { + if (section instanceof MemorySection) { + MemorySection sec = (MemorySection) section; + + for (Map.Entry entry : sec.map.entrySet()) { + output.add(createPath(section, entry.getKey(), this)); + + if (deep && (entry.getValue() instanceof ConfigurationSection)) { + ConfigurationSection subsection = (ConfigurationSection) entry.getValue(); + mapChildrenKeys(output, subsection, deep); } - } + } + } else { + Set keys = section.getKeys(deep); - @Override public Object get(String path) { - return get(path, getDefault(path)); + for (String key : keys) { + output.add(createPath(section, key, this)); + } } + } - @Override public Object get(String path, Object defaultValue) { - if (path == null) { - throw new NullPointerException("Path cannot be null"); + protected void mapChildrenValues(Map output, ConfigurationSection section, + boolean deep) { + if (section instanceof MemorySection) { + MemorySection sec = (MemorySection) section; + + for (Map.Entry entry : sec.map.entrySet()) { + output.put(createPath(section, entry.getKey(), this), entry.getValue()); + + if (entry.getValue() instanceof ConfigurationSection) { + if (deep) { + mapChildrenValues(output, (ConfigurationSection) entry.getValue(), deep); + } } + } + } else { + Map values = section.getValues(deep); - if (path.isEmpty()) { - return this; - } - - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot access section without a root"); - } - - char separator = root.options().pathSeparator(); - // i1 is the leading (higher) index - // i2 is the trailing (lower) index - int i1 = -1; - int i2; - ConfigurationSection section = this; - while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { - section = section.getConfigurationSection(path.substring(i2, i1)); - if (section == null) { - return defaultValue; - } - } - - String key = path.substring(i2); - if (section == this) { - Object result = this.map.get(key); - if (result == null) { - return defaultValue; - } else { - return result; - } - } - return section.get(key, defaultValue); + for (Map.Entry entry : values.entrySet()) { + output.put(createPath(section, entry.getKey(), this), entry.getValue()); + } } + } - @Override public ConfigurationSection createSection(String path) { - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot create section without a root"); - } - - char separator = root.options().pathSeparator(); - // i1 is the leading (higher) index - // i2 is the trailing (lower) index - int i1 = -1; - int i2; - ConfigurationSection section = this; - while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { - String node = path.substring(i2, i1); - ConfigurationSection subSection = section.getConfigurationSection(node); - if (subSection == null) { - section = section.createSection(node); - } else { - section = subSection; - } - } - - String key = path.substring(i2); - if (section == this) { - ConfigurationSection result = new MemorySection(this, key); - this.map.put(key, result); - return result; - } - return section.createSection(key); - } - - @Override public ConfigurationSection createSection(String path, Map map) { - ConfigurationSection section = createSection(path); - - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() instanceof Map) { - section.createSection(entry.getKey().toString(), (Map) entry.getValue()); - } else { - section.set(entry.getKey().toString(), entry.getValue()); - } - } - - return section; - } - - // Primitives - @Override public String getString(String path) { - Object def = getDefault(path); - return getString(path, def != null ? def.toString() : null); - } - - @Override public String getString(String path, String def) { - Object val = get(path, def); - if (val != null) { - return val.toString(); - } else { - return def; - } - } - - @Override public boolean isString(String path) { - Object val = get(path); - return val instanceof String; - } - - @Override public int getInt(String path) { - Object def = getDefault(path); - return getInt(path, toInt(def, 0)); - } - - @Override public int getInt(String path, int def) { - Object val = get(path, def); - return toInt(val, def); - } - - @Override public boolean isInt(String path) { - Object val = get(path); - return val instanceof Integer; - } - - @Override public boolean getBoolean(String path) { - Object def = getDefault(path); - if (def instanceof Boolean) { - return getBoolean(path, (Boolean) def); - } else { - return getBoolean(path, false); - } - } - - @Override public boolean getBoolean(String path, boolean defaultValue) { - Object val = get(path, defaultValue); - if (val instanceof Boolean) { - return (Boolean) val; - } else { - return defaultValue; - } - } - - @Override public boolean isBoolean(String path) { - Object val = get(path); - return val instanceof Boolean; - } - - @Override public double getDouble(String path) { - Object def = getDefault(path); - return getDouble(path, toDouble(def, 0)); - } - - @Override public double getDouble(String path, double defaultValue) { - Object val = get(path, defaultValue); - return toDouble(val, defaultValue); - } - - @Override public boolean isDouble(String path) { - Object val = get(path); - return val instanceof Double; - } - - @Override public long getLong(String path) { - Object def = getDefault(path); - return getLong(path, toLong(def, 0)); - } - - @Override public long getLong(String path, long def) { - Object val = get(path, def); - return toLong(val, def); - } - - @Override public boolean isLong(String path) { - Object val = get(path); - return val instanceof Long; - } - - // Java - @Override public List getList(String path) { - Object def = getDefault(path); - return getList(path, def instanceof List ? (List) def : null); - } - - @Override public List getList(String path, List def) { - Object val = get(path, def); - return (List) ((val instanceof List) ? val : def); - } - - @Override public boolean isList(String path) { - Object val = get(path); - return val instanceof List; - } - - @Override public List getStringList(String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList<>(0); - } - - List result = new ArrayList<>(); - - for (Object object : list) { - if ((object instanceof String) || isPrimitiveWrapper(object)) { - result.add(String.valueOf(object)); - } - } - - return result; - } - - @Override public List getIntegerList(String path) { - List list = getList(path); - - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Integer) { - result.add((Integer) object); - } else if (object instanceof String) { - try { - result.add(Integer.valueOf((String) object)); - } catch (NumberFormatException ignored) { - } - } else if (object instanceof Character) { - result.add((int) (Character) object); - } else if (object instanceof Number) { - result.add(((Number) object).intValue()); - } - } - - return result; - } - - @Override public List getBooleanList(String path) { - List list = getList(path); - - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Boolean) { - result.add((Boolean) object); - } else if (object instanceof String) { - if (Boolean.TRUE.toString().equals(object)) { - result.add(true); - } else if (Boolean.FALSE.toString().equals(object)) { - result.add(false); - } - } - } - - return result; - } - - @Override public List getDoubleList(String path) { - List list = getList(path); - - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Double) { - result.add((Double) object); - } else if (object instanceof String) { - try { - result.add(Double.valueOf((String) object)); - } catch (NumberFormatException ignored) { - } - } else if (object instanceof Character) { - result.add((double) (Character) object); - } else if (object instanceof Number) { - result.add(((Number) object).doubleValue()); - } - } - - return result; - } - - @Override public List getFloatList(String path) { - List list = getList(path); - - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Float) { - result.add((Float) object); - } else if (object instanceof String) { - try { - result.add(Float.valueOf((String) object)); - } catch (NumberFormatException ignored) { - } - } else if (object instanceof Character) { - result.add((float) (Character) object); - } else if (object instanceof Number) { - result.add(((Number) object).floatValue()); - } - } - - return result; - } - - @Override public List getLongList(String path) { - List list = getList(path); - - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Long) { - result.add((Long) object); - } else if (object instanceof String) { - try { - result.add(Long.valueOf((String) object)); - } catch (NumberFormatException ignored) { - } - } else if (object instanceof Character) { - result.add((long) (Character) object); - } else if (object instanceof Number) { - result.add(((Number) object).longValue()); - } - } - - return result; - } - - @Override public List getByteList(String path) { - List list = getList(path); - - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Byte) { - result.add((Byte) object); - } else if (object instanceof String) { - try { - result.add(Byte.valueOf((String) object)); - } catch (NumberFormatException ignored) { - } - } else if (object instanceof Character) { - result.add((byte) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).byteValue()); - } - } - - return result; - } - - @Override public List getCharacterList(String path) { - List list = getList(path); - - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Character) { - result.add((Character) object); - } else if (object instanceof String) { - String str = (String) object; - - if (str.length() == 1) { - result.add(str.charAt(0)); - } - } else if (object instanceof Number) { - result.add((char) ((Number) object).intValue()); - } - } - - return result; - } - - @Override public List getShortList(String path) { - List list = getList(path); - - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Short) { - result.add((Short) object); - } else if (object instanceof String) { - try { - result.add(Short.valueOf((String) object)); - } catch (NumberFormatException ignored) { - } - } else if (object instanceof Character) { - result.add((short) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).shortValue()); - } - } - - return result; - } - - @Override public List> getMapList(String path) { - List list = getList(path); - List> result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Map) { - result.add((Map) object); - } - } - - return result; - } - - @Override public ConfigurationSection getConfigurationSection(String path) { - Object val = get(path, null); - if (val != null) { - return (val instanceof ConfigurationSection) ? (ConfigurationSection) val : null; - } - - val = get(path, getDefault(path)); - return (val instanceof ConfigurationSection) ? createSection(path) : null; - } - - @Override public boolean isConfigurationSection(String path) { - Object val = get(path); - return val instanceof ConfigurationSection; - } - - protected boolean isPrimitiveWrapper(Object input) { - return (input instanceof Integer) || (input instanceof Boolean) - || (input instanceof Character) || (input instanceof Byte) || (input instanceof Short) - || (input instanceof Double) || (input instanceof Long) || (input instanceof Float); - } - - protected Object getDefault(String path) { - Configuration root = getRoot(); - Configuration defaults = root == null ? null : root.getDefaults(); - return (defaults == null) ? null : defaults.get(createPath(this, path)); - } - - protected void mapChildrenKeys(Set output, ConfigurationSection section, boolean deep) { - if (section instanceof MemorySection) { - MemorySection sec = (MemorySection) section; - - for (Map.Entry entry : sec.map.entrySet()) { - output.add(createPath(section, entry.getKey(), this)); - - if (deep && (entry.getValue() instanceof ConfigurationSection)) { - ConfigurationSection subsection = (ConfigurationSection) entry.getValue(); - mapChildrenKeys(output, subsection, deep); - } - } - } else { - Set keys = section.getKeys(deep); - - for (String key : keys) { - output.add(createPath(section, key, this)); - } - } - } - - protected void mapChildrenValues(Map output, ConfigurationSection section, - boolean deep) { - if (section instanceof MemorySection) { - MemorySection sec = (MemorySection) section; - - for (Map.Entry entry : sec.map.entrySet()) { - output.put(createPath(section, entry.getKey(), this), entry.getValue()); - - if (entry.getValue() instanceof ConfigurationSection) { - if (deep) { - mapChildrenValues(output, (ConfigurationSection) entry.getValue(), deep); - } - } - } - } else { - Map values = section.getValues(deep); - - for (Map.Entry entry : values.entrySet()) { - output.put(createPath(section, entry.getKey(), this), entry.getValue()); - } - } - } - - @Override public String toString() { - Configuration root = getRoot(); - if (root == null) { - return getClass().getSimpleName() + "[path='" + getCurrentPath() + "', root='" + null - + "']"; - } else { - return getClass().getSimpleName() + "[path='" + getCurrentPath() + "', root='" + root - .getClass().getSimpleName() + "']"; - } + @Override + public String toString() { + Configuration root = getRoot(); + if (root == null) { + return getClass().getSimpleName() + "[path='" + getCurrentPath() + "', root='" + null + + "']"; + } else { + return getClass().getSimpleName() + "[path='" + getCurrentPath() + "', root='" + root + .getClass().getSimpleName() + "']"; } + } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/FileConfiguration.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/FileConfiguration.java index 668509bf3..97643f7ee 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/FileConfiguration.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/FileConfiguration.java @@ -6,6 +6,7 @@ import com.github.intellectualsites.plotsquared.configuration.MemoryConfiguratio import java.io.*; import java.nio.charset.StandardCharsets; +import javax.annotation.Nonnull; /** * This is a base class for all File based implementations of {@link @@ -82,7 +83,7 @@ public abstract class FileConfiguration extends MemoryConfiguration { * a valid Configuration. * @throws IllegalArgumentException Thrown when file is null. */ - public void load(File file) throws IOException, InvalidConfigurationException { + public void load(@Nonnull File file) throws IOException, InvalidConfigurationException { FileInputStream stream = new FileInputStream(file); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConfiguration.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConfiguration.java index d8c41c3da..1e694f05a 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConfiguration.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConfiguration.java @@ -83,7 +83,7 @@ public class YamlConfiguration extends FileConfiguration { Map input; try { - input = (Map) yaml.load(contents); + input = yaml.load(contents); } catch (YAMLException e) { throw new InvalidConfigurationException(e); } catch (ClassCastException ignored) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConfigurationOptions.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConfigurationOptions.java index a17bc3538..730527652 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConfigurationOptions.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConfigurationOptions.java @@ -42,7 +42,7 @@ public class YamlConfigurationOptions extends FileConfigurationOptions { * * @return How much to indent by */ - public int indent() { + int indent() { return indent; } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConstructor.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConstructor.java index 1f52f7abb..cdc5eb821 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConstructor.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/configuration/file/YamlConstructor.java @@ -9,7 +9,7 @@ import org.yaml.snakeyaml.nodes.Tag; import java.util.LinkedHashMap; import java.util.Map; -public class YamlConstructor extends SafeConstructor { +class YamlConstructor extends SafeConstructor { YamlConstructor() { yamlConstructors.put(Tag.MAP, new ConstructCustomObject()); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/IPlotMain.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/IPlotMain.java index e50ec9e8e..7fa0ec41a 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/IPlotMain.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/IPlotMain.java @@ -76,7 +76,9 @@ public interface IPlotMain extends ILogger { * * @return */ - String getPluginName(); + default String getPluginName() { + return "PlotSquared"; + } /** * Get the version of Minecraft that is running. diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/Platform.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/Platform.java index b7eb33b83..9dfbf2ffb 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/Platform.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/Platform.java @@ -1,6 +1,6 @@ package com.github.intellectualsites.plotsquared.plot; public enum Platform { - Bukkit, Sponge, Spigot, Cauldron + Bukkit, Sponge, Spigot } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/PlotSquared.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/PlotSquared.java index 2d55e9048..84991d2b4 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/PlotSquared.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/PlotSquared.java @@ -47,179 +47,182 @@ import java.util.zip.ZipInputStream; /** * An implementation of the core, with a static getter for easy access. */ -@SuppressWarnings({"unused", "WeakerAccess"}) public class PlotSquared { - private static final Set EMPTY_SET = - Collections.unmodifiableSet(Collections.emptySet()); - private static PlotSquared instance; - // Implementation - public final IPlotMain IMP; - // Current thread - private final Thread thread; - // WorldEdit instance - public WorldEdit worldedit; - public File styleFile; - public File configFile; - public File worldsFile; - public File commandsFile; - public File translationFile; - public YamlConfiguration style; - public YamlConfiguration config; - public YamlConfiguration worlds; - public YamlConfiguration storage; - public YamlConfiguration commands; - // Temporary hold the plots/clusters before the worlds load - public HashMap> clusters_tmp; - public HashMap> plots_tmp; - // Implementation logger - @Setter @Getter private ILogger logger; - // Platform / Version / Update URL - private PlotVersion version; - // Files and configuration - @Getter private File jarFile = null; // This file - private File storageFile; - @Getter private PlotAreaManager plotAreaManager; +@SuppressWarnings({"unused", "WeakerAccess"}) +public class PlotSquared { - /** - * Initialize PlotSquared with the desired Implementation class. - * - * @param iPlotMain Implementation of {@link IPlotMain} used - * @param platform The platform being used - */ - public PlotSquared(final IPlotMain iPlotMain, final String platform) { - if (instance != null) { - throw new IllegalStateException("Cannot re-initialize the PlotSquared singleton"); + private static final Set EMPTY_SET = + Collections.unmodifiableSet(Collections.emptySet()); + private static PlotSquared instance; + // Implementation + public final IPlotMain IMP; + // Current thread + private final Thread thread; + // WorldEdit instance + public WorldEdit worldedit; + public File styleFile; + public File configFile; + public File worldsFile; + public File commandsFile; + public File translationFile; + public YamlConfiguration style; + public YamlConfiguration config; + public YamlConfiguration worlds; + public YamlConfiguration storage; + public YamlConfiguration commands; + // Temporary hold the plots/clusters before the worlds load + public HashMap> clusters_tmp; + public HashMap> plots_tmp; + // Implementation logger + @Setter + @Getter + private ILogger logger; + // Platform / Version / Update URL + private PlotVersion version; + // Files and configuration + @Getter + private File jarFile = null; // This file + private File storageFile; + @Getter + private PlotAreaManager plotAreaManager; + + /** + * Initialize PlotSquared with the desired Implementation class. + * + * @param iPlotMain Implementation of {@link IPlotMain} used + * @param platform The platform being used + */ + public PlotSquared(final IPlotMain iPlotMain, final String platform) { + if (instance != null) { + throw new IllegalStateException("Cannot re-initialize the PlotSquared singleton"); + } + instance = this; + + this.thread = Thread.currentThread(); + this.IMP = iPlotMain; + this.logger = iPlotMain; + Settings.PLATFORM = platform; + + // + // Register configuration serializable classes + // + ConfigurationSerialization.registerClass(PlotBlock.class, "PlotBlock"); + ConfigurationSerialization.registerClass(BlockBucket.class, "BlockBucket"); + + try { + new ReflectionUtils(this.IMP.getNMSPackage()); + try { + URL url = PlotSquared.class.getProtectionDomain().getCodeSource().getLocation(); + this.jarFile = new File( + new URL(url.toURI().toString().split("\\!")[0].replaceAll("jar:file", "file")) + .toURI().getPath()); + } catch (MalformedURLException | URISyntaxException | SecurityException e) { + e.printStackTrace(); + this.jarFile = new File(this.IMP.getDirectory().getParentFile(), "PlotSquared.jar"); + if (!this.jarFile.exists()) { + this.jarFile = new File(this.IMP.getDirectory().getParentFile(), + "PlotSquared-" + platform + ".jar"); } - instance = this; + } + TaskManager.IMP = this.IMP.getTaskManager(); - this.thread = Thread.currentThread(); - this.IMP = iPlotMain; - this.logger = iPlotMain; - Settings.PLATFORM = platform; + // World Util. Has to be done before config files are loaded + WorldUtil.IMP = this.IMP.initWorldUtil(); - // - // Register configuration serializable classes - // - ConfigurationSerialization.registerClass(PlotBlock.class, "PlotBlock"); - ConfigurationSerialization.registerClass(BlockBucket.class, "BlockBucket"); + if (!setupConfigs()) { + return; + } + this.translationFile = MainUtil.getFile(this.IMP.getDirectory(), + Settings.Paths.TRANSLATIONS + File.separator + IMP.getPluginName() + + ".use_THIS.yml"); + C.load(this.translationFile); + // Setup plotAreaManager + if (Settings.Enabled_Components.WORLDS) { + this.plotAreaManager = new SinglePlotAreaManager(); + } else { + this.plotAreaManager = new DefaultPlotAreaManager(); + } + + // Database + if (Settings.Enabled_Components.DATABASE) { + setupDatabase(); + } + // Comments + CommentManager.registerDefaultInboxes(); + // Kill entities + if (Settings.Enabled_Components.KILL_ROAD_MOBS + || Settings.Enabled_Components.KILL_ROAD_VEHICLES) { + this.IMP.runEntityTask(); + } + if (Settings.Enabled_Components.EVENTS) { + this.IMP.registerPlayerEvents(); + this.IMP.registerInventoryEvents(); + this.IMP.registerPlotPlusEvents(); + } + // Required + this.IMP.registerWorldEvents(); + if (Settings.Enabled_Components.METRICS) { + this.IMP.startMetrics(); + } else { + PlotSquared.log(C.CONSOLE_PLEASE_ENABLE_METRICS.f(IMP.getPluginName())); + } + if (Settings.Enabled_Components.CHUNK_PROCESSOR) { + this.IMP.registerChunkProcessor(); + } + // create UUIDWrapper + UUIDHandler.implementation = this.IMP.initUUIDHandler(); + if (Settings.Enabled_Components.UUID_CACHE) { + startUuidCatching(); + } else { + // Start these separately + UUIDHandler.add(new StringWrapper("*"), DBFunc.EVERYONE); + startExpiryTasks(); + } + // create event util class + EventUtil.manager = this.IMP.initEventUtil(); + // create Hybrid utility class + HybridUtils.manager = this.IMP.initHybridUtils(); + // Inventory utility class + InventoryUtil.manager = this.IMP.initInventoryUtil(); + // create setup util class + SetupUtils.manager = this.IMP.initSetupUtils(); + // Set block + GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1); + GlobalBlockQueue.IMP.runTask(); + // Set chunk + ChunkManager.manager = this.IMP.initChunkManager(); + // Schematic handler + SchematicHandler.manager = this.IMP.initSchematicHandler(); + // Titles + AbstractTitle.TITLE_CLASS = this.IMP.initTitleManager(); + // Chat + ChatManager.manager = this.IMP.initChatManager(); + // Commands + if (Settings.Enabled_Components.COMMANDS) { + this.IMP.registerCommands(); + } + // WorldEdit + if (Settings.Enabled_Components.WORLDEDIT_RESTRICTIONS) { try { - new ReflectionUtils(this.IMP.getNMSPackage()); - try { - URL url = PlotSquared.class.getProtectionDomain().getCodeSource().getLocation(); - this.jarFile = new File( - new URL(url.toURI().toString().split("\\!")[0].replaceAll("jar:file", "file")) - .toURI().getPath()); - } catch (MalformedURLException | URISyntaxException | SecurityException e) { - e.printStackTrace(); - this.jarFile = new File(this.IMP.getDirectory().getParentFile(), "PlotSquared.jar"); - if (!this.jarFile.exists()) { - this.jarFile = new File(this.IMP.getDirectory().getParentFile(), - "PlotSquared-" + platform + ".jar"); - } - } - TaskManager.IMP = this.IMP.getTaskManager(); - - // World Util. Has to be done before config files are loaded - WorldUtil.IMP = this.IMP.initWorldUtil(); - - if (!setupConfigs()) { - return; - } - this.translationFile = MainUtil.getFile(this.IMP.getDirectory(), - Settings.Paths.TRANSLATIONS + File.separator + IMP.getPluginName() - + ".use_THIS.yml"); - C.load(this.translationFile); - - // Setup plotAreaManager - if (Settings.Enabled_Components.WORLDS) { - this.plotAreaManager = new SinglePlotAreaManager(); - } else { - this.plotAreaManager = new DefaultPlotAreaManager(); - } - - // Database - if (Settings.Enabled_Components.DATABASE) { - setupDatabase(); - } - // Comments - CommentManager.registerDefaultInboxes(); - // Kill entities - if (Settings.Enabled_Components.KILL_ROAD_MOBS - || Settings.Enabled_Components.KILL_ROAD_VEHICLES) { - this.IMP.runEntityTask(); - } - if (Settings.Enabled_Components.EVENTS) { - this.IMP.registerPlayerEvents(); - this.IMP.registerInventoryEvents(); - this.IMP.registerPlotPlusEvents(); - } - // Required - this.IMP.registerWorldEvents(); - if (Settings.Enabled_Components.METRICS) { - this.IMP.startMetrics(); - } else { - PlotSquared.log(C.CONSOLE_PLEASE_ENABLE_METRICS.f(IMP.getPluginName())); - } - if (Settings.Enabled_Components.CHUNK_PROCESSOR) { - this.IMP.registerChunkProcessor(); - } - // create UUIDWrapper - UUIDHandler.implementation = this.IMP.initUUIDHandler(); - if (Settings.Enabled_Components.UUID_CACHE) { - startUuidCatching(); - } else { - // Start these separately - UUIDHandler.add(new StringWrapper("*"), DBFunc.EVERYONE); - startExpiryTasks(); - } - // create event util class - EventUtil.manager = this.IMP.initEventUtil(); - // create Hybrid utility class - HybridUtils.manager = this.IMP.initHybridUtils(); - // Inventory utility class - InventoryUtil.manager = this.IMP.initInventoryUtil(); - // create setup util class - SetupUtils.manager = this.IMP.initSetupUtils(); - // Set block - GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1); - GlobalBlockQueue.IMP.runTask(); - // Set chunk - ChunkManager.manager = this.IMP.initChunkManager(); - // Schematic handler - SchematicHandler.manager = this.IMP.initSchematicHandler(); - // Titles - AbstractTitle.TITLE_CLASS = this.IMP.initTitleManager(); - // Chat - ChatManager.manager = this.IMP.initChatManager(); - // Commands + if (this.IMP.initWorldEdit()) { + PlotSquared.debug(IMP.getPluginName() + " hooked into WorldEdit."); + this.worldedit = WorldEdit.getInstance(); + WorldEdit.getInstance().getEventBus().register(new WESubscriber()); if (Settings.Enabled_Components.COMMANDS) { - this.IMP.registerCommands(); + new WE_Anywhere(); } - // WorldEdit - if (Settings.Enabled_Components.WORLDEDIT_RESTRICTIONS) { - try { - if (this.IMP.initWorldEdit()) { - PlotSquared.debug(IMP.getPluginName() + " hooked into WorldEdit."); - this.worldedit = WorldEdit.getInstance(); - WorldEdit.getInstance().getEventBus().register(new WESubscriber()); - if (Settings.Enabled_Components.COMMANDS) { - new WE_Anywhere(); - } - } - } catch (Throwable e) { - PlotSquared.debug( - "Incompatible version of WorldEdit, please upgrade: http://builds.enginehub.org/job/worldedit?branch=master"); - } - } - // Economy - if (Settings.Enabled_Components.ECONOMY) { - TaskManager.runTask(new Runnable() { - @Override public void run() { - EconHandler.manager = PlotSquared.this.IMP.getEconomyHandler(); - } - }); - } + } + } catch (Throwable e) { + PlotSquared.debug( + "Incompatible version of WorldEdit, please upgrade: http://builds.enginehub.org/job/worldedit?branch=master"); + } + } + // Economy + if (Settings.Enabled_Components.ECONOMY) { + TaskManager.runTask( + () -> EconHandler.manager = PlotSquared.this.IMP.getEconomyHandler()); + } /* // Check for updates if (Settings.Enabled_Components.UPDATER) { @@ -236,1810 +239,1864 @@ import java.util.zip.ZipInputStream; }, 36000); }*/ - // World generators: - final ConfigurationSection section = this.worlds.getConfigurationSection("worlds"); - if (section != null) { - for (String world : section.getKeys(false)) { - if (world.equals("CheckingPlotSquaredGenerator")) { - continue; - } - if (WorldUtil.IMP.isWorld(world)) { - this.IMP.setGenerator(world); - } - } - TaskManager.runTaskLater(new Runnable() { - @Override public void run() { - for (String world : section.getKeys(false)) { - if (world.equals("CheckingPlotSquaredGenerator")) { - continue; - } - if (!WorldUtil.IMP.isWorld(world) && !world.equals("*")) { - debug("&c`" + world + "` was not properly loaded - " + IMP - .getPluginName() + " will now try to load it properly: "); - debug( - "&8 - &7Are you trying to delete this world? Remember to remove it from the settings.yml, bukkit.yml and multiverse worlds.yml"); - debug( - "&8 - &7Your world management plugin may be faulty (or non existent)"); - PlotSquared.this.IMP.setGenerator(world); - } - } - } - }, 1); + // World generators: + final ConfigurationSection section = this.worlds.getConfigurationSection("worlds"); + if (section != null) { + for (String world : section.getKeys(false)) { + if (world.equals("CheckingPlotSquaredGenerator")) { + continue; + } + if (WorldUtil.IMP.isWorld(world)) { + this.IMP.setGenerator(world); + } + } + TaskManager.runTaskLater(() -> { + for (String world : section.getKeys(false)) { + if (world.equals("CheckingPlotSquaredGenerator")) { + continue; } + if (!WorldUtil.IMP.isWorld(world) && !world.equals("*")) { + debug("&c`" + world + "` was not properly loaded - " + IMP + .getPluginName() + " will now try to load it properly: "); + debug( + "&8 - &7Are you trying to delete this world? Remember to remove it from the settings.yml, bukkit.yml and multiverse worlds.yml"); + debug( + "&8 - &7Your world management plugin may be faulty (or non existent)"); + PlotSquared.this.IMP.setGenerator(world); + } + } + }, 1); + } - // Copy files - copyFile("addplots.js", Settings.Paths.SCRIPTS); - copyFile("addsigns.js", Settings.Paths.SCRIPTS); - copyFile("automerge.js", Settings.Paths.SCRIPTS); - copyFile("furthest.js", Settings.Paths.SCRIPTS); - copyFile("mycommand.js", Settings.Paths.SCRIPTS); - copyFile("setbiomes.js", Settings.Paths.SCRIPTS); - copyFile("start.js", Settings.Paths.SCRIPTS); - copyFile("town.template", Settings.Paths.TEMPLATES); - copyFile("skyblock.template", Settings.Paths.TEMPLATES); - copyFile("bridge.template", Settings.Paths.TEMPLATES); - copyFile("de-DE.yml", Settings.Paths.TRANSLATIONS); - copyFile("es-ES.yml", Settings.Paths.TRANSLATIONS); - copyFile("zh-CN.yml", Settings.Paths.TRANSLATIONS); - copyFile("it-IT.yml", Settings.Paths.TRANSLATIONS); - copyFile("ko-KR.yml", Settings.Paths.TRANSLATIONS); - copyFile("fr-FR.yml", Settings.Paths.TRANSLATIONS); - showDebug(); - } catch (Throwable e) { - e.printStackTrace(); + // Copy files + copyFile("addplots.js", Settings.Paths.SCRIPTS); + copyFile("addsigns.js", Settings.Paths.SCRIPTS); + copyFile("automerge.js", Settings.Paths.SCRIPTS); + copyFile("furthest.js", Settings.Paths.SCRIPTS); + copyFile("mycommand.js", Settings.Paths.SCRIPTS); + copyFile("setbiomes.js", Settings.Paths.SCRIPTS); + copyFile("start.js", Settings.Paths.SCRIPTS); + copyFile("town.template", Settings.Paths.TEMPLATES); + copyFile("skyblock.template", Settings.Paths.TEMPLATES); + copyFile("bridge.template", Settings.Paths.TEMPLATES); + copyFile("de-DE.yml", Settings.Paths.TRANSLATIONS); + copyFile("es-ES.yml", Settings.Paths.TRANSLATIONS); + copyFile("zh-CN.yml", Settings.Paths.TRANSLATIONS); + copyFile("it-IT.yml", Settings.Paths.TRANSLATIONS); + copyFile("ko-KR.yml", Settings.Paths.TRANSLATIONS); + copyFile("fr-FR.yml", Settings.Paths.TRANSLATIONS); + showDebug(); + } catch (Throwable e) { + e.printStackTrace(); + } + + PlotSquared.log(C.ENABLED.f(IMP.getPluginName())); + } + + /** + * Get an instance of PlotSquared. + * + * @return instance of PlotSquared + */ + public static PlotSquared get() { + return PlotSquared.instance; + } + + public static IPlotMain imp() { + if (instance != null) { + return instance.IMP; + } + return null; + } + + /** + * Log a message to the IPlotMain logger. + * + * @param message Message to log + * @see IPlotMain#log(String) + */ + public static void log(Object message) { + if (message == null || message.toString().isEmpty()) { + return; + } + if (PlotSquared.get() == null || PlotSquared.get().getLogger() == null) { + System.out.printf("[P2][Info] %s\n", StringMan.getString(message)); + } else { + PlotSquared.get().getLogger().log(StringMan.getString(message)); + } + } + + /** + * Log a message to the IPlotMain logger. + * + * @param message Message to log + * @see IPlotMain#log(String) + */ + public static void debug(@Nullable Object message) { + if (Settings.DEBUG) { + if (PlotSquared.get() == null || PlotSquared.get().getLogger() == null) { + System.out.printf("[P2][Debug] %s\n", StringMan.getString(message)); + } else { + PlotSquared.get().getLogger().log(StringMan.getString(message)); + } + } + } + + private void startUuidCatching() { + TaskManager.runTaskLater(() -> { + debug("Starting UUID caching"); + UUIDHandler.startCaching(() -> { + UUIDHandler.add(new StringWrapper("*"), DBFunc.EVERYONE); + foreachPlotRaw(new RunnableVal() { + @Override + public void run(Plot plot) { + if (plot.hasOwner() && plot.temp != -1) { + if (UUIDHandler.getName(plot.owner) == null) { + UUIDHandler.implementation.unknown.add(plot.owner); + } + } + } + }); + startExpiryTasks(); + }); + }, 20); + } + + private void startExpiryTasks() { + if (Settings.Enabled_Components.PLOT_EXPIRY) { + ExpireManager.IMP = new ExpireManager(); + ExpireManager.IMP.runAutomatedTask(); + for (Settings.Auto_Clear settings : Settings.AUTO_CLEAR.getInstances()) { + ExpiryTask task = new ExpiryTask(settings); + ExpireManager.IMP.addTask(task); + } + } + } + + public boolean isMainThread(Thread thread) { + return this.thread == thread; + } + + /** + * Check if `version` is >= `version2`. + * + * @param version First version + * @param version2 Second version + * @return true if `version` is >= `version2` + */ + public boolean checkVersion(int[] version, int... version2) { + return version[0] > version2[0] || version[0] == version2[0] && version[1] > version2[1] + || version[0] == version2[0] && version[1] == version2[1] && version[2] >= version2[2]; + } + + /** + * Get the current PlotSquared version. + * + * @return current version in config or null + */ + public PlotVersion getVersion() { + return this.version; + } + + /** + * Get the server platform this plugin is running on this is running on. + *

+ *

This will be either Bukkit or Sponge

+ * + * @return the server implementation + */ + public String getPlatform() { + return Settings.PLATFORM; + } + + public PlotManager getPlotManager(Plot plot) { + return plot.getArea().manager; + } + + public PlotManager getPlotManager(Location location) { + PlotArea pa = getPlotAreaAbs(location); + return pa != null ? pa.manager : null; + } + + /** + * Add a global reference to a plot world. + * + * @param plotArea the {@code PlotArea} to add. + * @see #removePlotArea(PlotArea) To remove the reference + */ + public void addPlotArea(PlotArea plotArea) { + HashMap plots; + if (plots_tmp == null || (plots = plots_tmp.remove(plotArea.toString())) == null) { + if (plotArea.TYPE == 2) { + plots = this.plots_tmp != null ? this.plots_tmp.get(plotArea.worldname) : null; + if (plots != null) { + Iterator> iterator = plots.entrySet().iterator(); + while (iterator.hasNext()) { + Entry next = iterator.next(); + PlotId id = next.getKey(); + if (plotArea.contains(id)) { + next.getValue().setArea(plotArea); + iterator.remove(); + } + } } - - PlotSquared.log(C.ENABLED.f(IMP.getPluginName())); + } + } else { + for (Plot entry : plots.values()) { + entry.setArea(plotArea); + } } - - /** - * Get an instance of PlotSquared. - * - * @return instance of PlotSquared - */ - public static PlotSquared get() { - return PlotSquared.instance; - } - - public static IPlotMain imp() { - if (instance != null) { - return instance.IMP; + Set clusters; + if (clusters_tmp == null || (clusters = clusters_tmp.remove(plotArea.toString())) == null) { + if (plotArea.TYPE == 2) { + clusters = + this.clusters_tmp != null ? this.clusters_tmp.get(plotArea.worldname) : null; + if (clusters != null) { + Iterator iterator = clusters.iterator(); + while (iterator.hasNext()) { + PlotCluster next = iterator.next(); + if (next.intersects(plotArea.getMin(), plotArea.getMax())) { + next.setArea(plotArea); + iterator.remove(); + } + } } - return null; + } + } else { + for (PlotCluster cluster : clusters) { + cluster.setArea(plotArea); + } } + plotAreaManager.addPlotArea(plotArea); + plotArea.setupBorder(); + } - /** - * Log a message to the IPlotMain logger. - * - * @param message Message to log - * @see IPlotMain#log(String) - */ - public static void log(Object message) { - if (message == null || message.toString().isEmpty()) { + /** + * Remove a plot world reference. + * + * @param area the {@code PlotArea} to remove + */ + public void removePlotArea(PlotArea area) { + plotAreaManager.removePlotArea(area); + setPlotsTmp(area); + } + + public void removePlotAreas(String world) { + for (PlotArea area : getPlotAreas(world)) { + if (area.worldname.equals(world)) { + removePlotArea(area); + } + } + } + + private void setPlotsTmp(PlotArea area) { + if (this.plots_tmp == null) { + this.plots_tmp = new HashMap<>(); + } + HashMap map = this.plots_tmp + .computeIfAbsent(area.toString(), k -> new HashMap<>()); + for (Plot plot : area.getPlots()) { + map.put(plot.getId(), plot); + } + if (this.clusters_tmp == null) { + this.clusters_tmp = new HashMap<>(); + } + this.clusters_tmp.put(area.toString(), area.getClusters()); + } + + public Set getClusters(String world) { + Set set = new HashSet<>(); + for (PlotArea area : getPlotAreas(world)) { + set.addAll(area.getClusters()); + } + return Collections.unmodifiableSet(set); + + } + + /** + * Get all the base plots in a single set (for merged plots it just returns the bottom plot). + * + * @return Set of base Plots + */ + public Set getBasePlots() { + int size = getPlotCount(); + final Set result = new HashSet<>(size); + foreachPlotArea(new RunnableVal() { + @Override + public void run(PlotArea value) { + for (Plot plot : value.getPlots()) { + if (!plot.isBasePlot()) { + continue; + } + result.add(plot); + } + } + }); + return Collections.unmodifiableSet(result); + } + + public List sortPlotsByTemp(Collection plots) { + int max = 0; + int overflowCount = 0; + for (Plot plot : plots) { + if (plot.temp > 0) { + if (plot.temp > max) { + max = plot.temp; + } + } else { + overflowCount++; + } + } + Plot[] array = new Plot[max + 1]; + List overflow = new ArrayList<>(overflowCount); + for (Plot plot : plots) { + if (plot.temp <= 0) { + overflow.add(plot); + } else { + array[plot.temp] = plot; + } + } + ArrayList result = new ArrayList<>(plots.size()); + for (Plot plot : array) { + if (plot != null) { + result.add(plot); + } + } + overflow.sort(Comparator.comparingInt(Plot::hashCode)); + result.addAll(overflow); + return result; + } + + /** + * Sort plots by hashcode. + * + * @param plots the collection of plots to sort + * @return the sorted collection {@link #sortPlots(Collection, SortType, PlotArea)} which has + * additional checks before calling this + */ + // TODO: Re-evaluate this (previously public and deprecated), as it's being used internally + private ArrayList sortPlotsByHash(Collection plots) { + int hardmax = 256000; + int max = 0; + int overflowSize = 0; + for (Plot plot : plots) { + int hash = MathMan.getPositiveId(plot.hashCode()); + if (hash > max) { + if (hash >= hardmax) { + overflowSize++; + } else { + max = hash; + } + } + } + hardmax = Math.min(hardmax, max); + Plot[] cache = new Plot[hardmax + 1]; + List overflow = new ArrayList<>(overflowSize); + ArrayList extra = new ArrayList<>(); + for (Plot plot : plots) { + int hash = MathMan.getPositiveId(plot.hashCode()); + if (hash < hardmax) { + if (hash >= 0) { + cache[hash] = plot; + } else { + extra.add(plot); + } + } else if (Math.abs(plot.getId().x) > 15446 || Math.abs(plot.getId().y) > 15446) { + extra.add(plot); + } else { + overflow.add(plot); + } + } + Plot[] overflowArray = overflow.toArray(new Plot[overflow.size()]); + sortPlotsByHash(overflowArray); + ArrayList result = new ArrayList<>(cache.length + overflowArray.length); + for (Plot plot : cache) { + if (plot != null) { + result.add(plot); + } + } + Collections.addAll(result, overflowArray); + result.addAll(extra); + return result; + } + + private void sortPlotsByHash(Plot[] input) { + List[] bucket = new ArrayList[32]; + for (int i = 0; i < bucket.length; i++) { + bucket[i] = new ArrayList<>(); + } + boolean maxLength = false; + int placement = 1; + while (!maxLength) { + maxLength = true; + for (Plot i : input) { + int tmp = MathMan.getPositiveId(i.hashCode()) / placement; + bucket[tmp & 31].add(i); + if (maxLength && tmp > 0) { + maxLength = false; + } + } + int a = 0; + for (int b = 0; b < 32; b++) { + for (Plot i : bucket[b]) { + input[a++] = i; + } + bucket[b].clear(); + } + placement *= 32; + } + } + + private ArrayList sortPlotsByTimestamp(Collection plots) { + int hardMax = 256000; + int max = 0; + int overflowSize = 0; + for (Plot plot : plots) { + int hash = MathMan.getPositiveId(plot.hashCode()); + if (hash > max) { + if (hash >= hardMax) { + overflowSize++; + } else { + max = hash; + } + } + } + hardMax = Math.min(hardMax, max); + Plot[] cache = new Plot[hardMax + 1]; + List overflow = new ArrayList<>(overflowSize); + ArrayList extra = new ArrayList<>(); + for (Plot plot : plots) { + int hash = MathMan.getPositiveId(plot.hashCode()); + if (hash < hardMax) { + if (hash >= 0) { + cache[hash] = plot; + } else { + extra.add(plot); + } + } else if (Math.abs(plot.getId().x) > 15446 || Math.abs(plot.getId().y) > 15446) { + extra.add(plot); + } else { + overflow.add(plot); + } + } + Plot[] overflowArray = overflow.toArray(new Plot[overflow.size()]); + sortPlotsByHash(overflowArray); + ArrayList result = new ArrayList<>(cache.length + overflowArray.length); + for (Plot plot : cache) { + if (plot != null) { + result.add(plot); + } + } + Collections.addAll(result, overflowArray); + result.addAll(extra); + return result; + } + + /** + * Sort plots by creation timestamp. + */ + + private List sortPlotsByModified(Collection input) { + List list; + if (input instanceof List) { + list = (List) input; + } else { + list = new ArrayList<>(input); + } + list.sort(Comparator.comparingLong(a -> ExpireManager.IMP.getTimestamp(a.owner))); + return list; + } + + /** + * Sort a collection of plots by world (with a priority world), then by hashcode. + * + * @param plots the plots to sort + * @param type The sorting method to use for each world (timestamp, or hash) + * @param priorityArea Use null, "world", or "gibberish" if you want default world order + * @return ArrayList of plot + */ + public ArrayList sortPlots(Collection plots, SortType type, + final PlotArea priorityArea) { + // group by world + // sort each + HashMap> map = new HashMap<>(); + int totalSize = getPlotCount(); + if (plots.size() == totalSize) { + for (PlotArea area : plotAreaManager.getAllPlotAreas()) { + map.put(area, area.getPlots()); + } + } else { + for (PlotArea area : plotAreaManager.getAllPlotAreas()) { + map.put(area, new ArrayList<>(0)); + } + Collection lastList = null; + PlotArea lastWorld = null; + for (Plot plot : plots) { + if (lastWorld == plot.getArea()) { + lastList.add(plot); + } else { + lastWorld = plot.getArea(); + lastList = map.get(lastWorld); + lastList.add(plot); + } + } + } + List areas = Arrays.asList(plotAreaManager.getAllPlotAreas()); + areas.sort((a, b) -> { + if (priorityArea != null) { + if (a.equals(priorityArea)) { + return -1; + } else if (b.equals(priorityArea)) { + return 1; + } + } + return a.hashCode() - b.hashCode(); + }); + ArrayList toReturn = new ArrayList<>(plots.size()); + for (PlotArea area : areas) { + switch (type) { + case CREATION_DATE: + toReturn.addAll(sortPlotsByTemp(map.get(area))); + break; + case CREATION_DATE_TIMESTAMP: + toReturn.addAll(sortPlotsByTimestamp(map.get(area))); + break; + case DISTANCE_FROM_ORIGIN: + toReturn.addAll(sortPlotsByHash(map.get(area))); + break; + case LAST_MODIFIED: + toReturn.addAll(sortPlotsByModified(map.get(area))); + break; + default: + break; + } + } + return toReturn; + } + + /** + * A more generic way to filter plots - make your own method if you need complex filters. + * + * @param filters the filter + * @return a filtered set of plots + */ + public Set getPlots(final PlotFilter... filters) { + final HashSet set = new HashSet<>(); + foreachPlotArea(new RunnableVal() { + @Override + public void run(PlotArea value) { + for (PlotFilter filter : filters) { + if (!filter.allowsArea(value)) { return; + } } - if (PlotSquared.get() == null || PlotSquared.get().getLogger() == null) { - System.out.printf("[P2][Info] %s\n", StringMan.getString(message)); - } else { - PlotSquared.get().getLogger().log(StringMan.getString(message)); + loop: + for (Entry entry2 : value.getPlotEntries()) { + Plot plot = entry2.getValue(); + for (PlotFilter filter : filters) { + if (!filter.allowsPlot(plot)) { + continue loop; + } + } + set.add(plot); } - } + } + }); + return set; + } - /** - * Log a message to the IPlotMain logger. - * - * @param message Message to log - * @see IPlotMain#log(String) - */ - public static void debug(@Nullable Object message) { - if (Settings.DEBUG) { - if (PlotSquared.get() == null || PlotSquared.get().getLogger() == null) { - System.out.printf("[P2][Debug] %s\n", StringMan.getString(message)); - } else { - PlotSquared.get().getLogger().log(StringMan.getString(message)); - } + /** + * Get all the plots in a single set. + * + * @return Set of Plots + */ + public Set getPlots() { + int size = getPlotCount(); + final Set result = new HashSet<>(size); + foreachPlotArea(new RunnableVal() { + @Override + public void run(PlotArea value) { + result.addAll(value.getPlots()); + } + }); + return result; + } + + //TODO look at uncommenting or deleting tis. Is it useful and will it work? + //If it is readded make sure there is proper javadoc documentation for it. +/* + public void setPlots(HashMap> plots) { + if (this.plots_tmp == null) { + this.plots_tmp = new HashMap<>(); + } + for (Entry> entry : plots.entrySet()) { + String world = entry.getKey(); + PlotArea area = getPlotArea(world, null); + if (area == null) { + HashMap map = this.plots_tmp + .computeIfAbsent(world, k -> new HashMap<>()); + map.putAll(entry.getValue()); + } else { + for (Plot plot : entry.getValue().values()) { + plot.setArea(area); + area.addPlot(plot); } + } } + } +*/ - private void startUuidCatching() { - TaskManager.runTaskLater(new Runnable() { - @Override public void run() { - debug("Starting UUID caching"); - UUIDHandler.startCaching(new Runnable() { - @Override public void run() { - UUIDHandler.add(new StringWrapper("*"), DBFunc.EVERYONE); - foreachPlotRaw(new RunnableVal() { - @Override public void run(Plot plot) { - if (plot.hasOwner() && plot.temp != -1) { - if (UUIDHandler.getName(plot.owner) == null) { - UUIDHandler.implementation.unknown.add(plot.owner); - } - } - } - }); - startExpiryTasks(); - } - }); - } - }, 20); + /** + * Get all the plots owned by a player name. + * + * @param world the world + * @param player the plot owner + * @return Set of Plot + */ + public Set getPlots(String world, String player) { + final UUID uuid = UUIDHandler.getUUID(player, null); + return getPlots(world, uuid); + } + + /** + * Get all the plots owned by a player name. + * + * @param area the PlotArea + * @param player the plot owner + * @return Set of Plot + */ + public Set getPlots(PlotArea area, String player) { + UUID uuid = UUIDHandler.getUUID(player, null); + return getPlots(area, uuid); + } + + /** + * Get all plots by a PlotPlayer. + * + * @param world the world + * @param player the plot owner + * @return Set of plot + */ + public Set getPlots(String world, PlotPlayer player) { + return getPlots(world, player.getUUID()); + } + + /** + * Get all plots by a PlotPlayer. + * + * @param area the PlotArea + * @param player the plot owner + * @return Set of plot + */ + public Set getPlots(PlotArea area, PlotPlayer player) { + return getPlots(area, player.getUUID()); + } + + /** + * Get all plots by a UUID in a world. + * + * @param world the world + * @param uuid the plot owner + * @return Set of plot + */ + public Set getPlots(String world, UUID uuid) { + final Set plots = new HashSet<>(); + for (final Plot plot : getPlots(world)) { + if (plot.hasOwner() && plot.isOwnerAbs(uuid)) { + plots.add(plot); + } } + return Collections.unmodifiableSet(plots); + } - private void startExpiryTasks() { - if (Settings.Enabled_Components.PLOT_EXPIRY) { - ExpireManager.IMP = new ExpireManager(); - ExpireManager.IMP.runAutomatedTask(); - for (Settings.Auto_Clear settings : Settings.AUTO_CLEAR.getInstances()) { - ExpiryTask task = new ExpiryTask(settings); - ExpireManager.IMP.addTask(task); - } + /** + * Get all plots by a UUID in an area. + * + * @param area the {@code PlotArea} + * @param uuid the plot owner + * @return Set of plots + */ + public Set getPlots(PlotArea area, UUID uuid) { + final Set plots = new HashSet<>(); + for (Plot plot : getPlots(area)) { + if (plot.hasOwner() && plot.isOwnerAbs(uuid)) { + plots.add(plot); + } + } + return Collections.unmodifiableSet(plots); + } + + /** + * Check if a plot world. + * + * @param world the world + * @return if a plot world is registered + * @see #getPlotAreaByString(String) to get the PlotArea object + */ + public boolean hasPlotArea(String world) { + return plotAreaManager.getPlotAreas(world, null).length != 0; + } + + public Collection getPlots(String world) { + final Set set = new HashSet<>(); + foreachPlotArea(world, new RunnableVal() { + @Override + public void run(PlotArea value) { + set.addAll(value.getPlots()); + } + }); + return set; + } + + /** + * Get the plots for a PlotPlayer. + * + * @param player the player to retrieve the plots for + * @return Set of Plot + */ + public Set getPlots(PlotPlayer player) { + return getPlots(player.getUUID()); + } + + public Collection getPlots(PlotArea area) { + return area == null ? EMPTY_SET : area.getPlots(); + } + + public Plot getPlot(PlotArea area, PlotId id) { + return area == null ? null : id == null ? null : area.getPlot(id); + } + + public Set getBasePlots(PlotPlayer player) { + return getBasePlots(player.getUUID()); + } + + /** + * Get the plots for a UUID. + * + * @param uuid the plot owner + * @return Set of Plot's owned by the player + */ + public Set getPlots(final UUID uuid) { + final Set plots = new HashSet<>(); + foreachPlot(new RunnableVal() { + @Override + public void run(Plot value) { + if (value.isOwnerAbs(uuid)) { + plots.add(value); } - } + } + }); + return Collections.unmodifiableSet(plots); + } - public boolean isMainThread(Thread thread) { - return this.thread == thread; - } - - /** - * Check if `version` is >= `version2`. - * - * @param version First version - * @param version2 Second version - * @return true if `version` is >= `version2` - */ - public boolean checkVersion(int[] version, int... version2) { - return version[0] > version2[0] || version[0] == version2[0] && version[1] > version2[1] - || version[0] == version2[0] && version[1] == version2[1] && version[2] >= version2[2]; - } - - /** - * Get the current PlotSquared version. - * - * @return current version in config or null - */ - public PlotVersion getVersion() { - return this.version; - } - - /** - * Get the server platform this plugin is running on this is running on. - *

- *

This will be either Bukkit or Sponge

- * - * @return the server implementation - */ - public String getPlatform() { - return Settings.PLATFORM; - } - - public PlotManager getPlotManager(Plot plot) { - return plot.getArea().manager; - } - - public PlotManager getPlotManager(Location location) { - PlotArea pa = getPlotAreaAbs(location); - return pa != null ? pa.manager : null; - } - - /** - * Add a global reference to a plot world. - * - * @param plotArea the {@code PlotArea} to add. - * @see #removePlotArea(PlotArea) To remove the reference - */ - public void addPlotArea(PlotArea plotArea) { - HashMap plots; - if (plots_tmp == null || (plots = plots_tmp.remove(plotArea.toString())) == null) { - if (plotArea.TYPE == 2) { - plots = this.plots_tmp != null ? this.plots_tmp.get(plotArea.worldname) : null; - if (plots != null) { - Iterator> iterator = plots.entrySet().iterator(); - while (iterator.hasNext()) { - Entry next = iterator.next(); - PlotId id = next.getKey(); - if (plotArea.contains(id)) { - next.getValue().setArea(plotArea); - iterator.remove(); - } - } - } - } - } else { - for (Plot entry : plots.values()) { - entry.setArea(plotArea); - } - } - Set clusters; - if (clusters_tmp == null || (clusters = clusters_tmp.remove(plotArea.toString())) == null) { - if (plotArea.TYPE == 2) { - clusters = - this.clusters_tmp != null ? this.clusters_tmp.get(plotArea.worldname) : null; - if (clusters != null) { - Iterator iterator = clusters.iterator(); - while (iterator.hasNext()) { - PlotCluster next = iterator.next(); - if (next.intersects(plotArea.getMin(), plotArea.getMax())) { - next.setArea(plotArea); - iterator.remove(); - } - } - } - } - } else { - for (PlotCluster cluster : clusters) { - cluster.setArea(plotArea); - } - } - plotAreaManager.addPlotArea(plotArea); - plotArea.setupBorder(); - } - - /** - * Remove a plot world reference. - * - * @param area the {@code PlotArea} to remove - */ - public void removePlotArea(PlotArea area) { - plotAreaManager.removePlotArea(area); - setPlotsTmp(area); - } - - public void removePlotAreas(String world) { - for (PlotArea area : getPlotAreas(world)) { - if (area.worldname.equals(world)) { - removePlotArea(area); - } - } - } - - private void setPlotsTmp(PlotArea area) { - if (this.plots_tmp == null) { - this.plots_tmp = new HashMap<>(); - } - HashMap map = this.plots_tmp.get(area.toString()); - if (map == null) { - map = new HashMap<>(); - this.plots_tmp.put(area.toString(), map); - } - for (Plot plot : area.getPlots()) { - map.put(plot.getId(), plot); - } - if (this.clusters_tmp == null) { - this.clusters_tmp = new HashMap<>(); - } - this.clusters_tmp.put(area.toString(), area.getClusters()); - } - - public Set getClusters(String world) { - Set set = new HashSet<>(); - for (PlotArea area : getPlotAreas(world)) { - set.addAll(area.getClusters()); - } - return Collections.unmodifiableSet(set); - - } - - /** - * Get all the base plots in a single set (for merged plots it just returns - * the bottom plot). - * - * @return Set of base Plots - */ - public Set getBasePlots() { - int size = getPlotCount(); - final Set result = new HashSet<>(size); - foreachPlotArea(new RunnableVal() { - @Override public void run(PlotArea value) { - for (Plot plot : value.getPlots()) { - if (!plot.isBasePlot()) { - continue; - } - result.add(plot); - } - } - }); - return Collections.unmodifiableSet(result); - } - - public List sortPlotsByTemp(Collection plots) { - int max = 0; - int overflowCount = 0; - for (Plot plot : plots) { - if (plot.temp > 0) { - if (plot.temp > max) { - max = plot.temp; - } - } else { - overflowCount++; - } - } - Plot[] array = new Plot[max + 1]; - List overflow = new ArrayList<>(overflowCount); - for (Plot plot : plots) { - if (plot.temp <= 0) { - overflow.add(plot); - } else { - array[plot.temp] = plot; - } - } - ArrayList result = new ArrayList<>(plots.size()); - for (Plot plot : array) { - if (plot != null) { - result.add(plot); - } - } - Collections.sort(overflow, new Comparator() { - @Override public int compare(Plot a, Plot b) { - return a.hashCode() - b.hashCode(); - } - }); - result.addAll(overflow); - return result; - } - - /** - * Sort plots by hashcode. - * - * @param plots the collection of plots to sort - * @return the sorted collection - * @deprecated Unchecked, please use - * {@link #sortPlots(Collection, SortType, PlotArea)} which has - * additional checks before calling this - */ - // TODO: Re-evaluate deprecation of this, as it's being used internally - @Deprecated public ArrayList sortPlotsByHash(Collection plots) { - int hardmax = 256000; - int max = 0; - int overflowSize = 0; - for (Plot plot : plots) { - int hash = MathMan.getPositiveId(plot.hashCode()); - if (hash > max) { - if (hash >= hardmax) { - overflowSize++; - } else { - max = hash; - } - } - } - hardmax = Math.min(hardmax, max); - Plot[] cache = new Plot[hardmax + 1]; - List overflow = new ArrayList<>(overflowSize); - ArrayList extra = new ArrayList<>(); - for (Plot plot : plots) { - int hash = MathMan.getPositiveId(plot.hashCode()); - if (hash < hardmax) { - if (hash >= 0) { - cache[hash] = plot; - } else { - extra.add(plot); - } - } else if (Math.abs(plot.getId().x) > 15446 || Math.abs(plot.getId().y) > 15446) { - extra.add(plot); - } else { - overflow.add(plot); - } - } - Plot[] overflowArray = overflow.toArray(new Plot[overflow.size()]); - sortPlotsByHash(overflowArray); - ArrayList result = new ArrayList<>(cache.length + overflowArray.length); - for (Plot plot : cache) { - if (plot != null) { - result.add(plot); - } - } - Collections.addAll(result, overflowArray); - for (Plot plot : extra) { - result.add(plot); - } - return result; - } - - /** - * Unchecked, use {@link #sortPlots(Collection, SortType, PlotArea)} instead which will in turn call this. - * - * @param input an array of plots to sort - */ - // TODO: Re-evaluate deprecation of this, as it's being used internally - @Deprecated public void sortPlotsByHash(Plot[] input) { - List[] bucket = new ArrayList[32]; - for (int i = 0; i < bucket.length; i++) { - bucket[i] = new ArrayList<>(); - } - boolean maxLength = false; - int placement = 1; - while (!maxLength) { - maxLength = true; - for (Plot i : input) { - int tmp = MathMan.getPositiveId(i.hashCode()) / placement; - bucket[tmp & 31].add(i); - if (maxLength && tmp > 0) { - maxLength = false; - } - } - int a = 0; - for (int b = 0; b < 32; b++) { - for (Plot i : bucket[b]) { - input[a++] = i; - } - bucket[b].clear(); - } - placement *= 32; - } - } - - // TODO: Re-evaluate deprecation of this, as it's being used internally - @Deprecated public ArrayList sortPlotsByTimestamp(Collection plots) { - int hardMax = 256000; - int max = 0; - int overflowSize = 0; - for (Plot plot : plots) { - int hash = MathMan.getPositiveId(plot.hashCode()); - if (hash > max) { - if (hash >= hardMax) { - overflowSize++; - } else { - max = hash; - } - } - } - hardMax = Math.min(hardMax, max); - Plot[] cache = new Plot[hardMax + 1]; - List overflow = new ArrayList<>(overflowSize); - ArrayList extra = new ArrayList<>(); - for (Plot plot : plots) { - int hash = MathMan.getPositiveId(plot.hashCode()); - if (hash < hardMax) { - if (hash >= 0) { - cache[hash] = plot; - } else { - extra.add(plot); - } - } else if (Math.abs(plot.getId().x) > 15446 || Math.abs(plot.getId().y) > 15446) { - extra.add(plot); - } else { - overflow.add(plot); - } - } - Plot[] overflowArray = overflow.toArray(new Plot[overflow.size()]); - sortPlotsByHash(overflowArray); - ArrayList result = new ArrayList<>(cache.length + overflowArray.length); - for (Plot plot : cache) { - if (plot != null) { - result.add(plot); - } - } - Collections.addAll(result, overflowArray); - for (Plot plot : extra) { - result.add(plot); - } - return result; - } - - /** - * Sort plots by creation timestamp. - * - * @param input - * @return - * @deprecated Unchecked, use {@link #sortPlots(Collection, SortType, PlotArea)} instead which will call this after checks - */ - // TODO: Re-evaluate deprecation of this, as it's being used internally - @Deprecated public List sortPlotsByModified(Collection input) { - List list; - if (input instanceof List) { - list = (List) input; - } else { - list = new ArrayList<>(input); - } - Collections.sort(list, new Comparator() { - @Override public int compare(Plot a, Plot b) { - return Long.compare(ExpireManager.IMP.getTimestamp(a.owner), - ExpireManager.IMP.getTimestamp(b.owner)); - } - }); - return list; - } - - public ArrayList sortPlots(Collection plots) { - return sortPlots(plots, SortType.DISTANCE_FROM_ORIGIN, null); - } - - /** - * Sort a collection of plots by world (with a priority world), then - * by hashcode. - * - * @param plots the plots to sort - * @param type The sorting method to use for each world (timestamp, or hash) - * @param priorityArea Use null, "world", or "gibberish" if you - * want default world order - * @return ArrayList of plot - */ - public ArrayList sortPlots(Collection plots, SortType type, - final PlotArea priorityArea) { - // group by world - // sort each - HashMap> map = new HashMap<>(); - int totalSize = getPlotCount(); - if (plots.size() == totalSize) { - for (PlotArea area : plotAreaManager.getAllPlotAreas()) { - map.put(area, area.getPlots()); - } - } else { - for (PlotArea area : plotAreaManager.getAllPlotAreas()) { - map.put(area, new ArrayList(0)); - } - Collection lastList = null; - PlotArea lastWorld = null; - for (Plot plot : plots) { - if (lastWorld == plot.getArea()) { - lastList.add(plot); - } else { - lastWorld = plot.getArea(); - lastList = map.get(lastWorld); - lastList.add(plot); - } - } - } - List areas = Arrays.asList(plotAreaManager.getAllPlotAreas()); - Collections.sort(areas, new Comparator() { - @Override public int compare(PlotArea a, PlotArea b) { - if (priorityArea != null) { - if (a.equals(priorityArea)) { - return -1; - } else if (b.equals(priorityArea)) { - return 1; - } - } - return a.hashCode() - b.hashCode(); - } - }); - ArrayList toReturn = new ArrayList<>(plots.size()); - for (PlotArea area : areas) { - switch (type) { - case CREATION_DATE: - toReturn.addAll(sortPlotsByTemp(map.get(area))); - break; - case CREATION_DATE_TIMESTAMP: - toReturn.addAll(sortPlotsByTimestamp(map.get(area))); - break; - case DISTANCE_FROM_ORIGIN: - toReturn.addAll(sortPlotsByHash(map.get(area))); - break; - case LAST_MODIFIED: - toReturn.addAll(sortPlotsByModified(map.get(area))); - break; - default: - break; - } - } - return toReturn; - } - - /** - * A more generic way to filter plots - make your own method - * if you need complex filters. - * - * @param filters the filter - * @return a filtered set of plots - */ - public Set getPlots(final PlotFilter... filters) { - final HashSet set = new HashSet<>(); - foreachPlotArea(new RunnableVal() { - @Override public void run(PlotArea value) { - for (PlotFilter filter : filters) { - if (!filter.allowsArea(value)) { - return; - } - } - loop: - for (Entry entry2 : value.getPlotEntries()) { - Plot plot = entry2.getValue(); - for (PlotFilter filter : filters) { - if (!filter.allowsPlot(plot)) { - continue loop; - } - } - set.add(plot); - } - } - }); - return set; - } - - /** - * Get all the plots in a single set. - * - * @return Set of Plots - */ - public Set getPlots() { - int size = getPlotCount(); - final Set result = new HashSet<>(size); - foreachPlotArea(new RunnableVal() { - @Override public void run(PlotArea value) { - result.addAll(value.getPlots()); - } - }); - return result; - } - - public void setPlots(HashMap> plots) { - if (this.plots_tmp == null) { - this.plots_tmp = new HashMap<>(); - } - for (Entry> entry : plots.entrySet()) { - String world = entry.getKey(); - PlotArea area = getPlotArea(world, null); - if (area == null) { - HashMap map = this.plots_tmp.get(world); - if (map == null) { - map = new HashMap<>(); - this.plots_tmp.put(world, map); - } - map.putAll(entry.getValue()); - } else { - for (Plot plot : entry.getValue().values()) { - plot.setArea(area); - area.addPlot(plot); - } - } - } - } - - /** - * Get all the plots owned by a player name. - * - * @param world the world - * @param player the plot owner - * @return Set of Plot - */ - public Set getPlots(String world, String player) { - final UUID uuid = UUIDHandler.getUUID(player, null); - return getPlots(world, uuid); - } - - /** - * Get all the plots owned by a player name. - * - * @param area the PlotArea - * @param player the plot owner - * @return Set of Plot - */ - public Set getPlots(PlotArea area, String player) { - UUID uuid = UUIDHandler.getUUID(player, null); - return getPlots(area, uuid); - } - - /** - * Get all plots by a PlotPlayer. - * - * @param world the world - * @param player the plot owner - * @return Set of plot - */ - public Set getPlots(String world, PlotPlayer player) { - return getPlots(world, player.getUUID()); - } - - /** - * Get all plots by a PlotPlayer. - * - * @param area the PlotArea - * @param player the plot owner - * @return Set of plot - */ - public Set getPlots(PlotArea area, PlotPlayer player) { - return getPlots(area, player.getUUID()); - } - - /** - * Get all plots by a UUID in a world. - * - * @param world the world - * @param uuid the plot owner - * @return Set of plot - */ - public Set getPlots(String world, UUID uuid) { - final Set plots = new HashSet<>(); - for (final Plot plot : getPlots(world)) { - if (plot.hasOwner() && plot.isOwnerAbs(uuid)) { - plots.add(plot); - } - } - return Collections.unmodifiableSet(plots); - } - - /** - * Get all plots by a UUID in an area. - * - * @param area the {@code PlotArea} - * @param uuid the plot owner - * @return Set of plots - */ - public Set getPlots(PlotArea area, UUID uuid) { - final Set plots = new HashSet<>(); - for (Plot plot : getPlots(area)) { - if (plot.hasOwner() && plot.isOwnerAbs(uuid)) { - plots.add(plot); - } - } - return Collections.unmodifiableSet(plots); - } - - /** - * Check if a plot world. - * - * @param world the world - * @return if a plot world is registered - * @see #getPlotAreaByString(String) to get the PlotArea object - */ - public boolean hasPlotArea(String world) { - return plotAreaManager.getPlotAreas(world, null).length != 0; - } - - public Collection getPlots(String world) { - final Set set = new HashSet<>(); - foreachPlotArea(world, new RunnableVal() { - @Override public void run(PlotArea value) { - set.addAll(value.getPlots()); - } - }); - return set; - } - - /** - * Get the plots for a PlotPlayer. - * - * @param player the player to retrieve the plots for - * @return Set of Plot - */ - public Set getPlots(PlotPlayer player) { - return getPlots(player.getUUID()); - } - - public Collection getPlots(PlotArea area) { - return area == null ? EMPTY_SET : area.getPlots(); - } - - public Plot getPlot(PlotArea area, PlotId id) { - return area == null ? null : id == null ? null : area.getPlot(id); - } - - public Set getBasePlots(PlotPlayer player) { - return getBasePlots(player.getUUID()); - } - - /** - * Get the plots for a UUID. - * - * @param uuid the plot owner - * @return Set of Plot's owned by the player - */ - public Set getPlots(final UUID uuid) { - final Set plots = new HashSet<>(); - foreachPlot(new RunnableVal() { - @Override public void run(Plot value) { - if (value.isOwnerAbs(uuid)) { - plots.add(value); - } - } - }); - return Collections.unmodifiableSet(plots); - } - - public boolean hasPlot(final UUID uuid) { - for (final PlotArea area : plotAreaManager.getAllPlotAreas()) { - if (area.hasPlot(uuid)) - return true; - } - return false; - } - - public Set getBasePlots(final UUID uuid) { - final Set plots = new HashSet<>(); - foreachBasePlot(new RunnableVal() { - @Override public void run(Plot value) { - if (value.isOwner(uuid)) { - plots.add(value); - } - } - }); - return Collections.unmodifiableSet(plots); - } - - /** - * Get the plots for a UUID. - * - * @param uuid the UUID of the owner - * @return Set of Plot - */ - public Set getPlotsAbs(final UUID uuid) { - final Set plots = new HashSet<>(); - foreachPlot(new RunnableVal() { - @Override public void run(Plot value) { - if (value.isOwnerAbs(uuid)) { - plots.add(value); - } - } - }); - return Collections.unmodifiableSet(plots); - } - - /** - * Unregister a plot from local memory (does not call DB). - * - * @param plot the plot to remove - * @param callEvent If to call an event about the plot being removed - * @return true if plot existed | false if it didn't - */ - public boolean removePlot(Plot plot, boolean callEvent) { - if (plot == null) { - return false; - } - if (callEvent) { - EventUtil.manager.callDelete(plot); - } - if (plot.getArea().removePlot(plot.getId())) { - PlotId last = (PlotId) plot.getArea().getMeta("lastPlot"); - int last_max = Math.max(Math.abs(last.x), Math.abs(last.y)); - int this_max = Math.max(Math.abs(plot.getId().x), Math.abs(plot.getId().y)); - if (this_max < last_max) { - plot.getArea().setMeta("lastPlot", plot.getId()); - } - return true; - } - return false; - } - - /** - * This method is called by the PlotGenerator class normally. - *
    - *
  • Initializes the PlotArea and PlotManager classes - *
  • Registers the PlotArea and PlotManager classes - *
  • Loads (and/or generates) the PlotArea configuration - *
  • Sets up the world border if configured - *
- * - *

If loading an augmented plot world: - *

    - *
  • Creates the AugmentedPopulator classes - *
  • Injects the AugmentedPopulator classes if required - *
- * - * @param world the world to load - * @param baseGenerator The generator for that world, or null - */ - public void loadWorld(String world, GeneratorWrapper baseGenerator) { - if (world.equals("CheckingPlotSquaredGenerator")) { - return; - } - this.plotAreaManager.addWorld(world); - Set worlds; - if (this.worlds.contains("worlds")) { - worlds = this.worlds.getConfigurationSection("worlds").getKeys(false); - } else { - worlds = new HashSet<>(); - } - String path = "worlds." + world; - ConfigurationSection worldSection = this.worlds.getConfigurationSection(path); - int type; - if (worldSection != null) { - type = worldSection.getInt("generator.type", 0); - } else { - type = 0; - } - if (type == 0) { - if (plotAreaManager.getPlotAreas(world, null).length != 0) { - debug("World possibly already loaded: " + world); - return; - } - IndependentPlotGenerator plotGenerator; - if (baseGenerator != null && baseGenerator.isFull()) { - plotGenerator = baseGenerator.getPlotGenerator(); - } else if (worldSection != null) { - String secondaryGeneratorName = worldSection.getString("generator.plugin"); - GeneratorWrapper secondaryGenerator = - this.IMP.getGenerator(world, secondaryGeneratorName); - if (secondaryGenerator != null && secondaryGenerator.isFull()) { - plotGenerator = secondaryGenerator.getPlotGenerator(); - } else { - String primaryGeneratorName = worldSection.getString("generator.init"); - GeneratorWrapper primaryGenerator = - this.IMP.getGenerator(world, primaryGeneratorName); - if (primaryGenerator != null && primaryGenerator.isFull()) { - plotGenerator = primaryGenerator.getPlotGenerator(); - } else { - return; - } - } - } else { - return; - } - // Conventional plot generator - PlotArea plotArea = plotGenerator.getNewPlotArea(world, null, null, null); - PlotManager plotManager = plotGenerator.getNewPlotManager(); - PlotSquared.log(C.PREFIX + "&aDetected world load for '" + world + "'"); - PlotSquared.log(C.PREFIX + "&3 - generator: &7" + baseGenerator + ">" + plotGenerator); - PlotSquared.log(C.PREFIX + "&3 - plotworld: &7" + plotArea.getClass().getName()); - PlotSquared - .log(C.PREFIX + "&3 - plotAreaManager: &7" + plotManager.getClass().getName()); - if (!this.worlds.contains(path)) { - this.worlds.createSection(path); - worldSection = this.worlds.getConfigurationSection(path); - } - plotArea.saveConfiguration(worldSection); - plotArea.loadDefaultConfiguration(worldSection); - try { - this.worlds.save(this.worldsFile); - } catch (IOException e) { - e.printStackTrace(); - } - // Now add it - addPlotArea(plotArea); - plotGenerator.initialize(plotArea); - } else { - if (!worlds.contains(world)) { - return; - } - ConfigurationSection areasSection = worldSection.getConfigurationSection("areas"); - if (areasSection == null) { - if (plotAreaManager.getPlotAreas(world, null).length != 0) { - debug("World possibly already loaded: " + world); - return; - } - PlotSquared.log(C.PREFIX + "&aDetected world load for '" + world + "'"); - String gen_string = worldSection.getString("generator.plugin", IMP.getPluginName()); - if (type == 2) { - Set clusters = this.clusters_tmp != null ? - this.clusters_tmp.get(world) : - new HashSet(); - if (clusters == null) { - throw new IllegalArgumentException("No cluster exists for world: " + world); - } - ArrayDeque toLoad = new ArrayDeque<>(); - for (PlotCluster cluster : clusters) { - PlotId pos1 = cluster.getP1(); // Cluster pos1 - PlotId pos2 = cluster.getP2(); // Cluster pos2 - String name = cluster.getName(); // Cluster name - String fullId = name + "-" + pos1 + "-" + pos2; - worldSection.createSection("areas." + fullId); - DBFunc.replaceWorld(world, world + ";" + name, pos1, pos2); // NPE - - PlotSquared.log(C.PREFIX + "&3 - " + name + "-" + pos1 + "-" + pos2); - GeneratorWrapper areaGen = this.IMP.getGenerator(world, gen_string); - if (areaGen == null) { - throw new IllegalArgumentException("Invalid Generator: " + gen_string); - } - PlotArea pa = - areaGen.getPlotGenerator().getNewPlotArea(world, name, pos1, pos2); - pa.saveConfiguration(worldSection); - pa.loadDefaultConfiguration(worldSection); - try { - this.worlds.save(this.worldsFile); - } catch (IOException e) { - e.printStackTrace(); - } - PlotSquared - .log(C.PREFIX + "&c | &9generator: &7" + baseGenerator + ">" + areaGen); - PlotSquared.log(C.PREFIX + "&c | &9plotworld: &7" + pa); - PlotSquared.log(C.PREFIX + "&c | &9manager: &7" + pa); - PlotSquared.log(C.PREFIX + "&cNote: &7Area created for cluster:" + name - + " (invalid or old configuration?)"); - areaGen.getPlotGenerator().initialize(pa); - areaGen.augment(pa); - toLoad.add(pa); - } - for (PlotArea area : toLoad) { - addPlotArea(area); - } - return; - } - GeneratorWrapper areaGen = this.IMP.getGenerator(world, gen_string); - if (areaGen == null) { - throw new IllegalArgumentException("Invalid Generator: " + gen_string); - } - PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, null, null, null); - pa.saveConfiguration(worldSection); - pa.loadDefaultConfiguration(worldSection); - try { - this.worlds.save(this.worldsFile); - } catch (IOException e) { - e.printStackTrace(); - } - PlotSquared.log(C.PREFIX + "&3 - generator: &7" + baseGenerator + ">" + areaGen); - PlotSquared.log(C.PREFIX + "&3 - plotworld: &7" + pa); - PlotSquared.log(C.PREFIX + "&3 - plotAreaManager: &7" + pa.getPlotManager()); - areaGen.getPlotGenerator().initialize(pa); - areaGen.augment(pa); - addPlotArea(pa); - return; - } - if (type == 1) { - throw new IllegalArgumentException( - "Invalid type for multi-area world. Expected `2`, got `" + 1 + "`"); - } - for (String areaId : areasSection.getKeys(false)) { - PlotSquared.log(C.PREFIX + "&3 - " + areaId); - String[] split = areaId.split("(?<=[^;-])-"); - if (split.length != 3) { - throw new IllegalArgumentException("Invalid Area identifier: " + areaId - + ". Expected form `--`"); - } - String name = split[0]; - PlotId pos1 = PlotId.fromString(split[1]); - PlotId pos2 = PlotId.fromString(split[2]); - if (pos1 == null || pos2 == null || name.isEmpty()) { - throw new IllegalArgumentException("Invalid Area identifier: " + areaId - + ". Expected form `--`"); - } - PlotArea existing = getPlotArea(world, name); - if (existing != null && name.equals(existing.id)) { - continue; - } - ConfigurationSection section = areasSection.getConfigurationSection(areaId); - YamlConfiguration clone = new YamlConfiguration(); - for (String key : section.getKeys(true)) { - if (section.get(key) instanceof MemorySection) { - continue; - } - if (!clone.contains(key)) { - clone.set(key, section.get(key)); - } - } - for (String key : worldSection.getKeys(true)) { - if (worldSection.get(key) instanceof MemorySection) { - continue; - } - if (!key.startsWith("areas") && !clone.contains(key)) { - clone.set(key, worldSection.get(key)); - } - } - String gen_string = clone.getString("generator.plugin", IMP.getPluginName()); - GeneratorWrapper areaGen = this.IMP.getGenerator(world, gen_string); - if (areaGen == null) { - throw new IllegalArgumentException("Invalid Generator: " + gen_string); - } - PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, name, pos1, pos2); - pa.saveConfiguration(clone); - // netSections is the combination of - for (String key : clone.getKeys(true)) { - if (clone.get(key) instanceof MemorySection) { - continue; - } - if (!worldSection.contains(key)) { - worldSection.set(key, clone.get(key)); - } else { - Object value = worldSection.get(key); - if (!Objects.equals(value, clone.get(key))) { - section.set(key, clone.get(key)); - } - } - } - pa.loadDefaultConfiguration(clone); - try { - this.worlds.save(this.worldsFile); - } catch (IOException e) { - e.printStackTrace(); - } - PlotSquared.log(C.PREFIX + "&aDetected area load for '" + world + "'"); - PlotSquared.log(C.PREFIX + "&c | &9generator: &7" + baseGenerator + ">" + areaGen); - PlotSquared.log(C.PREFIX + "&c | &9plotworld: &7" + pa); - PlotSquared.log(C.PREFIX + "&c | &9manager: &7" + pa.getPlotManager()); - areaGen.getPlotGenerator().initialize(pa); - areaGen.augment(pa); - addPlotArea(pa); - } - } - } - - /** - * Setup the configuration for a plot world based on world arguments. - * - * - * e.g. /mv create <world> normal -g PlotSquared:<args> - * - * @param world The name of the world - * @param args The arguments - * @param generator the plot generator - * @return boolean | if valid arguments were provided - */ - public boolean setupPlotWorld(String world, String args, IndependentPlotGenerator generator) { - if (args != null && !args.isEmpty()) { - // save configuration - - final List validArguments = Arrays - .asList("s=", "size=", "g=", "gap=", "h=", "height=", "f=", "floor=", "m=", "main=", - "w=", "wall=", "b=", "border="); - - // Calculate the number of expected arguments - int expected = 0; - for (final String validArgument : validArguments) { - if (args.toLowerCase(Locale.ENGLISH).contains(validArgument)) { - expected += 1; - } - } - - String[] split = args.toLowerCase(Locale.ENGLISH).split(","); - - if (split.length > expected) { - // This means we have multi-block block buckets - String[] combinedArgs = new String[expected]; - int index = 0; - - StringBuilder argBuilder = new StringBuilder(); - outer: - for (final String string : split) { - for (final String validArgument : validArguments) { - if (string.contains(validArgument)) { - if (!argBuilder.toString().isEmpty()) { - combinedArgs[index++] = argBuilder.toString(); - argBuilder = new StringBuilder(); - } - argBuilder.append(string); - continue outer; - } - } - if (argBuilder.toString().charAt(argBuilder.length() - 1) != '=') { - argBuilder.append(","); - } - argBuilder.append(string); - } - - if (!argBuilder.toString().isEmpty()) { - combinedArgs[index] = argBuilder.toString(); - } - - split = combinedArgs; - } - - HybridPlotWorld plotworld = new HybridPlotWorld(world, null, generator, null, null); - for (String element : split) { - String[] pair = element.split("="); - if (pair.length != 2) { - PlotSquared.log("&cNo value provided for: &7" + element); - return false; - } - String key = pair[0].toLowerCase(); - String value = pair[1]; - String base = "worlds." + world + "."; - try { - switch (key) { - case "s": - case "size": - this.worlds.set(base + "plot.size", - Configuration.INTEGER.parseString(value).shortValue()); - break; - case "g": - case "gap": - this.worlds.set(base + "road.width", - Configuration.INTEGER.parseString(value).shortValue()); - break; - case "h": - case "height": - this.worlds.set(base + "road.height", - Configuration.INTEGER.parseString(value).shortValue()); - this.worlds.set(base + "plot.height", - Configuration.INTEGER.parseString(value).shortValue()); - this.worlds.set(base + "wall.height", - Configuration.INTEGER.parseString(value).shortValue()); - break; - case "f": - case "floor": - this.worlds.set(base + "plot.floor", - Configuration.BLOCK_BUCKET.parseString(value).toString()); - break; - case "m": - case "main": - this.worlds.set(base + "plot.filling", - Configuration.BLOCK_BUCKET.parseString(value).toString()); - break; - case "w": - case "wall": - this.worlds.set(base + "wall.filling", - Configuration.BLOCK_BUCKET.parseString(value).toString()); - break; - case "b": - case "border": - this.worlds.set(base + "wall.block", - Configuration.BLOCK_BUCKET.parseString(value).toString()); - break; - default: - PlotSquared.log("&cKey not found: &7" + element); - return false; - } - } catch (Exception e) { - e.printStackTrace(); - PlotSquared.log("&cInvalid value: &7" + value + " in arg " + element); - return false; - } - } - try { - ConfigurationSection section = - this.worlds.getConfigurationSection("worlds." + world); - plotworld.saveConfiguration(section); - plotworld.loadConfiguration(section); - this.worlds.save(this.worldsFile); - } catch (IOException e) { - e.printStackTrace(); - } - } + public boolean hasPlot(final UUID uuid) { + for (final PlotArea area : plotAreaManager.getAllPlotAreas()) { + if (area.hasPlot(uuid)) { return true; + } } + return false; + } - public boolean canUpdate(@NonNull final String current, @NonNull final String other) { - final String s1 = normalisedVersion(current); - final String s2 = normalisedVersion(other); - return s1.compareTo(s2) < 0; - } - - public String normalisedVersion(@NonNull final String version) { - final String[] split = Pattern.compile(".", Pattern.LITERAL).split(version); - final StringBuilder sb = new StringBuilder(); - for (final String s : split) { - sb.append(String.format("%" + 4 + 's', s)); + public Set getBasePlots(final UUID uuid) { + final Set plots = new HashSet<>(); + foreachBasePlot(new RunnableVal() { + @Override + public void run(Plot value) { + if (value.isOwner(uuid)) { + plots.add(value); } - return sb.toString(); - } + } + }); + return Collections.unmodifiableSet(plots); + } - public boolean update(PlotPlayer sender, URL url) { - try { - String name = this.jarFile.getName(); - File newJar = new File("plugins/update/" + name); - MainUtil.sendMessage(sender, "$1Downloading from provided URL: &7" + url); - URLConnection con = url.openConnection(); - try (InputStream stream = con.getInputStream()) { - File parent = newJar.getParentFile(); - if (!parent.exists()) { - parent.mkdirs(); - } - MainUtil.sendMessage(sender, "$2 - Output: " + newJar); - if (!newJar.delete()) { - MainUtil.sendMessage(sender, "Failed to update " + IMP.getPluginName() + ""); - MainUtil.sendMessage(sender, "Jar file failed to delete."); - MainUtil.sendMessage(sender, " - Please update manually"); - } - Files.copy(stream, newJar.toPath()); - } - MainUtil.sendMessage(sender, - "$1The update will take effect when the server is restarted next"); - return true; - } catch (IOException e) { - MainUtil.sendMessage(sender, "Failed to update " + IMP.getPluginName() + ""); - MainUtil.sendMessage(sender, " - Please update manually"); - PlotSquared.log("============ Stacktrace ============"); - e.printStackTrace(); - PlotSquared.log("===================================="); + /** + * Get the plots for a UUID. + * + * @param uuid the UUID of the owner + * @return Set of Plot + */ + public Set getPlotsAbs(final UUID uuid) { + final Set plots = new HashSet<>(); + foreachPlot(new RunnableVal() { + @Override + public void run(Plot value) { + if (value.isOwnerAbs(uuid)) { + plots.add(value); } - return false; - } + } + }); + return Collections.unmodifiableSet(plots); + } - /** - * Copy a file from inside the jar to a location - * - * @param file Name of the file inside PlotSquared.jar - * @param folder The output location relative to /plugins/PlotSquared/ - */ - public void copyFile(String file, String folder) { - try { - File output = this.IMP.getDirectory(); - if (!output.exists()) { - output.mkdirs(); - } - File newFile = MainUtil.getFile(output, folder + File.separator + file); - if (newFile.exists()) { - return; - } - try (InputStream stream = this.IMP.getClass().getResourceAsStream(file)) { - byte[] buffer = new byte[2048]; - if (stream == null) { - try (ZipInputStream zis = new ZipInputStream( - new FileInputStream(this.jarFile))) { - ZipEntry ze = zis.getNextEntry(); - while (ze != null) { - String name = ze.getName(); - if (name.equals(file)) { - new File(newFile.getParent()).mkdirs(); - try (FileOutputStream fos = new FileOutputStream(newFile)) { - int len; - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len); - } - } - ze = null; - } else { - ze = zis.getNextEntry(); - } - } - zis.closeEntry(); - } - return; - } - newFile.createNewFile(); - try (FileOutputStream fos = new FileOutputStream(newFile)) { - int len; - while ((len = stream.read(buffer)) > 0) { - fos.write(buffer, 0, len); - } - } - } - } catch (IOException e) { - e.printStackTrace(); - PlotSquared.log("&cCould not save " + file); + /** + * Unregister a plot from local memory (does not call DB). + * + * @param plot the plot to remove + * @param callEvent If to call an event about the plot being removed + * @return true if plot existed | false if it didn't + */ + public boolean removePlot(Plot plot, boolean callEvent) { + if (plot == null) { + return false; + } + if (callEvent) { + EventUtil.manager.callDelete(plot); + } + if (plot.getArea().removePlot(plot.getId())) { + PlotId last = (PlotId) plot.getArea().getMeta("lastPlot"); + int last_max = Math.max(Math.abs(last.x), Math.abs(last.y)); + int this_max = Math.max(Math.abs(plot.getId().x), Math.abs(plot.getId().y)); + if (this_max < last_max) { + plot.getArea().setMeta("lastPlot", plot.getId()); + } + return true; + } + return false; + } + + /** + * This method is called by the PlotGenerator class normally. + *
    + *
  • Initializes the PlotArea and PlotManager classes + *
  • Registers the PlotArea and PlotManager classes + *
  • Loads (and/or generates) the PlotArea configuration + *
  • Sets up the world border if configured + *
+ * + *

If loading an augmented plot world: + *

    + *
  • Creates the AugmentedPopulator classes + *
  • Injects the AugmentedPopulator classes if required + *
+ * + * @param world the world to load + * @param baseGenerator The generator for that world, or null + */ + public void loadWorld(String world, GeneratorWrapper baseGenerator) { + if (world.equals("CheckingPlotSquaredGenerator")) { + return; + } + this.plotAreaManager.addWorld(world); + Set worlds; + if (this.worlds.contains("worlds")) { + worlds = this.worlds.getConfigurationSection("worlds").getKeys(false); + } else { + worlds = new HashSet<>(); + } + String path = "worlds." + world; + ConfigurationSection worldSection = this.worlds.getConfigurationSection(path); + int type; + if (worldSection != null) { + type = worldSection.getInt("generator.type", 0); + } else { + type = 0; + } + if (type == 0) { + if (plotAreaManager.getPlotAreas(world, null).length != 0) { + debug("World possibly already loaded: " + world); + return; + } + IndependentPlotGenerator plotGenerator; + if (baseGenerator != null && baseGenerator.isFull()) { + plotGenerator = baseGenerator.getPlotGenerator(); + } else if (worldSection != null) { + String secondaryGeneratorName = worldSection.getString("generator.plugin"); + GeneratorWrapper secondaryGenerator = + this.IMP.getGenerator(world, secondaryGeneratorName); + if (secondaryGenerator != null && secondaryGenerator.isFull()) { + plotGenerator = secondaryGenerator.getPlotGenerator(); + } else { + String primaryGeneratorName = worldSection.getString("generator.init"); + GeneratorWrapper primaryGenerator = + this.IMP.getGenerator(world, primaryGeneratorName); + if (primaryGenerator != null && primaryGenerator.isFull()) { + plotGenerator = primaryGenerator.getPlotGenerator(); + } else { + return; + } } - } - - private Map> getPlotsRaw() { - HashMap> map = new HashMap<>(); - for (PlotArea area : this.plotAreaManager.getAllPlotAreas()) { - Map map2 = map.get(area.toString()); - if (map2 == null) { - map.put(area.toString(), area.getPlotsRaw()); - } else { - map2.putAll(area.getPlotsRaw()); - } + } else { + return; + } + // Conventional plot generator + PlotArea plotArea = plotGenerator.getNewPlotArea(world, null, null, null); + PlotManager plotManager = plotGenerator.getNewPlotManager(); + PlotSquared.log(C.PREFIX + "&aDetected world load for '" + world + "'"); + PlotSquared.log(C.PREFIX + "&3 - generator: &7" + baseGenerator + ">" + plotGenerator); + PlotSquared.log(C.PREFIX + "&3 - plotworld: &7" + plotArea.getClass().getName()); + PlotSquared + .log(C.PREFIX + "&3 - plotAreaManager: &7" + plotManager.getClass().getName()); + if (!this.worlds.contains(path)) { + this.worlds.createSection(path); + worldSection = this.worlds.getConfigurationSection(path); + } + plotArea.saveConfiguration(worldSection); + plotArea.loadDefaultConfiguration(worldSection); + try { + this.worlds.save(this.worldsFile); + } catch (IOException e) { + e.printStackTrace(); + } + // Now add it + addPlotArea(plotArea); + plotGenerator.initialize(plotArea); + } else { + if (!worlds.contains(world)) { + return; + } + ConfigurationSection areasSection = worldSection.getConfigurationSection("areas"); + if (areasSection == null) { + if (plotAreaManager.getPlotAreas(world, null).length != 0) { + debug("World possibly already loaded: " + world); + return; } - return map; - } + PlotSquared.log(C.PREFIX + "&aDetected world load for '" + world + "'"); + String gen_string = worldSection.getString("generator.plugin", IMP.getPluginName()); + if (type == 2) { + Set clusters = this.clusters_tmp != null ? + this.clusters_tmp.get(world) : + new HashSet<>(); + if (clusters == null) { + throw new IllegalArgumentException("No cluster exists for world: " + world); + } + ArrayDeque toLoad = new ArrayDeque<>(); + for (PlotCluster cluster : clusters) { + PlotId pos1 = cluster.getP1(); // Cluster pos1 + PlotId pos2 = cluster.getP2(); // Cluster pos2 + String name = cluster.getName(); // Cluster name + String fullId = name + "-" + pos1 + "-" + pos2; + worldSection.createSection("areas." + fullId); + DBFunc.replaceWorld(world, world + ";" + name, pos1, pos2); // NPE - /** - * Close the database connection. - */ - public void disable() { - try { - // Validate that all data in the db is correct - final HashSet plots = new HashSet<>(); + PlotSquared.log(C.PREFIX + "&3 - " + name + "-" + pos1 + "-" + pos2); + GeneratorWrapper areaGen = this.IMP.getGenerator(world, gen_string); + if (areaGen == null) { + throw new IllegalArgumentException("Invalid Generator: " + gen_string); + } + PlotArea pa = + areaGen.getPlotGenerator().getNewPlotArea(world, name, pos1, pos2); + pa.saveConfiguration(worldSection); + pa.loadDefaultConfiguration(worldSection); try { - foreachPlotRaw(new RunnableVal() { - @Override public void run(Plot value) { - plots.add(value); - } - }); - } catch (final Exception ignored) { + this.worlds.save(this.worldsFile); + } catch (IOException e) { + e.printStackTrace(); } - DBFunc.validatePlots(plots); - - // Close the connection - DBFunc.close(); - UUIDHandler.handleShutdown(); - } catch (NullPointerException ignored) { - ignored.printStackTrace(); - PlotSquared.log("&cCould not close database connection!"); + PlotSquared + .log(C.PREFIX + "&c | &9generator: &7" + baseGenerator + ">" + areaGen); + PlotSquared.log(C.PREFIX + "&c | &9plotworld: &7" + pa); + PlotSquared.log(C.PREFIX + "&c | &9manager: &7" + pa); + PlotSquared.log(C.PREFIX + "&cNote: &7Area created for cluster:" + name + + " (invalid or old configuration?)"); + areaGen.getPlotGenerator().initialize(pa); + areaGen.augment(pa); + toLoad.add(pa); + } + for (PlotArea area : toLoad) { + addPlotArea(area); + } + return; } - } - - /** - * Setup the database connection. - */ - public void setupDatabase() { + GeneratorWrapper areaGen = this.IMP.getGenerator(world, gen_string); + if (areaGen == null) { + throw new IllegalArgumentException("Invalid Generator: " + gen_string); + } + PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, null, null, null); + pa.saveConfiguration(worldSection); + pa.loadDefaultConfiguration(worldSection); try { - if (DBFunc.dbManager != null) { - DBFunc.dbManager.close(); + this.worlds.save(this.worldsFile); + } catch (IOException e) { + e.printStackTrace(); + } + PlotSquared.log(C.PREFIX + "&3 - generator: &7" + baseGenerator + ">" + areaGen); + PlotSquared.log(C.PREFIX + "&3 - plotworld: &7" + pa); + PlotSquared.log(C.PREFIX + "&3 - plotAreaManager: &7" + pa.getPlotManager()); + areaGen.getPlotGenerator().initialize(pa); + areaGen.augment(pa); + addPlotArea(pa); + return; + } + if (type == 1) { + throw new IllegalArgumentException( + "Invalid type for multi-area world. Expected `2`, got `" + 1 + "`"); + } + for (String areaId : areasSection.getKeys(false)) { + PlotSquared.log(C.PREFIX + "&3 - " + areaId); + String[] split = areaId.split("(?<=[^;-])-"); + if (split.length != 3) { + throw new IllegalArgumentException("Invalid Area identifier: " + areaId + + ". Expected form `--`"); + } + String name = split[0]; + PlotId pos1 = PlotId.fromString(split[1]); + PlotId pos2 = PlotId.fromString(split[2]); + if (pos1 == null || pos2 == null || name.isEmpty()) { + throw new IllegalArgumentException("Invalid Area identifier: " + areaId + + ". Expected form `--`"); + } + PlotArea existing = getPlotArea(world, name); + if (existing != null && name.equals(existing.id)) { + continue; + } + ConfigurationSection section = areasSection.getConfigurationSection(areaId); + YamlConfiguration clone = new YamlConfiguration(); + for (String key : section.getKeys(true)) { + if (section.get(key) instanceof MemorySection) { + continue; + } + if (!clone.contains(key)) { + clone.set(key, section.get(key)); + } + } + for (String key : worldSection.getKeys(true)) { + if (worldSection.get(key) instanceof MemorySection) { + continue; + } + if (!key.startsWith("areas") && !clone.contains(key)) { + clone.set(key, worldSection.get(key)); + } + } + String gen_string = clone.getString("generator.plugin", IMP.getPluginName()); + GeneratorWrapper areaGen = this.IMP.getGenerator(world, gen_string); + if (areaGen == null) { + throw new IllegalArgumentException("Invalid Generator: " + gen_string); + } + PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, name, pos1, pos2); + pa.saveConfiguration(clone); + // netSections is the combination of + for (String key : clone.getKeys(true)) { + if (clone.get(key) instanceof MemorySection) { + continue; + } + if (!worldSection.contains(key)) { + worldSection.set(key, clone.get(key)); + } else { + Object value = worldSection.get(key); + if (!Objects.equals(value, clone.get(key))) { + section.set(key, clone.get(key)); } - Database database; - if (Storage.MySQL.USE) { - database = new MySQL(Storage.MySQL.HOST, Storage.MySQL.PORT, Storage.MySQL.DATABASE, - Storage.MySQL.USER, Storage.MySQL.PASSWORD); - } else if (Storage.SQLite.USE) { - File file = MainUtil.getFile(IMP.getDirectory(), Storage.SQLite.DB + ".db"); - database = new SQLite(file); - } else { - PlotSquared.log(C.PREFIX + "&cNo storage type is set!"); - this.IMP.disable(); - return; + } + } + pa.loadDefaultConfiguration(clone); + try { + this.worlds.save(this.worldsFile); + } catch (IOException e) { + e.printStackTrace(); + } + PlotSquared.log(C.PREFIX + "&aDetected area load for '" + world + "'"); + PlotSquared.log(C.PREFIX + "&c | &9generator: &7" + baseGenerator + ">" + areaGen); + PlotSquared.log(C.PREFIX + "&c | &9plotworld: &7" + pa); + PlotSquared.log(C.PREFIX + "&c | &9manager: &7" + pa.getPlotManager()); + areaGen.getPlotGenerator().initialize(pa); + areaGen.augment(pa); + addPlotArea(pa); + } + } + } + + /** + * Setup the configuration for a plot world based on world arguments. + * + * + * e.g. /mv create <world> normal -g PlotSquared:<args> + * + * @param world The name of the world + * @param args The arguments + * @param generator the plot generator + * @return boolean | if valid arguments were provided + */ + public boolean setupPlotWorld(String world, String args, IndependentPlotGenerator generator) { + if (args != null && !args.isEmpty()) { + // save configuration + + final List validArguments = Arrays + .asList("s=", "size=", "g=", "gap=", "h=", "height=", "f=", "floor=", "m=", "main=", + "w=", "wall=", "b=", "border="); + + // Calculate the number of expected arguments + int expected = 0; + for (final String validArgument : validArguments) { + if (args.toLowerCase(Locale.ENGLISH).contains(validArgument)) { + expected += 1; + } + } + + String[] split = args.toLowerCase(Locale.ENGLISH).split(","); + + if (split.length > expected) { + // This means we have multi-block block buckets + String[] combinedArgs = new String[expected]; + int index = 0; + + StringBuilder argBuilder = new StringBuilder(); + outer: + for (final String string : split) { + for (final String validArgument : validArguments) { + if (string.contains(validArgument)) { + if (!argBuilder.toString().isEmpty()) { + combinedArgs[index++] = argBuilder.toString(); + argBuilder = new StringBuilder(); + } + argBuilder.append(string); + continue outer; } - DBFunc.dbManager = new SQLManager(database, Storage.PREFIX, false); - this.plots_tmp = DBFunc.getPlots(); - if (plotAreaManager instanceof SinglePlotAreaManager) { - SinglePlotArea area = ((SinglePlotAreaManager) plotAreaManager).getArea(); - addPlotArea(area); - ConfigurationSection section = worlds.getConfigurationSection("worlds.*"); - if (section == null) { - section = worlds.createSection("worlds.*"); + } + if (argBuilder.toString().charAt(argBuilder.length() - 1) != '=') { + argBuilder.append(","); + } + argBuilder.append(string); + } + + if (!argBuilder.toString().isEmpty()) { + combinedArgs[index] = argBuilder.toString(); + } + + split = combinedArgs; + } + + HybridPlotWorld plotworld = new HybridPlotWorld(world, null, generator, null, null); + for (String element : split) { + String[] pair = element.split("="); + if (pair.length != 2) { + PlotSquared.log("&cNo value provided for: &7" + element); + return false; + } + String key = pair[0].toLowerCase(); + String value = pair[1]; + String base = "worlds." + world + "."; + try { + switch (key) { + case "s": + case "size": + this.worlds.set(base + "plot.size", + Configuration.INTEGER.parseString(value).shortValue()); + break; + case "g": + case "gap": + this.worlds.set(base + "road.width", + Configuration.INTEGER.parseString(value).shortValue()); + break; + case "h": + case "height": + this.worlds.set(base + "road.height", + Configuration.INTEGER.parseString(value).shortValue()); + this.worlds.set(base + "plot.height", + Configuration.INTEGER.parseString(value).shortValue()); + this.worlds.set(base + "wall.height", + Configuration.INTEGER.parseString(value).shortValue()); + break; + case "f": + case "floor": + this.worlds.set(base + "plot.floor", + Configuration.BLOCK_BUCKET.parseString(value).toString()); + break; + case "m": + case "main": + this.worlds.set(base + "plot.filling", + Configuration.BLOCK_BUCKET.parseString(value).toString()); + break; + case "w": + case "wall": + this.worlds.set(base + "wall.filling", + Configuration.BLOCK_BUCKET.parseString(value).toString()); + break; + case "b": + case "border": + this.worlds.set(base + "wall.block", + Configuration.BLOCK_BUCKET.parseString(value).toString()); + break; + default: + PlotSquared.log("&cKey not found: &7" + element); + return false; + } + } catch (Exception e) { + e.printStackTrace(); + PlotSquared.log("&cInvalid value: &7" + value + " in arg " + element); + return false; + } + } + try { + ConfigurationSection section = + this.worlds.getConfigurationSection("worlds." + world); + plotworld.saveConfiguration(section); + plotworld.loadConfiguration(section); + this.worlds.save(this.worldsFile); + } catch (IOException e) { + e.printStackTrace(); + } + } + return true; + } + + public boolean canUpdate(@NonNull final String current, @NonNull final String other) { + final String s1 = normalisedVersion(current); + final String s2 = normalisedVersion(other); + return s1.compareTo(s2) < 0; + } + + public String normalisedVersion(@NonNull final String version) { + final String[] split = Pattern.compile(".", Pattern.LITERAL).split(version); + final StringBuilder sb = new StringBuilder(); + for (final String s : split) { + sb.append(String.format("%" + 4 + 's', s)); + } + return sb.toString(); + } + + public boolean update(PlotPlayer sender, URL url) { + try { + String name = this.jarFile.getName(); + File newJar = new File("plugins/update/" + name); + MainUtil.sendMessage(sender, "$1Downloading from provided URL: &7" + url); + URLConnection con = url.openConnection(); + try (InputStream stream = con.getInputStream()) { + File parent = newJar.getParentFile(); + if (!parent.exists()) { + parent.mkdirs(); + } + MainUtil.sendMessage(sender, "$2 - Output: " + newJar); + if (!newJar.delete()) { + MainUtil.sendMessage(sender, "Failed to update " + IMP.getPluginName() + ""); + MainUtil.sendMessage(sender, "Jar file failed to delete."); + MainUtil.sendMessage(sender, " - Please update manually"); + } + Files.copy(stream, newJar.toPath()); + } + MainUtil.sendMessage(sender, + "$1The update will take effect when the server is restarted next"); + return true; + } catch (IOException e) { + MainUtil.sendMessage(sender, "Failed to update " + IMP.getPluginName() + ""); + MainUtil.sendMessage(sender, " - Please update manually"); + PlotSquared.log("============ Stacktrace ============"); + e.printStackTrace(); + PlotSquared.log("===================================="); + } + return false; + } + + /** + * Copy a file from inside the jar to a location + * + * @param file Name of the file inside PlotSquared.jar + * @param folder The output location relative to /plugins/PlotSquared/ + */ + public void copyFile(String file, String folder) { + try { + File output = this.IMP.getDirectory(); + if (!output.exists()) { + output.mkdirs(); + } + File newFile = MainUtil.getFile(output, folder + File.separator + file); + if (newFile.exists()) { + return; + } + try (InputStream stream = this.IMP.getClass().getResourceAsStream(file)) { + byte[] buffer = new byte[2048]; + if (stream == null) { + try (ZipInputStream zis = new ZipInputStream( + new FileInputStream(this.jarFile))) { + ZipEntry ze = zis.getNextEntry(); + while (ze != null) { + String name = ze.getName(); + if (name.equals(file)) { + new File(newFile.getParent()).mkdirs(); + try (FileOutputStream fos = new FileOutputStream(newFile)) { + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } } - area.saveConfiguration(section); - area.loadDefaultConfiguration(section); + ze = null; + } else { + ze = zis.getNextEntry(); + } } - this.clusters_tmp = DBFunc.getClusters(); - } catch (ClassNotFoundException | SQLException e) { - PlotSquared.log( - C.PREFIX + "&cFailed to open DATABASE connection. The plugin will disable itself."); - if (Storage.MySQL.USE) { - PlotSquared.log("$4MYSQL"); - } else if (Storage.SQLite.USE) { - PlotSquared.log("$4SQLITE"); - } - PlotSquared.log( - "&d==== Here is an ugly stacktrace, if you are interested in those things ==="); + zis.closeEntry(); + } + return; + } + newFile.createNewFile(); + try (FileOutputStream fos = new FileOutputStream(newFile)) { + int len; + while ((len = stream.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + PlotSquared.log("&cCould not save " + file); + } + } + + private Map> getPlotsRaw() { + HashMap> map = new HashMap<>(); + for (PlotArea area : this.plotAreaManager.getAllPlotAreas()) { + Map map2 = map.get(area.toString()); + if (map2 == null) { + map.put(area.toString(), area.getPlotsRaw()); + } else { + map2.putAll(area.getPlotsRaw()); + } + } + return map; + } + + /** + * Close the database connection. + */ + public void disable() { + try { + // Validate that all data in the db is correct + final HashSet plots = new HashSet<>(); + try { + foreachPlotRaw(new RunnableVal() { + @Override + public void run(Plot value) { + plots.add(value); + } + }); + } catch (final Exception ignored) { + } + DBFunc.validatePlots(plots); + + // Close the connection + DBFunc.close(); + UUIDHandler.handleShutdown(); + } catch (NullPointerException exception) { + exception.printStackTrace(); + PlotSquared.log("&cCould not close database connection!"); + } + } + + /** + * Setup the database connection. + */ + public void setupDatabase() { + try { + if (DBFunc.dbManager != null) { + DBFunc.dbManager.close(); + } + Database database; + if (Storage.MySQL.USE) { + database = new MySQL(Storage.MySQL.HOST, Storage.MySQL.PORT, Storage.MySQL.DATABASE, + Storage.MySQL.USER, Storage.MySQL.PASSWORD); + } else if (Storage.SQLite.USE) { + File file = MainUtil.getFile(IMP.getDirectory(), Storage.SQLite.DB + ".db"); + database = new SQLite(file); + } else { + PlotSquared.log(C.PREFIX + "&cNo storage type is set!"); + this.IMP.disable(); + return; + } + DBFunc.dbManager = new SQLManager(database, Storage.PREFIX, false); + PlotSquared.log("GETTING PLOTS NOW AND STORING TO PLOTS_TMP"); + for (PlotArea allPlotArea : plotAreaManager.getAllPlotAreas()) { + PlotSquared.log(allPlotArea.toString()); + } + + this.plots_tmp = DBFunc.getPlots(); + if (plotAreaManager instanceof SinglePlotAreaManager) { + SinglePlotArea area = ((SinglePlotAreaManager) plotAreaManager).getArea(); + addPlotArea(area); + ConfigurationSection section = worlds.getConfigurationSection("worlds.*"); + if (section == null) { + section = worlds.createSection("worlds.*"); + } + area.saveConfiguration(section); + area.loadDefaultConfiguration(section); + } + this.clusters_tmp = DBFunc.getClusters(); + } catch (ClassNotFoundException | SQLException e) { + PlotSquared.log( + C.PREFIX + "&cFailed to open DATABASE connection. The plugin will disable itself."); + if (Storage.MySQL.USE) { + PlotSquared.log("$4MYSQL"); + } else if (Storage.SQLite.USE) { + PlotSquared.log("$4SQLITE"); + } + PlotSquared.log( + "&d==== Here is an ugly stacktrace, if you are interested in those things ==="); + e.printStackTrace(); + PlotSquared.log("&d==== End of stacktrace ===="); + PlotSquared.log("&6Please go to the " + IMP.getPluginName() + + " 'storage.yml' and configure the database correctly."); + this.IMP.disable(); + } + } + + /** + * Setup the default configuration. + * + * @throws IOException if the config failed to save + */ + public void setupConfig() throws IOException { + String lastVersionString = this.config.getString("version"); + if (lastVersionString != null) { + String[] split = lastVersionString.split("\\."); + int[] lastVersion = new int[]{Integer.parseInt(split[0]), Integer.parseInt(split[1]), + Integer.parseInt(split[2])}; + if (checkVersion(new int[]{3, 4, 0}, lastVersion)) { + Settings.convertLegacy(configFile); + if (config.contains("worlds")) { + ConfigurationSection worldSection = config.getConfigurationSection("worlds"); + worlds.set("worlds", worldSection); + try { + worlds.save(worldsFile); + } catch (IOException e) { + PlotSquared.debug("Failed to save " + IMP.getPluginName() + " worlds.yml"); e.printStackTrace(); - PlotSquared.log("&d==== End of stacktrace ===="); - PlotSquared.log("&6Please go to the " + IMP.getPluginName() - + " 'storage.yml' and configure the database correctly."); - this.IMP.disable(); - } - } - - /** - * Setup the default configuration. - * - * @throws IOException if the config failed to save - */ - public void setupConfig() throws IOException { - String lastVersionString = this.config.getString("version"); - if (lastVersionString != null) { - String[] split = lastVersionString.split("\\."); - int[] lastVersion = new int[] {Integer.parseInt(split[0]), Integer.parseInt(split[1]), - Integer.parseInt(split[2])}; - if (checkVersion(new int[] {3, 4, 0}, lastVersion)) { - Settings.convertLegacy(configFile); - if (config.contains("worlds")) { - ConfigurationSection worldSection = config.getConfigurationSection("worlds"); - worlds.set("worlds", worldSection); - try { - worlds.save(worldsFile); - } catch (IOException e) { - PlotSquared.debug("Failed to save " + IMP.getPluginName() + " worlds.yml"); - e.printStackTrace(); - } - } - Settings.save(configFile); - } - } - Settings.load(configFile); - try { - InputStream stream = getClass().getResourceAsStream("/plugin.properties"); - BufferedReader br = new BufferedReader(new InputStreamReader(stream)); - //java.util.Scanner scanner = new java.util.Scanner(stream).useDelimiter("\\A"); - String versionString = br.readLine(); - String commitString = br.readLine(); - String dateString = br.readLine(); - //scanner.close(); - br.close(); - this.version = PlotVersion.tryParse(versionString, commitString, dateString); - Settings.DATE = new Date(100 + version.year, version.month, version.day).toGMTString(); - Settings.BUILD = "https://ci.athion.net/job/PlotSquared/" + version.build; - Settings.COMMIT = "https://github.com/IntellectualSites/PlotSquared/commit/" + Integer - .toHexString(version.hash); - System.out.println("Version is " + this.version); - } catch (Throwable ignore) { - ignore.printStackTrace(); + } } Settings.save(configFile); - config = YamlConfiguration.loadConfiguration(configFile); + } } + Settings.load(configFile); + try { + InputStream stream = getClass().getResourceAsStream("/plugin.properties"); + BufferedReader br = new BufferedReader(new InputStreamReader(stream)); + //java.util.Scanner scanner = new java.util.Scanner(stream).useDelimiter("\\A"); + String versionString = br.readLine(); + String commitString = br.readLine(); + String dateString = br.readLine(); + //scanner.close(); + br.close(); + this.version = PlotVersion.tryParse(versionString, commitString, dateString); + Settings.DATE = new Date(100 + version.year, version.month, version.day).toGMTString(); + Settings.BUILD = "https://ci.athion.net/job/PlotSquared/" + version.build; + Settings.COMMIT = "https://github.com/IntellectualSites/PlotSquared/commit/" + Integer + .toHexString(version.hash); + System.out.println("Version is " + this.version); + } catch (IOException exception) { + exception.printStackTrace(); + } + Settings.save(configFile); + config = YamlConfiguration.loadConfiguration(configFile); + } - /** - * Setup all configuration files
- * - Config: settings.yml
- * - Storage: storage.yml
- * - Translation: PlotSquared.use_THIS.yml, style.yml
- */ - public boolean setupConfigs() { - File folder = new File(this.IMP.getDirectory(), "config"); - if (!folder.exists() && !folder.mkdirs()) { - PlotSquared.log(C.PREFIX - + "&cFailed to create the /plugins/config folder. Please create it manually."); - } - try { - this.worldsFile = new File(folder, "worlds.yml"); - if (!this.worldsFile.exists() && !this.worldsFile.createNewFile()) { - PlotSquared.log( - "Could not create the worlds file, please create \"worlds.yml\" manually."); - } - this.worlds = YamlConfiguration.loadConfiguration(this.worldsFile); + /** + * Setup all configuration files
- Config: settings.yml
- Storage: storage.yml
- + * Translation: PlotSquared.use_THIS.yml, style.yml
+ */ + public boolean setupConfigs() { + File folder = new File(this.IMP.getDirectory(), "config"); + if (!folder.exists() && !folder.mkdirs()) { + PlotSquared.log(C.PREFIX + + "&cFailed to create the /plugins/config folder. Please create it manually."); + } + try { + this.worldsFile = new File(folder, "worlds.yml"); + if (!this.worldsFile.exists() && !this.worldsFile.createNewFile()) { + PlotSquared.log( + "Could not create the worlds file, please create \"worlds.yml\" manually."); + } + this.worlds = YamlConfiguration.loadConfiguration(this.worldsFile); - if (this.worlds.contains("worlds")) { - if (!this.worlds.contains("configuration_version") || !this.worlds - .getString("configuration_version") - .equalsIgnoreCase(LegacyConverter.CONFIGURATION_VERSION)) { - // Conversion needed - log(C.LEGACY_CONFIG_FOUND.s()); - try { - com.google.common.io.Files - .copy(this.worldsFile, new File(folder, "worlds.yml.old")); - log(C.LEGACY_CONFIG_BACKUP.s()); - final ConfigurationSection worlds = - this.worlds.getConfigurationSection("worlds"); - final LegacyConverter converter = new LegacyConverter(worlds); - converter.convert(); - this.worlds - .set("configuration_version", LegacyConverter.CONFIGURATION_VERSION); - this.worlds.set("worlds", worlds); // Redundant, but hey... ¯\_(ツ)_/¯ - this.worlds.save(this.worldsFile); - log(C.LEGACY_CONFIG_DONE.s()); - } catch (final Exception e) { - log(C.LEGACY_CONFIG_CONVERSION_FAILED.s()); - e.printStackTrace(); - } - // Disable plugin - this.IMP.shutdown(); - return false; - } - } else { - this.worlds.set("configuration_version", LegacyConverter.CONFIGURATION_VERSION); - } - } catch (IOException ignored) { - PlotSquared.log("Failed to save settings.yml"); - } - try { - this.configFile = new File(folder, "settings.yml"); - if (!this.configFile.exists() && !this.configFile.createNewFile()) { - PlotSquared.log( - "Could not create the settings file, please create \"settings.yml\" manually."); - } - this.config = YamlConfiguration.loadConfiguration(this.configFile); - setupConfig(); - } catch (IOException ignored) { - PlotSquared.log("Failed to save settings.yml"); - } - try { - this.styleFile = MainUtil.getFile(IMP.getDirectory(), - Settings.Paths.TRANSLATIONS + File.separator + "style.yml"); - if (!this.styleFile.exists()) { - if (!this.styleFile.getParentFile().exists()) { - this.styleFile.getParentFile().mkdirs(); - } - if (!this.styleFile.createNewFile()) { - PlotSquared.log( - "Could not create the style file, please create \"translations/style.yml\" manually"); - } - } - this.style = YamlConfiguration.loadConfiguration(this.styleFile); - setupStyle(); - } catch (IOException err) { - err.printStackTrace(); - PlotSquared.log("failed to save style.yml"); - } - try { - this.storageFile = new File(folder, "storage.yml"); - if (!this.storageFile.exists() && !this.storageFile.createNewFile()) { - PlotSquared.log( - "Could not the storage settings file, please create \"storage.yml\" manually."); - } - this.storage = YamlConfiguration.loadConfiguration(this.storageFile); - setupStorage(); - } catch (IOException ignored) { - PlotSquared.log("Failed to save storage.yml"); - } - try { - this.commandsFile = new File(folder, "commands.yml"); - if (!this.commandsFile.exists() && !this.commandsFile.createNewFile()) { - PlotSquared.log( - "Could not the storage settings file, please create \"commands.yml\" manually."); - } - this.commands = YamlConfiguration.loadConfiguration(this.commandsFile); - } catch (IOException ignored) { - PlotSquared.log("Failed to save commands.yml"); - } - try { - this.style.save(this.styleFile); - this.commands.save(this.commandsFile); - } catch (IOException e) { - PlotSquared.log("Configuration file saving failed"); + if (this.worlds.contains("worlds")) { + if (!this.worlds.contains("configuration_version") || !this.worlds + .getString("configuration_version") + .equalsIgnoreCase(LegacyConverter.CONFIGURATION_VERSION)) { + // Conversion needed + log(C.LEGACY_CONFIG_FOUND.s()); + try { + com.google.common.io.Files + .copy(this.worldsFile, new File(folder, "worlds.yml.old")); + log(C.LEGACY_CONFIG_BACKUP.s()); + final ConfigurationSection worlds = + this.worlds.getConfigurationSection("worlds"); + final LegacyConverter converter = new LegacyConverter(worlds); + converter.convert(); + this.worlds + .set("configuration_version", LegacyConverter.CONFIGURATION_VERSION); + this.worlds.set("worlds", worlds); // Redundant, but hey... ¯\_(ツ)_/¯ + this.worlds.save(this.worldsFile); + log(C.LEGACY_CONFIG_DONE.s()); + } catch (final Exception e) { + log(C.LEGACY_CONFIG_CONVERSION_FAILED.s()); e.printStackTrace(); + } + // Disable plugin + this.IMP.shutdown(); + return false; } - return true; + } else { + this.worlds.set("configuration_version", LegacyConverter.CONFIGURATION_VERSION); + } + } catch (IOException ignored) { + PlotSquared.log("Failed to save settings.yml"); } - - /** - * Setup the storage file (load + save missing nodes). - */ - private void setupStorage() { - Storage.load(storageFile); - Storage.save(storageFile); - storage = YamlConfiguration.loadConfiguration(storageFile); + try { + this.configFile = new File(folder, "settings.yml"); + if (!this.configFile.exists() && !this.configFile.createNewFile()) { + PlotSquared.log( + "Could not create the settings file, please create \"settings.yml\" manually."); + } + this.config = YamlConfiguration.loadConfiguration(this.configFile); + setupConfig(); + } catch (IOException ignored) { + PlotSquared.log("Failed to save settings.yml"); } - - /** - * Show startup debug information. - */ - private void showDebug() { - if (Settings.DEBUG) { - Map components = Settings.getFields(Settings.Enabled_Components.class); - for (Entry component : components.entrySet()) { - PlotSquared.log(C.PREFIX + String - .format("&cKey: &6%s&c, Value: &6%s", component.getKey(), - component.getValue())); - } + try { + this.styleFile = MainUtil.getFile(IMP.getDirectory(), + Settings.Paths.TRANSLATIONS + File.separator + "style.yml"); + if (!this.styleFile.exists()) { + if (!this.styleFile.getParentFile().exists()) { + this.styleFile.getParentFile().mkdirs(); } - } - - /** - * Setup the style.yml file - */ - private void setupStyle() { - if (this.version != null) { - this.style.set("version", this.version.toString()); + if (!this.styleFile.createNewFile()) { + PlotSquared.log( + "Could not create the style file, please create \"translations/style.yml\" manually"); } - Map o = new HashMap<>(4); - o.put("color.1", "6"); - o.put("color.2", "7"); - o.put("color.3", "8"); - o.put("color.4", "3"); - if (!this.style.contains("color")) { - for (Entry node : o.entrySet()) { - this.style.set(node.getKey(), node.getValue()); - } + } + this.style = YamlConfiguration.loadConfiguration(this.styleFile); + setupStyle(); + } catch (IOException err) { + err.printStackTrace(); + PlotSquared.log("failed to save style.yml"); + } + try { + this.storageFile = new File(folder, "storage.yml"); + if (!this.storageFile.exists() && !this.storageFile.createNewFile()) { + PlotSquared.log( + "Could not the storage settings file, please create \"storage.yml\" manually."); + } + this.storage = YamlConfiguration.loadConfiguration(this.storageFile); + setupStorage(); + } catch (IOException ignored) { + PlotSquared.log("Failed to save storage.yml"); + } + try { + this.commandsFile = new File(folder, "commands.yml"); + if (!this.commandsFile.exists() && !this.commandsFile.createNewFile()) { + PlotSquared.log( + "Could not the storage settings file, please create \"commands.yml\" manually."); + } + this.commands = YamlConfiguration.loadConfiguration(this.commandsFile); + } catch (IOException ignored) { + PlotSquared.log("Failed to save commands.yml"); + } + try { + this.style.save(this.styleFile); + this.commands.save(this.commandsFile); + } catch (IOException e) { + PlotSquared.log("Configuration file saving failed"); + e.printStackTrace(); + } + return true; + } + + /** + * Setup the storage file (load + save missing nodes). + */ + private void setupStorage() { + Storage.load(storageFile); + Storage.save(storageFile); + storage = YamlConfiguration.loadConfiguration(storageFile); + } + + /** + * Show startup debug information. + */ + private void showDebug() { + if (Settings.DEBUG) { + Map components = Settings.getFields(Settings.Enabled_Components.class); + for (Entry component : components.entrySet()) { + PlotSquared.log(C.PREFIX + String + .format("&cKey: &6%s&c, Value: &6%s", component.getKey(), + component.getValue())); + } + } + } + + /** + * Setup the style.yml file + */ + private void setupStyle() { + if (this.version != null) { + this.style.set("version", this.version.toString()); + } + Map o = new HashMap<>(4); + o.put("color.1", "6"); + o.put("color.2", "7"); + o.put("color.3", "8"); + o.put("color.4", "3"); + if (!this.style.contains("color")) { + for (Entry node : o.entrySet()) { + this.style.set(node.getKey(), node.getValue()); + } + } + } + + /** + * Get the Java version. + * + * @return the java version + */ + public double getJavaVersion() { + return Double.parseDouble(System.getProperty("java.specification.version")); + } + + public void foreachPlotArea(@NonNull final RunnableVal runnable) { + for (final PlotArea area : this.plotAreaManager.getAllPlotAreas()) { + runnable.run(area); + } + } + + public void foreachPlotArea(@NonNull final String world, + @NonNull final RunnableVal runnable) { + final PlotArea[] array = this.plotAreaManager.getPlotAreas(world, null); + if (array == null) { + return; + } + for (final PlotArea area : array) { + runnable.run(area); + } + } + + public void foreachPlot(@NonNull final RunnableVal runnable) { + for (final PlotArea area : this.plotAreaManager.getAllPlotAreas()) { + area.getPlots().forEach(runnable::run); + } + } + + public void foreachPlotRaw(@NonNull final RunnableVal runnable) { + for (final PlotArea area : this.plotAreaManager.getAllPlotAreas()) { + area.getPlots().forEach(runnable::run); + } + if (this.plots_tmp != null) { + for (final HashMap entry : this.plots_tmp.values()) { + entry.values().forEach(runnable::run); + } + } + } + + public void foreachBasePlot(@NonNull final RunnableVal run) { + for (final PlotArea area : this.plotAreaManager.getAllPlotAreas()) { + area.foreachBasePlot(run); + } + } + + public PlotArea getFirstPlotArea() { + PlotArea[] areas = plotAreaManager.getAllPlotAreas(); + return areas.length > 0 ? areas[0] : null; + } + + public int getPlotAreaCount() { + return this.plotAreaManager.getAllPlotAreas().length; + } + + public int getPlotCount() { + int count = 0; + for (final PlotArea area : this.plotAreaManager.getAllPlotAreas()) { + count += area.getPlotCount(); + } + return count; + } + + public Set getPlotAreas() { + final Set set = new HashSet<>(); + Collections.addAll(set, plotAreaManager.getAllPlotAreas()); + return Collections.unmodifiableSet(set); + } + + public boolean isAugmented(@NonNull final String world) { + final PlotArea[] areas = plotAreaManager.getPlotAreas(world, null); + return areas != null && (areas.length > 1 || areas[0].TYPE != 0); + } + + /** + * Get a list of PlotArea objects. + * + * @param world the world + * @return Collection of PlotArea objects + */ + public Set getPlotAreas(@NonNull final String world) { + final Set set = new HashSet<>(); + Collections.addAll(set, plotAreaManager.getPlotAreas(world, null)); + return set; + } + + /** + * Get the relevant plot area for a specified location. + *
    + *
  • If there is only one plot area globally that will be returned. + *
  • If there is only one plot area in the world, it will return that. + *
  • If the plot area for a location cannot be unambiguously + * resolved, null will be returned. + *
+ * Note: An applicable plot area may not include the location i.e. clusters + * + * @param location the location + */ + public PlotArea getApplicablePlotArea(@NonNull final Location location) { + return plotAreaManager.getApplicablePlotArea(location); + } + + public PlotArea getPlotArea(@NonNull final String world, final String id) { + return plotAreaManager.getPlotArea(world, id); + } + + /** + * Get the {@code PlotArea} which contains a location. + *
    + *
  • If the plot area does not contain a location, null + * will be returned. + *
+ * + * @param location the location + * @return the {@link PlotArea} in the location, null if non existent + */ + public PlotArea getPlotAreaAbs(@NonNull final Location location) { + return plotAreaManager.getPlotArea(location); + } + + public PlotArea getPlotAreaByString(@NonNull final String search) { + String[] split = search.split("[;,]"); + PlotArea[] areas = plotAreaManager.getPlotAreas(split[0], null); + if (areas == null) { + for (PlotArea area : plotAreaManager.getAllPlotAreas()) { + if (area.worldname.equalsIgnoreCase(split[0])) { + if (area.id == null || split.length == 2 && area.id + .equalsIgnoreCase(split[1])) { + return area; + } } + } + return null; } - - /** - * Get the Java version. - * - * @return the java version - */ - public double getJavaVersion() { - return Double.parseDouble(System.getProperty("java.specification.version")); - } - - public void foreachPlotArea(@NonNull final RunnableVal runnable) { - for (final PlotArea area : this.plotAreaManager.getAllPlotAreas()) { - runnable.run(area); + if (areas.length == 1) { + return areas[0]; + } else if (split.length == 1) { + return null; + } else { + for (PlotArea area : areas) { + if (StringMan.isEqual(split[1], area.id)) { + return area; } + } + return null; } + } - public void foreachPlotArea(@NonNull final String world, - @NonNull final RunnableVal runnable) { - final PlotArea[] array = this.plotAreaManager.getPlotAreas(world, null); - if (array == null) { - return; - } - for (final PlotArea area : array) { - runnable.run(area); + /** + * Get Plots based on alias + * + * @param alias to search plots + * @param worldname to filter alias to a specific world [optional] null means all worlds + * @return Set<{ + * @ + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * link + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * Plot + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * }> empty if nothing found + */ + public Set getPlotsByAlias(@Nullable final String alias, + @NonNull final String worldname) { + final Set result = new HashSet<>(); + if (alias != null) { + for (final Plot plot : getPlots()) { + if (alias.equals(plot.getAlias()) && (worldname == null || worldname + .equals(plot.getWorldName()))) { + result.add(plot); } + } } + return Collections.unmodifiableSet(result); + } - public void foreachPlot(@NonNull final RunnableVal runnable) { - for (final PlotArea area : this.plotAreaManager.getAllPlotAreas()) { - area.getPlots().forEach(runnable::run); - } - } + public Set getPlotAreas(final String world, final RegionWrapper region) { + final PlotArea[] areas = plotAreaManager.getPlotAreas(world, region); + final Set set = new HashSet<>(); + Collections.addAll(set, areas); + return Collections.unmodifiableSet(set); + } - public void foreachPlotRaw(@NonNull final RunnableVal runnable) { - for (final PlotArea area : this.plotAreaManager.getAllPlotAreas()) { - area.getPlots().forEach(runnable::run); - } - if (this.plots_tmp != null) { - for (final HashMap entry : this.plots_tmp.values()) { - entry.values().forEach(runnable::run); - } - } - } - - public void foreachBasePlot(@NonNull final RunnableVal run) { - for (final PlotArea area : this.plotAreaManager.getAllPlotAreas()) { - area.foreachBasePlot(run); - } - } - - public PlotArea getFirstPlotArea() { - PlotArea[] areas = plotAreaManager.getAllPlotAreas(); - return areas.length > 0 ? areas[0] : null; - } - - public int getPlotAreaCount() { - return this.plotAreaManager.getAllPlotAreas().length; - } - - public int getPlotCount() { - int count = 0; - for (final PlotArea area : this.plotAreaManager.getAllPlotAreas()) { - count += area.getPlotCount(); - } - return count; - } - - public Set getPlotAreas() { - final Set set = new HashSet<>(); - Collections.addAll(set, plotAreaManager.getAllPlotAreas()); - return Collections.unmodifiableSet(set); - } - - public boolean isAugmented(@NonNull final String world) { - final PlotArea[] areas = plotAreaManager.getPlotAreas(world, null); - return areas != null && (areas.length > 1 || areas[0].TYPE != 0); - } - - /** - * Get a list of PlotArea objects. - * - * @param world the world - * @return Collection of PlotArea objects - */ - public Set getPlotAreas(@NonNull final String world) { - final Set set = new HashSet<>(); - Collections.addAll(set, plotAreaManager.getPlotAreas(world, null)); - return set; - } - - /** - * Get the relevant plot area for a specified location. - *
    - *
  • If there is only one plot area globally that will be returned. - *
  • If there is only one plot area in the world, it will return that. - *
  • If the plot area for a location cannot be unambiguously - * resolved, null will be returned. - *
- * Note: An applicable plot area may not include the location i.e. clusters - * - * @param location the location - * @return - */ - public PlotArea getApplicablePlotArea(@NonNull final Location location) { - return plotAreaManager.getApplicablePlotArea(location); - } - - public PlotArea getPlotArea(@NonNull final String world, final String id) { - return plotAreaManager.getPlotArea(world, id); - } - - /** - * Get the {@code PlotArea} which contains a location. - *
    - *
  • If the plot area does not contain a location, null - * will be returned. - *
- * - * @param location the location - * @return the {@link PlotArea} in the location, null if non existent - */ - public PlotArea getPlotAreaAbs(@NonNull final Location location) { - return plotAreaManager.getPlotArea(location); - } - - public PlotArea getPlotAreaByString(@NonNull final String search) { - String[] split = search.split("[;,]"); - PlotArea[] areas = plotAreaManager.getPlotAreas(split[0], null); - if (areas == null) { - for (PlotArea area : plotAreaManager.getAllPlotAreas()) { - if (area.worldname.equalsIgnoreCase(split[0])) { - if (area.id == null || split.length == 2 && area.id - .equalsIgnoreCase(split[1])) { - return area; - } - } - } - return null; - } - if (areas.length == 1) { - return areas[0]; - } else if (split.length == 1) { - return null; - } else { - for (PlotArea area : areas) { - if (StringMan.isEqual(split[1], area.id)) { - return area; - } - } - return null; - } - } - - /** - * Get Plots based on alias - * - * @param alias to search plots - * @param worldname to filter alias to a specific world [optional] null means all worlds - * @return Set<{ @ link Plot }> empty if nothing found - */ - public Set getPlotsByAlias(@Nullable final String alias, - @NonNull final String worldname) { - final Set result = new HashSet<>(); - if (alias != null) { - for (final Plot plot : getPlots()) { - if (alias.equals(plot.getAlias()) && (worldname == null || worldname - .equals(plot.getWorldName()))) { - result.add(plot); - } - } - } - return Collections.unmodifiableSet(result); - } - - public Set getPlotAreas(final String world, final RegionWrapper region) { - final PlotArea[] areas = plotAreaManager.getPlotAreas(world, region); - final Set set = new HashSet<>(); - Collections.addAll(set, areas); - return Collections.unmodifiableSet(set); - } - - public enum SortType { - CREATION_DATE, CREATION_DATE_TIMESTAMP, LAST_MODIFIED, DISTANCE_FROM_ORIGIN - } + public enum SortType { + CREATION_DATE, CREATION_DATE_TIMESTAMP, LAST_MODIFIED, DISTANCE_FROM_ORIGIN + } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Area.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Area.java index 9dc5ce20e..ee7c1cb23 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Area.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Area.java @@ -104,36 +104,34 @@ import java.util.Set; final String path = "worlds." + area.worldname + ".areas." + area.id + '-' + object.min + '-' + object.max; - Runnable run = new Runnable() { - @Override public void run() { - if (offsetX != 0) { - PlotSquared.get().worlds - .set(path + ".road.offset.x", offsetX); - } - if (offsetZ != 0) { - PlotSquared.get().worlds - .set(path + ".road.offset.z", offsetZ); - } - final String world = SetupUtils.manager.setupWorld(object); - if (WorldUtil.IMP.isWorld(world)) { - PlotSquared.get().loadWorld(world, null); - C.SETUP_FINISHED.send(player); - player.teleport(WorldUtil.IMP.getSpawn(world)); - if (area.TERRAIN != 3) { - ChunkManager.largeRegionTask(world, region, - new RunnableVal() { - @Override public void run(ChunkLoc value) { - AugmentedUtils - .generate(world, value.x, value.z, - null); - } - }, null); - } - } else { - MainUtil.sendMessage(player, - "An error occurred while creating the world: " - + area.worldname); + Runnable run = () -> { + if (offsetX != 0) { + PlotSquared.get().worlds + .set(path + ".road.offset.x", offsetX); + } + if (offsetZ != 0) { + PlotSquared.get().worlds + .set(path + ".road.offset.z", offsetZ); + } + final String world = SetupUtils.manager.setupWorld(object); + if (WorldUtil.IMP.isWorld(world)) { + PlotSquared.get().loadWorld(world, null); + C.SETUP_FINISHED.send(player); + player.teleport(WorldUtil.IMP.getSpawn(world)); + if (area.TERRAIN != 3) { + ChunkManager.largeRegionTask(world, region, + new RunnableVal() { + @Override public void run(ChunkLoc value) { + AugmentedUtils + .generate(world, value.x, value.z, + null); + } + }, null); } + } else { + MainUtil.sendMessage(player, + "An error occurred while creating the world: " + + area.worldname); } }; if (hasConfirmation(player)) { @@ -228,32 +226,30 @@ import java.util.Set; C.SETUP_WORLD_TAKEN.send(player, pa.worldname); return false; } - Runnable run = new Runnable() { - @Override public void run() { - String path = "worlds." + pa.worldname; - if (!PlotSquared.get().worlds.contains(path)) { - PlotSquared.get().worlds.createSection(path); - } - ConfigurationSection section = - PlotSquared.get().worlds.getConfigurationSection(path); - pa.saveConfiguration(section); - pa.loadConfiguration(section); - object.plotManager = PlotSquared.imp().getPluginName(); - object.setupGenerator = PlotSquared.imp().getPluginName(); - String world = SetupUtils.manager.setupWorld(object); - if (WorldUtil.IMP.isWorld(world)) { - C.SETUP_FINISHED.send(player); - player.teleport(WorldUtil.IMP.getSpawn(world)); - } else { - MainUtil.sendMessage(player, - "An error occurred while creating the world: " - + pa.worldname); - } - try { - PlotSquared.get().worlds.save(PlotSquared.get().worldsFile); - } catch (IOException e) { - e.printStackTrace(); - } + Runnable run = () -> { + String path = "worlds." + pa.worldname; + if (!PlotSquared.get().worlds.contains(path)) { + PlotSquared.get().worlds.createSection(path); + } + ConfigurationSection section = + PlotSquared.get().worlds.getConfigurationSection(path); + pa.saveConfiguration(section); + pa.loadConfiguration(section); + object.plotManager = PlotSquared.imp().getPluginName(); + object.setupGenerator = PlotSquared.imp().getPluginName(); + String world = SetupUtils.manager.setupWorld(object); + if (WorldUtil.IMP.isWorld(world)) { + C.SETUP_FINISHED.send(player); + player.teleport(WorldUtil.IMP.getSpawn(world)); + } else { + MainUtil.sendMessage(player, + "An error occurred while creating the world: " + + pa.worldname); + } + try { + PlotSquared.get().worlds.save(PlotSquared.get().worldsFile); + } catch (IOException e) { + e.printStackTrace(); } }; if (hasConfirmation(player)) { @@ -422,11 +418,7 @@ import java.util.Set; @Override public void run(ChunkLoc value) { AugmentedUtils.generate(area.worldname, value.x, value.z, null); } - }, new Runnable() { - @Override public void run() { - player.sendMessage("Regen complete"); - } - }); + }, () -> player.sendMessage("Regen complete")); return true; } case "goto": diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Claim.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Claim.java index 88f102967..e49155b8d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Claim.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Claim.java @@ -82,22 +82,14 @@ public class Claim extends SubCommand { if (plot.canClaim(player)) { plot.owner = player.getUUID(); final String finalSchematic = schematic; - DBFunc.createPlotSafe(plot, new Runnable() { - @Override public void run() { - TaskManager.IMP.sync(new RunnableVal() { - @Override public void run(Object value) { - plot.claim(player, true, finalSchematic, false); - if (area.AUTO_MERGE) { - plot.autoMerge(-1, Integer.MAX_VALUE, player.getUUID(), true); - } - } - }); + DBFunc.createPlotSafe(plot, () -> TaskManager.IMP.sync(new RunnableVal() { + @Override public void run(Object value) { + plot.claim(player, true, finalSchematic, false); + if (area.AUTO_MERGE) { + plot.autoMerge(-1, Integer.MAX_VALUE, player.getUUID(), true); + } } - }, new Runnable() { - @Override public void run() { - sendMessage(player, C.PLOT_NOT_CLAIMED); - } - }); + }), () -> sendMessage(player, C.PLOT_NOT_CLAIMED)); return true; } else { sendMessage(player, C.PLOT_NOT_CLAIMED); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Cluster.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Cluster.java index c8360f696..2ead96b4f 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Cluster.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Cluster.java @@ -302,6 +302,7 @@ import java.util.UUID; PlotArea area = player.getApplicablePlotArea(); if (area == null) { C.NOT_IN_PLOT_WORLD.send(player); + return false; } PlotCluster cluster = area.getCluster(player.getLocation()); if (cluster == null) { @@ -347,6 +348,7 @@ import java.util.UUID; PlotArea area = player.getApplicablePlotArea(); if (area == null) { C.NOT_IN_PLOT_WORLD.send(player); + return false; } PlotCluster cluster = area.getCluster(player.getLocation()); if (cluster == null) { @@ -405,6 +407,7 @@ import java.util.UUID; PlotArea area = player.getApplicablePlotArea(); if (area == null) { C.NOT_IN_PLOT_WORLD.send(player); + return false; } PlotCluster cluster; if (args.length == 2) { @@ -440,7 +443,6 @@ import java.util.UUID; PlotSquared.get().getPlots(player.getLocation().getWorld(), uuid))) { PlotCluster current = plot.getCluster(); if (current != null && current.equals(cluster)) { - player.getLocation().getWorld(); plot.unclaim(); } } @@ -462,6 +464,7 @@ import java.util.UUID; PlotArea area = player.getApplicablePlotArea(); if (area == null) { C.NOT_IN_PLOT_WORLD.send(player); + return false; } PlotCluster cluster = area.getCluster(player.getLocation()); if (cluster == null) { @@ -534,6 +537,7 @@ import java.util.UUID; PlotArea area = player.getApplicablePlotArea(); if (area == null) { C.NOT_IN_PLOT_WORLD.send(player); + return false; } PlotCluster cluster; if (args.length == 2) { @@ -581,6 +585,7 @@ import java.util.UUID; PlotArea area = player.getApplicablePlotArea(); if (area == null) { C.NOT_IN_PLOT_WORLD.send(player); + return false; } PlotCluster cluster = area.getCluster(player.getLocation()); if (cluster == null) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Condense.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Condense.java index 040fd97b8..44d0e5593 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Condense.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Condense.java @@ -65,6 +65,7 @@ import java.util.concurrent.atomic.AtomicBoolean; sizes.add(size - 1); } // Sort plots by size (buckets?)] + //noinspection unchecked ArrayList[] buckets = new ArrayList[maxSize]; for (int i = 0; i < plots.size(); i++) { Plot plot = plots.get(i); @@ -126,13 +127,11 @@ import java.util.concurrent.atomic.AtomicBoolean; } i++; final AtomicBoolean result = new AtomicBoolean(false); - result.set(origin.move(possible, new Runnable() { - @Override public void run() { - if (result.get()) { - MainUtil.sendMessage(player, - "Moving: " + origin + " -> " + possible); - TaskManager.runTaskLater(task, 1); - } + result.set(origin.move(possible, () -> { + if (result.get()) { + MainUtil.sendMessage(player, + "Moving: " + origin + " -> " + possible); + TaskManager.runTaskLater(task, 1); } }, false)); if (result.get()) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Database.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Database.java index b760bc282..d945f122a 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Database.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Database.java @@ -25,174 +25,163 @@ import java.util.Map.Entry; @CommandDeclaration(command = "database", aliases = {"convert"}, category = CommandCategory.ADMINISTRATION, permission = "plots.database", description = "Convert/Backup Storage", requiredType = RequiredType.CONSOLE, - usage = "/plot database [area] ") public class Database + usage = "/plot database [area] ") +public class Database extends SubCommand { - public static void insertPlots(final SQLManager manager, final List plots, - final PlotPlayer player) { - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - try { - ArrayList ps = new ArrayList<>(); - for (Plot p : plots) { - ps.add(p); - } - MainUtil.sendMessage(player, "&6Starting..."); - manager.createPlotsAndData(ps, new Runnable() { - @Override public void run() { - MainUtil.sendMessage(player, "&6Database conversion finished!"); - manager.close(); - } - }); - } catch (Exception e) { - MainUtil.sendMessage(player, - "Failed to insert plot objects, see stacktrace for info"); - e.printStackTrace(); - } - } + public static void insertPlots(final SQLManager manager, final List plots, + final PlotPlayer player) { + TaskManager.runTaskAsync(() -> { + try { + ArrayList ps = new ArrayList<>(plots); + MainUtil.sendMessage(player, "&6Starting..."); + manager.createPlotsAndData(ps, () -> { + MainUtil.sendMessage(player, "&6Database conversion finished!"); + manager.close(); }); - } + } catch (Exception e) { + MainUtil.sendMessage(player, + "Failed to insert plot objects, see stacktrace for info"); + e.printStackTrace(); + } + }); + } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { - if (args.length < 1) { - MainUtil.sendMessage(player, "/plot database [area] "); - return false; - } - List plots; - PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]); - if (area != null) { - plots = PlotSquared.get().sortPlotsByTemp(area.getPlots()); - args = Arrays.copyOfRange(args, 1, args.length); - } else { - plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getPlots()); - } - if (args.length < 1) { - MainUtil.sendMessage(player, "/plot database [world] "); - MainUtil.sendMessage(player, "[arg] indicates an optional argument"); - return false; - } - try { - com.github.intellectualsites.plotsquared.plot.database.Database implementation; - String prefix = ""; - switch (args[0].toLowerCase()) { - case "import": - if (args.length < 2) { - MainUtil - .sendMessage(player, "/plot database import [prefix]"); - return false; - } - File file = MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), - args[1].endsWith(".db") ? args[1] : args[1] + ".db"); - if (!file.exists()) { - MainUtil.sendMessage(player, "&6Database does not exist: " + file); - return false; - } - MainUtil.sendMessage(player, "&6Starting..."); - implementation = new SQLite(file); - SQLManager manager = - new SQLManager(implementation, args.length == 3 ? args[2] : "", true); - HashMap> map = manager.getPlots(); - plots = new ArrayList<>(); - for (Entry> entry : map.entrySet()) { - String areaname = entry.getKey(); - PlotArea pa = PlotSquared.get().getPlotAreaByString(areaname); - if (pa != null) { - for (Entry entry2 : entry.getValue().entrySet()) { - Plot plot = entry2.getValue(); - if (pa.getOwnedPlotAbs(plot.getId()) != null) { - if (pa instanceof SinglePlotArea) { - Plot newPlot = pa.getNextFreePlot(null, plot.getId()); - if (newPlot != null) { - PlotId newId = newPlot.getId(); - PlotId id = plot.getId(); - File worldFile = - new File(PlotSquared.imp().getWorldContainer(), - id.toCommaSeparatedString()); - if (worldFile.exists()) { - File newFile = - new File(PlotSquared.imp().getWorldContainer(), - newId.toCommaSeparatedString()); - worldFile.renameTo(newFile); - } - id.x = newId.x; - id.y = newId.y; - id.recalculateHash(); - plot.setArea(pa); - plots.add(plot); - continue; - } - } - MainUtil.sendMessage(player, - "Skipping duplicate plot: " + plot + " | id=" + plot.temp); - continue; - } - plot.setArea(pa); - plots.add(plot); - } - } else { - HashMap plotmap = - PlotSquared.get().plots_tmp.get(areaname); - if (plotmap == null) { - plotmap = new HashMap<>(); - PlotSquared.get().plots_tmp.put(areaname, plotmap); - } - plotmap.putAll(entry.getValue()); - } - } - DBFunc.createPlotsAndData(plots, new Runnable() { - @Override public void run() { - MainUtil.sendMessage(player, "&6Database conversion finished!"); - } - }); - return true; - case "mysql": - if (args.length < 6) { - return MainUtil.sendMessage(player, - "/plot database mysql [host] [port] [username] [password] [database] {prefix}"); - } - String host = args[1]; - String port = args[2]; - String username = args[3]; - String password = args[4]; - String database = args[5]; - if (args.length > 6) { - prefix = args[6]; - } - implementation = new MySQL(host, port, database, username, password); - break; - case "sqlite": - if (args.length < 2) { - return MainUtil.sendMessage(player, "/plot database sqlite [file]"); - } - File sqliteFile = - MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), args[1] + ".db"); - implementation = new SQLite(sqliteFile); - break; - default: - return MainUtil.sendMessage(player, "/plot database [sqlite/mysql]"); - } - try { - SQLManager manager = new SQLManager(implementation, prefix, true); - Database.insertPlots(manager, plots, player); - return true; - } catch (ClassNotFoundException | SQLException e) { - MainUtil.sendMessage(player, "$1Failed to save plots, read stacktrace for info"); - MainUtil.sendMessage(player, - "&d==== Here is an ugly stacktrace, if you are interested in those things ==="); - e.printStackTrace(); - MainUtil.sendMessage(player, "&d==== End of stacktrace ===="); - MainUtil - .sendMessage(player, "$1Please make sure you are using the correct arguments!"); - return false; - } - } catch (ClassNotFoundException | SQLException e) { - MainUtil.sendMessage(player, "$1Failed to open connection, read stacktrace for info"); - MainUtil.sendMessage(player, - "&d==== Here is an ugly stacktrace, if you are interested in those things ==="); - e.printStackTrace(); - MainUtil.sendMessage(player, "&d==== End of stacktrace ===="); - MainUtil.sendMessage(player, "$1Please make sure you are using the correct arguments!"); - return false; - } + @Override + public boolean onCommand(final PlotPlayer player, String[] args) { + if (args.length < 1) { + MainUtil.sendMessage(player, "/plot database [area] "); + return false; } + List plots; + PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]); + if (area != null) { + plots = PlotSquared.get().sortPlotsByTemp(area.getPlots()); + args = Arrays.copyOfRange(args, 1, args.length); + } else { + plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getPlots()); + } + if (args.length < 1) { + MainUtil.sendMessage(player, "/plot database [world] "); + MainUtil.sendMessage(player, "[arg] indicates an optional argument"); + return false; + } + try { + com.github.intellectualsites.plotsquared.plot.database.Database implementation; + String prefix = ""; + switch (args[0].toLowerCase()) { + case "import": + if (args.length < 2) { + MainUtil + .sendMessage(player, "/plot database import [prefix]"); + return false; + } + File file = MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), + args[1].endsWith(".db") ? args[1] : args[1] + ".db"); + if (!file.exists()) { + MainUtil.sendMessage(player, "&6Database does not exist: " + file); + return false; + } + MainUtil.sendMessage(player, "&6Starting..."); + implementation = new SQLite(file); + SQLManager manager = + new SQLManager(implementation, args.length == 3 ? args[2] : "", true); + HashMap> map = manager.getPlots(); + plots = new ArrayList<>(); + for (Entry> entry : map.entrySet()) { + String areaname = entry.getKey(); + PlotArea pa = PlotSquared.get().getPlotAreaByString(areaname); + if (pa != null) { + for (Entry entry2 : entry.getValue().entrySet()) { + Plot plot = entry2.getValue(); + if (pa.getOwnedPlotAbs(plot.getId()) != null) { + if (pa instanceof SinglePlotArea) { + Plot newPlot = pa.getNextFreePlot(null, plot.getId()); + if (newPlot != null) { + PlotId newId = newPlot.getId(); + PlotId id = plot.getId(); + File worldFile = + new File(PlotSquared.imp().getWorldContainer(), + id.toCommaSeparatedString()); + if (worldFile.exists()) { + File newFile = + new File(PlotSquared.imp().getWorldContainer(), + newId.toCommaSeparatedString()); + worldFile.renameTo(newFile); + } + id.x = newId.x; + id.y = newId.y; + id.recalculateHash(); + plot.setArea(pa); + plots.add(plot); + continue; + } + } + MainUtil.sendMessage(player, + "Skipping duplicate plot: " + plot + " | id=" + plot.temp); + continue; + } + plot.setArea(pa); + plots.add(plot); + } + } else { + HashMap plotmap = + PlotSquared.get().plots_tmp + .computeIfAbsent(areaname, k -> new HashMap<>()); + plotmap.putAll(entry.getValue()); + } + } + DBFunc.createPlotsAndData(plots, + () -> MainUtil.sendMessage(player, "&6Database conversion finished!")); + return true; + case "mysql": + if (args.length < 6) { + return MainUtil.sendMessage(player, + "/plot database mysql [host] [port] [username] [password] [database] {prefix}"); + } + String host = args[1]; + String port = args[2]; + String username = args[3]; + String password = args[4]; + String database = args[5]; + if (args.length > 6) { + prefix = args[6]; + } + implementation = new MySQL(host, port, database, username, password); + break; + case "sqlite": + if (args.length < 2) { + return MainUtil.sendMessage(player, "/plot database sqlite [file]"); + } + File sqliteFile = + MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), args[1] + ".db"); + implementation = new SQLite(sqliteFile); + break; + default: + return MainUtil.sendMessage(player, "/plot database [sqlite/mysql]"); + } + try { + SQLManager manager = new SQLManager(implementation, prefix, true); + Database.insertPlots(manager, plots, player); + return true; + } catch (ClassNotFoundException | SQLException e) { + MainUtil.sendMessage(player, "$1Failed to save plots, read stacktrace for info"); + MainUtil.sendMessage(player, + "&d==== Here is an ugly stacktrace, if you are interested in those things ==="); + e.printStackTrace(); + MainUtil.sendMessage(player, "&d==== End of stacktrace ===="); + MainUtil + .sendMessage(player, "$1Please make sure you are using the correct arguments!"); + return false; + } + } catch (ClassNotFoundException | SQLException e) { + MainUtil.sendMessage(player, "$1Failed to open connection, read stacktrace for info"); + MainUtil.sendMessage(player, + "&d==== Here is an ugly stacktrace, if you are interested in those things ==="); + e.printStackTrace(); + MainUtil.sendMessage(player, "&d==== End of stacktrace ===="); + MainUtil.sendMessage(player, "$1Please make sure you are using the correct arguments!"); + return false; + } + } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Help.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Help.java index f0ff64af1..ff697953c 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Help.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Help.java @@ -57,9 +57,7 @@ public class Help extends Command { public void displayHelp(PlotPlayer player, String cat, int page) { CommandCategory catEnum = null; if (cat != null) { - if (StringMan.isEqualIgnoreCase(cat, "all")) { - catEnum = null; - } else { + if (!StringMan.isEqualIgnoreCase(cat, "all")) { for (CommandCategory c : CommandCategory.values()) { if (StringMan.isEqualIgnoreCaseToAny(cat, c.name(), c.toString())) { catEnum = c; diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Inbox.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Inbox.java index 5c7cfc0ac..908e35afc 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Inbox.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Inbox.java @@ -165,9 +165,8 @@ import java.util.Optional; inbox.clearInbox(plot); Optional> comments = plot.getSettings().getComments(inbox.toString()); - if (comments.isPresent()) { - plot.getSettings().removeComments(comments.get()); - } + comments + .ifPresent(plotComments -> plot.getSettings().removeComments(plotComments)); MainUtil.sendMessage(player, C.COMMENT_REMOVED, "*"); return true; default: diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Merge.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Merge.java index 42075f2d2..39d368865 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Merge.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Merge.java @@ -60,9 +60,9 @@ public class Merge extends SubCommand { } final PlotArea plotArea = plot.getArea(); Expression priceExr = - plotArea.PRICES.containsKey("merge") ? plotArea.PRICES.get("merge") : null; + plotArea.PRICES.getOrDefault("merge", Expression.constant(0d)); final int size = plot.getConnectedPlots().size(); - final double price = priceExr == null ? 0d : priceExr.evaluate((double) size); + final double price = priceExr.evaluate((double) size); if (EconHandler.manager != null && plotArea.USE_ECONOMY && price > 0d && EconHandler.manager.getMoney(player) < price) { sendMessage(player, C.CANNOT_AFFORD_MERGE, String.valueOf(price)); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Purge.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Purge.java index b8b38e298..8cd4d9e56 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Purge.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Purge.java @@ -108,9 +108,7 @@ import java.util.UUID; if (unknown && UUIDHandler.getName(plot.owner) != null) { continue; } - for (Plot current : plot.getConnectedPlots()) { - toDelete.add(current); - } + toDelete.addAll(plot.getConnectedPlots()); } if (PlotSquared.get().plots_tmp != null) { for (Entry> entry : PlotSquared.get().plots_tmp @@ -143,23 +141,21 @@ import java.util.UUID; } String cmd = "/plot purge " + StringMan.join(args, " ") + " (" + toDelete.size() + " plots)"; - Runnable run = new Runnable() { - @Override public void run() { - PlotSquared.debug("Calculating plots to purge, please wait..."); - HashSet ids = new HashSet<>(); - for (Plot plot : toDelete) { - if (plot.temp != Integer.MAX_VALUE) { - ids.add(plot.temp); - plot.getArea().removePlot(plot.getId()); - for (PlotPlayer pp : plot.getPlayersInPlot()) { - PlotListener.plotEntry(pp, plot); - } - plot.removeSign(); + Runnable run = () -> { + PlotSquared.debug("Calculating plots to purge, please wait..."); + HashSet ids = new HashSet<>(); + for (Plot plot : toDelete) { + if (plot.temp != Integer.MAX_VALUE) { + ids.add(plot.temp); + plot.getArea().removePlot(plot.getId()); + for (PlotPlayer pp : plot.getPlayersInPlot()) { + PlotListener.plotEntry(pp, plot); } + plot.removeSign(); } - DBFunc.purgeIds(ids); - C.PURGE_SUCCESS.send(player, ids.size() + "/" + toDelete.size()); } + DBFunc.purgeIds(ids); + C.PURGE_SUCCESS.send(player, ids.size() + "/" + toDelete.size()); }; if (hasConfirmation(player)) { CmdConfirm.addPending(player, cmd, run); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Rate.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Rate.java index 7141df96e..33570b9b6 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Rate.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Rate.java @@ -22,25 +22,23 @@ import java.util.Map.Entry; switch (args[0].toLowerCase()) { case "next": { ArrayList plots = new ArrayList<>(PlotSquared.get().getBasePlots()); - Collections.sort(plots, new Comparator() { - @Override public int compare(Plot p1, Plot p2) { - double v1 = 0; - if (!p1.getRatings().isEmpty()) { - for (Entry entry : p1.getRatings().entrySet()) { - v1 -= 11 - entry.getValue().getAverageRating(); - } + plots.sort((p1, p2) -> { + double v1 = 0; + if (!p1.getRatings().isEmpty()) { + for (Entry entry : p1.getRatings().entrySet()) { + v1 -= 11 - entry.getValue().getAverageRating(); } - double v2 = 0; - if (!p2.getRatings().isEmpty()) { - for (Entry entry : p2.getRatings().entrySet()) { - v2 -= 11 - entry.getValue().getAverageRating(); - } - } - if (v1 == v2) { - return -0; - } - return v2 > v1 ? 1 : -1; } + double v2 = 0; + if (!p2.getRatings().isEmpty()) { + for (Entry entry : p2.getRatings().entrySet()) { + v2 -= 11 - entry.getValue().getAverageRating(); + } + } + if (v1 == v2) { + return -0; + } + return v2 > v1 ? 1 : -1; }); UUID uuid = player.getUUID(); for (Plot p : plots) { @@ -123,7 +121,7 @@ import java.util.Map.Entry; return true; } }; - inventory.setItem(0, new PlotItemStack(35, (short) 12, 0, "0/8")); + inventory.setItem(0, new PlotItemStack("minecraft:brown_wool", 0, "0/8")); inventory.setItem(1, new PlotItemStack(35, (short) 14, 1, "1/8")); inventory.setItem(2, new PlotItemStack(35, (short) 1, 2, "2/8")); inventory.setItem(3, new PlotItemStack(35, (short) 4, 3, "3/8")); @@ -137,11 +135,9 @@ import java.util.Map.Entry; }; if (plot.getSettings().ratings == null) { if (!Settings.Enabled_Components.RATING_CACHE) { - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - plot.getSettings().ratings = DBFunc.getRatings(plot); - run.run(); - } + TaskManager.runTaskAsync(() -> { + plot.getSettings().ratings = DBFunc.getRatings(plot); + run.run(); }); return true; } @@ -167,26 +163,22 @@ import java.util.Map.Entry; return false; } final UUID uuid = player.getUUID(); - final Runnable run = new Runnable() { - @Override public void run() { - if (plot.getRatings().containsKey(uuid)) { - sendMessage(player, C.RATING_ALREADY_EXISTS, plot.getId().toString()); - return; - } - Rating result = EventUtil.manager.callRating(player, plot, new Rating(rating)); - if (result != null) { - plot.addRating(uuid, result); - sendMessage(player, C.RATING_APPLIED, plot.getId().toString()); - } + final Runnable run = () -> { + if (plot.getRatings().containsKey(uuid)) { + sendMessage(player, C.RATING_ALREADY_EXISTS, plot.getId().toString()); + return; + } + Rating result = EventUtil.manager.callRating(player, plot, new Rating(rating)); + if (result != null) { + plot.addRating(uuid, result); + sendMessage(player, C.RATING_APPLIED, plot.getId().toString()); } }; if (plot.getSettings().ratings == null) { if (!Settings.Enabled_Components.RATING_CACHE) { - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - plot.getSettings().ratings = DBFunc.getRatings(plot); - run.run(); - } + TaskManager.runTaskAsync(() -> { + plot.getSettings().ratings = DBFunc.getRatings(plot); + run.run(); }); return true; } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/AbstractDB.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/AbstractDB.java index a26d4d02e..e5341103d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/AbstractDB.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/AbstractDB.java @@ -143,14 +143,6 @@ public interface AbstractDB { */ void setFlags(Plot plot, HashMap, Object> flags); - /** - * Set cluster flags. - * - * @param cluster PlotCluster Object - * @param flags flags to set (flag[]) - */ - void setFlags(PlotCluster cluster, HashMap, Object> flags); - /** * Rename a cluster to the given name. * diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/DBFunc.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/DBFunc.java index 5050c699f..6571a328c 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/DBFunc.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/DBFunc.java @@ -13,6 +13,7 @@ import java.util.*; * Database Functions * - These functions do not update the local plot objects and only make changes to the DB */ +@SuppressWarnings("deprecation") public class DBFunc { /** * The "global" uuid. @@ -298,17 +299,6 @@ public class DBFunc { DBFunc.dbManager.setFlags(plot, flags); } - public static void setFlags(PlotCluster cluster, HashMap, Object> flags) { - if (dbManager == null) { - return; - } - DBFunc.dbManager.setFlags(cluster, flags); - } - - /** - * @param plot - * @param alias - */ public static void setAlias(Plot plot, String alias) { if (plot.temp == -1 || dbManager == null) { return; @@ -330,10 +320,6 @@ public class DBFunc { DBFunc.dbManager.purge(area, plotIds); } - /** - * @param plot - * @param position - */ public static void setPosition(Plot plot, String position) { if (plot.temp == -1 || dbManager == null) { return; @@ -341,10 +327,6 @@ public class DBFunc { DBFunc.dbManager.setPosition(plot, position); } - /** - * @param plot - * @param comment - */ public static void removeComment(Plot plot, PlotComment comment) { if (plot.temp == -1 || dbManager == null) { return; @@ -359,10 +341,6 @@ public class DBFunc { DBFunc.dbManager.clearInbox(plot, inbox); } - /** - * @param plot - * @param comment - */ public static void setComment(Plot plot, PlotComment comment) { if (plot != null && plot.temp == -1 || dbManager == null) { return; @@ -370,9 +348,6 @@ public class DBFunc { DBFunc.dbManager.setComment(plot, comment); } - /** - * @param plot - */ public static void getComments(Plot plot, String inbox, RunnableVal> whenDone) { if (plot != null && plot.temp == -1 || dbManager == null) { @@ -381,10 +356,6 @@ public class DBFunc { DBFunc.dbManager.getComments(plot, inbox, whenDone); } - /** - * @param plot - * @param uuid - */ public static void removeTrusted(Plot plot, UUID uuid) { if (plot.temp == -1 || dbManager == null) { return; @@ -392,10 +363,6 @@ public class DBFunc { DBFunc.dbManager.removeTrusted(plot, uuid); } - /** - * @param cluster - * @param uuid - */ public static void removeHelper(PlotCluster cluster, UUID uuid) { if (dbManager == null) { return; @@ -403,9 +370,6 @@ public class DBFunc { DBFunc.dbManager.removeHelper(cluster, uuid); } - /** - * @param cluster - */ public static void createCluster(PlotCluster cluster) { if (dbManager == null) { return; @@ -413,11 +377,6 @@ public class DBFunc { DBFunc.dbManager.createCluster(cluster); } - /** - * @param current - * @param min - * @param max - */ public static void resizeCluster(PlotCluster current, PlotId min, PlotId max) { if (dbManager == null) { return; @@ -425,10 +384,6 @@ public class DBFunc { DBFunc.dbManager.resizeCluster(current, min, max); } - /** - * @param plot - * @param uuid - */ public static void removeMember(Plot plot, UUID uuid) { if (plot.temp == -1 || dbManager == null) { return; @@ -436,10 +391,6 @@ public class DBFunc { DBFunc.dbManager.removeMember(plot, uuid); } - /** - * @param cluster - * @param uuid - */ public static void removeInvited(PlotCluster cluster, UUID uuid) { if (dbManager == null) { return; @@ -447,10 +398,6 @@ public class DBFunc { DBFunc.dbManager.removeInvited(cluster, uuid); } - /** - * @param plot - * @param uuid - */ public static void setTrusted(Plot plot, UUID uuid) { if (plot.temp == -1 || dbManager == null) { return; @@ -465,10 +412,6 @@ public class DBFunc { DBFunc.dbManager.setHelper(cluster, uuid); } - /** - * @param plot - * @param uuid - */ public static void setMember(Plot plot, UUID uuid) { if (plot.temp == -1 || dbManager == null) { return; @@ -483,10 +426,6 @@ public class DBFunc { DBFunc.dbManager.setInvited(cluster, uuid); } - /** - * @param plot - * @param uuid - */ public static void removeDenied(Plot plot, UUID uuid) { if (plot.temp == -1 || dbManager == null) { return; @@ -494,10 +433,6 @@ public class DBFunc { DBFunc.dbManager.removeDenied(plot, uuid); } - /** - * @param plot - * @param uuid - */ public static void setDenied(Plot plot, UUID uuid) { if (plot.temp == -1 || dbManager == null) { return; diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/Database.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/Database.java index 4acecc01f..8626a1a24 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/Database.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/Database.java @@ -11,9 +11,9 @@ import java.sql.Statement; * @author -_Husky_- * @author tips48 */ -public abstract class Database { +public interface Database { - public abstract Connection forceConnection() throws SQLException, ClassNotFoundException; + Connection forceConnection() throws SQLException, ClassNotFoundException; /** * Opens a connection with the database. @@ -22,7 +22,7 @@ public abstract class Database { * @throws SQLException if the connection can not be opened * @throws ClassNotFoundException if the driver cannot be found */ - public abstract Connection openConnection() throws SQLException, ClassNotFoundException; + Connection openConnection() throws SQLException, ClassNotFoundException; /** * Checks if a connection is open with the database. @@ -30,14 +30,14 @@ public abstract class Database { * @return true if the connection is open * @throws SQLException if the connection cannot be checked */ - public abstract boolean checkConnection() throws SQLException; + boolean checkConnection() throws SQLException; /** * Gets the connection with the database. * * @return Connection with the database, null if none */ - public abstract Connection getConnection(); + Connection getConnection(); /** * Closes the connection with the database. @@ -45,7 +45,7 @@ public abstract class Database { * @return true if successful * @throws SQLException if the connection cannot be closed */ - public abstract boolean closeConnection() throws SQLException; + boolean closeConnection() throws SQLException; /** * Executes a SQL Query. @@ -56,7 +56,7 @@ public abstract class Database { * @throws SQLException If the query cannot be executed * @throws ClassNotFoundException If the driver cannot be found; see {@link #openConnection()} */ - public abstract ResultSet querySQL(String query) throws SQLException, ClassNotFoundException; + ResultSet querySQL(String query) throws SQLException, ClassNotFoundException; /** * Executes an Update SQL Query. @@ -68,5 +68,5 @@ public abstract class Database { * @throws SQLException If the query cannot be executed * @throws ClassNotFoundException If the driver cannot be found; see {@link #openConnection()} */ - public abstract int updateSQL(String query) throws SQLException, ClassNotFoundException; + int updateSQL(String query) throws SQLException, ClassNotFoundException; } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/MySQL.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/MySQL.java index 7e7df9124..4a0e655c5 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/MySQL.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/MySQL.java @@ -11,7 +11,7 @@ import java.sql.*; * @author -_Husky_- * @author tips48 */ -public class MySQL extends Database { +public class MySQL implements Database { private final String user; private final String database; diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/SQLManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/SQLManager.java index 66a21174d..ed460450d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/SQLManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/SQLManager.java @@ -7,3204 +7,3296 @@ import com.github.intellectualsites.plotsquared.plot.config.Storage; import com.github.intellectualsites.plotsquared.plot.flag.Flag; import com.github.intellectualsites.plotsquared.plot.flag.FlagManager; import com.github.intellectualsites.plotsquared.plot.flag.StringFlag; -import com.github.intellectualsites.plotsquared.plot.object.*; +import com.github.intellectualsites.plotsquared.plot.object.BlockLoc; +import com.github.intellectualsites.plotsquared.plot.object.Plot; +import com.github.intellectualsites.plotsquared.plot.object.PlotArea; +import com.github.intellectualsites.plotsquared.plot.object.PlotCluster; +import com.github.intellectualsites.plotsquared.plot.object.PlotId; +import com.github.intellectualsites.plotsquared.plot.object.PlotSettings; +import com.github.intellectualsites.plotsquared.plot.object.RunnableVal; import com.github.intellectualsites.plotsquared.plot.object.comment.PlotComment; import com.github.intellectualsites.plotsquared.plot.util.MainUtil; import com.github.intellectualsites.plotsquared.plot.util.StringMan; import com.github.intellectualsites.plotsquared.plot.util.TaskManager; import com.google.common.base.Charsets; - -import java.sql.*; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Queue; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nonnull; -@SuppressWarnings("SqlDialectInspection") public class SQLManager implements AbstractDB { +@SuppressWarnings("SqlDialectInspection") +public class SQLManager implements AbstractDB { - // Public final - public final String SET_OWNER; - public final String GET_ALL_PLOTS; - public final String CREATE_PLOTS; - public final String CREATE_SETTINGS; - public final String CREATE_TIERS; - public final String CREATE_PLOT; - public final String CREATE_PLOT_SAFE; - public final String CREATE_CLUSTER; - private final String prefix; - // Private Final - private final Database database; - private final boolean mySQL; - /** - * important tasks - */ - public volatile Queue globalTasks; - /** - * Notify tasks - */ - public volatile Queue notifyTasks; - /** - * plot - * plot_denied - * plot_helpers - * plot_trusted - * plot_comments - * plot_settings - * plot_rating - */ - public volatile ConcurrentHashMap> plotTasks; - /** - * player_meta - */ - public volatile ConcurrentHashMap> playerTasks; - /** - * cluster - * cluster_helpers - * cluster_invited - * cluster_settings - */ - public volatile ConcurrentHashMap> clusterTasks; - // Private - private Connection connection; - private boolean closed = false; + // Public final + public final String SET_OWNER; + public final String GET_ALL_PLOTS; + public final String CREATE_PLOTS; + public final String CREATE_SETTINGS; + public final String CREATE_TIERS; + public final String CREATE_PLOT; + public final String CREATE_PLOT_SAFE; + public final String CREATE_CLUSTER; + private final String prefix; + // Private Final + private final Database database; + private final boolean mySQL; + /** + * important tasks + */ + public volatile Queue globalTasks; + /** + * Notify tasks + */ + public volatile Queue notifyTasks; + /** + * plot plot_denied plot_helpers plot_trusted plot_comments plot_settings plot_rating + */ + public volatile ConcurrentHashMap> plotTasks; + /** + * player_meta + */ + public volatile ConcurrentHashMap> playerTasks; + /** + * cluster cluster_helpers cluster_invited cluster_settings + */ + public volatile ConcurrentHashMap> clusterTasks; + // Private + private Connection connection; + private boolean closed = false; - /** - * Constructor - * - * @param database - * @param p prefix - * @throws SQLException - * @throws ClassNotFoundException - */ - public SQLManager(final Database database, String p, boolean debug) - throws SQLException, ClassNotFoundException { - // Private final - this.database = database; - this.connection = database.openConnection(); - this.mySQL = database instanceof MySQL; - this.globalTasks = new ConcurrentLinkedQueue<>(); - this.notifyTasks = new ConcurrentLinkedQueue<>(); - this.plotTasks = new ConcurrentHashMap<>(); - this.playerTasks = new ConcurrentHashMap<>(); - this.clusterTasks = new ConcurrentHashMap<>(); - this.prefix = p; - this.SET_OWNER = "UPDATE `" + this.prefix - + "plot` SET `owner` = ? WHERE `plot_id_x` = ? AND `plot_id_z` = ? AND `world` = ?"; - this.GET_ALL_PLOTS = - "SELECT `id`, `plot_id_x`, `plot_id_z`, `world` FROM `" + this.prefix + "plot`"; - this.CREATE_PLOTS = "INSERT INTO `" + this.prefix - + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) values "; - this.CREATE_SETTINGS = - "INSERT INTO `" + this.prefix + "plot_settings` (`plot_plot_id`) values "; - this.CREATE_TIERS = - "INSERT INTO `" + this.prefix + "plot_%tier%` (`plot_plot_id`, `user_uuid`) values "; - this.CREATE_PLOT = "INSERT INTO `" + this.prefix - + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) VALUES(?, ?, ?, ?, ?)"; + /** + * Constructor + * + * @param p prefix + */ + public SQLManager(final Database database, String p, boolean debug) + throws SQLException, ClassNotFoundException { + // Private final + this.database = database; + this.connection = database.openConnection(); + this.mySQL = database instanceof MySQL; + this.globalTasks = new ConcurrentLinkedQueue<>(); + this.notifyTasks = new ConcurrentLinkedQueue<>(); + this.plotTasks = new ConcurrentHashMap<>(); + this.playerTasks = new ConcurrentHashMap<>(); + this.clusterTasks = new ConcurrentHashMap<>(); + this.prefix = p; + this.SET_OWNER = "UPDATE `" + this.prefix + + "plot` SET `owner` = ? WHERE `plot_id_x` = ? AND `plot_id_z` = ? AND `world` = ?"; + this.GET_ALL_PLOTS = + "SELECT `id`, `plot_id_x`, `plot_id_z`, `world` FROM `" + this.prefix + "plot`"; + this.CREATE_PLOTS = "INSERT INTO `" + this.prefix + + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) values "; + this.CREATE_SETTINGS = + "INSERT INTO `" + this.prefix + "plot_settings` (`plot_plot_id`) values "; + this.CREATE_TIERS = + "INSERT INTO `" + this.prefix + "plot_%tier%` (`plot_plot_id`, `user_uuid`) values "; + this.CREATE_PLOT = "INSERT INTO `" + this.prefix + + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) VALUES(?, ?, ?, ?, ?)"; - if (mySQL) { - this.CREATE_PLOT_SAFE = "INSERT IGNORE INTO `" + this.prefix - + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) SELECT ?, ?, ?, ?, ? FROM DUAL WHERE NOT EXISTS (SELECT null FROM `" - + this.prefix + "plot` WHERE `world` = ? AND `plot_id_x` = ? AND `plot_id_z` = ?)"; + if (mySQL) { + this.CREATE_PLOT_SAFE = "INSERT IGNORE INTO `" + this.prefix + + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) SELECT ?, ?, ?, ?, ? FROM DUAL WHERE NOT EXISTS (SELECT null FROM `" + + this.prefix + "plot` WHERE `world` = ? AND `plot_id_x` = ? AND `plot_id_z` = ?)"; + } else { + this.CREATE_PLOT_SAFE = "INSERT INTO `" + this.prefix + + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) SELECT ?, ?, ?, ?, ? WHERE NOT EXISTS (SELECT null FROM `" + + this.prefix + "plot` WHERE `world` = ? AND `plot_id_x` = ? AND `plot_id_z` = ?)"; + } + this.CREATE_CLUSTER = "INSERT INTO `" + this.prefix + + "cluster`(`pos1_x`, `pos1_z`, `pos2_x`, `pos2_z`, `owner`, `world`) VALUES(?, ?, ?, ?, ?, ?)"; + try { + createTables(); + } catch (SQLException e) { + e.printStackTrace(); + } + TaskManager.runTaskAsync(() -> { + long last = System.currentTimeMillis(); + while (true) { + if (SQLManager.this.closed) { + break; + } + boolean hasTask = + !globalTasks.isEmpty() || !playerTasks.isEmpty() || !plotTasks.isEmpty() + || !clusterTasks.isEmpty(); + if (hasTask) { + if (SQLManager.this.mySQL && System.currentTimeMillis() - last > 550000 + || !isValid()) { + last = System.currentTimeMillis(); + reconnect(); + } + if (!sendBatch()) { + try { + if (!getNotifyTasks().isEmpty()) { + for (Runnable task : getNotifyTasks()) { + TaskManager.runTask(task); + } + getNotifyTasks().clear(); + } + Thread.sleep(50); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } else { - this.CREATE_PLOT_SAFE = "INSERT INTO `" + this.prefix - + "plot`(`plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp`) SELECT ?, ?, ?, ?, ? WHERE NOT EXISTS (SELECT null FROM `" - + this.prefix + "plot` WHERE `world` = ? AND `plot_id_x` = ? AND `plot_id_z` = ?)"; - } - this.CREATE_CLUSTER = "INSERT INTO `" + this.prefix - + "cluster`(`pos1_x`, `pos1_z`, `pos2_x`, `pos2_z`, `owner`, `world`) VALUES(?, ?, ?, ?, ?, ?)"; - try { - createTables(); - } catch (SQLException e) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { e.printStackTrace(); + } } - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - long last = System.currentTimeMillis(); - while (true) { - if (SQLManager.this.closed) { - break; - } - boolean hasTask = - !globalTasks.isEmpty() || !playerTasks.isEmpty() || !plotTasks.isEmpty() - || !clusterTasks.isEmpty(); - if (hasTask) { - if (SQLManager.this.mySQL && System.currentTimeMillis() - last > 550000 - || !isValid()) { - last = System.currentTimeMillis(); - reconnect(); - } - if (!sendBatch()) { - try { - if (!getNotifyTasks().isEmpty()) { - for (Runnable task : getNotifyTasks()) { - TaskManager.runTask(task); - } - getNotifyTasks().clear(); - } - Thread.sleep(50); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } else { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - }); + } + }); + } + + public boolean isValid() { + try { + if (connection.isClosed()) { + return false; + } + } catch (SQLException e) { + return false; } - - public boolean isValid() { - try { - if (connection.isClosed()) { - return false; - } - } catch (SQLException e) { - return false; - } - try (PreparedStatement stmt = this.connection.prepareStatement("SELECT 1")) { - stmt.executeQuery(); - return true; - } catch (Throwable e) { - return false; - } + try (PreparedStatement stmt = this.connection.prepareStatement("SELECT 1")) { + stmt.executeQuery(); + return true; + } catch (Throwable e) { + return false; } + } - public void reconnect() { - try { - close(); - SQLManager.this.closed = false; - SQLManager.this.connection = database.forceConnection(); - } catch (SQLException | ClassNotFoundException e) { - e.printStackTrace(); - } + public void reconnect() { + try { + close(); + SQLManager.this.closed = false; + SQLManager.this.connection = database.forceConnection(); + } catch (SQLException | ClassNotFoundException e) { + e.printStackTrace(); } + } - public synchronized Queue getGlobalTasks() { - return this.globalTasks; + public synchronized Queue getGlobalTasks() { + return this.globalTasks; + } + + public synchronized Queue getNotifyTasks() { + return this.notifyTasks; + } + + public synchronized void addPlotTask(@Nonnull Plot plot, UniqueStatement task) { + Queue tasks = this.plotTasks.computeIfAbsent(plot, plot1 -> new ConcurrentLinkedQueue<>()); + if (task == null) { + task = new UniqueStatement(String.valueOf(plot.hashCode())) { + + @Override + public PreparedStatement get() { + return null; + } + + @Override + public void set(PreparedStatement stmt) { + } + + @Override + public void addBatch(PreparedStatement statement) { + } + + @Override + public void execute(PreparedStatement statement) { + } + + }; } + tasks.add(task); + } - public synchronized Queue getNotifyTasks() { - return this.notifyTasks; + public synchronized void addPlayerTask(UUID uuid, UniqueStatement task) { + if (uuid == null) { + return; } + Queue tasks = this.playerTasks.computeIfAbsent(uuid, uuid1 -> new ConcurrentLinkedQueue<>()); + if (task == null) { + task = new UniqueStatement(String.valueOf(uuid.hashCode())) { - public synchronized void addPlotTask(Plot plot, UniqueStatement task) { - if (plot == null) { - plot = new Plot(null, new PlotId(Integer.MAX_VALUE, Integer.MAX_VALUE)); + @Override + public PreparedStatement get() { + return null; } - Queue tasks = this.plotTasks.get(plot); - if (tasks == null) { - tasks = new ConcurrentLinkedQueue<>(); - this.plotTasks.put(plot, tasks); + + @Override + public void set(PreparedStatement stmt) { } - if (task == null) { - task = new UniqueStatement(String.valueOf(plot.hashCode())) { - @Override public PreparedStatement get() { - return null; - } - - @Override public void set(PreparedStatement stmt) { - } - - @Override public void addBatch(PreparedStatement statement) { - } - - @Override public void execute(PreparedStatement statement) { - } - - }; + @Override + public void addBatch(PreparedStatement statement) { } - tasks.add(task); + + @Override + public void execute(PreparedStatement statement) { + } + + }; } + tasks.add(task); + } - public synchronized void addPlayerTask(UUID uuid, UniqueStatement task) { - if (uuid == null) { - return; + public synchronized void addClusterTask(PlotCluster cluster, UniqueStatement task) { + Queue tasks = this.clusterTasks.computeIfAbsent(cluster, plotCluster -> new ConcurrentLinkedQueue<>()); + if (task == null) { + task = new UniqueStatement(String.valueOf(cluster.hashCode())) { + + @Override + public PreparedStatement get() { + return null; } - Queue tasks = this.playerTasks.get(uuid); - if (tasks == null) { - tasks = new ConcurrentLinkedQueue<>(); - this.playerTasks.put(uuid, tasks); + + @Override + public void set(PreparedStatement stmt) { } - if (task == null) { - task = new UniqueStatement(String.valueOf(uuid.hashCode())) { - @Override public PreparedStatement get() { - return null; - } - - @Override public void set(PreparedStatement stmt) { - } - - @Override public void addBatch(PreparedStatement statement) { - } - - @Override public void execute(PreparedStatement statement) { - } - - }; + @Override + public void addBatch(PreparedStatement statement) { } - tasks.add(task); + + @Override + public void execute(PreparedStatement statement) { + } + + }; } + tasks.add(task); + } - public synchronized void addClusterTask(PlotCluster cluster, UniqueStatement task) { - Queue tasks = this.clusterTasks.get(cluster); - if (tasks == null) { - tasks = new ConcurrentLinkedQueue<>(); - this.clusterTasks.put(cluster, tasks); - } - if (task == null) { - task = new UniqueStatement(String.valueOf(cluster.hashCode())) { + public synchronized void addGlobalTask(Runnable task) { + getGlobalTasks().add(task); + } - @Override public PreparedStatement get() { - return null; - } - - @Override public void set(PreparedStatement stmt) { - } - - @Override public void addBatch(PreparedStatement statement) { - } - - @Override public void execute(PreparedStatement statement) { - } - - }; - } - tasks.add(task); + public synchronized void addNotifyTask(Runnable task) { + if (task != null) { + getNotifyTasks().add(task); } + } - public synchronized void addGlobalTask(Runnable task) { - getGlobalTasks().add(task); - } - - public synchronized void addNotifyTask(Runnable task) { + public boolean sendBatch() { + try { + if (!getGlobalTasks().isEmpty()) { + if (this.connection.getAutoCommit()) { + this.connection.setAutoCommit(false); + } + Runnable task = getGlobalTasks().remove(); if (task != null) { - getNotifyTasks().add(task); - } - } - - public boolean sendBatch() { - try { - if (!getGlobalTasks().isEmpty()) { - if (this.connection.getAutoCommit()) { - this.connection.setAutoCommit(false); - } - Runnable task = getGlobalTasks().remove(); - if (task != null) { - try { - task.run(); - } catch (Throwable e) { - PlotSquared.debug("============ DATABASE ERROR ============"); - PlotSquared.debug("There was an error updating the database."); - PlotSquared.debug(" - It will be corrected on shutdown"); - PlotSquared.debug("========================================"); - e.printStackTrace(); - PlotSquared.debug("========================================"); - } - } - commit(); - return true; - } - int count = -1; - if (!this.plotTasks.isEmpty()) { - count = 0; - if (this.connection.getAutoCommit()) { - this.connection.setAutoCommit(false); - } - String method = null; - PreparedStatement statement = null; - UniqueStatement task = null; - UniqueStatement lastTask = null; - Iterator>> iter = - this.plotTasks.entrySet().iterator(); - while (iter.hasNext()) { - try { - Entry> entry = iter.next(); - Plot plot = entry.getKey(); - Queue tasks = entry.getValue(); - if (tasks.isEmpty()) { - iter.remove(); - continue; - } - task = tasks.remove(); - count++; - if (task != null) { - if (task.method == null || !task.method.equals(method) - || statement == null) { - if (statement != null) { - lastTask.execute(statement); - statement.close(); - } - method = task.method; - statement = task.get(); - } - task.set(statement); - task.addBatch(statement); - try { - if (statement.isClosed()) { - statement = null; - } - } catch (AbstractMethodError ignore) { - } - } - lastTask = task; - } catch (Throwable e) { - PlotSquared.debug("============ DATABASE ERROR ============"); - PlotSquared.debug("There was an error updating the database."); - PlotSquared.debug(" - It will be corrected on shutdown"); - PlotSquared.debug("========================================"); - e.printStackTrace(); - PlotSquared.debug("========================================"); - } - } - if (statement != null && task != null) { - task.execute(statement); - statement.close(); - } - } - if (!this.playerTasks.isEmpty()) { - count = 0; - if (this.connection.getAutoCommit()) { - this.connection.setAutoCommit(false); - } - String method = null; - PreparedStatement statement = null; - UniqueStatement task = null; - UniqueStatement lastTask = null; - for (Entry> entry : this.playerTasks.entrySet()) { - try { - UUID uuid = entry.getKey(); - if (this.playerTasks.get(uuid).isEmpty()) { - this.playerTasks.remove(uuid); - continue; - } - task = this.playerTasks.get(uuid).remove(); - count++; - if (task != null) { - if (task.method == null || !task.method.equals(method)) { - if (statement != null) { - lastTask.execute(statement); - statement.close(); - } - method = task.method; - statement = task.get(); - } - task.set(statement); - task.addBatch(statement); - } - lastTask = task; - } catch (Throwable e) { - PlotSquared.debug("============ DATABASE ERROR ============"); - PlotSquared.debug("There was an error updating the database."); - PlotSquared.debug(" - It will be corrected on shutdown"); - PlotSquared.debug("========================================"); - e.printStackTrace(); - PlotSquared.debug("========================================"); - } - } - if (statement != null && task != null) { - task.execute(statement); - statement.close(); - } - } - if (!this.clusterTasks.isEmpty()) { - count = 0; - if (this.connection.getAutoCommit()) { - this.connection.setAutoCommit(false); - } - String method = null; - PreparedStatement statement = null; - UniqueStatement task = null; - UniqueStatement lastTask = null; - for (Entry> entry : this.clusterTasks - .entrySet()) { - try { - PlotCluster cluster = entry.getKey(); - if (this.clusterTasks.get(cluster).isEmpty()) { - this.clusterTasks.remove(cluster); - continue; - } - task = this.clusterTasks.get(cluster).remove(); - count++; - if (task != null) { - if (task.method == null || !task.method.equals(method)) { - if (statement != null) { - lastTask.execute(statement); - statement.close(); - } - method = task.method; - statement = task.get(); - } - task.set(statement); - task.addBatch(statement); - } - lastTask = task; - } catch (Throwable e) { - PlotSquared.debug("============ DATABASE ERROR ============"); - PlotSquared.debug("There was an error updating the database."); - PlotSquared.debug(" - It will be corrected on shutdown"); - PlotSquared.debug("========================================"); - e.printStackTrace(); - PlotSquared.debug("========================================"); - } - } - if (statement != null && task != null) { - task.execute(statement); - statement.close(); - } - } - if (count > 0) { - commit(); - return true; - } - if (count != -1) { - if (!this.connection.getAutoCommit()) { - this.connection.setAutoCommit(true); - } - } - if (!this.clusterTasks.isEmpty()) { - this.clusterTasks.clear(); - } - if (!this.plotTasks.isEmpty()) { - this.plotTasks.clear(); - } - } catch (Throwable e) { + try { + task.run(); + } catch (Throwable e) { PlotSquared.debug("============ DATABASE ERROR ============"); PlotSquared.debug("There was an error updating the database."); PlotSquared.debug(" - It will be corrected on shutdown"); PlotSquared.debug("========================================"); e.printStackTrace(); PlotSquared.debug("========================================"); + } } - return false; - } - - public Connection getConnection() { - return this.connection; - } - - /** - * Set Plot owner - * - * @param plot Plot Object - * @param uuid Owner UUID - */ - @Override public void setOwner(final Plot plot, final UUID uuid) { - addPlotTask(plot, new UniqueStatement("setOwner") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setString(1, uuid.toString()); - statement.setInt(2, plot.getId().x); - statement.setInt(3, plot.getId().y); - statement.setString(4, plot.getArea().toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement(SQLManager.this.SET_OWNER); - } - }); - } - - @Override public void createPlotsAndData(final List myList, final Runnable whenDone) { - addGlobalTask(new Runnable() { - @Override public void run() { - try { - // Create the plots - createPlots(myList, new Runnable() { - @Override public void run() { - try { - // Creating datastructures - HashMap plotMap = new HashMap<>(); - for (Plot plot : myList) { - plotMap.put(plot.getId(), plot); - } - ArrayList settings = new ArrayList<>(); - final ArrayList helpers = new ArrayList<>(); - final ArrayList trusted = new ArrayList<>(); - final ArrayList denied = new ArrayList<>(); - - // Populating structures - try (PreparedStatement stmt = SQLManager.this.connection - .prepareStatement(SQLManager.this.GET_ALL_PLOTS); - ResultSet result = stmt.executeQuery()) { - while (result.next()) { - int id = result.getInt("id"); - int x = result.getInt("plot_id_x"); - int y = result.getInt("plot_id_z"); - PlotId plotId = new PlotId(x, y); - Plot plot = plotMap.get(plotId); - if (plot != null) { - settings.add(new SettingsPair(id, plot.getSettings())); - for (UUID uuid : plot.getDenied()) { - denied.add(new UUIDPair(id, uuid)); - } - for (UUID uuid : plot.getMembers()) { - trusted.add(new UUIDPair(id, uuid)); - } - for (UUID uuid : plot.getTrusted()) { - helpers.add(new UUIDPair(id, uuid)); - } - } - } - } - createSettings(settings, new Runnable() { - @Override public void run() { - createTiers(helpers, "helpers", new Runnable() { - @Override public void run() { - createTiers(trusted, "trusted", new Runnable() { - @Override public void run() { - createTiers(denied, "denied", - new Runnable() { - @Override public void run() { - try { - SQLManager.this.connection - .commit(); - } catch (SQLException e) { - e.printStackTrace(); - } - if (whenDone != null) { - whenDone.run(); - } - } - }); - } - }); - } - }); - } - }); - } catch (SQLException e) { - e.printStackTrace(); - PlotSquared.debug("&7[WARN] Failed to set all helpers for plots"); - try { - SQLManager.this.connection.commit(); - } catch (SQLException e1) { - e1.printStackTrace(); - } - } - } - }); - } catch (Exception e) { - e.printStackTrace(); - PlotSquared.debug("&7[WARN] Failed to set all helpers for plots"); - try { - SQLManager.this.connection.commit(); - } catch (SQLException e1) { - e1.printStackTrace(); - } - } - } - }); - } - - /** - * Create a plot - * - * @param myList list of plots to be created - */ - public void createTiers(ArrayList myList, final String tier, Runnable whenDone) { - StmtMod mod = new StmtMod() { - @Override public String getCreateMySQL(int size) { - return getCreateMySQL(size, SQLManager.this.CREATE_TIERS.replaceAll("%tier%", tier), - 2); - } - - @Override public String getCreateSQLite(int size) { - return getCreateSQLite(size, - "INSERT INTO `" + SQLManager.this.prefix + "plot_" + tier - + "` SELECT ? AS `plot_plot_id`, ? AS `user_uuid`", 2); - } - - @Override public String getCreateSQL() { - return "INSERT INTO `" + SQLManager.this.prefix + "plot_" + tier - + "` (`plot_plot_id`, `user_uuid`) VALUES(?,?)"; - } - - @Override public void setMySQL(PreparedStatement stmt, int i, UUIDPair pair) - throws SQLException { - stmt.setInt(i * 2 + 1, pair.id); - stmt.setString(i * 2 + 2, pair.uuid.toString()); - } - - @Override public void setSQLite(PreparedStatement stmt, int i, UUIDPair pair) - throws SQLException { - stmt.setInt(i * 2 + 1, pair.id); - stmt.setString(i * 2 + 2, pair.uuid.toString()); - } - - @Override public void setSQL(PreparedStatement stmt, UUIDPair pair) - throws SQLException { - stmt.setInt(1, pair.id); - stmt.setString(2, pair.uuid.toString()); - } - }; - setBulk(myList, mod, whenDone); - } - - /** - * Create a plot - * - * @param myList list of plots to be created - */ - public void createPlots(List myList, Runnable whenDone) { - StmtMod mod = new StmtMod() { - @Override public String getCreateMySQL(int size) { - return getCreateMySQL(size, SQLManager.this.CREATE_PLOTS, 5); - } - - @Override public String getCreateSQLite(int size) { - return getCreateSQLite(size, "INSERT INTO `" + SQLManager.this.prefix - + "plot` SELECT ? AS `id`, ? AS `plot_id_x`, ? AS `plot_id_z`, ? AS `owner`, ? AS `world`, ? AS `timestamp` ", - 6); - } - - @Override public String getCreateSQL() { - return SQLManager.this.CREATE_PLOT; - } - - @Override public void setMySQL(PreparedStatement stmt, int i, Plot plot) - throws SQLException { - stmt.setInt(i * 5 + 1, plot.getId().x); - stmt.setInt(i * 5 + 2, plot.getId().y); - try { - stmt.setString(i * 5 + 3, plot.owner.toString()); - } catch (SQLException ignored) { - stmt.setString(i * 5 + 3, everyone.toString()); - } - stmt.setString(i * 5 + 4, plot.getArea().toString()); - stmt.setTimestamp(i * 5 + 5, new Timestamp(plot.getTimestamp())); - } - - @Override public void setSQLite(PreparedStatement stmt, int i, Plot plot) - throws SQLException { - stmt.setNull(i * 6 + 1, 4); - stmt.setInt(i * 6 + 2, plot.getId().x); - stmt.setInt(i * 6 + 3, plot.getId().y); - try { - stmt.setString(i * 6 + 4, plot.owner.toString()); - } catch (SQLException ignored) { - stmt.setString(i * 6 + 4, everyone.toString()); - } - stmt.setString(i * 6 + 5, plot.getArea().toString()); - stmt.setTimestamp(i * 6 + 6, new Timestamp(plot.getTimestamp())); - } - - @Override public void setSQL(PreparedStatement stmt, Plot plot) throws SQLException { - stmt.setInt(1, plot.getId().x); - stmt.setInt(2, plot.getId().y); - stmt.setString(3, plot.owner.toString()); - stmt.setString(4, plot.getArea().toString()); - stmt.setTimestamp(5, new Timestamp(plot.getTimestamp())); - - } - }; - setBulk(myList, mod, whenDone); - } - - public void setBulk(List objList, StmtMod mod, Runnable whenDone) { - int size = objList.size(); - if (size == 0) { - if (whenDone != null) { - whenDone.run(); - } - return; - } - int packet; - if (this.mySQL) { - packet = Math.min(size, 5000); - } else { - packet = Math.min(size, 50); - } - int amount = size / packet; - try { - int count = 0; - PreparedStatement preparedStmt = null; - int last = -1; - for (int j = 0; j <= amount; j++) { - List subList = objList.subList(j * packet, Math.min(size, (j + 1) * packet)); - if (subList.isEmpty()) { - break; - } - String statement; - if (last == -1) { - last = subList.size(); - statement = mod.getCreateMySQL(subList.size()); - preparedStmt = this.connection.prepareStatement(statement); - } - if (subList.size() != last || count % 5000 == 0 && count > 0) { - preparedStmt.executeBatch(); - preparedStmt.close(); - statement = mod.getCreateMySQL(subList.size()); - preparedStmt = this.connection.prepareStatement(statement); - } - for (int i = 0; i < subList.size(); i++) { - count++; - T obj = subList.get(i); - mod.setMySQL(preparedStmt, i, obj); - } - last = subList.size(); - preparedStmt.addBatch(); - } - PlotSquared.debug( - "&aBatch 1: " + count + " | " + objList.get(0).getClass().getCanonicalName()); - preparedStmt.executeBatch(); - preparedStmt.clearParameters(); - preparedStmt.close(); - if (whenDone != null) { - whenDone.run(); - } - return; - } catch (SQLException e) { - if (this.mySQL) { - e.printStackTrace(); - PlotSquared.debug("&cERROR 1: | " + objList.get(0).getClass().getCanonicalName()); - } - } - try { - int count = 0; - PreparedStatement preparedStmt = null; - int last = -1; - for (int j = 0; j <= amount; j++) { - List subList = objList.subList(j * packet, Math.min(size, (j + 1) * packet)); - if (subList.isEmpty()) { - break; - } - String statement; - if (last == -1) { - last = subList.size(); - statement = mod.getCreateSQLite(subList.size()); - preparedStmt = this.connection.prepareStatement(statement); - } - if (subList.size() != last || count % 5000 == 0 && count > 0) { - preparedStmt.executeBatch(); - preparedStmt.clearParameters(); - statement = mod.getCreateSQLite(subList.size()); - preparedStmt = this.connection.prepareStatement(statement); - } - for (int i = 0; i < subList.size(); i++) { - count++; - T obj = subList.get(i); - mod.setSQLite(preparedStmt, i, obj); - } - last = subList.size(); - preparedStmt.addBatch(); - } - PlotSquared.debug( - "&aBatch 2: " + count + " | " + objList.get(0).getClass().getCanonicalName()); - preparedStmt.executeBatch(); - preparedStmt.clearParameters(); - preparedStmt.close(); - } catch (SQLException e) { - e.printStackTrace(); - PlotSquared.debug("&cERROR 2: | " + objList.get(0).getClass().getCanonicalName()); - PlotSquared.debug("&6[WARN] Could not bulk save!"); - try (PreparedStatement preparedStmt = this.connection - .prepareStatement(mod.getCreateSQL())) { - for (T obj : objList) { - mod.setSQL(preparedStmt, obj); - preparedStmt.addBatch(); - } - PlotSquared.debug("&aBatch 3"); - preparedStmt.executeBatch(); - } catch (SQLException e3) { - e3.printStackTrace(); - PlotSquared.debug("&c[ERROR] Failed to save all!"); - } - } - if (whenDone != null) { - whenDone.run(); - } - } - - public void createSettings(final ArrayList myList, final Runnable whenDone) { - final StmtMod mod = new StmtMod() { - @Override public String getCreateMySQL(int size) { - return getCreateMySQL(size, "INSERT INTO `" + SQLManager.this.prefix - + "plot_settings`(`plot_plot_id`,`biome`,`rain`,`custom_time`,`time`,`deny_entry`,`alias`,`flags`,`merged`," - + "`position`) VALUES ", 10); - } - - @Override public String getCreateSQLite(int size) { - return getCreateSQLite(size, "INSERT INTO `" + SQLManager.this.prefix - + "plot_settings` SELECT ? AS `plot_plot_id`, ? AS `biome`, ? AS `rain`, ? AS `custom_time`, ? AS `time`, ? AS " - + "`deny_entry`, ? AS `alias`, ? AS `flags`, ? AS `merged`, ? AS `position`", - 10); - } - - @Override public String getCreateSQL() { - return "INSERT INTO `" + SQLManager.this.prefix - + "plot_settings`(`plot_plot_id`) VALUES(?)"; - } - - @Override public void setMySQL(PreparedStatement statement, int i, SettingsPair pair) - throws SQLException { - statement.setInt(i * 10 + 1, pair.id); // id - statement.setNull(i * 10 + 2, 4); // biome - statement.setNull(i * 10 + 3, 4); // rain - statement.setNull(i * 10 + 4, 4); // custom_time - statement.setNull(i * 10 + 5, 4); // time - statement.setNull(i * 10 + 6, 4); // deny_entry - if (pair.settings.getAlias().isEmpty()) { - statement.setNull(i * 10 + 7, 4); - } else { - statement.setString(i * 10 + 7, pair.settings.getAlias()); - } - StringBuilder flag_string = new StringBuilder(); - int k = 0; - for (Entry, ?> flag : pair.settings.flags.entrySet()) { - if (k != 0) { - flag_string.append(','); - } - flag_string.append(flag.getKey().getName()).append(':').append( - flag.getKey().valueToString(flag.getValue()).replaceAll(":", "¯") - .replaceAll(",", "´")); - k++; - } - statement.setString(i * 10 + 8, flag_string.toString()); - boolean[] merged = pair.settings.getMerged(); - int hash = MainUtil.hash(merged); - statement.setInt(i * 10 + 9, hash); - BlockLoc loc = pair.settings.getPosition(); - String position; - if (loc.y == 0) { - position = "DEFAULT"; - } else { - position = loc.x + "," + loc.y + ',' + loc.z; - } - statement.setString(i * 10 + 10, position); - } - - @Override public void setSQLite(PreparedStatement stmt, int i, SettingsPair pair) - throws SQLException { - stmt.setInt(i * 10 + 1, pair.id); // id - stmt.setNull(i * 10 + 2, 4); // biome - stmt.setNull(i * 10 + 3, 4); // rain - stmt.setNull(i * 10 + 4, 4); // custom_time - stmt.setNull(i * 10 + 5, 4); // time - stmt.setNull(i * 10 + 6, 4); // deny_entry - if (pair.settings.getAlias().isEmpty()) { - stmt.setNull(i * 10 + 7, 4); - } else { - stmt.setString(i * 10 + 7, pair.settings.getAlias()); - } - StringBuilder flag_string = new StringBuilder(); - int k = 0; - for (Entry, ?> flag : pair.settings.flags.entrySet()) { - if (k != 0) { - flag_string.append(','); - } - flag_string.append(flag.getKey().getName()).append(':').append( - flag.getKey().valueToString(flag.getValue()).replaceAll(":", "¯") - .replaceAll(",", "´")); - k++; - } - stmt.setString(i * 10 + 8, flag_string.toString()); - boolean[] merged = pair.settings.getMerged(); - int n = 0; - for (int j = 0; j < 4; ++j) { - n = (n << 1) + (merged[j] ? 1 : 0); - } - stmt.setInt(i * 10 + 9, n); - BlockLoc loc = pair.settings.getPosition(); - String position; - if (loc.y == 0) { - position = "DEFAULT"; - } else { - position = loc.x + "," + loc.y + ',' + loc.z; - } - stmt.setString(i * 10 + 10, position); - } - - @Override public void setSQL(PreparedStatement stmt, SettingsPair pair) - throws SQLException { - stmt.setInt(1, pair.id); - } - }; - addGlobalTask(new Runnable() { - @Override public void run() { - setBulk(myList, mod, whenDone); - } - }); - } - - public void createEmptySettings(final ArrayList myList, final Runnable whenDone) { - final StmtMod mod = new StmtMod() { - @Override public String getCreateMySQL(int size) { - return getCreateMySQL(size, SQLManager.this.CREATE_SETTINGS, 1); - } - - @Override public String getCreateSQLite(int size) { - return getCreateSQLite(size, "INSERT INTO `" + SQLManager.this.prefix - + "plot_settings` SELECT ? AS `plot_plot_id`, ? AS `biome`, ? AS `rain`, ? AS `custom_time`, ? AS `time`, ? AS " - + "`deny_entry`, ? AS `alias`, ? AS `flags`, ? AS `merged`, ? AS `position` ", - 10); - } - - @Override public String getCreateSQL() { - return "INSERT INTO `" + SQLManager.this.prefix - + "plot_settings`(`plot_plot_id`) VALUES(?)"; - } - - @Override public void setMySQL(PreparedStatement stmt, int i, Integer id) - throws SQLException { - stmt.setInt(i + 1, id); - } - - @Override public void setSQLite(PreparedStatement stmt, int i, Integer id) - throws SQLException { - stmt.setInt(i * 10 + 1, id); - stmt.setNull(i * 10 + 2, 4); - stmt.setNull(i * 10 + 3, 4); - stmt.setNull(i * 10 + 4, 4); - stmt.setNull(i * 10 + 5, 4); - stmt.setNull(i * 10 + 6, 4); - stmt.setNull(i * 10 + 7, 4); - stmt.setNull(i * 10 + 8, 4); - stmt.setNull(i * 10 + 9, 4); - stmt.setString(i * 10 + 10, "DEFAULT"); - } - - @Override public void setSQL(PreparedStatement stmt, Integer id) throws SQLException { - stmt.setInt(1, id); - } - }; - addGlobalTask(new Runnable() { - @Override public void run() { - setBulk(myList, mod, whenDone); - } - }); - } - - public void createPlotSafe(final Plot plot, final Runnable success, final Runnable failure) { - final long timestamp = plot.getTimestamp(); - addPlotTask(plot, new UniqueStatement("createPlotSafe_" + plot.hashCode()) { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, plot.getId().x); - stmt.setInt(2, plot.getId().y); - stmt.setString(3, plot.owner.toString()); - stmt.setString(4, plot.getArea().toString()); - stmt.setTimestamp(5, new Timestamp(plot.getTimestamp())); - stmt.setString(6, plot.getArea().toString()); - stmt.setInt(7, plot.getId().x); - stmt.setInt(8, plot.getId().y); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement(SQLManager.this.CREATE_PLOT_SAFE, - Statement.RETURN_GENERATED_KEYS); - } - - @Override public void execute(PreparedStatement statement) { - - } - - @Override public void addBatch(PreparedStatement statement) throws SQLException { - int inserted = statement.executeUpdate(); - if (inserted > 0) { - try (ResultSet keys = statement.getGeneratedKeys()) { - if (keys.next()) { - plot.temp = keys.getInt(1); - addPlotTask(plot, new UniqueStatement( - "createPlotAndSettings_settings_" + plot.hashCode()) { - @Override public void set(PreparedStatement stmt) - throws SQLException { - stmt.setInt(1, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "plot_settings`(`plot_plot_id`) VALUES(?)"); - } - }); - if (success != null) - addNotifyTask(success); - return; - } - } - } - if (failure != null) - failure.run(); - } - }); - } - - public void commit() { - if (this.closed) { - return; - } - try { - if (!this.connection.getAutoCommit()) { - this.connection.commit(); - this.connection.setAutoCommit(true); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } - - @Override public void createPlotAndSettings(final Plot plot, Runnable whenDone) { - addPlotTask(plot, new UniqueStatement("createPlotAndSettings_" + plot.hashCode()) { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, plot.getId().x); - stmt.setInt(2, plot.getId().y); - stmt.setString(3, plot.owner.toString()); - stmt.setString(4, plot.getArea().toString()); - stmt.setTimestamp(5, new Timestamp(plot.getTimestamp())); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection - .prepareStatement(SQLManager.this.CREATE_PLOT, Statement.RETURN_GENERATED_KEYS); - } - - @Override public void execute(PreparedStatement statement) { - } - - @Override public void addBatch(PreparedStatement statement) throws SQLException { - statement.executeUpdate(); - try (ResultSet keys = statement.getGeneratedKeys()) { - if (keys.next()) { - plot.temp = keys.getInt(1); - } - } - } - }); - addPlotTask(plot, new UniqueStatement("createPlotAndSettings_settings_" + plot.hashCode()) { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "plot_settings`(`plot_plot_id`) VALUES(?)"); - } - }); - addNotifyTask(whenDone); - } - - /** - * Create tables. - * - * @throws SQLException - */ - @Override public void createTables() throws SQLException { - String[] tables = - new String[] {"plot", "plot_denied", "plot_helpers", "plot_comments", "plot_trusted", - "plot_rating", "plot_settings", "cluster", "player_meta"}; - DatabaseMetaData meta = this.connection.getMetaData(); - int create = 0; - for (String s : tables) { - ResultSet set = meta.getTables(null, null, this.prefix + s, new String[] {"TABLE"}); - // ResultSet set = meta.getTables(null, null, prefix + s, null); - if (!set.next()) { - create++; - } - set.close(); - } - if (create == 0) { - return; - } - boolean addConstraint = create == tables.length; - PlotSquared.debug("Creating tables"); - try (Statement stmt = this.connection.createStatement()) { - if (this.mySQL) { - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot` (" - + "`id` INT(11) NOT NULL AUTO_INCREMENT," + "`plot_id_x` INT(11) NOT NULL," - + "`plot_id_z` INT(11) NOT NULL," + "`owner` VARCHAR(40) NOT NULL," - + "`world` VARCHAR(45) NOT NULL," - + "`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," - + "PRIMARY KEY (`id`)" - + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix - + "plot_denied` (`plot_plot_id` INT(11) NOT NULL," - + "`user_uuid` VARCHAR(40) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_helpers` (" - + "`plot_plot_id` INT(11) NOT NULL," + "`user_uuid` VARCHAR(40) NOT NULL" - + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_comments` (" - + "`world` VARCHAR(40) NOT NULL, `hashcode` INT(11) NOT NULL," - + "`comment` VARCHAR(40) NOT NULL," + "`inbox` VARCHAR(40) NOT NULL," - + "`timestamp` INT(11) NOT NULL," + "`sender` VARCHAR(40) NOT NULL" - + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_trusted` (" - + "`plot_plot_id` INT(11) NOT NULL," + "`user_uuid` VARCHAR(40) NOT NULL" - + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_settings` (" - + " `plot_plot_id` INT(11) NOT NULL," - + " `biome` VARCHAR(45) DEFAULT 'FOREST'," + " `rain` INT(1) DEFAULT 0," - + " `custom_time` TINYINT(1) DEFAULT '0'," + " `time` INT(11) DEFAULT '8000'," - + " `deny_entry` TINYINT(1) DEFAULT '0'," - + " `alias` VARCHAR(50) DEFAULT NULL," + " `flags` VARCHAR(512) DEFAULT NULL," - + " `merged` INT(11) DEFAULT NULL," - + " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," - + " PRIMARY KEY (`plot_plot_id`)" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix - + "plot_rating` ( `plot_plot_id` INT(11) NOT NULL, `rating` INT(2) NOT NULL, `player` VARCHAR(40) NOT NULL) ENGINE=InnoDB " - + "DEFAULT CHARSET=utf8"); - if (addConstraint) { - stmt.addBatch("ALTER TABLE `" + this.prefix + "plot_settings` ADD CONSTRAINT `" - + this.prefix - + "plot_settings_ibfk_1` FOREIGN KEY (`plot_plot_id`) REFERENCES `" - + this.prefix + "plot` (`id`) ON DELETE CASCADE"); - } - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster` (" - + "`id` INT(11) NOT NULL AUTO_INCREMENT," + "`pos1_x` INT(11) NOT NULL," - + "`pos1_z` INT(11) NOT NULL," + "`pos2_x` INT(11) NOT NULL," - + "`pos2_z` INT(11) NOT NULL," + "`owner` VARCHAR(40) NOT NULL," - + "`world` VARCHAR(45) NOT NULL," - + "`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," - + "PRIMARY KEY (`id`)" - + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster_helpers` (" - + "`cluster_id` INT(11) NOT NULL," + "`user_uuid` VARCHAR(40) NOT NULL" - + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster_invited` (" - + "`cluster_id` INT(11) NOT NULL," + "`user_uuid` VARCHAR(40) NOT NULL" - + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster_settings` (" - + " `cluster_id` INT(11) NOT NULL," + " `biome` VARCHAR(45) DEFAULT 'FOREST'," - + " `rain` INT(1) DEFAULT 0," + " `custom_time` TINYINT(1) DEFAULT '0'," - + " `time` INT(11) DEFAULT '8000'," + " `deny_entry` TINYINT(1) DEFAULT '0'," - + " `alias` VARCHAR(50) DEFAULT NULL," + " `flags` VARCHAR(512) DEFAULT NULL," - + " `merged` INT(11) DEFAULT NULL," - + " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," - + " PRIMARY KEY (`cluster_id`)" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "player_meta` (" - + " `meta_id` INT(11) NOT NULL AUTO_INCREMENT," - + " `uuid` VARCHAR(40) NOT NULL," + " `key` VARCHAR(32) NOT NULL," - + " `value` blob NOT NULL," + " PRIMARY KEY (`meta_id`)" - + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); - } else { - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot` (" - + "`id` INTEGER PRIMARY KEY AUTOINCREMENT," + "`plot_id_x` INT(11) NOT NULL," - + "`plot_id_z` INT(11) NOT NULL," + "`owner` VARCHAR(45) NOT NULL," - + "`world` VARCHAR(45) NOT NULL," - + "`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP)"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix - + "plot_denied` (`plot_plot_id` INT(11) NOT NULL," - + "`user_uuid` VARCHAR(40) NOT NULL)"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix - + "plot_helpers` (`plot_plot_id` INT(11) NOT NULL," - + "`user_uuid` VARCHAR(40) NOT NULL)"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix - + "plot_trusted` (`plot_plot_id` INT(11) NOT NULL," - + "`user_uuid` VARCHAR(40) NOT NULL)"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_comments` (" - + "`world` VARCHAR(40) NOT NULL, `hashcode` INT(11) NOT NULL," - + "`comment` VARCHAR(40) NOT NULL," - + "`inbox` VARCHAR(40) NOT NULL, `timestamp` INT(11) NOT NULL," - + "`sender` VARCHAR(40) NOT NULL" + ')'); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_settings` (" - + " `plot_plot_id` INT(11) NOT NULL," - + " `biome` VARCHAR(45) DEFAULT 'FOREST'," + " `rain` INT(1) DEFAULT 0," - + " `custom_time` TINYINT(1) DEFAULT '0'," + " `time` INT(11) DEFAULT '8000'," - + " `deny_entry` TINYINT(1) DEFAULT '0'," - + " `alias` VARCHAR(50) DEFAULT NULL," + " `flags` VARCHAR(512) DEFAULT NULL," - + " `merged` INT(11) DEFAULT NULL," - + " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," - + " PRIMARY KEY (`plot_plot_id`)" + ')'); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix - + "plot_rating` (`plot_plot_id` INT(11) NOT NULL, `rating` INT(2) NOT NULL, `player` VARCHAR(40) NOT NULL)"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster` (" - + "`id` INTEGER PRIMARY KEY AUTOINCREMENT," + "`pos1_x` INT(11) NOT NULL," - + "`pos1_z` INT(11) NOT NULL," + "`pos2_x` INT(11) NOT NULL," - + "`pos2_z` INT(11) NOT NULL," + "`owner` VARCHAR(40) NOT NULL," - + "`world` VARCHAR(45) NOT NULL," - + "`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP" + ')'); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix - + "cluster_helpers` (`cluster_id` INT(11) NOT NULL," - + "`user_uuid` VARCHAR(40) NOT NULL)"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix - + "cluster_invited` (`cluster_id` INT(11) NOT NULL," - + "`user_uuid` VARCHAR(40) NOT NULL)"); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster_settings` (" - + " `cluster_id` INT(11) NOT NULL," + " `biome` VARCHAR(45) DEFAULT 'FOREST'," - + " `rain` INT(1) DEFAULT 0," + " `custom_time` TINYINT(1) DEFAULT '0'," - + " `time` INT(11) DEFAULT '8000'," + " `deny_entry` TINYINT(1) DEFAULT '0'," - + " `alias` VARCHAR(50) DEFAULT NULL," + " `flags` VARCHAR(512) DEFAULT NULL," - + " `merged` INT(11) DEFAULT NULL," - + " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," - + " PRIMARY KEY (`cluster_id`)" + ')'); - stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "player_meta` (" - + " `meta_id` INTEGER PRIMARY KEY AUTOINCREMENT," - + " `uuid` VARCHAR(40) NOT NULL," + " `key` VARCHAR(32) NOT NULL," - + " `value` blob NOT NULL" + ')'); - } - stmt.executeBatch(); - stmt.clearBatch(); - } - } - - @Override public void deleteSettings(final Plot plot) { - addPlotTask(plot, new UniqueStatement("delete_plot_settings") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_settings` WHERE `plot_plot_id` = ?"); - } - }); - } - - @Override public void deleteHelpers(final Plot plot) { - if (plot.getTrusted().isEmpty()) { - return; - } - addPlotTask(plot, new UniqueStatement("delete_plot_helpers") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_helpers` WHERE `plot_plot_id` = ?"); - } - }); - } - - @Override public void deleteTrusted(final Plot plot) { - if (plot.getMembers().isEmpty()) { - return; - } - addPlotTask(plot, new UniqueStatement("delete_plot_trusted") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_trusted` WHERE `plot_plot_id` = ?"); - } - }); - } - - @Override public void deleteDenied(final Plot plot) { - if (plot.getDenied().isEmpty()) { - return; - } - addPlotTask(plot, new UniqueStatement("delete_plot_denied") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_denied` WHERE `plot_plot_id` = ?"); - } - }); - } - - @Override public void deleteComments(final Plot plot) { - addPlotTask(plot, new UniqueStatement("delete_plot_comments") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setString(1, plot.getArea().toString()); - stmt.setInt(2, plot.hashCode()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_comments` WHERE `world` = ? AND `hashcode` = ?"); - } - }); - } - - @Override public void deleteRatings(final Plot plot) { - if (Settings.Enabled_Components.RATING_CACHE && plot.getSettings().getRatings().isEmpty()) { - return; - } - addPlotTask(plot, new UniqueStatement("delete_plot_ratings") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_rating` WHERE `plot_plot_id` = ?"); - } - }); - } - - /** - * Delete a plot. - * - * @param plot - */ - @Override public void delete(final Plot plot) { - PlotSquared.debug( - "Deleting plot... Id: " + plot.getId() + " World: " + plot.getWorldName() + " Owner: " - + plot.owner + " Index: " + plot.temp); - deleteSettings(plot); - deleteDenied(plot); - deleteHelpers(plot); - deleteTrusted(plot); - deleteComments(plot); - deleteRatings(plot); - addPlotTask(plot, new UniqueStatement("delete_plot") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix + "plot` WHERE `id` = ?"); - } - }); - } - - /** - * Create plot settings - * - * @param id - * @param plot - */ - @Override public void createPlotSettings(final int id, Plot plot) { - PlotSquared.debug( - "Creating plot... Id: " + plot.getId() + " World: " + plot.getWorldName() + " Owner: " - + plot.owner + " Index: " + id); - addPlotTask(plot, new UniqueStatement("createPlotSettings") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, id); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "plot_settings`(`plot_plot_id`) VALUES(?)"); - } - }); - } - - @Override public int getClusterId(PlotCluster cluster) { - if (cluster.temp > 0) { - return cluster.temp; - } - try { - commit(); - if (cluster.temp > 0) { - return cluster.temp; - } - int c_id; - try (PreparedStatement stmt = this.connection.prepareStatement( - "SELECT `id` FROM `" + this.prefix - + "cluster` WHERE `pos1_x` = ? AND `pos1_z` = ? AND `pos2_x` = ? AND `pos2_z` = ? AND `world` = ? ORDER BY `timestamp` ASC")) { - stmt.setInt(1, cluster.getP1().x); - stmt.setInt(2, cluster.getP1().y); - stmt.setInt(3, cluster.getP2().x); - stmt.setInt(4, cluster.getP2().y); - stmt.setString(5, cluster.area.toString()); - try (ResultSet resultSet = stmt.executeQuery()) { - c_id = Integer.MAX_VALUE; - while (resultSet.next()) { - c_id = resultSet.getInt("id"); - } - } - } - if (c_id == Integer.MAX_VALUE || c_id == 0) { - if (cluster.temp > 0) { - return cluster.temp; - } - throw new SQLException("Cluster does not exist in database"); - } - cluster.temp = c_id; - return c_id; - } catch (SQLException e) { - e.printStackTrace(); - } - return Integer.MAX_VALUE; - } - - @Override public int getId(Plot plot) { - if (plot.temp > 0) { - return plot.temp; - } - try { - commit(); - if (plot.temp > 0) { - return plot.temp; - } - int id; - try (PreparedStatement statement = this.connection.prepareStatement( - "SELECT `id` FROM `" + this.prefix - + "plot` WHERE `plot_id_x` = ? AND `plot_id_z` = ? AND world = ? ORDER BY `timestamp` ASC")) { - statement.setInt(1, plot.getId().x); - statement.setInt(2, plot.getId().y); - statement.setString(3, plot.getArea().toString()); - try (ResultSet resultSet = statement.executeQuery()) { - id = Integer.MAX_VALUE; - while (resultSet.next()) { - id = resultSet.getInt("id"); - } - } - } - if (id == Integer.MAX_VALUE || id == 0) { - if (plot.temp > 0) { - return plot.temp; - } - throw new SQLException("Plot does not exist in database"); - } - plot.temp = id; - return id; - } catch (SQLException e) { - e.printStackTrace(); - } - return Integer.MAX_VALUE; - } - - @Override public void updateTables(int[] oldVersion) { - try { - if (this.mySQL && !PlotSquared.get().checkVersion(oldVersion, 3, 3, 2)) { - try (Statement stmt = this.connection.createStatement()) { - stmt.executeUpdate( - "ALTER TABLE `" + this.prefix + "plots` DROP INDEX `unique_alias`"); - } catch (SQLException ignored) { - } - } - DatabaseMetaData data = this.connection.getMetaData(); - ResultSet rs = - data.getColumns(null, null, this.prefix + "plot_comments", "plot_plot_id"); - if (rs.next()) { - rs.close(); - rs = data.getColumns(null, null, this.prefix + "plot_comments", "hashcode"); - if (!rs.next()) { - rs.close(); - try (Statement statement = this.connection.createStatement()) { - statement.addBatch("DROP TABLE `" + this.prefix + "plot_comments`"); - if (Storage.MySQL.USE) { - statement.addBatch( - "CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_comments` (" - + "`world` VARCHAR(40) NOT NULL, `hashcode` INT(11) NOT NULL," - + "`comment` VARCHAR(40) NOT NULL," - + "`inbox` VARCHAR(40) NOT NULL," - + "`timestamp` INT(11) NOT NULL," - + "`sender` VARCHAR(40) NOT NULL" - + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); - } else { - statement.addBatch( - "CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_comments` (" - + "`world` VARCHAR(40) NOT NULL, `hashcode` INT(11) NOT NULL," - + "`comment` VARCHAR(40) NOT NULL," - + "`inbox` VARCHAR(40) NOT NULL, `timestamp` INT(11) NOT NULL," - + "`sender` VARCHAR(40) NOT NULL" + ')'); - } - statement.executeBatch(); - } catch (SQLException ignored) { - try (Statement statement = this.connection.createStatement()) { - statement.addBatch("ALTER IGNORE TABLE `" + this.prefix - + "plot_comments` ADD `inbox` VARCHAR(11) DEFAULT `public`"); - statement.addBatch("ALTER IGNORE TABLE `" + this.prefix - + "plot_comments` ADD `timestamp` INT(11) DEFAULT 0"); - statement.addBatch("ALTER TABLE `" + this.prefix + "plot` DROP `tier`"); - statement.executeBatch(); - } - } - } - } - rs.close(); - rs = data.getColumns(null, null, this.prefix + "plot_denied", "plot_plot_id"); - if (rs.next()) { - try (Statement statement = this.connection.createStatement()) { - statement.executeUpdate("DELETE FROM `" + this.prefix - + "plot_denied` WHERE `plot_plot_id` NOT IN (SELECT `id` FROM `" - + this.prefix + "plot`)"); - } catch (SQLException e) { - e.printStackTrace(); - } - - rs.close(); - try (Statement statement = this.connection.createStatement()) { - for (String table : new String[] {"plot_denied", "plot_helpers", - "plot_trusted"}) { - ResultSet result = statement.executeQuery( - "SELECT plot_plot_id, user_uuid, COUNT(*) FROM " + this.prefix + table - + " GROUP BY plot_plot_id, user_uuid HAVING COUNT(*) > 1"); - if (result.next()) { - PlotSquared.debug("BACKING UP: " + this.prefix + table); - result.close(); - statement.executeUpdate( - "CREATE TABLE " + this.prefix + table + "_tmp AS SELECT * FROM " - + this.prefix + table + " GROUP BY plot_plot_id, user_uuid"); - statement.executeUpdate("DROP TABLE " + this.prefix + table); - statement.executeUpdate( - "CREATE TABLE " + this.prefix + table + " AS SELECT * FROM " - + this.prefix + table + "_tmp"); - statement.executeUpdate("DROP TABLE " + this.prefix + table + "_tmp"); - PlotSquared.debug("RESTORING: " + this.prefix + table); - } - } - } catch (SQLException e2) { - e2.printStackTrace(); - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - - } - - public void deleteRows(ArrayList rowIds, final String table, final String column) { - setBulk(rowIds, new StmtMod() { - - @Override public String getCreateMySQL(int size) { - return getCreateMySQL(1, "DELETE FROM `" + table + "` WHERE `" + column + "` IN ", - size); - } - - @Override public String getCreateSQLite(int size) { - return getCreateMySQL(1, "DELETE FROM `" + table + "` WHERE `" + column + "` IN ", - size); - } - - @Override public String getCreateSQL() { - return "DELETE FROM `" + table + "` WHERE `" + column + "` = ?"; - } - - @Override public void setMySQL(PreparedStatement stmt, int i, Integer obj) - throws SQLException { - stmt.setInt(i + 1, obj); - } - - @Override public void setSQLite(PreparedStatement stmt, int i, Integer obj) - throws SQLException { - stmt.setInt(i + 1, obj); - } - - @Override public void setSQL(PreparedStatement stmt, Integer obj) throws SQLException { - stmt.setInt(1, obj); - } - }, null); - } - - /** - * Load all plots, helpers, denied, trusted, and every setting from DB into a {@link HashMap}. - */ - @Override public HashMap> getPlots() { - HashMap> newPlots = new HashMap<>(); - HashMap plots = new HashMap<>(); - try { - HashSet areas = new HashSet<>(); - if (PlotSquared.get().worlds.contains("worlds")) { - ConfigurationSection worldSection = - PlotSquared.get().worlds.getConfigurationSection("worlds"); - if (worldSection != null) { - for (String worldKey : worldSection.getKeys(false)) { - areas.add(worldKey); - ConfigurationSection areaSection = - worldSection.getConfigurationSection(worldKey + ".areas"); - if (areaSection != null) { - for (String areaKey : areaSection.getKeys(false)) { - String[] split = areaKey.split("(? uuids = new HashMap<>(); - HashMap noExist = new HashMap<>(); - - /* - * Getting plots - */ - try (Statement statement = this.connection.createStatement()) { - int id; - String o; - UUID user; - try (ResultSet resultSet = statement.executeQuery( - "SELECT `id`, `plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp` FROM `" - + this.prefix + "plot`")) { - ArrayList toDelete = new ArrayList<>(); - while (resultSet.next()) { - PlotId plot_id = new PlotId(resultSet.getInt("plot_id_x"), - resultSet.getInt("plot_id_z")); - id = resultSet.getInt("id"); - String areaid = resultSet.getString("world"); - if (!areas.contains(areaid)) { - if (Settings.Enabled_Components.DATABASE_PURGER) { - toDelete.add(id); - continue; - } else { - AtomicInteger value = noExist.get(areaid); - if (value != null) { - value.incrementAndGet(); - } else { - noExist.put(areaid, new AtomicInteger(1)); - } - } - } - o = resultSet.getString("owner"); - user = uuids.get(o); - if (user == null) { - try { - user = UUID.fromString(o); - } catch (IllegalArgumentException e) { - if (Settings.UUID.FORCE_LOWERCASE) { - user = UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + o.toLowerCase()) - .getBytes(Charsets.UTF_8)); - } else { - user = UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + o).getBytes(Charsets.UTF_8)); - } - } - uuids.put(o, user); - } - long time; - try { - Timestamp timestamp = resultSet.getTimestamp("timestamp"); - time = timestamp.getTime(); - } catch (SQLException exception) { - String parsable = resultSet.getString("timestamp"); - try { - time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(parsable) - .getTime(); - } catch (ParseException e) { - PlotSquared.debug( - "Could not parse date for plot: #" + id + "(" + areaid + ";" - + plot_id + ") (" + parsable + ")"); - time = System.currentTimeMillis() + id; - } - } - Plot p = new Plot(plot_id, user, new HashSet(), new HashSet(), - new HashSet(), "", null, null, null, - new boolean[] {false, false, false, false}, time, id); - HashMap map = newPlots.get(areaid); - if (map != null) { - Plot last = map.put(p.getId(), p); - if (last != null) { - if (Settings.Enabled_Components.DATABASE_PURGER) { - toDelete.add(last.temp); - } else { - PlotSquared.debug( - "&cPLOT #" + id + "(" + last + ") in `" + this.prefix - + "plot` is a duplicate. Delete this plot or set `database-purger: true` in the settings.yml."); - } - } - } else { - map = new HashMap<>(); - newPlots.put(areaid, map); - map.put(p.getId(), p); - } - plots.put(id, p); - } - deleteRows(toDelete, this.prefix + "plot", "id"); - } - if (Settings.Enabled_Components.RATING_CACHE) { - try (ResultSet r = statement.executeQuery( - "SELECT `plot_plot_id`, `player`, `rating` FROM `" + this.prefix - + "plot_rating`")) { - ArrayList toDelete = new ArrayList<>(); - while (r.next()) { - id = r.getInt("plot_plot_id"); - o = r.getString("player"); - user = uuids.get(o); - if (user == null) { - user = UUID.fromString(o); - uuids.put(o, user); - } - Plot plot = plots.get(id); - if (plot != null) { - plot.getSettings().getRatings().put(user, r.getInt("rating")); - } else if (Settings.Enabled_Components.DATABASE_PURGER) { - toDelete.add(id); - } else { - PlotSquared.debug("&cENTRY #" + id + "(" + plot - + ") in `plot_rating` does not exist. Create this plot or set `database-purger: true` in the " - + "settings.yml."); - } - } - deleteRows(toDelete, this.prefix + "plot_rating", "plot_plot_id"); - } - } - - /* - * Getting helpers - */ - try (ResultSet r = statement.executeQuery( - "SELECT `user_uuid`, `plot_plot_id` FROM `" + this.prefix + "plot_helpers`")) { - ArrayList toDelete = new ArrayList<>(); - while (r.next()) { - id = r.getInt("plot_plot_id"); - o = r.getString("user_uuid"); - user = uuids.get(o); - if (user == null) { - user = UUID.fromString(o); - uuids.put(o, user); - } - Plot plot = plots.get(id); - if (plot != null) { - plot.getTrusted().add(user); - } else if (Settings.Enabled_Components.DATABASE_PURGER) { - toDelete.add(id); - } else { - PlotSquared.debug("&cENTRY #" + id + "(" + plot - + ") in `plot_helpers` does not exist. Create this plot or set `database-purger: true` in the settings" - + ".yml."); - } - } - deleteRows(toDelete, this.prefix + "plot_helpers", "plot_plot_id"); - } - - /* - * Getting trusted - */ - try (ResultSet r = statement.executeQuery( - "SELECT `user_uuid`, `plot_plot_id` FROM `" + this.prefix + "plot_trusted`")) { - ArrayList toDelete = new ArrayList<>(); - while (r.next()) { - id = r.getInt("plot_plot_id"); - o = r.getString("user_uuid"); - user = uuids.get(o); - if (user == null) { - user = UUID.fromString(o); - uuids.put(o, user); - } - Plot plot = plots.get(id); - if (plot != null) { - plot.getMembers().add(user); - } else if (Settings.Enabled_Components.DATABASE_PURGER) { - toDelete.add(id); - } else { - PlotSquared.debug("&cENTRY #" + id + "(" + plot - + ") in `plot_trusted` does not exist. Create this plot or set `database-purger: true` in the settings" - + ".yml."); - } - } - deleteRows(toDelete, this.prefix + "plot_trusted", "plot_plot_id"); - } - - /* - * Getting denied - */ - try (ResultSet r = statement.executeQuery( - "SELECT `user_uuid`, `plot_plot_id` FROM `" + this.prefix + "plot_denied`")) { - ArrayList toDelete = new ArrayList<>(); - while (r.next()) { - id = r.getInt("plot_plot_id"); - o = r.getString("user_uuid"); - user = uuids.get(o); - if (user == null) { - user = UUID.fromString(o); - uuids.put(o, user); - } - Plot plot = plots.get(id); - if (plot != null) { - plot.getDenied().add(user); - } else if (Settings.Enabled_Components.DATABASE_PURGER) { - toDelete.add(id); - } else { - PlotSquared.debug("&cENTRY " + id - + " in `plot_denied` does not exist. Create this plot or set `database-purger: true` in the settings.yml."); - } - } - deleteRows(toDelete, this.prefix + "plot_denied", "plot_plot_id"); - } - - try (ResultSet resultSet = statement - .executeQuery("SELECT * FROM `" + this.prefix + "plot_settings`")) { - ArrayList toDelete = new ArrayList<>(); - while (resultSet.next()) { - id = resultSet.getInt("plot_plot_id"); - Plot plot = plots.get(id); - if (plot != null) { - plots.remove(id); - String alias = resultSet.getString("alias"); - if (alias != null) { - plot.getSettings().setAlias(alias); - } - String pos = resultSet.getString("position"); - switch (pos.toLowerCase()) { - case "": - case "default": - case "0,0,0": - case "center": - break; - default: - try { - plot.getSettings().setPosition(BlockLoc.fromString(pos)); - } catch (Exception ignored) { - } - } - Integer m = resultSet.getInt("merged"); - boolean[] merged = new boolean[4]; - for (int i = 0; i < 4; i++) { - merged[3 - i] = (m & 1 << i) != 0; - } - plot.getSettings().setMerged(merged); - String[] flags_string; - String myflags = resultSet.getString("flags"); - if (myflags == null || myflags.isEmpty()) { - flags_string = new String[] {}; - } else { - flags_string = myflags.split(","); - } - HashMap, Object> flags = new HashMap<>(); - boolean exception = false; - for (String element : flags_string) { - if (element.contains(":")) { - String[] split = element.split(":"); - try { - String flag_str = - split[1].replaceAll("¯", ":").replaceAll("\u00B4", ","); - Flag flag = FlagManager.getOrCreateFlag(split[0]); - flags.put(flag, flag.parseValue(flag_str)); - } catch (Exception e) { - e.printStackTrace(); - exception = true; - } - } else { - element = - element.replaceAll("\u00AF", ":").replaceAll("\u00B4", ","); - if (StringMan - .isAlpha(element.replaceAll("_", "").replaceAll("-", ""))) { - Flag flag = FlagManager.getOrCreateFlag(element); - if (flag == null) { - flag = new StringFlag(element) { - @Override public String getValueDescription() { - return "Generic Filler Flag"; - } - }; - } - flags.put(flag, flag.parseValue("")); - } else { - PlotSquared.debug("INVALID FLAG: " + element); - } - } - } - if (exception) { - PlotSquared.debug("&cPlot #" + id + "(" + plot + ") | " + plot - + " had an invalid flag. A fix has been attempted."); - PlotSquared.debug("&c" + myflags); - this.setFlags(plot, flags); - } - plot.getSettings().flags = flags; - } else if (Settings.Enabled_Components.DATABASE_PURGER) { - toDelete.add(id); - } else { - PlotSquared.debug("&cENTRY #" + id + "(" + plot - + ") in `plot_settings` does not exist. Create this plot or set `database-purger: true` in the settings" - + ".yml."); - } - } - deleteRows(toDelete, this.prefix + "plot_settings", "plot_plot_id"); - } - } - if (!plots.entrySet().isEmpty()) { - createEmptySettings(new ArrayList<>(plots.keySet()), null); - for (Entry entry : plots.entrySet()) { - entry.getValue().getSettings(); - } - } - boolean invalidPlot = false; - for (Entry entry : noExist.entrySet()) { - String worldName = entry.getKey(); - invalidPlot = true; - PlotSquared.debug("&c[WARNING] Found " + entry.getValue().intValue() - + " plots in DB for non existent world; '" + worldName + "'."); - } - if (invalidPlot) { - PlotSquared.debug( - "&c[WARNING] - Please create the world/s or remove the plots using the purge command"); - } - } catch (SQLException e) { - PlotSquared.debug("&7[WARN] Failed to load plots."); - e.printStackTrace(); - } - return newPlots; - } - - @Override public void setMerged(final Plot plot, final boolean[] merged) { - plot.getSettings().setMerged(merged); - addPlotTask(plot, new UniqueStatement("setMerged") { - @Override public void set(PreparedStatement stmt) throws SQLException { - int hash = MainUtil.hash(merged); - stmt.setInt(1, hash); - stmt.setInt(2, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "plot_settings` SET `merged` = ? WHERE `plot_plot_id` = ?"); - } - }); - } - - @Override public void swapPlots(Plot plot1, Plot plot2) { - final int id1 = getId(plot1); - final int id2 = getId(plot2); - final PlotId pos1 = plot1.getId(); - final PlotId pos2 = plot2.getId(); - addPlotTask(plot1, new UniqueStatement("swapPlots") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, pos2.x); - stmt.setInt(2, pos2.y); - stmt.setInt(3, id1); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "plot` SET `plot_id_x` = ?, `plot_id_z` = ? WHERE `id` = ?"); - } - }); - addPlotTask(plot2, new UniqueStatement("swapPlots") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, pos1.x); - stmt.setInt(2, pos1.y); - stmt.setInt(3, id2); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "plot` SET `plot_id_x` = ?, `plot_id_z` = ? WHERE `id` = ?"); - } - }); - } - - @Override public void movePlot(final Plot original, final Plot newPlot) { - addPlotTask(original, new UniqueStatement("movePlot") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, newPlot.getId().x); - stmt.setInt(2, newPlot.getId().y); - stmt.setString(3, newPlot.getArea().toString()); - stmt.setInt(4, getId(original)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "plot` SET `plot_id_x` = ?, `plot_id_z` = ?, `world` = ? WHERE `id` = ?"); - } - }); - addPlotTask(newPlot, null); - } - - @Override public void setFlags(final Plot plot, HashMap, Object> flags) { - final String flag_string = FlagManager.toString(flags); - addPlotTask(plot, new UniqueStatement("setFlags") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setString(1, flag_string); - stmt.setInt(2, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "plot_settings` SET `flags` = ? WHERE `plot_plot_id` = ?"); - } - }); - } - - @Override public void setAlias(final Plot plot, final String alias) { - addPlotTask(plot, new UniqueStatement("setAlias") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setString(1, alias); - stmt.setInt(2, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "plot_settings` SET `alias` = ? WHERE `plot_plot_id` = ?"); - } - }); - } - - /** - * Purge all plots with the following database IDs - */ - @Override public void purgeIds(final Set uniqueIds) { - addGlobalTask(new Runnable() { - @Override public void run() { - if (!uniqueIds.isEmpty()) { - try { - ArrayList uniqueIdsList = new ArrayList(uniqueIds); - String stmt_prefix = ""; - int size = uniqueIdsList.size(); - int packet = 990; - int amount = size / packet; - int count = 0; - int last = -1; - for (int j = 0; j <= amount; j++) { - PlotSquared.debug("Purging " + (j * packet) + " / " + size); - List subList = - uniqueIdsList.subList(j * packet, Math.min(size, (j + 1) * packet)); - if (subList.isEmpty()) { - break; - } - StringBuilder idstr2 = new StringBuilder(""); - stmt_prefix = ""; - for (Integer id : subList) { - idstr2.append(stmt_prefix).append(id); - stmt_prefix = " OR `id` = "; - } - stmt_prefix = ""; - StringBuilder idstr = new StringBuilder(); - for (Integer id : subList) { - idstr.append(stmt_prefix).append(id); - stmt_prefix = " OR `plot_plot_id` = "; - } - PreparedStatement stmt = SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_helpers` WHERE `plot_plot_id` = " + idstr); - stmt.executeUpdate(); - stmt.close(); - stmt = SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_denied` WHERE `plot_plot_id` = " + idstr); - stmt.executeUpdate(); - stmt.close(); - stmt = SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_settings` WHERE `plot_plot_id` = " + idstr); - stmt.executeUpdate(); - stmt.close(); - stmt = SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_trusted` WHERE `plot_plot_id` = " + idstr); - stmt.executeUpdate(); - stmt.close(); - stmt = SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix + "plot` WHERE `id` = " - + idstr2); - stmt.executeUpdate(); - stmt.close(); - commit(); - } - } catch (SQLException e) { - e.printStackTrace(); - PlotSquared.debug("&c[ERROR] FAILED TO PURGE PLOTS!"); - return; - } - } - PlotSquared.debug("&6[INFO] SUCCESSFULLY PURGED " + uniqueIds.size() + " PLOTS!"); - } - }); - } - - @Override public void purge(final PlotArea area, final Set plots) { - addGlobalTask(new Runnable() { - @Override public void run() { - try (PreparedStatement stmt = SQLManager.this.connection.prepareStatement( - "SELECT `id`, `plot_id_x`, `plot_id_z` FROM `" + SQLManager.this.prefix - + "plot` WHERE `world` = ?")) { - stmt.setString(1, area.toString()); - Set ids; - try (ResultSet r = stmt.executeQuery()) { - ids = new HashSet<>(); - while (r.next()) { - PlotId plot_id = - new PlotId(r.getInt("plot_id_x"), r.getInt("plot_id_z")); - if (plots.contains(plot_id)) { - ids.add(r.getInt("id")); - } - } - } - purgeIds(ids); - } catch (SQLException e) { - e.printStackTrace(); - PlotSquared.debug("&c[ERROR] FAILED TO PURGE AREA '" + area + "'!"); - } - for (Iterator iterator = plots.iterator(); iterator.hasNext(); ) { - PlotId plotId = iterator.next(); - iterator.remove(); - PlotId id = new PlotId(plotId.x, plotId.y); - area.removePlot(id); - } - } - }); - } - - @Override public void setPosition(final Plot plot, final String position) { - addPlotTask(plot, new UniqueStatement("setPosition") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setString(1, position == null ? "" : position); - stmt.setInt(2, getId(plot)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "plot_settings` SET `position` = ? WHERE `plot_plot_id` = ?"); - } - }); - } - - @Override public void removeComment(final Plot plot, final PlotComment comment) { - addPlotTask(plot, new UniqueStatement("removeComment") { - @Override public void set(PreparedStatement statement) throws SQLException { - if (plot != null) { - statement.setString(1, plot.getArea().toString()); - statement.setInt(2, plot.getId().hashCode()); - statement.setString(3, comment.comment); - statement.setString(4, comment.inbox); - statement.setString(5, comment.senderName); - } else { - statement.setString(1, comment.comment); - statement.setString(2, comment.inbox); - statement.setString(3, comment.senderName); - } - } - - @Override public PreparedStatement get() throws SQLException { - if (plot != null) { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_comments` WHERE `world` = ? AND `hashcode` = ? AND `comment` = ? AND `inbox` = ? AND `sender` = ?"); - } - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_comments` WHERE `comment` = ? AND `inbox` = ? AND `sender` = ?"); - } - }); - } - - @Override public void clearInbox(final Plot plot, final String inbox) { - addPlotTask(plot, new UniqueStatement("clearInbox") { - @Override public void set(PreparedStatement statement) throws SQLException { - if (plot != null) { - statement.setString(1, plot.getArea().toString()); - statement.setInt(2, plot.getId().hashCode()); - statement.setString(3, inbox); - } else { - statement.setString(1, inbox); - } - } - - @Override public PreparedStatement get() throws SQLException { - if (plot != null) { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_comments` WHERE `world` = ? AND `hashcode` = ? AND `inbox` = ?"); - } - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix + "plot_comments` `inbox` = ?"); - } - }); - } - - @Override public void getComments(final Plot plot, final String inbox, - final RunnableVal> whenDone) { - addPlotTask(plot, new UniqueStatement("getComments_" + plot) { - @Override public void set(PreparedStatement statement) throws SQLException { - if (plot != null) { - statement.setString(1, plot.getArea().toString()); - statement.setInt(2, plot.getId().hashCode()); - statement.setString(3, inbox); - } else { - statement.setString(1, inbox); - } - } - - @Override public PreparedStatement get() throws SQLException { - if (plot != null) { - return SQLManager.this.connection.prepareStatement( - "SELECT * FROM `" + SQLManager.this.prefix - + "plot_comments` WHERE `world` = ? AND `hashcode` = ? AND `inbox` = ?"); - } - return SQLManager.this.connection.prepareStatement( - "SELECT * FROM `" + SQLManager.this.prefix - + "plot_comments` WHERE `inbox` = ?"); - } - - @Override public void execute(PreparedStatement statement) { - } - - @Override public void addBatch(PreparedStatement statement) throws SQLException { - ArrayList comments = new ArrayList<>(); - try (ResultSet set = statement.executeQuery()) { - while (set.next()) { - String sender = set.getString("sender"); - String world = set.getString("world"); - int hash = set.getInt("hashcode"); - PlotId id; - if (hash != 0) { - id = PlotId.unpair(hash); - } else { - id = null; - } - String msg = set.getString("comment"); - long timestamp = set.getInt("timestamp") * 1000; - PlotComment comment = - new PlotComment(world, id, msg, sender, inbox, timestamp); - comments.add(comment); - whenDone.value = comments; - } - } - TaskManager.runTask(whenDone); - } - }); - } - - @Override public void setComment(final Plot plot, final PlotComment comment) { - addPlotTask(plot, new UniqueStatement("setComment") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setString(1, plot.getArea().toString()); - statement.setInt(2, plot.getId().hashCode()); - statement.setString(3, comment.comment); - statement.setString(4, comment.inbox); - statement.setInt(5, (int) (comment.timestamp / 1000)); - statement.setString(6, comment.senderName); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "plot_comments` (`world`, `hashcode`, `comment`, `inbox`, `timestamp`, `sender`) VALUES(?,?,?,?,?,?)"); - } - }); - } - - @Override public void removeTrusted(final Plot plot, final UUID uuid) { - addPlotTask(plot, new UniqueStatement("removeTrusted") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getId(plot)); - statement.setString(2, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_helpers` WHERE `plot_plot_id` = ? AND `user_uuid` = ?"); - } - }); - } - - @Override public void removeMember(final Plot plot, final UUID uuid) { - addPlotTask(plot, new UniqueStatement("removeMember") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getId(plot)); - statement.setString(2, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_trusted` WHERE `plot_plot_id` = ? AND `user_uuid` = ?"); - } - }); - } - - @Override public void setTrusted(final Plot plot, final UUID uuid) { - addPlotTask(plot, new UniqueStatement("setTrusted") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getId(plot)); - statement.setString(2, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "plot_helpers` (`plot_plot_id`, `user_uuid`) VALUES(?,?)"); - } - }); - } - - @Override public void setMember(final Plot plot, final UUID uuid) { - addPlotTask(plot, new UniqueStatement("setMember") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getId(plot)); - statement.setString(2, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "plot_trusted` (`plot_plot_id`, `user_uuid`) VALUES(?,?)"); - } - }); - } - - @Override public void removeDenied(final Plot plot, final UUID uuid) { - addPlotTask(plot, new UniqueStatement("removeDenied") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getId(plot)); - statement.setString(2, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "plot_denied` WHERE `plot_plot_id` = ? AND `user_uuid` = ?"); - } - }); - } - - @Override public void setDenied(final Plot plot, final UUID uuid) { - addPlotTask(plot, new UniqueStatement("setDenied") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getId(plot)); - statement.setString(2, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "plot_denied` (`plot_plot_id`, `user_uuid`) VALUES(?,?)"); - } - }); - } - - @Override public HashMap getRatings(Plot plot) { - HashMap map = new HashMap<>(); - try (PreparedStatement statement = this.connection.prepareStatement( - "SELECT `rating`, `player` FROM `" + this.prefix - + "plot_rating` WHERE `plot_plot_id` = ? ")) { - statement.setInt(1, getId(plot)); - try (ResultSet resultSet = statement.executeQuery()) { - while (resultSet.next()) { - UUID uuid = UUID.fromString(resultSet.getString("player")); - int rating = resultSet.getInt("rating"); - map.put(uuid, rating); - } - } - } catch (SQLException e) { - PlotSquared - .debug("&7[WARN] Failed to fetch rating for plot " + plot.getId().toString()); - e.printStackTrace(); - } - return map; - } - - @Override public void setRating(final Plot plot, final UUID rater, final int value) { - addPlotTask(plot, new UniqueStatement("setRating") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getId(plot)); - statement.setInt(2, value); - statement.setString(3, rater.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "plot_rating` (`plot_plot_id`, `rating`, `player`) VALUES(?,?,?)"); - } - }); - } - - @Override public void delete(PlotCluster cluster) { - final int id = getClusterId(cluster); - addClusterTask(cluster, new UniqueStatement("delete_cluster_settings") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, id); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "cluster_settings` WHERE `cluster_id` = ?"); - } - }); - addClusterTask(cluster, new UniqueStatement("delete_cluster_helpers") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, id); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "cluster_helpers` WHERE `cluster_id` = ?"); - } - }); - addClusterTask(cluster, new UniqueStatement("delete_cluster_invited") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, id); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "cluster_invited` WHERE `cluster_id` = ?"); - } - }); - addClusterTask(cluster, new UniqueStatement("delete_cluster") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, id); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix + "cluster` WHERE `id` = ?"); - } - }); - } - - @Override public void addPersistentMeta(final UUID uuid, final String key, final byte[] meta, - final boolean replace) { - addPlayerTask(uuid, new UniqueStatement("addPersistentMeta") { - @Override public void set(PreparedStatement stmt) throws SQLException { - if (replace) { - stmt.setBytes(1, meta); - stmt.setString(2, uuid.toString()); - stmt.setString(3, key); - } else { - stmt.setString(1, uuid.toString()); - stmt.setString(2, key); - stmt.setBytes(3, meta); - } - } - - @Override public PreparedStatement get() throws SQLException { - if (replace) { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "player_meta` SET `value` = ? WHERE `uuid` = ? AND `key` = ?"); - } else { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "player_meta`(`uuid`, `key`, `value`) VALUES(?, ? ,?)"); - } - } - }); - } - - @Override public void removePersistentMeta(final UUID uuid, final String key) { - addPlayerTask(uuid, new UniqueStatement("removePersistentMeta") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setString(1, uuid.toString()); - stmt.setString(2, key); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "player_meta` WHERE `uuid` = ? AND `key` = ?"); - } - }); - } - - @Override - public void getPersistentMeta(final UUID uuid, final RunnableVal> result) { - addPlayerTask(uuid, new UniqueStatement("getPersistentMeta") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setString(1, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "SELECT * FROM `" + SQLManager.this.prefix - + "player_meta` WHERE `uuid` = ? ORDER BY `meta_id` ASC"); - } - - @Override public void execute(PreparedStatement statement) { - } - - @Override public void addBatch(PreparedStatement statement) throws SQLException { - ResultSet resultSet = statement.executeQuery(); - - final Map metaMap = new HashMap<>(); - - while (resultSet.next()) { - String key = resultSet.getString("key"); - byte[] bytes = resultSet.getBytes("value"); - metaMap.put(key, bytes); - } - - resultSet.close(); - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - result.run(metaMap); - } - }); - } - - }); - } - - @Override public HashMap> getClusters() { - LinkedHashMap> newClusters = new LinkedHashMap<>(); - HashMap clusters = new HashMap<>(); - try { - HashSet areas = new HashSet<>(); - if (PlotSquared.get().worlds.contains("worlds")) { - ConfigurationSection worldSection = - PlotSquared.get().worlds.getConfigurationSection("worlds"); - if (worldSection != null) { - for (String worldKey : worldSection.getKeys(false)) { - areas.add(worldKey); - ConfigurationSection areaSection = - worldSection.getConfigurationSection(worldKey + ".areas"); - if (areaSection != null) { - for (String areaKey : areaSection.getKeys(false)) { - String[] split = areaKey.split("(? uuids = new HashMap<>(); - HashMap noExist = new HashMap<>(); - /* - * Getting clusters - */ - try (Statement stmt = this.connection.createStatement()) { - ResultSet resultSet = - stmt.executeQuery("SELECT * FROM `" + this.prefix + "cluster`"); - PlotCluster cluster; - String owner; - UUID user; - int id; - while (resultSet.next()) { - PlotId pos1 = - new PlotId(resultSet.getInt("pos1_x"), resultSet.getInt("pos1_z")); - PlotId pos2 = - new PlotId(resultSet.getInt("pos2_x"), resultSet.getInt("pos2_z")); - id = resultSet.getInt("id"); - String areaid = resultSet.getString("world"); - if (!areas.contains(areaid)) { - if (noExist.containsKey(areaid)) { - noExist.put(areaid, noExist.get(areaid) + 1); - } else { - noExist.put(areaid, 1); - } - } - owner = resultSet.getString("owner"); - user = uuids.get(owner); - if (user == null) { - user = UUID.fromString(owner); - uuids.put(owner, user); - } - cluster = new PlotCluster(null, pos1, pos2, user, id); - clusters.put(id, cluster); - Set set = newClusters.get(areaid); - if (set == null) { - set = new HashSet<>(); - newClusters.put(areaid, set); - } - set.add(cluster); - } - //Getting helpers - resultSet = stmt.executeQuery( - "SELECT `user_uuid`, `cluster_id` FROM `" + this.prefix + "cluster_helpers`"); - while (resultSet.next()) { - id = resultSet.getInt("cluster_id"); - owner = resultSet.getString("user_uuid"); - user = uuids.get(owner); - if (user == null) { - user = UUID.fromString(owner); - uuids.put(owner, user); - } - cluster = clusters.get(id); - if (cluster != null) { - cluster.helpers.add(user); - } else { - PlotSquared.debug("&cCluster #" + id + "(" + cluster - + ") in cluster_helpers does not exist. Please create the cluster or remove this entry."); - } - } - // Getting invited - resultSet = stmt.executeQuery( - "SELECT `user_uuid`, `cluster_id` FROM `" + this.prefix + "cluster_invited`"); - while (resultSet.next()) { - id = resultSet.getInt("cluster_id"); - owner = resultSet.getString("user_uuid"); - user = uuids.get(owner); - if (user == null) { - user = UUID.fromString(owner); - uuids.put(owner, user); - } - cluster = clusters.get(id); - if (cluster != null) { - cluster.invited.add(user); - } else { - PlotSquared.debug("&cCluster #" + id + "(" + cluster - + ") in cluster_invited does not exist. Please create the cluster or remove this entry."); - } - } - resultSet = - stmt.executeQuery("SELECT * FROM `" + this.prefix + "cluster_settings`"); - while (resultSet.next()) { - id = resultSet.getInt("cluster_id"); - cluster = clusters.get(id); - if (cluster != null) { - String alias = resultSet.getString("alias"); - if (alias != null) { - cluster.settings.setAlias(alias); - } - String pos = resultSet.getString("position"); - switch (pos.toLowerCase()) { - case "": - case "default": - case "0,0,0": - case "center": - break; - default: - try { - BlockLoc loc = BlockLoc.fromString(pos); - cluster.settings.setPosition(loc); - } catch (Exception ignored) { - } - } - Integer m = resultSet.getInt("merged"); - boolean[] merged = new boolean[4]; - for (int i = 0; i < 4; i++) { - merged[3 - i] = (m & 1 << i) != 0; - } - cluster.settings.setMerged(merged); - String[] flags_string; - String myflags = resultSet.getString("flags"); - if (myflags == null || myflags.isEmpty()) { - flags_string = new String[] {}; - } else { - flags_string = myflags.split(","); - } - HashMap, Object> flags = new HashMap<>(); - for (String element : flags_string) { - if (element.contains(":")) { - String[] split = element.split(":"); - String flag_str = - split[1].replaceAll("\u00AF", ":").replaceAll("´", ","); - Flag flag = FlagManager.getOrCreateFlag(split[0]); - if (flag == null) { - flag = new StringFlag(split[0]) { - @Override public String getValueDescription() { - return "Generic Filler Flag"; - } - }; - } - flags.put(flag, flag.parseValue(flag_str)); - } else { - Flag flag = FlagManager.getOrCreateFlag(element); - if (flag == null) { - flag = new StringFlag(element) { - @Override public String getValueDescription() { - return "Generic Filler Flag"; - } - }; - } - flags.put(flag, flag.parseValue("")); - } - } - cluster.settings.flags = flags; - } else { - PlotSquared.debug("&cCluster #" + id + "(" + cluster - + ") in cluster_settings does not exist. Please create the cluster or remove this entry."); - } - } - resultSet.close(); - } - boolean invalidPlot = false; - for (Entry entry : noExist.entrySet()) { - String a = entry.getKey(); - invalidPlot = true; - PlotSquared.debug("&c[WARNING] Found " + noExist.get(a) - + " clusters in DB for non existent area; '" + a + "'."); - } - if (invalidPlot) { - PlotSquared.debug( - "&c[WARNING] - Please create the world/s or remove the clusters using the purge command"); - } - } catch (SQLException e) { - PlotSquared.debug("&7[WARN] Failed to load clusters."); - e.printStackTrace(); - } - return newClusters; - } - - @Override public void setFlags(final PlotCluster cluster, HashMap, Object> flags) { - final StringBuilder flag_string = new StringBuilder(); - int i = 0; - for (Entry, Object> flag : flags.entrySet()) { - if (i != 0) { - flag_string.append(','); - } - flag_string.append(flag.getKey().getName()).append(':').append( - flag.getKey().valueToString(flag.getValue()).replaceAll(":", "\u00AF") - .replaceAll(",", "´")); - i++; - } - addClusterTask(cluster, new UniqueStatement("setFlags") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setString(1, flag_string.toString()); - stmt.setInt(2, getClusterId(cluster)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "cluster_settings` SET `flags` = ? WHERE `cluster_id` = ?"); - } - }); - } - - @Override public void setClusterName(final PlotCluster cluster, final String name) { - addClusterTask(cluster, new UniqueStatement("setClusterName") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setString(1, name); - stmt.setInt(2, getClusterId(cluster)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "cluster_settings` SET `alias` = ? WHERE `cluster_id` = ?"); - } - }); - cluster.settings.setAlias(name); - } - - @Override public void removeHelper(final PlotCluster cluster, final UUID uuid) { - addClusterTask(cluster, new UniqueStatement("removeHelper") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getClusterId(cluster)); - statement.setString(2, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "cluster_helpers` WHERE `cluster_id` = ? AND `user_uuid` = ?"); - } - }); - } - - @Override public void setHelper(final PlotCluster cluster, final UUID uuid) { - addClusterTask(cluster, new UniqueStatement("setHelper") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getClusterId(cluster)); - statement.setString(2, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "cluster_helpers` (`cluster_id`, `user_uuid`) VALUES(?,?)"); - } - }); - } - - @Override public void createCluster(final PlotCluster cluster) { - addClusterTask(cluster, new UniqueStatement("createCluster_" + cluster.hashCode()) { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, cluster.getP1().x); - stmt.setInt(2, cluster.getP1().y); - stmt.setInt(3, cluster.getP2().x); - stmt.setInt(4, cluster.getP2().y); - stmt.setString(5, cluster.owner.toString()); - stmt.setString(6, cluster.area.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement(SQLManager.this.CREATE_CLUSTER, - Statement.RETURN_GENERATED_KEYS); - } - - @Override public void execute(PreparedStatement statement) { - } - - @Override public void addBatch(PreparedStatement statement) throws SQLException { - statement.executeUpdate(); - try (ResultSet keys = statement.getGeneratedKeys()) { - if (keys.next()) { - cluster.temp = keys.getInt(1); - } - } - } - }); - addClusterTask(cluster, - new UniqueStatement("createCluster_settings_" + cluster.hashCode()) { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, getClusterId(cluster)); - stmt.setString(2, cluster.settings.getAlias()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "cluster_settings`(`cluster_id`, `alias`) VALUES(?, ?)"); - } - }); - } - - @Override public void resizeCluster(final PlotCluster current, PlotId min, PlotId max) { - final PlotId pos1 = new PlotId(current.getP1().x, current.getP1().y); - final PlotId pos2 = new PlotId(current.getP2().x, current.getP2().y); - current.setP1(min); - current.setP2(max); - - addClusterTask(current, new UniqueStatement("resizeCluster") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setInt(1, pos1.x); - stmt.setInt(2, pos1.y); - stmt.setInt(3, pos2.x); - stmt.setInt(4, pos2.y); - stmt.setInt(5, getClusterId(current)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "cluster` SET `pos1_x` = ?, `pos1_z` = ?, `pos2_x` = ?, `pos2_z` = ? WHERE `id` = ?"); - } - }); - } - - @Override public void setPosition(final PlotCluster cluster, final String position) { - addClusterTask(cluster, new UniqueStatement("setPosition") { - @Override public void set(PreparedStatement stmt) throws SQLException { - stmt.setString(1, position); - stmt.setInt(2, getClusterId(cluster)); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "cluster_settings` SET `position` = ? WHERE `cluster_id` = ?"); - } - }); - } - - @Override public void removeInvited(final PlotCluster cluster, final UUID uuid) { - addClusterTask(cluster, new UniqueStatement("removeInvited") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getClusterId(cluster)); - statement.setString(2, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "DELETE FROM `" + SQLManager.this.prefix - + "cluster_invited` WHERE `cluster_id` = ? AND `user_uuid` = ?"); - } - }); - } - - @Override public void setInvited(final PlotCluster cluster, final UUID uuid) { - addClusterTask(cluster, new UniqueStatement("setInvited") { - @Override public void set(PreparedStatement statement) throws SQLException { - statement.setInt(1, getClusterId(cluster)); - statement.setString(2, uuid.toString()); - } - - @Override public PreparedStatement get() throws SQLException { - return SQLManager.this.connection.prepareStatement( - "INSERT INTO `" + SQLManager.this.prefix - + "cluster_invited` (`cluster_id`, `user_uuid`) VALUES(?,?)"); - } - }); - } - - @Override public boolean deleteTables() { - try (Statement stmt = this.connection.createStatement(); - PreparedStatement statement = this.connection - .prepareStatement("DROP TABLE `" + this.prefix + "plot`")) { - close(); - this.closed = false; - SQLManager.this.connection = this.database.forceConnection(); - stmt.addBatch("DROP TABLE `" + this.prefix + "cluster_invited`"); - stmt.addBatch("DROP TABLE `" + this.prefix + "cluster_helpers`"); - stmt.addBatch("DROP TABLE `" + this.prefix + "cluster`"); - stmt.addBatch("DROP TABLE `" + this.prefix + "plot_rating`"); - stmt.addBatch("DROP TABLE `" + this.prefix + "plot_settings`"); - stmt.addBatch("DROP TABLE `" + this.prefix + "plot_comments`"); - stmt.addBatch("DROP TABLE `" + this.prefix + "plot_trusted`"); - stmt.addBatch("DROP TABLE `" + this.prefix + "plot_helpers`"); - stmt.addBatch("DROP TABLE `" + this.prefix + "plot_denied`"); - stmt.executeBatch(); - stmt.clearBatch(); - statement.executeUpdate(); - } catch (ClassNotFoundException | SQLException e) { - e.printStackTrace(); - - } + commit(); return true; - } - - @Override public void validateAllPlots(Set toValidate) { - if (!isValid()) { - reconnect(); + } + int count = -1; + if (!this.plotTasks.isEmpty()) { + count = 0; + if (this.connection.getAutoCommit()) { + this.connection.setAutoCommit(false); } - PlotSquared.debug( - "$1All DB transactions during this session are being validated (This may take a while if corrections need to be made)"); - commit(); - while (true) { - if (!sendBatch()) { - break; + String method = null; + PreparedStatement statement = null; + UniqueStatement task = null; + UniqueStatement lastTask = null; + Iterator>> iter = + this.plotTasks.entrySet().iterator(); + while (iter.hasNext()) { + try { + Entry> entry = iter.next(); + Plot plot = entry.getKey(); + Queue tasks = entry.getValue(); + if (tasks.isEmpty()) { + iter.remove(); + continue; } - } - try { - if (this.connection.getAutoCommit()) { - this.connection.setAutoCommit(false); + task = tasks.remove(); + count++; + if (task != null) { + if (task.method == null || !task.method.equals(method) || statement == null) { + if (statement != null) { + lastTask.execute(statement); + statement.close(); + } + method = task.method; + statement = task.get(); + } + task.set(statement); + task.addBatch(statement); + try { + if (statement.isClosed()) { + statement = null; + } + } catch (AbstractMethodError ignore) { + } } - } catch (SQLException e) { + lastTask = task; + } catch (Throwable e) { + PlotSquared.debug("============ DATABASE ERROR ============"); + PlotSquared.debug("There was an error updating the database."); + PlotSquared.debug(" - It will be corrected on shutdown"); + PlotSquared.debug("========================================"); e.printStackTrace(); + PlotSquared.debug("========================================"); + } } - HashMap> database = getPlots(); - ArrayList toCreate = new ArrayList<>(); - for (Plot plot : toValidate) { - if (plot.temp == -1) { - continue; - } - HashMap worldPlots = database.get(plot.getArea().toString()); - if (worldPlots == null) { - PlotSquared.debug("&8 - &7Creating plot (1): " + plot); - toCreate.add(plot); - continue; - } - Plot dataPlot = worldPlots.remove(plot.getId()); - if (dataPlot == null) { - PlotSquared.debug("&8 - &7Creating plot (2): " + plot); - toCreate.add(plot); - continue; - } - // owner - if (!plot.owner.equals(dataPlot.owner)) { - PlotSquared - .debug("&8 - &7Setting owner: " + plot + " -> " + MainUtil.getName(plot.owner)); - setOwner(plot, plot.owner); - } - // trusted - if (!plot.getTrusted().equals(dataPlot.getTrusted())) { - HashSet toAdd = (HashSet) plot.getTrusted().clone(); - HashSet toRemove = (HashSet) dataPlot.getTrusted().clone(); - toRemove.removeAll(plot.getTrusted()); - toAdd.removeAll(dataPlot.getTrusted()); - PlotSquared.debug( - "&8 - &7Correcting " + (toAdd.size() + toRemove.size()) + " trusted for: " - + plot); - if (!toRemove.isEmpty()) { - for (UUID uuid : toRemove) { - removeTrusted(plot, uuid); - } - } - if (!toAdd.isEmpty()) { - for (UUID uuid : toAdd) { - setTrusted(plot, uuid); - } - } - } - if (!plot.getMembers().equals(dataPlot.getMembers())) { - HashSet toAdd = (HashSet) plot.getMembers().clone(); - HashSet toRemove = (HashSet) dataPlot.getMembers().clone(); - toRemove.removeAll(plot.getMembers()); - toAdd.removeAll(dataPlot.getMembers()); - PlotSquared.debug( - "&8 - &7Correcting " + (toAdd.size() + toRemove.size()) + " members for: " - + plot); - if (!toRemove.isEmpty()) { - for (UUID uuid : toRemove) { - removeMember(plot, uuid); - } - } - if (!toAdd.isEmpty()) { - for (UUID uuid : toAdd) { - setMember(plot, uuid); - } - } - } - if (!plot.getDenied().equals(dataPlot.getDenied())) { - HashSet toAdd = (HashSet) plot.getDenied().clone(); - HashSet toRemove = (HashSet) dataPlot.getDenied().clone(); - toRemove.removeAll(plot.getDenied()); - toAdd.removeAll(dataPlot.getDenied()); - PlotSquared.debug( - "&8 - &7Correcting " + (toAdd.size() + toRemove.size()) + " denied for: " - + plot); - if (!toRemove.isEmpty()) { - for (UUID uuid : toRemove) { - removeDenied(plot, uuid); - } - } - if (!toAdd.isEmpty()) { - for (UUID uuid : toAdd) { - setDenied(plot, uuid); - } - } - } - boolean[] pm = plot.getMerged(); - boolean[] dm = dataPlot.getMerged(); - if (pm[0] != dm[0] || pm[1] != dm[1]) { - PlotSquared.debug("&8 - &7Correcting merge for: " + plot); - setMerged(dataPlot, plot.getMerged()); - } - HashMap, Object> pf = plot.getFlags(); - HashMap, Object> df = dataPlot.getFlags(); - if (!pf.isEmpty() && !df.isEmpty()) { - if (pf.size() != df.size() || !StringMan - .isEqual(StringMan.joinOrdered(pf.values(), ","), - StringMan.joinOrdered(df.values(), ","))) { - PlotSquared.debug("&8 - &7Correcting flags for: " + plot); - setFlags(plot, pf); - } - } + if (statement != null && task != null) { + task.execute(statement); + statement.close(); } - - for (Entry> entry : database.entrySet()) { - HashMap map = entry.getValue(); - if (!map.isEmpty()) { - for (Entry entry2 : map.entrySet()) { - PlotSquared.debug("$1Plot was deleted: " + entry2.getValue().toString() - + "// TODO implement this when sure safe"); - } - } + } + if (!this.playerTasks.isEmpty()) { + count = 0; + if (this.connection.getAutoCommit()) { + this.connection.setAutoCommit(false); } - commit(); - } - - @Override - public void replaceWorld(final String oldWorld, final String newWorld, final PlotId min, - final PlotId max) { - addGlobalTask(new Runnable() { - @Override public void run() { - if (min == null) { - try (PreparedStatement stmt = SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "plot` SET `world` = ? WHERE `world` = ?")) { - stmt.setString(1, newWorld); - stmt.setString(2, oldWorld); - stmt.executeUpdate(); - } catch (SQLException e) { - e.printStackTrace(); - } - try (PreparedStatement stmt = SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "cluster` SET `world` = ? WHERE `world` = ?")) { - stmt.setString(1, newWorld); - stmt.setString(2, oldWorld); - stmt.executeUpdate(); - } catch (SQLException e) { - e.printStackTrace(); - } - } else { - try (PreparedStatement stmt = SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "plot` SET `world` = ? WHERE `world` = ? AND `plot_id_x` BETWEEN ? AND ? AND `plot_id_z` BETWEEN ? AND ?")) { - stmt.setString(1, newWorld); - stmt.setString(2, oldWorld); - stmt.setInt(3, min.x); - stmt.setInt(4, max.x); - stmt.setInt(5, min.y); - stmt.setInt(6, max.y); - stmt.executeUpdate(); - } catch (SQLException e) { - e.printStackTrace(); - } - try (PreparedStatement stmt = SQLManager.this.connection.prepareStatement( - "UPDATE `" + SQLManager.this.prefix - + "cluster` SET `world` = ? WHERE `world` = ? AND `pos1_x` <= ? AND `pos1_z` <= ? AND `pos2_x` >= ? AND `pos2_z` >= ?")) { - stmt.setString(1, newWorld); - stmt.setString(2, oldWorld); - stmt.setInt(3, max.x); - stmt.setInt(4, max.y); - stmt.setInt(5, min.x); - stmt.setInt(6, min.y); - stmt.executeUpdate(); - } catch (SQLException e) { - e.printStackTrace(); - } - } + String method = null; + PreparedStatement statement = null; + UniqueStatement task = null; + UniqueStatement lastTask = null; + for (Entry> entry : this.playerTasks.entrySet()) { + try { + UUID uuid = entry.getKey(); + if (this.playerTasks.get(uuid).isEmpty()) { + this.playerTasks.remove(uuid); + continue; } - }); - } - - @Override public void replaceUUID(final UUID old, final UUID now) { - addGlobalTask(new Runnable() { - @Override public void run() { - try (Statement stmt = SQLManager.this.connection.createStatement()) { - stmt.executeUpdate( - "UPDATE `" + SQLManager.this.prefix + "cluster` SET `owner` = '" + now - .toString() + "' WHERE `owner` = '" + old.toString() + '\''); - stmt.executeUpdate( - "UPDATE `" + SQLManager.this.prefix + "cluster_helpers` SET `user_uuid` = '" - + now.toString() + "' WHERE `user_uuid` = '" + old.toString() + '\''); - stmt.executeUpdate( - "UPDATE `" + SQLManager.this.prefix + "cluster_invited` SET `user_uuid` = '" - + now.toString() + "' WHERE `user_uuid` = '" + old.toString() + '\''); - stmt.executeUpdate( - "UPDATE `" + SQLManager.this.prefix + "plot` SET `owner` = '" + now - .toString() + "' WHERE `owner` = '" + old.toString() + '\''); - stmt.executeUpdate( - "UPDATE `" + SQLManager.this.prefix + "plot_denied` SET `user_uuid` = '" - + now.toString() + "' WHERE `user_uuid` = '" + old.toString() + '\''); - stmt.executeUpdate( - "UPDATE `" + SQLManager.this.prefix + "plot_helpers` SET `user_uuid` = '" - + now.toString() + "' WHERE `user_uuid` = '" + old.toString() + '\''); - stmt.executeUpdate( - "UPDATE `" + SQLManager.this.prefix + "plot_trusted` SET `user_uuid` = '" - + now.toString() + "' WHERE `user_uuid` = '" + old.toString() + '\''); - } catch (SQLException e) { - e.printStackTrace(); + task = this.playerTasks.get(uuid).remove(); + count++; + if (task != null) { + if (task.method == null || !task.method.equals(method)) { + if (statement != null) { + lastTask.execute(statement); + statement.close(); } + method = task.method; + statement = task.get(); + } + task.set(statement); + task.addBatch(statement); } - }); - } - - @Override public void close() { - try { - this.closed = true; - this.connection.close(); - } catch (SQLException e) { + lastTask = task; + } catch (Throwable e) { + PlotSquared.debug("============ DATABASE ERROR ============"); + PlotSquared.debug("There was an error updating the database."); + PlotSquared.debug(" - It will be corrected on shutdown"); + PlotSquared.debug("========================================"); e.printStackTrace(); + PlotSquared.debug("========================================"); + } } + if (statement != null && task != null) { + task.execute(statement); + statement.close(); + } + } + if (!this.clusterTasks.isEmpty()) { + count = 0; + if (this.connection.getAutoCommit()) { + this.connection.setAutoCommit(false); + } + String method = null; + PreparedStatement statement = null; + UniqueStatement task = null; + UniqueStatement lastTask = null; + for (Entry> entry : this.clusterTasks + .entrySet()) { + try { + PlotCluster cluster = entry.getKey(); + if (this.clusterTasks.get(cluster).isEmpty()) { + this.clusterTasks.remove(cluster); + continue; + } + task = this.clusterTasks.get(cluster).remove(); + count++; + if (task != null) { + if (task.method == null || !task.method.equals(method)) { + if (statement != null) { + lastTask.execute(statement); + statement.close(); + } + method = task.method; + statement = task.get(); + } + task.set(statement); + task.addBatch(statement); + } + lastTask = task; + } catch (Throwable e) { + PlotSquared.debug("============ DATABASE ERROR ============"); + PlotSquared.debug("There was an error updating the database."); + PlotSquared.debug(" - It will be corrected on shutdown"); + PlotSquared.debug("========================================"); + e.printStackTrace(); + PlotSquared.debug("========================================"); + } + } + if (statement != null && task != null) { + task.execute(statement); + statement.close(); + } + } + if (count > 0) { + commit(); + return true; + } + if (count != -1) { + if (!this.connection.getAutoCommit()) { + this.connection.setAutoCommit(true); + } + } + if (!this.clusterTasks.isEmpty()) { + this.clusterTasks.clear(); + } + if (!this.plotTasks.isEmpty()) { + this.plotTasks.clear(); + } + } catch (Throwable e) { + PlotSquared.debug("============ DATABASE ERROR ============"); + PlotSquared.debug("There was an error updating the database."); + PlotSquared.debug(" - It will be corrected on shutdown"); + PlotSquared.debug("========================================"); + e.printStackTrace(); + PlotSquared.debug("========================================"); } + return false; + } - public abstract class UniqueStatement { + public Connection getConnection() { + return this.connection; + } - public final String method; + /** + * Set Plot owner + * + * @param plot Plot Object + * @param uuid Owner UUID + */ + @Override + public void setOwner(final Plot plot, final UUID uuid) { + addPlotTask(plot, new UniqueStatement("setOwner") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setString(1, uuid.toString()); + statement.setInt(2, plot.getId().x); + statement.setInt(3, plot.getId().y); + statement.setString(4, plot.getArea().toString()); + } - public UniqueStatement(String method) { - this.method = method; + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement(SQLManager.this.SET_OWNER); + } + }); + } + + @Override + public void createPlotsAndData(final List myList, final Runnable whenDone) { + addGlobalTask(() -> { + try { + // Create the plots + createPlots(myList, () -> { + try { + // Creating datastructures + HashMap plotMap = new HashMap<>(); + for (Plot plot : myList) { + plotMap.put(plot.getId(), plot); + } + ArrayList settings = new ArrayList<>(); + final ArrayList helpers = new ArrayList<>(); + final ArrayList trusted = new ArrayList<>(); + final ArrayList denied = new ArrayList<>(); + + // Populating structures + try (PreparedStatement stmt = SQLManager.this.connection + .prepareStatement(SQLManager.this.GET_ALL_PLOTS); + ResultSet result = stmt.executeQuery()) { + while (result.next()) { + int id = result.getInt("id"); + int x = result.getInt("plot_id_x"); + int y = result.getInt("plot_id_z"); + PlotId plotId = new PlotId(x, y); + Plot plot = plotMap.get(plotId); + if (plot != null) { + settings.add(new SettingsPair(id, plot.getSettings())); + for (UUID uuid : plot.getDenied()) { + denied.add(new UUIDPair(id, uuid)); + } + for (UUID uuid : plot.getMembers()) { + trusted.add(new UUIDPair(id, uuid)); + } + for (UUID uuid : plot.getTrusted()) { + helpers.add(new UUIDPair(id, uuid)); + } + } + } + } + createSettings(settings, () -> createTiers(helpers, "helpers", + () -> createTiers(trusted, "trusted", + () -> createTiers(denied, "denied", + () -> { + try { + SQLManager.this.connection.commit(); + } catch (SQLException e) { + e.printStackTrace(); + } + if (whenDone != null) { + whenDone.run(); + } + })))); + } catch (SQLException e) { + e.printStackTrace(); + PlotSquared.debug("&7[WARN] Failed to set all helpers for plots"); + try { + SQLManager.this.connection.commit(); + } catch (SQLException e1) { + e1.printStackTrace(); + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + PlotSquared.debug("&7[WARN] Failed to set all helpers for plots"); + try { + SQLManager.this.connection.commit(); + } catch (SQLException e1) { + e1.printStackTrace(); } + } + }); + } - public void addBatch(PreparedStatement statement) throws SQLException { - statement.addBatch(); + /** + * Create a plot + * + * @param myList list of plots to be created + */ + public void createTiers(ArrayList myList, final String tier, Runnable whenDone) { + StmtMod mod = new StmtMod() { + @Override + public String getCreateMySQL(int size) { + return getCreateMySQL(size, SQLManager.this.CREATE_TIERS.replaceAll("%tier%", tier), + 2); + } + + @Override + public String getCreateSQLite(int size) { + return getCreateSQLite(size, + "INSERT INTO `" + SQLManager.this.prefix + "plot_" + tier + + "` SELECT ? AS `plot_plot_id`, ? AS `user_uuid`", 2); + } + + @Override + public String getCreateSQL() { + return "INSERT INTO `" + SQLManager.this.prefix + "plot_" + tier + + "` (`plot_plot_id`, `user_uuid`) VALUES(?,?)"; + } + + @Override + public void setMySQL(PreparedStatement stmt, int i, UUIDPair pair) + throws SQLException { + stmt.setInt(i * 2 + 1, pair.id); + stmt.setString(i * 2 + 2, pair.uuid.toString()); + } + + @Override + public void setSQLite(PreparedStatement stmt, int i, UUIDPair pair) + throws SQLException { + stmt.setInt(i * 2 + 1, pair.id); + stmt.setString(i * 2 + 2, pair.uuid.toString()); + } + + @Override + public void setSQL(PreparedStatement stmt, UUIDPair pair) + throws SQLException { + stmt.setInt(1, pair.id); + stmt.setString(2, pair.uuid.toString()); + } + }; + setBulk(myList, mod, whenDone); + } + + /** + * Create a plot + * + * @param myList list of plots to be created + */ + public void createPlots(List myList, Runnable whenDone) { + StmtMod mod = new StmtMod() { + @Override + public String getCreateMySQL(int size) { + return getCreateMySQL(size, SQLManager.this.CREATE_PLOTS, 5); + } + + @Override + public String getCreateSQLite(int size) { + return getCreateSQLite(size, "INSERT INTO `" + SQLManager.this.prefix + + "plot` SELECT ? AS `id`, ? AS `plot_id_x`, ? AS `plot_id_z`, ? AS `owner`, ? AS `world`, ? AS `timestamp` ", + 6); + } + + @Override + public String getCreateSQL() { + return SQLManager.this.CREATE_PLOT; + } + + @Override + public void setMySQL(PreparedStatement stmt, int i, Plot plot) + throws SQLException { + stmt.setInt(i * 5 + 1, plot.getId().x); + stmt.setInt(i * 5 + 2, plot.getId().y); + try { + stmt.setString(i * 5 + 3, plot.owner.toString()); + } catch (SQLException ignored) { + stmt.setString(i * 5 + 3, everyone.toString()); } + stmt.setString(i * 5 + 4, plot.getArea().toString()); + stmt.setTimestamp(i * 5 + 5, new Timestamp(plot.getTimestamp())); + } - public void execute(PreparedStatement statement) throws SQLException { + @Override + public void setSQLite(PreparedStatement stmt, int i, Plot plot) + throws SQLException { + stmt.setNull(i * 6 + 1, 4); + stmt.setInt(i * 6 + 2, plot.getId().x); + stmt.setInt(i * 6 + 3, plot.getId().y); + try { + stmt.setString(i * 6 + 4, plot.owner.toString()); + } catch (SQLException ignored) { + stmt.setString(i * 6 + 4, everyone.toString()); + } + stmt.setString(i * 6 + 5, plot.getArea().toString()); + stmt.setTimestamp(i * 6 + 6, new Timestamp(plot.getTimestamp())); + } + + @Override + public void setSQL(PreparedStatement stmt, Plot plot) throws SQLException { + stmt.setInt(1, plot.getId().x); + stmt.setInt(2, plot.getId().y); + stmt.setString(3, plot.owner.toString()); + stmt.setString(4, plot.getArea().toString()); + stmt.setTimestamp(5, new Timestamp(plot.getTimestamp())); + + } + }; + setBulk(myList, mod, whenDone); + } + + public void setBulk(List objList, StmtMod mod, Runnable whenDone) { + int size = objList.size(); + if (size == 0) { + if (whenDone != null) { + whenDone.run(); + } + return; + } + int packet; + if (this.mySQL) { + packet = Math.min(size, 5000); + } else { + packet = Math.min(size, 50); + } + int amount = size / packet; + try { + int count = 0; + PreparedStatement preparedStmt = null; + int last = -1; + for (int j = 0; j <= amount; j++) { + List subList = objList.subList(j * packet, Math.min(size, (j + 1) * packet)); + if (subList.isEmpty()) { + break; + } + String statement; + if (last == -1) { + last = subList.size(); + statement = mod.getCreateMySQL(subList.size()); + preparedStmt = this.connection.prepareStatement(statement); + } + if (subList.size() != last || count % 5000 == 0 && count > 0) { + preparedStmt.executeBatch(); + preparedStmt.close(); + statement = mod.getCreateMySQL(subList.size()); + preparedStmt = this.connection.prepareStatement(statement); + } + for (int i = 0; i < subList.size(); i++) { + count++; + T obj = subList.get(i); + mod.setMySQL(preparedStmt, i, obj); + } + last = subList.size(); + preparedStmt.addBatch(); + } + PlotSquared.debug( + "&aBatch 1: " + count + " | " + objList.get(0).getClass().getCanonicalName()); + preparedStmt.executeBatch(); + preparedStmt.clearParameters(); + preparedStmt.close(); + if (whenDone != null) { + whenDone.run(); + } + return; + } catch (SQLException e) { + if (this.mySQL) { + e.printStackTrace(); + PlotSquared.debug("&cERROR 1: | " + objList.get(0).getClass().getCanonicalName()); + } + } + try { + int count = 0; + PreparedStatement preparedStmt = null; + int last = -1; + for (int j = 0; j <= amount; j++) { + List subList = objList.subList(j * packet, Math.min(size, (j + 1) * packet)); + if (subList.isEmpty()) { + break; + } + String statement; + if (last == -1) { + last = subList.size(); + statement = mod.getCreateSQLite(subList.size()); + preparedStmt = this.connection.prepareStatement(statement); + } + if (subList.size() != last || count % 5000 == 0 && count > 0) { + preparedStmt.executeBatch(); + preparedStmt.clearParameters(); + statement = mod.getCreateSQLite(subList.size()); + preparedStmt = this.connection.prepareStatement(statement); + } + for (int i = 0; i < subList.size(); i++) { + count++; + T obj = subList.get(i); + mod.setSQLite(preparedStmt, i, obj); + } + last = subList.size(); + preparedStmt.addBatch(); + } + PlotSquared.debug( + "&aBatch 2: " + count + " | " + objList.get(0).getClass().getCanonicalName()); + preparedStmt.executeBatch(); + preparedStmt.clearParameters(); + preparedStmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + PlotSquared.debug("&cERROR 2: | " + objList.get(0).getClass().getCanonicalName()); + PlotSquared.debug("&6[WARN] Could not bulk save!"); + try (PreparedStatement preparedStmt = this.connection + .prepareStatement(mod.getCreateSQL())) { + for (T obj : objList) { + mod.setSQL(preparedStmt, obj); + preparedStmt.addBatch(); + } + PlotSquared.debug("&aBatch 3"); + preparedStmt.executeBatch(); + } catch (SQLException e3) { + e3.printStackTrace(); + PlotSquared.debug("&c[ERROR] Failed to save all!"); + } + } + if (whenDone != null) { + whenDone.run(); + } + } + + public void createSettings(final ArrayList myList, final Runnable whenDone) { + final StmtMod mod = new StmtMod() { + @Override + public String getCreateMySQL(int size) { + return getCreateMySQL(size, "INSERT INTO `" + SQLManager.this.prefix + + "plot_settings`(`plot_plot_id`,`biome`,`rain`,`custom_time`,`time`,`deny_entry`,`alias`,`flags`,`merged`," + + "`position`) VALUES ", 10); + } + + @Override + public String getCreateSQLite(int size) { + return getCreateSQLite(size, "INSERT INTO `" + SQLManager.this.prefix + + "plot_settings` SELECT ? AS `plot_plot_id`, ? AS `biome`, ? AS `rain`, ? AS `custom_time`, ? AS `time`, ? AS " + + "`deny_entry`, ? AS `alias`, ? AS `flags`, ? AS `merged`, ? AS `position`", + 10); + } + + @Override + public String getCreateSQL() { + return "INSERT INTO `" + SQLManager.this.prefix + + "plot_settings`(`plot_plot_id`) VALUES(?)"; + } + + @Override + public void setMySQL(PreparedStatement statement, int i, SettingsPair pair) + throws SQLException { + statement.setInt(i * 10 + 1, pair.id); // id + statement.setNull(i * 10 + 2, 4); // biome + statement.setNull(i * 10 + 3, 4); // rain + statement.setNull(i * 10 + 4, 4); // custom_time + statement.setNull(i * 10 + 5, 4); // time + statement.setNull(i * 10 + 6, 4); // deny_entry + if (pair.settings.getAlias().isEmpty()) { + statement.setNull(i * 10 + 7, 4); + } else { + statement.setString(i * 10 + 7, pair.settings.getAlias()); + } + StringBuilder flag_string = new StringBuilder(); + int k = 0; + for (Entry, ?> flag : pair.settings.flags.entrySet()) { + if (k != 0) { + flag_string.append(','); + } + flag_string.append(flag.getKey().getName()).append(':').append( + flag.getKey().valueToString(flag.getValue()).replaceAll(":", "¯") + .replaceAll(",", "´")); + k++; + } + statement.setString(i * 10 + 8, flag_string.toString()); + boolean[] merged = pair.settings.getMerged(); + int hash = MainUtil.hash(merged); + statement.setInt(i * 10 + 9, hash); + BlockLoc loc = pair.settings.getPosition(); + String position; + if (loc.y == 0) { + position = "DEFAULT"; + } else { + position = loc.x + "," + loc.y + ',' + loc.z; + } + statement.setString(i * 10 + 10, position); + } + + @Override + public void setSQLite(PreparedStatement stmt, int i, SettingsPair pair) + throws SQLException { + stmt.setInt(i * 10 + 1, pair.id); // id + stmt.setNull(i * 10 + 2, 4); // biome + stmt.setNull(i * 10 + 3, 4); // rain + stmt.setNull(i * 10 + 4, 4); // custom_time + stmt.setNull(i * 10 + 5, 4); // time + stmt.setNull(i * 10 + 6, 4); // deny_entry + if (pair.settings.getAlias().isEmpty()) { + stmt.setNull(i * 10 + 7, 4); + } else { + stmt.setString(i * 10 + 7, pair.settings.getAlias()); + } + StringBuilder flag_string = new StringBuilder(); + int k = 0; + for (Entry, ?> flag : pair.settings.flags.entrySet()) { + if (k != 0) { + flag_string.append(','); + } + flag_string.append(flag.getKey().getName()).append(':').append( + flag.getKey().valueToString(flag.getValue()).replaceAll(":", "¯") + .replaceAll(",", "´")); + k++; + } + stmt.setString(i * 10 + 8, flag_string.toString()); + boolean[] merged = pair.settings.getMerged(); + int n = 0; + for (int j = 0; j < 4; ++j) { + n = (n << 1) + (merged[j] ? 1 : 0); + } + stmt.setInt(i * 10 + 9, n); + BlockLoc loc = pair.settings.getPosition(); + String position; + if (loc.y == 0) { + position = "DEFAULT"; + } else { + position = loc.x + "," + loc.y + ',' + loc.z; + } + stmt.setString(i * 10 + 10, position); + } + + @Override + public void setSQL(PreparedStatement stmt, SettingsPair pair) + throws SQLException { + stmt.setInt(1, pair.id); + } + }; + addGlobalTask(() -> setBulk(myList, mod, whenDone)); + } + + public void createEmptySettings(final ArrayList myList, final Runnable whenDone) { + final StmtMod mod = new StmtMod() { + @Override + public String getCreateMySQL(int size) { + return getCreateMySQL(size, SQLManager.this.CREATE_SETTINGS, 1); + } + + @Override + public String getCreateSQLite(int size) { + return getCreateSQLite(size, "INSERT INTO `" + SQLManager.this.prefix + + "plot_settings` SELECT ? AS `plot_plot_id`, ? AS `biome`, ? AS `rain`, ? AS `custom_time`, ? AS `time`, ? AS " + + "`deny_entry`, ? AS `alias`, ? AS `flags`, ? AS `merged`, ? AS `position` ", + 10); + } + + @Override + public String getCreateSQL() { + return "INSERT INTO `" + SQLManager.this.prefix + + "plot_settings`(`plot_plot_id`) VALUES(?)"; + } + + @Override + public void setMySQL(PreparedStatement stmt, int i, Integer id) + throws SQLException { + stmt.setInt(i + 1, id); + } + + @Override + public void setSQLite(PreparedStatement stmt, int i, Integer id) + throws SQLException { + stmt.setInt(i * 10 + 1, id); + stmt.setNull(i * 10 + 2, 4); + stmt.setNull(i * 10 + 3, 4); + stmt.setNull(i * 10 + 4, 4); + stmt.setNull(i * 10 + 5, 4); + stmt.setNull(i * 10 + 6, 4); + stmt.setNull(i * 10 + 7, 4); + stmt.setNull(i * 10 + 8, 4); + stmt.setNull(i * 10 + 9, 4); + stmt.setString(i * 10 + 10, "DEFAULT"); + } + + @Override + public void setSQL(PreparedStatement stmt, Integer id) throws SQLException { + stmt.setInt(1, id); + } + }; + addGlobalTask(() -> setBulk(myList, mod, whenDone)); + } + + public void createPlotSafe(final Plot plot, final Runnable success, final Runnable failure) { + final long timestamp = plot.getTimestamp(); + addPlotTask(plot, new UniqueStatement("createPlotSafe_" + plot.hashCode()) { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, plot.getId().x); + stmt.setInt(2, plot.getId().y); + stmt.setString(3, plot.owner.toString()); + stmt.setString(4, plot.getArea().toString()); + stmt.setTimestamp(5, new Timestamp(plot.getTimestamp())); + stmt.setString(6, plot.getArea().toString()); + stmt.setInt(7, plot.getId().x); + stmt.setInt(8, plot.getId().y); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement(SQLManager.this.CREATE_PLOT_SAFE, + Statement.RETURN_GENERATED_KEYS); + } + + @Override + public void execute(PreparedStatement statement) { + + } + + @Override + public void addBatch(PreparedStatement statement) throws SQLException { + int inserted = statement.executeUpdate(); + if (inserted > 0) { + try (ResultSet keys = statement.getGeneratedKeys()) { + if (keys.next()) { + plot.temp = keys.getInt(1); + addPlotTask(plot, new UniqueStatement( + "createPlotAndSettings_settings_" + plot.hashCode()) { + @Override + public void set(PreparedStatement stmt) + throws SQLException { + stmt.setInt(1, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "plot_settings`(`plot_plot_id`) VALUES(?)"); + } + }); + if (success != null) { + addNotifyTask(success); + } + return; + } + } + } + if (failure != null) { + failure.run(); + } + } + }); + } + + public void commit() { + if (this.closed) { + return; + } + try { + if (!this.connection.getAutoCommit()) { + this.connection.commit(); + this.connection.setAutoCommit(true); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Override + public void createPlotAndSettings(final Plot plot, Runnable whenDone) { + addPlotTask(plot, new UniqueStatement("createPlotAndSettings_" + plot.hashCode()) { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, plot.getId().x); + stmt.setInt(2, plot.getId().y); + stmt.setString(3, plot.owner.toString()); + stmt.setString(4, plot.getArea().toString()); + stmt.setTimestamp(5, new Timestamp(plot.getTimestamp())); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection + .prepareStatement(SQLManager.this.CREATE_PLOT, Statement.RETURN_GENERATED_KEYS); + } + + @Override + public void execute(PreparedStatement statement) { + } + + @Override + public void addBatch(PreparedStatement statement) throws SQLException { + statement.executeUpdate(); + try (ResultSet keys = statement.getGeneratedKeys()) { + if (keys.next()) { + plot.temp = keys.getInt(1); + } + } + } + }); + addPlotTask(plot, new UniqueStatement("createPlotAndSettings_settings_" + plot.hashCode()) { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "plot_settings`(`plot_plot_id`) VALUES(?)"); + } + }); + addNotifyTask(whenDone); + } + + /** + * Create tables. + */ + @Override + public void createTables() throws SQLException { + String[] tables = + new String[]{"plot", "plot_denied", "plot_helpers", "plot_comments", "plot_trusted", + "plot_rating", "plot_settings", "cluster", "player_meta"}; + DatabaseMetaData meta = this.connection.getMetaData(); + int create = 0; + for (String s : tables) { + ResultSet set = meta.getTables(null, null, this.prefix + s, new String[]{"TABLE"}); + // ResultSet set = meta.getTables(null, null, prefix + s, null); + if (!set.next()) { + create++; + } + set.close(); + } + if (create == 0) { + return; + } + boolean addConstraint = create == tables.length; + PlotSquared.debug("Creating tables"); + try (Statement stmt = this.connection.createStatement()) { + if (this.mySQL) { + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot` (" + + "`id` INT(11) NOT NULL AUTO_INCREMENT," + "`plot_id_x` INT(11) NOT NULL," + + "`plot_id_z` INT(11) NOT NULL," + "`owner` VARCHAR(40) NOT NULL," + + "`world` VARCHAR(45) NOT NULL," + + "`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," + + "PRIMARY KEY (`id`)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + + "plot_denied` (`plot_plot_id` INT(11) NOT NULL," + + "`user_uuid` VARCHAR(40) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_helpers` (" + + "`plot_plot_id` INT(11) NOT NULL," + "`user_uuid` VARCHAR(40) NOT NULL" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_comments` (" + + "`world` VARCHAR(40) NOT NULL, `hashcode` INT(11) NOT NULL," + + "`comment` VARCHAR(40) NOT NULL," + "`inbox` VARCHAR(40) NOT NULL," + + "`timestamp` INT(11) NOT NULL," + "`sender` VARCHAR(40) NOT NULL" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_trusted` (" + + "`plot_plot_id` INT(11) NOT NULL," + "`user_uuid` VARCHAR(40) NOT NULL" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_settings` (" + + " `plot_plot_id` INT(11) NOT NULL," + + " `biome` VARCHAR(45) DEFAULT 'FOREST'," + " `rain` INT(1) DEFAULT 0," + + " `custom_time` TINYINT(1) DEFAULT '0'," + " `time` INT(11) DEFAULT '8000'," + + " `deny_entry` TINYINT(1) DEFAULT '0'," + + " `alias` VARCHAR(50) DEFAULT NULL," + " `flags` VARCHAR(512) DEFAULT NULL," + + " `merged` INT(11) DEFAULT NULL," + + " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," + + " PRIMARY KEY (`plot_plot_id`)" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + + "plot_rating` ( `plot_plot_id` INT(11) NOT NULL, `rating` INT(2) NOT NULL, `player` VARCHAR(40) NOT NULL) ENGINE=InnoDB " + + "DEFAULT CHARSET=utf8"); + if (addConstraint) { + stmt.addBatch("ALTER TABLE `" + this.prefix + "plot_settings` ADD CONSTRAINT `" + + this.prefix + + "plot_settings_ibfk_1` FOREIGN KEY (`plot_plot_id`) REFERENCES `" + + this.prefix + "plot` (`id`) ON DELETE CASCADE"); + } + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster` (" + + "`id` INT(11) NOT NULL AUTO_INCREMENT," + "`pos1_x` INT(11) NOT NULL," + + "`pos1_z` INT(11) NOT NULL," + "`pos2_x` INT(11) NOT NULL," + + "`pos2_z` INT(11) NOT NULL," + "`owner` VARCHAR(40) NOT NULL," + + "`world` VARCHAR(45) NOT NULL," + + "`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," + + "PRIMARY KEY (`id`)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster_helpers` (" + + "`cluster_id` INT(11) NOT NULL," + "`user_uuid` VARCHAR(40) NOT NULL" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster_invited` (" + + "`cluster_id` INT(11) NOT NULL," + "`user_uuid` VARCHAR(40) NOT NULL" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster_settings` (" + + " `cluster_id` INT(11) NOT NULL," + " `biome` VARCHAR(45) DEFAULT 'FOREST'," + + " `rain` INT(1) DEFAULT 0," + " `custom_time` TINYINT(1) DEFAULT '0'," + + " `time` INT(11) DEFAULT '8000'," + " `deny_entry` TINYINT(1) DEFAULT '0'," + + " `alias` VARCHAR(50) DEFAULT NULL," + " `flags` VARCHAR(512) DEFAULT NULL," + + " `merged` INT(11) DEFAULT NULL," + + " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," + + " PRIMARY KEY (`cluster_id`)" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "player_meta` (" + + " `meta_id` INT(11) NOT NULL AUTO_INCREMENT," + + " `uuid` VARCHAR(40) NOT NULL," + " `key` VARCHAR(32) NOT NULL," + + " `value` blob NOT NULL," + " PRIMARY KEY (`meta_id`)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); + } else { + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot` (" + + "`id` INTEGER PRIMARY KEY AUTOINCREMENT," + "`plot_id_x` INT(11) NOT NULL," + + "`plot_id_z` INT(11) NOT NULL," + "`owner` VARCHAR(45) NOT NULL," + + "`world` VARCHAR(45) NOT NULL," + + "`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP)"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + + "plot_denied` (`plot_plot_id` INT(11) NOT NULL," + + "`user_uuid` VARCHAR(40) NOT NULL)"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + + "plot_helpers` (`plot_plot_id` INT(11) NOT NULL," + + "`user_uuid` VARCHAR(40) NOT NULL)"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + + "plot_trusted` (`plot_plot_id` INT(11) NOT NULL," + + "`user_uuid` VARCHAR(40) NOT NULL)"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_comments` (" + + "`world` VARCHAR(40) NOT NULL, `hashcode` INT(11) NOT NULL," + + "`comment` VARCHAR(40) NOT NULL," + + "`inbox` VARCHAR(40) NOT NULL, `timestamp` INT(11) NOT NULL," + + "`sender` VARCHAR(40) NOT NULL" + ')'); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_settings` (" + + " `plot_plot_id` INT(11) NOT NULL," + + " `biome` VARCHAR(45) DEFAULT 'FOREST'," + " `rain` INT(1) DEFAULT 0," + + " `custom_time` TINYINT(1) DEFAULT '0'," + " `time` INT(11) DEFAULT '8000'," + + " `deny_entry` TINYINT(1) DEFAULT '0'," + + " `alias` VARCHAR(50) DEFAULT NULL," + " `flags` VARCHAR(512) DEFAULT NULL," + + " `merged` INT(11) DEFAULT NULL," + + " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," + + " PRIMARY KEY (`plot_plot_id`)" + ')'); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + + "plot_rating` (`plot_plot_id` INT(11) NOT NULL, `rating` INT(2) NOT NULL, `player` VARCHAR(40) NOT NULL)"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster` (" + + "`id` INTEGER PRIMARY KEY AUTOINCREMENT," + "`pos1_x` INT(11) NOT NULL," + + "`pos1_z` INT(11) NOT NULL," + "`pos2_x` INT(11) NOT NULL," + + "`pos2_z` INT(11) NOT NULL," + "`owner` VARCHAR(40) NOT NULL," + + "`world` VARCHAR(45) NOT NULL," + + "`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP" + ')'); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + + "cluster_helpers` (`cluster_id` INT(11) NOT NULL," + + "`user_uuid` VARCHAR(40) NOT NULL)"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + + "cluster_invited` (`cluster_id` INT(11) NOT NULL," + + "`user_uuid` VARCHAR(40) NOT NULL)"); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "cluster_settings` (" + + " `cluster_id` INT(11) NOT NULL," + " `biome` VARCHAR(45) DEFAULT 'FOREST'," + + " `rain` INT(1) DEFAULT 0," + " `custom_time` TINYINT(1) DEFAULT '0'," + + " `time` INT(11) DEFAULT '8000'," + " `deny_entry` TINYINT(1) DEFAULT '0'," + + " `alias` VARCHAR(50) DEFAULT NULL," + " `flags` VARCHAR(512) DEFAULT NULL," + + " `merged` INT(11) DEFAULT NULL," + + " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," + + " PRIMARY KEY (`cluster_id`)" + ')'); + stmt.addBatch("CREATE TABLE IF NOT EXISTS `" + this.prefix + "player_meta` (" + + " `meta_id` INTEGER PRIMARY KEY AUTOINCREMENT," + + " `uuid` VARCHAR(40) NOT NULL," + " `key` VARCHAR(32) NOT NULL," + + " `value` blob NOT NULL" + ')'); + } + stmt.executeBatch(); + stmt.clearBatch(); + } + } + + @Override + public void deleteSettings(final Plot plot) { + addPlotTask(plot, new UniqueStatement("delete_plot_settings") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_settings` WHERE `plot_plot_id` = ?"); + } + }); + } + + @Override + public void deleteHelpers(final Plot plot) { + if (plot.getTrusted().isEmpty()) { + return; + } + addPlotTask(plot, new UniqueStatement("delete_plot_helpers") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_helpers` WHERE `plot_plot_id` = ?"); + } + }); + } + + @Override + public void deleteTrusted(final Plot plot) { + if (plot.getMembers().isEmpty()) { + return; + } + addPlotTask(plot, new UniqueStatement("delete_plot_trusted") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_trusted` WHERE `plot_plot_id` = ?"); + } + }); + } + + @Override + public void deleteDenied(final Plot plot) { + if (plot.getDenied().isEmpty()) { + return; + } + addPlotTask(plot, new UniqueStatement("delete_plot_denied") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_denied` WHERE `plot_plot_id` = ?"); + } + }); + } + + @Override + public void deleteComments(final Plot plot) { + addPlotTask(plot, new UniqueStatement("delete_plot_comments") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setString(1, plot.getArea().toString()); + stmt.setInt(2, plot.hashCode()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_comments` WHERE `world` = ? AND `hashcode` = ?"); + } + }); + } + + @Override + public void deleteRatings(final Plot plot) { + if (Settings.Enabled_Components.RATING_CACHE && plot.getSettings().getRatings().isEmpty()) { + return; + } + addPlotTask(plot, new UniqueStatement("delete_plot_ratings") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_rating` WHERE `plot_plot_id` = ?"); + } + }); + } + + /** + * Delete a plot. + */ + @Override + public void delete(final Plot plot) { + PlotSquared.debug( + "Deleting plot... Id: " + plot.getId() + " World: " + plot.getWorldName() + " Owner: " + + plot.owner + " Index: " + plot.temp); + deleteSettings(plot); + deleteDenied(plot); + deleteHelpers(plot); + deleteTrusted(plot); + deleteComments(plot); + deleteRatings(plot); + addPlotTask(plot, new UniqueStatement("delete_plot") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + "plot` WHERE `id` = ?"); + } + }); + } + + /** + * Create plot settings + */ + @Override + public void createPlotSettings(final int id, Plot plot) { + PlotSquared.debug( + "Creating plot... Id: " + plot.getId() + " World: " + plot.getWorldName() + " Owner: " + + plot.owner + " Index: " + id); + addPlotTask(plot, new UniqueStatement("createPlotSettings") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, id); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "plot_settings`(`plot_plot_id`) VALUES(?)"); + } + }); + } + + @Override + public int getClusterId(PlotCluster cluster) { + if (cluster.temp > 0) { + return cluster.temp; + } + try { + commit(); + if (cluster.temp > 0) { + return cluster.temp; + } + int c_id; + try (PreparedStatement stmt = this.connection.prepareStatement( + "SELECT `id` FROM `" + this.prefix + + "cluster` WHERE `pos1_x` = ? AND `pos1_z` = ? AND `pos2_x` = ? AND `pos2_z` = ? AND `world` = ? ORDER BY `timestamp` ASC")) { + stmt.setInt(1, cluster.getP1().x); + stmt.setInt(2, cluster.getP1().y); + stmt.setInt(3, cluster.getP2().x); + stmt.setInt(4, cluster.getP2().y); + stmt.setString(5, cluster.area.toString()); + try (ResultSet resultSet = stmt.executeQuery()) { + c_id = Integer.MAX_VALUE; + while (resultSet.next()) { + c_id = resultSet.getInt("id"); + } + } + } + if (c_id == Integer.MAX_VALUE || c_id == 0) { + if (cluster.temp > 0) { + return cluster.temp; + } + throw new SQLException("Cluster does not exist in database"); + } + cluster.temp = c_id; + return c_id; + } catch (SQLException e) { + e.printStackTrace(); + } + return Integer.MAX_VALUE; + } + + @Override + public int getId(Plot plot) { + if (plot.temp > 0) { + return plot.temp; + } + try { + commit(); + if (plot.temp > 0) { + return plot.temp; + } + int id; + try (PreparedStatement statement = this.connection.prepareStatement( + "SELECT `id` FROM `" + this.prefix + + "plot` WHERE `plot_id_x` = ? AND `plot_id_z` = ? AND world = ? ORDER BY `timestamp` ASC")) { + statement.setInt(1, plot.getId().x); + statement.setInt(2, plot.getId().y); + statement.setString(3, plot.getArea().toString()); + try (ResultSet resultSet = statement.executeQuery()) { + id = Integer.MAX_VALUE; + while (resultSet.next()) { + id = resultSet.getInt("id"); + } + } + } + if (id == Integer.MAX_VALUE || id == 0) { + if (plot.temp > 0) { + return plot.temp; + } + throw new SQLException("Plot does not exist in database"); + } + plot.temp = id; + return id; + } catch (SQLException e) { + e.printStackTrace(); + } + return Integer.MAX_VALUE; + } + + @Override + public void updateTables(int[] oldVersion) { + try { + if (this.mySQL && !PlotSquared.get().checkVersion(oldVersion, 3, 3, 2)) { + try (Statement stmt = this.connection.createStatement()) { + stmt.executeUpdate( + "ALTER TABLE `" + this.prefix + "plots` DROP INDEX `unique_alias`"); + } catch (SQLException ignored) { + } + } + DatabaseMetaData data = this.connection.getMetaData(); + ResultSet rs = + data.getColumns(null, null, this.prefix + "plot_comments", "plot_plot_id"); + if (rs.next()) { + rs.close(); + rs = data.getColumns(null, null, this.prefix + "plot_comments", "hashcode"); + if (!rs.next()) { + rs.close(); + try (Statement statement = this.connection.createStatement()) { + statement.addBatch("DROP TABLE `" + this.prefix + "plot_comments`"); + if (Storage.MySQL.USE) { + statement.addBatch( + "CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_comments` (" + + "`world` VARCHAR(40) NOT NULL, `hashcode` INT(11) NOT NULL," + + "`comment` VARCHAR(40) NOT NULL," + + "`inbox` VARCHAR(40) NOT NULL," + + "`timestamp` INT(11) NOT NULL," + + "`sender` VARCHAR(40) NOT NULL" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8"); + } else { + statement.addBatch( + "CREATE TABLE IF NOT EXISTS `" + this.prefix + "plot_comments` (" + + "`world` VARCHAR(40) NOT NULL, `hashcode` INT(11) NOT NULL," + + "`comment` VARCHAR(40) NOT NULL," + + "`inbox` VARCHAR(40) NOT NULL, `timestamp` INT(11) NOT NULL," + + "`sender` VARCHAR(40) NOT NULL" + ')'); + } statement.executeBatch(); + } catch (SQLException ignored) { + try (Statement statement = this.connection.createStatement()) { + statement.addBatch("ALTER IGNORE TABLE `" + this.prefix + + "plot_comments` ADD `inbox` VARCHAR(11) DEFAULT `public`"); + statement.addBatch("ALTER IGNORE TABLE `" + this.prefix + + "plot_comments` ADD `timestamp` INT(11) DEFAULT 0"); + statement.addBatch("ALTER TABLE `" + this.prefix + "plot` DROP `tier`"); + statement.executeBatch(); + } + } + } + } + rs.close(); + rs = data.getColumns(null, null, this.prefix + "plot_denied", "plot_plot_id"); + if (rs.next()) { + try (Statement statement = this.connection.createStatement()) { + statement.executeUpdate("DELETE FROM `" + this.prefix + + "plot_denied` WHERE `plot_plot_id` NOT IN (SELECT `id` FROM `" + + this.prefix + "plot`)"); + } catch (SQLException e) { + e.printStackTrace(); } - public abstract PreparedStatement get() throws SQLException; - - public abstract void set(PreparedStatement stmt) throws SQLException; - } - - - private class UUIDPair { - - public final int id; - public final UUID uuid; - - public UUIDPair(int id, UUID uuid) { - this.id = id; - this.uuid = uuid; + rs.close(); + try (Statement statement = this.connection.createStatement()) { + for (String table : new String[]{"plot_denied", "plot_helpers", + "plot_trusted"}) { + ResultSet result = statement.executeQuery( + "SELECT plot_plot_id, user_uuid, COUNT(*) FROM " + this.prefix + table + + " GROUP BY plot_plot_id, user_uuid HAVING COUNT(*) > 1"); + if (result.next()) { + PlotSquared.debug("BACKING UP: " + this.prefix + table); + result.close(); + statement.executeUpdate( + "CREATE TABLE " + this.prefix + table + "_tmp AS SELECT * FROM " + + this.prefix + table + " GROUP BY plot_plot_id, user_uuid"); + statement.executeUpdate("DROP TABLE " + this.prefix + table); + statement.executeUpdate( + "CREATE TABLE " + this.prefix + table + " AS SELECT * FROM " + + this.prefix + table + "_tmp"); + statement.executeUpdate("DROP TABLE " + this.prefix + table + "_tmp"); + PlotSquared.debug("RESTORING: " + this.prefix + table); + } + } + } catch (SQLException e2) { + e2.printStackTrace(); } + } + } catch (SQLException e) { + e.printStackTrace(); } + } - private class SettingsPair { + public void deleteRows(ArrayList rowIds, final String table, final String column) { + setBulk(rowIds, new StmtMod() { - public final int id; - public final PlotSettings settings; + @Override + public String getCreateMySQL(int size) { + return getCreateMySQL(1, "DELETE FROM `" + table + "` WHERE `" + column + "` IN ", + size); + } - public SettingsPair(int id, PlotSettings settings) { - this.id = id; - this.settings = settings; + @Override + public String getCreateSQLite(int size) { + return getCreateMySQL(1, "DELETE FROM `" + table + "` WHERE `" + column + "` IN ", + size); + } + + @Override + public String getCreateSQL() { + return "DELETE FROM `" + table + "` WHERE `" + column + "` = ?"; + } + + @Override + public void setMySQL(PreparedStatement stmt, int i, Integer obj) + throws SQLException { + stmt.setInt(i + 1, obj); + } + + @Override + public void setSQLite(PreparedStatement stmt, int i, Integer obj) + throws SQLException { + stmt.setInt(i + 1, obj); + } + + @Override + public void setSQL(PreparedStatement stmt, Integer obj) throws SQLException { + stmt.setInt(1, obj); + } + }, null); + } + + /** + * Load all plots, helpers, denied, trusted, and every setting from DB into a {@link HashMap}. + */ + @Override + public HashMap> getPlots() { + HashMap> newPlots = new HashMap<>(); + HashMap plots = new HashMap<>(); + try { + HashSet areas = new HashSet<>(); + if (PlotSquared.get().worlds.contains("worlds")) { + ConfigurationSection worldSection = + PlotSquared.get().worlds.getConfigurationSection("worlds"); + if (worldSection != null) { + for (String worldKey : worldSection.getKeys(false)) { + areas.add(worldKey); + ConfigurationSection areaSection = + worldSection.getConfigurationSection(worldKey + ".areas"); + if (areaSection != null) { + areaSection.getKeys(false).forEach(s -> { + String[] split = s.split("(? uuids = new HashMap<>(); + HashMap noExist = new HashMap<>(); + + /* + * Getting plots + */ + try (Statement statement = this.connection.createStatement()) { + int id; + String owner; + UUID user; + try (ResultSet resultSet = statement.executeQuery( + "SELECT `id`, `plot_id_x`, `plot_id_z`, `owner`, `world`, `timestamp` FROM `" + + this.prefix + "plot`")) { + ArrayList toDelete = new ArrayList<>(); + while (resultSet.next()) { + PlotId plot_id = new PlotId(resultSet.getInt("plot_id_x"), + resultSet.getInt("plot_id_z")); + id = resultSet.getInt("id"); + String areaid = resultSet.getString("world"); + if (!areas.contains(areaid)) { + if (Settings.Enabled_Components.DATABASE_PURGER) { + toDelete.add(id); + continue; + } else { + AtomicInteger value = noExist.get(areaid); + if (value != null) { + value.incrementAndGet(); + } else { + noExist.put(areaid, new AtomicInteger(1)); + } + } + } + owner = resultSet.getString("owner"); + user = uuids.computeIfAbsent(owner, s -> { + try { + return UUID.fromString(s); + } catch (IllegalArgumentException ignored) { + if (Settings.UUID.FORCE_LOWERCASE) { + return UUID.nameUUIDFromBytes( + ("OfflinePlayer:" + s.toLowerCase()) + .getBytes(Charsets.UTF_8)); + } else { + return UUID.nameUUIDFromBytes( + ("OfflinePlayer:" + s).getBytes(Charsets.UTF_8)); + } + } + }); + long time; + try { + Timestamp timestamp = resultSet.getTimestamp("timestamp"); + time = timestamp.getTime(); + } catch (SQLException exception) { + String parsable = resultSet.getString("timestamp"); + try { + time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(parsable) + .getTime(); + } catch (ParseException e) { + PlotSquared.debug( + "Could not parse date for plot: #" + id + "(" + areaid + ";" + + plot_id + ") (" + parsable + ")"); + time = System.currentTimeMillis() + id; + } + } + Plot plot = new Plot(plot_id, user, new HashSet<>(), new HashSet<>(), + new HashSet<>(), "", null, null, null, + new boolean[]{false, false, false, false}, time, id); + HashMap map = newPlots.get(areaid); + if (map != null) { + Plot last = map.put(plot.getId(), plot); + if (last != null) { + if (Settings.Enabled_Components.DATABASE_PURGER) { + toDelete.add(last.temp); + } else { + PlotSquared.debug( + "&cPLOT #" + id + "(" + last + ") in `" + this.prefix + + "plot` is a duplicate. Delete this plot or set `database-purger: true` in the settings.yml."); + } + } + } else { + map = new HashMap<>(); + newPlots.put(areaid, map); + map.put(plot.getId(), plot); + } + plots.put(id, plot); + } + deleteRows(toDelete, this.prefix + "plot", "id"); + } + if (Settings.Enabled_Components.RATING_CACHE) { + try (ResultSet r = statement.executeQuery( + "SELECT `plot_plot_id`, `player`, `rating` FROM `" + this.prefix + + "plot_rating`")) { + ArrayList toDelete = new ArrayList<>(); + while (r.next()) { + id = r.getInt("plot_plot_id"); + owner = r.getString("player"); + user = uuids.computeIfAbsent(owner, UUID::fromString); + Plot plot = plots.get(id); + if (plot != null) { + plot.getSettings().getRatings().put(user, r.getInt("rating")); + } else if (Settings.Enabled_Components.DATABASE_PURGER) { + toDelete.add(id); + } else { + PlotSquared.debug("&cENTRY #" + id + "(" + plot + + ") in `plot_rating` does not exist. Create this plot or set `database-purger: true` in the " + + "settings.yml."); + } + } + deleteRows(toDelete, this.prefix + "plot_rating", "plot_plot_id"); + } + } + + /* + * Getting helpers + */ + try (ResultSet r = statement.executeQuery( + "SELECT `user_uuid`, `plot_plot_id` FROM `" + this.prefix + "plot_helpers`")) { + ArrayList toDelete = new ArrayList<>(); + while (r.next()) { + id = r.getInt("plot_plot_id"); + owner = r.getString("user_uuid"); + user = uuids.computeIfAbsent(owner, UUID::fromString); + Plot plot = plots.get(id); + if (plot != null) { + plot.getTrusted().add(user); + } else if (Settings.Enabled_Components.DATABASE_PURGER) { + toDelete.add(id); + } else { + PlotSquared.debug("&cENTRY #" + id + "(" + plot + + ") in `plot_helpers` does not exist. Create this plot or set `database-purger: true` in the settings" + + ".yml."); + } + } + deleteRows(toDelete, this.prefix + "plot_helpers", "plot_plot_id"); + } + + /* + * Getting trusted + */ + try (ResultSet r = statement.executeQuery( + "SELECT `user_uuid`, `plot_plot_id` FROM `" + this.prefix + "plot_trusted`")) { + ArrayList toDelete = new ArrayList<>(); + while (r.next()) { + id = r.getInt("plot_plot_id"); + owner = r.getString("user_uuid"); + user = uuids.computeIfAbsent(owner,UUID::fromString); + Plot plot = plots.get(id); + if (plot != null) { + plot.getMembers().add(user); + } else if (Settings.Enabled_Components.DATABASE_PURGER) { + toDelete.add(id); + } else { + PlotSquared.debug("&cENTRY #" + id + "(" + plot + + ") in `plot_trusted` does not exist. Create this plot or set `database-purger: true` in the settings" + + ".yml."); + } + } + deleteRows(toDelete, this.prefix + "plot_trusted", "plot_plot_id"); + } + + /* + * Getting denied + */ + try (ResultSet r = statement.executeQuery( + "SELECT `user_uuid`, `plot_plot_id` FROM `" + this.prefix + "plot_denied`")) { + ArrayList toDelete = new ArrayList<>(); + while (r.next()) { + id = r.getInt("plot_plot_id"); + owner = r.getString("user_uuid"); + user = uuids.computeIfAbsent(owner, UUID::fromString); + Plot plot = plots.get(id); + if (plot != null) { + plot.getDenied().add(user); + } else if (Settings.Enabled_Components.DATABASE_PURGER) { + toDelete.add(id); + } else { + PlotSquared.debug("&cENTRY " + id + + " in `plot_denied` does not exist. Create this plot or set `database-purger: true` in the settings.yml."); + } + } + deleteRows(toDelete, this.prefix + "plot_denied", "plot_plot_id"); + } + + try (ResultSet resultSet = statement + .executeQuery("SELECT * FROM `" + this.prefix + "plot_settings`")) { + ArrayList toDelete = new ArrayList<>(); + while (resultSet.next()) { + id = resultSet.getInt("plot_plot_id"); + Plot plot = plots.get(id); + if (plot != null) { + plots.remove(id); + String alias = resultSet.getString("alias"); + if (alias != null) { + plot.getSettings().setAlias(alias); + } + String pos = resultSet.getString("position"); + switch (pos.toLowerCase()) { + case "": + case "default": + case "0,0,0": + case "center": + break; + default: + try { + plot.getSettings().setPosition(BlockLoc.fromString(pos)); + } catch (Exception ignored) { + } + } + int m = resultSet.getInt("merged"); + boolean[] merged = new boolean[4]; + for (int i = 0; i < 4; i++) { + merged[3 - i] = (m & 1 << i) != 0; + } + plot.getSettings().setMerged(merged); + String[] flags_string; + String myflags = resultSet.getString("flags"); + if (myflags == null || myflags.isEmpty()) { + flags_string = new String[]{}; + } else { + flags_string = myflags.split(","); + } + HashMap, Object> flags = new HashMap<>(); + boolean exception = false; + for (String element : flags_string) { + if (element.contains(":")) { + String[] split = element.split(":"); + try { + String flag_str = + split[1].replaceAll("¯", ":").replaceAll("\u00B4", ","); + Flag flag = FlagManager.getOrCreateFlag(split[0]); + flags.put(flag, flag.parseValue(flag_str)); + } catch (Exception e) { + e.printStackTrace(); + exception = true; + } + } else { + element = + element.replaceAll("\u00AF", ":").replaceAll("\u00B4", ","); + if (StringMan + .isAlpha(element.replaceAll("_", "").replaceAll("-", ""))) { + Flag flag = FlagManager.getOrCreateFlag(element); + if (flag == null) { + flag = new StringFlag(element) { + @Override + public String getValueDescription() { + return "Generic Filler Flag"; + } + }; + } + flags.put(flag, flag.parseValue("")); + } else { + PlotSquared.debug("INVALID FLAG: " + element); + } + } + } + if (exception) { + PlotSquared.debug("&cPlot #" + id + "(" + plot + ") | " + plot + + " had an invalid flag. A fix has been attempted."); + PlotSquared.debug("&c" + myflags); + this.setFlags(plot, flags); + } + plot.getSettings().flags = flags; + } else if (Settings.Enabled_Components.DATABASE_PURGER) { + toDelete.add(id); + } else { + PlotSquared.debug("&cENTRY #" + id + "(" + plot + + ") in `plot_settings` does not exist. Create this plot or set `database-purger: true` in the settings" + + ".yml."); + } + } + deleteRows(toDelete, this.prefix + "plot_settings", "plot_plot_id"); + } + } + if (!plots.entrySet().isEmpty()) { + createEmptySettings(new ArrayList<>(plots.keySet()), null); + for (Entry entry : plots.entrySet()) { + entry.getValue().getSettings(); + } + } + boolean invalidPlot = false; + for (Entry entry : noExist.entrySet()) { + String worldName = entry.getKey(); + invalidPlot = true; + PlotSquared.debug("&c[WARNING] Found " + entry.getValue().intValue() + + " plots in DB for non existent world; '" + worldName + "'."); + } + if (invalidPlot) { + PlotSquared.debug( + "&c[WARNING] - Please create the world/s or remove the plots using the purge command"); + } + } catch (SQLException e) { + PlotSquared.debug("&7[WARN] Failed to load plots."); + e.printStackTrace(); } + return newPlots; + } + + @Override + public void setMerged(final Plot plot, final boolean[] merged) { + plot.getSettings().setMerged(merged); + addPlotTask(plot, new UniqueStatement("setMerged") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + int hash = MainUtil.hash(merged); + stmt.setInt(1, hash); + stmt.setInt(2, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "plot_settings` SET `merged` = ? WHERE `plot_plot_id` = ?"); + } + }); + } + + @Override + public void swapPlots(Plot plot1, Plot plot2) { + final int id1 = getId(plot1); + final int id2 = getId(plot2); + final PlotId pos1 = plot1.getId(); + final PlotId pos2 = plot2.getId(); + addPlotTask(plot1, new UniqueStatement("swapPlots") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, pos2.x); + stmt.setInt(2, pos2.y); + stmt.setInt(3, id1); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "plot` SET `plot_id_x` = ?, `plot_id_z` = ? WHERE `id` = ?"); + } + }); + addPlotTask(plot2, new UniqueStatement("swapPlots") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, pos1.x); + stmt.setInt(2, pos1.y); + stmt.setInt(3, id2); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "plot` SET `plot_id_x` = ?, `plot_id_z` = ? WHERE `id` = ?"); + } + }); + } + + @Override + public void movePlot(final Plot original, final Plot newPlot) { + addPlotTask(original, new UniqueStatement("movePlot") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, newPlot.getId().x); + stmt.setInt(2, newPlot.getId().y); + stmt.setString(3, newPlot.getArea().toString()); + stmt.setInt(4, getId(original)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "plot` SET `plot_id_x` = ?, `plot_id_z` = ?, `world` = ? WHERE `id` = ?"); + } + }); + addPlotTask(newPlot, null); + } + + @Override + public void setFlags(final Plot plot, HashMap, Object> flags) { + final String flag_string = FlagManager.toString(flags); + addPlotTask(plot, new UniqueStatement("setFlags") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setString(1, flag_string); + stmt.setInt(2, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "plot_settings` SET `flags` = ? WHERE `plot_plot_id` = ?"); + } + }); + } + + @Override + public void setAlias(final Plot plot, final String alias) { + addPlotTask(plot, new UniqueStatement("setAlias") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setString(1, alias); + stmt.setInt(2, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "plot_settings` SET `alias` = ? WHERE `plot_plot_id` = ?"); + } + }); + } + + /** + * Purge all plots with the following database IDs + */ + @Override + public void purgeIds(final Set uniqueIds) { + addGlobalTask(() -> { + if (!uniqueIds.isEmpty()) { + try { + ArrayList uniqueIdsList = new ArrayList<>(uniqueIds); + String stmt_prefix = ""; + int size = uniqueIdsList.size(); + int packet = 990; + int amount = size / packet; + int count = 0; + int last = -1; + for (int j = 0; j <= amount; j++) { + PlotSquared.debug("Purging " + (j * packet) + " / " + size); + List subList = + uniqueIdsList.subList(j * packet, Math.min(size, (j + 1) * packet)); + if (subList.isEmpty()) { + break; + } + StringBuilder idstr2 = new StringBuilder(); + stmt_prefix = ""; + for (Integer id : subList) { + idstr2.append(stmt_prefix).append(id); + stmt_prefix = " OR `id` = "; + } + stmt_prefix = ""; + StringBuilder idstr = new StringBuilder(); + for (Integer id : subList) { + idstr.append(stmt_prefix).append(id); + stmt_prefix = " OR `plot_plot_id` = "; + } + PreparedStatement stmt = SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_helpers` WHERE `plot_plot_id` = " + idstr); + stmt.executeUpdate(); + stmt.close(); + stmt = SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_denied` WHERE `plot_plot_id` = " + idstr); + stmt.executeUpdate(); + stmt.close(); + stmt = SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_settings` WHERE `plot_plot_id` = " + idstr); + stmt.executeUpdate(); + stmt.close(); + stmt = SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_trusted` WHERE `plot_plot_id` = " + idstr); + stmt.executeUpdate(); + stmt.close(); + stmt = SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + "plot` WHERE `id` = " + + idstr2); + stmt.executeUpdate(); + stmt.close(); + commit(); + } + } catch (SQLException e) { + e.printStackTrace(); + PlotSquared.debug("&c[ERROR] FAILED TO PURGE PLOTS!"); + return; + } + } + PlotSquared.debug("&6[INFO] SUCCESSFULLY PURGED " + uniqueIds.size() + " PLOTS!"); + }); + } + + @Override + public void purge(final PlotArea area, final Set plots) { + addGlobalTask(() -> { + try (PreparedStatement stmt = SQLManager.this.connection.prepareStatement( + "SELECT `id`, `plot_id_x`, `plot_id_z` FROM `" + SQLManager.this.prefix + + "plot` WHERE `world` = ?")) { + stmt.setString(1, area.toString()); + Set ids; + try (ResultSet r = stmt.executeQuery()) { + ids = new HashSet<>(); + while (r.next()) { + PlotId plot_id = + new PlotId(r.getInt("plot_id_x"), r.getInt("plot_id_z")); + if (plots.contains(plot_id)) { + ids.add(r.getInt("id")); + } + } + } + purgeIds(ids); + } catch (SQLException e) { + e.printStackTrace(); + PlotSquared.debug("&c[ERROR] FAILED TO PURGE AREA '" + area + "'!"); + } + for (Iterator iterator = plots.iterator(); iterator.hasNext(); ) { + PlotId plotId = iterator.next(); + iterator.remove(); + PlotId id = new PlotId(plotId.x, plotId.y); + area.removePlot(id); + } + }); + } + + @Override + public void setPosition(final Plot plot, final String position) { + addPlotTask(plot, new UniqueStatement("setPosition") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setString(1, position == null ? "" : position); + stmt.setInt(2, getId(plot)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "plot_settings` SET `position` = ? WHERE `plot_plot_id` = ?"); + } + }); + } + + @Override + public void removeComment(final Plot plot, final PlotComment comment) { + addPlotTask(plot, new UniqueStatement("removeComment") { + @Override + public void set(PreparedStatement statement) throws SQLException { + if (plot != null) { + statement.setString(1, plot.getArea().toString()); + statement.setInt(2, plot.getId().hashCode()); + statement.setString(3, comment.comment); + statement.setString(4, comment.inbox); + statement.setString(5, comment.senderName); + } else { + statement.setString(1, comment.comment); + statement.setString(2, comment.inbox); + statement.setString(3, comment.senderName); + } + } + + @Override + public PreparedStatement get() throws SQLException { + if (plot != null) { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_comments` WHERE `world` = ? AND `hashcode` = ? AND `comment` = ? AND `inbox` = ? AND `sender` = ?"); + } + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_comments` WHERE `comment` = ? AND `inbox` = ? AND `sender` = ?"); + } + }); + } + + @Override + public void clearInbox(final Plot plot, final String inbox) { + addPlotTask(plot, new UniqueStatement("clearInbox") { + @Override + public void set(PreparedStatement statement) throws SQLException { + if (plot != null) { + statement.setString(1, plot.getArea().toString()); + statement.setInt(2, plot.getId().hashCode()); + statement.setString(3, inbox); + } else { + statement.setString(1, inbox); + } + } + + @Override + public PreparedStatement get() throws SQLException { + if (plot != null) { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_comments` WHERE `world` = ? AND `hashcode` = ? AND `inbox` = ?"); + } + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + "plot_comments` `inbox` = ?"); + } + }); + } + + @Override + public void getComments(final Plot plot, final String inbox, + final RunnableVal> whenDone) { + addPlotTask(plot, new UniqueStatement("getComments_" + plot) { + @Override + public void set(PreparedStatement statement) throws SQLException { + if (plot != null) { + statement.setString(1, plot.getArea().toString()); + statement.setInt(2, plot.getId().hashCode()); + statement.setString(3, inbox); + } else { + statement.setString(1, inbox); + } + } + + @Override + public PreparedStatement get() throws SQLException { + if (plot != null) { + return SQLManager.this.connection.prepareStatement( + "SELECT * FROM `" + SQLManager.this.prefix + + "plot_comments` WHERE `world` = ? AND `hashcode` = ? AND `inbox` = ?"); + } + return SQLManager.this.connection.prepareStatement( + "SELECT * FROM `" + SQLManager.this.prefix + + "plot_comments` WHERE `inbox` = ?"); + } + + @Override + public void execute(PreparedStatement statement) { + } + + @Override + public void addBatch(PreparedStatement statement) throws SQLException { + ArrayList comments = new ArrayList<>(); + try (ResultSet set = statement.executeQuery()) { + while (set.next()) { + String sender = set.getString("sender"); + String world = set.getString("world"); + int hash = set.getInt("hashcode"); + PlotId id; + if (hash != 0) { + id = PlotId.unpair(hash); + } else { + id = null; + } + String msg = set.getString("comment"); + long timestamp = set.getInt("timestamp") * 1000; + PlotComment comment = + new PlotComment(world, id, msg, sender, inbox, timestamp); + comments.add(comment); + whenDone.value = comments; + } + } + TaskManager.runTask(whenDone); + } + }); + } + + @Override + public void setComment(final Plot plot, final PlotComment comment) { + addPlotTask(plot, new UniqueStatement("setComment") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setString(1, plot.getArea().toString()); + statement.setInt(2, plot.getId().hashCode()); + statement.setString(3, comment.comment); + statement.setString(4, comment.inbox); + statement.setInt(5, (int) (comment.timestamp / 1000)); + statement.setString(6, comment.senderName); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "plot_comments` (`world`, `hashcode`, `comment`, `inbox`, `timestamp`, `sender`) VALUES(?,?,?,?,?,?)"); + } + }); + } + + @Override + public void removeTrusted(final Plot plot, final UUID uuid) { + addPlotTask(plot, new UniqueStatement("removeTrusted") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getId(plot)); + statement.setString(2, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_helpers` WHERE `plot_plot_id` = ? AND `user_uuid` = ?"); + } + }); + } + + @Override + public void removeMember(final Plot plot, final UUID uuid) { + addPlotTask(plot, new UniqueStatement("removeMember") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getId(plot)); + statement.setString(2, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_trusted` WHERE `plot_plot_id` = ? AND `user_uuid` = ?"); + } + }); + } + + @Override + public void setTrusted(final Plot plot, final UUID uuid) { + addPlotTask(plot, new UniqueStatement("setTrusted") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getId(plot)); + statement.setString(2, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "plot_helpers` (`plot_plot_id`, `user_uuid`) VALUES(?,?)"); + } + }); + } + + @Override + public void setMember(final Plot plot, final UUID uuid) { + addPlotTask(plot, new UniqueStatement("setMember") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getId(plot)); + statement.setString(2, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "plot_trusted` (`plot_plot_id`, `user_uuid`) VALUES(?,?)"); + } + }); + } + + @Override + public void removeDenied(final Plot plot, final UUID uuid) { + addPlotTask(plot, new UniqueStatement("removeDenied") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getId(plot)); + statement.setString(2, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "plot_denied` WHERE `plot_plot_id` = ? AND `user_uuid` = ?"); + } + }); + } + + @Override + public void setDenied(final Plot plot, final UUID uuid) { + addPlotTask(plot, new UniqueStatement("setDenied") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getId(plot)); + statement.setString(2, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "plot_denied` (`plot_plot_id`, `user_uuid`) VALUES(?,?)"); + } + }); + } + + @Override + public HashMap getRatings(Plot plot) { + HashMap map = new HashMap<>(); + try (PreparedStatement statement = this.connection.prepareStatement( + "SELECT `rating`, `player` FROM `" + this.prefix + + "plot_rating` WHERE `plot_plot_id` = ? ")) { + statement.setInt(1, getId(plot)); + try (ResultSet resultSet = statement.executeQuery()) { + while (resultSet.next()) { + UUID uuid = UUID.fromString(resultSet.getString("player")); + int rating = resultSet.getInt("rating"); + map.put(uuid, rating); + } + } + } catch (SQLException e) { + PlotSquared + .debug("&7[WARN] Failed to fetch rating for plot " + plot.getId().toString()); + e.printStackTrace(); + } + return map; + } + + @Override + public void setRating(final Plot plot, final UUID rater, final int value) { + addPlotTask(plot, new UniqueStatement("setRating") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getId(plot)); + statement.setInt(2, value); + statement.setString(3, rater.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "plot_rating` (`plot_plot_id`, `rating`, `player`) VALUES(?,?,?)"); + } + }); + } + + @Override + public void delete(PlotCluster cluster) { + final int id = getClusterId(cluster); + addClusterTask(cluster, new UniqueStatement("delete_cluster_settings") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, id); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "cluster_settings` WHERE `cluster_id` = ?"); + } + }); + addClusterTask(cluster, new UniqueStatement("delete_cluster_helpers") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, id); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "cluster_helpers` WHERE `cluster_id` = ?"); + } + }); + addClusterTask(cluster, new UniqueStatement("delete_cluster_invited") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, id); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "cluster_invited` WHERE `cluster_id` = ?"); + } + }); + addClusterTask(cluster, new UniqueStatement("delete_cluster") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, id); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + "cluster` WHERE `id` = ?"); + } + }); + } + + @Override + public void addPersistentMeta(final UUID uuid, final String key, final byte[] meta, + final boolean replace) { + addPlayerTask(uuid, new UniqueStatement("addPersistentMeta") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + if (replace) { + stmt.setBytes(1, meta); + stmt.setString(2, uuid.toString()); + stmt.setString(3, key); + } else { + stmt.setString(1, uuid.toString()); + stmt.setString(2, key); + stmt.setBytes(3, meta); + } + } + + @Override + public PreparedStatement get() throws SQLException { + if (replace) { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "player_meta` SET `value` = ? WHERE `uuid` = ? AND `key` = ?"); + } else { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "player_meta`(`uuid`, `key`, `value`) VALUES(?, ? ,?)"); + } + } + }); + } + + @Override + public void removePersistentMeta(final UUID uuid, final String key) { + addPlayerTask(uuid, new UniqueStatement("removePersistentMeta") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setString(1, uuid.toString()); + stmt.setString(2, key); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "player_meta` WHERE `uuid` = ? AND `key` = ?"); + } + }); + } + + @Override + public void getPersistentMeta(final UUID uuid, final RunnableVal> result) { + addPlayerTask(uuid, new UniqueStatement("getPersistentMeta") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setString(1, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "SELECT * FROM `" + SQLManager.this.prefix + + "player_meta` WHERE `uuid` = ? ORDER BY `meta_id` ASC"); + } + + @Override + public void execute(PreparedStatement statement) { + } + + @Override + public void addBatch(PreparedStatement statement) throws SQLException { + ResultSet resultSet = statement.executeQuery(); + + final Map metaMap = new HashMap<>(); + + while (resultSet.next()) { + String key = resultSet.getString("key"); + byte[] bytes = resultSet.getBytes("value"); + metaMap.put(key, bytes); + } + + resultSet.close(); + TaskManager.runTaskAsync(() -> result.run(metaMap)); + } + + }); + } + + @Override + public HashMap> getClusters() { + LinkedHashMap> newClusters = new LinkedHashMap<>(); + HashMap clusters = new HashMap<>(); + try { + HashSet areas = new HashSet<>(); + if (PlotSquared.get().worlds.contains("worlds")) { + ConfigurationSection worldSection = + PlotSquared.get().worlds.getConfigurationSection("worlds"); + if (worldSection != null) { + for (String worldKey : worldSection.getKeys(false)) { + areas.add(worldKey); + ConfigurationSection areaSection = + worldSection.getConfigurationSection(worldKey + ".areas"); + if (areaSection != null) { + for (String areaKey : areaSection.getKeys(false)) { + String[] split = areaKey.split("(? uuids = new HashMap<>(); + HashMap noExist = new HashMap<>(); + /* + * Getting clusters + */ + try (Statement stmt = this.connection.createStatement()) { + ResultSet resultSet = + stmt.executeQuery("SELECT * FROM `" + this.prefix + "cluster`"); + PlotCluster cluster; + String owner; + UUID user; + int id; + while (resultSet.next()) { + PlotId pos1 = + new PlotId(resultSet.getInt("pos1_x"), resultSet.getInt("pos1_z")); + PlotId pos2 = + new PlotId(resultSet.getInt("pos2_x"), resultSet.getInt("pos2_z")); + id = resultSet.getInt("id"); + String areaid = resultSet.getString("world"); + if (!areas.contains(areaid)) { + if (noExist.containsKey(areaid)) { + noExist.put(areaid, noExist.get(areaid) + 1); + } else { + noExist.put(areaid, 1); + } + } + owner = resultSet.getString("owner"); + user = uuids.computeIfAbsent(owner, UUID::fromString); + cluster = new PlotCluster(null, pos1, pos2, user, id); + clusters.put(id, cluster); + Set set = newClusters + .computeIfAbsent(areaid, k -> new HashSet<>()); + set.add(cluster); + } + //Getting helpers + resultSet = stmt.executeQuery( + "SELECT `user_uuid`, `cluster_id` FROM `" + this.prefix + "cluster_helpers`"); + while (resultSet.next()) { + id = resultSet.getInt("cluster_id"); + owner = resultSet.getString("user_uuid"); + user = uuids.computeIfAbsent(owner,UUID::fromString); + cluster = clusters.get(id); + if (cluster != null) { + cluster.helpers.add(user); + } else { + PlotSquared.debug("&cCluster #" + id + "(" + cluster + + ") in cluster_helpers does not exist. Please create the cluster or remove this entry."); + } + } + // Getting invited + resultSet = stmt.executeQuery( + "SELECT `user_uuid`, `cluster_id` FROM `" + this.prefix + "cluster_invited`"); + while (resultSet.next()) { + id = resultSet.getInt("cluster_id"); + owner = resultSet.getString("user_uuid"); + user = uuids.computeIfAbsent(owner,UUID::fromString); + cluster = clusters.get(id); + if (cluster != null) { + cluster.invited.add(user); + } else { + PlotSquared.debug("&cCluster #" + id + "(" + cluster + + ") in cluster_invited does not exist. Please create the cluster or remove this entry."); + } + } + resultSet = + stmt.executeQuery("SELECT * FROM `" + this.prefix + "cluster_settings`"); + while (resultSet.next()) { + id = resultSet.getInt("cluster_id"); + cluster = clusters.get(id); + if (cluster != null) { + String alias = resultSet.getString("alias"); + if (alias != null) { + cluster.settings.setAlias(alias); + } + String pos = resultSet.getString("position"); + switch (pos.toLowerCase()) { + case "": + case "default": + case "0,0,0": + case "center": + break; + default: + try { + BlockLoc loc = BlockLoc.fromString(pos); + cluster.settings.setPosition(loc); + } catch (Exception ignored) { + } + } + int m = resultSet.getInt("merged"); + boolean[] merged = new boolean[4]; + for (int i = 0; i < 4; i++) { + merged[3 - i] = (m & 1 << i) != 0; + } + cluster.settings.setMerged(merged); + String[] flags_string; + String myflags = resultSet.getString("flags"); + if (myflags == null || myflags.isEmpty()) { + flags_string = new String[]{}; + } else { + flags_string = myflags.split(","); + } + HashMap, Object> flags = new HashMap<>(); + for (String element : flags_string) { + if (element.contains(":")) { + String[] split = element.split(":"); + String flag_str = + split[1].replaceAll("\u00AF", ":").replaceAll("´", ","); + Flag flag = FlagManager.getOrCreateFlag(split[0]); + if (flag == null) { + flag = new StringFlag(split[0]) { + @Override + public String getValueDescription() { + return "Generic Filler Flag"; + } + }; + } + flags.put(flag, flag.parseValue(flag_str)); + } else { + Flag flag = FlagManager.getOrCreateFlag(element); + if (flag == null) { + flag = new StringFlag(element) { + @Override + public String getValueDescription() { + return "Generic Filler Flag"; + } + }; + } + flags.put(flag, flag.parseValue("")); + } + } + cluster.settings.flags = flags; + } else { + PlotSquared.debug("&cCluster #" + id + "(" + cluster + + ") in cluster_settings does not exist. Please create the cluster or remove this entry."); + } + } + resultSet.close(); + } + boolean invalidPlot = false; + for (Entry entry : noExist.entrySet()) { + String a = entry.getKey(); + invalidPlot = true; + PlotSquared.debug("&c[WARNING] Found " + noExist.get(a) + + " clusters in DB for non existent area; '" + a + "'."); + } + if (invalidPlot) { + PlotSquared.debug( + "&c[WARNING] - Please create the world/s or remove the clusters using the purge command"); + } + } catch (SQLException e) { + PlotSquared.debug("&7[WARN] Failed to load clusters."); + e.printStackTrace(); + } + return newClusters; + } + + @Override + public void setClusterName(final PlotCluster cluster, final String name) { + addClusterTask(cluster, new UniqueStatement("setClusterName") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setString(1, name); + stmt.setInt(2, getClusterId(cluster)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "cluster_settings` SET `alias` = ? WHERE `cluster_id` = ?"); + } + }); + cluster.settings.setAlias(name); + } + + @Override + public void removeHelper(final PlotCluster cluster, final UUID uuid) { + addClusterTask(cluster, new UniqueStatement("removeHelper") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getClusterId(cluster)); + statement.setString(2, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "cluster_helpers` WHERE `cluster_id` = ? AND `user_uuid` = ?"); + } + }); + } + + @Override + public void setHelper(final PlotCluster cluster, final UUID uuid) { + addClusterTask(cluster, new UniqueStatement("setHelper") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getClusterId(cluster)); + statement.setString(2, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "cluster_helpers` (`cluster_id`, `user_uuid`) VALUES(?,?)"); + } + }); + } + + @Override + public void createCluster(final PlotCluster cluster) { + addClusterTask(cluster, new UniqueStatement("createCluster_" + cluster.hashCode()) { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, cluster.getP1().x); + stmt.setInt(2, cluster.getP1().y); + stmt.setInt(3, cluster.getP2().x); + stmt.setInt(4, cluster.getP2().y); + stmt.setString(5, cluster.owner.toString()); + stmt.setString(6, cluster.area.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement(SQLManager.this.CREATE_CLUSTER, + Statement.RETURN_GENERATED_KEYS); + } + + @Override + public void execute(PreparedStatement statement) { + } + + @Override + public void addBatch(PreparedStatement statement) throws SQLException { + statement.executeUpdate(); + try (ResultSet keys = statement.getGeneratedKeys()) { + if (keys.next()) { + cluster.temp = keys.getInt(1); + } + } + } + }); + addClusterTask(cluster, + new UniqueStatement("createCluster_settings_" + cluster.hashCode()) { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, getClusterId(cluster)); + stmt.setString(2, cluster.getAlias()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "cluster_settings`(`cluster_id`, `alias`) VALUES(?, ?)"); + } + }); + } + + @Override + public void resizeCluster(final PlotCluster current, PlotId min, PlotId max) { + final PlotId pos1 = new PlotId(current.getP1().x, current.getP1().y); + final PlotId pos2 = new PlotId(current.getP2().x, current.getP2().y); + current.setP1(min); + current.setP2(max); + + addClusterTask(current, new UniqueStatement("resizeCluster") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setInt(1, pos1.x); + stmt.setInt(2, pos1.y); + stmt.setInt(3, pos2.x); + stmt.setInt(4, pos2.y); + stmt.setInt(5, getClusterId(current)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "cluster` SET `pos1_x` = ?, `pos1_z` = ?, `pos2_x` = ?, `pos2_z` = ? WHERE `id` = ?"); + } + }); + } + + @Override + public void setPosition(final PlotCluster cluster, final String position) { + addClusterTask(cluster, new UniqueStatement("setPosition") { + @Override + public void set(PreparedStatement stmt) throws SQLException { + stmt.setString(1, position); + stmt.setInt(2, getClusterId(cluster)); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "cluster_settings` SET `position` = ? WHERE `cluster_id` = ?"); + } + }); + } + + @Override + public void removeInvited(final PlotCluster cluster, final UUID uuid) { + addClusterTask(cluster, new UniqueStatement("removeInvited") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getClusterId(cluster)); + statement.setString(2, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "DELETE FROM `" + SQLManager.this.prefix + + "cluster_invited` WHERE `cluster_id` = ? AND `user_uuid` = ?"); + } + }); + } + + @Override + public void setInvited(final PlotCluster cluster, final UUID uuid) { + addClusterTask(cluster, new UniqueStatement("setInvited") { + @Override + public void set(PreparedStatement statement) throws SQLException { + statement.setInt(1, getClusterId(cluster)); + statement.setString(2, uuid.toString()); + } + + @Override + public PreparedStatement get() throws SQLException { + return SQLManager.this.connection.prepareStatement( + "INSERT INTO `" + SQLManager.this.prefix + + "cluster_invited` (`cluster_id`, `user_uuid`) VALUES(?,?)"); + } + }); + } + + @Override + public boolean deleteTables() { + try (Statement stmt = this.connection.createStatement(); + PreparedStatement statement = this.connection + .prepareStatement("DROP TABLE `" + this.prefix + "plot`")) { + close(); + this.closed = false; + SQLManager.this.connection = this.database.forceConnection(); + stmt.addBatch("DROP TABLE `" + this.prefix + "cluster_invited`"); + stmt.addBatch("DROP TABLE `" + this.prefix + "cluster_helpers`"); + stmt.addBatch("DROP TABLE `" + this.prefix + "cluster`"); + stmt.addBatch("DROP TABLE `" + this.prefix + "plot_rating`"); + stmt.addBatch("DROP TABLE `" + this.prefix + "plot_settings`"); + stmt.addBatch("DROP TABLE `" + this.prefix + "plot_comments`"); + stmt.addBatch("DROP TABLE `" + this.prefix + "plot_trusted`"); + stmt.addBatch("DROP TABLE `" + this.prefix + "plot_helpers`"); + stmt.addBatch("DROP TABLE `" + this.prefix + "plot_denied`"); + stmt.executeBatch(); + stmt.clearBatch(); + statement.executeUpdate(); + } catch (ClassNotFoundException | SQLException e) { + e.printStackTrace(); + + } + return true; + } + + @Override + public void validateAllPlots(Set toValidate) { + if (!isValid()) { + reconnect(); + } + PlotSquared.debug( + "$1All DB transactions during this session are being validated (This may take a while if corrections need to be made)"); + commit(); + while (true) { + if (!sendBatch()) { + break; + } + } + try { + if (this.connection.getAutoCommit()) { + this.connection.setAutoCommit(false); + } + } catch (SQLException e) { + e.printStackTrace(); + } + HashMap> database = getPlots(); + ArrayList toCreate = new ArrayList<>(); + for (Plot plot : toValidate) { + if (plot.temp == -1) { + continue; + } + HashMap worldPlots = database.get(plot.getArea().toString()); + if (worldPlots == null) { + PlotSquared.debug("&8 - &7Creating plot (1): " + plot); + toCreate.add(plot); + continue; + } + Plot dataPlot = worldPlots.remove(plot.getId()); + if (dataPlot == null) { + PlotSquared.debug("&8 - &7Creating plot (2): " + plot); + toCreate.add(plot); + continue; + } + // owner + if (!plot.owner.equals(dataPlot.owner)) { + PlotSquared + .debug("&8 - &7Setting owner: " + plot + " -> " + MainUtil.getName(plot.owner)); + setOwner(plot, plot.owner); + } + // trusted + if (!plot.getTrusted().equals(dataPlot.getTrusted())) { + HashSet toAdd = (HashSet) plot.getTrusted().clone(); + HashSet toRemove = (HashSet) dataPlot.getTrusted().clone(); + toRemove.removeAll(plot.getTrusted()); + toAdd.removeAll(dataPlot.getTrusted()); + PlotSquared.debug( + "&8 - &7Correcting " + (toAdd.size() + toRemove.size()) + " trusted for: " + + plot); + if (!toRemove.isEmpty()) { + for (UUID uuid : toRemove) { + removeTrusted(plot, uuid); + } + } + if (!toAdd.isEmpty()) { + for (UUID uuid : toAdd) { + setTrusted(plot, uuid); + } + } + } + if (!plot.getMembers().equals(dataPlot.getMembers())) { + HashSet toAdd = (HashSet) plot.getMembers().clone(); + HashSet toRemove = (HashSet) dataPlot.getMembers().clone(); + toRemove.removeAll(plot.getMembers()); + toAdd.removeAll(dataPlot.getMembers()); + PlotSquared.debug( + "&8 - &7Correcting " + (toAdd.size() + toRemove.size()) + " members for: " + + plot); + if (!toRemove.isEmpty()) { + for (UUID uuid : toRemove) { + removeMember(plot, uuid); + } + } + if (!toAdd.isEmpty()) { + for (UUID uuid : toAdd) { + setMember(plot, uuid); + } + } + } + if (!plot.getDenied().equals(dataPlot.getDenied())) { + HashSet toAdd = (HashSet) plot.getDenied().clone(); + HashSet toRemove = (HashSet) dataPlot.getDenied().clone(); + toRemove.removeAll(plot.getDenied()); + toAdd.removeAll(dataPlot.getDenied()); + PlotSquared.debug( + "&8 - &7Correcting " + (toAdd.size() + toRemove.size()) + " denied for: " + + plot); + if (!toRemove.isEmpty()) { + for (UUID uuid : toRemove) { + removeDenied(plot, uuid); + } + } + if (!toAdd.isEmpty()) { + for (UUID uuid : toAdd) { + setDenied(plot, uuid); + } + } + } + boolean[] pm = plot.getMerged(); + boolean[] dm = dataPlot.getMerged(); + if (pm[0] != dm[0] || pm[1] != dm[1]) { + PlotSquared.debug("&8 - &7Correcting merge for: " + plot); + setMerged(dataPlot, plot.getMerged()); + } + HashMap, Object> pf = plot.getFlags(); + HashMap, Object> df = dataPlot.getFlags(); + if (!pf.isEmpty() && !df.isEmpty()) { + if (pf.size() != df.size() || !StringMan + .isEqual(StringMan.joinOrdered(pf.values(), ","), + StringMan.joinOrdered(df.values(), ","))) { + PlotSquared.debug("&8 - &7Correcting flags for: " + plot); + setFlags(plot, pf); + } + } + } + + for (Entry> entry : database.entrySet()) { + HashMap map = entry.getValue(); + if (!map.isEmpty()) { + for (Entry entry2 : map.entrySet()) { + PlotSquared.debug("$1Plot was deleted: " + entry2.getValue().toString() + + "// TODO implement this when sure safe"); + } + } + } + commit(); + } + + @Override + public void replaceWorld(final String oldWorld, final String newWorld, final PlotId min, + final PlotId max) { + addGlobalTask(() -> { + if (min == null) { + try (PreparedStatement stmt = SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "plot` SET `world` = ? WHERE `world` = ?")) { + stmt.setString(1, newWorld); + stmt.setString(2, oldWorld); + stmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + try (PreparedStatement stmt = SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "cluster` SET `world` = ? WHERE `world` = ?")) { + stmt.setString(1, newWorld); + stmt.setString(2, oldWorld); + stmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + } else { + try (PreparedStatement stmt = SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "plot` SET `world` = ? WHERE `world` = ? AND `plot_id_x` BETWEEN ? AND ? AND `plot_id_z` BETWEEN ? AND ?")) { + stmt.setString(1, newWorld); + stmt.setString(2, oldWorld); + stmt.setInt(3, min.x); + stmt.setInt(4, max.x); + stmt.setInt(5, min.y); + stmt.setInt(6, max.y); + stmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + try (PreparedStatement stmt = SQLManager.this.connection.prepareStatement( + "UPDATE `" + SQLManager.this.prefix + + "cluster` SET `world` = ? WHERE `world` = ? AND `pos1_x` <= ? AND `pos1_z` <= ? AND `pos2_x` >= ? AND `pos2_z` >= ?")) { + stmt.setString(1, newWorld); + stmt.setString(2, oldWorld); + stmt.setInt(3, max.x); + stmt.setInt(4, max.y); + stmt.setInt(5, min.x); + stmt.setInt(6, min.y); + stmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + }); + } + + @Override + public void replaceUUID(final UUID old, final UUID now) { + addGlobalTask(() -> { + try (Statement stmt = SQLManager.this.connection.createStatement()) { + stmt.executeUpdate( + "UPDATE `" + SQLManager.this.prefix + "cluster` SET `owner` = '" + now + .toString() + "' WHERE `owner` = '" + old.toString() + '\''); + stmt.executeUpdate( + "UPDATE `" + SQLManager.this.prefix + "cluster_helpers` SET `user_uuid` = '" + + now.toString() + "' WHERE `user_uuid` = '" + old.toString() + '\''); + stmt.executeUpdate( + "UPDATE `" + SQLManager.this.prefix + "cluster_invited` SET `user_uuid` = '" + + now.toString() + "' WHERE `user_uuid` = '" + old.toString() + '\''); + stmt.executeUpdate( + "UPDATE `" + SQLManager.this.prefix + "plot` SET `owner` = '" + now + .toString() + "' WHERE `owner` = '" + old.toString() + '\''); + stmt.executeUpdate( + "UPDATE `" + SQLManager.this.prefix + "plot_denied` SET `user_uuid` = '" + + now.toString() + "' WHERE `user_uuid` = '" + old.toString() + '\''); + stmt.executeUpdate( + "UPDATE `" + SQLManager.this.prefix + "plot_helpers` SET `user_uuid` = '" + + now.toString() + "' WHERE `user_uuid` = '" + old.toString() + '\''); + stmt.executeUpdate( + "UPDATE `" + SQLManager.this.prefix + "plot_trusted` SET `user_uuid` = '" + + now.toString() + "' WHERE `user_uuid` = '" + old.toString() + '\''); + } catch (SQLException e) { + e.printStackTrace(); + } + }); + } + + @Override + public void close() { + try { + this.closed = true; + this.connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public abstract class UniqueStatement { + + public final String method; + + public UniqueStatement(String method) { + this.method = method; + } + + public void addBatch(PreparedStatement statement) throws SQLException { + statement.addBatch(); + } + + public void execute(PreparedStatement statement) throws SQLException { + statement.executeBatch(); + } + + public abstract PreparedStatement get() throws SQLException; + + public abstract void set(PreparedStatement stmt) throws SQLException; + } + + + private class UUIDPair { + + public final int id; + public final UUID uuid; + + public UUIDPair(int id, UUID uuid) { + this.id = id; + this.uuid = uuid; + } + } + + + private class SettingsPair { + + public final int id; + public final PlotSettings settings; + + public SettingsPair(int id, PlotSettings settings) { + this.id = id; + this.settings = settings; + } + } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/SQLite.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/SQLite.java index 3675ad0cd..d42b1d67b 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/SQLite.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/database/SQLite.java @@ -9,7 +9,7 @@ import java.sql.*; /** * Connects to and uses a SQLite database. */ -public class SQLite extends Database { +public class SQLite implements Database { private final String dbLocation; private Connection connection; diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flag/FlagManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flag/FlagManager.java index 06be89e15..2c0746d13 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flag/FlagManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flag/FlagManager.java @@ -114,6 +114,7 @@ public class FlagManager { * @param flag * @return */ + @SuppressWarnings("deprecation") public static V getPlotFlagRaw(Plot plot, Flag flag) { if (plot.owner == null) { return null; @@ -141,13 +142,6 @@ public class FlagManager { return true; } - public static boolean addClusterFlag(PlotCluster cluster, Flag flag, V value) { - getSettingFlag(cluster.area, cluster.settings, flag); - cluster.settings.flags.put(flag, value); - DBFunc.setFlags(cluster, cluster.settings.flags); - return true; - } - /** * Returns a map of the {@link Flag}s and their values for the specified plot. * @@ -217,20 +211,6 @@ public class FlagManager { return true; } - public static boolean removeClusterFlag(PlotCluster cluster, Flag id) { - Object object = cluster.settings.flags.remove(id); - if (object == null) { - return false; - } - boolean result = EventUtil.manager.callFlagRemove(id, object, cluster); - if (!result) { - cluster.settings.flags.put(id, object); - return false; - } - DBFunc.setFlags(cluster, cluster.settings.flags); - return true; - } - public static void setPlotFlags(Plot origin, HashMap, Object> flags) { for (Plot plot : origin.getConnectedPlots()) { if (flags != null && !flags.isEmpty()) { @@ -248,20 +228,6 @@ public class FlagManager { } } - public static void setClusterFlags(PlotCluster cluster, Set flags) { - if (flags != null && !flags.isEmpty()) { - cluster.settings.flags.clear(); - for (Flag flag : flags) { - cluster.settings.flags.put(flag, flag); - } - } else if (cluster.settings.flags.isEmpty()) { - return; - } else { - cluster.settings.flags.clear(); - } - DBFunc.setFlags(cluster, cluster.settings.flags); - } - /** * Get a list of registered {@link Flag} objects based on player permissions. * diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridPlotWorld.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridPlotWorld.java index 0a722b4d6..5466df8bc 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridPlotWorld.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridPlotWorld.java @@ -277,11 +277,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { id = rotate(id); } int pair = MathMan.pair(x, z); - BaseBlock[] existing = this.G_SCH.get(pair); - if (existing == null) { - existing = new BaseBlock[height]; - this.G_SCH.put(pair, existing); - } + BaseBlock[] existing = this.G_SCH.computeIfAbsent(pair, k -> new BaseBlock[height]); existing[y] = id; } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/logger/ILogger.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/logger/ILogger.java index 16fb343bf..3a4645cac 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/logger/ILogger.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/logger/ILogger.java @@ -1,5 +1,6 @@ package com.github.intellectualsites.plotsquared.plot.logger; +@FunctionalInterface public interface ILogger { void log(String message); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Expression.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Expression.java index bb466c082..1214a2769 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Expression.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Expression.java @@ -4,9 +4,12 @@ import com.github.intellectualsites.plotsquared.plot.PlotSquared; import com.github.intellectualsites.plotsquared.plot.commands.DebugExec; import com.github.intellectualsites.plotsquared.plot.commands.MainCommand; +import javax.annotation.Nonnull; import javax.script.ScriptException; public abstract class Expression { + + @Nonnull public static Expression constant(final U value) { return new Expression() { @Override public U evaluate(U arg) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java index 83af645cf..5a6f1c2ba 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/Plot.java @@ -20,6 +20,7 @@ import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableSet; import com.sk89q.jnbt.CompoundTag; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.awt.geom.Area; import java.awt.geom.PathIterator; @@ -32,2971 +33,2880 @@ import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; /** - * The plot class
- * [IMPORTANT] - * - Unclaimed plots will not have persistent information. - * - Any information set/modified in an unclaimed object may not be reflected in other instances - * - Using the `new` operator will create an unclaimed plot instance - * - Use the methods from the PlotArea/PS/Location etc to get existing plots + * The plot class
[IMPORTANT] - Unclaimed plots will not have persistent information. - Any + * information set/modified in an unclaimed object may not be reflected in other instances - Using + * the `new` operator will create an unclaimed plot instance - Use the methods from the + * PlotArea/PS/Location etc to get existing plots */ public class Plot { - /** - * @deprecated raw access is deprecated - */ - @Deprecated private static HashSet connected_cache; - private static HashSet regions_cache; - /** - * The {@link PlotId}. - */ - private final PlotId id; - /** - * plot owner - * (Merged plots can have multiple owners) - * Direct access is Deprecated: use getOwners() - */ - @Deprecated public UUID owner; - /** - * Has the plot changed since the last save cycle? - */ - public boolean countsTowardsMax = true; - /** - * Represents whatever the database manager needs it to:
- * - A value of -1 usually indicates the plot will not be stored in the DB
- * - A value of 0 usually indicates that the DB manager hasn't set a value
- * - * @deprecated magical - */ - @Deprecated public int temp; - /** - * Plot creation timestamp (not accurate if the plot was created before this was implemented)
- * - Milliseconds since the epoch
- */ - private long timestamp; - /** - * List of trusted (with plot permissions). - */ - private HashSet trusted; - /** - * List of members users (with plot permissions). - */ - private HashSet members; - /** - * List of denied players. - */ - private HashSet denied; - /** - * External settings class. - * - Please favor the methods over direct access to this class
- * - The methods are more likely to be left unchanged from version changes
- */ - private PlotSettings settings; - /** - * The {@link PlotArea}. - */ - private PlotArea area; - /** - * Session only plot metadata (session is until the server stops)
- *
- * For persistent metadata use the flag system - * - * @see FlagManager - */ - private ConcurrentHashMap meta; - /** - * The cached origin plot. - * - The origin plot is used for plot grouping and relational data - */ - private Plot origin; + /** + * @deprecated raw access is deprecated + */ + @Deprecated + private static HashSet connected_cache; + private static HashSet regions_cache; + /** + * The {@link PlotId}. + */ + private final PlotId id; + /** + * plot owner (Merged plots can have multiple owners) Direct access is Deprecated: use + * getOwners() + */ + @Deprecated + public UUID owner; + /** + * Has the plot changed since the last save cycle? + */ + public boolean countsTowardsMax = true; + /** + * Represents whatever the database manager needs it to:
- A value of -1 usually indicates + * the plot will not be stored in the DB
- A value of 0 usually indicates that the DB manager + * hasn't set a value
+ * + * @deprecated magical + */ + @Deprecated + public int temp; + /** + * Plot creation timestamp (not accurate if the plot was created before this was implemented)
+ * - Milliseconds since the epoch
+ */ + private long timestamp; + /** + * List of trusted (with plot permissions). + */ + private HashSet trusted; + /** + * List of members users (with plot permissions). + */ + private HashSet members; + /** + * List of denied players. + */ + private HashSet denied; + /** + * External settings class. - Please favor the methods over direct access to this class
- The + * methods are more likely to be left unchanged from version changes
+ */ + private PlotSettings settings; + /** + * The {@link PlotArea}. + */ + @Nonnull + private PlotArea area; + /** + * Session only plot metadata (session is until the server stops)
+ *
+ * For persistent metadata use the flag system + * + * @see FlagManager + */ + private ConcurrentHashMap meta; + /** + * The cached origin plot. - The origin plot is used for plot grouping and relational data + */ + private Plot origin; - /** - * Constructor for a new plot. - * (Only changes after plot.create() will be properly set in the database) - * - * @param area the PlotArea where the plot is located - * @param id the plot id - * @param owner the plot owner - * @see Plot#getPlot(Location) for existing plots - */ - public Plot(PlotArea area, PlotId id, UUID owner) { - this.area = area; - this.id = id; - this.owner = owner; + /** + * Constructor for a new plot. (Only changes after plot.create() will be properly set in the + * database) + * + * @param area the PlotArea where the plot is located + * @param id the plot id + * @param owner the plot owner + * @see Plot#getPlot(Location) for existing plots + */ + public Plot(@Nonnull PlotArea area, PlotId id, UUID owner) { + this.area = area; + this.id = id; + this.owner = owner; + } + + /** + * Constructor for an unowned plot. (Only changes after plot.create() will be properly set in the + * database) + * + * @param area the PlotArea where the plot is located + * @param id the plot id + * @see Plot#getPlot(Location) for existing plots + */ + public Plot(@Nonnull PlotArea area, PlotId id) { + this.area = area; + this.id = id; + } + + /** + * Constructor for a temporary plot (use -1 for temp)
The database will ignore any queries + * regarding temporary plots. Please note that some bulk plot management functions may still + * affect temporary plots (TODO: fix this) + * + * @param area the PlotArea where the plot is located + * @param id the plot id + * @param owner the owner of the plot + * @param temp Represents whatever the database manager needs it to + * @see Plot#getPlot(Location) for existing plots + */ + public Plot(@Nonnull PlotArea area, PlotId id, UUID owner, int temp) { + this.area = area; + this.id = id; + this.owner = owner; + this.temp = temp; + } + + /** + * Constructor for a saved plots (Used by the database manager when plots are fetched) + * + * @param id the plot id + * @param owner the plot owner + * @param trusted the plot trusted players + * @param denied the plot denied players + * @param merged array giving merged plots + * @see Plot#getPlot(Location) for existing plots + */ + public Plot(PlotId id, UUID owner, HashSet trusted, HashSet members, + HashSet denied, String alias, BlockLoc position, Collection flags, + @Nonnull PlotArea area, boolean[] merged, long timestamp, int temp) { + this.id = id; + this.area = area; + this.owner = owner; + this.settings = new PlotSettings(); + this.members = members; + this.trusted = trusted; + this.denied = denied; + this.settings.setAlias(alias); + this.settings.setPosition(position); + this.settings.setMerged(merged); + if (flags != null) { + for (Flag flag : flags) { + this.settings.flags.put(flag, flag); + } } + this.timestamp = timestamp; + this.temp = temp; + } - /** - * Constructor for an unowned plot. - * (Only changes after plot.create() will be properly set in the database) - * - * @param area the PlotArea where the plot is located - * @param id the plot id - * @see Plot#getPlot(Location) for existing plots - */ - public Plot(PlotArea area, PlotId id) { - this.area = area; - this.id = id; + /** + * Get a plot from a string e.g. [area];[id] + * + * @param defaultArea If no area is specified + * @param string plot id/area + id + * @return New or existing plot object + */ + public static Plot fromString(PlotArea defaultArea, String string) { + String[] split = string.split(";|,"); + if (split.length == 2) { + if (defaultArea != null) { + PlotId id = PlotId.fromString(split[0] + ';' + split[1]); + return id != null ? defaultArea.getPlotAbs(id) : null; + } + } else if (split.length == 3) { + PlotArea pa = PlotSquared.get().getPlotArea(split[0], null); + if (pa != null) { + PlotId id = PlotId.fromString(split[1] + ';' + split[2]); + return pa.getPlotAbs(id); + } + } else if (split.length == 4) { + PlotArea pa = PlotSquared.get().getPlotArea(split[0], split[1]); + if (pa != null) { + PlotId id = PlotId.fromString(split[1] + ';' + split[2]); + return pa.getPlotAbs(id); + } } + return null; + } - /** - * Constructor for a temporary plot (use -1 for temp)
- * The database will ignore any queries regarding temporary plots. - * Please note that some bulk plot management functions may still affect temporary plots (TODO: fix this) - * - * @param area the PlotArea where the plot is located - * @param id the plot id - * @param owner the owner of the plot - * @param temp Represents whatever the database manager needs it to - * @see Plot#getPlot(Location) for existing plots - */ - public Plot(PlotArea area, PlotId id, UUID owner, int temp) { - this.area = area; - this.id = id; - this.owner = owner; - this.temp = temp; + /** + * Return a new/cached plot object at a given location. + * + * @param location the location of the plot + * @return plot at location or null + * @see PlotPlayer#getCurrentPlot() if a player is expected here. + */ + public static Plot getPlot(Location location) { + PlotArea pa = PlotSquared.get().getPlotAreaAbs(location); + if (pa != null) { + return pa.getPlot(location); } + return null; + } - /** - * Constructor for a saved plots (Used by the database manager when plots are fetched) - * - * @param id the plot id - * @param owner the plot owner - * @param trusted the plot trusted players - * @param denied the plot denied players - * @param merged array giving merged plots - * @see Plot#getPlot(Location) for existing plots - */ - public Plot(PlotId id, UUID owner, HashSet trusted, HashSet members, - HashSet denied, String alias, BlockLoc position, Collection flags, - PlotArea area, boolean[] merged, long timestamp, int temp) { - this.id = id; - this.area = area; - this.owner = owner; - this.settings = new PlotSettings(); - this.members = members; - this.trusted = trusted; - this.denied = denied; - this.settings.setAlias(alias); - this.settings.setPosition(position); - this.settings.setMerged(merged); - if (flags != null) { - for (Flag flag : flags) { - this.settings.flags.put(flag, flag); - } + public String getWorldName() { + return area.worldname; + } + + /** + * Session only plot metadata (session is until the server stops)
+ *
+ * For persistent metadata use the flag system + * + * @param key metadata key + * @param value metadata value + * @see FlagManager + */ + public void setMeta(String key, Object value) { + if (this.meta == null) { + this.meta = new ConcurrentHashMap<>(); + } + this.meta.put(key, value); + } + + /** + * Get the metadata for a key
+ *
+ * For persistent metadata use the flag system + * + * @param key metadata key to get value for + * @return Object value + */ + public Object getMeta(String key) { + if (this.meta != null) { + return this.meta.get(key); + } + return null; + } + + /** + * Delete the metadata for a key
- metadata is session only - deleting other plugin's metadata + * may cause issues + * + * @param key key to delete + */ + public void deleteMeta(String key) { + if (this.meta != null) { + this.meta.remove(key); + } + } + + /** + * Get the cluster this plot is associated with + * + * @return the PlotCluster object, or null + */ + public PlotCluster getCluster() { + return this.getArea().getCluster(this.id); + } + + /** + * Efficiently get the players currently inside this plot
- Will return an empty list if no + * players are in the plot
- Remember, you can cast a PlotPlayer to it's respective + * implementation (BukkitPlayer, SpongePlayer) to obtain the player object + * + * @return list of PlotPlayer(s) or an empty list + */ + public List getPlayersInPlot() { + ArrayList players = new ArrayList<>(); + for (Entry entry : UUIDHandler.getPlayers().entrySet()) { + PlotPlayer pp = entry.getValue(); + if (this.equals(pp.getCurrentPlot())) { + players.add(pp); + } + } + return players; + } + + /** + * Check if the plot has an owner. + * + * @return false if there is no owner + */ + public boolean hasOwner() { + return this.owner != null; + } + + /** + * Check if a UUID is a plot owner (merged plots may have multiple owners) + * + * @param uuid the player uuid + * @return if the provided uuid is the owner of the plot + */ + public boolean isOwner(UUID uuid) { + if (uuid.equals(this.owner)) { + return true; + } + if (!isMerged()) { + return false; + } + Set connected = getConnectedPlots(); + for (Plot current : connected) { + if (uuid.equals(current.owner)) { + return true; + } + } + return false; + } + + public boolean isOwnerAbs(UUID uuid) { + return uuid.equals(this.owner); + } + + /** + * Get a immutable set of owner UUIDs for a plot (supports multi-owner mega-plots). + * + * @return the plot owners + */ + public Set getOwners() { + if (this.owner == null) { + return ImmutableSet.of(); + } + if (isMerged()) { + Set plots = getConnectedPlots(); + Plot[] array = plots.toArray(new Plot[0]); + ImmutableSet.Builder owners = ImmutableSet.builder(); + UUID last = this.owner; + owners.add(this.owner); + for (Plot current : array) { + if (last == null || current.owner.getMostSignificantBits() != last + .getMostSignificantBits()) { + owners.add(current.owner); + last = current.owner; } - this.timestamp = timestamp; - this.temp = temp; + } + return owners.build(); } + return ImmutableSet.of(this.owner); + } - /** - * Get a plot from a string e.g. [area];[id] - * - * @param defaultArea If no area is specified - * @param string plot id/area + id - * @return New or existing plot object - */ - public static Plot fromString(PlotArea defaultArea, String string) { - String[] split = string.split(";|,"); - if (split.length == 2) { - if (defaultArea != null) { - PlotId id = PlotId.fromString(split[0] + ';' + split[1]); - return id != null ? defaultArea.getPlotAbs(id) : null; - } - } else if (split.length == 3) { - PlotArea pa = PlotSquared.get().getPlotArea(split[0], null); - if (pa != null) { - PlotId id = PlotId.fromString(split[1] + ';' + split[2]); - return pa.getPlotAbs(id); - } - } else if (split.length == 4) { - PlotArea pa = PlotSquared.get().getPlotArea(split[0], split[1]); - if (pa != null) { - PlotId id = PlotId.fromString(split[1] + ';' + split[2]); - return pa.getPlotAbs(id); - } - } - return null; + /** + * Check if the player is either the owner or on the trusted/added list. + * + * @param uuid uuid to check + * @return true if the player is added/trusted or is the owner + */ + public boolean isAdded(UUID uuid) { + if (this.owner == null || getDenied().contains(uuid)) { + return false; } - - /** - * Return a new/cached plot object at a given location. - * - * @param location the location of the plot - * @return plot at location or null - * @see PlotPlayer#getCurrentPlot() if a player is expected here. - */ - public static Plot getPlot(Location location) { - PlotArea pa = PlotSquared.get().getPlotAreaAbs(location); - if (pa != null) { - return pa.getPlot(location); - } - return null; + if (isOwner(uuid)) { + return true; } - - public String getWorldName() { - return area.worldname; + if (getMembers().contains(uuid)) { + return isOnline(); } - - /** - * Session only plot metadata (session is until the server stops)
- *
- * For persistent metadata use the flag system - * - * @param key metadata key - * @param value metadata value - * @see FlagManager - */ - public void setMeta(String key, Object value) { - if (this.meta == null) { - this.meta = new ConcurrentHashMap<>(); - } - this.meta.put(key, value); + if (getTrusted().contains(uuid) || getTrusted().contains(DBFunc.EVERYONE)) { + return true; } - - /** - * Get the metadata for a key
- *
- * For persistent metadata use the flag system - * - * @param key metadata key to get value for - * @return Object value - */ - public Object getMeta(String key) { - if (this.meta != null) { - return this.meta.get(key); - } - return null; + if (getMembers().contains(DBFunc.EVERYONE)) { + return isOnline(); } + return false; + } - /** - * Delete the metadata for a key
- * - metadata is session only - * - deleting other plugin's metadata may cause issues - * - * @param key key to delete - */ - public void deleteMeta(String key) { - if (this.meta != null) { - this.meta.remove(key); - } + /** + * Should the player be denied from entering. + * + * @param uuid uuid to check + * @return boolean false if the player is allowed to enter + */ + public boolean isDenied(UUID uuid) { + return this.denied != null && (this.denied.contains(DBFunc.EVERYONE) && !this.isAdded(uuid) + || !this.isAdded(uuid) && this.denied.contains(uuid)); + } + + /** + * Get the {@link PlotId}. + */ + @Nonnull + public PlotId getId() { + return this.id; + } + + /** + * Get the plot world object for this plot
- The generic PlotArea object can be casted to its + * respective class for more control (e.g. HybridPlotWorld) + * + * @return PlotArea + */ + @Nonnull + public PlotArea getArea() { + return this.area; + } + + /** + * Assign this plot to a plot area.
(Mostly used during startup when worlds are being + * created)
Note: Using this when it doesn't make sense will result in strange behavior + * + * @param area area to assign to + */ + public void setArea(@Nonnull PlotArea area) { + if (this.getArea() == area) { + return; } + this.area.removePlot(this.id); + this.area = area; + area.addPlot(this); + } - /** - * Get the cluster this plot is associated with - * - * @return the PlotCluster object, or null - */ - public PlotCluster getCluster() { - return this.getArea().getCluster(this.id); + /** + * Get the plot manager object for this plot
- The generic PlotManager object can be casted to + * its respective class for more control (e.g. HybridPlotManager) + * + * @return PlotManager + */ + public PlotManager getManager() { + return this.area.getPlotManager(); + } + + /** + * Get or create plot settings. + * + * @return PlotSettings + * @deprecated use equivalent plot method; + */ + @Deprecated + @Nonnull + public PlotSettings getSettings() { + if (this.settings == null) { + this.settings = new PlotSettings(); } + return this.settings; + } - /** - * Efficiently get the players currently inside this plot
- * - Will return an empty list if no players are in the plot
- * - Remember, you can cast a PlotPlayer to it's respective implementation (BukkitPlayer, SpongePlayer) to obtain the player object - * - * @return list of PlotPlayer(s) or an empty list - */ - public List getPlayersInPlot() { - ArrayList players = new ArrayList<>(); - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer pp = entry.getValue(); - if (this.equals(pp.getCurrentPlot())) { - players.add(pp); - } - } - return players; + /** + * Returns true if the plot is not merged, or it is the base plot of multiple merged plots. + * + * @return Boolean + */ + public boolean isBasePlot() { + return !this.isMerged() || this.equals(this.getBasePlot(false)); + } + + /** + * The base plot is an arbitrary but specific connected plot. It is useful for the following:
+ * - Merged plots need to be treated as a single plot for most purposes
- Some data such as + * home location needs to be associated with the group rather than each plot
- If the plot is + * not merged it will return itself.
- The result is cached locally + * + * @return base Plot + */ + public Plot getBasePlot(boolean recalculate) { + if (this.origin != null && !recalculate) { + if (this.equals(this.origin)) { + return this; + } + return this.origin.getBasePlot(false); } - - /** - * Check if the plot has an owner. - * - * @return false if there is no owner - */ - public boolean hasOwner() { - return this.owner != null; + if (!this.isMerged()) { + this.origin = this; + return this.origin; } + this.origin = this; + PlotId min = this.id; + for (Plot plot : this.getConnectedPlots()) { + if (plot.id.y < min.y || plot.id.y == min.y && plot.id.x < min.x) { + this.origin = plot; + min = plot.id; + } + } + for (Plot plot : this.getConnectedPlots()) { + plot.origin = this.origin; + } + return this.origin; + } - /** - * Check if a UUID is a plot owner (merged plots may have multiple owners) - * - * @param uuid the player uuid - * @return if the provided uuid is the owner of the plot - */ - public boolean isOwner(UUID uuid) { - if (uuid.equals(this.owner)) { - return true; - } - if (!isMerged()) { - return false; - } - Set connected = getConnectedPlots(); - for (Plot current : connected) { - if (uuid.equals(current.owner)) { + /** + * Check if the plot is merged in any direction. + * + * @return is the plot merged or not + */ + public boolean isMerged() { + return getSettings().getMerged(0) || getSettings().getMerged(2) || getSettings() + .getMerged(1) || getSettings().getMerged(3); + } + + /** + * Get the timestamp of when the plot was created (unreliable)
- not accurate if the plot was + * created before this was implemented
- Milliseconds since the epoch
+ * + * @return the creation date of the plot + */ + public long getTimestamp() { + if (this.timestamp == 0) { + this.timestamp = System.currentTimeMillis(); + } + return this.timestamp; + } + + /** + * Get if the plot is merged in a direction
------- Actual -------
0 = north
1 = + * east
2 = south
3 = west
----- Artificial -----
4 = north-east
5 = + * south-east
6 = south-west
7 = north-west
----------
Note: A plot that is merged + * north and east will not be merged northeast if the northeast plot is not part of the same + * group
+ * + * @param direction direction to check for merged plot + * @return true if merged in that direction + */ + public boolean getMerged(int direction) { + if (this.settings == null) { + return false; + } + switch (direction) { + case 0: + case 1: + case 2: + case 3: + return this.getSettings().getMerged(direction); + case 7: + int i = direction - 4; + int i2 = 0; + if (this.getSettings().getMerged(i2)) { + if (this.getSettings().getMerged(i)) { + if (this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2)) { + if (this.area.getPlotAbs(this.id.getRelative(i2)).getMerged(i)) { return true; + } } + } } return false; - } + case 4: + case 5: + case 6: + i = direction - 4; + i2 = direction - 3; + return this.getSettings().getMerged(i2) && this.getSettings().getMerged(i) + && this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2) && this.area + .getPlotAbs(this.id.getRelative(i2)).getMerged(i); - public boolean isOwnerAbs(UUID uuid) { - return uuid.equals(this.owner); } + return false; + } - /** - * Get a immutable set of owner UUIDs for a plot (supports multi-owner mega-plots). - * - * @return the plot owners - */ - public Set getOwners() { - if (this.owner == null) { - return ImmutableSet.of(); - } - if (isMerged()) { - Set plots = getConnectedPlots(); - Plot[] array = plots.toArray(new Plot[plots.size()]); - ImmutableSet.Builder owners = ImmutableSet.builder(); - UUID last = this.owner; - owners.add(this.owner); - for (Plot current : array) { - if (last == null || current.owner.getMostSignificantBits() != last - .getMostSignificantBits()) { - owners.add(current.owner); - last = current.owner; - } - } - return owners.build(); - } - return ImmutableSet.of(this.owner); + /** + * Get the denied users. + * + * @return a set of denied users + */ + public HashSet getDenied() { + if (this.denied == null) { + this.denied = new HashSet<>(); } + return this.denied; + } - /** - * Check if the player is either the owner or on the trusted/added list. - * - * @param uuid uuid to check - * @return true if the player is added/trusted or is the owner - */ - public boolean isAdded(UUID uuid) { - if (this.owner == null || getDenied().contains(uuid)) { - return false; - } - if (isOwner(uuid)) { - return true; - } - if (getMembers().contains(uuid)) { - return isOnline(); - } - if (getTrusted().contains(uuid) || getTrusted().contains(DBFunc.EVERYONE)) { - return true; - } - if (getMembers().contains(DBFunc.EVERYONE)) { - return isOnline(); - } + /** + * Set the denied users for this plot. + * + * @param uuids uuids to deny + */ + public void setDenied(Set uuids) { + boolean larger = uuids.size() > getDenied().size(); + HashSet intersection = new HashSet<>(larger ? getDenied() : uuids); + intersection.retainAll(larger ? uuids : getDenied()); + uuids.removeAll(intersection); + HashSet toRemove = new HashSet<>(getDenied()); + toRemove.removeAll(intersection); + for (UUID uuid : toRemove) { + removeDenied(uuid); + } + for (UUID uuid : uuids) { + addDenied(uuid); + } + } + + /** + * Get the trusted users. + * + * @return a set of trusted users + */ + public HashSet getTrusted() { + if (this.trusted == null) { + this.trusted = new HashSet<>(); + } + return this.trusted; + } + + /** + * Set the trusted users for this plot. + * + * @param uuids uuids to trust + */ + public void setTrusted(Set uuids) { + boolean larger = uuids.size() > getTrusted().size(); + HashSet intersection = new HashSet<>(larger ? getTrusted() : uuids); + intersection.retainAll(larger ? uuids : getTrusted()); + uuids.removeAll(intersection); + HashSet toRemove = new HashSet<>(getTrusted()); + toRemove.removeAll(intersection); + for (UUID uuid : toRemove) { + removeTrusted(uuid); + } + for (UUID uuid : uuids) { + addTrusted(uuid); + } + } + + /** + * Get the members + * + * @return a set of members + */ + public HashSet getMembers() { + if (this.members == null) { + this.members = new HashSet<>(); + } + return this.members; + } + + /** + * Set the members for this plot + * + * @param uuids uuids to set member status for + */ + public void setMembers(Set uuids) { + boolean larger = uuids.size() > getMembers().size(); + HashSet intersection = new HashSet<>(larger ? getMembers() : uuids); + intersection.retainAll(larger ? uuids : getMembers()); + uuids.removeAll(intersection); + HashSet toRemove = new HashSet<>(getMembers()); + toRemove.removeAll(intersection); + for (UUID uuid : toRemove) { + removeMember(uuid); + } + for (UUID uuid : uuids) { + addMember(uuid); + } + } + + /** + * Deny someone (updates database as well) + * + * @param uuid the uuid of the player to deny. + */ + public void addDenied(UUID uuid) { + for (Plot current : getConnectedPlots()) { + if (current.getDenied().add(uuid)) { + DBFunc.setDenied(current, uuid); + } + } + } + + /** + * Add someone as a helper (updates database as well) + * + * @param uuid the uuid of the player to trust + */ + public void addTrusted(UUID uuid) { + for (Plot current : getConnectedPlots()) { + if (current.getTrusted().add(uuid)) { + DBFunc.setTrusted(current, uuid); + } + } + } + + /** + * Add someone as a trusted user (updates database as well) + * + * @param uuid the uuid of the player to add as a member + */ + public void addMember(UUID uuid) { + for (Plot current : getConnectedPlots()) { + if (current.getMembers().add(uuid)) { + DBFunc.setMember(current, uuid); + } + } + } + + /** + * Set the plot owner (and update the database) + * + * @param owner uuid to set as owner + */ + public void setOwner(UUID owner) { + if (!hasOwner()) { + this.owner = owner; + create(); + return; + } + if (!isMerged()) { + if (!this.owner.equals(owner)) { + this.owner = owner; + DBFunc.setOwner(this, owner); + } + return; + } + for (Plot current : getConnectedPlots()) { + if (!owner.equals(current.owner)) { + current.owner = owner; + DBFunc.setOwner(current, owner); + } + } + } + + /** + * Set the plot owner (and update the database) + * + * @param owner uuid to set as owner + * @param initiator player initiating set owner + * @return boolean + */ + public boolean setOwner(UUID owner, PlotPlayer initiator) { + boolean result = EventUtil.manager + .callOwnerChange(initiator, this, owner, hasOwner() ? this.owner : null, hasOwner()); + if (!result) { + return false; + } + if (!hasOwner()) { + this.owner = owner; + create(); + return true; + } + if (!isMerged()) { + if (!this.owner.equals(owner)) { + this.owner = owner; + DBFunc.setOwner(this, owner); + } + return true; + } + for (Plot current : getConnectedPlots()) { + if (!owner.equals(current.owner)) { + current.owner = owner; + DBFunc.setOwner(current, owner); + } + } + return true; + } + + /** + * Clear a plot. + * + * @param whenDone A runnable to execute when clearing finishes, or null + * @see this#clear(boolean, boolean, Runnable) + * @see #deletePlot(Runnable) to clear and delete a plot + */ + public void clear(Runnable whenDone) { + this.clear(false, false, whenDone); + } + + public boolean clear(boolean checkRunning, final boolean isDelete, final Runnable whenDone) { + if (checkRunning && this.getRunning() != 0) { + return false; + } + if (isDelete) { + if (!EventUtil.manager.callDelete(this)) { return false; - } - - /** - * Should the player be denied from entering. - * - * @param uuid uuid to check - * @return boolean false if the player is allowed to enter - */ - public boolean isDenied(UUID uuid) { - return this.denied != null && (this.denied.contains(DBFunc.EVERYONE) && !this.isAdded(uuid) - || !this.isAdded(uuid) && this.denied.contains(uuid)); - } - - /** - * Get the {@link PlotId}. - */ - public PlotId getId() { - return this.id; - } - - /** - * Get the plot world object for this plot
- * - The generic PlotArea object can be casted to its respective class for more control (e.g. HybridPlotWorld) - * - * @return PlotArea - */ - public PlotArea getArea() { - return this.area; - } - - /** - * Assign this plot to a plot area.
- * (Mostly used during startup when worlds are being created)
- * Note: Using this when it doesn't make sense will result in strange behavior - * - * @param area area to assign to - */ - public void setArea(PlotArea area) { - if (this.getArea() == area) { - return; - } - if (this.getArea() != null) { - this.area.removePlot(this.id); - } - this.area = area; - area.addPlot(this); - } - - /** - * Get the plot manager object for this plot
- * - The generic PlotManager object can be casted to its respective class for more control (e.g. HybridPlotManager) - * - * @return PlotManager - */ - public PlotManager getManager() { - return this.area.getPlotManager(); - } - - /** - * Get or create plot settings. - * - * @return PlotSettings - * @deprecated use equivalent plot method; - */ - @Deprecated public PlotSettings getSettings() { - if (this.settings == null) { - this.settings = new PlotSettings(); - } - return this.settings; - } - - /** - * Returns true if the plot is not merged, or it is the base - * plot of multiple merged plots. - * - * @return Boolean - */ - public boolean isBasePlot() { - return !this.isMerged() || this.equals(this.getBasePlot(false)); - } - - /** - * The base plot is an arbitrary but specific connected plot. It is useful for the following:
- * - Merged plots need to be treated as a single plot for most purposes
- * - Some data such as home location needs to be associated with the group rather than each plot
- * - If the plot is not merged it will return itself.
- * - The result is cached locally - * - * @return base Plot - */ - public Plot getBasePlot(boolean recalculate) { - if (this.origin != null && !recalculate) { - if (this.equals(this.origin)) { - return this; - } - return this.origin.getBasePlot(false); - } - if (!this.isMerged()) { - this.origin = this; - return this.origin; - } - this.origin = this; - PlotId min = this.id; - for (Plot plot : this.getConnectedPlots()) { - if (plot.id.y < min.y || plot.id.y == min.y && plot.id.x < min.x) { - this.origin = plot; - min = plot.id; - } - } - for (Plot plot : this.getConnectedPlots()) { - plot.origin = this.origin; - } - return this.origin; - } - - /** - * Check if the plot is merged in any direction. - * - * @return is the plot merged or not - */ - public boolean isMerged() { - return getSettings().getMerged(0) || getSettings().getMerged(2) || getSettings() - .getMerged(1) || getSettings().getMerged(3); - } - - /** - * Get the timestamp of when the plot was created (unreliable)
- * - not accurate if the plot was created before this was implemented
- * - Milliseconds since the epoch
- * - * @return the creation date of the plot - */ - public long getTimestamp() { - if (this.timestamp == 0) { - this.timestamp = System.currentTimeMillis(); - } - return this.timestamp; - } - - /** - * Get if the plot is merged in a direction
- * ------- Actual -------
- * 0 = north
- * 1 = east
- * 2 = south
- * 3 = west
- * ----- Artificial -----
- * 4 = north-east
- * 5 = south-east
- * 6 = south-west
- * 7 = north-west
- * ----------
- * Note: A plot that is merged north and east will not be merged northeast if the northeast plot is not part of the same group
- * - * @param direction direction to check for merged plot - * @return true if merged in that direction - */ - public boolean getMerged(int direction) { - if (this.settings == null) { - return false; - } - switch (direction) { - case 0: - case 1: - case 2: - case 3: - return this.getSettings().getMerged(direction); - case 7: - int i = direction - 4; - int i2 = 0; - if (this.getSettings().getMerged(i2)) { - if (this.getSettings().getMerged(i)) { - if (this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2)) { - if (this.area.getPlotAbs(this.id.getRelative(i2)).getMerged(i)) { - return true; - } - } - } - } - return false; - case 4: - case 5: - case 6: - i = direction - 4; - i2 = direction - 3; - return this.getSettings().getMerged(i2) && this.getSettings().getMerged(i) - && this.area.getPlotAbs(this.id.getRelative(i)).getMerged(i2) && this.area - .getPlotAbs(this.id.getRelative(i2)).getMerged(i); - - } + } + } else { + if (!EventUtil.manager.callClear(this)) { return false; + } } - - /** - * Get the denied users. - * - * @return a set of denied users - */ - public HashSet getDenied() { - if (this.denied == null) { - this.denied = new HashSet<>(); - } - return this.denied; + final HashSet regions = this.getRegions(); + final Set plots = this.getConnectedPlots(); + final ArrayDeque queue = new ArrayDeque<>(plots); + if (isDelete) { + this.removeSign(); } - - /** - * Set the denied users for this plot. - * - * @param uuids uuids to deny - */ - public void setDenied(Set uuids) { - boolean larger = uuids.size() > getDenied().size(); - HashSet intersection = new HashSet<>(larger ? getDenied() : uuids); - intersection.retainAll(larger ? uuids : getDenied()); - uuids.removeAll(intersection); - HashSet toRemove = new HashSet<>(getDenied()); - toRemove.removeAll(intersection); - for (UUID uuid : toRemove) { - removeDenied(uuid); - } - for (UUID uuid : uuids) { - addDenied(uuid); - } - } - - /** - * Get the trusted users. - * - * @return a set of trusted users - */ - public HashSet getTrusted() { - if (this.trusted == null) { - this.trusted = new HashSet<>(); - } - return this.trusted; - } - - /** - * Set the trusted users for this plot. - * - * @param uuids uuids to trust - */ - public void setTrusted(Set uuids) { - boolean larger = uuids.size() > getTrusted().size(); - HashSet intersection = new HashSet<>(larger ? getTrusted() : uuids); - intersection.retainAll(larger ? uuids : getTrusted()); - uuids.removeAll(intersection); - HashSet toRemove = new HashSet<>(getTrusted()); - toRemove.removeAll(intersection); - for (UUID uuid : toRemove) { - removeTrusted(uuid); - } - for (UUID uuid : uuids) { - addTrusted(uuid); - } - } - - /** - * Get the members - * - * @return a set of members - */ - public HashSet getMembers() { - if (this.members == null) { - this.members = new HashSet<>(); - } - return this.members; - } - - /** - * Set the members for this plot - * - * @param uuids uuids to set member status for - */ - public void setMembers(Set uuids) { - boolean larger = uuids.size() > getMembers().size(); - HashSet intersection = new HashSet<>(larger ? getMembers() : uuids); - intersection.retainAll(larger ? uuids : getMembers()); - uuids.removeAll(intersection); - HashSet toRemove = new HashSet<>(getMembers()); - toRemove.removeAll(intersection); - for (UUID uuid : toRemove) { - removeMember(uuid); - } - for (UUID uuid : uuids) { - addMember(uuid); - } - } - - /** - * Deny someone (updates database as well) - * - * @param uuid the uuid of the player to deny. - */ - public void addDenied(UUID uuid) { - for (Plot current : getConnectedPlots()) { - if (current.getDenied().add(uuid)) { - DBFunc.setDenied(current, uuid); + this.unlinkPlot(true, !isDelete); + final PlotManager manager = this.area.getPlotManager(); + Runnable run = new Runnable() { + @Override + public void run() { + if (queue.isEmpty()) { + Runnable run = () -> { + for (RegionWrapper region : regions) { + Location[] corners = region.getCorners(getWorldName()); + ChunkManager.manager.clearAllEntities(corners[0], corners[1]); } + TaskManager.runTask(whenDone); + }; + for (Plot current : plots) { + if (isDelete || current.owner == null) { + manager.unclaimPlot(Plot.this.area, current, null); + } else { + manager.claimPlot(Plot.this.area, current); + } + } + GlobalBlockQueue.IMP.addTask(run); + return; } + Plot current = queue.poll(); + if (Plot.this.area.TERRAIN != 0) { + ChunkManager.manager + .regenerateRegion(current.getBottomAbs(), current.getTopAbs(), false, this); + return; + } + manager.clearPlot(Plot.this.area, current, this); + } + }; + run.run(); + return true; + } + + /** + * Set the biome for a plot asynchronously + * + * @param biome The biome e.g. "forest" + * @param whenDone The task to run when finished, or null + */ + public void setBiome(final String biome, final Runnable whenDone) { + final ArrayDeque regions = new ArrayDeque<>(this.getRegions()); + final int extendBiome; + if (area instanceof SquarePlotWorld) { + extendBiome = (((SquarePlotWorld) area).ROAD_WIDTH > 0) ? 1 : 0; + } else { + extendBiome = 0; } - - /** - * Add someone as a helper (updates database as well) - * - * @param uuid the uuid of the player to trust - */ - public void addTrusted(UUID uuid) { - for (Plot current : getConnectedPlots()) { - if (current.getTrusted().add(uuid)) { - DBFunc.setTrusted(current, uuid); - } + Runnable run = new Runnable() { + @Override + public void run() { + if (regions.isEmpty()) { + Plot.this.refreshChunks(); + TaskManager.runTask(whenDone); + return; } + RegionWrapper region = regions.poll(); + Location pos1 = new Location(getWorldName(), region.minX - extendBiome, region.minY, + region.minZ - extendBiome); + Location pos2 = new Location(getWorldName(), region.maxX + extendBiome, region.maxY, + region.maxZ + extendBiome); + ChunkManager.chunkTask(pos1, pos2, new RunnableVal() { + @Override + public void run(int[] value) { + ChunkLoc loc = new ChunkLoc(value[0], value[1]); + ChunkManager.manager.loadChunk(getWorldName(), loc, false); + MainUtil.setBiome(getWorldName(), value[2], value[3], value[4], value[5], + biome); + ChunkManager.manager.unloadChunk(getWorldName(), loc, true, true); + } + }, this, 5); + + } + }; + run.run(); + } + + /** + * Unlink the plot and all connected plots. + * + * @param createSign whether to recreate signs + * @param createRoad whether to recreate road + * @return success/!cancelled + */ + public boolean unlinkPlot(boolean createRoad, boolean createSign) { + if (!this.isMerged()) { + return false; } - - /** - * Add someone as a trusted user (updates database as well) - * - * @param uuid the uuid of the player to add as a member - */ - public void addMember(UUID uuid) { - for (Plot current : getConnectedPlots()) { - if (current.getMembers().add(uuid)) { - DBFunc.setMember(current, uuid); - } - } + final Set plots = this.getConnectedPlots(); + ArrayList ids = new ArrayList<>(plots.size()); + for (Plot current : plots) { + current.setHome(null); + ids.add(current.getId()); } - - /** - * Set the plot owner (and update the database) - * - * @param owner uuid to set as owner - */ - public void setOwner(UUID owner) { - if (!hasOwner()) { - this.owner = owner; - create(); - return; - } - if (!isMerged()) { - if (!this.owner.equals(owner)) { - this.owner = owner; - DBFunc.setOwner(this, owner); - } - return; - } - for (Plot current : getConnectedPlots()) { - if (!owner.equals(current.owner)) { - current.owner = owner; - DBFunc.setOwner(current, owner); - } - } + boolean result = EventUtil.manager.callUnlink(this.area, ids); + if (!result) { + return false; } - - /** - * Set the plot owner (and update the database) - * - * @param owner uuid to set as owner - * @param initiator player initiating set owner - * @return boolean - */ - public boolean setOwner(UUID owner, PlotPlayer initiator) { - boolean result = EventUtil.manager - .callOwnerChange(initiator, this, owner, hasOwner() ? this.owner : null, hasOwner()); - if (!result) - return false; - if (!hasOwner()) { - this.owner = owner; - create(); - return true; - } - if (!isMerged()) { - if (!this.owner.equals(owner)) { - this.owner = owner; - DBFunc.setOwner(this, owner); - } - return true; - } - for (Plot current : getConnectedPlots()) { - if (!owner.equals(current.owner)) { - current.owner = owner; - DBFunc.setOwner(current, owner); - } - } - return true; + this.clearRatings(); + if (createSign) { + this.removeSign(); } - - /** - * Clear a plot. - * - * @param whenDone A runnable to execute when clearing finishes, or null - * @see this#clear(boolean, boolean, Runnable) - * @see #deletePlot(Runnable) to clear and delete a plot - */ - public void clear(Runnable whenDone) { - this.clear(false, false, whenDone); + PlotManager manager = this.area.getPlotManager(); + if (createRoad) { + manager.startPlotUnlink(this.area, ids); } - - public boolean clear(boolean checkRunning, final boolean isDelete, final Runnable whenDone) { - if (checkRunning && this.getRunning() != 0) { - return false; - } - if (isDelete) { - if (!EventUtil.manager.callDelete(this)) { - return false; - } - } else { - if (!EventUtil.manager.callClear(this)) { - return false; + if (this.area.TERRAIN != 3 && createRoad) { + for (Plot current : plots) { + if (current.getMerged(1)) { + manager.createRoadEast(current.area, current); + if (current.getMerged(2)) { + manager.createRoadSouth(current.area, current); + if (current.getMerged(5)) { + manager.createRoadSouthEast(current.area, current); } + } + } else if (current.getMerged(2)) { + manager.createRoadSouth(current.area, current); } - final HashSet regions = this.getRegions(); - final Set plots = this.getConnectedPlots(); - final ArrayDeque queue = new ArrayDeque<>(plots); - if (isDelete) { - this.removeSign(); - } - this.unlinkPlot(true, !isDelete); - final PlotManager manager = this.area.getPlotManager(); - Runnable run = new Runnable() { - @Override public void run() { - if (queue.isEmpty()) { - Runnable run = () -> { - for (RegionWrapper region : regions) { - Location[] corners = region.getCorners(getWorldName()); - ChunkManager.manager.clearAllEntities(corners[0], corners[1]); - } - TaskManager.runTask(whenDone); - }; - for (Plot current : plots) { - if (isDelete || current.owner == null) { - manager.unclaimPlot(Plot.this.area, current, null); - } else { - manager.claimPlot(Plot.this.area, current); - } - } - GlobalBlockQueue.IMP.addTask(run); - return; - } - Plot current = queue.poll(); - if (Plot.this.area.TERRAIN != 0) { - ChunkManager.manager - .regenerateRegion(current.getBottomAbs(), current.getTopAbs(), false, this); - return; - } - manager.clearPlot(Plot.this.area, current, this); - } - }; - run.run(); - return true; + } } - - /** - * Set the biome for a plot asynchronously - * - * @param biome The biome e.g. "forest" - * @param whenDone The task to run when finished, or null - */ - public void setBiome(final String biome, final Runnable whenDone) { - final ArrayDeque regions = new ArrayDeque<>(this.getRegions()); - final int extendBiome; - if (area instanceof SquarePlotWorld) { - extendBiome = (((SquarePlotWorld) area).ROAD_WIDTH > 0) ? 1 : 0; - } else { - extendBiome = 0; - } - Runnable run = new Runnable() { - @Override public void run() { - if (regions.isEmpty()) { - Plot.this.refreshChunks(); - TaskManager.runTask(whenDone); - return; - } - RegionWrapper region = regions.poll(); - Location pos1 = new Location(getWorldName(), region.minX - extendBiome, region.minY, - region.minZ - extendBiome); - Location pos2 = new Location(getWorldName(), region.maxX + extendBiome, region.maxY, - region.maxZ + extendBiome); - ChunkManager.chunkTask(pos1, pos2, new RunnableVal() { - @Override public void run(int[] value) { - ChunkLoc loc = new ChunkLoc(value[0], value[1]); - ChunkManager.manager.loadChunk(getWorldName(), loc, false); - MainUtil.setBiome(getWorldName(), value[2], value[3], value[4], value[5], - biome); - ChunkManager.manager.unloadChunk(getWorldName(), loc, true, true); - } - }, this, 5); - - } - }; - run.run(); + for (Plot current : plots) { + boolean[] merged = new boolean[]{false, false, false, false}; + current.setMerged(merged); } - - /** - * Unlink the plot and all connected plots. - * - * @param createSign whether to recreate signs - * @param createRoad whether to recreate road - * @return success/!cancelled - */ - public boolean unlinkPlot(boolean createRoad, boolean createSign) { - if (!this.isMerged()) { - return false; - } - final Set plots = this.getConnectedPlots(); - ArrayList ids = new ArrayList<>(plots.size()); + if (createSign) { + GlobalBlockQueue.IMP.addTask(() -> { for (Plot current : plots) { - current.setHome(null); - ids.add(current.getId()); + current.setSign(MainUtil.getName(current.owner)); } - boolean result = EventUtil.manager.callUnlink(this.area, ids); - if (!result) { - return false; + }); + } + if (createRoad) { + manager.finishPlotUnlink(this.area, ids); + } + return true; + } + + /** + * Set the sign for a plot to a specific name + * + * @param name name + */ + public void setSign(final String name) { + if (!isLoaded()) { + return; + } + if (!PlotSquared.get().isMainThread(Thread.currentThread())) { + TaskManager.runTask(() -> Plot.this.setSign(name)); + return; + } + if (name == null) { + PlotSquared.log("Attempted to add null name to sign at plot: " + getId()); + return; + } + PlotManager manager = this.area.getPlotManager(); + if (this.area.ALLOW_SIGNS) { + Location loc = manager.getSignLoc(this.area, this); + String id = this.id.x + ";" + this.id.y; + String[] lines = new String[]{C.OWNER_SIGN_LINE_1.formatted().replaceAll("%id%", id), + C.OWNER_SIGN_LINE_2.formatted().replaceAll("%id%", id).replaceAll("%plr%", name), + C.OWNER_SIGN_LINE_3.formatted().replaceAll("%id%", id).replaceAll("%plr%", name), + C.OWNER_SIGN_LINE_4.formatted().replaceAll("%id%", id).replaceAll("%plr%", name)}; + WorldUtil.IMP.setSign(this.getWorldName(), loc.getX(), loc.getY(), loc.getZ(), lines); + } + } + + protected boolean isLoaded() { + return WorldUtil.IMP.isWorld(getWorldName()); + } + + /** + * This will return null if the plot hasn't been analyzed + * + * @return analysis of plot + */ + public PlotAnalysis getComplexity(Settings.Auto_Clear settings) { + return PlotAnalysis.getAnalysis(this, settings); + } + + public void analyze(RunnableVal whenDone) { + PlotAnalysis.analyzePlot(this, whenDone); + } + + /** + * Set a flag for this plot + * + * @param flag Flag to set + * @param value Flag value + */ + public boolean setFlag(Flag flag, Object value) { + if (flag == Flags.KEEP && ExpireManager.IMP != null) { + ExpireManager.IMP.updateExpired(this); + } + return FlagManager.addPlotFlag(this, flag, value); + } + + /** + * Remove a flag from this plot + * + * @param flag the flag to remove + * @return success + */ + public boolean removeFlag(Flag flag) { + return FlagManager.removePlotFlag(this, flag); + } + + /** + * Get the flag for a given key + * + * @param key Flag to get value for + */ + public Optional getFlag(Flag key) { + return FlagManager.getPlotFlag(this, key); + } + + /** + * Get the flag for a given key + * + * @param key the flag + * @param defaultValue if the key is null, the value to return + */ + public V getFlag(Flag key, V defaultValue) { + V value = FlagManager.getPlotFlagRaw(this, key); + if (value == null) { + return defaultValue; + } else { + return value; + } + } + + /** + * Delete a plot (use null for the runnable if you don't need to be notified on completion) + * + * @see PlotSquared#removePlot(Plot, boolean) + * @see #clear(Runnable) to simply clear a plot + */ + public boolean deletePlot(final Runnable whenDone) { + if (!this.hasOwner()) { + return false; + } + final Set plots = this.getConnectedPlots(); + this.clear(false, true, () -> { + for (Plot current : plots) { + current.unclaim(); + } + TaskManager.runTask(whenDone); + }); + return true; + } + + /** + * Count the entities in a plot + * + * @return array of entity counts + * @see ChunkManager#countEntities(Plot) 0 = Entity 1 = Animal 2 = Monster 3 = Mob 4 = Boat 5 = + * Misc + */ + public int[] countEntities() { + int[] count = new int[6]; + for (Plot current : this.getConnectedPlots()) { + int[] result = ChunkManager.manager.countEntities(current); + count[0] += result[0]; + count[1] += result[1]; + count[2] += result[2]; + count[3] += result[3]; + count[4] += result[4]; + count[5] += result[5]; + } + return count; + } + + /** + * Returns true if a previous task was running + * + * @return true if a previous task is running + */ + public int addRunning() { + int value = this.getRunning(); + for (Plot plot : this.getConnectedPlots()) { + plot.setMeta("running", value + 1); + } + return value; + } + + /** + * Decrement the number of tracked tasks this plot is running
- Used to track/limit the number + * of things a player can do on the plot at once + * + * @return previous number of tasks (int) + */ + public int removeRunning() { + int value = this.getRunning(); + if (value < 2) { + for (Plot plot : this.getConnectedPlots()) { + plot.deleteMeta("running"); + } + } else { + for (Plot plot : this.getConnectedPlots()) { + plot.setMeta("running", value - 1); + } + } + return value; + } + + /** + * Get the number of tracked running tasks for this plot
- Used to track/limit the number of + * things a player can do on the plot at once + * + * @return number of tasks (int) + */ + public int getRunning() { + Integer value = (Integer) this.getMeta("running"); + return value == null ? 0 : value; + } + + /** + * Unclaim the plot (does not modify terrain). Changes made to this plot will not be reflected in + * unclaimed plot objects. + * + * @return false if the Plot has no owner, otherwise true. + */ + public boolean unclaim() { + if (this.owner == null) { + return false; + } + for (Plot current : getConnectedPlots()) { + List players = current.getPlayersInPlot(); + for (PlotPlayer pp : players) { + PlotListener.plotExit(pp, current); + } + getArea().removePlot(getId()); + DBFunc.delete(current); + current.owner = null; + current.settings = null; + for (PlotPlayer pp : players) { + PlotListener.plotEntry(pp, current); + } + } + return true; + } + + /** + * Unlink a plot and remove the roads + * + * @return true if plot was linked + * @see this#unlinkPlot(boolean, boolean) + */ + public boolean unlink() { + return this.unlinkPlot(true, true); + } + + public Location getCenter() { + Location[] corners = getCorners(); + Location top = corners[0]; + Location bot = corners[1]; + Location loc = new Location(this.getWorldName(), MathMan.average(bot.getX(), top.getX()), + MathMan.average(bot.getY(), top.getY()), MathMan.average(bot.getZ(), top.getZ())); + if (!isLoaded()) { + return loc; + } + int y = + isLoaded() ? WorldUtil.IMP.getHighestBlock(getWorldName(), loc.getX(), loc.getZ()) : 62; + if (area.ALLOW_SIGNS) { + y = Math.max(y, getManager().getSignLoc(area, this).getY()); + } + loc.setY(1 + y); + return loc; + } + + public Location getSide() { + RegionWrapper largest = getLargestRegion(); + int x = (largest.maxX >> 1) - (largest.minX >> 1) + largest.minX; + int z = largest.minZ - 1; + PlotManager manager = getManager(); + int y = isLoaded() ? WorldUtil.IMP.getHighestBlock(getWorldName(), x, z) : 62; + 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); + } + + /** + * Return the home location for the plot + * + * @return Home location + */ + public Location getHome() { + BlockLoc home = this.getPosition(); + if (home == null || home.x == 0 && home.z == 0) { + return this.getDefaultHome(true); + } else { + 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).isAir()) { + loc.setY(Math.max( + 1 + WorldUtil.IMP.getHighestBlock(this.getWorldName(), loc.getX(), loc.getZ()), + bot.getY())); + } + return loc; + } + } + + /** + * Set the home location + * + * @param location location to set as home + */ + public void setHome(BlockLoc location) { + Plot plot = this.getBasePlot(false); + if (location != null && new BlockLoc(0, 0, 0).equals(location)) { + return; + } + plot.getSettings().setPosition(location); + if (location != null) { + DBFunc.setPosition(plot, plot.getSettings().getPosition().toString()); + return; + } + DBFunc.setPosition(plot, null); + } + + /** + * Get the default home location for a plot
- Ignores any home location set for that specific + * plot + * + * @return Location + */ + public Location getDefaultHome() { + return getDefaultHome(false); + } + + public Location getDefaultHome(boolean member) { + Plot plot = this.getBasePlot(false); + PlotLoc loc = member ? area.DEFAULT_HOME : area.NONMEMBER_HOME; + if (loc != null) { + int x; + int z; + if (loc.x == Integer.MAX_VALUE && loc.z == Integer.MAX_VALUE) { + // center + RegionWrapper largest = plot.getLargestRegion(); + x = (largest.maxX >> 1) - (largest.minX >> 1) + largest.minX; + z = (largest.maxZ >> 1) - (largest.minZ >> 1) + largest.minZ; + } else { + // specific + Location bot = plot.getBottomAbs(); + x = bot.getX() + loc.x; + z = bot.getZ() + loc.z; + } + int y = loc.y < 1 ? + (isLoaded() ? WorldUtil.IMP.getHighestBlock(plot.getWorldName(), x, z) + 1 : 63) : + loc.y; + PlotSquared.log("Getting home with Y " + y); + return new Location(plot.getWorldName(), x, y, z); + } + // Side + return plot.getSide(); + } + + public double getVolume() { + double count = 0; + for (RegionWrapper region : getRegions()) { + count += + (region.maxX - (double) region.minX + 1) * (region.maxZ - (double) region.minZ + 1) + * 256; + } + return count; + } + + /** + * Get the average rating of the plot. This is the value displayed in /plot info + * + * @return average rating as double + */ + public double getAverageRating() { + double sum = 0; + Collection ratings = this.getRatings().values(); + for (Rating rating : ratings) { + sum += rating.getAverageRating(); + } + return sum / ratings.size(); + } + + /** + * Set a rating for a user
- If the user has already rated, the following will return false + * + * @param uuid uuid of rater + * @param rating rating + * @return success + */ + public boolean addRating(UUID uuid, Rating rating) { + Plot base = this.getBasePlot(false); + PlotSettings baseSettings = base.getSettings(); + if (baseSettings.getRatings().containsKey(uuid)) { + return false; + } + int aggregate = rating.getAggregate(); + baseSettings.getRatings().put(uuid, aggregate); + DBFunc.setRating(base, uuid, aggregate); + return true; + } + + /** + * Clear the ratings for this plot + */ + public void clearRatings() { + Plot base = this.getBasePlot(false); + PlotSettings baseSettings = base.getSettings(); + if (baseSettings.ratings != null && !baseSettings.getRatings().isEmpty()) { + DBFunc.deleteRatings(base); + baseSettings.ratings = null; + } + } + + /** + * Get the ratings associated with a plot
- The rating object may contain multiple categories + * + * @return Map of user who rated to the rating + */ + public HashMap getRatings() { + Plot base = this.getBasePlot(false); + HashMap map = new HashMap<>(); + if (!base.hasRatings()) { + return map; + } + for (Entry entry : base.getSettings().getRatings().entrySet()) { + map.put(entry.getKey(), new Rating(entry.getValue())); + } + return map; + } + + public boolean hasRatings() { + Plot base = this.getBasePlot(false); + return base.settings != null && base.settings.ratings != null; + } + + /** + * Resend all chunks inside the plot to nearby players
This should not need to be called + */ + public void refreshChunks() { + LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(getWorldName(), false); + HashSet chunks = new HashSet<>(); + for (RegionWrapper region : Plot.this.getRegions()) { + for (int x = region.minX >> 4; x <= region.maxX >> 4; x++) { + for (int z = region.minZ >> 4; z <= region.maxZ >> 4; z++) { + if (chunks.add(new ChunkLoc(x, z))) { + queue.refreshChunk(x, z); + } } - this.clearRatings(); - if (createSign) { - this.removeSign(); - } - PlotManager manager = this.area.getPlotManager(); - if (createRoad) { - manager.startPlotUnlink(this.area, ids); - } - if (this.area.TERRAIN != 3 && createRoad) { - for (Plot current : plots) { - if (current.getMerged(1)) { - manager.createRoadEast(current.area, current); - if (current.getMerged(2)) { - manager.createRoadSouth(current.area, current); - if (current.getMerged(5)) { - manager.createRoadSouthEast(current.area, current); - } - } - } else if (current.getMerged(2)) { - manager.createRoadSouth(current.area, current); - } - } - } - for (Plot current : plots) { - boolean[] merged = new boolean[] {false, false, false, false}; - current.setMerged(merged); - } - if (createSign) { - GlobalBlockQueue.IMP.addTask(() -> { - for (Plot current : plots) { - current.setSign(MainUtil.getName(current.owner)); - } - }); - } - if (createRoad) { - manager.finishPlotUnlink(this.area, ids); + } + } + } + + /** + * Remove the plot sign if it is set. + */ + public void removeSign() { + PlotManager manager = this.area.getPlotManager(); + if (!this.area.ALLOW_SIGNS) { + return; + } + Location loc = manager.getSignLoc(this.area, this); + LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(getWorldName(), false); + queue.setBlock(loc.getX(), loc.getY(), loc.getZ(), PlotBlock.get("air")); + queue.flush(); + } + + /** + * Set the plot sign if plot signs are enabled. + */ + public void setSign() { + if (this.owner == null) { + this.setSign("unknown"); + return; + } + this.setSign(UUIDHandler.getName(this.owner)); + } + + /** + * Register a plot and create it in the database
- The plot will not be created if the owner + * is null
- Any setting from before plot creation will not be saved until the server is + * stopped properly. i.e. Set any values/options after plot creation. + * + * @return true if plot was created successfully + */ + public boolean create() { + return this.create(this.owner, true); + } + + public boolean claim(final PlotPlayer player, boolean teleport, String schematic) { + if (!canClaim(player)) { + return false; + } + return claim(player, teleport, schematic, true); + } + + public boolean claim(final PlotPlayer player, boolean teleport, String schematic, + boolean updateDB) { + boolean result = EventUtil.manager.callClaim(player, this, false); + if (updateDB) { + if (!result || (!create(player.getUUID(), true))) { + return false; + } + } else { + area.addPlot(this); + } + setSign(player.getName()); + MainUtil.sendMessage(player, C.CLAIMED); + if (teleport) { + teleportPlayer(player); + } + PlotArea plotworld = getArea(); + if (plotworld.SCHEMATIC_ON_CLAIM) { + Schematic sch; + try { + if (schematic == null || schematic.isEmpty()) { + sch = SchematicHandler.manager.getSchematic(plotworld.SCHEMATIC_FILE); + } else { + sch = SchematicHandler.manager.getSchematic(schematic); + if (sch == null) { + sch = SchematicHandler.manager.getSchematic(plotworld.SCHEMATIC_FILE); + } } + } catch (SchematicHandler.UnsupportedFormatException e) { + e.printStackTrace(); return true; + } + SchematicHandler.manager + .paste(sch, this, 0, 1, 0, Settings.Schematics.PASTE_ON_TOP, new RunnableVal() { + @Override + public void run(Boolean value) { + if (value) { + MainUtil.sendMessage(player, C.SCHEMATIC_PASTE_SUCCESS); + } else { + MainUtil.sendMessage(player, C.SCHEMATIC_PASTE_FAILED); + } + } + }); } + plotworld.getPlotManager().claimPlot(plotworld, this); + return true; + } - /** - * Set the sign for a plot to a specific name - * - * @param name name - */ - public void setSign(final String name) { - if (!isLoaded()) - return; - if (!PlotSquared.get().isMainThread(Thread.currentThread())) { - TaskManager.runTask(() -> Plot.this.setSign(name)); - return; - } - if(name == null) { - PlotSquared.log("Attempted to add null name to sign at plot: " + getId()); - return; - } - PlotManager manager = this.area.getPlotManager(); - if (this.area.ALLOW_SIGNS) { - Location loc = manager.getSignLoc(this.area, this); - String id = this.id.x + ";" + this.id.y; - String[] lines = new String[] {C.OWNER_SIGN_LINE_1.formatted().replaceAll("%id%", id), - C.OWNER_SIGN_LINE_2.formatted().replaceAll("%id%", id).replaceAll("%plr%", name), - C.OWNER_SIGN_LINE_3.formatted().replaceAll("%id%", id).replaceAll("%plr%", name), - C.OWNER_SIGN_LINE_4.formatted().replaceAll("%id%", id).replaceAll("%plr%", name)}; - WorldUtil.IMP.setSign(this.getWorldName(), loc.getX(), loc.getY(), loc.getZ(), lines); + /** + * Register a plot and create it in the database
- The plot will not be created if the owner + * is null
- Any setting from before plot creation will not be saved until the server is + * stopped properly. i.e. Set any values/options after plot creation. + * + * @param uuid the uuid of the plot owner + * @param notify notify + * @return true if plot was created successfully + */ + public boolean create(final UUID uuid, final boolean notify) { + if (uuid == null) { + throw new IllegalArgumentException("UUID cannot be null"); + } + this.owner = uuid; + Plot existing = this.area.getOwnedPlotAbs(this.id); + if (existing != null) { + throw new IllegalStateException("Plot already exists!"); + } + if (notify) { + Integer meta = (Integer) this.area.getMeta("worldBorder"); + if (meta != null) { + this.updateWorldBorder(); + } + } + connected_cache = null; + regions_cache = null; + this.getTrusted().clear(); + this.getMembers().clear(); + this.getDenied().clear(); + this.settings = new PlotSettings(); + if (this.area.addPlot(this)) { + DBFunc.createPlotAndSettings(this, () -> { + PlotArea plotworld = Plot.this.area; + if (notify && plotworld.AUTO_MERGE) { + Plot.this.autoMerge(-1, Integer.MAX_VALUE, uuid, true); } + }); + return true; } + return false; + } - protected boolean isLoaded() { - return WorldUtil.IMP.isWorld(getWorldName()); + /** + * Set components such as border, wall, floor. (components are generator specific) + */ + public boolean setComponent(String component, String blocks) { + BlockBucket parsed = Configuration.BLOCK_BUCKET.parseString(blocks); + return !(parsed == null || parsed.isEmpty()) && this.setComponent(component, parsed); + } + + /** + * Retrieve the biome of the plot. + * + * @return the name of the biome + */ + public String getBiome() { + Location loc = this.getCenter(); + return WorldUtil.IMP.getBiome(loc.getWorld(), loc.getX(), loc.getZ()); + } + + /** + * Return the top location for the plot. + */ + public Location getTopAbs() { + Location top = this.area.getPlotManager().getPlotTopLocAbs(this.area, this.id); + top.setWorld(getWorldName()); + return top; + } + + /** + * Return the bottom location for the plot. + */ + public Location getBottomAbs() { + Location loc = this.area.getPlotManager().getPlotBottomLocAbs(this.area, this.id); + loc.setWorld(getWorldName()); + return loc; + } + + /** + * Swap the settings for two plots. + * + * @param plot the plot to swap data with + * @param whenDone the task to run at the end of this method. + */ + public boolean swapData(Plot plot, Runnable whenDone) { + if (this.owner == null) { + if (plot != null && plot.hasOwner()) { + plot.moveData(this, whenDone); + return true; + } + return false; } - - /** - * This will return null if the plot hasn't been analyzed - * - * @return analysis of plot - */ - public PlotAnalysis getComplexity(Settings.Auto_Clear settings) { - return PlotAnalysis.getAnalysis(this, settings); + if (plot == null || plot.owner == null) { + this.moveData(plot, whenDone); + return true; } + // Swap cached + PlotId temp = new PlotId(this.getId().x, this.getId().y); + this.getId().x = plot.getId().x; + this.getId().y = plot.getId().y; + plot.getId().x = temp.x; + plot.getId().y = temp.y; + this.area.removePlot(this.getId()); + plot.area.removePlot(plot.getId()); + this.getId().recalculateHash(); + plot.getId().recalculateHash(); + this.area.addPlotAbs(this); + plot.area.addPlotAbs(plot); + // Swap database + DBFunc.swapPlots(plot, this); + TaskManager.runTaskLater(whenDone, 1); + return true; + } - public void analyze(RunnableVal whenDone) { - PlotAnalysis.analyzePlot(this, whenDone); + /** + * Move the settings for a plot. + * + * @param plot the plot to move + */ + public boolean moveData(Plot plot, Runnable whenDone) { + if (this.owner == null) { + PlotSquared.debug(plot + " is unowned (single)"); + TaskManager.runTask(whenDone); + return false; } - - /** - * Set a flag for this plot - * - * @param flag Flag to set - * @param value Flag value - */ - public boolean setFlag(Flag flag, Object value) { - if (flag == Flags.KEEP && ExpireManager.IMP != null) { - ExpireManager.IMP.updateExpired(this); - } - return FlagManager.addPlotFlag(this, flag, value); + if (plot.hasOwner()) { + PlotSquared.debug(plot + " is unowned (multi)"); + TaskManager.runTask(whenDone); + return false; } + this.area.removePlot(this.id); + this.getId().x = plot.getId().x; + this.getId().y = plot.getId().y; + this.getId().recalculateHash(); + this.area.addPlotAbs(this); + DBFunc.movePlot(this, plot); + TaskManager.runTaskLater(whenDone, 1); + return true; + } - /** - * Remove a flag from this plot - * - * @param flag the flag to remove - * @return success - */ - public boolean removeFlag(Flag flag) { - return FlagManager.removePlotFlag(this, flag); + /** + * Gets the top loc of a plot (if mega, returns top loc of that mega plot) - If you would like + * each plot treated as a small plot use getPlotTopLocAbs(...) + * + * @return Location top of mega plot + */ + public Location getExtendedTopAbs() { + Location top = this.getTopAbs(); + if (!this.isMerged()) { + return top; } - - /** - * Get the flag for a given key - * - * @param key Flag to get value for - */ - public Optional getFlag(Flag key) { - return FlagManager.getPlotFlag(this, key); + if (this.getMerged(2)) { + top.setZ(this.getRelative(2).getBottomAbs().getZ() - 1); } + if (this.getMerged(1)) { + top.setX(this.getRelative(1).getBottomAbs().getX() - 1); + } + return top; + } - /** - * Get the flag for a given key - * - * @param key the flag - * @param defaultValue if the key is null, the value to return - */ - public V getFlag(Flag key, V defaultValue) { - V value = FlagManager.getPlotFlagRaw(this, key); + /** + * Gets the bottom location for a plot.
- Does not respect mega plots
- Merged plots, only + * the road will be considered part of the plot
+ * + * @return Location bottom of mega plot + */ + public Location getExtendedBottomAbs() { + Location bot = this.getBottomAbs(); + if (!this.isMerged()) { + return bot; + } + if (this.getMerged(0)) { + bot.setZ(this.getRelative(0).getTopAbs().getZ() + 1); + } + if (this.getMerged(3)) { + bot.setX(this.getRelative(3).getTopAbs().getX() + 1); + } + return bot; + } + + /** + * Returns the top and bottom location.
- If the plot is not connected, it will return its own + * corners
- the returned locations will not necessarily correspond to claimed plots if the + * connected plots do not form a rectangular shape + * + * @return new Location[] { bottom, top } + * @deprecated as merged plots no longer need to be rectangular + */ + @Deprecated + public Location[] getCorners() { + if (!this.isMerged()) { + return new Location[]{this.getBottomAbs(), this.getTopAbs()}; + } + return MainUtil.getCorners(this.getWorldName(), this.getRegions()); + } + + /** + * Remove the east road section of a plot
- Used when a plot is merged
+ */ + public void removeRoadEast() { + if (this.area.TYPE != 0 && this.area.TERRAIN > 1) { + if (this.area.TERRAIN == 3) { + return; + } + Plot other = this.getRelative(1); + Location bot = other.getBottomAbs(); + Location top = this.getTopAbs(); + Location pos1 = new Location(this.getWorldName(), top.getX(), 0, bot.getZ()); + Location pos2 = new Location(this.getWorldName(), bot.getX(), 256, top.getZ()); + ChunkManager.manager.regenerateRegion(pos1, pos2, true, null); + } else { + this.area.getPlotManager().removeRoadEast(this.area, this); + } + } + + /** + * @deprecated in favor of getCorners()[0];
+ */ + // Won't remove as suggestion also points to deprecated method + @Deprecated + public Location getBottom() { + return this.getCorners()[0]; + } + + /** + * @return the top corner of the plot + * @deprecated in favor of getCorners()[1]; + */ + // Won't remove as suggestion also points to deprecated method + @Deprecated + public Location getTop() { + return this.getCorners()[1]; + } + + /** + * Swap the plot contents and settings with another location
- The destination must correspond + * to a valid plot of equal dimensions + * + * @param destination The other plot to swap with + * @param whenDone A task to run when finished, or null + * @return boolean if swap was successful + * @see ChunkManager#swap(Location, Location, Location, Location, Runnable) to swap terrain + * @see this#swapData(Plot, Runnable) to swap plot settings + * @see this#swapData(Plot, Runnable) + */ + public boolean swap(Plot destination, Runnable whenDone) { + return this.move(destination, whenDone, true); + } + + /** + * Move the plot to an empty location
- The location must be empty + * + * @param destination Where to move the plot + * @param whenDone A task to run when done, or null + * @return if the move was successful + */ + public boolean move(Plot destination, Runnable whenDone) { + return this.move(destination, whenDone, false); + } + + /** + * Get plot display name. + * + * @return alias if set, else id + */ + @Override + public String toString() { + if (this.settings != null && this.settings.getAlias().length() > 1) { + return this.settings.getAlias(); + } + return this.area + ";" + this.id.x + ";" + this.id.y; + } + + + /** + * Remove a denied player (use DBFunc as well)
Using the * uuid will remove all users + */ + public boolean removeDenied(UUID uuid) { + if (uuid == DBFunc.EVERYONE && !denied.contains(uuid)) { + boolean result = false; + for (UUID other : new HashSet<>(getDenied())) { + result = rmvDenied(other) || result; + } + return result; + } + return rmvDenied(uuid); + } + + private boolean rmvDenied(UUID uuid) { + for (Plot current : this.getConnectedPlots()) { + if (current.getDenied().remove(uuid)) { + DBFunc.removeDenied(current, uuid); + } else { + return false; + } + } + return true; + } + + /** + * Remove a helper (use DBFunc as well)
Using the * uuid will remove all users + */ + public boolean removeTrusted(UUID uuid) { + if (uuid == DBFunc.EVERYONE && !trusted.contains(uuid)) { + boolean result = false; + for (UUID other : new HashSet<>(getTrusted())) { + result = rmvTrusted(other) || result; + } + return result; + } + return rmvTrusted(uuid); + } + + private boolean rmvTrusted(UUID uuid) { + for (Plot plot : this.getConnectedPlots()) { + if (plot.getTrusted().remove(uuid)) { + DBFunc.removeTrusted(plot, uuid); + } else { + return false; + } + } + return true; + } + + /** + * Remove a trusted user (use DBFunc as well)
Using the * uuid will remove all users + */ + public boolean removeMember(UUID uuid) { + if (this.members == null) { + return false; + } + if (uuid == DBFunc.EVERYONE && !members.contains(uuid)) { + boolean result = false; + for (UUID other : new HashSet<>(this.members)) { + result = rmvMember(other) || result; + } + return result; + } + return rmvMember(uuid); + } + + private boolean rmvMember(UUID uuid) { + for (Plot current : this.getConnectedPlots()) { + if (current.getMembers().remove(uuid)) { + DBFunc.removeMember(current, uuid); + } else { + return false; + } + } + return true; + } + + /** + * Export the plot as a schematic to the configured output directory. + */ + public void export(final RunnableVal whenDone) { + SchematicHandler.manager.getCompoundTag(this, new RunnableVal() { + @Override + public void run(final CompoundTag value) { if (value == null) { - return defaultValue; - } else { - return value; - } - } - - /** - * Delete a plot (use null for the runnable if you don't need to be notified on completion) - * - * @see PlotSquared#removePlot(Plot, boolean) - * @see #clear(Runnable) to simply clear a plot - */ - public boolean deletePlot(final Runnable whenDone) { - if (!this.hasOwner()) { - return false; - } - final Set plots = this.getConnectedPlots(); - this.clear(false, true, () -> { - for (Plot current : plots) { - current.unclaim(); - } + if (whenDone != null) { + whenDone.value = false; TaskManager.runTask(whenDone); - }); - return true; - } - - /** - * Count the entities in a plot - * - * @return array of entity counts - * @see ChunkManager#countEntities(Plot) - * 0 = Entity - * 1 = Animal - * 2 = Monster - * 3 = Mob - * 4 = Boat - * 5 = Misc - */ - public int[] countEntities() { - int[] count = new int[6]; - for (Plot current : this.getConnectedPlots()) { - int[] result = ChunkManager.manager.countEntities(current); - count[0] += result[0]; - count[1] += result[1]; - count[2] += result[2]; - count[3] += result[3]; - count[4] += result[4]; - count[5] += result[5]; - } - return count; - } - - /** - * Returns true if a previous task was running - * - * @return true if a previous task is running - */ - public int addRunning() { - int value = this.getRunning(); - for (Plot plot : this.getConnectedPlots()) { - plot.setMeta("running", value + 1); - } - return value; - } - - /** - * Decrement the number of tracked tasks this plot is running
- * - Used to track/limit the number of things a player can do on the plot at once - * - * @return previous number of tasks (int) - */ - public int removeRunning() { - int value = this.getRunning(); - if (value < 2) { - for (Plot plot : this.getConnectedPlots()) { - plot.deleteMeta("running"); - } + } } else { - for (Plot plot : this.getConnectedPlots()) { - plot.setMeta("running", value - 1); + TaskManager.runTaskAsync(() -> { + String name = Plot.this.id + "," + Plot.this.area + ',' + MainUtil + .getName(Plot.this.owner); + boolean result = SchematicHandler.manager.save(value, + Settings.Paths.SCHEMATICS + File.separator + name + ".schematic"); + if (whenDone != null) { + whenDone.value = result; + TaskManager.runTask(whenDone); } + }); } - return value; - } + } + }); + } - /** - * Get the number of tracked running tasks for this plot
- * - Used to track/limit the number of things a player can do on the plot at once - * - * @return number of tasks (int) - */ - public int getRunning() { - Integer value = (Integer) this.getMeta("running"); - return value == null ? 0 : value; - } + /** + * Upload the plot as a schematic to the configured web interface. + * + * @param whenDone value will be null if uploading fails + */ + public void upload(final RunnableVal whenDone) { + SchematicHandler.manager.getCompoundTag(this, new RunnableVal() { + @Override + public void run(CompoundTag value) { + SchematicHandler.manager.upload(value, null, null, whenDone); + } + }); + } - /** - * Unclaim the plot (does not modify terrain). Changes made to this plot will not be reflected in unclaimed plot objects. - * - * @return false if the Plot has no owner, otherwise true. - */ - public boolean unclaim() { - if (this.owner == null) { - return false; + /** + * Upload this plot as a world file
- The mca files are each 512x512, so depending on the plot + * size it may also download adjacent plots
- Works best when (plot width + road width) % 512 + * == 0
+ * + * @see WorldUtil + */ + public void uploadWorld(RunnableVal whenDone) { + WorldUtil.IMP.upload(this, null, null, whenDone); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (this.getClass() != obj.getClass()) { + return false; + } + Plot other = (Plot) obj; + return this.hashCode() == other.hashCode() && this.id.equals(other.id) + && this.area == other.area; + } + + /** + * Get the plot hashcode
Note: The hashcode is unique if:
- Plots are in the same + * world
- The x,z coordinates are between Short.MIN_VALUE and Short.MAX_VALUE
+ * + * @return integer. + */ + @Override + public int hashCode() { + return this.id.hashCode(); + } + + /** + * Get the flags specific to this plot
- Does not take default flags into account
+ */ + public HashMap, Object> getFlags() { + return this.getSettings().flags; + } + + /** + * Set a flag for this plot. + */ + public void setFlags(HashMap, Object> flags) { + FlagManager.setPlotFlags(this, flags); + } + + /** + * Get the plot alias. - Returns an empty string if no alias is set + * + * @return The plot alias + */ + public String getAlias() { + if (this.settings == null) { + return ""; + } + return this.settings.getAlias(); + } + + /** + * Set the plot alias. + * + * @param alias The alias + */ + public void setAlias(String alias) { + for (Plot current : this.getConnectedPlots()) { + String name = this.getSettings().getAlias(); + if (alias == null) { + alias = ""; + } + if (name.equals(alias)) { + return; + } + current.getSettings().setAlias(alias); + DBFunc.setAlias(current, alias); + } + } + + /** + * Set the raw merge data
- Updates DB
- Does not modify terrain
----------
0 = + * north
1 = east
2 = south
3 = west
----------
+ */ + private void setMerged(int direction, boolean value) { + if (this.getSettings().setMerged(direction, value)) { + if (value) { + Plot other = this.getRelative(direction).getBasePlot(false); + if (!other.equals(this.getBasePlot(false))) { + Plot base = other.id.y < this.id.y + || other.id.y == this.id.y && other.id.x < this.id.x ? other : this.origin; + this.origin.origin = base; + other.origin = base; + this.origin = base; + connected_cache = null; } - for (Plot current : getConnectedPlots()) { - List players = current.getPlayersInPlot(); - for (PlotPlayer pp : players) { - PlotListener.plotExit(pp, current); - } - getArea().removePlot(getId()); - DBFunc.delete(current); - current.owner = null; - current.settings = null; - for (PlotPlayer pp : players) { - PlotListener.plotEntry(pp, current); - } - } - return true; - } - - /** - * Unlink a plot and remove the roads - * - * @return true if plot was linked - * @see this#unlinkPlot(boolean, boolean) - */ - public boolean unlink() { - return this.unlinkPlot(true, true); - } - - public Location getCenter() { - Location[] corners = getCorners(); - Location top = corners[0]; - Location bot = corners[1]; - Location loc = new Location(this.getWorldName(), MathMan.average(bot.getX(), top.getX()), - MathMan.average(bot.getY(), top.getY()), MathMan.average(bot.getZ(), top.getZ())); - if (!isLoaded()) - return loc; - int y = - isLoaded() ? WorldUtil.IMP.getHighestBlock(getWorldName(), loc.getX(), loc.getZ()) : 62; - if (area.ALLOW_SIGNS) { - y = Math.max(y, getManager().getSignLoc(area, this).getY()); - } - loc.setY(1 + y); - return loc; - } - - public Location getSide() { - RegionWrapper largest = getLargestRegion(); - int x = (largest.maxX >> 1) - (largest.minX >> 1) + largest.minX; - int z = largest.minZ - 1; - PlotManager manager = getManager(); - int y = isLoaded() ? WorldUtil.IMP.getHighestBlock(getWorldName(), x, z) : 62; - 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); - } - - /** - * Return the home location for the plot - * - * @return Home location - */ - public Location getHome() { - BlockLoc home = this.getPosition(); - if (home == null || home.x == 0 && home.z == 0) { - return this.getDefaultHome(true); - } else { - 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).isAir()) { - loc.setY(Math.max( - 1 + WorldUtil.IMP.getHighestBlock(this.getWorldName(), loc.getX(), loc.getZ()), - bot.getY())); - } - return loc; - } - } - - /** - * Set the home location - * - * @param location location to set as home - */ - public void setHome(BlockLoc location) { - Plot plot = this.getBasePlot(false); - if (location != null && new BlockLoc(0, 0, 0).equals(location)) { - return; - } - plot.getSettings().setPosition(location); - if (location != null) { - DBFunc.setPosition(plot, plot.getSettings().getPosition().toString()); - return; - } - DBFunc.setPosition(plot, null); - } - - /** - * Get the default home location for a plot
- * - Ignores any home location set for that specific plot - * - * @return Location - */ - public Location getDefaultHome() { - return getDefaultHome(false); - } - - public Location getDefaultHome(boolean member) { - Plot plot = this.getBasePlot(false); - PlotLoc loc = member ? area.DEFAULT_HOME : area.NONMEMBER_HOME; - if (loc != null) { - int x; - int z; - if (loc.x == Integer.MAX_VALUE && loc.z == Integer.MAX_VALUE) { - // center - RegionWrapper largest = plot.getLargestRegion(); - x = (largest.maxX >> 1) - (largest.minX >> 1) + largest.minX; - z = (largest.maxZ >> 1) - (largest.minZ >> 1) + largest.minZ; - } else { - // specific - Location bot = plot.getBottomAbs(); - x = bot.getX() + loc.x; - z = bot.getZ() + loc.z; - } - int y = loc.y < 1 ? - (isLoaded() ? WorldUtil.IMP.getHighestBlock(plot.getWorldName(), x, z) + 1 : 63) : - loc.y; - PlotSquared.log("Getting home with Y " + y); - return new Location(plot.getWorldName(), x, y, z); - } - // Side - return plot.getSide(); - } - - public double getVolume() { - double count = 0; - for (RegionWrapper region : getRegions()) { - count += - (region.maxX - (double) region.minX + 1) * (region.maxZ - (double) region.minZ + 1) - * 256; - } - return count; - } - - /** - * Get the average rating of the plot. This is the value displayed in /plot info - * - * @return average rating as double - */ - public double getAverageRating() { - double sum = 0; - Collection ratings = this.getRatings().values(); - for (Rating rating : ratings) { - sum += rating.getAverageRating(); - } - return sum / ratings.size(); - } - - /** - * Set a rating for a user
- * - If the user has already rated, the following will return false - * - * @param uuid uuid of rater - * @param rating rating - * @return success - */ - public boolean addRating(UUID uuid, Rating rating) { - Plot base = this.getBasePlot(false); - PlotSettings baseSettings = base.getSettings(); - if (baseSettings.getRatings().containsKey(uuid)) { - return false; - } - int aggregate = rating.getAggregate(); - baseSettings.getRatings().put(uuid, aggregate); - DBFunc.setRating(base, uuid, aggregate); - return true; - } - - /** - * Clear the ratings for this plot - */ - public void clearRatings() { - Plot base = this.getBasePlot(false); - PlotSettings baseSettings = base.getSettings(); - if (baseSettings.ratings != null && !baseSettings.getRatings().isEmpty()) { - DBFunc.deleteRatings(base); - baseSettings.ratings = null; - } - } - - /** - * Get the ratings associated with a plot
- * - The rating object may contain multiple categories - * - * @return Map of user who rated to the rating - */ - public HashMap getRatings() { - Plot base = this.getBasePlot(false); - HashMap map = new HashMap<>(); - if (!base.hasRatings()) { - return map; - } - for (Entry entry : base.getSettings().getRatings().entrySet()) { - map.put(entry.getKey(), new Rating(entry.getValue())); - } - return map; - } - - public boolean hasRatings() { - Plot base = this.getBasePlot(false); - return base.settings != null && base.settings.ratings != null; - } - - /** - * Resend all chunks inside the plot to nearby players
- * This should not need to be called - */ - public void refreshChunks() { - LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(getWorldName(), false); - HashSet chunks = new HashSet<>(); - for (RegionWrapper region : Plot.this.getRegions()) { - for (int x = region.minX >> 4; x <= region.maxX >> 4; x++) { - for (int z = region.minZ >> 4; z <= region.maxZ >> 4; z++) { - if (chunks.add(new ChunkLoc(x, z))) { - queue.refreshChunk(x, z); - } - } - } - } - } - - /** - * Remove the plot sign if it is set. - */ - public void removeSign() { - PlotManager manager = this.area.getPlotManager(); - if (!this.area.ALLOW_SIGNS) { - return; - } - Location loc = manager.getSignLoc(this.area, this); - LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(getWorldName(), false); - queue.setBlock(loc.getX(), loc.getY(), loc.getZ(), PlotBlock.get("air")); - queue.flush(); - } - - /** - * Set the plot sign if plot signs are enabled. - */ - public void setSign() { - if (this.owner == null) { - this.setSign("unknown"); - return; - } - this.setSign(UUIDHandler.getName(this.owner)); - } - - /** - * Register a plot and create it in the database
- * - The plot will not be created if the owner is null
- * - Any setting from before plot creation will not be saved until the server is stopped properly. i.e. Set any values/options after plot - * creation. - * - * @return true if plot was created successfully - */ - public boolean create() { - return this.create(this.owner, true); - } - - public boolean claim(final PlotPlayer player, boolean teleport, String schematic) { - if (!canClaim(player)) { - return false; - } - return claim(player, teleport, schematic, true); - } - - public boolean claim(final PlotPlayer player, boolean teleport, String schematic, - boolean updateDB) { - boolean result = EventUtil.manager.callClaim(player, this, false); - if (updateDB) { - if (!result || (!create(player.getUUID(), true))) { - return false; - } - } else { - area.addPlot(this); - } - setSign(player.getName()); - MainUtil.sendMessage(player, C.CLAIMED); - if (teleport) { - teleportPlayer(player); - } - PlotArea plotworld = getArea(); - if (plotworld.SCHEMATIC_ON_CLAIM) { - Schematic sch; - try { - if (schematic == null || schematic.isEmpty()) { - sch = SchematicHandler.manager.getSchematic(plotworld.SCHEMATIC_FILE); - } else { - sch = SchematicHandler.manager.getSchematic(schematic); - if (sch == null) { - sch = SchematicHandler.manager.getSchematic(plotworld.SCHEMATIC_FILE); - } - } - } catch (SchematicHandler.UnsupportedFormatException e) { - e.printStackTrace(); - return true; - } - SchematicHandler.manager.paste(sch, this, 0, 1, 0, Settings.Schematics.PASTE_ON_TOP, new RunnableVal() { - @Override public void run(Boolean value) { - if (value) { - MainUtil.sendMessage(player, C.SCHEMATIC_PASTE_SUCCESS); - } else { - MainUtil.sendMessage(player, C.SCHEMATIC_PASTE_FAILED); - } - } - }); - } - plotworld.getPlotManager().claimPlot(plotworld, this); - return true; - } - - /** - * Register a plot and create it in the database
- * - The plot will not be created if the owner is null
- * - Any setting from before plot creation will not be saved until the server is stopped properly. i.e. Set any values/options after plot - * creation. - * - * @param uuid the uuid of the plot owner - * @param notify notify - * @return true if plot was created successfully - */ - public boolean create(final UUID uuid, final boolean notify) { - if (uuid == null) { - throw new IllegalArgumentException("UUID cannot be null"); - } - this.owner = uuid; - Plot existing = this.area.getOwnedPlotAbs(this.id); - if (existing != null) { - throw new IllegalStateException("Plot already exists!"); - } - if (notify) { - Integer meta = (Integer) this.area.getMeta("worldBorder"); - if (meta != null) { - this.updateWorldBorder(); - } - } - connected_cache = null; - regions_cache = null; - this.getTrusted().clear(); - this.getMembers().clear(); - this.getDenied().clear(); - this.settings = new PlotSettings(); - if (this.area.addPlot(this)) { - DBFunc.createPlotAndSettings(this, () -> { - PlotArea plotworld = Plot.this.area; - if (notify && plotworld.AUTO_MERGE) { - Plot.this.autoMerge(-1, Integer.MAX_VALUE, uuid, true); - } - }); - return true; - } - return false; - } - - /** - * Set components such as border, wall, floor. - * (components are generator specific) - */ - public boolean setComponent(String component, String blocks) { - BlockBucket parsed = Configuration.BLOCK_BUCKET.parseString(blocks); - return !(parsed == null || parsed.isEmpty()) && this.setComponent(component, parsed); - } - - /** - * Retrieve the biome of the plot. - * - * @return the name of the biome - */ - public String getBiome() { - Location loc = this.getCenter(); - return WorldUtil.IMP.getBiome(loc.getWorld(), loc.getX(), loc.getZ()); - } - - /** - * Return the top location for the plot. - * - * @return - */ - public Location getTopAbs() { - Location top = this.area.getPlotManager().getPlotTopLocAbs(this.area, this.id); - top.setWorld(getWorldName()); - return top; - } - - /** - * Return the bottom location for the plot. - * - * @return - */ - public Location getBottomAbs() { - Location loc = this.area.getPlotManager().getPlotBottomLocAbs(this.area, this.id); - loc.setWorld(getWorldName()); - return loc; - } - - /** - * Swap the settings for two plots. - * - * @param plot the plot to swap data with - * @param whenDone the task to run at the end of this method. - * @return - */ - public boolean swapData(Plot plot, Runnable whenDone) { - if (this.owner == null) { - if (plot != null && plot.hasOwner()) { - plot.moveData(this, whenDone); - return true; - } - return false; - } - if (plot == null || plot.owner == null) { - this.moveData(plot, whenDone); - return true; - } - // Swap cached - PlotId temp = new PlotId(this.getId().x, this.getId().y); - this.getId().x = plot.getId().x; - this.getId().y = plot.getId().y; - plot.getId().x = temp.x; - plot.getId().y = temp.y; - this.area.removePlot(this.getId()); - plot.area.removePlot(plot.getId()); - this.getId().recalculateHash(); - plot.getId().recalculateHash(); - this.area.addPlotAbs(this); - plot.area.addPlotAbs(plot); - // Swap database - DBFunc.swapPlots(plot, this); - TaskManager.runTaskLater(whenDone, 1); - return true; - } - - /** - * Move the settings for a plot. - * - * @param plot the plot to move - * @param whenDone - * @return - */ - public boolean moveData(Plot plot, Runnable whenDone) { - if (this.owner == null) { - PlotSquared.debug(plot + " is unowned (single)"); - TaskManager.runTask(whenDone); - return false; - } - if (plot.hasOwner()) { - PlotSquared.debug(plot + " is unowned (multi)"); - TaskManager.runTask(whenDone); - return false; - } - this.area.removePlot(this.id); - this.getId().x = plot.getId().x; - this.getId().y = plot.getId().y; - this.getId().recalculateHash(); - this.area.addPlotAbs(this); - DBFunc.movePlot(this, plot); - TaskManager.runTaskLater(whenDone, 1); - return true; - } - - /** - * Gets the top loc of a plot (if mega, returns top loc of that mega plot) - If you would like each plot treated as - * a small plot use getPlotTopLocAbs(...) - * - * @return Location top of mega plot - */ - public Location getExtendedTopAbs() { - Location top = this.getTopAbs(); - if (!this.isMerged()) { - return top; - } - if (this.getMerged(2)) { - top.setZ(this.getRelative(2).getBottomAbs().getZ() - 1); - } - if (this.getMerged(1)) { - top.setX(this.getRelative(1).getBottomAbs().getX() - 1); - } - return top; - } - - /** - * Gets the bottom location for a plot.
- * - Does not respect mega plots
- * - Merged plots, only the road will be considered part of the plot
- * - * @return Location bottom of mega plot - */ - public Location getExtendedBottomAbs() { - Location bot = this.getBottomAbs(); - if (!this.isMerged()) { - return bot; - } - if (this.getMerged(0)) { - bot.setZ(this.getRelative(0).getTopAbs().getZ() + 1); - } - if (this.getMerged(3)) { - bot.setX(this.getRelative(3).getTopAbs().getX() + 1); - } - return bot; - } - - /** - * Returns the top and bottom location.
- * - If the plot is not connected, it will return its own corners
- * - the returned locations will not necessarily correspond to claimed plots if the connected plots do not form a rectangular shape - * - * @return new Location[] { bottom, top } - * @deprecated as merged plots no longer need to be rectangular - */ - @Deprecated public Location[] getCorners() { - if (!this.isMerged()) { - return new Location[] {this.getBottomAbs(), this.getTopAbs()}; - } - return MainUtil.getCorners(this.getWorldName(), this.getRegions()); - } - - /** - * Remove the east road section of a plot
- * - Used when a plot is merged
- */ - public void removeRoadEast() { - if (this.area.TYPE != 0 && this.area.TERRAIN > 1) { - if (this.area.TERRAIN == 3) { - return; - } - Plot other = this.getRelative(1); - Location bot = other.getBottomAbs(); - Location top = this.getTopAbs(); - Location pos1 = new Location(this.getWorldName(), top.getX(), 0, bot.getZ()); - Location pos2 = new Location(this.getWorldName(), bot.getX(), 256, top.getZ()); - ChunkManager.manager.regenerateRegion(pos1, pos2, true, null); - } else { - this.area.getPlotManager().removeRoadEast(this.area, this); - } - } - - /** - * @return - * @deprecated in favor of getCorners()[0];
- */ - // Won't remove as suggestion also points to deprecated method - @Deprecated public Location getBottom() { - return this.getCorners()[0]; - } - - /** - * @return the top corner of the plot - * @deprecated in favor of getCorners()[1]; - */ - // Won't remove as suggestion also points to deprecated method - @Deprecated public Location getTop() { - return this.getCorners()[1]; - } - - /** - * Swap the plot contents and settings with another location
- * - The destination must correspond to a valid plot of equal dimensions - * - * @param destination The other plot to swap with - * @param whenDone A task to run when finished, or null - * @return boolean if swap was successful - * @see ChunkManager#swap(Location, Location, Location, Location, Runnable) to swap terrain - * @see this#swapData(Plot, Runnable) to swap plot settings - * @see this#swapData(Plot, Runnable) - */ - public boolean swap(Plot destination, Runnable whenDone) { - return this.move(destination, whenDone, true); - } - - /** - * Move the plot to an empty location
- * - The location must be empty - * - * @param destination Where to move the plot - * @param whenDone A task to run when done, or null - * @return if the move was successful - */ - public boolean move(Plot destination, Runnable whenDone) { - return this.move(destination, whenDone, false); - } - - /** - * Get plot display name. - * - * @return alias if set, else id - */ - @Override public String toString() { - if (this.settings != null && this.settings.getAlias().length() > 1) { - return this.settings.getAlias(); - } - return this.area + ";" + this.id.x + ";" + this.id.y; - } - - - /** - * Remove a denied player (use DBFunc as well)
- * Using the * uuid will remove all users - * - * @param uuid - */ - public boolean removeDenied(UUID uuid) { - if (uuid == DBFunc.EVERYONE && !denied.contains(uuid)) { - boolean result = false; - for (UUID other : new HashSet<>(getDenied())) { - result = rmvDenied(other) || result; - } - return result; - } - return rmvDenied(uuid); - } - - private boolean rmvDenied(UUID uuid) { - for (Plot current : this.getConnectedPlots()) { - if (current.getDenied().remove(uuid)) { - DBFunc.removeDenied(current, uuid); - } else { - return false; - } - } - return true; - } - - /** - * Remove a helper (use DBFunc as well)
- * Using the * uuid will remove all users - * - * @param uuid - */ - public boolean removeTrusted(UUID uuid) { - if (uuid == DBFunc.EVERYONE && !trusted.contains(uuid)) { - boolean result = false; - for (UUID other : new HashSet<>(getTrusted())) { - result = rmvTrusted(other) || result; - } - return result; - } - return rmvTrusted(uuid); - } - - private boolean rmvTrusted(UUID uuid) { - for (Plot plot : this.getConnectedPlots()) { - if (plot.getTrusted().remove(uuid)) { - DBFunc.removeTrusted(plot, uuid); - } else { - return false; - } - } - return true; - } - - /** - * Remove a trusted user (use DBFunc as well)
- * Using the * uuid will remove all users - * - * @param uuid - */ - public boolean removeMember(UUID uuid) { - if (this.members == null) { - return false; - } - if (uuid == DBFunc.EVERYONE && !members.contains(uuid)) { - boolean result = false; - for (UUID other : new HashSet<>(this.members)) { - result = rmvMember(other) || result; - } - return result; - } - return rmvMember(uuid); - } - - private boolean rmvMember(UUID uuid) { - for (Plot current : this.getConnectedPlots()) { - if (current.getMembers().remove(uuid)) { - DBFunc.removeMember(current, uuid); - } else { - return false; - } - } - return true; - } - - /** - * Export the plot as a schematic to the configured output directory. - * - * @return - */ - public void export(final RunnableVal whenDone) { - SchematicHandler.manager.getCompoundTag(this, new RunnableVal() { - @Override public void run(final CompoundTag value) { - if (value == null) { - if (whenDone != null) { - whenDone.value = false; - TaskManager.runTask(whenDone); - } - } else { - TaskManager.runTaskAsync(() -> { - String name = Plot.this.id + "," + Plot.this.area + ',' + MainUtil - .getName(Plot.this.owner); - boolean result = SchematicHandler.manager.save(value, - Settings.Paths.SCHEMATICS + File.separator + name + ".schematic"); - if (whenDone != null) { - whenDone.value = result; - TaskManager.runTask(whenDone); - } - }); - } - } - }); - } - - /** - * Upload the plot as a schematic to the configured web interface. - * - * @param whenDone value will be null if uploading fails - */ - public void upload(final RunnableVal whenDone) { - SchematicHandler.manager.getCompoundTag(this, new RunnableVal() { - @Override public void run(CompoundTag value) { - SchematicHandler.manager.upload(value, null, null, whenDone); - } - }); - } - - /** - * Upload this plot as a world file
- * - The mca files are each 512x512, so depending on the plot size it may also download adjacent plots
- * - Works best when (plot width + road width) % 512 == 0
- * - * @param whenDone - * @see WorldUtil - */ - public void uploadWorld(RunnableVal whenDone) { - WorldUtil.IMP.upload(this, null, null, whenDone); - } - - @Override public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (this.getClass() != obj.getClass()) { - return false; - } - Plot other = (Plot) obj; - return this.hashCode() == other.hashCode() && this.id.equals(other.id) - && this.area == other.area; - } - - /** - * Get the plot hashcode
- * Note: The hashcode is unique if:
- * - Plots are in the same world
- * - The x,z coordinates are between Short.MIN_VALUE and Short.MAX_VALUE
- * - * @return integer. - */ - @Override public int hashCode() { - return this.id.hashCode(); - } - - /** - * Get the flags specific to this plot
- * - Does not take default flags into account
- * - * @return - */ - public HashMap, Object> getFlags() { - return this.getSettings().flags; - } - - /** - * Set a flag for this plot. - * - * @param flags - */ - public void setFlags(HashMap, Object> flags) { - FlagManager.setPlotFlags(this, flags); - } - - /** - * Get the plot alias. - * - Returns an empty string if no alias is set - * - * @return The plot alias - */ - public String getAlias() { - if (this.settings == null) { - return ""; - } - return this.settings.getAlias(); - } - - /** - * Set the plot alias. - * - * @param alias The alias - */ - public void setAlias(String alias) { - for (Plot current : this.getConnectedPlots()) { - String name = this.getSettings().getAlias(); - if (alias == null) { - alias = ""; - } - if (name.equals(alias)) { - return; - } - current.getSettings().setAlias(alias); - DBFunc.setAlias(current, alias); - } - } - - /** - * Set the raw merge data
- * - Updates DB
- * - Does not modify terrain
- * ----------
- * 0 = north
- * 1 = east
- * 2 = south
- * 3 = west
- * ----------
- * - * @param direction - * @param value - */ - public void setMerged(int direction, boolean value) { - if (this.getSettings().setMerged(direction, value)) { - if (value) { - Plot other = this.getRelative(direction).getBasePlot(false); - if (!other.equals(this.getBasePlot(false))) { - Plot base = other.id.y < this.id.y - || other.id.y == this.id.y && other.id.x < this.id.x ? other : this.origin; - this.origin.origin = base; - other.origin = base; - this.origin = base; - connected_cache = null; - } - } else { - if (this.origin != null) { - this.origin.origin = null; - this.origin = null; - } - connected_cache = null; - } - DBFunc.setMerged(this, this.getSettings().getMerged()); - regions_cache = null; - } - } - - /** - * Get the merged array. - * - * @return boolean [ north, east, south, west ] - */ - public boolean[] getMerged() { - return this.getSettings().getMerged(); - } - - /** - * Set the raw merge data
- * - Updates DB
- * - Does not modify terrain
- * Get if the plot is merged in a direction
- * ----------
- * 0 = north
- * 1 = east
- * 2 = south
- * 3 = west
- * ----------
- * Note: Diagonal merging (4-7) must be done by merging the corresponding plots. - * - * @param merged - */ - public void setMerged(boolean[] merged) { - this.getSettings().setMerged(merged); - DBFunc.setMerged(this, merged); - clearCache(); - } - - public void clearCache() { - connected_cache = null; - regions_cache = null; + } else { if (this.origin != null) { - this.origin.origin = null; - this.origin = null; + this.origin.origin = null; + this.origin = null; } + connected_cache = null; + } + DBFunc.setMerged(this, this.getSettings().getMerged()); + regions_cache = null; + } + } + + /** + * Get the merged array. + * + * @return boolean [ north, east, south, west ] + */ + public boolean[] getMerged() { + return this.getSettings().getMerged(); + } + + /** + * Set the raw merge data
- Updates DB
- Does not modify terrain
Get if the plot is + * merged in a direction
----------
0 = north
1 = east
2 = south
3 = west
+ * ----------
Note: Diagonal merging (4-7) must be done by merging the corresponding plots. + */ + public void setMerged(boolean[] merged) { + this.getSettings().setMerged(merged); + DBFunc.setMerged(this, merged); + clearCache(); + } + + private void clearCache() { + connected_cache = null; + regions_cache = null; + if (this.origin != null) { + this.origin.origin = null; + this.origin = null; + } + } + + /** + * Get the set home location or 0,0,0 if no location is set
- Does not take the default home + * location into account + * + * @see #getHome() + */ + public BlockLoc getPosition() { + return this.getSettings().getPosition(); + } + + /** + * Check if a plot can be claimed by the provided player. + * + * @param player the claiming player + */ + public boolean canClaim(@Nullable PlotPlayer player) { + PlotCluster cluster = this.getCluster(); + if (cluster != null && player != null) { + if (!cluster.isAdded(player.getUUID()) && !Permissions + .hasPermission(player, "plots.admin.command.claim")) { + return false; + } + } + return this.guessOwner() == null && !isMerged(); + } + + /** + * Guess the owner of a plot either by the value in memory, or the sign data
Note: Recovering + * from sign information is useful if e.g. PlotMe conversion wasn't successful + * + * @return UUID + */ + public UUID guessOwner() { + if (this.hasOwner()) { + return this.owner; + } + if (!this.area.ALLOW_SIGNS) { + return null; + } + try { + final Location loc = this.getManager().getSignLoc(this.area, this); + String[] lines = TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(String[] value) { + ChunkManager.manager.loadChunk(loc.getWorld(), loc.getChunkLoc(), false); + this.value = WorldUtil.IMP.getSign(loc); + } + }); + if (lines == null) { + return null; + } + loop: + for (int i = 4; i > 0; i--) { + String caption = C.valueOf("OWNER_SIGN_LINE_" + i).s(); + int index = caption.indexOf("%plr%"); + if (index < 0) { + continue; + } + String line = lines[i - 1]; + if (line.length() <= index) { + return null; + } + String name = line.substring(index); + if (name.isEmpty()) { + return null; + } + UUID owner = UUIDHandler.getUUID(name, null); + if (owner != null) { + this.owner = owner; + break; + } + if (lines[i - 1].length() == 15) { + BiMap map = UUIDHandler.getUuidMap(); + for (Entry entry : map.entrySet()) { + String key = entry.getKey().value; + if (key.length() > name.length() && key.startsWith(name)) { + this.owner = entry.getValue(); + break loop; + } + } + } + this.owner = UUID.nameUUIDFromBytes( + ("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8)); + break; + } + if (this.hasOwner()) { + this.create(); + } + return this.owner; + } catch (IllegalArgumentException ignored) { + return null; + } + } + + /** + * Remove the south road section of a plot
- Used when a plot is merged
+ */ + public void removeRoadSouth() { + if (this.area.TYPE != 0 && this.area.TERRAIN > 1) { + if (this.area.TERRAIN == 3) { + return; + } + Plot other = this.getRelative(2); + Location bot = other.getBottomAbs(); + Location top = this.getTopAbs(); + Location pos1 = new Location(this.getWorldName(), bot.getX(), 0, top.getZ()); + Location pos2 = new Location(this.getWorldName(), top.getX(), 256, bot.getZ()); + ChunkManager.manager.regenerateRegion(pos1, pos2, true, null); + } else { + this.getManager().removeRoadSouth(this.area, this); + } + } + + /** + * Auto merge a plot in a specific direction
+ * + * @param dir The direction to merge
-1 = All directions
0 = north
1 = east
2 = + * south
3 = west
+ * @param max The max number of merges to do + * @param uuid The UUID it is allowed to merge with + * @param removeRoads Whether to remove roads + * @return true if a merge takes place + */ + public boolean autoMerge(int dir, int max, UUID uuid, boolean removeRoads) { + if (this.owner == null) { + return false; + } + if (!EventUtil.manager.callMerge(this, dir, max)) { + return false; + } + HashSet visited = new HashSet<>(); + HashSet merged = new HashSet<>(); + Set connected = this.getConnectedPlots(); + for (Plot current : connected) { + merged.add(current.getId()); + } + ArrayDeque frontier = new ArrayDeque<>(connected); + Plot current; + boolean toReturn = false; + while ((current = frontier.poll()) != null && max >= 0) { + if (visited.contains(current)) { + continue; + } + visited.add(current); + Set plots; + if ((dir == -1 || dir == 0) && !current.getMerged(0)) { + Plot other = current.getRelative(0); + if (other != null && other.isOwner(uuid) && ( + other.getBasePlot(false).equals(current.getBasePlot(false)) + || (plots = other.getConnectedPlots()).size() <= max && frontier + .addAll(plots) && (max -= plots.size()) != -1)) { + current.mergePlot(other, removeRoads); + merged.add(current.getId()); + merged.add(other.getId()); + toReturn = true; + } + } + if (max >= 0 && (dir == -1 || dir == 1) && !current.getMerged(1)) { + Plot other = current.getRelative(1); + if (other != null && other.isOwner(uuid) && ( + other.getBasePlot(false).equals(current.getBasePlot(false)) + || (plots = other.getConnectedPlots()).size() <= max && frontier + .addAll(plots) && (max -= plots.size()) != -1)) { + current.mergePlot(other, removeRoads); + merged.add(current.getId()); + merged.add(other.getId()); + toReturn = true; + } + } + if (max >= 0 && (dir == -1 || dir == 2) && !current.getMerged(2)) { + Plot other = current.getRelative(2); + if (other != null && other.isOwner(uuid) && ( + other.getBasePlot(false).equals(current.getBasePlot(false)) + || (plots = other.getConnectedPlots()).size() <= max && frontier + .addAll(plots) && (max -= plots.size()) != -1)) { + current.mergePlot(other, removeRoads); + merged.add(current.getId()); + merged.add(other.getId()); + toReturn = true; + } + } + if (max >= 0 && (dir == -1 || dir == 3) && !current.getMerged(3)) { + Plot other = current.getRelative(3); + if (other != null && other.isOwner(uuid) && ( + other.getBasePlot(false).equals(current.getBasePlot(false)) + || (plots = other.getConnectedPlots()).size() <= max && frontier + .addAll(plots) && (max -= plots.size()) != -1)) { + current.mergePlot(other, removeRoads); + merged.add(current.getId()); + merged.add(other.getId()); + toReturn = true; + } + } + } + if (removeRoads && toReturn) { + ArrayList ids = new ArrayList<>(merged); + this.getManager().finishPlotMerge(this.area, ids); + } + return toReturn; + } + + /** + * Merge the plot settings
- Used when a plot is merged
+ */ + public void mergeData(Plot b) { + HashMap, Object> flags1 = this.getFlags(); + HashMap, Object> flags2 = b.getFlags(); + if ((!flags1.isEmpty() || !flags2.isEmpty()) && !flags1.equals(flags2)) { + boolean greater = flags1.size() > flags2.size(); + if (greater) { + flags1.putAll(flags2); + } else { + flags2.putAll(flags1); + } + HashMap, Object> net = (greater ? flags1 : flags2); + this.setFlags(net); + b.setFlags(net); + } + if (!this.getAlias().isEmpty()) { + b.setAlias(this.getAlias()); + } else if (!b.getAlias().isEmpty()) { + this.setAlias(b.getAlias()); + } + for (UUID uuid : this.getTrusted()) { + b.addTrusted(uuid); + } + for (UUID uuid : b.getTrusted()) { + this.addTrusted(uuid); + } + for (UUID uuid : this.getMembers()) { + b.addMember(uuid); + } + for (UUID uuid : b.getMembers()) { + this.addMember(uuid); } - /** - * Get the set home location or 0,0,0 if no location is set
- * - Does not take the default home location into account - * - * @return - * @see #getHome() - */ - public BlockLoc getPosition() { - return this.getSettings().getPosition(); + for (UUID uuid : this.getDenied()) { + b.addDenied(uuid); } - - /** - * Check if a plot can be claimed by the provided player. - * - * @param player the claiming player - * @return - */ - public boolean canClaim(@Nullable PlotPlayer player) { - PlotCluster cluster = this.getCluster(); - if (cluster != null && player != null) { - if (!cluster.isAdded(player.getUUID()) && !Permissions - .hasPermission(player, "plots.admin.command.claim")) { - return false; - } - } - return this.guessOwner() == null && !isMerged(); + for (UUID uuid : b.getDenied()) { + this.addDenied(uuid); } + } - /** - * Guess the owner of a plot either by the value in memory, or the sign data
- * Note: Recovering from sign information is useful if e.g. PlotMe conversion wasn't successful - * - * @return UUID - */ - public UUID guessOwner() { - if (this.hasOwner()) { - return this.owner; - } - if (!this.area.ALLOW_SIGNS) { - return null; - } - try { - final Location loc = this.getManager().getSignLoc(this.area, this); - String[] lines = TaskManager.IMP.sync(new RunnableVal() { - @Override public void run(String[] value) { - ChunkManager.manager.loadChunk(loc.getWorld(), loc.getChunkLoc(), false); - this.value = WorldUtil.IMP.getSign(loc); - } - }); - if (lines == null) { - return null; - } - loop: - for (int i = 4; i > 0; i--) { - String caption = C.valueOf("OWNER_SIGN_LINE_" + i).s(); - int index = caption.indexOf("%plr%"); - if (index < 0) { - continue; - } - String line = lines[i - 1]; - if (line.length() <= index) { - return null; - } - String name = line.substring(index); - if (name.isEmpty()) { - return null; - } - UUID owner = UUIDHandler.getUUID(name, null); - if (owner != null) { - this.owner = owner; - break; - } - if (lines[i - 1].length() == 15) { - BiMap map = UUIDHandler.getUuidMap(); - for (Entry entry : map.entrySet()) { - String key = entry.getKey().value; - if (key.length() > name.length() && key.startsWith(name)) { - this.owner = entry.getValue(); - break loop; - } - } - } - this.owner = UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8)); - break; - } - if (this.hasOwner()) { - this.create(); - } - return this.owner; - } catch (IllegalArgumentException ignored) { - return null; - } + /** + * Remove the SE road (only effects terrain) + */ + public void removeRoadSouthEast() { + if (this.area.TYPE != 0 && this.area.TERRAIN > 1) { + if (this.area.TERRAIN == 3) { + return; + } + Plot other = this.getRelative(1, 1); + Location pos1 = this.getTopAbs().add(1, 0, 1); + Location pos2 = other.getBottomAbs().subtract(1, 0, 1); + pos1.setY(0); + pos2.setY(256); + ChunkManager.manager.regenerateRegion(pos1, pos2, true, null); + } else { + this.area.getPlotManager().removeRoadSouthEast(this.area, this); } + } - /** - * Remove the south road section of a plot
- * - Used when a plot is merged
- */ - public void removeRoadSouth() { - if (this.area.TYPE != 0 && this.area.TERRAIN > 1) { - if (this.area.TERRAIN == 3) { - return; - } - Plot other = this.getRelative(2); - Location bot = other.getBottomAbs(); - Location top = this.getTopAbs(); - Location pos1 = new Location(this.getWorldName(), bot.getX(), 0, top.getZ()); - Location pos2 = new Location(this.getWorldName(), top.getX(), 256, bot.getZ()); - ChunkManager.manager.regenerateRegion(pos1, pos2, true, null); + /** + * Get the plot in a relative location
Note: May be null if the partial plot area does not + * include the relative location + * + * @return Plot + */ + public Plot getRelative(int x, int y) { + return this.area.getPlotAbs(this.id.getRelative(x, y)); + } + + public Plot getRelative(PlotArea area, int x, int y) { + return area.getPlotAbs(this.id.getRelative(x, y)); + } + + /** + * Get the plot in a relative direction
0 = north
1 = east
2 = south
3 = west
+ * Note: May be null if the partial plot area does not include the relative location + */ + public Plot getRelative(int direction) { + return this.area.getPlotAbs(this.id.getRelative(direction)); + } + + /** + * Get a set of plots connected (and including) this plot
- This result is cached globally + */ + public Set getConnectedPlots() { + if (this.settings == null || !this.isMerged()) { + return Collections.singleton(this); + } + boolean[] merged = this.getMerged(); + int hash = MainUtil.hash(merged); + if (hash == 0) { + return Collections.singleton(this); + } + if (connected_cache != null && connected_cache.contains(this)) { + return connected_cache; + } + regions_cache = null; + + HashSet tmpSet = new HashSet<>(); + ArrayDeque frontier = new ArrayDeque<>(); + HashSet queuecache = new HashSet<>(); + tmpSet.add(this); + Plot tmp; + if (merged[0]) { + tmp = this.area.getPlotAbs(this.id.getRelative(0)); + if (!tmp.getMerged(2)) { + // invalid merge + PlotSquared.debug("Fixing invalid merge: " + this); + if (tmp.isOwnerAbs(this.owner)) { + tmp.getSettings().setMerged(2, true); + DBFunc.setMerged(tmp, tmp.getSettings().getMerged()); } else { - this.getManager().removeRoadSouth(this.area, this); + this.getSettings().setMerged(0, false); + DBFunc.setMerged(this, this.getSettings().getMerged()); } + } + queuecache.add(tmp); + frontier.add(tmp); } - - /** - * Auto merge a plot in a specific direction
- * - * @param dir The direction to merge
- * -1 = All directions
- * 0 = north
- * 1 = east
- * 2 = south
- * 3 = west
- * @param max The max number of merges to do - * @param uuid The UUID it is allowed to merge with - * @param removeRoads Whether to remove roads - * @return true if a merge takes place - */ - public boolean autoMerge(int dir, int max, UUID uuid, boolean removeRoads) { - if (this.owner == null) { - return false; - } - if (!EventUtil.manager.callMerge(this, dir, max)) { - return false; - } - HashSet visited = new HashSet<>(); - HashSet merged = new HashSet<>(); - Set connected = this.getConnectedPlots(); - for (Plot current : connected) { - merged.add(current.getId()); - } - ArrayDeque frontier = new ArrayDeque<>(connected); - Plot current; - boolean toReturn = false; - while ((current = frontier.poll()) != null && max >= 0) { - if (visited.contains(current)) { - continue; - } - visited.add(current); - Set plots; - if ((dir == -1 || dir == 0) && !current.getMerged(0)) { - Plot other = current.getRelative(0); - if (other != null && other.isOwner(uuid) && ( - other.getBasePlot(false).equals(current.getBasePlot(false)) - || (plots = other.getConnectedPlots()).size() <= max && frontier - .addAll(plots) && (max -= plots.size()) != -1)) { - current.mergePlot(other, removeRoads); - merged.add(current.getId()); - merged.add(other.getId()); - toReturn = true; - } - } - if (max >= 0 && (dir == -1 || dir == 1) && !current.getMerged(1)) { - Plot other = current.getRelative(1); - if (other != null && other.isOwner(uuid) && ( - other.getBasePlot(false).equals(current.getBasePlot(false)) - || (plots = other.getConnectedPlots()).size() <= max && frontier - .addAll(plots) && (max -= plots.size()) != -1)) { - current.mergePlot(other, removeRoads); - merged.add(current.getId()); - merged.add(other.getId()); - toReturn = true; - } - } - if (max >= 0 && (dir == -1 || dir == 2) && !current.getMerged(2)) { - Plot other = current.getRelative(2); - if (other != null && other.isOwner(uuid) && ( - other.getBasePlot(false).equals(current.getBasePlot(false)) - || (plots = other.getConnectedPlots()).size() <= max && frontier - .addAll(plots) && (max -= plots.size()) != -1)) { - current.mergePlot(other, removeRoads); - merged.add(current.getId()); - merged.add(other.getId()); - toReturn = true; - } - } - if (max >= 0 && (dir == -1 || dir == 3) && !current.getMerged(3)) { - Plot other = current.getRelative(3); - if (other != null && other.isOwner(uuid) && ( - other.getBasePlot(false).equals(current.getBasePlot(false)) - || (plots = other.getConnectedPlots()).size() <= max && frontier - .addAll(plots) && (max -= plots.size()) != -1)) { - current.mergePlot(other, removeRoads); - merged.add(current.getId()); - merged.add(other.getId()); - toReturn = true; - } - } - } - if (removeRoads && toReturn) { - ArrayList ids = new ArrayList<>(merged); - this.getManager().finishPlotMerge(this.area, ids); - } - return toReturn; - } - - /** - * Merge the plot settings
- * - Used when a plot is merged
- * - * @param b - */ - public void mergeData(Plot b) { - HashMap, Object> flags1 = this.getFlags(); - HashMap, Object> flags2 = b.getFlags(); - if ((!flags1.isEmpty() || !flags2.isEmpty()) && !flags1.equals(flags2)) { - boolean greater = flags1.size() > flags2.size(); - if (greater) { - flags1.putAll(flags2); - } else { - flags2.putAll(flags1); - } - HashMap, Object> net = (greater ? flags1 : flags2); - this.setFlags(net); - b.setFlags(net); - } - if (!this.getAlias().isEmpty()) { - b.setAlias(this.getAlias()); - } else if (!b.getAlias().isEmpty()) { - this.setAlias(b.getAlias()); - } - for (UUID uuid : this.getTrusted()) { - b.addTrusted(uuid); - } - for (UUID uuid : b.getTrusted()) { - this.addTrusted(uuid); - } - for (UUID uuid : this.getMembers()) { - b.addMember(uuid); - } - for (UUID uuid : b.getMembers()) { - this.addMember(uuid); - } - - for (UUID uuid : this.getDenied()) { - b.addDenied(uuid); - } - for (UUID uuid : b.getDenied()) { - this.addDenied(uuid); - } - } - - /** - * Remove the SE road (only effects terrain) - */ - public void removeRoadSouthEast() { - if (this.area.TYPE != 0 && this.area.TERRAIN > 1) { - if (this.area.TERRAIN == 3) { - return; - } - Plot other = this.getRelative(1, 1); - Location pos1 = this.getTopAbs().add(1, 0, 1); - Location pos2 = other.getBottomAbs().subtract(1, 0, 1); - pos1.setY(0); - pos2.setY(256); - ChunkManager.manager.regenerateRegion(pos1, pos2, true, null); + if (merged[1]) { + tmp = this.area.getPlotAbs(this.id.getRelative(1)); + if (!tmp.getMerged(3)) { + // invalid merge + PlotSquared.debug("Fixing invalid merge: " + this); + if (tmp.isOwnerAbs(this.owner)) { + tmp.getSettings().setMerged(3, true); + DBFunc.setMerged(tmp, tmp.getSettings().getMerged()); } else { - this.area.getPlotManager().removeRoadSouthEast(this.area, this); + this.getSettings().setMerged(1, false); + DBFunc.setMerged(this, this.getSettings().getMerged()); } + } + queuecache.add(tmp); + frontier.add(tmp); } - - /** - * Get the plot in a relative location
- * Note: May be null if the partial plot area does not include the relative location - * - * @param x - * @param y - * @return Plot - */ - public Plot getRelative(int x, int y) { - return this.area.getPlotAbs(this.id.getRelative(x, y)); + if (merged[2]) { + tmp = this.area.getPlotAbs(this.id.getRelative(2)); + if (!tmp.getMerged(0)) { + // invalid merge + PlotSquared.debug("Fixing invalid merge: " + this); + if (tmp.isOwnerAbs(this.owner)) { + tmp.getSettings().setMerged(0, true); + DBFunc.setMerged(tmp, tmp.getSettings().getMerged()); + } else { + this.getSettings().setMerged(2, false); + DBFunc.setMerged(this, this.getSettings().getMerged()); + } + } + queuecache.add(tmp); + frontier.add(tmp); } - - public Plot getRelative(PlotArea area, int x, int y) { - return area.getPlotAbs(this.id.getRelative(x, y)); + if (merged[3]) { + tmp = this.area.getPlotAbs(this.id.getRelative(3)); + if (!tmp.getMerged(1)) { + // invalid merge + PlotSquared.debug("Fixing invalid merge: " + this); + if (tmp.isOwnerAbs(this.owner)) { + tmp.getSettings().setMerged(1, true); + DBFunc.setMerged(tmp, tmp.getSettings().getMerged()); + } else { + this.getSettings().setMerged(3, false); + DBFunc.setMerged(this, this.getSettings().getMerged()); + } + } + queuecache.add(tmp); + frontier.add(tmp); } - - /** - * Get the plot in a relative direction
- * 0 = north
- * 1 = east
- * 2 = south
- * 3 = west
- * Note: May be null if the partial plot area does not include the relative location - * - * @param direction - * @return - */ - public Plot getRelative(int direction) { - return this.area.getPlotAbs(this.id.getRelative(direction)); + Plot current; + while ((current = frontier.poll()) != null) { + if (current.owner == null || current.settings == null) { + // Invalid plot + // merged onto unclaimed plot + PlotSquared + .debug("Ignoring invalid merged plot: " + current + " | " + current.owner); + continue; + } + tmpSet.add(current); + queuecache.remove(current); + merged = current.getMerged(); + if (merged[0]) { + tmp = current.area.getPlotAbs(current.id.getRelative(0)); + if (tmp != null && !queuecache.contains(tmp) && !tmpSet.contains(tmp)) { + queuecache.add(tmp); + frontier.add(tmp); + } + } + if (merged[1]) { + tmp = current.area.getPlotAbs(current.id.getRelative(1)); + if (tmp != null && !queuecache.contains(tmp) && !tmpSet.contains(tmp)) { + queuecache.add(tmp); + frontier.add(tmp); + } + } + if (merged[2]) { + tmp = current.area.getPlotAbs(current.id.getRelative(2)); + if (tmp != null && !queuecache.contains(tmp) && !tmpSet.contains(tmp)) { + queuecache.add(tmp); + frontier.add(tmp); + } + } + if (merged[3]) { + tmp = current.area.getPlotAbs(current.id.getRelative(3)); + if (tmp != null && !queuecache.contains(tmp) && !tmpSet.contains(tmp)) { + queuecache.add(tmp); + frontier.add(tmp); + } + } } + connected_cache = tmpSet; + return tmpSet; + } - /** - * Get a set of plots connected (and including) this plot
- * - This result is cached globally - * - * @return - */ - public Set getConnectedPlots() { - if (this.settings == null) { - return Collections.singleton(this); - } - boolean[] merged = this.getMerged(); - int hash = MainUtil.hash(merged); - if (hash == 0) { - return Collections.singleton(this); - } - if (connected_cache != null && connected_cache.contains(this)) { - return connected_cache; - } - regions_cache = null; - - HashSet tmpSet = new HashSet<>(); - ArrayDeque frontier = new ArrayDeque<>(); - HashSet queuecache = new HashSet<>(); - tmpSet.add(this); - Plot tmp; - if (merged[0]) { - tmp = this.area.getPlotAbs(this.id.getRelative(0)); - if (!tmp.getMerged(2)) { - // invalid merge - PlotSquared.debug("Fixing invalid merge: " + this); - if (tmp.isOwnerAbs(this.owner)) { - tmp.getSettings().setMerged(2, true); - DBFunc.setMerged(tmp, tmp.getSettings().getMerged()); - } else { - this.getSettings().setMerged(0, false); - DBFunc.setMerged(this, this.getSettings().getMerged()); - } - } - queuecache.add(tmp); - frontier.add(tmp); - } - if (merged[1]) { - tmp = this.area.getPlotAbs(this.id.getRelative(1)); - if (!tmp.getMerged(3)) { - // invalid merge - PlotSquared.debug("Fixing invalid merge: " + this); - if (tmp.isOwnerAbs(this.owner)) { - tmp.getSettings().setMerged(3, true); - DBFunc.setMerged(tmp, tmp.getSettings().getMerged()); - } else { - this.getSettings().setMerged(1, false); - DBFunc.setMerged(this, this.getSettings().getMerged()); - } - } - queuecache.add(tmp); - frontier.add(tmp); - } - if (merged[2]) { - tmp = this.area.getPlotAbs(this.id.getRelative(2)); - if (!tmp.getMerged(0)) { - // invalid merge - PlotSquared.debug("Fixing invalid merge: " + this); - if (tmp.isOwnerAbs(this.owner)) { - tmp.getSettings().setMerged(0, true); - DBFunc.setMerged(tmp, tmp.getSettings().getMerged()); - } else { - this.getSettings().setMerged(2, false); - DBFunc.setMerged(this, this.getSettings().getMerged()); - } - } - queuecache.add(tmp); - frontier.add(tmp); - } - if (merged[3]) { - tmp = this.area.getPlotAbs(this.id.getRelative(3)); - if (!tmp.getMerged(1)) { - // invalid merge - PlotSquared.debug("Fixing invalid merge: " + this); - if (tmp.isOwnerAbs(this.owner)) { - tmp.getSettings().setMerged(1, true); - DBFunc.setMerged(tmp, tmp.getSettings().getMerged()); - } else { - this.getSettings().setMerged(3, false); - DBFunc.setMerged(this, this.getSettings().getMerged()); - } - } - queuecache.add(tmp); - frontier.add(tmp); - } - Plot current; - while ((current = frontier.poll()) != null) { - if (current.owner == null || current.settings == null) { - // Invalid plot - // merged onto unclaimed plot - PlotSquared - .debug("Ignoring invalid merged plot: " + current + " | " + current.owner); - continue; - } - tmpSet.add(current); - queuecache.remove(current); - merged = current.getMerged(); - if (merged[0]) { - tmp = current.area.getPlotAbs(current.id.getRelative(0)); - if (tmp != null && !queuecache.contains(tmp) && !tmpSet.contains(tmp)) { - queuecache.add(tmp); - frontier.add(tmp); - } - } - if (merged[1]) { - tmp = current.area.getPlotAbs(current.id.getRelative(1)); - if (tmp != null && !queuecache.contains(tmp) && !tmpSet.contains(tmp)) { - queuecache.add(tmp); - frontier.add(tmp); - } - } - if (merged[2]) { - tmp = current.area.getPlotAbs(current.id.getRelative(2)); - if (tmp != null && !queuecache.contains(tmp) && !tmpSet.contains(tmp)) { - queuecache.add(tmp); - frontier.add(tmp); - } - } - if (merged[3]) { - tmp = current.area.getPlotAbs(current.id.getRelative(3)); - if (tmp != null && !queuecache.contains(tmp) && !tmpSet.contains(tmp)) { - queuecache.add(tmp); - frontier.add(tmp); - } - } - } - connected_cache = tmpSet; - return tmpSet; + /** + * This will combine each plot into effective rectangular regions
- This result is cached + * globally
- Useful for handling non rectangular shapes + */ + public HashSet getRegions() { + if (regions_cache != null && connected_cache != null && connected_cache.contains(this)) { + return regions_cache; } - - /** - * This will combine each plot into effective rectangular regions
- * - This result is cached globally
- * - Useful for handling non rectangular shapes - * - * @return - */ - public HashSet getRegions() { - if (regions_cache != null && connected_cache != null && connected_cache.contains(this)) { - return regions_cache; + if (!this.isMerged()) { + Location pos1 = this.getBottomAbs(); + Location pos2 = this.getTopAbs(); + connected_cache = new HashSet<>(Collections.singletonList(this)); + regions_cache = new HashSet<>(1); + regions_cache.add( + new RegionWrapper(pos1.getX(), pos2.getX(), pos1.getY(), pos2.getY(), pos1.getZ(), + pos2.getZ())); + return regions_cache; + } + Set plots = this.getConnectedPlots(); + HashSet regions = regions_cache = new HashSet<>(); + HashSet visited = new HashSet<>(); + for (Plot current : plots) { + if (visited.contains(current.getId())) { + continue; + } + boolean merge = true; + PlotId bot = new PlotId(current.getId().x, current.getId().y); + PlotId top = new PlotId(current.getId().x, current.getId().y); + while (merge) { + merge = false; + ArrayList ids = MainUtil.getPlotSelectionIds(new PlotId(bot.x, bot.y - 1), + new PlotId(top.x, bot.y - 1)); + boolean tmp = true; + for (PlotId id : ids) { + Plot plot = this.area.getPlotAbs(id); + if (plot == null || !plot.getMerged(2) || visited.contains(plot.getId())) { + tmp = false; + } } - if (!this.isMerged()) { - Location pos1 = this.getBottomAbs(); - Location pos2 = this.getTopAbs(); - connected_cache = new HashSet<>(Collections.singletonList(this)); - regions_cache = new HashSet<>(1); - regions_cache.add( - new RegionWrapper(pos1.getX(), pos2.getX(), pos1.getY(), pos2.getY(), pos1.getZ(), - pos2.getZ())); - return regions_cache; + if (tmp) { + merge = true; + bot.y--; } - Set plots = this.getConnectedPlots(); - HashSet regions = regions_cache = new HashSet<>(); - HashSet visited = new HashSet<>(); - for (Plot current : plots) { - if (visited.contains(current.getId())) { - continue; - } - boolean merge = true; - PlotId bot = new PlotId(current.getId().x, current.getId().y); - PlotId top = new PlotId(current.getId().x, current.getId().y); - while (merge) { - merge = false; - ArrayList ids = MainUtil.getPlotSelectionIds(new PlotId(bot.x, bot.y - 1), - new PlotId(top.x, bot.y - 1)); - boolean tmp = true; - for (PlotId id : ids) { - Plot plot = this.area.getPlotAbs(id); - if (plot == null || !plot.getMerged(2) || visited.contains(plot.getId())) { - tmp = false; - } - } - if (tmp) { - merge = true; - bot.y--; - } - ids = MainUtil.getPlotSelectionIds(new PlotId(top.x + 1, bot.y), - new PlotId(top.x + 1, top.y)); - tmp = true; - for (PlotId id : ids) { - Plot plot = this.area.getPlotAbs(id); - if (plot == null || !plot.getMerged(3) || visited.contains(plot.getId())) { - tmp = false; - } - } - if (tmp) { - merge = true; - top.x++; - } - ids = MainUtil.getPlotSelectionIds(new PlotId(bot.x, top.y + 1), - new PlotId(top.x, top.y + 1)); - tmp = true; - for (PlotId id : ids) { - Plot plot = this.area.getPlotAbs(id); - if (plot == null || !plot.getMerged(0) || visited.contains(plot.getId())) { - tmp = false; - } - } - if (tmp) { - merge = true; - top.y++; - } - ids = MainUtil.getPlotSelectionIds(new PlotId(bot.x - 1, bot.y), - new PlotId(bot.x - 1, top.y)); - tmp = true; - for (PlotId id : ids) { - Plot plot = this.area.getPlotAbs(id); - if (plot == null || !plot.getMerged(1) || visited.contains(plot.getId())) { - tmp = false; - } - } - if (tmp) { - merge = true; - bot.x--; - } - } - Location gtopabs = this.area.getPlotAbs(top).getTopAbs(); - Location gbotabs = this.area.getPlotAbs(bot).getBottomAbs(); - for (PlotId id : MainUtil.getPlotSelectionIds(bot, top)) { - visited.add(id); - } - for (int x = bot.x; x <= top.x; x++) { - Plot plot = this.area.getPlotAbs(new PlotId(x, top.y)); - if (plot.getMerged(2)) { - // south wedge - Location toploc = plot.getExtendedTopAbs(); - Location botabs = plot.getBottomAbs(); - Location topabs = plot.getTopAbs(); - regions.add(new RegionWrapper(botabs.getX(), topabs.getX(), topabs.getZ() + 1, - toploc.getZ())); - if (plot.getMerged(5)) { - regions.add( - new RegionWrapper(topabs.getX() + 1, toploc.getX(), topabs.getZ() + 1, - toploc.getZ())); - // intersection - } - } - } - - for (int y = bot.y; y <= top.y; y++) { - Plot plot = this.area.getPlotAbs(new PlotId(top.x, y)); - if (plot.getMerged(1)) { - // east wedge - Location toploc = plot.getExtendedTopAbs(); - Location botabs = plot.getBottomAbs(); - Location topabs = plot.getTopAbs(); - regions.add(new RegionWrapper(topabs.getX() + 1, toploc.getX(), botabs.getZ(), - topabs.getZ())); - if (plot.getMerged(5)) { - regions.add( - new RegionWrapper(topabs.getX() + 1, toploc.getX(), topabs.getZ() + 1, - toploc.getZ())); - // intersection - } - } - } + ids = MainUtil.getPlotSelectionIds(new PlotId(top.x + 1, bot.y), + new PlotId(top.x + 1, top.y)); + tmp = true; + for (PlotId id : ids) { + Plot plot = this.area.getPlotAbs(id); + if (plot == null || !plot.getMerged(3) || visited.contains(plot.getId())) { + tmp = false; + } + } + if (tmp) { + merge = true; + top.x++; + } + ids = MainUtil.getPlotSelectionIds(new PlotId(bot.x, top.y + 1), + new PlotId(top.x, top.y + 1)); + tmp = true; + for (PlotId id : ids) { + Plot plot = this.area.getPlotAbs(id); + if (plot == null || !plot.getMerged(0) || visited.contains(plot.getId())) { + tmp = false; + } + } + if (tmp) { + merge = true; + top.y++; + } + ids = MainUtil.getPlotSelectionIds(new PlotId(bot.x - 1, bot.y), + new PlotId(bot.x - 1, top.y)); + tmp = true; + for (PlotId id : ids) { + Plot plot = this.area.getPlotAbs(id); + if (plot == null || !plot.getMerged(1) || visited.contains(plot.getId())) { + tmp = false; + } + } + if (tmp) { + merge = true; + bot.x--; + } + } + Location gtopabs = this.area.getPlotAbs(top).getTopAbs(); + Location gbotabs = this.area.getPlotAbs(bot).getBottomAbs(); + visited.addAll(MainUtil.getPlotSelectionIds(bot, top)); + for (int x = bot.x; x <= top.x; x++) { + Plot plot = this.area.getPlotAbs(new PlotId(x, top.y)); + if (plot.getMerged(2)) { + // south wedge + Location toploc = plot.getExtendedTopAbs(); + Location botabs = plot.getBottomAbs(); + Location topabs = plot.getTopAbs(); + regions.add(new RegionWrapper(botabs.getX(), topabs.getX(), topabs.getZ() + 1, + toploc.getZ())); + if (plot.getMerged(5)) { regions.add( - new RegionWrapper(gbotabs.getX(), gtopabs.getX(), gbotabs.getZ(), gtopabs.getZ())); + new RegionWrapper(topabs.getX() + 1, toploc.getX(), topabs.getZ() + 1, + toploc.getZ())); + // intersection + } } - return regions; - } + } - /** - * Attempt to find the largest rectangular region in a plot (as plots can form non rectangular shapes) - * - * @return - */ - public RegionWrapper getLargestRegion() { - HashSet regions = this.getRegions(); - RegionWrapper max = null; - double area = Double.NEGATIVE_INFINITY; - for (RegionWrapper region : regions) { - double current = - (region.maxX - (double) region.minX + 1) * (region.maxZ - (double) region.minZ + 1); - if (current > area) { - max = region; - area = current; - } + for (int y = bot.y; y <= top.y; y++) { + Plot plot = this.area.getPlotAbs(new PlotId(top.x, y)); + if (plot.getMerged(1)) { + // east wedge + Location toploc = plot.getExtendedTopAbs(); + Location botabs = plot.getBottomAbs(); + Location topabs = plot.getTopAbs(); + regions.add(new RegionWrapper(topabs.getX() + 1, toploc.getX(), botabs.getZ(), + topabs.getZ())); + if (plot.getMerged(5)) { + regions.add( + new RegionWrapper(topabs.getX() + 1, toploc.getX(), topabs.getZ() + 1, + toploc.getZ())); + // intersection + } } - return max; + } + regions.add( + new RegionWrapper(gbotabs.getX(), gtopabs.getX(), gbotabs.getZ(), gtopabs.getZ())); } + return regions; + } - /** - * Do the plot entry tasks for each player in the plot
- * - Usually called when the plot state changes (unclaimed/claimed/flag change etc) - */ - public void reEnter() { - TaskManager.runTaskLater(() -> { - for (PlotPlayer pp : Plot.this.getPlayersInPlot()) { - PlotListener.plotExit(pp, Plot.this); - PlotListener.plotEntry(pp, Plot.this); - } - }, 1); + /** + * Attempt to find the largest rectangular region in a plot (as plots can form non rectangular + * shapes) + */ + public RegionWrapper getLargestRegion() { + HashSet regions = this.getRegions(); + RegionWrapper max = null; + double area = Double.NEGATIVE_INFINITY; + for (RegionWrapper region : regions) { + double current = + (region.maxX - (double) region.minX + 1) * (region.maxZ - (double) region.minZ + 1); + if (current > area) { + max = region; + area = current; + } } + return max; + } - /** - * Get all the corners of the plot (supports non-rectangular shapes). - * - * @return A list of the plot corners - */ - public List getAllCorners() { - Area area = new Area(); - for (RegionWrapper region : this.getRegions()) { - Rectangle2D rect = new Rectangle2D.Double(region.minX - 0.6, region.minZ - 0.6, - region.maxX - region.minX + 1.2, region.maxZ - region.minZ + 1.2); - Area rectArea = new Area(rect); - area.add(rectArea); - } - List locs = new ArrayList<>(); - double[] coords = new double[6]; - for (PathIterator pi = area.getPathIterator(null); !pi.isDone(); pi.next()) { - int type = pi.currentSegment(coords); - int x = (int) MathMan.inverseRound(coords[0]); - int z = (int) MathMan.inverseRound(coords[1]); - if (type != 4) { - locs.add(new Location(this.getWorldName(), x, 0, z)); - } - } - return locs; + /** + * Do the plot entry tasks for each player in the plot
- Usually called when the plot state + * changes (unclaimed/claimed/flag change etc) + */ + public void reEnter() { + TaskManager.runTaskLater(() -> { + for (PlotPlayer pp : Plot.this.getPlayersInPlot()) { + PlotListener.plotExit(pp, Plot.this); + PlotListener.plotEntry(pp, Plot.this); + } + }, 1); + } + + /** + * Get all the corners of the plot (supports non-rectangular shapes). + * + * @return A list of the plot corners + */ + public List getAllCorners() { + Area area = new Area(); + for (RegionWrapper region : this.getRegions()) { + Rectangle2D rect = new Rectangle2D.Double(region.minX - 0.6, region.minZ - 0.6, + region.maxX - region.minX + 1.2, region.maxZ - region.minZ + 1.2); + Area rectArea = new Area(rect); + area.add(rectArea); } - - /** - * Teleport a player to a plot and send them the teleport message. - * - * @param player the player - * @return if the teleport succeeded - */ - public boolean teleportPlayer(final PlotPlayer player) { - Plot plot = this.getBasePlot(false); - boolean result = EventUtil.manager.callTeleport(player, player.getLocation(), plot); - if (result) { - final Location location; - if (this.area.HOME_ALLOW_NONMEMBER || plot.isAdded(player.getUUID())) { - location = this.getHome(); - } else { - location = this.getDefaultHome(false); - } - if (Settings.Teleport.DELAY == 0 || Permissions - .hasPermission(player, "plots.teleport.delay.bypass")) { - MainUtil.sendMessage(player, C.TELEPORTED_TO_PLOT); - player.teleport(location); - return true; - } - MainUtil.sendMessage(player, C.TELEPORT_IN_SECONDS, Settings.Teleport.DELAY + ""); - final String name = player.getName(); - TaskManager.TELEPORT_QUEUE.add(name); - TaskManager.runTaskLater(() -> { - if (!TaskManager.TELEPORT_QUEUE.contains(name)) { - MainUtil.sendMessage(player, C.TELEPORT_FAILED); - return; - } - TaskManager.TELEPORT_QUEUE.remove(name); - if (player.isOnline()) { - MainUtil.sendMessage(player, C.TELEPORTED_TO_PLOT); - player.teleport(location); - } - }, Settings.Teleport.DELAY * 20); - return true; - } - return false; + List locs = new ArrayList<>(); + double[] coords = new double[6]; + for (PathIterator pi = area.getPathIterator(null); !pi.isDone(); pi.next()) { + int type = pi.currentSegment(coords); + int x = (int) MathMan.inverseRound(coords[0]); + int z = (int) MathMan.inverseRound(coords[1]); + if (type != 4) { + locs.add(new Location(this.getWorldName(), x, 0, z)); + } } + return locs; + } - public boolean isOnline() { - if (this.owner == null) { - return false; - } - if (!isMerged()) { - return UUIDHandler.getPlayer(this.owner) != null; - } - for (Plot current : getConnectedPlots()) { - if (current.hasOwner() && UUIDHandler.getPlayer(current.owner) != null) { - return true; - } - } - return false; - } - - /** - * Set a component for a plot to the provided blocks
- * - E.g. floor, wall, border etc.
- * - The available components depend on the generator being used
- * - * @param component - * @param blocks - * @return - */ - public boolean setComponent(String component, BlockBucket blocks) { - if (StringMan - .isEqualToAny(component, getManager().getPlotComponents(this.area, this.getId()))) { - EventUtil.manager.callComponentSet(this, component); - } - return this.getManager().setComponent(this.area, this.getId(), component, blocks); - } - - public int getDistanceFromOrigin() { - Location bot = getManager().getPlotBottomLocAbs(this.area, id); - Location top = getManager().getPlotTopLocAbs(this.area, id); - return Math.max(Math.max(Math.abs(bot.getX()), Math.abs(bot.getZ())), - Math.max(Math.abs(top.getX()), Math.abs(top.getZ()))); - } - - /** - * Expand the world border to include the provided plot (if applicable). - */ - public void updateWorldBorder() { - if (this.owner == null) { - return; - } - int border = this.area.getBorder(); - if (border == Integer.MAX_VALUE) { - return; - } - int max = getDistanceFromOrigin(); - if (max > border) { - this.area.setMeta("worldBorder", max); - } - } - - /** - * Merges 2 plots Removes the road in-between
- Assumes plots are directly next to each other
- saves to DB - * - * @param lesserPlot - * @param removeRoads - */ - public void mergePlot(Plot lesserPlot, boolean removeRoads) { - Plot greaterPlot = this; - if (lesserPlot.getId().x == greaterPlot.getId().x) { - if (lesserPlot.getId().y > greaterPlot.getId().y) { - Plot tmp = lesserPlot; - lesserPlot = greaterPlot; - greaterPlot = tmp; - } - if (!lesserPlot.getMerged(2)) { - lesserPlot.clearRatings(); - greaterPlot.clearRatings(); - lesserPlot.setMerged(2, true); - greaterPlot.setMerged(0, true); - lesserPlot.mergeData(greaterPlot); - if (removeRoads) { - lesserPlot.removeRoadSouth(); - Plot diagonal = greaterPlot.getRelative(1); - if (diagonal.getMerged(7)) { - lesserPlot.removeRoadSouthEast(); - } - Plot below = greaterPlot.getRelative(3); - if (below.getMerged(4)) { - below.getRelative(0).removeRoadSouthEast(); - } - } - } - } else { - if (lesserPlot.getId().x > greaterPlot.getId().x) { - Plot tmp = lesserPlot; - lesserPlot = greaterPlot; - greaterPlot = tmp; - } - if (!lesserPlot.getMerged(1)) { - lesserPlot.clearRatings(); - greaterPlot.clearRatings(); - lesserPlot.setMerged(1, true); - greaterPlot.setMerged(3, true); - lesserPlot.mergeData(greaterPlot); - if (removeRoads) { - Plot diagonal = greaterPlot.getRelative(2); - if (diagonal.getMerged(7)) { - lesserPlot.removeRoadSouthEast(); - } - lesserPlot.removeRoadEast(); - } - Plot below = greaterPlot.getRelative(0); - if (below.getMerged(6)) { - below.getRelative(3).removeRoadSouthEast(); - } - } - } - } - - /** - * Move a plot physically, as well as the corresponding settings. - * - * @param destination Plot moved to - * @param whenDone task when done - * @param allowSwap whether to swap plots - * @return success - */ - public boolean move(final Plot destination, final Runnable whenDone, boolean allowSwap) { - final PlotId offset = new PlotId(destination.getId().x - this.getId().x, - destination.getId().y - this.getId().y); - Location db = destination.getBottomAbs(); - Location ob = this.getBottomAbs(); - final int offsetX = db.getX() - ob.getX(); - final int offsetZ = db.getZ() - ob.getZ(); - if (this.owner == null) { - TaskManager.runTaskLater(whenDone, 1); - return false; - } - boolean occupied = false; - Set plots = this.getConnectedPlots(); - for (Plot plot : plots) { - Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); - if (other.hasOwner()) { - if (!allowSwap) { - TaskManager.runTaskLater(whenDone, 1); - return false; - } - occupied = true; - } else { - plot.removeSign(); - } - } - // world border - destination.updateWorldBorder(); - final ArrayDeque regions = new ArrayDeque<>(this.getRegions()); - // move / swap data - final PlotArea originArea = getArea(); - for (Plot plot : plots) { - Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); - plot.swapData(other, null); - } - // copy terrain - Runnable move = new Runnable() { - @Override public void run() { - if (regions.isEmpty()) { - Plot plot = destination.getRelative(0, 0); - for (Plot current : plot.getConnectedPlots()) { - getManager().claimPlot(current.getArea(), current); - Plot originPlot = originArea.getPlotAbs( - new PlotId(current.id.x - offset.x, current.id.y - offset.y)); - originPlot.getManager().unclaimPlot(originArea, originPlot, null); - } - plot.setSign(); - TaskManager.runTask(whenDone); - return; - } - final Runnable task = this; - RegionWrapper region = regions.poll(); - Location[] corners = region.getCorners(getWorldName()); - final Location pos1 = corners[0]; - final Location pos2 = corners[1]; - Location newPos = pos1.clone().add(offsetX, 0, offsetZ); - newPos.setWorld(destination.getWorldName()); - ChunkManager.manager.copyRegion(pos1, pos2, newPos, - () -> ChunkManager.manager.regenerateRegion(pos1, pos2, false, task)); - } - }; - Runnable swap = new Runnable() { - @Override public void run() { - if (regions.isEmpty()) { - TaskManager.runTask(whenDone); - return; - } - RegionWrapper region = regions.poll(); - Location[] corners = region.getCorners(getWorldName()); - Location pos1 = corners[0]; - Location pos2 = corners[1]; - Location pos3 = pos1.clone().add(offsetX, 0, offsetZ); - Location pos4 = pos2.clone().add(offsetX, 0, offsetZ); - pos3.setWorld(destination.getWorldName()); - pos4.setWorld(destination.getWorldName()); - ChunkManager.manager.swap(pos1, pos2, pos3, pos4, this); - } - }; - if (occupied) { - swap.run(); - } else { - move.run(); - } + /** + * Teleport a player to a plot and send them the teleport message. + * + * @param player the player + * @return if the teleport succeeded + */ + public boolean teleportPlayer(final PlotPlayer player) { + Plot plot = this.getBasePlot(false); + boolean result = EventUtil.manager.callTeleport(player, player.getLocation(), plot); + if (result) { + final Location location; + if (this.area.HOME_ALLOW_NONMEMBER || plot.isAdded(player.getUUID())) { + location = this.getHome(); + } else { + location = this.getDefaultHome(false); + } + if (Settings.Teleport.DELAY == 0 || Permissions + .hasPermission(player, "plots.teleport.delay.bypass")) { + MainUtil.sendMessage(player, C.TELEPORTED_TO_PLOT); + player.teleport(location); return true; + } + MainUtil.sendMessage(player, C.TELEPORT_IN_SECONDS, Settings.Teleport.DELAY + ""); + final String name = player.getName(); + TaskManager.TELEPORT_QUEUE.add(name); + TaskManager.runTaskLater(() -> { + if (!TaskManager.TELEPORT_QUEUE.contains(name)) { + MainUtil.sendMessage(player, C.TELEPORT_FAILED); + return; + } + TaskManager.TELEPORT_QUEUE.remove(name); + if (player.isOnline()) { + MainUtil.sendMessage(player, C.TELEPORTED_TO_PLOT); + player.teleport(location); + } + }, Settings.Teleport.DELAY * 20); + return true; } + return false; + } - /** - * Copy a plot to a location, both physically and the settings - * - * @param destination - * @param whenDone - * @return - */ - public boolean copy(final Plot destination, final Runnable whenDone) { - PlotId offset = new PlotId(destination.getId().x - this.getId().x, - destination.getId().y - this.getId().y); - Location db = destination.getBottomAbs(); - Location ob = this.getBottomAbs(); - final int offsetX = db.getX() - ob.getX(); - final int offsetZ = db.getZ() - ob.getZ(); - if (this.owner == null) { - TaskManager.runTaskLater(whenDone, 1); - return false; - } - Set plots = this.getConnectedPlots(); - for (Plot plot : plots) { - Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); - if (other.hasOwner()) { - TaskManager.runTaskLater(whenDone, 1); - return false; - } - } - // world border - destination.updateWorldBorder(); - // copy data - for (Plot plot : plots) { - Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); - other.create(plot.owner, false); - if (!plot.getFlags().isEmpty()) { - other.getSettings().flags = plot.getFlags(); - DBFunc.setFlags(other, plot.getFlags()); - } - if (plot.isMerged()) { - other.setMerged(plot.getMerged()); - } - if (plot.members != null && !plot.members.isEmpty()) { - other.members = plot.members; - for (UUID member : plot.members) { - DBFunc.setMember(other, member); - } - } - if (plot.trusted != null && !plot.trusted.isEmpty()) { - other.trusted = plot.trusted; - for (UUID trusted : plot.trusted) { - DBFunc.setTrusted(other, trusted); - } - } - if (plot.denied != null && !plot.denied.isEmpty()) { - other.denied = plot.denied; - for (UUID denied : plot.denied) { - DBFunc.setDenied(other, denied); - } - } - } - // copy terrain - final ArrayDeque regions = new ArrayDeque<>(this.getRegions()); - Runnable run = new Runnable() { - @Override public void run() { - if (regions.isEmpty()) { - for (Plot current : getConnectedPlots()) { - destination.getManager().claimPlot(destination.getArea(), destination); - } - destination.setSign(); - TaskManager.runTask(whenDone); - return; - } - RegionWrapper region = regions.poll(); - Location[] corners = region.getCorners(getWorldName()); - Location pos1 = corners[0]; - Location pos2 = corners[1]; - Location newPos = pos1.clone().add(offsetX, 0, offsetZ); - newPos.setWorld(destination.getWorldName()); - ChunkManager.manager.copyRegion(pos1, pos2, newPos, this); - } - }; - run.run(); + public boolean isOnline() { + if (this.owner == null) { + return false; + } + if (!isMerged()) { + return UUIDHandler.getPlayer(this.owner) != null; + } + for (Plot current : getConnectedPlots()) { + if (current.hasOwner() && UUIDHandler.getPlayer(current.owner) != null) { return true; + } } + return false; + } - public boolean hasFlag(Flag flag) { - return getFlags().containsKey(flag); + /** + * Set a component for a plot to the provided blocks
- E.g. floor, wall, border etc.
- The + * available components depend on the generator being used
+ */ + public boolean setComponent(String component, BlockBucket blocks) { + if (StringMan + .isEqualToAny(component, getManager().getPlotComponents(this.area, this.getId()))) { + EventUtil.manager.callComponentSet(this, component); } + return this.getManager().setComponent(this.area, this.getId(), component, blocks); + } + + public int getDistanceFromOrigin() { + Location bot = getManager().getPlotBottomLocAbs(this.area, id); + Location top = getManager().getPlotTopLocAbs(this.area, id); + return Math.max(Math.max(Math.abs(bot.getX()), Math.abs(bot.getZ())), + Math.max(Math.abs(top.getX()), Math.abs(top.getZ()))); + } + + /** + * Expand the world border to include the provided plot (if applicable). + */ + public void updateWorldBorder() { + if (this.owner == null) { + return; + } + int border = this.area.getBorder(); + if (border == Integer.MAX_VALUE) { + return; + } + int max = getDistanceFromOrigin(); + if (max > border) { + this.area.setMeta("worldBorder", max); + } + } + + /** + * Merges 2 plots Removes the road in-between
- Assumes plots are directly next to each other + *
- saves to DB + */ + public void mergePlot(Plot lesserPlot, boolean removeRoads) { + Plot greaterPlot = this; + if (lesserPlot.getId().x == greaterPlot.getId().x) { + if (lesserPlot.getId().y > greaterPlot.getId().y) { + Plot tmp = lesserPlot; + lesserPlot = greaterPlot; + greaterPlot = tmp; + } + if (!lesserPlot.getMerged(2)) { + lesserPlot.clearRatings(); + greaterPlot.clearRatings(); + lesserPlot.setMerged(2, true); + greaterPlot.setMerged(0, true); + lesserPlot.mergeData(greaterPlot); + if (removeRoads) { + lesserPlot.removeRoadSouth(); + Plot diagonal = greaterPlot.getRelative(1); + if (diagonal.getMerged(7)) { + lesserPlot.removeRoadSouthEast(); + } + Plot below = greaterPlot.getRelative(3); + if (below.getMerged(4)) { + below.getRelative(0).removeRoadSouthEast(); + } + } + } + } else { + if (lesserPlot.getId().x > greaterPlot.getId().x) { + Plot tmp = lesserPlot; + lesserPlot = greaterPlot; + greaterPlot = tmp; + } + if (!lesserPlot.getMerged(1)) { + lesserPlot.clearRatings(); + greaterPlot.clearRatings(); + lesserPlot.setMerged(1, true); + greaterPlot.setMerged(3, true); + lesserPlot.mergeData(greaterPlot); + if (removeRoads) { + Plot diagonal = greaterPlot.getRelative(2); + if (diagonal.getMerged(7)) { + lesserPlot.removeRoadSouthEast(); + } + lesserPlot.removeRoadEast(); + } + Plot below = greaterPlot.getRelative(0); + if (below.getMerged(6)) { + below.getRelative(3).removeRoadSouthEast(); + } + } + } + } + + /** + * Move a plot physically, as well as the corresponding settings. + * + * @param destination Plot moved to + * @param whenDone task when done + * @param allowSwap whether to swap plots + * @return success + */ + public boolean move(final Plot destination, final Runnable whenDone, boolean allowSwap) { + final PlotId offset = new PlotId(destination.getId().x - this.getId().x, + destination.getId().y - this.getId().y); + Location db = destination.getBottomAbs(); + Location ob = this.getBottomAbs(); + final int offsetX = db.getX() - ob.getX(); + final int offsetZ = db.getZ() - ob.getZ(); + if (this.owner == null) { + TaskManager.runTaskLater(whenDone, 1); + return false; + } + boolean occupied = false; + Set plots = this.getConnectedPlots(); + for (Plot plot : plots) { + Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); + if (other.hasOwner()) { + if (!allowSwap) { + TaskManager.runTaskLater(whenDone, 1); + return false; + } + occupied = true; + } else { + plot.removeSign(); + } + } + // world border + destination.updateWorldBorder(); + final ArrayDeque regions = new ArrayDeque<>(this.getRegions()); + // move / swap data + final PlotArea originArea = getArea(); + for (Plot plot : plots) { + Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); + plot.swapData(other, null); + } + // copy terrain + Runnable move = new Runnable() { + @Override + public void run() { + if (regions.isEmpty()) { + Plot plot = destination.getRelative(0, 0); + for (Plot current : plot.getConnectedPlots()) { + getManager().claimPlot(current.getArea(), current); + Plot originPlot = originArea.getPlotAbs( + new PlotId(current.id.x - offset.x, current.id.y - offset.y)); + originPlot.getManager().unclaimPlot(originArea, originPlot, null); + } + plot.setSign(); + TaskManager.runTask(whenDone); + return; + } + final Runnable task = this; + RegionWrapper region = regions.poll(); + Location[] corners = region.getCorners(getWorldName()); + final Location pos1 = corners[0]; + final Location pos2 = corners[1]; + Location newPos = pos1.clone().add(offsetX, 0, offsetZ); + newPos.setWorld(destination.getWorldName()); + ChunkManager.manager.copyRegion(pos1, pos2, newPos, + () -> ChunkManager.manager.regenerateRegion(pos1, pos2, false, task)); + } + }; + Runnable swap = new Runnable() { + @Override + public void run() { + if (regions.isEmpty()) { + TaskManager.runTask(whenDone); + return; + } + RegionWrapper region = regions.poll(); + Location[] corners = region.getCorners(getWorldName()); + Location pos1 = corners[0]; + Location pos2 = corners[1]; + Location pos3 = pos1.clone().add(offsetX, 0, offsetZ); + Location pos4 = pos2.clone().add(offsetX, 0, offsetZ); + pos3.setWorld(destination.getWorldName()); + pos4.setWorld(destination.getWorldName()); + ChunkManager.manager.swap(pos1, pos2, pos3, pos4, this); + } + }; + if (occupied) { + swap.run(); + } else { + move.run(); + } + return true; + } + + /** + * Copy a plot to a location, both physically and the settings + */ + public boolean copy(final Plot destination, final Runnable whenDone) { + PlotId offset = new PlotId(destination.getId().x - this.getId().x, + destination.getId().y - this.getId().y); + Location db = destination.getBottomAbs(); + Location ob = this.getBottomAbs(); + final int offsetX = db.getX() - ob.getX(); + final int offsetZ = db.getZ() - ob.getZ(); + if (this.owner == null) { + TaskManager.runTaskLater(whenDone, 1); + return false; + } + Set plots = this.getConnectedPlots(); + for (Plot plot : plots) { + Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); + if (other.hasOwner()) { + TaskManager.runTaskLater(whenDone, 1); + return false; + } + } + // world border + destination.updateWorldBorder(); + // copy data + for (Plot plot : plots) { + Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); + other.create(plot.owner, false); + if (!plot.getFlags().isEmpty()) { + other.getSettings().flags = plot.getFlags(); + DBFunc.setFlags(other, plot.getFlags()); + } + if (plot.isMerged()) { + other.setMerged(plot.getMerged()); + } + if (plot.members != null && !plot.members.isEmpty()) { + other.members = plot.members; + for (UUID member : plot.members) { + DBFunc.setMember(other, member); + } + } + if (plot.trusted != null && !plot.trusted.isEmpty()) { + other.trusted = plot.trusted; + for (UUID trusted : plot.trusted) { + DBFunc.setTrusted(other, trusted); + } + } + if (plot.denied != null && !plot.denied.isEmpty()) { + other.denied = plot.denied; + for (UUID denied : plot.denied) { + DBFunc.setDenied(other, denied); + } + } + } + // copy terrain + final ArrayDeque regions = new ArrayDeque<>(this.getRegions()); + Runnable run = new Runnable() { + @Override + public void run() { + if (regions.isEmpty()) { + for (Plot current : getConnectedPlots()) { + destination.getManager().claimPlot(destination.getArea(), destination); + } + destination.setSign(); + TaskManager.runTask(whenDone); + return; + } + RegionWrapper region = regions.poll(); + Location[] corners = region.getCorners(getWorldName()); + Location pos1 = corners[0]; + Location pos2 = corners[1]; + Location newPos = pos1.clone().add(offsetX, 0, offsetZ); + newPos.setWorld(destination.getWorldName()); + ChunkManager.manager.copyRegion(pos1, pos2, newPos, this); + } + }; + run.run(); + return true; + } + + public boolean hasFlag(Flag flag) { + return getFlags().containsKey(flag); + } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotArea.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotArea.java index 48ebb759a..00a30e22d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotArea.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotArea.java @@ -721,6 +721,9 @@ public abstract class PlotArea { } else { start = start.getNextId(1); } + if (start == null) { + PlotSquared.debug("NPE possible in getNextFreePlot"); + } currentId = new PlotId(center.x + start.x, center.y + start.y); Plot plot = getPlotAbs(currentId); if (plot != null && plot.canClaim(player)) { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotCluster.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotCluster.java index a1134cbce..4a12bfb7b 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotCluster.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotCluster.java @@ -5,19 +5,25 @@ import com.github.intellectualsites.plotsquared.plot.util.MainUtil; import java.util.HashSet; import java.util.UUID; +import javax.annotation.Nonnull; +import lombok.Getter; public class PlotCluster { public PlotArea area; + @Nonnull + @Getter public PlotSettings settings; public UUID owner; public HashSet helpers = new HashSet<>(); public HashSet invited = new HashSet<>(); public int temp; + @Nonnull private PlotId pos1; + @Nonnull private PlotId pos2; private RegionWrapper region; - public PlotCluster(PlotArea area, PlotId pos1, PlotId pos2, UUID owner) { + public PlotCluster(PlotArea area, @Nonnull PlotId pos1, @Nonnull PlotId pos2, UUID owner) { this.area = area; this.pos1 = pos1; this.pos2 = pos2; @@ -27,7 +33,7 @@ public class PlotCluster { setRegion(); } - public PlotCluster(PlotArea area, PlotId pos1, PlotId pos2, UUID owner, int temp) { + public PlotCluster(PlotArea area, @Nonnull PlotId pos1, PlotId pos2, UUID owner, int temp) { this.area = area; this.pos1 = pos1; this.pos2 = pos2; @@ -82,6 +88,11 @@ public class PlotCluster { return this.settings.getAlias(); } + public String getAlias() { + return this.settings.getAlias(); + } + + public void setName(String name) { this.settings.setAlias(name);} /** * Get the area (in plots). * diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotMessage.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotMessage.java index 47069a38e..6db234de3 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotMessage.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotMessage.java @@ -13,6 +13,7 @@ public class PlotMessage { try { reset(ChatManager.manager); } catch (Throwable e) { + assert PlotSquared.imp() != null; PlotSquared.debug( PlotSquared.imp().getPluginName() + " doesn't support fancy chat for " + PlotSquared .get().IMP.getServerVersion()); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotPlayer.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotPlayer.java index d535c625e..850c77365 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotPlayer.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotPlayer.java @@ -24,655 +24,632 @@ import java.util.concurrent.atomic.AtomicInteger; */ public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer { - public static final String META_LAST_PLOT = "lastplot"; - public static final String META_LOCATION = "location"; - private static final Map converters = new HashMap<>(); - private Map metaMap = new HashMap<>(); - /** - * The metadata map. - */ - private ConcurrentHashMap meta; + public static final String META_LAST_PLOT = "lastplot"; + public static final String META_LOCATION = "location"; + private static final Map converters = new HashMap<>(); + private Map metaMap = new HashMap<>(); + /** + * The metadata map. + */ + private ConcurrentHashMap meta; - public static PlotPlayer from(@NonNull final T object) { - if (!converters.containsKey(object.getClass())) { - throw new IllegalArgumentException(String - .format("There is no registered PlotPlayer converter for type %s", - object.getClass().getSimpleName())); + public static PlotPlayer from(@NonNull final T object) { + if (!converters.containsKey(object.getClass())) { + throw new IllegalArgumentException(String + .format("There is no registered PlotPlayer converter for type %s", + object.getClass().getSimpleName())); + } + return converters.get(object.getClass()).convert(object); + } + + public static void registerConverter(@NonNull final Class clazz, + final PlotPlayerConverter converter) { + converters.put(clazz, converter); + } + + /** + * Efficiently wrap a Player, or OfflinePlayer object to get a PlotPlayer (or fetch if it's + * already cached)
- Accepts sponge/bukkit Player (online) - Accepts player name (online) - + * Accepts UUID - Accepts bukkit OfflinePlayer (offline) + */ + public static PlotPlayer wrap(Object player) { + return PlotSquared.get().IMP.wrapPlayer(player); + } + + /** + * Get the cached PlotPlayer from a username
- This will return null if the player has not + * finished logging in or is not online + */ + public static PlotPlayer get(String name) { + return UUIDHandler.getPlayer(name); + } + + /** + * Set some session only metadata for this player. + */ + public void setMeta(String key, Object value) { + if (value == null) { + deleteMeta(key); + } else { + if (this.meta == null) { + this.meta = new ConcurrentHashMap<>(); + } + this.meta.put(key, value); + } + } + + /** + * Get the session metadata for a key. + * + * @param key the name of the metadata key + * @param the object type to return + * @return the value assigned to the key or null if it does not exist + */ + public T getMeta(String key) { + if (this.meta != null) { + return (T) this.meta.get(key); + } + return null; + } + + public T getMeta(String key, T defaultValue) { + T meta = getMeta(key); + if (meta == null) { + return defaultValue; + } + return meta; + } + + /** + * Delete the metadata for a key. - metadata is session only - deleting other plugin's metadata + * may cause issues + */ + public Object deleteMeta(String key) { + return this.meta == null ? null : this.meta.remove(key); + } + + /** + * This player's name. + * + * @return the name of the player + */ + @Override + public String toString() { + return getName(); + } + + /** + * Get this player's current plot. + * + * @return the plot the player is standing on or null if standing on a road or not in a {@link + * PlotArea} + */ + public Plot getCurrentPlot() { + Plot value = getMeta(PlotPlayer.META_LAST_PLOT); + if (value == null && !Settings.Enabled_Components.EVENTS) { + return getLocation().getPlot(); + } + return value; + } + + /** + * Get the total number of allowed plots Possibly relevant: (To increment the player's allowed + * plots, see the example script on the wiki) + * + * @return number of allowed plots within the scope (globally, or in the player's current world as + * defined in the settings.yml) + */ + public int getAllowedPlots() { + return Permissions.hasPermissionRange(this, "plots.plot", Settings.Limit.MAX_PLOTS); + } + + /** + * Get the total number of allowed clusters + * + * @return number of allowed clusters within the scope (globally, or in the player's current world + * as defined in the settings.yml) + */ + public int getAllowedClusters() { + return Permissions.hasPermissionRange(this, "plots.cluster", Settings.Limit.MAX_PLOTS); + } + + public int hasPermissionRange(String stub, int range) { + if (hasPermission(C.PERMISSION_ADMIN.s())) { + return Integer.MAX_VALUE; + } + String[] nodes = stub.split("\\."); + StringBuilder n = new StringBuilder(); + for (int i = 0; i < (nodes.length - 1); i++) { + n.append(nodes[i]).append("."); + if (!stub.equals(n + C.PERMISSION_STAR.s())) { + if (hasPermission(n + C.PERMISSION_STAR.s())) { + return Integer.MAX_VALUE; } - return converters.get(object.getClass()).convert(object); + } } - - public static void registerConverter(@NonNull final Class clazz, - final PlotPlayerConverter converter) { - converters.put(clazz, converter); + if (hasPermission(stub + ".*")) { + return Integer.MAX_VALUE; } - - /** - * Efficiently wrap a Player, or OfflinePlayer object to get a PlotPlayer (or fetch if it's already cached)
- * - Accepts sponge/bukkit Player (online) - * - Accepts player name (online) - * - Accepts UUID - * - Accepts bukkit OfflinePlayer (offline) - * - * @param player - * @return - */ - public static PlotPlayer wrap(Object player) { - return PlotSquared.get().IMP.wrapPlayer(player); + for (int i = range; i > 0; i--) { + if (hasPermission(stub + "." + i)) { + return i; + } } + return 0; + } - /** - * Get the cached PlotPlayer from a username
- * - This will return null if the player has not finished logging in or is not online - * - * @param name - * @return - */ - public static PlotPlayer get(String name) { - return UUIDHandler.getPlayer(name); + /** + * Get the number of plots this player owns. + * + * @return number of plots within the scope (globally, or in the player's current world as defined + * in the settings.yml) + * @see #getPlotCount(String); + * @see #getPlots() + */ + public int getPlotCount() { + if (!Settings.Limit.GLOBAL) { + return getPlotCount(getLocation().getWorld()); } - - /** - * Set some session only metadata for this player. - * - * @param key - * @param value - */ - public void setMeta(String key, Object value) { - if (value == null) { - deleteMeta(key); + final AtomicInteger count = new AtomicInteger(0); + final UUID uuid = getUUID(); + PlotSquared.get().foreachPlotArea(new RunnableVal() { + @Override + public void run(PlotArea value) { + if (!Settings.Done.COUNTS_TOWARDS_LIMIT) { + for (Plot plot : value.getPlotsAbs(uuid)) { + if (!plot.hasFlag(Flags.DONE)) { + count.incrementAndGet(); + } + } } else { - if (this.meta == null) { - this.meta = new ConcurrentHashMap<>(); - } - this.meta.put(key, value); + count.addAndGet(value.getPlotsAbs(uuid).size()); } - } + } + }); + return count.get(); + } - /** - * Get the session metadata for a key. - * - * @param key the name of the metadata key - * @param the object type to return - * @return the value assigned to the key or null if it does not exist - */ - public T getMeta(String key) { - if (this.meta != null) { - return (T) this.meta.get(key); + public int getClusterCount() { + if (!Settings.Limit.GLOBAL) { + return getClusterCount(getLocation().getWorld()); + } + final AtomicInteger count = new AtomicInteger(0); + final UUID uuid = getUUID(); + PlotSquared.get().foreachPlotArea(new RunnableVal() { + @Override + public void run(PlotArea value) { + for (PlotCluster cluster : value.getClusters()) { + if (cluster.isOwner(getUUID())) { + count.incrementAndGet(); + } } - return null; - } + } + }); + return count.get(); + } - public T getMeta(String key, T defaultValue) { - T meta = getMeta(key); - if (meta == null) { - return defaultValue; + /** + * Get the number of plots this player owns in the world. + * + * @param world the name of the plotworld to check. + */ + public int getPlotCount(String world) { + UUID uuid = getUUID(); + int count = 0; + for (PlotArea area : PlotSquared.get().getPlotAreas(world)) { + if (!Settings.Done.COUNTS_TOWARDS_LIMIT) { + for (Plot plot : area.getPlotsAbs(uuid)) { + if (!plot.getFlag(Flags.DONE).isPresent()) { + count++; + } } - return meta; + } else { + count += area.getPlotsAbs(uuid).size(); + } } + return count; + } - /** - * Delete the metadata for a key. - * - metadata is session only - * - deleting other plugin's metadata may cause issues - * - * @param key - */ - public Object deleteMeta(String key) { - return this.meta == null ? null : this.meta.remove(key); - } - - /** - * This player's name. - * - * @return the name of the player - */ - @Override public String toString() { - return getName(); - } - - /** - * Get this player's current plot. - * - * @return the plot the player is standing on or null if standing on a road or not in a {@link PlotArea} - */ - public Plot getCurrentPlot() { - Plot value = getMeta(PlotPlayer.META_LAST_PLOT); - if (value == null && !Settings.Enabled_Components.EVENTS) { - return getLocation().getPlot(); + public int getClusterCount(String world) { + UUID uuid = getUUID(); + int count = 0; + for (PlotArea area : PlotSquared.get().getPlotAreas(world)) { + for (PlotCluster cluster : area.getClusters()) { + if (cluster.isOwner(getUUID())) { + count++; } - return value; + } } + return count; + } - /** - * Get the total number of allowed plots - * Possibly relevant: (To increment the player's allowed plots, see the example script on the wiki) - * - * @return number of allowed plots within the scope (globally, or in the player's current world as defined in the settings.yml) - */ - public int getAllowedPlots() { - return Permissions.hasPermissionRange(this, "plots.plot", Settings.Limit.MAX_PLOTS); + /** + * Get a {@code Set} of plots owned by this player. + * + * @return a {@code Set} of plots owned by the player + * @see PlotSquared for more searching functions + * @see #getPlotCount() for the number of plots + */ + public Set getPlots() { + return PlotSquared.get().getPlots(this); + } + + /** + * Return the PlotArea this player is currently in, or null. + */ + public PlotArea getPlotAreaAbs() { + return PlotSquared.get().getPlotAreaAbs(getLocation()); + } + + public PlotArea getApplicablePlotArea() { + return PlotSquared.get().getApplicablePlotArea(getLocation()); + } + + @Override + public RequiredType getSuperCaller() { + return RequiredType.PLAYER; + } + + /** + * Get this player's last recorded location or null if they don't any plot relevant location. + * + * @return The location + */ + public Location getLocation() { + Location location = getMeta("location"); + if (location != null) { + return location; } + return getLocationFull(); + } - /** - * Get the total number of allowed clusters - * - * @return number of allowed clusters within the scope (globally, or in the player's current world as defined in the settings.yml) - */ - public int getAllowedClusters() { - return Permissions.hasPermissionRange(this, "plots.cluster", Settings.Limit.MAX_PLOTS); + /////////////// PLAYER META /////////////// + + ////////////// PARTIALLY IMPLEMENTED /////////// + + /** + * Get this player's full location (including yaw/pitch) + */ + public abstract Location getLocationFull(); + + //////////////////////////////////////////////// + + /** + * Get this player's UUID. === !IMPORTANT ===
The UUID is dependent on the mode chosen in the + * settings.yml and may not be the same as Bukkit has (especially if using an old version of + * Bukkit that does not support UUIDs) + * + * @return UUID + */ + @Override + public abstract UUID getUUID(); + + public boolean canTeleport(Location loc) { + Location current = getLocationFull(); + teleport(loc); + boolean result = true; + if (!getLocation().equals(loc)) { + result = false; } + teleport(current); + return result; + } - public int hasPermissionRange(String stub, int range) { - if (hasPermission(C.PERMISSION_ADMIN.s())) { - return Integer.MAX_VALUE; - } - String[] nodes = stub.split("\\."); - StringBuilder n = new StringBuilder(); - for (int i = 0; i < (nodes.length - 1); i++) { - n.append(nodes[i]).append("."); - if (!stub.equals(n + C.PERMISSION_STAR.s())) { - if (hasPermission(n + C.PERMISSION_STAR.s())) { - return Integer.MAX_VALUE; - } - } - } - if (hasPermission(stub + ".*")) { - return Integer.MAX_VALUE; - } - for (int i = range; i > 0; i--) { - if (hasPermission(stub + "." + i)) { - return i; - } - } - return 0; + /** + * Teleport this player to a location. + * + * @param location the target location + */ + public abstract void teleport(Location location); + + /** + * Kick this player to a location + * + * @param location the target location + */ + public void plotkick(Location location) { + setMeta("kick", true); + teleport(location); + deleteMeta("kick"); + } + + /** + * Set this compass target. + * + * @param location the target location + */ + public abstract void setCompassTarget(Location location); + + /** + * Set player data that will persist restarts. - Please note that this is not intended to store + * large values - For session only data use meta + */ + public void setAttribute(String key) { + setPersistentMeta("attrib_" + key, new byte[]{(byte) 1}); + } + + /** + * Retrieves the attribute of this player. + * + * @return the attribute will be either true or false + */ + public boolean getAttribute(String key) { + if (!hasPersistentMeta("attrib_" + key)) { + return false; } + return getPersistentMeta("attrib_" + key)[0] == 1; + } - /** - * Get the number of plots this player owns. - * - * @return number of plots within the scope (globally, or in the player's current world as defined in the settings.yml) - * @see #getPlotCount(String); - * @see #getPlots() - */ - public int getPlotCount() { - if (!Settings.Limit.GLOBAL) { - return getPlotCount(getLocation().getWorld()); - } - final AtomicInteger count = new AtomicInteger(0); - final UUID uuid = getUUID(); - PlotSquared.get().foreachPlotArea(new RunnableVal() { - @Override public void run(PlotArea value) { - if (!Settings.Done.COUNTS_TOWARDS_LIMIT) { - for (Plot plot : value.getPlotsAbs(uuid)) { - if (!plot.hasFlag(Flags.DONE)) { - count.incrementAndGet(); - } - } - } else { - count.addAndGet(value.getPlotsAbs(uuid).size()); - } - } - }); - return count.get(); + /** + * Remove an attribute from a player. + */ + public void removeAttribute(String key) { + removePersistentMeta("attrib_" + key); + } + + /** + * Sets the local weather for this Player. + * + * @param weather the weather visible to the player + */ + public abstract void setWeather(PlotWeather weather); + + /** + * Get this player's gamemode. + * + * @return the gamemode of the player. + */ + public abstract PlotGameMode getGameMode(); + + /** + * Set this player's gameMode. + * + * @param gameMode the gamemode to set + */ + public abstract void setGameMode(PlotGameMode gameMode); + + /** + * Set this player's local time (ticks). + * + * @param time the time visible to the player + */ + public abstract void setTime(long time); + + public abstract boolean getFlight(); + + /** + * Set this player's fly mode. + * + * @param fly if the player can fly + */ + public abstract void setFlight(boolean fly); + + /** + * Play music at a location for this player. + * + * @param location where to play the music + * @param id the record item id + */ + public abstract void playMusic(Location location, PlotBlock id); + + /** + * Check if this player is banned. + * + * @return true if the player is banned, false otherwise. + */ + public abstract boolean isBanned(); + + /** + * Kick this player from the game. + * + * @param message the reason for the kick + */ + public abstract void kick(String message); + + /** + * Called when this player quits. + */ + public void unregister() { + Plot plot = getCurrentPlot(); + if (plot != null && Settings.Enabled_Components.PERSISTENT_META && plot + .getArea() instanceof SinglePlotArea) { + PlotId id = plot.getId(); + int x = id.x; + int z = id.y; + ByteBuffer buffer = ByteBuffer.allocate(13); + buffer.putShort((short) x); + buffer.putShort((short) z); + Location loc = getLocation(); + buffer.putInt(loc.getX()); + buffer.put((byte) loc.getY()); + buffer.putInt(loc.getZ()); + setPersistentMeta("quitLoc", buffer.array()); + } else if (hasPersistentMeta("quitLoc")) { + removePersistentMeta("quitLoc"); } - - public int getClusterCount() { - if (!Settings.Limit.GLOBAL) { - return getClusterCount(getLocation().getWorld()); - } - final AtomicInteger count = new AtomicInteger(0); - final UUID uuid = getUUID(); - PlotSquared.get().foreachPlotArea(new RunnableVal() { - @Override public void run(PlotArea value) { - for (PlotCluster cluster : value.getClusters()) { - if (cluster.isOwner(getUUID())) { - count.incrementAndGet(); - } - } - } - }); - return count.get(); + if (plot != null) { + EventUtil.manager.callLeave(this, plot); } - - /** - * Get the number of plots this player owns in the world. - * - * @param world the name of the plotworld to check. - * @return - */ - public int getPlotCount(String world) { - UUID uuid = getUUID(); - int count = 0; - for (PlotArea area : PlotSquared.get().getPlotAreas(world)) { - if (!Settings.Done.COUNTS_TOWARDS_LIMIT) { - for (Plot plot : area.getPlotsAbs(uuid)) { - if (!plot.getFlag(Flags.DONE).isPresent()) { - count++; - } - } - } else { - count += area.getPlotsAbs(uuid).size(); - } - } - return count; + if (Settings.Enabled_Components.BAN_DELETER && isBanned()) { + for (Plot owned : getPlots()) { + owned.deletePlot(null); + PlotSquared.debug(String + .format("&cPlot &6%s &cwas deleted + cleared due to &6%s&c getting banned", + owned.getId(), getName())); + } } - - public int getClusterCount(String world) { - UUID uuid = getUUID(); - int count = 0; - for (PlotArea area : PlotSquared.get().getPlotAreas(world)) { - for (PlotCluster cluster : area.getClusters()) { - if (cluster.isOwner(getUUID())) { - count++; - } - } - } - return count; + String name = getName(); + if (ExpireManager.IMP != null) { + ExpireManager.IMP.storeDate(getUUID(), System.currentTimeMillis()); } + UUIDHandler.getPlayers().remove(name); + PlotSquared.get().IMP.unregister(this); + } - /** - * Get a {@code Set} of plots owned by this player. - * - * @return a {@code Set} of plots owned by the player - * @see PlotSquared for more searching functions - * @see #getPlotCount() for the number of plots - */ - public Set getPlots() { - return PlotSquared.get().getPlots(this); + /** + * Get the amount of clusters this player owns in the specific world. + */ + public int getPlayerClusterCount(String world) { + UUID uuid = getUUID(); + int count = 0; + for (PlotCluster cluster : PlotSquared.get().getClusters(world)) { + if (uuid.equals(cluster.owner)) { + count += cluster.getArea(); + } } + return count; + } - /** - * Return the PlotArea this player is currently in, or null. - * - * @return - */ - public PlotArea getPlotAreaAbs() { - return PlotSquared.get().getPlotAreaAbs(getLocation()); + /** + * Get the amount of clusters this player owns. + * + * @return the number of clusters this player owns + */ + public int getPlayerClusterCount() { + final AtomicInteger count = new AtomicInteger(); + PlotSquared.get().foreachPlotArea(new RunnableVal() { + @Override + public void run(PlotArea value) { + count.addAndGet(value.getClusters().size()); + } + }); + return count.get(); + } + + /** + * Return a {@code Set} of all plots this player owns in a certain world. + * + * @param world the world to retrieve plots from + * @return a {@code Set} of plots this player owns in the provided world + */ + public Set getPlots(String world) { + UUID uuid = getUUID(); + HashSet plots = new HashSet<>(); + for (Plot plot : PlotSquared.get().getPlots(world)) { + if (plot.isOwner(uuid)) { + plots.add(plot); + } } + return plots; + } - public PlotArea getApplicablePlotArea() { - return PlotSquared.get().getApplicablePlotArea(getLocation()); - } + public void populatePersistentMetaMap() { + if (Settings.Enabled_Components.PERSISTENT_META) { + DBFunc.getPersistentMeta(getUUID(), new RunnableVal>() { + @Override + public void run(Map value) { + try { + PlotPlayer.this.metaMap = value; + if (!value.isEmpty()) { + if (Settings.Enabled_Components.PERSISTENT_META) { + PlotAreaManager manager = PlotSquared.get().getPlotAreaManager(); + if (manager instanceof SinglePlotAreaManager) { + PlotArea area = ((SinglePlotAreaManager) manager).getArea(); + byte[] arr = PlotPlayer.this.getPersistentMeta("quitLoc"); + if (arr != null) { + removePersistentMeta("quitLoc"); - @Override public RequiredType getSuperCaller() { - return RequiredType.PLAYER; - } - - /** - * Get this player's last recorded location or null if they don't any plot relevant location. - * - * @return The location - */ - public Location getLocation() { - Location location = getMeta("location"); - if (location != null) { - return location; - } - return getLocationFull(); - } - - /////////////// PLAYER META /////////////// - - ////////////// PARTIALLY IMPLEMENTED /////////// - - /** - * Get this player's full location (including yaw/pitch) - * - * @return - */ - public abstract Location getLocationFull(); - - //////////////////////////////////////////////// - - /** - * Get this player's UUID. - * === !IMPORTANT ===
- * The UUID is dependent on the mode chosen in the settings.yml and may not be the same as Bukkit has - * (especially if using an old version of Bukkit that does not support UUIDs) - * - * @return UUID - */ - @Override public abstract UUID getUUID(); - - public boolean canTeleport(Location loc) { - Location current = getLocationFull(); - teleport(loc); - boolean result = true; - if (!getLocation().equals(loc)) { - result = false; - } - teleport(current); - return result; - } - - /** - * Teleport this player to a location. - * - * @param location the target location - */ - public abstract void teleport(Location location); - - /** - * Kick this player to a location - * - * @param location the target location - */ - public void plotkick(Location location) { - setMeta("kick", true); - teleport(location); - deleteMeta("kick"); - } - - /** - * Set this compass target. - * - * @param location the target location - */ - public abstract void setCompassTarget(Location location); - - /** - * Set player data that will persist restarts. - * - Please note that this is not intended to store large values - * - For session only data use meta - * - * @param key - */ - public void setAttribute(String key) { - setPersistentMeta("attrib_" + key, new byte[] {(byte) 1}); - } - - /** - * Retrieves the attribute of this player. - * - * @param key - * @return the attribute will be either true or false - */ - public boolean getAttribute(String key) { - if (!hasPersistentMeta("attrib_" + key)) { - return false; - } - return getPersistentMeta("attrib_" + key)[0] == 1; - } - - /** - * Remove an attribute from a player. - * - * @param key - */ - public void removeAttribute(String key) { - removePersistentMeta("attrib_" + key); - } - - /** - * Sets the local weather for this Player. - * - * @param weather the weather visible to the player - */ - public abstract void setWeather(PlotWeather weather); - - /** - * Get this player's gamemode. - * - * @return the gamemode of the player. - */ - public abstract PlotGameMode getGameMode(); - - /** - * Set this player's gameMode. - * - * @param gameMode the gamemode to set - */ - public abstract void setGameMode(PlotGameMode gameMode); - - /** - * Set this player's local time (ticks). - * - * @param time the time visible to the player - */ - public abstract void setTime(long time); - - public abstract boolean getFlight(); - - /** - * Set this player's fly mode. - * - * @param fly if the player can fly - */ - public abstract void setFlight(boolean fly); - - /** - * Play music at a location for this player. - * - * @param location where to play the music - * @param id the record item id - */ - public abstract void playMusic(Location location, PlotBlock id); - - /** - * Check if this player is banned. - * - * @return true if the player is banned, false otherwise. - */ - public abstract boolean isBanned(); - - /** - * Kick this player from the game. - * - * @param message the reason for the kick - */ - public abstract void kick(String message); - - /** - * Called when this player quits. - */ - public void unregister() { - Plot plot = getCurrentPlot(); - if (plot != null && Settings.Enabled_Components.PERSISTENT_META && plot - .getArea() instanceof SinglePlotArea) { - PlotId id = plot.getId(); - int x = id.x; - int z = id.y; - ByteBuffer buffer = ByteBuffer.allocate(13); - buffer.putShort((short) x); - buffer.putShort((short) z); - Location loc = getLocation(); - buffer.putInt(loc.getX()); - buffer.put((byte) loc.getY()); - buffer.putInt(loc.getZ()); - setPersistentMeta("quitLoc", buffer.array()); - } else if (hasPersistentMeta("quitLoc")) { - removePersistentMeta("quitLoc"); - } - if (plot != null) { - EventUtil.manager.callLeave(this, plot); - } - if (Settings.Enabled_Components.BAN_DELETER && isBanned()) { - for (Plot owned : getPlots()) { - owned.deletePlot(null); - PlotSquared.debug(String - .format("&cPlot &6%s &cwas deleted + cleared due to &6%s&c getting banned", - plot.getId(), getName())); - } - } - String name = getName(); - if (ExpireManager.IMP != null) { - ExpireManager.IMP.storeDate(getUUID(), System.currentTimeMillis()); - } - UUIDHandler.getPlayers().remove(name); - PlotSquared.get().IMP.unregister(this); - } - - /** - * Get the amount of clusters this player owns in the specific world. - * - * @param world - * @return - */ - public int getPlayerClusterCount(String world) { - UUID uuid = getUUID(); - int count = 0; - for (PlotCluster cluster : PlotSquared.get().getClusters(world)) { - if (uuid.equals(cluster.owner)) { - count += cluster.getArea(); - } - } - return count; - } - - /** - * Get the amount of clusters this player owns. - * - * @return the number of clusters this player owns - */ - public int getPlayerClusterCount() { - final AtomicInteger count = new AtomicInteger(); - PlotSquared.get().foreachPlotArea(new RunnableVal() { - @Override public void run(PlotArea value) { - count.addAndGet(value.getClusters().size()); - } - }); - return count.get(); - } - - /** - * Return a {@code Set} of all plots this player owns in a certain world. - * - * @param world the world to retrieve plots from - * @return a {@code Set} of plots this player owns in the provided world - */ - public Set getPlots(String world) { - UUID uuid = getUUID(); - HashSet plots = new HashSet<>(); - for (Plot plot : PlotSquared.get().getPlots(world)) { - if (plot.isOwner(uuid)) { - plots.add(plot); - } - } - return plots; - } - - public void populatePersistentMetaMap() { - if (Settings.Enabled_Components.PERSISTENT_META) { - DBFunc.getPersistentMeta(getUUID(), new RunnableVal>() { - @Override public void run(Map value) { - try { - PlotPlayer.this.metaMap = value; - if (!value.isEmpty()) { - if (Settings.Enabled_Components.PERSISTENT_META) { - PlotAreaManager manager = PlotSquared.get().getPlotAreaManager(); - if (manager instanceof SinglePlotAreaManager) { - PlotArea area = ((SinglePlotAreaManager) manager).getArea(); - byte[] arr = PlotPlayer.this.getPersistentMeta("quitLoc"); - if (arr != null) { - removePersistentMeta("quitLoc"); - - if (getMeta("teleportOnLogin", true)) { - ByteBuffer quitWorld = ByteBuffer.wrap(arr); - final int plotX = quitWorld.getShort(); - final int plotZ = quitWorld.getShort(); - PlotId id = new PlotId(plotX, plotZ); - int x = quitWorld.getInt(); - int y = quitWorld.get() & 0xFF; - int z = quitWorld.getInt(); - Plot plot = area.getOwnedPlot(id); - if (plot != null) { - final Location loc = - new Location(plot.getWorldName(), x, y, z); - if (plot.isLoaded()) { - TaskManager.runTask(new Runnable() { - @Override public void run() { - if (getMeta("teleportOnLogin", true)) { - teleport(loc); - sendMessage(C.TELEPORTED_TO_PLOT.f() - + " (quitLoc) (" + plotX + "," - + plotZ + ")"); - } - } - }); - } else if (!PlotSquared.get() - .isMainThread(Thread.currentThread())) { - if (getMeta("teleportOnLogin", true)) { - if (plot.teleportPlayer(PlotPlayer.this)) { - TaskManager.runTask(new Runnable() { - @Override public void run() { - if (getMeta("teleportOnLogin", - true)) { - teleport(loc); - sendMessage( - C.TELEPORTED_TO_PLOT.f() - + " (quitLoc-unloaded) (" - + plotX + "," - + plotZ + ")"); - } - } - }); - } - } - } - } - } - } - } + if (getMeta("teleportOnLogin", true)) { + ByteBuffer quitWorld = ByteBuffer.wrap(arr); + final int plotX = quitWorld.getShort(); + final int plotZ = quitWorld.getShort(); + PlotId id = new PlotId(plotX, plotZ); + int x = quitWorld.getInt(); + int y = quitWorld.get() & 0xFF; + int z = quitWorld.getInt(); + Plot plot = area.getOwnedPlot(id); + if (plot != null) { + final Location loc = + new Location(plot.getWorldName(), x, y, z); + if (plot.isLoaded()) { + TaskManager.runTask(() -> { + if (getMeta("teleportOnLogin", true)) { + teleport(loc); + sendMessage(C.TELEPORTED_TO_PLOT.f() + + " (quitLoc) (" + plotX + "," + + plotZ + ")"); } + }); + } else if (!PlotSquared.get() + .isMainThread(Thread.currentThread())) { + if (getMeta("teleportOnLogin", true)) { + if (plot.teleportPlayer(PlotPlayer.this)) { + TaskManager.runTask(() -> { + if (getMeta("teleportOnLogin", + true)) { + teleport(loc); + sendMessage( + C.TELEPORTED_TO_PLOT.f() + + " (quitLoc-unloaded) (" + + plotX + "," + + plotZ + ")"); + } + }); + } + } } - } catch (Throwable e) { - e.printStackTrace(); + } } + } } - }); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } } + }); } + } - public byte[] getPersistentMeta(String key) { - return this.metaMap.get(key); + public byte[] getPersistentMeta(String key) { + return this.metaMap.get(key); + } + + public void removePersistentMeta(String key) { + if (this.metaMap.containsKey(key)) { + this.metaMap.remove(key); } - - public void removePersistentMeta(String key) { - if (this.metaMap.containsKey(key)) { - this.metaMap.remove(key); - } - if (Settings.Enabled_Components.PERSISTENT_META) { - DBFunc.removePersistentMeta(getUUID(), key); - } + if (Settings.Enabled_Components.PERSISTENT_META) { + DBFunc.removePersistentMeta(getUUID(), key); } + } - public void setPersistentMeta(String key, byte[] value) { - boolean delete = hasPersistentMeta(key); - this.metaMap.put(key, value); - if (Settings.Enabled_Components.PERSISTENT_META) { - DBFunc.addPersistentMeta(getUUID(), key, value, delete); - } + public void setPersistentMeta(String key, byte[] value) { + boolean delete = hasPersistentMeta(key); + this.metaMap.put(key, value); + if (Settings.Enabled_Components.PERSISTENT_META) { + DBFunc.addPersistentMeta(getUUID(), key, value, delete); } + } - public boolean hasPersistentMeta(String key) { - return this.metaMap.containsKey(key); + public boolean hasPersistentMeta(String key) { + return this.metaMap.containsKey(key); + } + + public abstract void stopSpectating(); + + /** + * The amount of money this Player has. + */ + public double getMoney() { + return EconHandler.manager == null ? 0 : EconHandler.manager.getMoney(this); + } + + public void withdraw(double amount) { + if (EconHandler.manager != null) { + EconHandler.manager.withdrawMoney(this, amount); } + } - public abstract void stopSpectating(); - - /** - * The amount of money this Player has. - * - * @return - */ - public double getMoney() { - return EconHandler.manager == null ? 0 : EconHandler.manager.getMoney(this); + public void deposit(double amount) { + if (EconHandler.manager != null) { + EconHandler.manager.depositMoney(this, amount); } + } - public void withdraw(double amount) { - if (EconHandler.manager != null) { - EconHandler.manager.withdrawMoney(this, amount); - } - } + public interface PlotPlayerConverter { - public void deposit(double amount) { - if (EconHandler.manager != null) { - EconHandler.manager.depositMoney(this, amount); - } - } - - public interface PlotPlayerConverter { - PlotPlayer convert(BaseObject object); - } + PlotPlayer convert(BaseObject object); + } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotSettings.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotSettings.java index 4f3701f56..2ccaa47a8 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotSettings.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotSettings.java @@ -42,7 +42,7 @@ public class PlotSettings { /** * Flags. * - * @deprecated Raw access + * @deprecated Raw access. Not compatible with PlotClusters. */ @Deprecated public HashMap, Object> flags = new HashMap<>(); /** @@ -85,7 +85,7 @@ public class PlotSettings { return this.ratings; } - public boolean setMerged(int direction, boolean merged) { + boolean setMerged(int direction, boolean merged) { if (this.merged[direction] != merged) { this.merged[direction] = merged; return true; @@ -142,6 +142,7 @@ public class PlotSettings { } } + //todo need a plot method public Optional> getComments(String inbox) { ArrayList c = new ArrayList<>(); if (this.comments == null) { @@ -155,22 +156,26 @@ public class PlotSettings { return Optional.of(c); } + //todo need a plot method public void setComments(List comments) { this.comments = comments; } + //todo need a plot method public void removeComment(PlotComment comment) { if (this.comments.contains(comment)) { this.comments.remove(comment); } } + //todo need a plot method public void removeComments(List comments) { for (PlotComment comment : comments) { removeComment(comment); } } + //todo need a plot method public void addComment(PlotComment comment) { if (this.comments == null) { this.comments = new ArrayList<>(); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/stream/AbstractDelegateOutputStream.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/stream/AbstractDelegateOutputStream.java index 994f6a465..19425065f 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/stream/AbstractDelegateOutputStream.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/stream/AbstractDelegateOutputStream.java @@ -4,30 +4,31 @@ import java.io.IOException; import java.io.OutputStream; public class AbstractDelegateOutputStream extends OutputStream { - private final OutputStream parent; - public AbstractDelegateOutputStream(OutputStream os) { - this.parent = os; - } + private final OutputStream parent; - @Override public void write(int b) throws IOException { - parent.write(b); - } + public AbstractDelegateOutputStream(OutputStream os) { + this.parent = os; + } - @Override public void write(byte[] b) throws IOException { - parent.write(b); - } + @Override + public void write(int b) throws IOException { + parent.write(b); + } - @Override public void write(byte[] b, int off, int len) throws IOException { - parent.write(b, off, len); - } + @Override + public void write(byte[] b) throws IOException { + parent.write(b); + } + + @Override + public void flush() throws IOException { + parent.flush(); + } - @Override public void flush() throws IOException { - parent.flush(); - } - - @Override public void close() throws IOException { - parent.close(); - } + @Override + public void close() throws IOException { + parent.close(); + } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/DefaultPlotAreaManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/DefaultPlotAreaManager.java index 989948f0c..0919624d9 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/DefaultPlotAreaManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/DefaultPlotAreaManager.java @@ -88,9 +88,9 @@ public class DefaultPlotAreaManager implements PlotAreaManager { HashSet globalAreas = new HashSet<>(Arrays.asList(plotAreas)); localAreas.add(plotArea); globalAreas.add(plotArea); - this.plotAreas = globalAreas.toArray(new PlotArea[globalAreas.size()]); + this.plotAreas = globalAreas.toArray(new PlotArea[0]); this.plotAreaMap - .put(plotArea.worldname, localAreas.toArray(new PlotArea[localAreas.size()])); + .put(plotArea.worldname, localAreas.toArray(new PlotArea[0])); QuadMap map = this.plotAreaGrid.get(plotArea.worldname); if (map == null) { map = new QuadMap(Integer.MAX_VALUE, 0, 0) { @@ -104,15 +104,15 @@ public class DefaultPlotAreaManager implements PlotAreaManager { } @Override public void removePlotArea(PlotArea area) { - ArrayList globalAreas = new ArrayList(Arrays.asList(plotAreas)); + ArrayList globalAreas = new ArrayList<>(Arrays.asList(plotAreas)); globalAreas.remove(area); - this.plotAreas = globalAreas.toArray(new PlotArea[globalAreas.size()]); + this.plotAreas = globalAreas.toArray(new PlotArea[0]); if (globalAreas.isEmpty()) { this.plotAreaMap.remove(area.worldname); this.plotAreaGrid.remove(area.worldname); } else { this.plotAreaMap - .put(area.worldname, globalAreas.toArray(new PlotArea[globalAreas.size()])); + .put(area.worldname, globalAreas.toArray(new PlotArea[0])); this.plotAreaGrid.get(area.worldname).remove(area); } } @@ -206,7 +206,7 @@ public class DefaultPlotAreaManager implements PlotAreaManager { return noPlotAreas; } else { Set found = areas.get(region); - return found.toArray(new PlotArea[found.size()]); + return found.toArray(new PlotArea[0]); } } @@ -217,14 +217,14 @@ public class DefaultPlotAreaManager implements PlotAreaManager { Set tmp = new LinkedHashSet<>(); Collections.addAll(tmp, worlds); tmp.add(worldName); - worlds = tmp.toArray(new String[tmp.size()]); + worlds = tmp.toArray(new String[0]); } @Override public void removeWorld(String worldName) { Set tmp = new LinkedHashSet<>(); Collections.addAll(tmp, worlds); tmp.remove(worldName); - worlds = tmp.toArray(new String[tmp.size()]); + worlds = tmp.toArray(new String[0]); } @Override public String[] getAllWorlds() { diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/PlotAreaManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/PlotAreaManager.java index aef7f53a8..7a59dab9d 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/PlotAreaManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/PlotAreaManager.java @@ -5,24 +5,24 @@ import com.github.intellectualsites.plotsquared.plot.object.PlotArea; import com.github.intellectualsites.plotsquared.plot.object.RegionWrapper; public interface PlotAreaManager { - public PlotArea getApplicablePlotArea(Location location); + PlotArea getApplicablePlotArea(Location location); - public PlotArea getPlotArea(Location location); + PlotArea getPlotArea(Location location); - public PlotArea getPlotArea(String world, String id); + PlotArea getPlotArea(String world, String id); - public PlotArea[] getPlotAreas(String world, RegionWrapper region); + PlotArea[] getPlotAreas(String world, RegionWrapper region); - public PlotArea[] getAllPlotAreas(); + PlotArea[] getAllPlotAreas(); - public String[] getAllWorlds(); + String[] getAllWorlds(); - public void addPlotArea(PlotArea area); + void addPlotArea(PlotArea area); - public void removePlotArea(PlotArea area); + void removePlotArea(PlotArea area); - public void addWorld(String worldName); + void addWorld(String worldName); - public void removeWorld(String worldName); + void removeWorld(String worldName); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlot.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlot.java index 5e153c02e..7d57e7d2c 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlot.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlot.java @@ -7,6 +7,7 @@ import com.github.intellectualsites.plotsquared.plot.object.*; import java.util.Collection; import java.util.HashSet; import java.util.UUID; +import javax.annotation.Nonnull; public class SinglePlot extends Plot { private HashSet regions; @@ -40,6 +41,7 @@ public class SinglePlot extends Plot { return getId().toCommaSeparatedString(); } + @Nonnull @Override public SinglePlotArea getArea() { return (SinglePlotArea) super.getArea(); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlotAreaManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlotAreaManager.java index adc462f4e..a3b398136 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlotAreaManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlotAreaManager.java @@ -35,8 +35,7 @@ public class SinglePlotAreaManager extends DefaultPlotAreaManager { if (chars.length == 1 && chars[0] == '*') { return true; } - for (int i = 0; i < chars.length; i++) { - char c = chars[i]; + for (char c : chars) { switch (mode) { case 0: mode = 1; diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlotManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlotManager.java index 8e5a6da12..f8e4ab000 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlotManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/worlds/SinglePlotManager.java @@ -30,12 +30,10 @@ public class SinglePlotManager extends PlotManager { SetupUtils.manager.unload(plot.getWorldName(), false); final File worldFolder = new File(PlotSquared.get().IMP.getWorldContainer(), plot.getWorldName()); - TaskManager.IMP.taskAsync(new Runnable() { - @Override public void run() { - MainUtil.deleteDirectory(worldFolder); - if (whenDone != null) - whenDone.run(); - } + TaskManager.IMP.taskAsync(() -> { + MainUtil.deleteDirectory(worldFolder); + if (whenDone != null) + whenDone.run(); }); return true; } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/AbstractTitle.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/AbstractTitle.java index a5f75c96a..329230eaf 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/AbstractTitle.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/AbstractTitle.java @@ -15,6 +15,6 @@ public abstract class AbstractTitle { } } - public abstract void sendTitle(PlotPlayer player, String head, String sub, int in, int delay, + protected abstract void sendTitle(PlotPlayer player, String head, String sub, int in, int delay, int out); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/ChunkManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/ChunkManager.java index e863e1302..d27dc7597 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/ChunkManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/ChunkManager.java @@ -71,41 +71,39 @@ public abstract class ChunkManager { public static void largeRegionTask(final String world, final RegionWrapper region, final RunnableVal task, final Runnable whenDone) { - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - HashSet chunks = new HashSet<>(); - Set mcrs = manager.getChunkChunks(world); - for (ChunkLoc mcr : mcrs) { - int bx = mcr.x << 9; - int bz = mcr.z << 9; - int tx = bx + 511; - int tz = bz + 511; - if (bx <= region.maxX && tx >= region.minX && bz <= region.maxZ - && tz >= region.minZ) { - for (int x = bx >> 4; x <= (tx >> 4); x++) { - int cbx = x << 4; - int ctx = cbx + 15; - if (cbx <= region.maxX && ctx >= region.minX) { - for (int z = bz >> 4; z <= (tz >> 4); z++) { - int cbz = z << 4; - int ctz = cbz + 15; - if (cbz <= region.maxZ && ctz >= region.minZ) { - chunks.add(new ChunkLoc(x, z)); - } + TaskManager.runTaskAsync(() -> { + HashSet chunks = new HashSet<>(); + Set mcrs = manager.getChunkChunks(world); + for (ChunkLoc mcr : mcrs) { + int bx = mcr.x << 9; + int bz = mcr.z << 9; + int tx = bx + 511; + int tz = bz + 511; + if (bx <= region.maxX && tx >= region.minX && bz <= region.maxZ + && tz >= region.minZ) { + for (int x = bx >> 4; x <= (tx >> 4); x++) { + int cbx = x << 4; + int ctx = cbx + 15; + if (cbx <= region.maxX && ctx >= region.minX) { + for (int z = bz >> 4; z <= (tz >> 4); z++) { + int cbz = z << 4; + int ctz = cbz + 15; + if (cbz <= region.maxZ && ctz >= region.minZ) { + chunks.add(new ChunkLoc(x, z)); } } } } } - TaskManager.objectTask(chunks, new RunnableVal() { - - @Override public void run(ChunkLoc value) { - if (manager.loadChunk(world, value, false)) { - task.run(value); - } - } - }, whenDone); } + TaskManager.objectTask(chunks, new RunnableVal() { + + @Override public void run(ChunkLoc value) { + if (manager.loadChunk(world, value, false)) { + task.run(value); + } + } + }, whenDone); }); } @@ -239,20 +237,18 @@ public abstract class ChunkManager { public void deleteRegionFiles(final String world, final Collection chunks, final Runnable whenDone) { - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - for (ChunkLoc loc : chunks) { - String directory = - world + File.separator + "region" + File.separator + "r." + loc.x + "." - + loc.z + ".mca"; - File file = new File(PlotSquared.get().IMP.getWorldContainer(), directory); - PlotSquared.log("&6 - Deleting file: " + file.getName() + " (max 1024 chunks)"); - if (file.exists()) { - file.delete(); - } + TaskManager.runTaskAsync(() -> { + for (ChunkLoc loc : chunks) { + String directory = + world + File.separator + "region" + File.separator + "r." + loc.x + "." + + loc.z + ".mca"; + File file = new File(PlotSquared.get().IMP.getWorldContainer(), directory); + PlotSquared.log("&6 - Deleting file: " + file.getName() + " (max 1024 chunks)"); + if (file.exists()) { + file.delete(); } - TaskManager.runTask(whenDone); } + TaskManager.runTask(whenDone); }); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/CmdConfirm.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/CmdConfirm.java index 11c157320..d0b4012a6 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/CmdConfirm.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/CmdConfirm.java @@ -19,11 +19,9 @@ public class CmdConfirm { removePending(player); if (commandStr != null) MainUtil.sendMessage(player, C.REQUIRES_CONFIRM, commandStr); - TaskManager.runTaskLater(new Runnable() { - @Override public void run() { - CmdInstance cmd = new CmdInstance(runnable); - player.setMeta("cmdConfirm", cmd); - } + TaskManager.runTaskLater(() -> { + CmdInstance cmd = new CmdInstance(runnable); + player.setMeta("cmdConfirm", cmd); }, 1); } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/CommentManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/CommentManager.java index 3dc43fe06..cc5021c57 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/CommentManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/CommentManager.java @@ -20,34 +20,32 @@ public class CommentManager { if (!Settings.Enabled_Components.COMMENT_NOTIFIER || !plot.isOwner(player.getUUID())) { return; } - TaskManager.runTaskLaterAsync(new Runnable() { - @Override public void run() { - Collection boxes = CommentManager.inboxes.values(); - final AtomicInteger count = new AtomicInteger(0); - final AtomicInteger size = new AtomicInteger(boxes.size()); - for (final CommentInbox inbox : inboxes.values()) { - inbox.getComments(plot, new RunnableVal>() { - @Override public void run(List value) { - int total; - if (value != null) { - int num = 0; - for (PlotComment comment : value) { - if (comment.timestamp > getTimestamp(player, - inbox.toString())) { - num++; - } + TaskManager.runTaskLaterAsync(() -> { + Collection boxes = CommentManager.inboxes.values(); + final AtomicInteger count = new AtomicInteger(0); + final AtomicInteger size = new AtomicInteger(boxes.size()); + for (final CommentInbox inbox : inboxes.values()) { + inbox.getComments(plot, new RunnableVal>() { + @Override public void run(List value) { + int total; + if (value != null) { + int num = 0; + for (PlotComment comment : value) { + if (comment.timestamp > getTimestamp(player, + inbox.toString())) { + num++; } - total = count.addAndGet(num); - } else { - total = count.get(); - } - if ((size.decrementAndGet() == 0) && (total > 0)) { - AbstractTitle.sendTitle(player, "", - C.INBOX_NOTIFICATION.s().replaceAll("%s", "" + total)); } + total = count.addAndGet(num); + } else { + total = count.get(); } - }); - } + if ((size.decrementAndGet() == 0) && (total > 0)) { + AbstractTitle.sendTitle(player, "", + C.INBOX_NOTIFICATION.s().replaceAll("%s", "" + total)); + } + } + }); } }, 20); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/EventUtil.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/EventUtil.java index b8037944e..7d82e5236 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/EventUtil.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/EventUtil.java @@ -43,8 +43,6 @@ public abstract class EventUtil { public abstract boolean callFlagRemove(Flag flag, Plot plot, Object value); - public abstract boolean callFlagRemove(Flag flag, Object value, PlotCluster cluster); - public abstract boolean callMerge(Plot plot, int dir, int max); public abstract boolean callAutoMerge(Plot plot, List plots); @@ -78,11 +76,7 @@ public abstract class EventUtil { } final Plot plot = player.getCurrentPlot(); if (Settings.Teleport.ON_LOGIN && plot != null) { - TaskManager.runTask(new Runnable() { - @Override public void run() { - plot.teleportPlayer(player); - } - }); + TaskManager.runTask(() -> plot.teleportPlayer(player)); MainUtil.sendMessage(player, C.TELEPORTED_TO_ROAD.f() + " (on-login) " + "(" + plot.getId().x + ";" + plot .getId().y + ")"); diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/MainUtil.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/MainUtil.java index 906c70595..e65169260 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/MainUtil.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/MainUtil.java @@ -411,7 +411,7 @@ public class MainUtil { ArrayList> plotList = new ArrayList<>(size); for (int i = 0; i < size; i++) { - plotList.add(new ArrayList()); + plotList.add(new ArrayList<>()); } for (Plot plot : PlotSquared.get().getPlots()) { @@ -430,7 +430,7 @@ public class MainUtil { count++; } } - if (area != null && plot.getArea().equals(area)) { + if (plot.getArea().equals(area)) { count++; } if (alias != null && alias.equals(plot.getAlias())) { @@ -622,14 +622,12 @@ public class MainUtil { if (caption.s().isEmpty()) { return true; } - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - String m = C.format(caption, args); - if (player == null) { - PlotSquared.log(m); - } else { - player.sendMessage(m); - } + TaskManager.runTaskAsync(() -> { + String m = C.format(caption, args); + if (player == null) { + PlotSquared.log(m); + } else { + player.sendMessage(m); } }); return true; @@ -780,31 +778,29 @@ public class MainUtil { info = info.replace("%desc%", "No description set."); if (info.contains("%rating%")) { final String newInfo = info; - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - int max = 10; - if (Settings.Ratings.CATEGORIES != null && !Settings.Ratings.CATEGORIES - .isEmpty()) { - max = 8; - } - String info; - if (full && Settings.Ratings.CATEGORIES != null - && Settings.Ratings.CATEGORIES.size() > 1) { - double[] ratings = MainUtil.getAverageRatings(plot); - String rating = ""; - String prefix = ""; - for (int i = 0; i < ratings.length; i++) { - rating += prefix + Settings.Ratings.CATEGORIES.get(i) + '=' + String - .format("%.1f", ratings[i]); - prefix = ","; - } - info = newInfo.replaceAll("%rating%", rating); - } else { - info = newInfo.replaceAll("%rating%", - String.format("%.1f", plot.getAverageRating()) + '/' + max); - } - whenDone.run(info); + TaskManager.runTaskAsync(() -> { + int max = 10; + if (Settings.Ratings.CATEGORIES != null && !Settings.Ratings.CATEGORIES + .isEmpty()) { + max = 8; } + String info1; + if (full && Settings.Ratings.CATEGORIES != null + && Settings.Ratings.CATEGORIES.size() > 1) { + double[] ratings = MainUtil.getAverageRatings(plot); + String rating = ""; + String prefix = ""; + for (int i = 0; i < ratings.length; i++) { + rating += prefix + Settings.Ratings.CATEGORIES.get(i) + '=' + String + .format("%.1f", ratings[i]); + prefix = ","; + } + info1 = newInfo.replaceAll("%rating%", rating); + } else { + info1 = newInfo.replaceAll("%rating%", + String.format("%.1f", plot.getAverageRating()) + '/' + max); + } + whenDone.run(info1); }); return; } @@ -815,10 +811,9 @@ public class MainUtil { if (directory.exists()) { File[] files = directory.listFiles(); if (null != files) { - for (int i = 0; i < files.length; i++) { - File file = files[i]; + for (File file : files) { if (file.isDirectory()) { - deleteDirectory(files[i]); + deleteDirectory(file); } else { PlotSquared.debug("Deleting file: " + file + " | " + file.delete()); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/SchematicHandler.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/SchematicHandler.java index f1ca31b4d..05eeee166 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/SchematicHandler.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/SchematicHandler.java @@ -87,7 +87,7 @@ public abstract class SchematicHandler { } else { MainUtil.sendMessage(null, "&7 - &a success: " + plot.getId()); } - TaskManager.runTask(() -> THIS.run()); + TaskManager.runTask(THIS); }); } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/GlobalBlockQueue.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/GlobalBlockQueue.java index 3991cd78d..3d065a527 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/GlobalBlockQueue.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/block/GlobalBlockQueue.java @@ -13,292 +13,292 @@ import java.util.concurrent.atomic.AtomicBoolean; public class GlobalBlockQueue { - public static GlobalBlockQueue IMP; - private final int PARALLEL_THREADS; - private final ConcurrentLinkedDeque activeQueues; - private final ConcurrentLinkedDeque inactiveQueues; - private final ConcurrentLinkedDeque runnables; - private final AtomicBoolean running; - private QueueProvider provider; - /** - * Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the server - */ - private long last; - private long secondLast; - private long lastSuccess; - private final RunnableVal2 SET_TASK = - new RunnableVal2() { - @Override public void run(Long free, LocalBlockQueue queue) { - do { - boolean more = queue.next(); - if (!more) { - lastSuccess = last; - if (inactiveQueues.size() == 0 && activeQueues.size() == 0) { - tasks(); - } - return; - } - } while (((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) - - GlobalBlockQueue.this.last) < free); + public static GlobalBlockQueue IMP; + private final int PARALLEL_THREADS; + private final ConcurrentLinkedDeque activeQueues; + private final ConcurrentLinkedDeque inactiveQueues; + private final ConcurrentLinkedDeque runnables; + private final AtomicBoolean running; + private QueueProvider provider; + /** + * Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the + * server + */ + private long last; + private long secondLast; + private long lastSuccess; + private final RunnableVal2 SET_TASK = + new RunnableVal2() { + @Override + public void run(Long free, LocalBlockQueue queue) { + do { + boolean more = queue.next(); + if (!more) { + lastSuccess = last; + if (inactiveQueues.size() == 0 && activeQueues.size() == 0) { + tasks(); + } + return; } - }; - - public GlobalBlockQueue(QueueProvider provider, int threads) { - this.provider = provider; - activeQueues = new ConcurrentLinkedDeque<>(); - inactiveQueues = new ConcurrentLinkedDeque<>(); - runnables = new ConcurrentLinkedDeque<>(); - running = new AtomicBoolean(); - this.PARALLEL_THREADS = threads; - } - - public QueueProvider getProvider() { - return provider; - } - - public void setProvider(QueueProvider provider) { - this.provider = provider; - } - - public LocalBlockQueue getNewQueue(String world, boolean autoQueue) { - LocalBlockQueue queue = provider.getNewQueue(world); - if (autoQueue) { - inactiveQueues.add(queue); + } while (((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) + - GlobalBlockQueue.this.last) < free); } - return queue; - } + }; - public boolean stop() { - if (!running.get()) { - return false; - } - running.set(false); - return true; - } + public GlobalBlockQueue(QueueProvider provider, int threads) { + this.provider = provider; + activeQueues = new ConcurrentLinkedDeque<>(); + inactiveQueues = new ConcurrentLinkedDeque<>(); + runnables = new ConcurrentLinkedDeque<>(); + running = new AtomicBoolean(); + this.PARALLEL_THREADS = threads; + } - public boolean runTask() { - if (running.get()) { - return false; - } - running.set(true); - TaskManager.runTaskRepeat(new Runnable() { - @Override public void run() { - if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) { - lastSuccess = System.currentTimeMillis(); - tasks(); - return; - } - SET_TASK.value1 = 50 + Math.min( - (50 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = - System.currentTimeMillis()), - GlobalBlockQueue.this.secondLast - System.currentTimeMillis()); - SET_TASK.value2 = getNextQueue(); - if (SET_TASK.value2 == null) { - return; - } - if (!PlotSquared.get().isMainThread(Thread.currentThread())) { - throw new IllegalStateException( - "This shouldn't be possible for placement to occur off the main thread"); - } - // Disable the async catcher as it can't discern async vs parallel - SET_TASK.value2.startSet(true); - try { - if (PARALLEL_THREADS <= 1) { - SET_TASK.run(); - } else { - ArrayList threads = new ArrayList(); - for (int i = 0; i < PARALLEL_THREADS; i++) { - threads.add(new Thread(SET_TASK)); - } - for (Thread thread : threads) { - thread.start(); - } - for (Thread thread : threads) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } catch (Throwable e) { - e.printStackTrace(); - } finally { - // Enable it again (note that we are still on the main thread) - SET_TASK.value2.endSet(true); - } - } - }, 1); - return true; - } + public QueueProvider getProvider() { + return provider; + } - public QueueStage getStage(LocalBlockQueue queue) { - if (activeQueues.contains(queue)) { - return QueueStage.ACTIVE; - } else if (inactiveQueues.contains(queue)) { - return QueueStage.INACTIVE; - } - return QueueStage.NONE; - } + public void setProvider(QueueProvider provider) { + this.provider = provider; + } - public boolean isStage(LocalBlockQueue queue, QueueStage stage) { - switch (stage) { - case ACTIVE: - return activeQueues.contains(queue); - case INACTIVE: - return inactiveQueues.contains(queue); - case NONE: - return !activeQueues.contains(queue) && !inactiveQueues.contains(queue); - } - return false; + public LocalBlockQueue getNewQueue(String world, boolean autoQueue) { + LocalBlockQueue queue = provider.getNewQueue(world); + if (autoQueue) { + inactiveQueues.add(queue); } + return queue; + } - public void enqueue(LocalBlockQueue queue) { - inactiveQueues.remove(queue); - if (queue.size() > 0 && !activeQueues.contains(queue)) { - queue.optimize(); - activeQueues.add(queue); - } + public boolean stop() { + if (!running.get()) { + return false; } + running.set(false); + return true; + } - public void dequeue(LocalBlockQueue queue) { - inactiveQueues.remove(queue); - activeQueues.remove(queue); + public boolean runTask() { + if (running.get()) { + return false; } - - public List getAllQueues() { - ArrayList list = - new ArrayList(activeQueues.size() + inactiveQueues.size()); - list.addAll(inactiveQueues); - list.addAll(activeQueues); - return list; - } - - public List getActiveQueues() { - return new ArrayList<>(activeQueues); - } - - public List getInactiveQueues() { - return new ArrayList<>(inactiveQueues); - } - - public void flush(LocalBlockQueue queue) { - SET_TASK.value1 = Long.MAX_VALUE; - SET_TASK.value2 = queue; - if (SET_TASK.value2 == null) { - return; - } - if (PlotSquared.get().isMainThread(Thread.currentThread())) { - throw new IllegalStateException("Must be flushed on the main thread!"); - } - // Disable the async catcher as it can't discern async vs parallel - SET_TASK.value2.startSet(true); - try { - if (PARALLEL_THREADS <= 1) { - SET_TASK.run(); - } else { - ArrayList threads = new ArrayList(); - for (int i = 0; i < PARALLEL_THREADS; i++) { - threads.add(new Thread(SET_TASK)); - } - for (Thread thread : threads) { - thread.start(); - } - for (Thread thread : threads) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } catch (Throwable e) { - e.printStackTrace(); - } finally { - // Enable it again (note that we are still on the main thread) - SET_TASK.value2.endSet(true); - dequeue(queue); - } - } - - public LocalBlockQueue getNextQueue() { - long now = System.currentTimeMillis(); - while (activeQueues.size() > 0) { - LocalBlockQueue queue = activeQueues.peek(); - if (queue != null && queue.size() > 0) { - queue.setModified(now); - return queue; - } else { - activeQueues.poll(); - } - } - int size = inactiveQueues.size(); - if (size > 0) { - Iterator iter = inactiveQueues.iterator(); + running.set(true); + TaskManager.runTaskRepeat(() -> { + if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) { + lastSuccess = System.currentTimeMillis(); + tasks(); + return; + } + SET_TASK.value1 = 50 + Math.min( + (50 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = + System.currentTimeMillis()), + GlobalBlockQueue.this.secondLast - System.currentTimeMillis()); + SET_TASK.value2 = getNextQueue(); + if (SET_TASK.value2 == null) { + return; + } + if (!PlotSquared.get().isMainThread(Thread.currentThread())) { + throw new IllegalStateException( + "This shouldn't be possible for placement to occur off the main thread"); + } + // Disable the async catcher as it can't discern async vs parallel + SET_TASK.value2.startSet(true); + try { + if (PARALLEL_THREADS <= 1) { + SET_TASK.run(); + } else { + ArrayList threads = new ArrayList(); + for (int i = 0; i < PARALLEL_THREADS; i++) { + threads.add(new Thread(SET_TASK)); + } + for (Thread thread : threads) { + thread.start(); + } + for (Thread thread : threads) { try { - int total = 0; - LocalBlockQueue firstNonEmpty = null; - while (iter.hasNext()) { - LocalBlockQueue queue = iter.next(); - long age = now - queue.getModified(); - total += queue.size(); - if (queue.size() == 0) { - if (age > 1000) { - iter.remove(); - } - continue; - } - if (firstNonEmpty == null) { - firstNonEmpty = queue; - } - if (total > 64) { - firstNonEmpty.setModified(now); - return firstNonEmpty; - } - if (age > 60000) { - queue.setModified(now); - return queue; - } - } - } catch (ConcurrentModificationException e) { - e.printStackTrace(); + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); } + } } - return null; - } + } catch (Throwable e) { + e.printStackTrace(); + } finally { + // Enable it again (note that we are still on the main thread) + SET_TASK.value2.endSet(true); + } + }, 1); + return true; + } - public boolean isDone() { - return activeQueues.size() == 0 && inactiveQueues.size() == 0; + public QueueStage getStage(LocalBlockQueue queue) { + if (activeQueues.contains(queue)) { + return QueueStage.ACTIVE; + } else if (inactiveQueues.contains(queue)) { + return QueueStage.INACTIVE; } + return QueueStage.NONE; + } - public boolean addTask(final Runnable whenDone) { - if (this.isDone()) { - // Run - this.tasks(); - if (whenDone != null) { - whenDone.run(); + public boolean isStage(LocalBlockQueue queue, QueueStage stage) { + switch (stage) { + case ACTIVE: + return activeQueues.contains(queue); + case INACTIVE: + return inactiveQueues.contains(queue); + case NONE: + return !activeQueues.contains(queue) && !inactiveQueues.contains(queue); + } + return false; + } + + public void enqueue(LocalBlockQueue queue) { + inactiveQueues.remove(queue); + if (queue.size() > 0 && !activeQueues.contains(queue)) { + queue.optimize(); + activeQueues.add(queue); + } + } + + public void dequeue(LocalBlockQueue queue) { + inactiveQueues.remove(queue); + activeQueues.remove(queue); + } + + public List getAllQueues() { + ArrayList list = + new ArrayList<>(activeQueues.size() + inactiveQueues.size()); + list.addAll(inactiveQueues); + list.addAll(activeQueues); + return list; + } + + public List getActiveQueues() { + return new ArrayList<>(activeQueues); + } + + public List getInactiveQueues() { + return new ArrayList<>(inactiveQueues); + } + + public void flush(LocalBlockQueue queue) { + SET_TASK.value1 = Long.MAX_VALUE; + SET_TASK.value2 = queue; + if (SET_TASK.value2 == null) { + return; + } + if (PlotSquared.get().isMainThread(Thread.currentThread())) { + throw new IllegalStateException("Must be flushed on the main thread!"); + } + // Disable the async catcher as it can't discern async vs parallel + SET_TASK.value2.startSet(true); + try { + if (PARALLEL_THREADS <= 1) { + SET_TASK.run(); + } else { + ArrayList threads = new ArrayList<>(); + for (int i = 0; i < PARALLEL_THREADS; i++) { + threads.add(new Thread(SET_TASK)); + } + for (Thread thread : threads) { + thread.start(); + } + for (Thread thread : threads) { + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } catch (Throwable e) { + e.printStackTrace(); + } finally { + // Enable it again (note that we are still on the main thread) + SET_TASK.value2.endSet(true); + dequeue(queue); + } + } + + public LocalBlockQueue getNextQueue() { + long now = System.currentTimeMillis(); + while (activeQueues.size() > 0) { + LocalBlockQueue queue = activeQueues.peek(); + if (queue != null && queue.size() > 0) { + queue.setModified(now); + return queue; + } else { + activeQueues.poll(); + } + } + int size = inactiveQueues.size(); + if (size > 0) { + Iterator iter = inactiveQueues.iterator(); + try { + int total = 0; + LocalBlockQueue firstNonEmpty = null; + while (iter.hasNext()) { + LocalBlockQueue queue = iter.next(); + long age = now - queue.getModified(); + total += queue.size(); + if (queue.size() == 0) { + if (age > 1000) { + iter.remove(); } - return true; + continue; + } + if (firstNonEmpty == null) { + firstNonEmpty = queue; + } + if (total > 64) { + firstNonEmpty.setModified(now); + return firstNonEmpty; + } + if (age > 60000) { + queue.setModified(now); + return queue; + } } - if (whenDone != null) { - this.runnables.add(whenDone); - } - return false; + } catch (ConcurrentModificationException e) { + e.printStackTrace(); + } } + return null; + } - public synchronized boolean tasks() { - if (this.runnables.isEmpty()) { - return false; - } - final ArrayList tmp = new ArrayList<>(this.runnables); - this.runnables.clear(); - for (final Runnable runnable : tmp) { - runnable.run(); - } - return true; - } + public boolean isDone() { + return activeQueues.size() == 0 && inactiveQueues.size() == 0; + } - public enum QueueStage { - INACTIVE, ACTIVE, NONE; + public boolean addTask(final Runnable whenDone) { + if (this.isDone()) { + // Run + this.tasks(); + if (whenDone != null) { + whenDone.run(); + } + return true; } + if (whenDone != null) { + this.runnables.add(whenDone); + } + return false; + } + + public synchronized boolean tasks() { + if (this.runnables.isEmpty()) { + return false; + } + final ArrayList tmp = new ArrayList<>(this.runnables); + this.runnables.clear(); + for (final Runnable runnable : tmp) { + runnable.run(); + } + return true; + } + + public enum QueueStage { + INACTIVE, ACTIVE, NONE + } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpireManager.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpireManager.java index 84f86daa2..2f69b818e 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpireManager.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpireManager.java @@ -19,454 +19,435 @@ import java.util.concurrent.ConcurrentLinkedDeque; public class ExpireManager { - public static ExpireManager IMP; - private final ConcurrentHashMap dates_cache; - private final ConcurrentHashMap account_age_cache; - private volatile HashSet plotsToDelete; - private ArrayDeque tasks; - /** - * 0 = stopped, 1 = stopping, 2 = running - */ - private int running; + public static ExpireManager IMP; + private final ConcurrentHashMap dates_cache; + private final ConcurrentHashMap account_age_cache; + private volatile HashSet plotsToDelete; + private ArrayDeque tasks; + /** + * 0 = stopped, 1 = stopping, 2 = running + */ + private int running; - public ExpireManager() { - tasks = new ArrayDeque<>(); - dates_cache = new ConcurrentHashMap<>(); - account_age_cache = new ConcurrentHashMap<>(); + public ExpireManager() { + tasks = new ArrayDeque<>(); + dates_cache = new ConcurrentHashMap<>(); + account_age_cache = new ConcurrentHashMap<>(); + } + + public void addTask(ExpiryTask task) { + PlotSquared.debug("Adding new expiry task!"); + this.tasks.add(task); + } + + public void handleJoin(PlotPlayer pp) { + storeDate(pp.getUUID(), System.currentTimeMillis()); + if (plotsToDelete != null && !plotsToDelete.isEmpty()) { + for (Plot plot : pp.getPlots()) { + plotsToDelete.remove(plot); + } } + confirmExpiry(pp); + } - public void addTask(ExpiryTask task) { - PlotSquared.debug("Adding new expiry task!"); - this.tasks.add(task); - } - - public void handleJoin(PlotPlayer pp) { - storeDate(pp.getUUID(), System.currentTimeMillis()); - if (plotsToDelete != null && !plotsToDelete.isEmpty()) { - for (Plot plot : pp.getPlots()) { - plotsToDelete.remove(plot); - } - } + public void handleEntry(PlotPlayer pp, Plot plot) { + if (plotsToDelete != null && !plotsToDelete.isEmpty() && pp + .hasPermission("plots.admin.command.autoclear") && plotsToDelete.contains(plot)) { + if (!isExpired(new ArrayDeque<>(tasks), plot).isEmpty()) { confirmExpiry(pp); + } else { + plotsToDelete.remove(plot); + confirmExpiry(pp); + } } + } - public void handleEntry(PlotPlayer pp, Plot plot) { - if (plotsToDelete != null && !plotsToDelete.isEmpty() && pp - .hasPermission("plots.admin.command.autoclear") && plotsToDelete.contains(plot)) { - if (!isExpired(new ArrayDeque<>(tasks), plot).isEmpty()) { - confirmExpiry(pp); - } else { - plotsToDelete.remove(plot); - confirmExpiry(pp); - } - } + /** + * Gets the account last joined - first joined (or Long.MAX_VALUE) + * + * @return result + */ + public long getAccountAge(UUID uuid) { + Long value = this.account_age_cache.get(uuid); + return value == null ? Long.MAX_VALUE : value; + } + + public long getTimestamp(UUID uuid) { + Long value = this.dates_cache.get(uuid); + return value == null ? 0 : value; + } + + public void updateExpired(Plot plot) { + if (plotsToDelete != null && !plotsToDelete.isEmpty() && plotsToDelete.contains(plot)) { + if (isExpired(new ArrayDeque<>(tasks), plot).isEmpty()) { + plotsToDelete.remove(plot); + } } + } - /** - * Gets the account last joined - first joined (or Long.MAX_VALUE) - * - * @param uuid - * @return result - */ - public long getAccountAge(UUID uuid) { - Long value = this.account_age_cache.get(uuid); - return value == null ? Long.MAX_VALUE : value; + public void confirmExpiry(final PlotPlayer pp) { + if (pp.getMeta("ignoreExpireTask") != null) { + return; } - - public long getTimestamp(UUID uuid) { - Long value = this.dates_cache.get(uuid); - return value == null ? 0 : value; - } - - public void updateExpired(Plot plot) { - if (plotsToDelete != null && !plotsToDelete.isEmpty() && plotsToDelete.contains(plot)) { - if (isExpired(new ArrayDeque<>(tasks), plot).isEmpty()) { - plotsToDelete.remove(plot); - } - } - } - - public void confirmExpiry(final PlotPlayer pp) { - if (pp.getMeta("ignoreExpireTask") != null) { - return; - } - if (plotsToDelete != null && !plotsToDelete.isEmpty() && pp - .hasPermission("plots.admin.command.autoclear")) { - final int num = plotsToDelete.size(); - while (!plotsToDelete.isEmpty()) { - Iterator iter = plotsToDelete.iterator(); - final Plot current = iter.next(); - if (!isExpired(new ArrayDeque<>(tasks), current).isEmpty()) { - TaskManager.runTask(new Runnable() { - @Override public void run() { - pp.setMeta("ignoreExpireTask", true); - pp.teleport(current.getCenter()); - pp.deleteMeta("ignoreExpireTask"); - PlotMessage msg = new PlotMessage().text( - num + " " + (num > 1 ? "plots are" : "plot is") + " expired: ") - .color("$1").text(current.toString()).color("$2") - .suggest("/plot list expired").tooltip("/plot list expired") - //.text("\n - ").color("$3").text("Delete all (/plot delete expired)").color("$2").command("/plot delete expired") - .text("\n - ").color("$3").text("Delete this (/plot delete)") - .color("$2").suggest("/plot delete").tooltip("/plot delete") - .text("\n - ").color("$3").text("Remind later (/plot set keep 1d)") - .color("$2").suggest("/plot set keep 1d") - .tooltip("/plot set keep 1d").text("\n - ").color("$3") - .text("Keep this (/plot set keep true)").color("$2") - .suggest("/plot set keep true").tooltip("/plot set keep true") - .text("\n - ").color("$3").text("Don't show me this").color("$2") - .suggest("/plot toggle clear-confirmation") - .tooltip("/plot toggle clear-confirmation"); - msg.send(pp); - } - }); - return; - } else { - iter.remove(); - } - } - plotsToDelete.clear(); - } - } - - - public boolean cancelTask() { - if (this.running != 2) { - return false; - } - this.running = 1; - return true; - } - - public boolean runAutomatedTask() { - return runTask(new RunnableVal3() { - @Override public void run(Plot plot, Runnable runnable, Boolean confirm) { - if (confirm) { - if (plotsToDelete == null) { - plotsToDelete = new HashSet<>(); - } - plotsToDelete.add(plot); - runnable.run(); - } else { - deleteWithMessage(plot, runnable); - } - } - }); - } - - public Collection isExpired(ArrayDeque applicable, Plot plot) { - // Filter out invalid worlds - for (int i = 0; i < applicable.size(); i++) { - ExpiryTask et = applicable.poll(); - if (et.applies(plot.getArea())) { - applicable.add(et); - } - } - if (applicable.isEmpty()) { - return new ArrayList<>(); - } - boolean shouldCheckAccountAge = false; - - long diff = getAge(plot); - if (diff == 0) { - return new ArrayList<>(); - } - // Filter out non old plots - for (int i = 0; i < applicable.size(); i++) { - ExpiryTask et = applicable.poll(); - if (et.applies(diff)) { - applicable.add(et); - shouldCheckAccountAge |= et.getSettings().SKIP_ACCOUNT_AGE_DAYS != -1; - } - } - if (applicable.isEmpty()) { - return new ArrayList<>(); - } - // Check account age - if (shouldCheckAccountAge) { - long accountAge = getAge(plot); - for (int i = 0; i < applicable.size(); i++) { - ExpiryTask et = applicable.poll(); - if (et.appliesAccountAge(accountAge)) { - applicable.add(et); - } - } - if (applicable.isEmpty()) { - return new ArrayList<>(); - } - } - - // Run applicable non confirming tasks - for (int i = 0; i < applicable.size(); i++) { - ExpiryTask expiryTask = applicable.poll(); - if (!expiryTask.needsAnalysis() || plot.getArea().TYPE != 0) { - if (!expiryTask.requiresConfirmation()) { - return Collections.singletonList(expiryTask); - } - } - applicable.add(expiryTask); - } - // Run applicable confirming tasks - for (int i = 0; i < applicable.size(); i++) { - ExpiryTask expiryTask = applicable.poll(); - if (!expiryTask.needsAnalysis() || plot.getArea().TYPE != 0) { - return Collections.singletonList(expiryTask); - } - applicable.add(expiryTask); - } - return applicable; - } - - public ArrayDeque getTasks(PlotArea area) { - ArrayDeque queue = new ArrayDeque<>(tasks); - Iterator iter = queue.iterator(); - while (iter.hasNext()) { - if (!iter.next().applies(area)) { - iter.remove(); - } - } - return queue; - } - - public void passesComplexity(PlotAnalysis analysis, Collection applicable, - RunnableVal success, Runnable failure) { - if (analysis != null) { - // Run non confirming tasks - for (ExpiryTask et : applicable) { - if (!et.requiresConfirmation() && et.applies(analysis)) { - success.run(false); - return; - } - } - for (ExpiryTask et : applicable) { - if (et.applies(analysis)) { - success.run(true); - return; - } - } - failure.run(); - } - } - - public boolean runTask(final RunnableVal3 expiredTask) { - if (this.running != 0) { - return false; - } - this.running = 2; - final ConcurrentLinkedDeque plots = - new ConcurrentLinkedDeque(PlotSquared.get().getPlots()); - TaskManager.runTaskAsync(new Runnable() { - @Override public void run() { - final Runnable task = this; - if (ExpireManager.this.running != 2) { - ExpireManager.this.running = 0; - return; - } - long start = System.currentTimeMillis(); - while (!plots.isEmpty()) { - if (ExpireManager.this.running != 2) { - ExpireManager.this.running = 0; - return; - } - Plot plot = plots.poll(); - PlotArea area = plot.getArea(); - final Plot newPlot = area.getPlot(plot.getId()); - final ArrayDeque applicable = new ArrayDeque<>(tasks); - final Collection expired = isExpired(applicable, newPlot); - if (expired.isEmpty()) { - continue; - } - for (ExpiryTask expiryTask : expired) { - if (!expiryTask.needsAnalysis()) { - expiredTask.run(newPlot, new Runnable() { - @Override public void run() { - TaskManager.IMP.taskLaterAsync(task, 1); - } - }, expiryTask.requiresConfirmation()); - return; - } - } - final RunnableVal handleAnalysis = - new RunnableVal() { - @Override public void run(final PlotAnalysis changed) { - passesComplexity(changed, expired, new RunnableVal() { - @Override public void run(Boolean confirmation) { - expiredTask.run(newPlot, new Runnable() { - @Override public void run() { - TaskManager.IMP.taskLaterAsync(task, 1); - } - }, confirmation); - } - }, new Runnable() { - @Override public void run() { - FlagManager - .addPlotFlag(newPlot, Flags.ANALYSIS, changed.asList()); - TaskManager.runTaskLaterAsync(task, 20); - } - }); - } - }; - final Runnable doAnalysis = new Runnable() { - @Override public void run() { - HybridUtils.manager.analyzePlot(newPlot, handleAnalysis); - } - }; - - PlotAnalysis analysis = newPlot.getComplexity(null); - if (analysis != null) { - passesComplexity(analysis, expired, new RunnableVal() { - @Override public void run(Boolean value) { - doAnalysis.run(); - } - }, new Runnable() { - @Override public void run() { - TaskManager.IMP.taskLaterAsync(task, 1); - } - }); - } else { - doAnalysis.run(); - } - return; - } - if (plots.isEmpty()) { - ExpireManager.this.running = 3; - TaskManager.runTaskLater(new Runnable() { - @Override public void run() { - if (ExpireManager.this.running == 3) { - ExpireManager.this.running = 2; - runTask(expiredTask); - } - } - }, 86400000); - } else { - TaskManager.runTaskLaterAsync(task, 20 * 10); - } - } - }); - return true; - } - - public void storeDate(UUID uuid, long time) { - Long existing = this.dates_cache.put(uuid, time); - if (existing != null) { - long diff = time - existing; - if (diff > 0) { - Long account_age = this.account_age_cache.get(uuid); - if (account_age != null) - this.account_age_cache.put(uuid, account_age + diff); - } - } - } - - public void storeAccountAge(UUID uuid, long time) { - this.account_age_cache.put(uuid, time); - } - - public HashSet getPendingExpired() { - return plotsToDelete == null ? new HashSet() : plotsToDelete; - } - - public void deleteWithMessage(Plot plot, Runnable whenDone) { - if (plot.isMerged()) { - plot.unlinkPlot(true, false); - } - for (UUID helper : plot.getTrusted()) { - PlotPlayer player = UUIDHandler.getPlayer(helper); - if (player != null) { - MainUtil.sendMessage(player, C.PLOT_REMOVED_USER, plot.toString()); - } - } - for (UUID helper : plot.getMembers()) { - PlotPlayer player = UUIDHandler.getPlayer(helper); - if (player != null) { - MainUtil.sendMessage(player, C.PLOT_REMOVED_USER, plot.toString()); - } - } - Set plots = plot.getConnectedPlots(); - plot.deletePlot(whenDone); - PlotAnalysis changed = plot.getComplexity(null); - int changes = changed == null ? 0 : changed.changes_sd; - int modified = changed == null ? 0 : changed.changes; - PlotSquared.debug( - "$2[&5Expire&dManager$2] &cDeleted expired plot: " + plot + " User:" + plot.owner - + " Delta:" + changes + "/" + modified + " Connected: " + StringMan - .getString(plots)); - PlotSquared.debug("$4 - Area: " + plot.getArea()); - if (plot.hasOwner()) { - PlotSquared.debug("$4 - Owner: " + UUIDHandler.getName(plot.owner)); + if (plotsToDelete != null && !plotsToDelete.isEmpty() && pp + .hasPermission("plots.admin.command.autoclear")) { + final int num = plotsToDelete.size(); + while (!plotsToDelete.isEmpty()) { + Iterator iter = plotsToDelete.iterator(); + final Plot current = iter.next(); + if (!isExpired(new ArrayDeque<>(tasks), current).isEmpty()) { + TaskManager.runTask(() -> { + pp.setMeta("ignoreExpireTask", true); + pp.teleport(current.getCenter()); + pp.deleteMeta("ignoreExpireTask"); + PlotMessage msg = new PlotMessage().text( + num + " " + (num > 1 ? "plots are" : "plot is") + " expired: ") + .color("$1").text(current.toString()).color("$2") + .suggest("/plot list expired").tooltip("/plot list expired") + //.text("\n - ").color("$3").text("Delete all (/plot delete expired)").color("$2").command("/plot delete expired") + .text("\n - ").color("$3").text("Delete this (/plot delete)") + .color("$2").suggest("/plot delete").tooltip("/plot delete") + .text("\n - ").color("$3").text("Remind later (/plot set keep 1d)") + .color("$2").suggest("/plot set keep 1d") + .tooltip("/plot set keep 1d").text("\n - ").color("$3") + .text("Keep this (/plot set keep true)").color("$2") + .suggest("/plot set keep true").tooltip("/plot set keep true") + .text("\n - ").color("$3").text("Don't show me this").color("$2") + .suggest("/plot toggle clear-confirmation") + .tooltip("/plot toggle clear-confirmation"); + msg.send(pp); + }); + return; } else { - PlotSquared.debug("$4 - Owner: Unowned"); + iter.remove(); } + } + plotsToDelete.clear(); + } + } + + + public boolean cancelTask() { + if (this.running != 2) { + return false; + } + this.running = 1; + return true; + } + + public boolean runAutomatedTask() { + return runTask(new RunnableVal3() { + @Override + public void run(Plot plot, Runnable runnable, Boolean confirm) { + if (confirm) { + if (plotsToDelete == null) { + plotsToDelete = new HashSet<>(); + } + plotsToDelete.add(plot); + runnable.run(); + } else { + deleteWithMessage(plot, runnable); + } + } + }); + } + + public Collection isExpired(ArrayDeque applicable, Plot plot) { + // Filter out invalid worlds + for (int i = 0; i < applicable.size(); i++) { + ExpiryTask et = applicable.poll(); + if (et.applies(plot.getArea())) { + applicable.add(et); + } + } + if (applicable.isEmpty()) { + return new ArrayList<>(); + } + boolean shouldCheckAccountAge = false; + + long diff = getAge(plot); + if (diff == 0) { + return new ArrayList<>(); + } + // Filter out non old plots + for (int i = 0; i < applicable.size(); i++) { + ExpiryTask et = applicable.poll(); + if (et.applies(diff)) { + applicable.add(et); + shouldCheckAccountAge |= et.getSettings().SKIP_ACCOUNT_AGE_DAYS != -1; + } + } + if (applicable.isEmpty()) { + return new ArrayList<>(); + } + // Check account age + if (shouldCheckAccountAge) { + long accountAge = getAge(plot); + for (int i = 0; i < applicable.size(); i++) { + ExpiryTask et = applicable.poll(); + if (et.appliesAccountAge(accountAge)) { + applicable.add(et); + } + } + if (applicable.isEmpty()) { + return new ArrayList<>(); + } } - public long getAge(UUID uuid) { - if (UUIDHandler.getPlayer(uuid) != null) { - return 0; + // Run applicable non confirming tasks + for (int i = 0; i < applicable.size(); i++) { + ExpiryTask expiryTask = applicable.poll(); + if (!expiryTask.needsAnalysis() || plot.getArea().TYPE != 0) { + if (!expiryTask.requiresConfirmation()) { + return Collections.singletonList(expiryTask); } - String name = UUIDHandler.getName(uuid); - if (name != null) { - Long last = this.dates_cache.get(uuid); - if (last == null) { - OfflinePlotPlayer opp; - if (Settings.UUID.NATIVE_UUID_PROVIDER) { - opp = UUIDHandler.getUUIDWrapper().getOfflinePlayer(uuid); - } else { - opp = UUIDHandler.getUUIDWrapper().getOfflinePlayer(name); - } - if (opp != null && (last = opp.getLastPlayed()) != 0) { - this.dates_cache.put(uuid, last); - } else { - return 0; - } - } - if (last == 0) { - return 0; - } - return System.currentTimeMillis() - last; + } + applicable.add(expiryTask); + } + // Run applicable confirming tasks + for (int i = 0; i < applicable.size(); i++) { + ExpiryTask expiryTask = applicable.poll(); + if (!expiryTask.needsAnalysis() || plot.getArea().TYPE != 0) { + return Collections.singletonList(expiryTask); + } + applicable.add(expiryTask); + } + return applicable; + } + + public ArrayDeque getTasks(PlotArea area) { + ArrayDeque queue = new ArrayDeque<>(tasks); + queue.removeIf(expiryTask -> !expiryTask.applies(area)); + return queue; + } + + public void passesComplexity(PlotAnalysis analysis, Collection applicable, + RunnableVal success, Runnable failure) { + if (analysis != null) { + // Run non confirming tasks + for (ExpiryTask et : applicable) { + if (!et.requiresConfirmation() && et.applies(analysis)) { + success.run(false); + return; } + } + for (ExpiryTask et : applicable) { + if (et.applies(analysis)) { + success.run(true); + return; + } + } + failure.run(); + } + } + + public boolean runTask(final RunnableVal3 expiredTask) { + if (this.running != 0) { + return false; + } + this.running = 2; + final ConcurrentLinkedDeque plots = + new ConcurrentLinkedDeque<>(PlotSquared.get().getPlots()); + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + final Runnable task = this; + if (ExpireManager.this.running != 2) { + ExpireManager.this.running = 0; + return; + } + long start = System.currentTimeMillis(); + while (!plots.isEmpty()) { + if (ExpireManager.this.running != 2) { + ExpireManager.this.running = 0; + return; + } + Plot plot = plots.poll(); + PlotArea area = plot.getArea(); + final Plot newPlot = area.getPlot(plot.getId()); + final ArrayDeque applicable = new ArrayDeque<>(tasks); + final Collection expired = isExpired(applicable, newPlot); + if (expired.isEmpty()) { + continue; + } + for (ExpiryTask expiryTask : expired) { + if (!expiryTask.needsAnalysis()) { + expiredTask.run(newPlot, () -> TaskManager.IMP.taskLaterAsync(task, 1), + expiryTask.requiresConfirmation()); + return; + } + } + final RunnableVal handleAnalysis = + new RunnableVal() { + @Override + public void run(final PlotAnalysis changed) { + passesComplexity(changed, expired, new RunnableVal() { + @Override + public void run(Boolean confirmation) { + expiredTask.run(newPlot, + () -> TaskManager.IMP.taskLaterAsync(task, 1), confirmation); + } + }, () -> { + FlagManager + .addPlotFlag(newPlot, Flags.ANALYSIS, changed.asList()); + TaskManager.runTaskLaterAsync(task, 20); + }); + } + }; + final Runnable doAnalysis = () -> HybridUtils.manager + .analyzePlot(newPlot, handleAnalysis); + + PlotAnalysis analysis = newPlot.getComplexity(null); + if (analysis != null) { + passesComplexity(analysis, expired, new RunnableVal() { + @Override + public void run(Boolean value) { + doAnalysis.run(); + } + }, () -> TaskManager.IMP.taskLaterAsync(task, 1)); + } else { + doAnalysis.run(); + } + return; + } + if (plots.isEmpty()) { + ExpireManager.this.running = 3; + TaskManager.runTaskLater(() -> { + if (ExpireManager.this.running == 3) { + ExpireManager.this.running = 2; + runTask(expiredTask); + } + }, 86400000); + } else { + TaskManager.runTaskLaterAsync(task, 20 * 10); + } + } + }); + return true; + } + + public void storeDate(UUID uuid, long time) { + Long existing = this.dates_cache.put(uuid, time); + if (existing != null) { + long diff = time - existing; + if (diff > 0) { + Long account_age = this.account_age_cache.get(uuid); + if (account_age != null) { + this.account_age_cache.put(uuid, account_age + diff); + } + } + } + } + + public void storeAccountAge(UUID uuid, long time) { + this.account_age_cache.put(uuid, time); + } + + public HashSet getPendingExpired() { + return plotsToDelete == null ? new HashSet<>() : plotsToDelete; + } + + public void deleteWithMessage(Plot plot, Runnable whenDone) { + if (plot.isMerged()) { + plot.unlinkPlot(true, false); + } + for (UUID helper : plot.getTrusted()) { + PlotPlayer player = UUIDHandler.getPlayer(helper); + if (player != null) { + MainUtil.sendMessage(player, C.PLOT_REMOVED_USER, plot.toString()); + } + } + for (UUID helper : plot.getMembers()) { + PlotPlayer player = UUIDHandler.getPlayer(helper); + if (player != null) { + MainUtil.sendMessage(player, C.PLOT_REMOVED_USER, plot.toString()); + } + } + Set plots = plot.getConnectedPlots(); + plot.deletePlot(whenDone); + PlotAnalysis changed = plot.getComplexity(null); + int changes = changed == null ? 0 : changed.changes_sd; + int modified = changed == null ? 0 : changed.changes; + PlotSquared.debug( + "$2[&5Expire&dManager$2] &cDeleted expired plot: " + plot + " User:" + plot.owner + + " Delta:" + changes + "/" + modified + " Connected: " + StringMan + .getString(plots)); + PlotSquared.debug("$4 - Area: " + plot.getArea()); + if (plot.hasOwner()) { + PlotSquared.debug("$4 - Owner: " + UUIDHandler.getName(plot.owner)); + } else { + PlotSquared.debug("$4 - Owner: Unowned"); + } + } + + public long getAge(UUID uuid) { + if (UUIDHandler.getPlayer(uuid) != null) { + return 0; + } + String name = UUIDHandler.getName(uuid); + if (name != null) { + Long last = this.dates_cache.get(uuid); + if (last == null) { + OfflinePlotPlayer opp; + if (Settings.UUID.NATIVE_UUID_PROVIDER) { + opp = UUIDHandler.getUUIDWrapper().getOfflinePlayer(uuid); + } else { + opp = UUIDHandler.getUUIDWrapper().getOfflinePlayer(name); + } + if (opp != null && (last = opp.getLastPlayed()) != 0) { + this.dates_cache.put(uuid, last); + } else { + return 0; + } + } + if (last == 0) { return 0; + } + return System.currentTimeMillis() - last; } + return 0; + } - public long getAccountAge(Plot plot) { - if (!plot.hasOwner() || Objects.equals(DBFunc.EVERYONE, plot.owner) - || UUIDHandler.getPlayer(plot.owner) != null || plot.getRunning() > 0) { - return Long.MAX_VALUE; - } - long max = 0; - for (UUID owner : plot.getOwners()) { - long age = getAccountAge(owner); - max = Math.max(age, max); - } - return max; + public long getAccountAge(Plot plot) { + if (!plot.hasOwner() || Objects.equals(DBFunc.EVERYONE, plot.owner) + || UUIDHandler.getPlayer(plot.owner) != null || plot.getRunning() > 0) { + return Long.MAX_VALUE; } + long max = 0; + for (UUID owner : plot.getOwners()) { + long age = getAccountAge(owner); + max = Math.max(age, max); + } + return max; + } - public long getAge(Plot plot) { - if (!plot.hasOwner() || Objects.equals(DBFunc.EVERYONE, plot.owner) - || UUIDHandler.getPlayer(plot.owner) != null || plot.getRunning() > 0) { - return 0; - } - Optional keep = plot.getFlag(Flags.KEEP); - if (keep.isPresent()) { - Object value = keep.get(); - if (value instanceof Boolean) { - if (Boolean.TRUE.equals(value)) { - return 0; - } - } else if (value instanceof Long) { - if ((Long) value > System.currentTimeMillis()) { - return 0; - } - } else { // Invalid? - return 0; - } - } - long min = Long.MAX_VALUE; - for (UUID owner : plot.getOwners()) { - long age = getAge(owner); - if (age < min) { - min = age; - } - } - return min; + public long getAge(Plot plot) { + if (!plot.hasOwner() || Objects.equals(DBFunc.EVERYONE, plot.owner) + || UUIDHandler.getPlayer(plot.owner) != null || plot.getRunning() > 0) { + return 0; } + Optional keep = plot.getFlag(Flags.KEEP); + if (keep.isPresent()) { + Object value = keep.get(); + if (value instanceof Boolean) { + if (Boolean.TRUE.equals(value)) { + return 0; + } + } else if (value instanceof Long) { + if ((Long) value > System.currentTimeMillis()) { + return 0; + } + } else { // Invalid? + return 0; + } + } + long min = Long.MAX_VALUE; + for (UUID owner : plot.getOwners()) { + long age = getAge(owner); + if (age < min) { + min = age; + } + } + return min; + } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpiryTask.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpiryTask.java index df1244a12..3a0b82c56 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpiryTask.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/ExpiryTask.java @@ -5,7 +5,6 @@ import com.github.intellectualsites.plotsquared.plot.config.Settings; import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.PlotArea; import com.github.intellectualsites.plotsquared.plot.object.PlotFilter; - import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/PlotAnalysis.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/PlotAnalysis.java index b17f3ce47..f11cb429a 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/PlotAnalysis.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/util/expiry/PlotAnalysis.java @@ -118,16 +118,14 @@ public class PlotAnalysis { final AtomicInteger mi = new AtomicInteger(0); - Thread ratingAnalysis = new Thread(new Runnable() { - @Override public void run() { - for (; mi.intValue() < plots.size(); mi.incrementAndGet()) { - int i = mi.intValue(); - Plot plot = plots.get(i); - ratings[i] = (int) ( - (plot.getAverageRating() + plot.getSettings().getRatings().size()) - * 100); - PlotSquared.debug(" | " + plot + " (rating) " + ratings[i]); - } + Thread ratingAnalysis = new Thread(() -> { + for (; mi.intValue() < plots.size(); mi.incrementAndGet()) { + int i = mi.intValue(); + Plot plot = plots.get(i); + ratings[i] = (int) ( + (plot.getAverageRating() + plot.getSettings().getRatings().size()) + * 100); + PlotSquared.debug(" | " + plot + " (rating) " + ratings[i]); } }); ratingAnalysis.start(); @@ -424,9 +422,6 @@ public class PlotAnalysis { /** * A simple array squaring algorithm. * - Used for calculating the variance - * - * @param array - * @return */ public static int[] square(int[] array) { array = array.clone(); @@ -439,8 +434,6 @@ public class PlotAnalysis { /** * An optimized lossy standard deviation algorithm. * - * @param ranks - * @return */ public static int[] getSD(int[]... ranks) { if (ranks.length == 0) { @@ -468,19 +461,13 @@ public class PlotAnalysis { * - Input is an array of int with a max size of 102400
* - A reduced sample space allows for sorting (and ranking in this case) in linear time * - * @param input - * @param input - * @return */ public static int[] rank(int[] input) { return rank(input, 102400); } /** - * An optimized algorithm for ranking a very specific set of inputs - * - * @param input - * @return + * An optimized algorithm for ranking a very specific set of inputs. */ public static int[] rank(int[] input, int size) { int[] cache = new int[size]; diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/uuid/UUIDWrapper.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/uuid/UUIDWrapper.java index 235b51a34..55f3697f7 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/uuid/UUIDWrapper.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/uuid/UUIDWrapper.java @@ -5,17 +5,17 @@ import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import java.util.UUID; -public abstract class UUIDWrapper { +public interface UUIDWrapper { - public abstract UUID getUUID(PlotPlayer player); + UUID getUUID(PlotPlayer player); - public abstract UUID getUUID(OfflinePlotPlayer player); + UUID getUUID(OfflinePlotPlayer player); - public abstract UUID getUUID(String name); + UUID getUUID(String name); - public abstract OfflinePlotPlayer getOfflinePlayer(UUID uuid); + OfflinePlotPlayer getOfflinePlayer(UUID uuid); - public abstract OfflinePlotPlayer getOfflinePlayer(String name); + OfflinePlotPlayer getOfflinePlayer(String name); - public abstract OfflinePlotPlayer[] getOfflinePlayers(); + OfflinePlotPlayer[] getOfflinePlayers(); } diff --git a/Core/src/test/java/com/github/intellectualsites/plotsquared/plot/database/AbstractDBTest.java b/Core/src/test/java/com/github/intellectualsites/plotsquared/plot/database/AbstractDBTest.java index 7b29cdf97..cf118c717 100644 --- a/Core/src/test/java/com/github/intellectualsites/plotsquared/plot/database/AbstractDBTest.java +++ b/Core/src/test/java/com/github/intellectualsites/plotsquared/plot/database/AbstractDBTest.java @@ -84,10 +84,7 @@ public class AbstractDBTest implements AbstractDB { @Override public void setFlags(Plot plot, HashMap, Object> flags) { } - @Override public void setFlags(PlotCluster cluster, HashMap, Object> flags) { - } - - @Override public void setClusterName(PlotCluster cluster, String name) { + @Override public void setClusterName(PlotCluster cluster, String name) { } @Override public void setAlias(Plot plot, String alias) { diff --git a/Core/src/test/java/com/github/intellectualsites/plotsquared/plot/util/EventUtilTest.java b/Core/src/test/java/com/github/intellectualsites/plotsquared/plot/util/EventUtilTest.java index 011fbb7f3..f6550ce98 100644 --- a/Core/src/test/java/com/github/intellectualsites/plotsquared/plot/util/EventUtilTest.java +++ b/Core/src/test/java/com/github/intellectualsites/plotsquared/plot/util/EventUtilTest.java @@ -40,11 +40,7 @@ public class EventUtilTest extends EventUtil { return true; } - @Override public boolean callFlagRemove(Flag flag, Object value, PlotCluster cluster) { - return true; - } - - @Override public boolean callMerge(Plot plot, int dir, int max){ + @Override public boolean callMerge(Plot plot, int dir, int max){ return false; }