diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 717a9cdfc..9b0dbc13e 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +custom: https://www.paypal.me/AlexanderBrandes # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index a70ab837c..f1ee68845 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -28,6 +28,7 @@ assignees: '' +**/plot debugpaste:** ### Server type: **Select one** @@ -97,4 +98,4 @@ for short (20 lines or less) text blobs, or a paste service for large blobs --> - [] I made sure there are no duplicates of this report [(Use Search)](https://github.com/IntellectualSites/PlotSquared/issues?utf8=%E2%9C%93&q=is%3Aissue) - [] I made sure I am using an up-to-date version of PlotSquared - [] I made sure the bug/error is not caused by any other plugin -- [x] I didn't read but checked everything above. +- [x] I didn't read but checked everything above. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug-issue-report-for-plotsquared.md b/.github/ISSUE_TEMPLATE/bug-issue-report-for-plotsquared.md deleted file mode 100644 index c619a6d14..000000000 --- a/.github/ISSUE_TEMPLATE/bug-issue-report-for-plotsquared.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -name: Bug/Issue report for PlotSquared -about: Bug / Issue report about this plugin -title: '' -labels: "[?] Testing Required" -assignees: '' - ---- - - - - - - - -# Bug Report Template: - -## Required Information section: -> ALL FIELDS IN THIS SECTION ARE REQUIRED, and must contain appropriate information -### Server config info (/plot debugpaste / file paste links): - - - -**/plot debugpaste:** - -### Server type: -**Select one** - -- [] Spigot / Paper *(CraftBukkit should not be used, re-test with Spigot first!)* -- [] Sponge -- [] NukkitX - -### PlotSquared version: - -``` -Paste the output here, between the tick marks, replacing this text -``` - -### Minecraft Version: -**Select one** - -- [] Minecraft 1.15.2 -- [] Minecraft 1.14.4 -- [] Minecraft 1.13.2 -- [] Minecraft 1.12.2 -- [] Minecraft 1.11.2 -- [] Minecraft 1.10.2 -- [] Minecraft 1.9.4 -- [] Minecraft 1.8.8 -- [] Minecraft Java Edition *other versions, please specify*: -- [] Minecraft Bedrock Edition *specify version*: -- [] Minecraft Sponge *specify version*: - -### Server build info: - -``` -Paste the output here, between the tick marks, replacing this text -``` - -### WorldEdit/FAWE versions: - -- [] FAWE version: -- [] WorldEdit version: - -### Description of the problem: - - - -### How to replicate: - - -## Additional Information: -> The information here is optional for you to provide, however it may help us to more readily diagnose any compatibility and bug issues. - -### Other plugins being used on the server: - - -### Relevant console output, log lines, and/or screenshots: - - -### Additional relevant comments/remarks: - - -# AFFIRMATION OF COMPLETION: - -- [] I included all information required in the sections above -- [] I made sure there are no duplicates of this report [(Use Search)](https://github.com/IntellectualSites/PlotSquared/issues?utf8=%E2%9C%93&q=is%3Aissue) -- [] I made sure I am using an up-to-date version of PlotSquared -- [] I made sure the bug/error is not caused by any other plugin -- [x] I didn't read but checked everything above. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 83661f8c6..fd39e3738 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,8 @@ blank_issues_enabled: false contact_links: + - name: PlotSquared Issue Tracker + url: https://issues.intellectualsites.com/projects/ps + about: Click here to move to our new issue tracker - name: PlotSquared Suggestions url: https://github.com/IntellectualSites/PlotSquaredSuggestions about: If you want to submit feature or suggestion ideas, do that here \ No newline at end of file diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 0c86fe2f0..9cdb65d18 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -31,9 +31,9 @@ dependencies { compile("com.github.MilkBowl:VaultAPI:1.7") { exclude(module: "bukkit") } - implementation("me.clip:placeholderapi:2.10.4") - implementation("net.luckperms:api:5.0") - implementation("net.ess3:EssentialsX:2.16.1") + implementation("me.clip:placeholderapi:2.10.6") + implementation("net.luckperms:api:5.1") + implementation("net.ess3:EssentialsX:2.17.2") implementation("net.alpenblock:BungeePerms:4.0-dev-106") compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false } compile 'com.github.pavog:SquirrelID:0.6.1' @@ -93,6 +93,9 @@ shadowJar { include(dependency("io.papermc:paperlib:1.0.2")) include(dependency("net.kyori:text-adapter-bukkit:3.0.3")) include(dependency("org.bstats:bstats-bukkit:1.7")) + include(dependency("com.github.davidmoten:rtree:0.8.7")) + include(dependency("io.reactivex:rxjava:1.3.8")) + include(dependency("com.github.davidmoten:guava-mini:0.1.1")) include(dependency("com.github.pavog:SquirrelID:0.6.1")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java index 482d02896..4646868a1 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java @@ -36,6 +36,9 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; /** * Default Bukkit world manager. It will handle world creation by @@ -76,4 +79,13 @@ public class BukkitWorldManager implements PlatformWorldManager { return "bukkit"; } + @Override public Collection getWorlds() { + final List worlds = Bukkit.getWorlds(); + final List worldNames = new ArrayList<>(); + for (final World world : worlds) { + worldNames.add(world.getName()); + } + return worldNames; + } + } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java index 16c63d093..158f90928 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java @@ -348,7 +348,7 @@ public class BukkitRegionManager extends RegionManager { CuboidRegion currentPlotClear = RegionUtil .createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); map.saveEntitiesOut(chunkObj, currentPlotClear); - AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager.manager + AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager .setChunkInPlotArea(null, new RunnableVal() { @Override public void run(ScopedLocalBlockQueue value) { Location min = value.getMin(); diff --git a/Core/build.gradle b/Core/build.gradle index ee6edfda2..8581a39a4 100644 --- a/Core/build.gradle +++ b/Core/build.gradle @@ -16,6 +16,7 @@ dependencies { testAnnotationProcessor("org.projectlombok:lombok:1.18.8") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.3.72") implementation("org.jetbrains:annotations:19.0.0") + implementation 'com.github.davidmoten:rtree:0.8.7' } sourceCompatibility = 1.8 @@ -73,6 +74,7 @@ shadowJar { include(dependency("net.kyori:text-serializer-gson:3.0.2")) include(dependency("net.kyori:text-serializer-legacy:3.0.2")) include(dependency("net.kyori:text-serializer-plain:3.0.2")) + include(dependency("com.github.davidmoten:rtree:0.8.7")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("org.json", "com.plotsquared.json") { diff --git a/Core/pom.xml b/Core/pom.xml index 280cd8b1a..4e53e831a 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -92,6 +92,12 @@ 1.3.72 runtime + + com.github.davidmoten + rtree + 0.8.7 + runtime + junit junit diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index 6c3b78ba3..a33fd502e 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -53,6 +53,7 @@ import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.BlockBucket; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotAreaTerrainType; import com.plotsquared.core.plot.PlotAreaType; import com.plotsquared.core.plot.PlotCluster; import com.plotsquared.core.plot.PlotFilter; @@ -81,6 +82,7 @@ import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.logger.ILogger; +import com.plotsquared.core.util.query.PlotQuery; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.uuid.UUIDPipeline; import com.sk89q.worldedit.WorldEdit; @@ -116,6 +118,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; @@ -267,7 +270,8 @@ public class PlotSquared { // create setup util class SetupUtils.manager = this.IMP.initSetupUtils(); // Set block - GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1, Settings.QUEUE.TARGET_TIME); + GlobalBlockQueue.IMP = + new GlobalBlockQueue(IMP.initBlockQueue(), 1, Settings.QUEUE.TARGET_TIME); GlobalBlockQueue.IMP.runTask(); // Set chunk ChunkManager.manager = this.IMP.initChunkManager(); @@ -620,17 +624,7 @@ public class PlotSquared { * @return Set of base Plots */ public Set getBasePlots() { - int size = getPlotCount(); - final Set result = new HashSet<>(size); - forEachPlotArea(value -> { - for (Plot plot : value.getPlots()) { - if (!plot.isBasePlot()) { - continue; - } - result.add(plot); - } - }); - return Collections.unmodifiableSet(result); + return PlotQuery.newQuery().whereBasePlot().asSet(); } public List sortPlotsByTemp(Collection plots) { @@ -883,27 +877,25 @@ public class PlotSquared { * * @param filters the filter * @return a filtered set of plots + * @deprecated Use {@link PlotQuery} */ - public Set getPlots(final PlotFilter... filters) { - final HashSet set = new HashSet<>(); - forEachPlotArea(value -> { - for (PlotFilter filter : filters) { - if (!filter.allowsArea(value)) { - return; + @Deprecated public Set getPlots(final PlotFilter... filters) { + final List areas = new LinkedList<>(); + for (final PlotArea plotArea : this.getPlotAreas()) { + for (final PlotFilter filter : filters) { + if (filter.allowsArea(plotArea)) { + areas.add(plotArea); } } - loop: - for (Entry entry2 : value.getPlotEntries()) { - Plot plot = entry2.getValue(); - for (PlotFilter filter : filters) { - if (!filter.allowsPlot(plot)) { - continue loop; - } + } + return PlotQuery.newQuery().inAreas(areas).thatPasses(plot -> { + for (final PlotFilter filter : filters) { + if (!filter.allowsPlot(plot)) { + return false; } - set.add(plot); } - }); - return set; + return true; + }).asSet(); } /** @@ -970,7 +962,7 @@ public class PlotSquared { * @return Set of plot */ public Set getPlots(String world, PlotPlayer player) { - return getPlots(world, player.getUUID()); + return PlotQuery.newQuery().inWorld(world).ownedBy(player).asSet(); } /** @@ -981,7 +973,7 @@ public class PlotSquared { * @return Set of plot */ public Set getPlots(PlotArea area, PlotPlayer player) { - return getPlots(area, player.getUUID()); + return PlotQuery.newQuery().inArea(area).ownedBy(player).asSet(); } /** @@ -991,14 +983,8 @@ public class PlotSquared { * @param uuid the plot owner * @return Set of plot */ - public Set getPlots(String world, @Nullable UUID uuid) { - if (uuid == null) { - return Collections.emptySet(); - } - final Set plots = - getPlots(world).stream().filter(plot -> plot.hasOwner() && plot.isOwnerAbs(uuid)) - .collect(Collectors.toSet()); - return Collections.unmodifiableSet(plots); + public Set getPlots(String world, UUID uuid) { + return PlotQuery.newQuery().inWorld(world).ownedBy(uuid).asSet(); } /** @@ -1009,13 +995,7 @@ public class PlotSquared { * @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); + return PlotQuery.newQuery().inArea(area).ownedBy(uuid).asSet(); } /** @@ -1030,9 +1010,7 @@ public class PlotSquared { } public Collection getPlots(String world) { - final Set set = new HashSet<>(); - forEachPlotArea(world, value -> set.addAll(value.getPlots())); - return set; + return PlotQuery.newQuery().inWorld(world).asCollection(); } /** @@ -1042,7 +1020,7 @@ public class PlotSquared { * @return Set of Plot */ public Set getPlots(PlotPlayer player) { - return getPlots(player.getUUID()); + return PlotQuery.newQuery().ownedBy(player).asSet(); } public Collection getPlots(PlotArea area) { @@ -1064,13 +1042,7 @@ public class PlotSquared { * @return Set of Plot's owned by the player */ public Set getPlots(final UUID uuid) { - final Set plots = new HashSet<>(); - forEachPlot(value -> { - if (value.isOwnerAbs(uuid)) { - plots.add(value); - } - }); - return Collections.unmodifiableSet(plots); + return PlotQuery.newQuery().ownedBy(uuid).asSet(); } public boolean hasPlot(final UUID uuid) { @@ -1079,13 +1051,7 @@ public class PlotSquared { } public Set getBasePlots(final UUID uuid) { - final Set plots = new HashSet<>(); - forEachBasePlot(value -> { - if (value.isOwner(uuid)) { - plots.add(value); - } - }); - return Collections.unmodifiableSet(plots); + return PlotQuery.newQuery().ownedBy(uuid).whereBasePlot().asSet(); } /** @@ -1095,13 +1061,7 @@ public class PlotSquared { * @return Set of Plot */ public Set getPlotsAbs(final UUID uuid) { - final Set plots = new HashSet<>(); - forEachPlot(value -> { - if (value.isOwnerAbs(uuid)) { - plots.add(value); - } - }); - return Collections.unmodifiableSet(plots); + return PlotQuery.newQuery().ownedBy(uuid).asSet(); } /** @@ -1996,6 +1956,23 @@ public class PlotSquared { return Collections.unmodifiableSet(set); } + /** + * Check if the chunk uses vanilla/non-PlotSquared generation + * + * @param world World name + * @param chunkCoordinates Chunk coordinates + * @return True if the chunk uses non-standard generation, false if not + */ + public boolean isNonStandardGeneration(@NotNull final String world, + @NotNull final BlockVector2 chunkCoordinates) { + final Location location = new Location(world, chunkCoordinates.getBlockX() << 4, 64, chunkCoordinates.getBlockZ() << 4); + final PlotArea area = plotAreaManager.getApplicablePlotArea(location); + if (area == null) { + return true; + } + return area.getTerrain() != PlotAreaTerrainType.NONE; + } + public boolean isAugmented(@NonNull final String world) { final PlotArea[] areas = plotAreaManager.getPlotAreas(world, null); return areas != null && (areas.length > 1 || areas[0].getType() != PlotAreaType.NORMAL); @@ -2085,16 +2062,7 @@ public class PlotSquared { */ 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); + return PlotQuery.newQuery().inWorld(worldname).withAlias(alias).asSet(); } public Set getPlotAreas(final String world, final CuboidRegion region) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java index f5d494868..932bbf0ab 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -33,6 +33,7 @@ import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.generator.AugmentedUtils; import com.plotsquared.core.generator.HybridPlotWorld; import com.plotsquared.core.location.Location; +import com.plotsquared.core.player.ConsolePlayer; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotAreaTerrainType; @@ -45,14 +46,28 @@ import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.RegionUtil; +import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal3; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; +import com.sk89q.worldedit.function.operation.ForwardExtentCopy; +import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.Region; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Objects; @@ -74,6 +89,139 @@ public class Area extends SubCommand { return false; } switch (args[0].toLowerCase()) { + case "single": + if (player instanceof ConsolePlayer) { + MainUtil.sendMessage(player, Captions.IS_CONSOLE); + return false; + } + if (!Permissions.hasPermission(player, Captions.PERMISSION_AREA_CREATE)) { + MainUtil.sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_AREA_CREATE); + return false; + } + if (args.length < 2) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_NEEDS_NAME); + return false; + } + final PlotArea existingArea = PlotSquared.get().getPlotArea(player.getLocation().getWorld(), args[1]); + if (existingArea != null && existingArea.getId().equalsIgnoreCase(args[1])) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_NAME_TAKEN); + return false; + } + final LocalSession localSession = WorldEdit.getInstance().getSessionManager().getIfPresent(player.toActor()); + if (localSession == null) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_MISSING_SELECTION); + return false; + } + Region playerSelectedRegion = null; + try { + playerSelectedRegion = localSession.getSelection(((Player) player.toActor()).getWorld()); + } catch (final Exception ignored) {} + if (playerSelectedRegion == null) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_MISSING_SELECTION); + return false; + } + if (playerSelectedRegion.getWidth() != playerSelectedRegion.getLength()) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_NOT_SQUARE); + return false; + } + if (PlotSquared.get().getPlotAreaManager().getPlotAreas( + Objects.requireNonNull(playerSelectedRegion.getWorld()).getName(), CuboidRegion.makeCuboid(playerSelectedRegion)).length != 0) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_OVERLAPPING); + } + // Alter the region + final BlockVector3 playerSelectionMin = playerSelectedRegion.getMinimumPoint(); + final BlockVector3 playerSelectionMax = playerSelectedRegion.getMaximumPoint(); + // Create a new selection that spans the entire vertical range of the world + final CuboidRegion selectedRegion = new CuboidRegion(playerSelectedRegion.getWorld(), + BlockVector3.at(playerSelectionMin.getX(), 0, playerSelectionMin.getZ()), + BlockVector3.at(playerSelectionMax.getX(), 255, playerSelectionMax.getZ())); + // There's only one plot in the area... + final PlotId plotId = new PlotId(1, 1); + final HybridPlotWorld hybridPlotWorld = new HybridPlotWorld(player.getLocation().getWorld(), args[1], + Objects.requireNonNull(PlotSquared.imp()).getDefaultGenerator(), plotId, plotId); + // Plot size is the same as the region width + hybridPlotWorld.PLOT_WIDTH = hybridPlotWorld.SIZE = (short) selectedRegion.getWidth(); + // We use a schematic generator + hybridPlotWorld.setTerrain(PlotAreaTerrainType.NONE); + // It is always a partial plot world + hybridPlotWorld.setType(PlotAreaType.PARTIAL); + // We save the schematic :D + hybridPlotWorld.PLOT_SCHEMATIC = true; + // Set the road width to 0 + hybridPlotWorld.ROAD_WIDTH = hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0; + // Set the plot height to the selection height + hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT = hybridPlotWorld.WALL_HEIGHT = playerSelectionMin.getBlockY(); + // No sign plz + hybridPlotWorld.setAllowSigns(false); + final File parentFile = MainUtil.getFile(PlotSquared.imp().getDirectory(), "schematics" + File.separator + + "GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld.getWorldName() + File.separator + + hybridPlotWorld.getId()); + if (!parentFile.exists() && !parentFile.mkdirs()) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_COULD_NOT_MAKE_DIRECTORIES); + return false; + } + final File file = new File(parentFile, "plot.schem"); + try (final ClipboardWriter clipboardWriter = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(new FileOutputStream(file))) { + final BlockArrayClipboard clipboard = new BlockArrayClipboard(selectedRegion); + final EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(selectedRegion.getWorld(), -1); + final ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(editSession, selectedRegion, clipboard, selectedRegion.getMinimumPoint()); + forwardExtentCopy.setCopyingBiomes(true); + forwardExtentCopy.setCopyingEntities(true); + Operations.complete(forwardExtentCopy); + clipboardWriter.write(clipboard); + } catch (final Exception e) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_FAILED_TO_SAVE); + e.printStackTrace(); + return false; + } + + // Setup schematic + try { + hybridPlotWorld.setupSchematics(); + } catch (final SchematicHandler.UnsupportedFormatException e) { + e.printStackTrace(); + } + + // Calculate the offset + final BlockVector3 singlePos1 = selectedRegion.getMinimumPoint(); + + // Now the schematic is saved, which is wonderful! + final SetupObject singleSetup = new SetupObject(); + singleSetup.world = hybridPlotWorld.getWorldName(); + singleSetup.id = hybridPlotWorld.getId(); + singleSetup.terrain = hybridPlotWorld.getTerrain(); + singleSetup.type = hybridPlotWorld.getType(); + singleSetup.plotManager = PlotSquared.imp().getPluginName(); + singleSetup.setupGenerator = PlotSquared.imp().getPluginName(); + singleSetup.step = hybridPlotWorld.getSettingNodes(); + singleSetup.max = plotId; + singleSetup.min = plotId; + Runnable singleRun = () -> { + final String path = + "worlds." + hybridPlotWorld.getWorldName() + ".areas." + hybridPlotWorld.getId() + '-' + + singleSetup.min + '-' + singleSetup.max; + final int offsetX = singlePos1.getX(); + final int offsetZ = singlePos1.getZ(); + 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(singleSetup); + if (WorldUtil.IMP.isWorld(world)) { + PlotSquared.get().loadWorld(world, null); + MainUtil.sendMessage(player, Captions.SINGLE_AREA_CREATED); + } else { + MainUtil.sendMessage(player, + "An error occurred while creating the world: " + hybridPlotWorld + .getWorldName()); + } + }; + singleRun.run(); + return true; case "c": case "setup": case "create": diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java b/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java index 412d2b066..0c805d6bc 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java @@ -121,7 +121,7 @@ public class DebugPaste extends SubCommand { b.append("OS Arch: ").append(System.getProperty("os.arch")).append('\n'); b.append("# Okay :D Great. You are now ready to create your bug report!"); b.append( - "\n# You can do so at https://github.com/IntellectualSites/PlotSquared/issues"); + "\n# You can do so at https://issues.intellectualsites.com/projects/ps"); b.append("\n# or via our Discord at https://discord.gg/KxkjDVg"); final IncendoPaster incendoPaster = new IncendoPaster("plotsquared"); diff --git a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java index e9304e53f..0054df62e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java @@ -26,14 +26,12 @@ package com.plotsquared.core.command; import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.PlotSquared.SortType; import com.plotsquared.core.configuration.CaptionUtility; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; -import com.plotsquared.core.plot.Rating; import com.plotsquared.core.plot.expiration.ExpireManager; import com.plotsquared.core.plot.flag.implementations.DoneFlag; import com.plotsquared.core.plot.flag.implementations.PriceFlag; @@ -44,19 +42,24 @@ import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.StringMan; +import com.plotsquared.core.util.TabCompletions; +import com.plotsquared.core.util.query.PlotQuery; +import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal3; import com.plotsquared.core.uuid.UUIDMapping; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; import java.util.List; -import java.util.Map.Entry; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; +import java.util.stream.Collectors; @CommandDeclaration(command = "list", aliases = {"l", "find", "search"}, @@ -140,22 +143,31 @@ public class ListCmd extends SubCommand { String arg = args[0].toLowerCase(); final boolean[] sort = new boolean[] {true}; - final Consumer> plotConsumer = plots -> { - if (plots == null) { + final Consumer plotConsumer = query -> { + if (query == null) { sendMessage(player, Captions.DID_YOU_MEAN, new StringComparison<>(args[0], new String[] {"mine", "shared", "world", "all"}) .getBestMatch()); return; } + if (area != null) { + query.relativeToArea(area); + } + + if (sort[0]) { + query.withSortingStrategy(SortingStrategy.SORT_BY_CREATION); + } + + final List plots = query.asList(); + if (plots.isEmpty()) { MainUtil.sendMessage(player, Captions.FOUND_NO_PLOTS); return; } - displayPlots(player, new ArrayList<>(plots), 12, page, area, args, sort[0]); + displayPlots(player, plots, 12, page, args); }; - final List plots = new ArrayList<>(); switch (arg) { case "mine": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_MINE)) { @@ -164,8 +176,7 @@ public class ListCmd extends SubCommand { return false; } sort[0] = false; - plotConsumer.accept( - PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getBasePlots(player))); + plotConsumer.accept(PlotQuery.newQuery().ownedBy(player).whereBasePlot().withSortingStrategy(SortingStrategy.SORT_BY_TEMP)); break; case "shared": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_SHARED)) { @@ -173,13 +184,7 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_SHARED); return false; } - for (Plot plot : PlotSquared.get().getPlots()) { - if (plot.getTrusted().contains(player.getUUID()) || plot.getMembers() - .contains(player.getUUID())) { - plots.add(plot); - } - } - plotConsumer.accept(plots); + plotConsumer.accept(PlotQuery.newQuery().withMember(player.getUUID()).thatPasses(plot -> !plot.isOwnerAbs(player.getUUID()))); break; case "world": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_WORLD)) { @@ -194,7 +199,7 @@ public class ListCmd extends SubCommand { world)); return false; } - plotConsumer.accept(PlotSquared.get().getPlots(world)); + plotConsumer.accept(PlotQuery.newQuery().inWorld(world)); break; case "expired": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_EXPIRED)) { @@ -202,9 +207,11 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_EXPIRED); return false; } - plotConsumer.accept(ExpireManager.IMP == null ? - new ArrayList<>() : - new ArrayList<>(ExpireManager.IMP.getPendingExpired())); + if (ExpireManager.IMP == null) { + plotConsumer.accept(PlotQuery.newQuery().noPlots()); + } else { + plotConsumer.accept(PlotQuery.newQuery().expiredPlots()); + } break; case "area": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_AREA)) { @@ -219,8 +226,11 @@ public class ListCmd extends SubCommand { world)); return false; } - plotConsumer.accept( - area == null ? new ArrayList() : new ArrayList<>(area.getPlots())); + if (area == null) { + plotConsumer.accept(PlotQuery.newQuery().noPlots()); + } else { + plotConsumer.accept(PlotQuery.newQuery().inArea(area)); + } break; case "all": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_ALL)) { @@ -228,7 +238,7 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_ALL); return false; } - plotConsumer.accept(new ArrayList<>(PlotSquared.get().getPlots())); + plotConsumer.accept(PlotQuery.newQuery().allPlots()); break; case "done": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_DONE)) { @@ -236,24 +246,8 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_DONE); return false; } - for (Plot plot : PlotSquared.get().getPlots()) { - if (DoneFlag.isDone(plot)) { - plots.add(plot); - } - } - plots.sort((a, b) -> { - String va = a.getFlag(DoneFlag.class); - String vb = b.getFlag(DoneFlag.class); - if (MathMan.isInteger(va)) { - if (MathMan.isInteger(vb)) { - return Integer.parseInt(vb) - Integer.parseInt(va); - } - return -1; - } - return 1; - }); sort[0] = false; - plotConsumer.accept(plots); + plotConsumer.accept(PlotQuery.newQuery().allPlots().thatPasses(DoneFlag::isDone).withSortingStrategy(SortingStrategy.SORT_BY_DONE)); break; case "top": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_TOP)) { @@ -261,33 +255,8 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_TOP); return false; } - plots.addAll(PlotSquared.get().getPlots()); - plots.sort((p1, p2) -> { - double v1 = 0; - int p1s = p1.getSettings().getRatings().size(); - int p2s = p2.getRatings().size(); - if (!p1.getSettings().getRatings().isEmpty()) { - v1 = p1.getRatings().values().stream().mapToDouble(Rating::getAverageRating) - .map(av -> av * av).sum(); - v1 /= p1s; - v1 += p1s; - } - double v2 = 0; - if (!p2.getSettings().getRatings().isEmpty()) { - for (Entry entry : p2.getRatings().entrySet()) { - double av = entry.getValue().getAverageRating(); - v2 += av * av; - } - v2 /= p2s; - v2 += p2s; - } - if (v2 == v1 && v2 != 0) { - return p2s - p1s; - } - return (int) Math.signum(v2 - v1); - }); sort[0] = false; - plotConsumer.accept(plots); + plotConsumer.accept(PlotQuery.newQuery().allPlots().withSortingStrategy(SortingStrategy.SORT_BY_RATING)); break; case "forsale": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_FOR_SALE)) { @@ -298,12 +267,7 @@ public class ListCmd extends SubCommand { if (EconHandler.manager == null) { break; } - for (Plot plot : PlotSquared.get().getPlots()) { - if (plot.getFlag(PriceFlag.class) > 0) { - plots.add(plot); - } - } - plotConsumer.accept(plots); + plotConsumer.accept(PlotQuery.newQuery().allPlots().thatPasses(plot -> plot.getFlag(PriceFlag.class) > 0)); break; case "unowned": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNOWNED)) { @@ -311,12 +275,7 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_UNOWNED); return false; } - for (Plot plot : PlotSquared.get().getPlots()) { - if (plot.getOwner() == null) { - plots.add(plot); - } - } - plotConsumer.accept(plots); + plotConsumer.accept(PlotQuery.newQuery().allPlots().thatPasses(plot -> plot.getOwner() == null)); break; case "fuzzy": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_FUZZY)) { @@ -335,7 +294,7 @@ public class ListCmd extends SubCommand { term = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " "); } sort[0] = false; - plotConsumer.accept(MainUtil.getPlotsBySearch(term)); + plotConsumer.accept(PlotQuery.newQuery().plotsBySearch(term)); break; default: if (PlotSquared.get().hasPlotArea(args[0])) { @@ -352,7 +311,7 @@ public class ListCmd extends SubCommand { args[0])); return false; } - plotConsumer.accept(new ArrayList<>(PlotSquared.get().getPlots(args[0]))); + plotConsumer.accept(PlotQuery.newQuery().inWorld(args[0])); break; } @@ -377,24 +336,18 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_PLAYER); } else { sort[0] = false; - plotConsumer.accept(PlotSquared.get() - .sortPlotsByTemp(PlotSquared.get().getPlots(uuid))); + plotConsumer.accept(PlotQuery.newQuery().ownedBy(uuid).withSortingStrategy(SortingStrategy.SORT_BY_TEMP)); } } }); - break; } return true; } - public void displayPlots(final PlotPlayer player, List plots, int pageSize, int page, - PlotArea area, String[] args, boolean sort) { + public void displayPlots(final PlotPlayer player, List plots, int pageSize, int page, String[] args) { // Header plots.removeIf(plot -> !plot.isBasePlot()); - if (sort) { - plots = PlotSquared.get().sortPlots(plots, SortType.CREATION_DATE, area); - } this.paginate(player, plots, pageSize, page, new RunnableVal3() { @Override public void run(Integer i, Plot plot, PlotMessage message) { @@ -449,4 +402,48 @@ public class ListCmd extends SubCommand { }, "/plot list " + args[0], Captions.PLOT_LIST_HEADER_PAGED.getTranslated()); } + @Override public Collection tab(PlotPlayer player, String[] args, boolean space) { + final List completions = new LinkedList<>(); + if (EconHandler.manager != null && Permissions + .hasPermission(player, Captions.PERMISSION_LIST_FOR_SALE)) { + completions.add("forsale"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_MINE)) { + completions.add("mine"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_SHARED)) { + completions.add("shared"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_WORLD)) { + completions.addAll(PlotSquared.imp().getWorldManager().getWorlds()); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_TOP)) { + completions.add("top"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_ALL)) { + completions.add("all"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNOWNED)) { + completions.add("unowned"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_DONE)) { + completions.add("done"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_EXPIRED)) { + completions.add("expired"); + } + + final List commands = new LinkedList<>(); + commands.addAll(completions.stream() + .filter(completion -> completion.toLowerCase().startsWith(args[0].toLowerCase())) + .map(completion -> new Command(null, true, completion, "", RequiredType.NONE, CommandCategory.TELEPORT) {}) + .collect(Collectors.toList())); + + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_PLAYER) && args[0].length() > 0) { + commands.addAll(TabCompletions.completePlayers(args[0], Collections.emptyList())); + } + + return commands; + } + } diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index 78acbd88e..651a1c0b0 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -27,7 +27,6 @@ package com.plotsquared.core.command; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; @@ -36,19 +35,20 @@ import com.plotsquared.core.plot.flag.implementations.UntrustedVisitFlag; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; +import com.plotsquared.core.util.TabCompletions; +import com.plotsquared.core.util.query.PlotQuery; +import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; +import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; @CommandDeclaration(command = "visit", permission = "plots.visit", @@ -63,154 +63,246 @@ public class Visit extends Command { super(MainCommand.getInstance(), true); } - @Override public Collection tab(PlotPlayer player, String[] args, boolean space) { - return tabOf(player, args, space, getUsage()); + private void visit(@NotNull final PlotPlayer player, @NotNull final PlotQuery query, final PlotArea sortByArea, + final RunnableVal3 confirm, final RunnableVal2 whenDone) { + this.visit(player, query, sortByArea, confirm, whenDone, 1); + } + + private void visit(@NotNull final PlotPlayer player, @NotNull final PlotQuery query, final PlotArea sortByArea, + final RunnableVal3 confirm, final RunnableVal2 whenDone, int page) { + // We get the query once, + // then we get it another time further on + final List unsorted = query.asList(); + + if (unsorted.isEmpty()) { + Captions.FOUND_NO_PLOTS.send(player); + return; + } + + if (unsorted.size() > 1) { + query.whereBasePlot(); + } + + if (page == Integer.MIN_VALUE) { + page = 1; + } + + if (page < 1 || page > unsorted.size()) { + MainUtil.sendMessage(player, String.format("(1, %d)", unsorted.size())); + return; + } + + if (sortByArea != null) { + query.relativeToArea(sortByArea).withSortingStrategy(SortingStrategy.SORT_BY_CREATION); + } else { + query.withSortingStrategy(SortingStrategy.SORT_BY_TEMP); + } + + final List plots = query.asList(); + + final Plot plot = plots.get(page - 1); + if (!plot.hasOwner()) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_UNOWNED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_UNOWNED); + return; + } + } else if (plot.isOwner(player.getUUID())) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OWNED) && !Permissions + .hasPermission(player, Captions.PERMISSION_HOME)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OWNED); + return; + } + } else if (plot.isAdded(player.getUUID())) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_SHARED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_SHARED); + return; + } + } else { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OTHER)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OTHER); + return; + } + if (!plot.getFlag(UntrustedVisitFlag.class) && !Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED); + return; + } + } + + confirm.run(this, () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { + if (result) { + whenDone.run(Visit.this, CommandResult.SUCCESS); + } else { + whenDone.run(Visit.this, CommandResult.FAILURE); + } + }), () -> whenDone.run(Visit.this, CommandResult.FAILURE)); } @Override - public CompletableFuture execute(final PlotPlayer player, String[] args, - RunnableVal3 confirm, + public CompletableFuture execute(final PlotPlayer player, + String[] args, + final RunnableVal3 confirm, final RunnableVal2 whenDone) throws CommandException { if (args.length == 1 && args[0].contains(":")) { args = args[0].split(":"); } - final Collection unsortedPre = new HashSet<>(); - final PlotArea[] sortByArea = new PlotArea[] {player.getApplicablePlotArea()}; - final AtomicBoolean shouldSortByArea = new AtomicBoolean(Settings.Teleport.PER_WORLD_VISIT); + PlotArea sortByArea; - final Consumer pageConsumer = page -> { - if (page == Integer.MIN_VALUE) { - page = 1; - } - if (unsortedPre.isEmpty()) { - Captions.FOUND_NO_PLOTS.send(player); - } else { - final Collection unsorted = new ArrayList<>(unsortedPre); - if (unsorted.size() > 1) { - unsorted.removeIf(plot -> !plot.isBasePlot()); - } - if (page < 1 || page > unsorted.size()) { - Captions.NOT_VALID_NUMBER.send(player, "(1, " + unsorted.size() + ")"); - } else { - List plots; - if (shouldSortByArea.get()) { - plots = PlotSquared.get().sortPlots(unsorted, PlotSquared.SortType.CREATION_DATE, sortByArea[0]); - } else { - plots = PlotSquared.get().sortPlotsByTemp(unsorted); - } - final Plot plot = plots.get(page - 1); - if (!plot.hasOwner()) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_UNOWNED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_UNOWNED); - return; - } - } else if (plot.isOwner(player.getUUID())) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OWNED) && !Permissions.hasPermission(player, Captions.PERMISSION_HOME)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OWNED); - return; - } - } else if (plot.isAdded(player.getUUID())) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_SHARED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_SHARED); - return; - } - } else { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OTHER)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OTHER); - return; - } - if (!plot.getFlag(UntrustedVisitFlag.class) && !Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED); - return; - } - } - confirm.run(this, - () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { - if (result) { - whenDone.run(Visit.this, CommandResult.SUCCESS); - } else { - whenDone.run(Visit.this, CommandResult.FAILURE); - } - }), () -> whenDone.run(Visit.this, CommandResult.FAILURE)); - } - } - }; - - final int[] page = new int[]{Integer.MIN_VALUE}; + int page = Integer.MIN_VALUE; switch (args.length) { + // /p v [...] [...] case 3: if (!MathMan.isInteger(args[1])) { Captions.NOT_VALID_NUMBER.send(player, "(1, ∞)"); Captions.COMMAND_SYNTAX.send(player, getUsage()); return CompletableFuture.completedFuture(false); } - page[0] = Integer.parseInt(args[2]); + page = Integer.parseInt(args[2]); + // /p v [page] + // /p v [page] case 2: - if (page[0] != Integer.MIN_VALUE || !MathMan.isInteger(args[1])) { - sortByArea[0] = PlotSquared.get().getPlotAreaByString(args[1]); - if (sortByArea[0] == null) { + if (page != Integer.MIN_VALUE || !MathMan.isInteger(args[1])) { + sortByArea = PlotSquared.get().getPlotAreaByString(args[1]); + if (sortByArea == null) { Captions.NOT_VALID_NUMBER.send(player, "(1, ∞)"); Captions.COMMAND_SYNTAX.send(player, getUsage()); return CompletableFuture.completedFuture(false); } + final PlotArea finalSortByArea = sortByArea; + int finalPage1 = page; MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { if (throwable instanceof TimeoutException) { Captions.FETCHING_PLAYERS_TIMEOUT.send(player); } else if (throwable != null || uuids.size() != 1) { Captions.COMMAND_SYNTAX.send(player, getUsage()); } else { - unsortedPre.addAll(PlotSquared.get().getBasePlots((UUID) uuids.toArray()[0])); - shouldSortByArea.set(true); - pageConsumer.accept(page[0]); + final UUID uuid = uuids.toArray(new UUID[0])[0]; + this.visit(player, PlotQuery.newQuery().ownedBy(uuid).whereBasePlot(), finalSortByArea, confirm, whenDone, finalPage1); } }); break; } - page[0] = Integer.parseInt(args[1]); + page = Integer.parseInt(args[1]); + // /p v [page] + // /p v [page] + // /p v [page] + // /p v [page] case 1: final String[] finalArgs = args; - final Consumer uuidConsumer = uuid -> { - if (page[0] == Integer.MIN_VALUE && uuid == null && MathMan.isInteger(finalArgs[0])) { - page[0] = Integer.parseInt(finalArgs[0]); - unsortedPre.addAll(PlotSquared.get().getBasePlots(player)); - } else { - if (uuid != null) { - unsortedPre.addAll(PlotSquared.get().getBasePlots(uuid)); - } else { - Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true); - if (plot != null) { - unsortedPre.addAll(Collections.singletonList(plot.getBasePlot(false))); - } - } - } - pageConsumer.accept(page[0]); - }; - - if (args[0].length() >= 2) { + int finalPage = page; + if (args[0].length() >= 2 && !args[0].contains(";") && !args[0].contains(",")) { PlotSquared.get().getImpromptuUUIDPipeline().getSingle(args[0], (uuid, throwable) -> { if (throwable instanceof TimeoutException) { + // The request timed out MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); } else if (uuid != null && !PlotSquared.get().hasPlot(uuid)) { - uuidConsumer.accept(null); + // It was a valid UUID but the player has no plots + MainUtil.sendMessage(player, Captions.PLAYER_NO_PLOTS); + } else if (uuid == null) { + if (finalPage == Integer.MIN_VALUE && MathMan.isInteger(finalArgs[0])) { + // The argument was a number, so we assume it's the page number + int parsedPage; + try { + parsedPage = Integer.parseInt(finalArgs[0]); + } catch (final Throwable t) { + MainUtil.sendMessage(player, Captions.NOT_A_NUMBER, finalArgs[0]); + return; + } + this.visit(player, PlotQuery.newQuery().ownedBy(player).whereBasePlot(), null, + confirm, whenDone, parsedPage); + } else { + // Try to parse a plot + final Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true); + if (plot == null) { + MainUtil.sendMessage(player, Captions.NOT_VALID_PLOT_ID); + return; + } + this.visit(player, PlotQuery.newQuery().withPlot(plot), null, confirm, whenDone, 1); + } } else { - uuidConsumer.accept(uuid); + this.visit(player, PlotQuery.newQuery().ownedBy(uuid).whereBasePlot(), null, confirm, whenDone, finalPage); } }); } else { - uuidConsumer.accept(null); + if (finalPage == Integer.MIN_VALUE && MathMan.isInteger(finalArgs[0])) { + // The argument was a number, so we assume it's the page number + int parsedPage; + try { + parsedPage = Integer.parseInt(finalArgs[0]); + this.visit(player, PlotQuery.newQuery().ownedBy(player).whereBasePlot(), null, confirm, + whenDone, parsedPage); + } catch (final Throwable throwable) { + MainUtil.sendMessage(player, Captions.NOT_A_NUMBER, finalArgs[0]); + } + } else { + // Try to parse a plot + final Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true); + if (plot == null) { + MainUtil.sendMessage(player, Captions.NOT_VALID_PLOT_ID); + } else { + this.visit(player, PlotQuery.newQuery().withPlot(plot), null, confirm, whenDone, 1); + } + } } break; case 0: - unsortedPre.addAll(PlotSquared.get().getPlots(player)); - pageConsumer.accept(1); + // /p v + this.visit(player, PlotQuery.newQuery().ownedBy(player), null, confirm, whenDone); break; default: - } + return CompletableFuture.completedFuture(true); } + public Collection tab(PlotPlayer player, String[] args, boolean space) { + final List completions = new LinkedList<>(); + switch (args.length - 1) { + case 0: + this.completeNumbers(completions, args[0], 0); + completions.addAll(TabCompletions.completePlayers(args[0], Collections.emptyList())); + break; + case 1: + if (MathMan.isInteger(args[0])) { + break; + } + this.completeNumbers(completions, args[1], 0); + this.completeAreas(completions, args[1]); + break; + case 2: + if (MathMan.isInteger(args[1])) { + break; + } + this.completeNumbers(completions, args[2], 0); + break; + } + + return completions; + } + + private void completeNumbers(final List commands, final String arg, final int start) { + for (int i = 0; i < 100; i++) { + final String command = Integer.toString(start + 1); + if (!command.toLowerCase().startsWith(arg.toLowerCase())) { + continue; + } + commands.add(new Command(this, false, command, "", + RequiredType.NONE, CommandCategory.TELEPORT) {}); + } + } + + private void completeAreas(final List commands, final String arg) { + for (final PlotArea area : PlotSquared.get().getPlotAreas()) { + final String areaName = area.getWorldName() + ";" + area.getId(); + if (!areaName.toLowerCase().startsWith(arg.toLowerCase())) { + continue; + } + commands.add(new Command(this, false, area.getWorldName() + ";" + area.getId(), "", + RequiredType.NONE, CommandCategory.TELEPORT) {}); + } + } + } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 98cb8b9ce..26515db06 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -445,6 +445,7 @@ public enum Captions implements Caption { NOT_VALID_WORLD("$2That is not a valid world (case sensitive)", "Errors"), NOT_VALID_PLOT_WORLD("$2That is not a valid plot area (case sensitive)", "Errors"), NO_PLOTS("$2You don't have any plots", "Errors"), + PLAYER_NO_PLOTS("$2That player does not own any plots", "Errors"), WAIT_FOR_TIMER("$2A set block timer is bound to either the current plot or you. Please wait for it to finish", "Errors"), TILE_ENTITY_CAP_REACHED("$2The total number of tile entities in this chunk may not exceed $1%s", "Errors"), // @@ -785,6 +786,17 @@ public enum Captions implements Caption { GENERIC_INVALID_CHOICE("invalid choice", "Generic"), // + // + SINGLE_AREA_MISSING_SELECTION("$2Error! You need to select a square region", "Single"), + SINGLE_AREA_NOT_SQUARE("$2Error! Your selection needs to be a square", "Single"), + SINGLE_AREA_OVERLAPPING("$2Error! Your selection overlaps with an existing plot area", "Single"), + SINGLE_AREA_NEEDS_NAME("$2Error! Please specify a plot name: /plot area single ", "Single"), + SINGLE_AREA_NAME_TAKEN("$2Error! The plot name is already taken", "Single"), + SINGLE_AREA_FAILED_TO_SAVE("$2Error! Failed to save the area schematic", "Single"), + SINGLE_AREA_COULD_NOT_MAKE_DIRECTORIES("$2Error! Failed to create the schematic directory", "Single"), + SINGLE_AREA_CREATED("$1The area was created successfully!", "Single"), + // + /** * Legacy Configuration Conversion */ diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index e5bbd3180..78b7c6e37 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -506,7 +506,7 @@ public class Settings extends Config { @Comment("Settings relating to PlotSquared's GlobalBlockQueue") public static final class QUEUE { - @Comment({"Average time per tick spent completing chunk tasks in ms. Target average TPS = 20 * 50 / TARGET_TIME.", + @Comment({"Average time per tick spent completing chunk tasks in ms.", "Waits (chunk task time / target_time) ticks before completely the next task."}) public static int TARGET_TIME = 65; } diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java index da7f46a47..49a5c0da4 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java @@ -195,8 +195,16 @@ public class HybridPlotWorld extends ClassicPlotWorld { public void setupSchematics() throws SchematicHandler.UnsupportedFormatException { this.G_SCH = new HashMap<>(); this.G_SCH_B = new HashMap<>(); - File root = MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), - "schematics/GEN_ROAD_SCHEMATIC/" + this.getWorldName()); + + // Try to determine root. This means that plot areas can have separate schematic + // directories + File root; + if (!(root = MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), "schematics/GEN_ROAD_SCHEMATIC/" + + this.getWorldName() + "/" + this.getId())).exists()) { + root = MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), + "schematics/GEN_ROAD_SCHEMATIC/" + this.getWorldName()); + } + File schematic1File = new File(root, "sideroad.schem"); if (!schematic1File.exists()) schematic1File = new File(root, "sideroad.schematic"); @@ -272,37 +280,8 @@ public class HybridPlotWorld extends ClassicPlotWorld { (short) (z + shift + oddshift + centerShiftZ), biome); } } -/* HashMap items = schematic3.getTiles(); - if (!items.isEmpty()) { - this.G_SCH_STATE = new HashMap<>(); - outer: - for (Map.Entry entry : items.entrySet()) { - BlockLoc loc = entry.getKey(); - short x = (short) (loc.x + shift + oddshift + centerShiftX); - short z = (short) (loc.z + shift + oddshift + centerShiftZ); - short y = (short) (loc.y + this.PLOT_HEIGHT); - int pair = MathMan.pair(x, z); - HashMap existing = this.G_SCH_STATE.get(pair); - if (existing == null) { - existing = new HashMap<>(); - this.G_SCH_STATE.put(pair, existing); - } - existing.put((int) y, entry.getValue()); - CompoundTag tag = entry.getValue(); - Map map = ReflectionUtils.getMap(tag.getValue()); - for (int i = 1; i <= 4; i++) { - String ln = tag.getString("Line" + i); - if (ln == null || ln.length() > 11) - continue outer; - } - SIGN_LOCATION = - new Location(worldname, loc.x + centerShiftX, this.PLOT_HEIGHT + loc.y, - loc.z + centerShiftZ); - ALLOW_SIGNS = true; - continue outer; - } - }*/ + PlotSquared.debug(Captions.PREFIX + "&3 - plot schematic: &7" + schematic3File.getPath()); } if (schematic1 == null || schematic2 == null || this.ROAD_WIDTH == 0) { PlotSquared.debug(Captions.PREFIX + "&3 - schematic: &7false"); diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java b/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java index 45749d9e1..fc2c12453 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java @@ -1023,7 +1023,7 @@ public abstract class PlotArea { * @return true if plot signs are allow, false otherwise. */ public boolean allowSigns() { - return allowSigns; + return allowSigns && (this.plots.size() > 1) /* Do not generate signs for single plots */; } /** diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotFilter.java b/Core/src/main/java/com/plotsquared/core/plot/PlotFilter.java index f7433a2ae..9319c048e 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotFilter.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotFilter.java @@ -25,7 +25,10 @@ */ package com.plotsquared.core.plot; -public abstract class PlotFilter { +/** + * Use {@link com.plotsquared.core.util.query.PlotQuery} instead + */ +@Deprecated public abstract class PlotFilter { public boolean allowsArea(final PlotArea area) { return true; } @@ -33,4 +36,5 @@ public abstract class PlotFilter { public boolean allowsPlot(final Plot plot) { return true; } + } diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java new file mode 100644 index 000000000..ed7b854c2 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java @@ -0,0 +1,105 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.plot; + +import com.plotsquared.core.location.Location; +import com.sk89q.worldedit.regions.CuboidRegion; +import lombok.EqualsAndHashCode; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * A world that contains plots + */ +@EqualsAndHashCode +public abstract class PlotWorld { + + private final String world; + + /** + * Create a new plot world with a given world name + * + * @param world World name + */ + protected PlotWorld(@NotNull final String world) { + this.world = world; + } + + /** + * Get the plot area that contains the given location, or null + * if the location is not a part of a plot area. + * + * @param location Location + * @return Containing plot area, or null + */ + @Nullable public abstract PlotArea getArea(@NotNull final Location location); + + /** + * Get all plot areas in the world + * + * @return All plot areas in the world + */ + @NotNull public abstract Collection getAreas(); + + /** + * Get all plot areas in a specified region + * + * @param region Region + * @return All areas in the region + */ + @NotNull public abstract Collection getAreasInRegion( + @NotNull final CuboidRegion region); + + /** + * Register a new area in the world + * + * @param area Plot area + */ + public void addArea(@NotNull final PlotArea area) { + throw new UnsupportedOperationException("This world type does not allow adding new areas"); + } + + /** + * Remove an area from the world + * + * @param area Plot area + */ + public void removeArea(@NotNull final PlotArea area) { + throw new UnsupportedOperationException("This world type does not allow removing areas"); + } + + /** + * Get the world name + * + * @return World name + */ + public String getWorld() { + return this.world; + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java index 833bf3d4f..9ce0b1623 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java @@ -25,143 +25,93 @@ */ package com.plotsquared.core.plot.world; -import com.plotsquared.core.collection.QuadMap; import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotAreaType; +import com.plotsquared.core.plot.PlotWorld; import com.plotsquared.core.util.StringMan; import com.sk89q.worldedit.regions.CuboidRegion; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; import java.util.Set; public class DefaultPlotAreaManager implements PlotAreaManager { final PlotArea[] noPlotAreas = new PlotArea[0]; - // All plot areas mapped by world - private final HashMap plotAreaMap = new HashMap<>(); - // All plot areas mapped by position - private final HashMap> plotAreaGrid = new HashMap<>(); - private final HashSet plotAreaHashCheck = new HashSet<>(); - // All plot areas - private PlotArea[] plotAreas = new PlotArea[0]; - // Optimization if there are no hash collisions - private boolean plotAreaHasCollision = false; - private String[] worlds = new String[0]; + private final Map plotWorlds = new HashMap<>(); @Override public PlotArea[] getAllPlotAreas() { - return plotAreas; - } - - @Override public PlotArea getApplicablePlotArea(Location location) { - switch (this.plotAreas.length) { - case 0: - return null; - case 1: - return this.plotAreas[0].getWorldHash() == location.getWorld().hashCode() - && this.plotAreas[0].contains(location) && (!this.plotAreaHasCollision - || location.getWorld().equals(this.plotAreas[0].getWorldName())) ? - this.plotAreas[0] : - null; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - String world = location.getWorld(); - int hash = world.hashCode(); - for (PlotArea area : this.plotAreas) { - if (hash == area.getWorldHash()) { - if (area.contains(location.getX(), location.getZ()) && ( - !this.plotAreaHasCollision || world.equals(area.getWorldName()))) { - return area; - } - } - } - return null; - default: - PlotArea[] areas = this.plotAreaMap.get(location.getWorld()); - if (areas == null) { - return null; - } - int z; - int x; - switch (areas.length) { - case 1: - return areas[0]; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - x = location.getX(); - z = location.getZ(); - for (PlotArea area : areas) { - if (area.contains(x, z)) { - return area; - } - } - return null; - default: - QuadMap search = this.plotAreaGrid.get(location.getWorld()); - return search.get(location.getX(), location.getZ()); - } + final Set area = new HashSet<>(); + for (final PlotWorld world : plotWorlds.values()) { + area.addAll(world.getAreas()); } + return area.toArray(new PlotArea[0]); } - @Override public void addPlotArea(PlotArea plotArea) { - HashSet localAreas = - new HashSet<>(Arrays.asList(getPlotAreas(plotArea.getWorldName(), null))); - HashSet globalAreas = new HashSet<>(Arrays.asList(plotAreas)); - localAreas.add(plotArea); - globalAreas.add(plotArea); - this.plotAreas = globalAreas.toArray(new PlotArea[0]); - this.plotAreaMap.put(plotArea.getWorldName(), localAreas.toArray(new PlotArea[0])); - QuadMap map = this.plotAreaGrid.get(plotArea.getWorldName()); - if (map == null) { - map = new QuadMap(Integer.MAX_VALUE, 0, 0) { - @Override public CuboidRegion getRegion(PlotArea value) { - return value.getRegion(); - } - }; - this.plotAreaGrid.put(plotArea.getWorldName(), map); + @Override @Nullable public PlotArea getApplicablePlotArea(final Location location) { + if (location == null) { + return null; } - map.add(plotArea); + final PlotWorld world = this.plotWorlds.get(location.getWorld()); + if (world == null) { + return null; + } + return world.getArea(location); } - @Override public void removePlotArea(PlotArea area) { - ArrayList globalAreas = new ArrayList<>(Arrays.asList(plotAreas)); - globalAreas.remove(area); - this.plotAreas = globalAreas.toArray(new PlotArea[0]); - if (globalAreas.isEmpty()) { - this.plotAreaMap.remove(area.getWorldName()); - this.plotAreaGrid.remove(area.getWorldName()); + @Override public void addPlotArea(final PlotArea plotArea) { + PlotWorld world = this.plotWorlds.get(plotArea.getWorldName()); + if (world != null) { + if (world instanceof StandardPlotWorld && world.getAreas().isEmpty()) { + this.plotWorlds.remove(plotArea.getWorldName()); + } else { + world.addArea(plotArea); + return; + } + } + if (plotArea.getType() != PlotAreaType.PARTIAL) { + world = new StandardPlotWorld(plotArea.getWorldName(), plotArea); } else { - this.plotAreaMap.put(area.getWorldName(), globalAreas.toArray(new PlotArea[0])); - this.plotAreaGrid.get(area.getWorldName()).remove(area); + world = new ScatteredPlotWorld(plotArea.getWorldName()); + world.addArea(plotArea); + } + this.plotWorlds.put(plotArea.getWorldName(), world); + } + + @Override public void removePlotArea(final PlotArea area) { + final PlotWorld world = this.plotWorlds.get(area.getWorldName()); + if (world == null) { + return; + } + if (world instanceof StandardPlotWorld) { + this.plotWorlds.remove(world.getWorld()); + } else { + world.removeArea(area); + if (world.getAreas().isEmpty()) { + this.plotWorlds.remove(world.getWorld()); + } } } - @Override public PlotArea getPlotArea(String world, String id) { - PlotArea[] areas = this.plotAreaMap.get(world); - if (areas == null) { + @Override public PlotArea getPlotArea(final String world, final String id) { + final PlotWorld plotWorld = this.plotWorlds.get(world); + if (plotWorld == null) { return null; } - if (areas.length == 1) { - return areas[0]; - } else if (id == null) { + final List areas = new ArrayList<>(plotWorld.getAreas()); + if (areas.size() == 1) { + return areas.get(0); + } + if (id == null) { return null; } - for (PlotArea area : areas) { + for (final PlotArea area : areas) { if (StringMan.isEqual(id, area.getId())) { return area; } @@ -169,103 +119,37 @@ public class DefaultPlotAreaManager implements PlotAreaManager { return null; } - @Override public PlotArea getPlotArea(@NotNull Location location) { - switch (this.plotAreas.length) { - case 0: - return null; - case 1: - PlotArea pa = this.plotAreas[0]; - if (pa.contains(location)) { - return pa; - } else { - return null; - } - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - String world = location.getWorld(); - int hash = world.hashCode(); - for (PlotArea area : this.plotAreas) { - if (hash == area.getWorldHash()) { - if (area.contains(location.getX(), location.getZ()) && ( - !this.plotAreaHasCollision || world.equals(area.getWorldName()))) { - return area; - } - } - } - return null; - default: - PlotArea[] areas = this.plotAreaMap.get(location.getWorld()); - if (areas == null) { - return null; - } - int x; - int z; - switch (areas.length) { - case 0: - PlotArea a = areas[0]; - return a.contains(location.getX(), location.getZ()) ? a : null; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - x = location.getX(); - z = location.getZ(); - for (PlotArea area : areas) { - if (area.contains(x, z)) { - return area; - } - } - return null; - default: - QuadMap search = this.plotAreaGrid.get(location.getWorld()); - return search.get(location.getX(), location.getZ()); - } - } + @Override public PlotArea getPlotArea(@NotNull final Location location) { + return this.getApplicablePlotArea(location); } - @Override public PlotArea[] getPlotAreas(String world, CuboidRegion region) { - if (region == null) { - PlotArea[] areas = this.plotAreaMap.get(world); - if (areas == null) { - return noPlotAreas; - } - return areas; - } - QuadMap areas = this.plotAreaGrid.get(world); - if (areas == null) { + @Override public PlotArea[] getPlotAreas(final String world, final CuboidRegion region) { + final PlotWorld plotWorld = this.plotWorlds.get(world); + if (plotWorld == null) { return noPlotAreas; - } else { - Set found = areas.get(region); - return found.toArray(new PlotArea[0]); } + if (region == null) { + return plotWorld.getAreas().toArray(new PlotArea[0]); + } + return plotWorld.getAreasInRegion(region).toArray(new PlotArea[0]); } - @Override public void addWorld(String worldName) { - if (!this.plotAreaHasCollision && !this.plotAreaHashCheck.add(worldName.hashCode())) { - this.plotAreaHasCollision = true; + @Override public void addWorld(final String worldName) { + PlotWorld world = this.plotWorlds.get(worldName); + if (world != null) { + return; } - Set tmp = new LinkedHashSet<>(); - Collections.addAll(tmp, worlds); - tmp.add(worldName); - worlds = tmp.toArray(new String[0]); + // Create a new empty world. When a new area is added + // the world will be re-recreated with the correct type + world = new StandardPlotWorld(worldName, null); + this.plotWorlds.put(worldName, world); } - @Override public void removeWorld(String worldName) { - Set tmp = new LinkedHashSet<>(); - Collections.addAll(tmp, worlds); - tmp.remove(worldName); - worlds = tmp.toArray(new String[0]); + @Override public void removeWorld(final String worldName) { + this.plotWorlds.remove(worldName); } @Override public String[] getAllWorlds() { - return worlds; + return this.plotWorlds.keySet().toArray(new String[0]); } } diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java index b6d23b3d4..34033cb2b 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java @@ -29,6 +29,7 @@ import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.PlotArea; import com.sk89q.worldedit.regions.CuboidRegion; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface PlotAreaManager { @@ -44,7 +45,7 @@ public interface PlotAreaManager { * @param location The location * @return An applicable area, or null */ - PlotArea getApplicablePlotArea(Location location); + @Nullable PlotArea getApplicablePlotArea(Location location); /** * Get the plot area, if there is any, for the given diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java new file mode 100644 index 000000000..9f245a5ba --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java @@ -0,0 +1,116 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.plot.world; + +import com.github.davidmoten.rtree.Entry; +import com.github.davidmoten.rtree.RTree; +import com.github.davidmoten.rtree.geometry.Geometries; +import com.github.davidmoten.rtree.geometry.Geometry; +import com.plotsquared.core.location.Location; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotWorld; +import com.plotsquared.core.util.RegionUtil; +import com.sk89q.worldedit.regions.CuboidRegion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import rx.Observable; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * Plot world that contains several plot areas (clusters) + */ +public class ScatteredPlotWorld extends PlotWorld { + + private final List areas = new LinkedList<>(); + private final Object treeLock = new Object(); + private RTree areaTree; + + /** + * Create a new plot world with a given world name + * + * @param world World name + */ + public ScatteredPlotWorld(@NotNull final String world) { + super(world); + } + + @Override @Nullable public PlotArea getArea(@NotNull final Location location) { + if (this.areas.isEmpty()) { + return null; + } + synchronized (this.treeLock) { + final Observable> area = + areaTree.search(Geometries.point(location.getX(), location.getZ())); + if (area.isEmpty().toBlocking().first()) { + return null; + } + return area.toBlocking().first().value(); + } + } + + @Override @NotNull public Collection getAreas() { + return Collections.unmodifiableCollection(this.areas); + } + + @Override public void addArea(@NotNull final PlotArea area) { + this.areas.add(area); + this.buildTree(); + } + + @Override public void removeArea(@NotNull final PlotArea area) { + this.areas.remove(area); + this.buildTree(); + } + + @Override @NotNull public Collection getAreasInRegion(@NotNull final CuboidRegion region) { + if (this.areas.isEmpty()) { + return Collections.emptyList(); + } + synchronized (this.treeLock) { + final List areas = new LinkedList<>(); + this.areaTree.search(RegionUtil.toRectangle(region)).toBlocking().forEach(entry -> areas.add(entry.value())); + return areas; + } + } + + /** + * Rebuild the area tree + */ + private void buildTree() { + synchronized (this.treeLock) { + this.areaTree = RTree.create(); + for (final PlotArea area : areas) { + this.areaTree = this.areaTree.add(area, + RegionUtil.toRectangle(area.getRegion())); + } + } + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java new file mode 100644 index 000000000..162cf0e9f --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java @@ -0,0 +1,65 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.plot.world; + +import com.plotsquared.core.location.Location; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotWorld; +import com.sk89q.worldedit.regions.CuboidRegion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; + +/** + * Ordinary plot world with a single plot area + */ +public class StandardPlotWorld extends PlotWorld { + + private final PlotArea area; + + public StandardPlotWorld(@NotNull final String world, @Nullable final PlotArea area) { + super(world); + this.area = area; + } + + @Override @Nullable public PlotArea getArea(@NotNull final Location location) { + return this.area; + } + + @Override @NotNull public Collection getAreas() { + if (this.area == null) { + return Collections.emptyList(); + } + return Collections.singletonList(this.area); + } + + @Override @NotNull public Collection getAreasInRegion(@NotNull final CuboidRegion region) { + return this.getAreas(); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java b/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java index 7bbea34d1..3e052737a 100644 --- a/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java @@ -52,7 +52,7 @@ public abstract class ChunkManager { public static void setChunkInPlotArea(RunnableVal force, RunnableVal add, String world, BlockVector2 loc) { LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false); - if (PlotSquared.get().isAugmented(world)) { + if (PlotSquared.get().isAugmented(world) && PlotSquared.get().isNonStandardGeneration(world, loc)) { int blockX = loc.getX() << 4; int blockZ = loc.getZ() << 4; ScopedLocalBlockQueue scoped = diff --git a/Core/src/main/java/com/plotsquared/core/util/PlatformWorldManager.java b/Core/src/main/java/com/plotsquared/core/util/PlatformWorldManager.java index f57e42a21..c304ff04c 100644 --- a/Core/src/main/java/com/plotsquared/core/util/PlatformWorldManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/PlatformWorldManager.java @@ -28,6 +28,8 @@ package com.plotsquared.core.util; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; + /** * This class should be implemented by each platform to allow PlotSquared to interact * with the world management solution used on the server. @@ -62,4 +64,11 @@ public interface PlatformWorldManager { */ String getName(); + /** + * Get the names of all worlds on the server + * + * @return Worlds + */ + Collection getWorlds(); + } diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java b/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java index fe4d83a96..59b14651a 100644 --- a/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java @@ -25,9 +25,13 @@ */ package com.plotsquared.core.util; +import com.github.davidmoten.rtree.geometry.Geometries; +import com.github.davidmoten.rtree.geometry.Rectangle; import com.plotsquared.core.plot.Plot; +import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; +import org.jetbrains.annotations.NotNull; public class RegionUtil { public static CuboidRegion createRegion(int pos1x, int pos2x, int pos1z, int pos2z) { @@ -54,6 +58,12 @@ public class RegionUtil { .getY() && y <= max.getY(); } + @NotNull public static Rectangle toRectangle(@NotNull final CuboidRegion region) { + final BlockVector2 min = region.getMinimumPoint().toBlockVector2(); + final BlockVector2 max = region.getMaximumPoint().toBlockVector2(); + return Geometries.rectangle(min.getX(), min.getZ(), max.getX(), max.getZ()); + } + // Because WE (not fawe) lack this for CuboidRegion public static boolean intersects(CuboidRegion region, CuboidRegion other) { BlockVector3 regionMin = region.getMinimumPoint(); diff --git a/Core/src/main/java/com/plotsquared/core/util/query/AliasFilter.java b/Core/src/main/java/com/plotsquared/core/util/query/AliasFilter.java new file mode 100644 index 000000000..808f34797 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/AliasFilter.java @@ -0,0 +1,43 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +class AliasFilter implements PlotFilter { + + private final String alias; + + AliasFilter(@NotNull final String alias) { + this.alias = alias; + } + + @Override public boolean accepts(@NotNull final Plot plot) { + return this.alias.equalsIgnoreCase(plot.getAlias()); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java new file mode 100644 index 000000000..2a6e88171 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java @@ -0,0 +1,51 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.PlotArea; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +class AreaLimitedPlotProvider implements PlotProvider { + + private final Collection areas; + + AreaLimitedPlotProvider(Collection areas) { + this.areas = areas; + } + + @Override public Collection getPlots() { + final List plots = new LinkedList<>(); + for (final PlotArea area : areas) { + plots.addAll(area.getPlots()); + } + return plots; + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/ExpiredPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/ExpiredPlotProvider.java new file mode 100644 index 000000000..9b369dc4e --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/ExpiredPlotProvider.java @@ -0,0 +1,39 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.expiration.ExpireManager; + +import java.util.Collection; + +class ExpiredPlotProvider implements PlotProvider { + + @Override public Collection getPlots() { + return ExpireManager.IMP.getPendingExpired(); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/FixedPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/FixedPlotProvider.java new file mode 100644 index 000000000..3bf79c783 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/FixedPlotProvider.java @@ -0,0 +1,46 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Collections; + +class FixedPlotProvider implements PlotProvider { + + private final Plot plot; + + FixedPlotProvider(@NotNull final Plot plot) { + this.plot = plot; + } + + @Override public Collection getPlots() { + return Collections.singleton(plot); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java new file mode 100644 index 000000000..3fb2420c5 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java @@ -0,0 +1,39 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.plot.Plot; + +import java.util.Collection; + +class GlobalPlotProvider implements PlotProvider { + + @Override public Collection getPlots() { + return PlotSquared.get().getPlots(); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/MemberFilter.java b/Core/src/main/java/com/plotsquared/core/util/query/MemberFilter.java new file mode 100644 index 000000000..3f9670d08 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/MemberFilter.java @@ -0,0 +1,45 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +class MemberFilter implements PlotFilter { + + @NotNull private final UUID uuid; + + MemberFilter(@NotNull final UUID uuid) { + this.uuid = uuid; + } + + @Override public boolean accepts(@NotNull final Plot plot) { + return plot.isAdded(uuid); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/NullProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/NullProvider.java new file mode 100644 index 000000000..6cf3a70d4 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/NullProvider.java @@ -0,0 +1,39 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; + +import java.util.Collection; +import java.util.Collections; + +class NullProvider implements PlotProvider { + + @Override public Collection getPlots() { + return Collections.emptyList(); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/OwnerFilter.java b/Core/src/main/java/com/plotsquared/core/util/query/OwnerFilter.java new file mode 100644 index 000000000..cae258722 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/OwnerFilter.java @@ -0,0 +1,46 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.UUID; + +class OwnerFilter implements PlotFilter { + + private final UUID owner; + + OwnerFilter(@NotNull final UUID owner) { + this.owner = owner; + } + + @Override public boolean accepts(@NotNull final Plot plot) { + return plot.hasOwner() && Objects.equals(plot.getOwnerAbs(), this.owner); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PaginatedPlotResult.java b/Core/src/main/java/com/plotsquared/core/util/query/PaginatedPlotResult.java new file mode 100644 index 000000000..2c0ed9152 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PaginatedPlotResult.java @@ -0,0 +1,73 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.google.common.base.Preconditions; +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +/** + * Paginated collection of plots as a result of a {@link PlotQuery query} + */ +public final class PaginatedPlotResult { + + private final List plots; + private final int pageSize; + + PaginatedPlotResult(@NotNull final List plots, final int pageSize) { + this.plots = plots; + this.pageSize = pageSize; + } + + /** + * Get the plots belonging to a certain page. + * + * @param page Positive page number. Indexed from 1 + * @return Plots that belong to the specified page + */ + public List getPage(final int page) { + Preconditions.checkState(page >= 0, "Page must be positive"); + final int from = (page - 1) * this.pageSize; + if (this.plots.size() < from) { + return Collections.emptyList(); + } + final int to = Math.max(from + pageSize, this.plots.size()); + return this.plots.subList(from, to); + } + + /** + * Get the number of available pages + * + * @return Available pages + */ + public int getPages() { + return (int) Math.ceil((double) plots.size() / (double) pageSize); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotFilter.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotFilter.java new file mode 100644 index 000000000..c017b21b0 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotFilter.java @@ -0,0 +1,41 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Predicate; + +@FunctionalInterface interface PlotFilter extends Predicate { + + @Override default boolean test(@NotNull final Plot plot) { + return this.accepts(plot); + } + + boolean accepts(@NotNull final Plot plot); + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java new file mode 100644 index 000000000..c8048da1a --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java @@ -0,0 +1,36 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; + +import java.util.Collection; + +@FunctionalInterface interface PlotProvider { + + Collection getPlots(); + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java new file mode 100644 index 000000000..40d883062 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -0,0 +1,385 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.google.common.base.Preconditions; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.Rating; +import com.plotsquared.core.plot.flag.implementations.DoneFlag; +import com.plotsquared.core.util.MathMan; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.function.Predicate; +import java.util.stream.Stream; + +/** + * This represents a plot query, and can be used to + * search for plots matching certain criteria. + *

