diff --git a/src/main/java/com/intellectualcrafters/plot/PS.java b/src/main/java/com/intellectualcrafters/plot/PS.java index 002e29337..26ba516b6 100644 --- a/src/main/java/com/intellectualcrafters/plot/PS.java +++ b/src/main/java/com/intellectualcrafters/plot/PS.java @@ -351,9 +351,9 @@ public class PS { * @param message Message to log * @see IPlotMain#log(String) */ - public static void debug(final String message) { + public static void debug(final Object message) { if (Settings.DEBUG) { - get().IMP.log(message); + log(message); } } diff --git a/src/main/java/com/intellectualcrafters/plot/commands/Auto.java b/src/main/java/com/intellectualcrafters/plot/commands/Auto.java index da70a006a..aaa54114b 100644 --- a/src/main/java/com/intellectualcrafters/plot/commands/Auto.java +++ b/src/main/java/com/intellectualcrafters/plot/commands/Auto.java @@ -167,7 +167,7 @@ public class Auto extends SubCommand { if (plot == null) { return sendMessage(plr, C.NOT_IN_PLOT); } - final PlotCluster cluster = ClusterManager.getCluster(loc); + final PlotCluster cluster = plot.getCluster(); // Must be standing in a cluster if (cluster == null) { MainUtil.sendMessage(plr, C.NOT_IN_CLUSTER); @@ -183,7 +183,7 @@ public class Auto extends SubCommand { for (int i = 0; i <= max; i++) { final PlotId currentId = new PlotId(origin.x + id.x, origin.y + id.y); final Plot current = MainUtil.getPlot(worldname, currentId); - if (MainUtil.canClaim(plr, current) && (current.getSettings().isMerged() == false) && cluster.equals(ClusterManager.getCluster(current))) { + if (MainUtil.canClaim(plr, current) && (current.getSettings().isMerged() == false) && cluster.equals(current.getCluster())) { Claim.claimPlot(plr, current, true, true); return true; } diff --git a/src/main/java/com/intellectualcrafters/plot/commands/Cluster.java b/src/main/java/com/intellectualcrafters/plot/commands/Cluster.java index c070220c2..82ef3b78f 100644 --- a/src/main/java/com/intellectualcrafters/plot/commands/Cluster.java +++ b/src/main/java/com/intellectualcrafters/plot/commands/Cluster.java @@ -22,11 +22,14 @@ package com.intellectualcrafters.plot.commands; import java.util.ArrayList; import java.util.HashSet; +import java.util.Set; import java.util.UUID; import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.database.DBFunc; +import com.intellectualcrafters.plot.flag.Flag; +import com.intellectualcrafters.plot.flag.FlagManager; import com.intellectualcrafters.plot.generator.PlotGenerator; import com.intellectualcrafters.plot.object.BlockLoc; import com.intellectualcrafters.plot.object.Location; @@ -123,34 +126,28 @@ public class Cluster extends SubCommand { return false; } } - //check if overlap - final PlotClusterId id = new PlotClusterId(pos1, pos2); - final HashSet intersects = ClusterManager.getIntersects(plr.getLocation().getWorld(), id); - if ((intersects.size() > 0)) { - MainUtil.sendMessage(plr, C.CLUSTER_INTERSECTION, intersects.size() + ""); - return false; - } if ((pos2.x < pos1.x) || (pos2.y < pos1.y) ) { pos1 = new PlotId(Math.min(pos1.x, pos2.x), Math.min(pos1.y, pos2.y)); pos2 = new PlotId(Math.max(pos1.x, pos2.x), Math.max(pos1.y, pos2.y)); } - // create cluster - final String world = plr.getLocation().getWorld(); - final PlotCluster cluster = new PlotCluster(world, pos1, pos2, UUIDHandler.getUUID(plr)); - cluster.settings.setAlias(name); - DBFunc.createCluster(world, cluster); - if (!ClusterManager.clusters.containsKey(world)) { - ClusterManager.clusters.put(world, new HashSet()); + //check if overlap + String world = plr.getLocation().getWorld(); + final PlotClusterId id = new PlotClusterId(pos1, pos2); + final HashSet intersects = ClusterManager.getIntersects(world, id); + if ((intersects.size() > 0)) { + MainUtil.sendMessage(plr, C.CLUSTER_INTERSECTION, intersects.size() + ""); + return false; } - ClusterManager.clusters.get(world).add(cluster); - // Add any existing plots to the current cluster - for (final Plot plot : PS.get().getPlotsInWorld(plr.getLocation().getWorld())) { - final PlotCluster current = ClusterManager.getCluster(plot); - if (cluster.equals(current) && !cluster.isAdded(plot.owner)) { - cluster.invited.add(plot.owner); - DBFunc.setInvited(world, cluster, plot.owner); + // Check if it occupies existing plots + Set plots = MainUtil.getPlotSelectionOwned(world, pos1, pos2); + if (plots.size() > 0) { + if (!Permissions.hasPermission(plr, "plots.cluster.create.other")) { + MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.create.other"); + return false; } } + // Set the generator (if applicable) + final PlotCluster cluster = new PlotCluster(world, pos1, pos2, UUIDHandler.getUUID(plr)); PlotWorld plotworld = PS.get().getPlotWorld(world); if (plotworld == null) { PS.get().config.createSection("worlds." + world); @@ -184,6 +181,24 @@ public class Cluster extends SubCommand { // } // new AugmentedPopulator(world, generator, cluster, plotworld.TERRAIN == 2, plotworld.TERRAIN != 2); } + // create cluster + cluster.settings.setAlias(name); + DBFunc.createCluster(world, cluster); + if (!ClusterManager.clusters.containsKey(world)) { + ClusterManager.clusters.put(world, new HashSet()); + } + ClusterManager.clusters.get(world).add(cluster); + // Add any existing plots to the current cluster + for (Plot plot : plots) { + if (plot.hasOwner()) { + Flag flag = new Flag(FlagManager.getFlag("cluster"), cluster); + FlagManager.addPlotFlag(plot, flag); + if (!cluster.isAdded(plot.owner)) { + cluster.invited.add(plot.owner); + DBFunc.setInvited(world, cluster, plot.owner); + } + } + } MainUtil.sendMessage(plr, C.CLUSTER_ADDED); return true; } @@ -252,14 +267,20 @@ public class Cluster extends SubCommand { return false; } // check pos1 / pos2 - final PlotId pos1 = MainUtil.parseId(args[1]); - final PlotId pos2 = MainUtil.parseId(args[2]); + PlotId pos1 = MainUtil.parseId(args[1]); + PlotId pos2 = MainUtil.parseId(args[2]); if ((pos1 == null) || (pos2 == null)) { MainUtil.sendMessage(plr, C.NOT_VALID_PLOT_ID); return false; } + if ((pos2.x < pos1.x) || (pos2.y < pos1.y) ) { + pos1 = new PlotId(Math.min(pos1.x, pos2.x), Math.min(pos1.y, pos2.y)); + pos2 = new PlotId(Math.max(pos1.x, pos2.x), Math.max(pos1.y, pos2.y)); + } // check if in cluster - final PlotCluster cluster = ClusterManager.getCluster(plr.getLocation()); + Location loc = plr.getLocation(); + String world = loc.getWorld(); + final PlotCluster cluster = ClusterManager.getCluster(loc); if (cluster == null) { MainUtil.sendMessage(plr, C.NOT_IN_CLUSTER); return false; @@ -272,11 +293,35 @@ public class Cluster extends SubCommand { } //check if overlap final PlotClusterId id = new PlotClusterId(pos1, pos2); - final HashSet intersects = ClusterManager.getIntersects(plr.getLocation().getWorld(), id); + final HashSet intersects = ClusterManager.getIntersects(world, id); if (intersects.size() > 1) { MainUtil.sendMessage(plr, C.CLUSTER_INTERSECTION, (intersects.size() - 1) + ""); return false; } + HashSet existing = MainUtil.getPlotSelectionOwned(world, cluster.getP1(), cluster.getP2()); + HashSet newplots = MainUtil.getPlotSelectionOwned(world, pos1, pos2); + HashSet removed = ((HashSet) existing.clone()); + removed.removeAll(newplots); + // Check expand / shrink + if (removed.size() > 0) { + if (!Permissions.hasPermission(plr, "plots.cluster.resize.shrink")) { + MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.resize.shrink"); + return false; + } + } + newplots.removeAll(existing); + if (newplots.size() > 0) { + if (!Permissions.hasPermission(plr, "plots.cluster.resize.expand")) { + MainUtil.sendMessage(plr, C.NO_PERMISSION, "plots.cluster.resize.expand"); + return false; + } + } + for (Plot plot : removed) { + FlagManager.removePlotFlag(plot, "cluster"); + } + for (Plot plot : newplots) { + FlagManager.addPlotFlag(plot, new Flag(FlagManager.getFlag("cluster"), cluster)); + } // resize cluster DBFunc.resizeCluster(cluster, id); MainUtil.sendMessage(plr, C.CLUSTER_RESIZED); diff --git a/src/main/java/com/intellectualcrafters/plot/object/Plot.java b/src/main/java/com/intellectualcrafters/plot/object/Plot.java index 2348f916b..905d4daf0 100644 --- a/src/main/java/com/intellectualcrafters/plot/object/Plot.java +++ b/src/main/java/com/intellectualcrafters/plot/object/Plot.java @@ -43,6 +43,7 @@ import com.intellectualcrafters.plot.flag.FlagManager; import com.intellectualcrafters.plot.util.BO3Handler; import com.intellectualcrafters.plot.util.BlockManager; import com.intellectualcrafters.plot.util.ChunkManager; +import com.intellectualcrafters.plot.util.ClusterManager; import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.SchematicHandler; import com.intellectualcrafters.plot.util.TaskManager; @@ -226,6 +227,44 @@ public class Plot { this.meta.remove(key); } } + + /** + * Get the cluster this plot is associated with + * @return + */ + public PlotCluster getCluster() { + if (!Settings.ENABLE_CLUSTERS) { + return null; + } + if (owner == null) { + return ClusterManager.getCluster(this); + } + Flag flag = FlagManager.getPlotFlag(this, "cluster"); + if (flag != null) { + PlotCluster cluster = (PlotCluster) flag.getValue(); + cluster = ClusterManager.getCluster(cluster.world, cluster.getName()); + if (cluster != null) { + return cluster; + } + cluster = ClusterManager.getCluster(this); + if (cluster == null) { + FlagManager.removePlotFlag(this, "cluster"); + return null; + } + else { + flag = new Flag(flag.getAbstractFlag(), cluster); + FlagManager.addPlotFlag(this, flag); + return cluster; + } + } + PlotCluster cluster = ClusterManager.getCluster(this); + if (cluster != null) { + flag = new Flag(FlagManager.getFlag("cluster"), cluster); + FlagManager.addPlotFlag(this, flag); + return cluster; + } + return null; + } /** * Get the players currently inside this plot diff --git a/src/main/java/com/intellectualcrafters/plot/util/ClusterManager.java b/src/main/java/com/intellectualcrafters/plot/util/ClusterManager.java index 13ff0af0a..be1e5ba66 100644 --- a/src/main/java/com/intellectualcrafters/plot/util/ClusterManager.java +++ b/src/main/java/com/intellectualcrafters/plot/util/ClusterManager.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Random; +import java.util.Set; import org.bukkit.Bukkit; import org.bukkit.Chunk; @@ -43,7 +44,7 @@ public class ClusterManager { } return new HashSet<>(); } - + public static Location getHome(final PlotCluster cluster) { final BlockLoc home = cluster.settings.getPosition(); Location toReturn; diff --git a/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java b/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java index 93cec65d9..8f823c3bd 100644 --- a/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java +++ b/src/main/java/com/intellectualcrafters/plot/util/MainUtil.java @@ -27,6 +27,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -381,7 +382,7 @@ public class MainUtil { public static boolean isPlotArea(final Plot plot) { final PlotWorld plotworld = PS.get().getPlotWorld(plot.world); if (plotworld.TYPE == 2) { - return ClusterManager.getCluster(plot) != null; + return plot.getCluster() != null; } return true; } @@ -609,6 +610,12 @@ public class MainUtil { return id; } + /** + * Get a list of plot ids within a selection + * @param pos1 + * @param pos2 + * @return + */ public static ArrayList getPlotSelectionIds(final PlotId pos1, final PlotId pos2) { final ArrayList myplots = new ArrayList<>(); for (int x = pos1.x; x <= pos2.x; x++) { @@ -618,6 +625,38 @@ public class MainUtil { } return myplots; } + + /** + * Get a set of owned plots within a selection (chooses the best algorithm based on selection size.
+ * i.e. A selection of billions of plots will work fine + * @param pos1 + * @param pos2 + * @return + */ + public static HashSet getPlotSelectionOwned(String world, final PlotId pos1, final PlotId pos2) { + int size = (1 + pos2.x - pos1.x) * (1 + pos2.y - pos1.y); + HashSet result = new HashSet<>(); + if (PS.get().isPlotWorld(world)) { + if (size < PS.get().getAllPlotsRaw().get(world).size()) { + for (PlotId pid : MainUtil.getPlotSelectionIds(pos1, pos2)) { + Plot plot = MainUtil.getPlot(world, pid); + if (plot.hasOwner()) { + if (plot.id.x > pos1.x || plot.id.y > pos1.y || plot.id.x < pos2.x || plot.id.y < pos2.y) { + result.add(plot); + } + } + } + } + else { + for (Plot plot : PS.get().getPlotsInWorld(world)) { + if (plot.id.x > pos1.x || plot.id.y > pos1.y || plot.id.x < pos2.x || plot.id.y < pos2.y) { + result.add(plot); + } + } + } + } + return result; + } /** * Completely merges a set of plots
(There are no checks to make sure you supply the correct @@ -1333,7 +1372,7 @@ public class MainUtil { return false; } if (Settings.ENABLE_CLUSTERS) { - PlotCluster cluster = ClusterManager.getCluster(plot); + PlotCluster cluster = plot.getCluster(); if (cluster != null) { if (!cluster.isAdded(player.getUUID()) && !Permissions.hasPermission(player, "plots.admin.command.claim")) { return false;