diff --git a/pom.xml b/pom.xml index f5a726c09..c0b25acae 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ UTF-8 PlotSquared - 3.2.3 + 3.2.4 PlotSquared jar diff --git a/src/main/java/com/intellectualcrafters/plot/commands/GenerateDocs.java b/src/main/java/com/intellectualcrafters/plot/commands/GenerateDocs.java index 30e56feaa..d24a573bb 100644 --- a/src/main/java/com/intellectualcrafters/plot/commands/GenerateDocs.java +++ b/src/main/java/com/intellectualcrafters/plot/commands/GenerateDocs.java @@ -4,12 +4,16 @@ import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.object.PlotPlayer; +import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.StringMan; import com.plotsquared.general.commands.Command; @@ -91,10 +95,35 @@ public class GenerateDocs { } public static List getPerms(final String cmd, final List lines) { - final ArrayList perms = new ArrayList(); + final HashSet perms = new HashSet(); final Pattern p = Pattern.compile("\"([^\"]*)\""); + final Pattern p2 = Pattern.compile("C.PERMISSION_\\s*(\\w+)"); + String last = null; for (final String line : lines) { + + Matcher m2 = p2.matcher(line); + while (m2.find()) { + perms.add(C.valueOf("PERMISSION_" + m2.group(1)).s()); + } + if (line.contains("Permissions.hasPermission(")) { + String[] split = line.split("Permissions.hasPermission"); + split = Arrays.copyOfRange(split, 1, split.length); + for (String method : split) { + String perm = method.split("[,|)]")[1].trim(); + if (!perm.toLowerCase().equals(perm)) { + if (perm.startsWith("C.")) { + perm = C.valueOf(perm.split("\\.")[1]).s(); + } + else { + continue; + } + } + else { + perm = perm.substring(1, perm.length() - 1); + } + perms.add(perm); + } final Matcher m = p.matcher(line); while (m.find()) { String perm = m.group(1); @@ -102,21 +131,42 @@ public class GenerateDocs { perm += ""; } if (perm.startsWith(".")) { - perms.set(perms.size() - 1, perms.get(perms.size() - 1) + perm); + perms.remove(last); + perms.add(last + perm); } else if (perm.contains(".")) { + last = perm; perms.add(perm); } } } + else if (line.contains("Permissions.hasPermissionRange")) { + String[] split = line.split("Permissions.hasPermissionRange"); + split = Arrays.copyOfRange(split, 1, split.length); + for (String method : split) { + String perm = method.split("[,|)]")[1].trim(); + if (!perm.toLowerCase().equals(perm)) { + if (perm.startsWith("C.")) { + perm = C.valueOf(perm.split("\\.")[1]).s(); + } + else { + continue; + } + } + else { + perm = perm.substring(1, perm.length() - 1); + } + perms.add(perm + ".<#>"); + } + } } switch (cmd.toLowerCase()) { case "auto": case "claim": { - perms.add("plots.plot.#"); + perms.add("plots.plot.<#>"); break; } } - return perms; + return new ArrayList<>(perms); } public static String getComments(final List lines) { diff --git a/src/main/java/com/intellectualcrafters/plot/commands/Merge.java b/src/main/java/com/intellectualcrafters/plot/commands/Merge.java index b2556e782..2f7173792 100644 --- a/src/main/java/com/intellectualcrafters/plot/commands/Merge.java +++ b/src/main/java/com/intellectualcrafters/plot/commands/Merge.java @@ -86,10 +86,15 @@ public class Merge extends SubCommand { MainUtil.sendMessage(plr, C.PLOT_UNOWNED); return false; } - final boolean admin = Permissions.hasPermission(plr, "plots.admin.command.merge"); - if (!plot.isOwner(plr.getUUID()) && !admin) { - MainUtil.sendMessage(plr, C.NO_PLOT_PERMS); - return false; + UUID uuid = plr.getUUID(); + if (!plot.isOwner(uuid)) { + if (!Permissions.hasPermission(plr, "plots.admin.command.merge")) { + MainUtil.sendMessage(plr, C.NO_PLOT_PERMS); + return false; + } + else { + uuid = plot.owner; + } } final PlotWorld plotworld = PS.get().getPlotWorld(plot.world); if ((EconHandler.manager != null) && plotworld.USE_ECONOMY && plotworld.MERGE_PRICE > 0d && EconHandler.manager.getMoney(plr) < plotworld.MERGE_PRICE) { @@ -98,8 +103,8 @@ public class Merge extends SubCommand { } int direction = -1; final int size = plot.getConnectedPlots().size(); - final int maxSize = Permissions.hasPermissionRange(plr, "plots.merge", Settings.MAX_PLOTS); - if (size >= maxSize) { + final int maxSize = Permissions.hasPermissionRange(plr, "plots.merge", Settings.MAX_PLOTS); + if (size - 1> maxSize) { MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.merge." + (size + 1)); return false; } @@ -120,7 +125,7 @@ public class Merge extends SubCommand { // } } else { if (args[0].equalsIgnoreCase("all") || args[0].equalsIgnoreCase("auto")) { - if (MainUtil.autoMerge(plot, -1, maxSize - size, plr.getUUID(), (args.length != 2) || !args[1].equalsIgnoreCase("false"))) { + if (MainUtil.autoMerge(plot, -1, maxSize - size, uuid, (args.length != 2) || !args[1].equalsIgnoreCase("false"))) { if ((EconHandler.manager != null) && plotworld.USE_ECONOMY && plotworld.MERGE_PRICE > 0d) { EconHandler.manager.withdrawMoney(plr, plotworld.MERGE_PRICE); sendMessage(plr, C.REMOVED_BALANCE, plotworld.MERGE_PRICE + ""); @@ -144,7 +149,7 @@ public class Merge extends SubCommand { MainUtil.sendMessage(plr, C.DIRECTION.s().replaceAll("%dir%", direction(loc.getYaw()))); return false; } - if (MainUtil.autoMerge(plot, direction, maxSize - size, plot.owner, (args.length != 2) || !args[1].equalsIgnoreCase("false"))) { + if (MainUtil.autoMerge(plot, direction, maxSize - size, uuid, (args.length != 2) || !args[1].equalsIgnoreCase("false"))) { if ((EconHandler.manager != null) && plotworld.USE_ECONOMY && plotworld.MERGE_PRICE > 0d) { EconHandler.manager.withdrawMoney(plr, plotworld.MERGE_PRICE); sendMessage(plr, C.REMOVED_BALANCE, plotworld.MERGE_PRICE + ""); @@ -153,7 +158,7 @@ public class Merge extends SubCommand { return true; } Plot adjacent = MainUtil.getPlotAbs(plot.world, MainUtil.getPlotIdRelative(plot.id, direction)); - if (adjacent == null || !adjacent.hasOwner() || adjacent.getMerged((direction + 2) % 4)) { + if (adjacent == null || !adjacent.hasOwner() || adjacent.getMerged((direction + 2) % 4) || adjacent.isOwner(uuid)) { MainUtil.sendMessage(plr, C.NO_AVAILABLE_AUTOMERGE); return false; } @@ -163,8 +168,8 @@ public class Merge extends SubCommand { } HashSet uuids = adjacent.getOwners(); boolean isOnline = false; - for (final UUID uuid : uuids) { - final PlotPlayer accepter = UUIDHandler.getPlayer(uuid); + for (final UUID owner : uuids) { + final PlotPlayer accepter = UUIDHandler.getPlayer(owner); if (accepter == null) { continue; } @@ -174,7 +179,7 @@ public class Merge extends SubCommand { @Override public void run() { MainUtil.sendMessage(accepter, C.MERGE_ACCEPTED); - MainUtil.autoMerge(plot, dir, maxSize - size, uuid, true); + MainUtil.autoMerge(plot, dir, maxSize - size, owner, true); final PlotPlayer pp = UUIDHandler.getPlayer(plr.getUUID()); if (pp == null) { sendMessage(accepter, C.MERGE_NOT_VALID); diff --git a/src/main/java/com/intellectualcrafters/plot/commands/Toggle.java b/src/main/java/com/intellectualcrafters/plot/commands/Toggle.java index cc763dcb4..a63381f28 100644 --- a/src/main/java/com/intellectualcrafters/plot/commands/Toggle.java +++ b/src/main/java/com/intellectualcrafters/plot/commands/Toggle.java @@ -97,7 +97,7 @@ public class Toggle extends SubCommand { return true; } }); - if (PS.get().worldedit != null) { + if (PS.get() != null && PS.get().worldedit != null) { toggles.put("worldedit", new Command("worldedit", "/plot toggle worldedit", "Toggle worldedit bypass", C.PERMISSION_WORLDEDIT_BYPASS.s()) { @Override diff --git a/src/main/java/com/intellectualcrafters/plot/commands/Visit.java b/src/main/java/com/intellectualcrafters/plot/commands/Visit.java index 99ec231d2..884f634e4 100644 --- a/src/main/java/com/intellectualcrafters/plot/commands/Visit.java +++ b/src/main/java/com/intellectualcrafters/plot/commands/Visit.java @@ -21,6 +21,7 @@ package com.intellectualcrafters.plot.commands; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; @@ -44,7 +45,7 @@ import com.plotsquared.general.commands.CommandDeclaration; command = "visit", permission = "plots.visit", description = "Visit someones plot", -usage = "/plot visit [#]", +usage = "/plot visit [#]", aliases = { "v" }, requiredType = RequiredType.NONE, category = CommandCategory.TELEPORT) @@ -94,8 +95,7 @@ public class Visit extends SubCommand { } else { final Plot plot = MainUtil.getPlotFromString(player, args[0], true); if (plot != null) { - unsorted = new HashSet<>(); - unsorted.add(plot); + unsorted = new HashSet<>(Arrays.asList(plot.getBasePlot(false))); } } break; diff --git a/src/main/java/com/intellectualcrafters/plot/config/C.java b/src/main/java/com/intellectualcrafters/plot/config/C.java index 5ea8a5ce0..61315b6a4 100644 --- a/src/main/java/com/intellectualcrafters/plot/config/C.java +++ b/src/main/java/com/intellectualcrafters/plot/config/C.java @@ -339,7 +339,7 @@ public enum C { MERGE_REQUESTED("$2Successfully sent a merge request", "Merge"), MERGE_REQUEST_CONFIRM("merge request from %s", "Permission"), NO_PERM_MERGE("$2You are not the owner of the plot: $1%plot%", "Merge"), - NO_AVAILABLE_AUTOMERGE("$2You do not own any adjacent plots in the specified direction.", "Merge"), + NO_AVAILABLE_AUTOMERGE("$2You do not own any adjacent plots in the specified direction or are not allowed to merge to the required size.", "Merge"), UNLINK_REQUIRED("$2An unlink is required to do this.", "Merge"), UNLINK_IMPOSSIBLE("$2You can only unlink a mega-plot", "Merge"), UNLINK_SUCCESS("$2Successfully unlinked plots.", "Merge"), diff --git a/src/main/java/com/intellectualcrafters/plot/object/Plot.java b/src/main/java/com/intellectualcrafters/plot/object/Plot.java index 05433ca8e..003c131f3 100644 --- a/src/main/java/com/intellectualcrafters/plot/object/Plot.java +++ b/src/main/java/com/intellectualcrafters/plot/object/Plot.java @@ -429,25 +429,21 @@ public class Plot { */ public Plot getBasePlot(boolean recalculate) { if ((origin != null && !recalculate)) { - return origin; + if (this.equals(origin)) { + return this; + } + return origin.getBasePlot(false); } if (!isMerged()) { origin = this; return origin; } - int min = Integer.MAX_VALUE; + origin = this; + PlotId min = id; for (Plot plot : MainUtil.getConnectedPlots(this)) { - if (plot.temp != -1) { - if (plot.temp < min) { - min = plot.temp; - origin = plot; - } - } - else { - if (plot.hashCode() < min) { - origin = plot; - min = plot.hashCode(); - } + if (plot.id.y < min.y || (plot.id.y == min.y && plot.id.x < min.x)) { + origin = plot; + min = plot.id; } } for (Plot plot : MainUtil.getConnectedPlots(this)) { @@ -772,15 +768,17 @@ public class Plot { * @param alias */ public void setAlias(String alias) { - final String name = getSettings().getAlias(); - if (alias == null) { - alias = ""; + for (Plot current : getConnectedPlots()) { + final String name = getSettings().getAlias(); + if (alias == null) { + alias = ""; + } + if (name.equals(alias)) { + return; + } + current.getSettings().setAlias(alias); + DBFunc.setAlias(current, alias); } - if (name.equals(alias)) { - return; - } - getSettings().setAlias(alias); - DBFunc.setAlias(this, alias); } /** @@ -1120,6 +1118,9 @@ public class Plot { } public String getAlias() { + if (settings == null) { + return ""; + } return getSettings().getAlias(); } @@ -1134,7 +1135,10 @@ public class Plot { DBFunc.setMerged(this, merged); MainUtil.connected_cache = null; MainUtil.regions_cache = null; - origin = null; + if (origin != null) { + origin.origin = null; + origin = null; + } } /** @@ -1145,10 +1149,25 @@ public class Plot { */ public void setMerged(int direction, boolean value) { if (getSettings().setMerged(direction, value)) { + if (value) { + Plot other = MainUtil.getPlotRelative(this, direction).getBasePlot(false); + if (!other.equals(getBasePlot(false))) { + Plot base = ((other.id.y < id.y) || ((other.id.y == id.y) && (other.id.x < id.x))) ? other : origin; + origin.origin = base; + other.origin = base; + origin = base; + MainUtil.connected_cache = null; + } + } + else { + if (origin != null) { + origin.origin = null; + origin = null; + } + MainUtil.connected_cache = null; + } DBFunc.setMerged(this, getSettings().getMerged()); - MainUtil.connected_cache = null; MainUtil.regions_cache = null; - origin = null; } } diff --git a/src/main/java/com/intellectualcrafters/plot/object/PlotSettings.java b/src/main/java/com/intellectualcrafters/plot/object/PlotSettings.java index 533329c89..b0270a8cd 100644 --- a/src/main/java/com/intellectualcrafters/plot/object/PlotSettings.java +++ b/src/main/java/com/intellectualcrafters/plot/object/PlotSettings.java @@ -111,7 +111,10 @@ public class PlotSettings { return position; } - public void setPosition(final BlockLoc position) { + public void setPosition(BlockLoc position) { + if (position != null && position.x == 0 && position.y == 0 && position.z == 0) { + position = null; + } this.position = position; } diff --git a/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java b/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java index 343f0f3d0..7f180d18d 100644 --- a/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java +++ b/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java @@ -424,7 +424,7 @@ public class MainUtil { } for (final Plot p : PS.get().getPlotsInWorld(worldname)) { final String name = p.getAlias(); - if ((name.length() != 0) && name.equalsIgnoreCase(arg)) { + if ((name.length() != 0) && StringMan.isEqualIgnoreCase(name, arg)) { return p; } } @@ -631,22 +631,24 @@ public class MainUtil { final PlotManager manager = PS.get().getPlotManager(plot.world); final int x; final int z; - Location bot = plot.getBottomAbs(); if ((plotworld.DEFAULT_HOME.x == Integer.MAX_VALUE) && (plotworld.DEFAULT_HOME.z == Integer.MAX_VALUE)) { - Location top = plot.getTopAbs(); - x = ((top.getX() - bot.getX()) / 2) + bot.getX(); - z = ((top.getZ() - bot.getZ()) / 2) + bot.getZ(); + // center + RegionWrapper largest = getLargestRegion(plot); + x = ((largest.maxX - largest.minX) / 2) + largest.minX; + z = ((largest.maxZ - largest.minZ) / 2) + largest.minZ; } else { + // specific + Location bot = plot.getBottomAbs(); x = bot.getX() + plotworld.DEFAULT_HOME.x; z = bot.getZ() + plotworld.DEFAULT_HOME.z; } final int y = Math.max(getHeighestBlock(plot.world, x, z), manager.getSignLoc(PS.get().getPlotWorld(plot.world), plot).getY()); return new Location(plot.world, x, y + 1, z); } - Location bot = plot.getBottomAbs(); - Location top = plot.getTopAbs(); - final int x = ((top.getX() - bot.getX()) / 2) + bot.getX(); - final int z = bot.getZ() - 1; + // Side + RegionWrapper largest = getLargestRegion(plot); + final int x = ((largest.maxX - largest.minX) / 2) + largest.minX; + final int z = largest.minZ - 1; final PlotManager manager = PS.get().getPlotManager(plot.world); final int y = Math.max(getHeighestBlock(plot.world, x, z), manager.getSignLoc(PS.get().getPlotWorld(plot.world), plot).getY()); return new Location(plot.world, x, y + 1, z); @@ -770,6 +772,18 @@ public class MainUtil { return id; } + /** + * direction 0 = north, 1 = south, etc: + * + * @param id + * @param direction + * + * @return Plot relative + */ + public static Plot getPlotRelative(final Plot plot, final int direction) { + return getPlotAbs(plot.world, getPlotIdRelative(plot.id, direction)); + } + /** * Get a list of plot ids within a selection * @param pos1 @@ -1019,13 +1033,18 @@ public class MainUtil { a.setFlags(net); b.setFlags(net); } + if (a.getAlias().length() > 0) { + b.setAlias(a.getAlias()); + } + else if (b.getAlias().length() > 0) { + a.setAlias(b.getAlias()); + } for (UUID uuid : a.getTrusted()) { b.addTrusted(uuid); } for (UUID uuid : b.getTrusted()) { a.addTrusted(uuid); } - for (UUID uuid : a.getMembers()) { b.addMember(uuid); } @@ -1174,62 +1193,58 @@ public class MainUtil { } HashSet visited = new HashSet<>(); HashSet merged = new HashSet<>(); + for (Plot current : getConnectedPlots(plot)) { + merged.add(current.id); + } ArrayDeque frontier = new ArrayDeque<>(getConnectedPlots(plot)); Plot current; boolean toReturn = false; - while ((current = frontier.poll()) != null && max > 0) { + Set plots; + while ((current = frontier.poll()) != null && max >= 0) { if (visited.contains(current)) { continue; } visited.add(current); - if (max > 0 && (dir == -1 || dir == 0) && !current.getMerged(0)) { - Plot other = getPlotAbs(current.world, getPlotIdRelative(current.id, 0)); - if (other.isOwner(uuid)) { - frontier.addAll(other.getConnectedPlots()); + if (max >= 0 && (dir == -1 || dir == 0) && !current.getMerged(0)) { + Plot other = getPlotRelative(current, 0); + if (other.isOwner(uuid) && (other.getBasePlot(false).equals(current.getBasePlot(false)) || ((plots = other.getConnectedPlots()).size() <= max && frontier.addAll(plots) && (max -= plots.size()) != -1))) { mergePlot(current.world, current, other, removeRoads); merged.add(current.id); merged.add(other.id); toReturn = true; - max--; } } - if (max > 0 && (dir == -1 || dir == 1) && !current.getMerged(1)) { - Plot other = getPlotAbs(current.world, getPlotIdRelative(current.id, 1)); - if (other.isOwner(uuid)) { - frontier.addAll(other.getConnectedPlots()); + if (max >= 0 && (dir == -1 || dir == 1) && !current.getMerged(1)) { + Plot other = getPlotRelative(current, 1); + if (other.isOwner(uuid) && (other.getBasePlot(false).equals(current.getBasePlot(false)) || ((plots = other.getConnectedPlots()).size() <= max && frontier.addAll(plots) && (max -= plots.size()) != -1))) { mergePlot(current.world, current, other, removeRoads); merged.add(current.id); merged.add(other.id); toReturn = true; - max--; } } - if (max > 0 && (dir == -1 || dir == 2) && !current.getMerged(2)) { - Plot other = getPlotAbs(current.world, getPlotIdRelative(current.id, 2)); - if (other.isOwner(uuid)) { - frontier.addAll(other.getConnectedPlots()); + if (max >= 0 && (dir == -1 || dir == 2) && !current.getMerged(2)) { + Plot other = getPlotRelative(current, 2); + if (other.isOwner(uuid) && (other.getBasePlot(false).equals(current.getBasePlot(false)) || ((plots = other.getConnectedPlots()).size() <= max && frontier.addAll(plots) && (max -= plots.size()) != -1))) { mergePlot(current.world, current, other, removeRoads); merged.add(current.id); merged.add(other.id); toReturn = true; - max--; } } - if (max > 0 && (dir == -1 || dir == 3) && !current.getMerged(3)) { - Plot other = getPlotAbs(current.world, getPlotIdRelative(current.id, 3)); - if (other.isOwner(uuid)) { - frontier.addAll(other.getConnectedPlots()); + if (max >= 0 && (dir == -1 || dir == 3) && !current.getMerged(3)) { + Plot other = getPlotRelative(current, 3); + if (other.isOwner(uuid) && (other.getBasePlot(false).equals(current.getBasePlot(false)) || ((plots = other.getConnectedPlots()).size() <= max && frontier.addAll(plots) && (max -= plots.size()) != -1))) { mergePlot(current.world, current, other, removeRoads); merged.add(current.id); merged.add(other.id); toReturn = true; - max--; } } } - PlotManager manager = PS.get().getPlotManager(plot.world); - ArrayList ids = new ArrayList<>(merged); - if (removeRoads) { + if (removeRoads && toReturn) { + PlotManager manager = PS.get().getPlotManager(plot.world); + ArrayList ids = new ArrayList<>(merged); manager.finishPlotMerge(plot.getWorld(), ids); } return toReturn; @@ -1548,7 +1563,7 @@ public class MainUtil { * @return Home Location */ public static Location getPlotHome(final String w, final PlotId plotid) { - final Plot plot = getPlotAbs(w, plotid).getBasePlot(false); + final Plot plot = getPlot(w, plotid); final BlockLoc home = plot.getPosition(); PS.get().getPlotManager(w); if ((home == null) || ((home.x == 0) && (home.z == 0))) { @@ -2153,7 +2168,7 @@ public class MainUtil { } Plot current; while ((current = frontier.poll()) != null) { - if (current.settings == null) { + if (current.owner == null || current.settings == null) { // Invalid plot // merged onto unclaimed plot PS.debug("Ignoring invalid merged plot: " + current + " | " + current.owner); diff --git a/target/PlotSquared-Bukkit.jar b/target/PlotSquared-Bukkit.jar index c32e9c3ce..d268e4acc 100644 Binary files a/target/PlotSquared-Bukkit.jar and b/target/PlotSquared-Bukkit.jar differ