+ * The queries can be reused as no results are stored + * in the query itself + */ +public final class PlotQuery { + + private final Collection filters = new LinkedList<>(); + private PlotProvider plotProvider = new GlobalPlotProvider(); + private SortingStrategy sortingStrategy = SortingStrategy.NO_SORTING; + private PlotArea priorityArea; + private Comparator plotComparator; + + private PlotQuery() { + } + + /** + * Create a new plot query instance + * + * @return New query + */ + public static PlotQuery newQuery() { + return new PlotQuery(); + } + + /** + * Query for plots in a single area + * + * @param area Area + * @return The query instance + */ + @NotNull public PlotQuery inArea(@NotNull final PlotArea area) { + Preconditions.checkNotNull(area, "Area may not be null"); + this.plotProvider = new AreaLimitedPlotProvider(Collections.singletonList(area)); + return this; + } + + /** + * Query for plots in all areas in a world + * + * @param world World name + * @return The query instance + */ + @NotNull public PlotQuery inWorld(@NotNull final String world) { + Preconditions.checkNotNull(world, "World may not be null"); + this.plotProvider = new AreaLimitedPlotProvider(PlotSquared.get().getPlotAreas(world)); + return this; + } + + /** + * Query for plots in specific areas + * + * @param areas Plot areas + * @return The query instance + */ + @NotNull public PlotQuery inAreas(@NotNull final Collection areas) { + Preconditions.checkNotNull(areas, "Areas may not be null"); + Preconditions.checkState(!areas.isEmpty(), "At least one area must be provided"); + this.plotProvider = new AreaLimitedPlotProvider(Collections.unmodifiableCollection(areas)); + return this; + } + + /** + * Query for expired plots + * + * @return The query instance + */ + @NotNull public PlotQuery expiredPlots() { + this.plotProvider = new ExpiredPlotProvider(); + return this; + } + + /** + * Query for all plots + * + * @return The query instance + */ + @NotNull public PlotQuery allPlots() { + this.plotProvider = new GlobalPlotProvider(); + return this; + } + + /** + * Don't query at all + * + * @return The query instance + */ + @NotNull public PlotQuery noPlots() { + this.plotProvider = new NullProvider(); + return this; + } + + /** + * Query for plots based on a search term + * + * @return The query instance + */ + @NotNull public PlotQuery plotsBySearch(@NotNull final String searchTerm) { + Preconditions.checkNotNull(searchTerm, "Search term may not be null"); + this.plotProvider = new SearchPlotProvider(searchTerm); + return this; + } + + /** + * Query with a pre-defined result + * + * @return The query instance + */ + @NotNull public PlotQuery withPlot(@NotNull final Plot plot) { + Preconditions.checkNotNull(plot, "Plot may not be null"); + this.plotProvider = new FixedPlotProvider(plot); + return this; + } + + /** + * Query for base plots only + * + * @return The query instance + */ + @NotNull public PlotQuery whereBasePlot() { + return this.addFilter(new PredicateFilter(Plot::isBasePlot)); + } + + /** + * Query for plots owned by a specific player + * + * @param owner Owner UUID + * @return The query instance + */ + @NotNull public PlotQuery ownedBy(@NotNull final UUID owner) { + Preconditions.checkNotNull(owner, "Owner may not be null"); + return this.addFilter(new OwnerFilter(owner)); + } + + /** + * Query for plots owned by a specific player + * + * @param owner Owner + * @return The query instance + */ + @NotNull public PlotQuery ownedBy(@NotNull final PlotPlayer owner) { + Preconditions.checkNotNull(owner, "Owner may not be null"); + return this.addFilter(new OwnerFilter(owner.getUUID())); + } + + /** + * Query for plots with a specific alias + * + * @param alias Plot alias + * @return The query instance + */ + @NotNull public PlotQuery withAlias(@NotNull final String alias) { + Preconditions.checkNotNull(alias, "Alias may not be null"); + return this.addFilter(new AliasFilter(alias)); + } + + /** + * Query for plots with a specific member (added/trusted/owner) + * + * @param member Member UUID + * @return The query instance + */ + @NotNull public PlotQuery withMember(@NotNull final UUID member) { + Preconditions.checkNotNull(member, "Member may not be null"); + return this.addFilter(new MemberFilter(member)); + } + + /** + * Query for plots that passes a given predicate + * + * @param predicate Predicate + * @return The query instance + */ + @NotNull public PlotQuery thatPasses(@NotNull final Predicate predicate) { + Preconditions.checkNotNull(predicate, "Predicate may not be null"); + return this.addFilter(new PredicateFilter(predicate)); + } + + /** + * Specify the sorting strategy that will decide how to + * sort the results. This only matters if you use {@link #asList()} + * + * @param strategy Strategy + * @return The query instance + */ + @NotNull public PlotQuery withSortingStrategy(@NotNull final SortingStrategy strategy) { + Preconditions.checkNotNull(strategy, "Strategy may not be null"); + this.sortingStrategy = strategy; + return this; + } + + /** + * Use a custom comparator to sort the results + * + * @param comparator Comparator + * @return The query instance + */ + @NotNull public PlotQuery sorted(@NotNull final Comparator comparator) { + Preconditions.checkNotNull(comparator, "Comparator may not be null"); + this.sortingStrategy = SortingStrategy.COMPARATOR; + this.plotComparator = comparator; + return this; + } + + /** + * Defines the area around which plots may be sorted, depending on the + * sorting strategy + * + * @param plotArea Plot area + * @return The query instance + */ + @NotNull public PlotQuery relativeToArea(@NotNull final PlotArea plotArea) { + Preconditions.checkNotNull(plotArea, "Area may not be null"); + this.priorityArea = plotArea; + return this; + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots + */ + @NotNull public Stream asStream() { + return this.asList().stream(); + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots as a mutable + */ + @NotNull public List asList() { + final List result; + if (this.filters.isEmpty()) { + result = new ArrayList<>(this.plotProvider.getPlots()); + } else { + final Collection plots = this.plotProvider.getPlots(); + result = new ArrayList<>(plots.size()); + outer: for (final Plot plot : plots) { + for (final PlotFilter filter : this.filters) { + if (!filter.accepts(plot)) { + continue outer; + } + } + result.add(plot); + } + } + if (this.sortingStrategy == SortingStrategy.NO_SORTING) { + return result; + } else if (this.sortingStrategy == SortingStrategy.SORT_BY_TEMP) { + return PlotSquared.get().sortPlotsByTemp(result); + } else if (this.sortingStrategy == SortingStrategy.SORT_BY_DONE) { + result.sort((a, b) -> { + String va = a.getFlag(DoneFlag.class); + String vb = b.getFlag(DoneFlag.class); + if (MathMan.isInteger(va)) { + if (MathMan.isInteger(vb)) { + return Integer.parseInt(vb) - Integer.parseInt(va); + } + return -1; + } + return 1; + }); + } else if (this.sortingStrategy == SortingStrategy.SORT_BY_RATING) { + result.sort((p1, p2) -> { + double v1 = 0; + int p1s = p1.getSettings().getRatings().size(); + int p2s = p2.getRatings().size(); + if (!p1.getSettings().getRatings().isEmpty()) { + v1 = p1.getRatings().values().stream().mapToDouble(Rating::getAverageRating) + .map(av -> av * av).sum(); + v1 /= p1s; + v1 += p1s; + } + double v2 = 0; + if (!p2.getSettings().getRatings().isEmpty()) { + for (Map.Entry entry : p2.getRatings().entrySet()) { + double av = entry.getValue().getAverageRating(); + v2 += av * av; + } + v2 /= p2s; + v2 += p2s; + } + if (v2 == v1 && v2 != 0) { + return p2s - p1s; + } + return (int) Math.signum(v2 - v1); + }); + } else if (this.sortingStrategy == SortingStrategy.SORT_BY_CREATION) { + return PlotSquared.get().sortPlots(result, PlotSquared.SortType.CREATION_DATE, this.priorityArea); + } else if (this.sortingStrategy == SortingStrategy.COMPARATOR) { + result.sort(this.plotComparator); + } + return result; + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots as a mutable set + */ + @NotNull public Set asSet() { + return new HashSet<>(this.asList()); + } + + /** + * Get all plots that match the given criteria + * in the form of a {@link PaginatedPlotResult} + * + * @param pageSize The size of the pages. Must be positive. + * @return Paginated plot result + */ + @NotNull public PaginatedPlotResult getPaginated(final int pageSize) { + Preconditions.checkState(pageSize > 0, "Page size must be greater than 0"); + return new PaginatedPlotResult(this.asList(), pageSize); + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots as an immutable collection + */ + @NotNull public Collection asCollection() { + return this.asList(); + } + + @NotNull private PlotQuery addFilter(@NotNull final PlotFilter filter) { + this.filters.add(filter); + return this; + } + + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PredicateFilter.java b/Core/src/main/java/com/plotsquared/core/util/query/PredicateFilter.java new file mode 100644 index 000000000..dd68f081d --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PredicateFilter.java @@ -0,0 +1,45 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Predicate; + +class PredicateFilter implements PlotFilter { + + private final Predicate predicate; + + PredicateFilter(@NotNull final Predicate predicate) { + this.predicate = predicate; + } + + @Override public boolean accepts(@NotNull final Plot plot) { + return predicate.test(plot); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/SearchPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/SearchPlotProvider.java new file mode 100644 index 000000000..91193a79e --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/SearchPlotProvider.java @@ -0,0 +1,46 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.util.MainUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +class SearchPlotProvider implements PlotProvider { + + private final String searchTerm; + + SearchPlotProvider(@NotNull final String searchTerm) { + this.searchTerm = searchTerm; + } + + @Override public Collection getPlots() { + return MainUtil.getPlotsBySearch(this.searchTerm); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java b/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java new file mode 100644 index 000000000..7a70b46fd --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java @@ -0,0 +1,56 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.util.query; + +/** + * Strategy used when sorting plot results + */ +public enum SortingStrategy { + /** + * Plots won't be sorted at all + */ + NO_SORTING, + /** + * Sort by the temporary (magic) plot ID + */ + SORT_BY_TEMP, + /** + * Sort by the value in the plot's {@link com.plotsquared.core.plot.flag.implementations.DoneFlag} + */ + SORT_BY_DONE, + /** + * Sort by the plot rating + */ + SORT_BY_RATING, + /** + * Sort by creation date + */ + SORT_BY_CREATION, + /** + * Sort using a comparator + */ + COMPARATOR; +} diff --git a/README.md b/README.md index 17dc0331c..64a012710 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ is to provide a lag-free and smooth experience. * [Download](https://www.spigotmc.org/resources/plotsquared-v5.77506/) * [Discord](https://discord.gg/KxkjDVg) * [Wiki](https://wiki.intellectualsites.com/plotsquared/home) +* [Issues](https://issues.intellectualsites.com/projects/ps) ### Developer Resources * [API Documentation](https://wiki.intellectualsites.com/en/plotsquared/developer/development-portal)