From bbde2f5e069379a6bb09cca70747dcc7d3c88c4f Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 22 May 2020 10:44:51 +0100 Subject: [PATCH 01/16] Slow down queue a bit because 1.13+ performance is bad --- .../com/plotsquared/core/configuration/Settings.java | 4 ++-- .../com/plotsquared/core/queue/GlobalBlockQueue.java | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) 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 3fbd71394..2be87ada3 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -491,9 +491,9 @@ 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; + public static int TARGET_TIME = 40; } diff --git a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java index 3b63a94c0..6abfea8f8 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java @@ -57,6 +57,7 @@ public class GlobalBlockQueue { private final RunnableVal2 SET_TASK = new RunnableVal2() { @Override public void run(Long free, LocalBlockQueue queue) { + long t1 = System.currentTimeMillis(); do { boolean more = queue.next(); if (!more) { @@ -66,9 +67,9 @@ public class GlobalBlockQueue { } return; } - } while ((lastPeriod = - ((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) - - GlobalBlockQueue.this.last)) < free); + } while (((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) + - GlobalBlockQueue.this.last) < free); + lastPeriod = System.currentTimeMillis() - t1; } }; @@ -124,8 +125,8 @@ public class GlobalBlockQueue { lastPeriod -= targetTime; return; } - SET_TASK.value1 = 50 + Math.min( - (50 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = + SET_TASK.value1 = 30 + Math.min( + (30 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = System.currentTimeMillis()), GlobalBlockQueue.this.secondLast - System.currentTimeMillis()); SET_TASK.value2 = GlobalBlockQueue.this.getNextQueue(); From 1e3379b00a553987026831f6177ff8242e40d0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 21 May 2020 20:06:04 +0200 Subject: [PATCH 02/16] Fix up the plot area nightmare --- Core/build.gradle | 2 + .../com/plotsquared/core/plot/PlotWorld.java | 105 +++++++ .../plot/world/DefaultPlotAreaManager.java | 269 +++++------------- .../core/plot/world/PlotAreaManager.java | 3 +- .../core/plot/world/ScatteredPlotWorld.java | 110 +++++++ .../core/plot/world/StandardPlotWorld.java | 65 +++++ .../com/plotsquared/core/util/RegionUtil.java | 10 + 7 files changed, 372 insertions(+), 192 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java create mode 100644 Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java create mode 100644 Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java 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/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..f86b5b8b6 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,96 @@ */ 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]; + + private final Map plotWorlds = new HashMap<>(); // Optimization if there are no hash collisions private boolean plotAreaHasCollision = false; - private String[] worlds = new String[0]; @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 +122,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..78cb0b7b2 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java @@ -0,0 +1,110 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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) { + 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) { + 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/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(); From dd4c5014fc2eb65540a93f2e89b98ec5eb4f39d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 21 May 2020 20:06:37 +0200 Subject: [PATCH 03/16] Get rid of unused field --- .../plotsquared/core/plot/world/DefaultPlotAreaManager.java | 3 --- 1 file changed, 3 deletions(-) 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 f86b5b8b6..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 @@ -44,10 +44,7 @@ import java.util.Set; public class DefaultPlotAreaManager implements PlotAreaManager { final PlotArea[] noPlotAreas = new PlotArea[0]; - private final Map plotWorlds = new HashMap<>(); - // Optimization if there are no hash collisions - private boolean plotAreaHasCollision = false; @Override public PlotArea[] getAllPlotAreas() { final Set area = new HashSet<>(); From 93619b39888791e9dd37c1d918b16dad60e442d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 21 May 2020 20:23:36 +0200 Subject: [PATCH 04/16] Don't access tree until it has been created --- .../com/plotsquared/core/plot/world/ScatteredPlotWorld.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 index 78cb0b7b2..9f245a5ba 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java @@ -62,6 +62,9 @@ public class ScatteredPlotWorld extends PlotWorld { } @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())); @@ -87,6 +90,9 @@ public class ScatteredPlotWorld extends PlotWorld { } @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())); From d2af342a5d15b43d6b3f19d29796257f93f33b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 02:51:40 +0200 Subject: [PATCH 05/16] Shade r-tree into the bukkit module --- Bukkit/build.gradle | 1 + Core/pom.xml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 9fa1f8cf1..4e69d6a41 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -87,6 +87,7 @@ 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")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") 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 From a833803bdf223793573162448b50688f55bf3ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 02:54:10 +0200 Subject: [PATCH 06/16] Shade rx into the bukkot module --- Bukkit/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 4e69d6a41..1e1f8bb02 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -88,6 +88,7 @@ shadowJar { 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")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") From eee04ab87d272e494b8dd6931ace9f68b6d1ea5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 02:56:23 +0200 Subject: [PATCH 07/16] Shade guava-mini into the bukkot module --- Bukkit/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 1e1f8bb02..5a1c91e20 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -89,6 +89,7 @@ shadowJar { 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")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") From 5e6b27e21f4f6af015917d8b2217dfd005ef4532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 00:33:30 +0200 Subject: [PATCH 08/16] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 17dc0331c..f001d121e 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/6572cc05-7756-4c9e-92de-bd28b9aabc3f) ### Developer Resources * [API Documentation](https://wiki.intellectualsites.com/en/plotsquared/developer/development-portal) From 6090c7ccacc764b5a056a35fe3e9a8fca2e3cf90 Mon Sep 17 00:00:00 2001 From: N0tMyFaultOG Date: Sat, 23 May 2020 01:25:18 +0200 Subject: [PATCH 09/16] Link issues to new issue tracker for legacy reasons --- .github/FUNDING.yml | 2 +- .github/ISSUE_TEMPLATE.md | 3 +- .../bug-issue-report-for-plotsquared.md | 101 ------------------ .github/ISSUE_TEMPLATE/config.yml | 3 + README.md | 2 +- 5 files changed, 7 insertions(+), 104 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug-issue-report-for-plotsquared.md 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/README.md b/README.md index f001d121e..64a012710 100644 --- a/README.md +++ b/README.md @@ -28,7 +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/6572cc05-7756-4c9e-92de-bd28b9aabc3f) +* [Issues](https://issues.intellectualsites.com/projects/ps) ### Developer Resources * [API Documentation](https://wiki.intellectualsites.com/en/plotsquared/developer/development-portal) From e912909aade0eff98e66c093d4b64346d36b44b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 22:20:57 +0200 Subject: [PATCH 10/16] Add plot query system --- .../com/plotsquared/core/PlotSquared.java | 99 ++------ .../core/util/query/AliasFilter.java | 43 ++++ .../util/query/AreaLimitedPlotProvider.java | 46 ++++ .../core/util/query/GlobalPlotProvider.java | 39 +++ .../core/util/query/MemberFilter.java | 45 ++++ .../core/util/query/OwnerFilter.java | 46 ++++ .../core/util/query/PaginatedPlotResult.java | 73 ++++++ .../core/util/query/PlotFilter.java | 41 ++++ .../core/util/query/PlotProvider.java | 36 +++ .../core/util/query/PlotQuery.java | 228 ++++++++++++++++++ .../core/util/query/PredicateFilter.java | 45 ++++ 11 files changed, 667 insertions(+), 74 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/AliasFilter.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/MemberFilter.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/OwnerFilter.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/PaginatedPlotResult.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/PlotFilter.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/PredicateFilter.java diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index 4cb0731d5..e83cc56ba 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -82,6 +82,7 @@ import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.StringWrapper; 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.util.uuid.UUIDHandler; import com.sk89q.worldedit.WorldEdit; @@ -116,6 +117,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; @@ -640,17 +642,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) { @@ -905,25 +897,22 @@ public class PlotSquared { * @return a filtered set of plots */ public Set getPlots(final PlotFilter... filters) { - final HashSet set = new HashSet<>(); - forEachPlotArea(value -> { - for (PlotFilter filter : filters) { - if (!filter.allowsArea(value)) { - return; + 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(); } /** @@ -990,7 +979,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(); } /** @@ -1001,7 +990,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(); } /** @@ -1012,10 +1001,7 @@ public class PlotSquared { * @return Set of plot */ public Set getPlots(String world, UUID uuid) { - final Set plots = - getPlots(world).stream().filter(plot -> plot.hasOwner() && plot.isOwnerAbs(uuid)) - .collect(Collectors.toSet()); - return Collections.unmodifiableSet(plots); + return PlotQuery.newQuery().inWorld(world).ownedBy(uuid).asSet(); } /** @@ -1026,13 +1012,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(); } /** @@ -1047,9 +1027,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(); } /** @@ -1059,7 +1037,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) { @@ -1081,13 +1059,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) { @@ -1096,13 +1068,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(); } /** @@ -1112,13 +1078,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(); } /** @@ -2103,16 +2063,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/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..21a149176 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.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.plot.PlotArea; + +import java.util.Collection; +import java.util.stream.Stream; + +class AreaLimitedPlotProvider implements PlotProvider { + + private final Collection areas; + + AreaLimitedPlotProvider(Collection areas) { + this.areas = areas; + } + + @Override public Stream getPlots() { + return areas.stream().flatMap(area -> area.getPlots().stream()); + } + +} 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..82965aec3 --- /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.stream.Stream; + +class GlobalPlotProvider implements PlotProvider { + + @Override public Stream getPlots() { + return PlotSquared.get().getPlots().stream(); + } + +} 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/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..783288850 --- /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.stream.Stream; + +@FunctionalInterface interface PlotProvider { + + Stream 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..0c6132fd9 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -0,0 +1,228 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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 org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.function.Predicate; +import java.util.stream.Collectors; +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 PlotProvider plotProvider = new GlobalPlotProvider(); + private final Collection filters = new LinkedList<>(); + + 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 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)); + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots + */ + @NotNull public Stream asStream() { + Stream plots = this.plotProvider.getPlots(); + for (final PlotFilter filter : this.filters) { + plots = plots.filter(filter); + } + return plots; + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots as an immutable list + */ + @NotNull public List asList() { + return Collections.unmodifiableList(this.asStream().collect(Collectors.toList())); + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots as an immutable set + */ + @NotNull public Set asSet() { + return Collections.unmodifiableSet(this.asStream().collect(Collectors.toSet())); + } + + /** + * 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); + } + +} From 508fdce70485a111bbe75e79988b323aef28311f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 23:58:24 +0200 Subject: [PATCH 11/16] Add missing methods to PlotQuery and use PlotQuery in ListCmd --- .../com/plotsquared/core/command/ListCmd.java | 135 ++++++----------- .../util/query/AreaLimitedPlotProvider.java | 11 +- .../core/util/query/ExploredPlotProvider.java | 39 +++++ .../core/util/query/GlobalPlotProvider.java | 6 +- .../core/util/query/NullProvider.java | 39 +++++ .../core/util/query/PlotProvider.java | 4 +- .../core/util/query/PlotQuery.java | 139 ++++++++++++++++-- .../core/util/query/SearchPlotProvider.java | 46 ++++++ .../core/util/query/SortingStrategy.java | 52 +++++++ 9 files changed, 364 insertions(+), 107 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/NullProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/SearchPlotProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java 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 8d151fb10..c83ee5c4a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java @@ -26,13 +26,11 @@ 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.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; @@ -43,13 +41,14 @@ 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.query.PlotQuery; +import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal3; import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map.Entry; import java.util.UUID; @CommandDeclaration(command = "list", @@ -128,12 +127,13 @@ public class ListCmd extends SubCommand { } } - List plots = null; - String world = player.getLocation().getWorld(); PlotArea area = player.getApplicablePlotArea(); String arg = args[0].toLowerCase(); boolean sort = true; + + PlotQuery query = null; + switch (arg) { case "mine": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_MINE)) { @@ -141,8 +141,8 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_MINE); return false; } + query = PlotQuery.newQuery().ownedBy(player).whereBasePlot().withSortingStrategy(SortingStrategy.SORT_BY_TEMP); sort = false; - plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getBasePlots(player)); break; case "shared": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_SHARED)) { @@ -150,13 +150,8 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_SHARED); return false; } - plots = new ArrayList<>(); - for (Plot plot : PlotSquared.get().getPlots()) { - if (plot.getTrusted().contains(player.getUUID()) || plot.getMembers() - .contains(player.getUUID())) { - plots.add(plot); - } - } + // withMember checks for trusted + members + owner, we don't want the owner part + query = PlotQuery.newQuery().withMember(player.getUUID()).thatPasses(plot -> !plot.isOwnerAbs(player.getUUID())); break; case "world": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_WORLD)) { @@ -171,7 +166,7 @@ public class ListCmd extends SubCommand { world)); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots(world)); + query = PlotQuery.newQuery().inWorld(world); break; case "expired": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_EXPIRED)) { @@ -179,9 +174,11 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_EXPIRED); return false; } - plots = ExpireManager.IMP == null ? - new ArrayList() : - new ArrayList<>(ExpireManager.IMP.getPendingExpired()); + if (ExpireManager.IMP == null) { + query = PlotQuery.newQuery().noPlots(); + } else { + query = PlotQuery.newQuery().expiredPlots(); + } break; case "area": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_AREA)) { @@ -196,7 +193,11 @@ public class ListCmd extends SubCommand { world)); return false; } - plots = area == null ? new ArrayList() : new ArrayList<>(area.getPlots()); + if (area == null) { + query = PlotQuery.newQuery().noPlots(); + } else { + query = PlotQuery.newQuery().inArea(area); + } break; case "all": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_ALL)) { @@ -204,7 +205,7 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_ALL); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots()); + query = PlotQuery.newQuery().allPlots(); break; case "done": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_DONE)) { @@ -212,23 +213,7 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_DONE); return false; } - plots = new ArrayList<>(); - 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; - }); + query = PlotQuery.newQuery().allPlots().thatPasses(DoneFlag::isDone).withSortingStrategy(SortingStrategy.SORT_BY_DONE); sort = false; break; case "top": @@ -237,31 +222,7 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_TOP); return false; } - plots = new ArrayList<>(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); - }); + query = PlotQuery.newQuery().allPlots().withSortingStrategy(SortingStrategy.SORT_BY_RATING); sort = false; break; case "forsale": @@ -273,12 +234,7 @@ public class ListCmd extends SubCommand { if (EconHandler.manager == null) { break; } - plots = new ArrayList<>(); - for (Plot plot : PlotSquared.get().getPlots()) { - if (plot.getFlag(PriceFlag.class) > 0) { - plots.add(plot); - } - } + query = PlotQuery.newQuery().allPlots().thatPasses(plot -> plot.getFlag(PriceFlag.class) > 0); break; case "unowned": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNOWNED)) { @@ -286,12 +242,7 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_UNOWNED); return false; } - plots = new ArrayList<>(); - for (Plot plot : PlotSquared.get().getPlots()) { - if (plot.getOwner() == null) { - plots.add(plot); - } - } + query = PlotQuery.newQuery().allPlots().thatPasses(plot -> plot.getOwner() == null); break; case "unknown": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNKNOWN)) { @@ -299,15 +250,12 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_UNKNOWN); return false; } - plots = new ArrayList<>(); - for (Plot plot : PlotSquared.get().getPlots()) { + query = PlotQuery.newQuery().allPlots().thatPasses(plot -> { if (plot.getOwner() == null) { - continue; + return false; } - if (UUIDHandler.getName(plot.getOwner()) == null) { - plots.add(plot); - } - } + return UUIDHandler.getName(plot.getOwner()) == null; + }); break; case "fuzzy": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_FUZZY)) { @@ -325,7 +273,7 @@ public class ListCmd extends SubCommand { } else { term = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " "); } - plots = MainUtil.getPlotsBySearch(term); + query = PlotQuery.newQuery().plotsBySearch(term); sort = false; break; default: @@ -343,7 +291,7 @@ public class ListCmd extends SubCommand { args[0])); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots(args[0])); + query = PlotQuery.newQuery().inWorld(args[0]); break; } UUID uuid = UUIDHandler.getUUID(args[0], null); @@ -360,33 +308,40 @@ public class ListCmd extends SubCommand { return false; } sort = false; - plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getPlots(uuid)); + query = PlotQuery.newQuery().ownedBy(uuid).withSortingStrategy(SortingStrategy.SORT_BY_TEMP); break; } } - if (plots == null) { + if (query == null) { sendMessage(player, Captions.DID_YOU_MEAN, new StringComparison<>(args[0], new String[] {"mine", "shared", "world", "all"}) .getBestMatch()); return false; } + + if (area != null) { + query.relativeToArea(area); + } + + if (sort) { + query.withSortingStrategy(SortingStrategy.SORT_BY_CREATION); + } + + final List plots = query.asList(); + if (plots.isEmpty()) { MainUtil.sendMessage(player, Captions.FOUND_NO_PLOTS); return false; } - displayPlots(player, plots, 12, page, area, args, sort); + displayPlots(player, plots, 12, page, args); 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) { 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 index 21a149176..2a6e88171 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java @@ -29,7 +29,8 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; import java.util.Collection; -import java.util.stream.Stream; +import java.util.LinkedList; +import java.util.List; class AreaLimitedPlotProvider implements PlotProvider { @@ -39,8 +40,12 @@ class AreaLimitedPlotProvider implements PlotProvider { this.areas = areas; } - @Override public Stream getPlots() { - return areas.stream().flatMap(area -> area.getPlots().stream()); + @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/ExploredPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java new file mode 100644 index 000000000..94bf9b92e --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.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 ExploredPlotProvider implements PlotProvider { + + @Override public Collection getPlots() { + return ExpireManager.IMP.getPendingExpired(); + } + +} 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 index 82965aec3..3fb2420c5 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java @@ -28,12 +28,12 @@ package com.plotsquared.core.util.query; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.plot.Plot; -import java.util.stream.Stream; +import java.util.Collection; class GlobalPlotProvider implements PlotProvider { - @Override public Stream getPlots() { - return PlotSquared.get().getPlots().stream(); + @Override public Collection getPlots() { + return PlotSquared.get().getPlots(); } } 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/PlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java index 783288850..c8048da1a 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java @@ -27,10 +27,10 @@ package com.plotsquared.core.util.query; import com.plotsquared.core.plot.Plot; -import java.util.stream.Stream; +import java.util.Collection; @FunctionalInterface interface PlotProvider { - Stream getPlots(); + 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 index 0c6132fd9..612c4c21c 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -30,16 +30,21 @@ 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.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.Collectors; import java.util.stream.Stream; /** @@ -51,8 +56,10 @@ import java.util.stream.Stream; */ public final class PlotQuery { - private PlotProvider plotProvider = new GlobalPlotProvider(); private final Collection filters = new LinkedList<>(); + private PlotProvider plotProvider = new GlobalPlotProvider(); + private SortingStrategy sortingStrategy = SortingStrategy.NO_SORTING; + private PlotArea priorityArea; private PlotQuery() { } @@ -103,6 +110,47 @@ public final class PlotQuery { return this; } + /** + * Query for expired plots + * + * @return The query instance + */ + @NotNull public PlotQuery expiredPlots() { + this.plotProvider = new ExploredPlotProvider(); + 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 for base plots only * @@ -167,17 +215,32 @@ public final class PlotQuery { 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; + } + + @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() { - Stream plots = this.plotProvider.getPlots(); - for (final PlotFilter filter : this.filters) { - plots = plots.filter(filter); - } - return plots; + return this.asList().stream(); } /** @@ -186,7 +249,65 @@ public final class PlotQuery { * @return Matching plots as an immutable list */ @NotNull public List asList() { - return Collections.unmodifiableList(this.asStream().collect(Collectors.toList())); + 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()); + for (final Plot plot : plots) { + for (final PlotFilter filter : this.filters) { + if (filter.accepts(plot)) { + 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); + } + return result; } /** @@ -195,7 +316,7 @@ public final class PlotQuery { * @return Matching plots as an immutable set */ @NotNull public Set asSet() { - return Collections.unmodifiableSet(this.asStream().collect(Collectors.toSet())); + return new HashSet<>(this.asList()); } /** 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..2e6351dcc --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java @@ -0,0 +1,52 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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 +} From 6b31743fb30462fa7ffc8cd2f1209d01fc05e7b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 00:02:08 +0200 Subject: [PATCH 12/16] add missing javadoc --- .../java/com/plotsquared/core/util/query/PlotQuery.java | 7 +++++++ 1 file changed, 7 insertions(+) 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 index 612c4c21c..379702e12 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -228,6 +228,13 @@ public final class PlotQuery { 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; From 1aa144e47deb7fab83ce63f0c0fc61077e0a5898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 00:05:55 +0200 Subject: [PATCH 13/16] Deprecate old PlotFilter class --- Core/src/main/java/com/plotsquared/core/PlotSquared.java | 3 ++- .../src/main/java/com/plotsquared/core/plot/PlotFilter.java | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index e83cc56ba..bf0ef762b 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -895,8 +895,9 @@ public class PlotSquared { * * @param filters the filter * @return a filtered set of plots + * @deprecated Use {@link PlotQuery} */ - public Set getPlots(final PlotFilter... filters) { + @Deprecated public Set getPlots(final PlotFilter... filters) { final List areas = new LinkedList<>(); for (final PlotArea plotArea : this.getPlotAreas()) { for (final PlotFilter filter : filters) { 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; } + } From a0d1da32742ddb73b7889abe487931e487fba9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 00:08:52 +0200 Subject: [PATCH 14/16] fix dum typo --- .../{ExploredPlotProvider.java => ExpiredPlotProvider.java} | 2 +- .../main/java/com/plotsquared/core/util/query/PlotQuery.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename Core/src/main/java/com/plotsquared/core/util/query/{ExploredPlotProvider.java => ExpiredPlotProvider.java} (96%) diff --git a/Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/ExpiredPlotProvider.java similarity index 96% rename from Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java rename to Core/src/main/java/com/plotsquared/core/util/query/ExpiredPlotProvider.java index 94bf9b92e..9b369dc4e 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/ExpiredPlotProvider.java @@ -30,7 +30,7 @@ import com.plotsquared.core.plot.expiration.ExpireManager; import java.util.Collection; -class ExploredPlotProvider implements PlotProvider { +class ExpiredPlotProvider implements PlotProvider { @Override public Collection getPlots() { return ExpireManager.IMP.getPendingExpired(); 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 index 379702e12..208fac5d7 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -116,7 +116,7 @@ public final class PlotQuery { * @return The query instance */ @NotNull public PlotQuery expiredPlots() { - this.plotProvider = new ExploredPlotProvider(); + this.plotProvider = new ExpiredPlotProvider(); return this; } From 76913d4a78d581067ec2db93d5b27c1484f6bc68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 00:14:33 +0200 Subject: [PATCH 15/16] immutable -> mutable --- .../main/java/com/plotsquared/core/util/query/PlotQuery.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index 208fac5d7..67abfd1fa 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -253,7 +253,7 @@ public final class PlotQuery { /** * Get all plots that match the given criteria * - * @return Matching plots as an immutable list + * @return Matching plots as a mutable */ @NotNull public List asList() { final List result; @@ -320,7 +320,7 @@ public final class PlotQuery { /** * Get all plots that match the given criteria * - * @return Matching plots as an immutable set + * @return Matching plots as a mutable set */ @NotNull public Set asSet() { return new HashSet<>(this.asList()); From 0ac6383c2cf3bc6fe687f70a35876e209db0608d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 00:27:38 +0200 Subject: [PATCH 16/16] Use PlotQuery in Visit --- .../com/plotsquared/core/command/Visit.java | 41 +++++++++++------ .../core/util/query/FixedPlotProvider.java | 46 +++++++++++++++++++ .../core/util/query/PlotQuery.java | 28 +++++++++++ .../core/util/query/SortingStrategy.java | 6 ++- 4 files changed, 105 insertions(+), 16 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/FixedPlotProvider.java 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 372130a2d..442c40aeb 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -36,13 +36,13 @@ 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.query.PlotQuery; +import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; import com.plotsquared.core.util.uuid.UUIDHandler; -import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -72,9 +72,11 @@ public class Visit extends Command { args = args[0].split(":"); } int page = Integer.MIN_VALUE; - Collection unsorted = null; PlotArea sortByArea = player.getApplicablePlotArea(); boolean shouldSortByArea = Settings.Teleport.PER_WORLD_VISIT; + + final PlotQuery query = PlotQuery.newQuery(); + switch (args.length) { case 3: if (!MathMan.isInteger(args[1])) { @@ -96,7 +98,7 @@ public class Visit extends Command { Captions.COMMAND_SYNTAX.send(player, getUsage()); return CompletableFuture.completedFuture(false); } - unsorted = PlotSquared.get().getBasePlots(user); + query.ownedBy(user).whereBasePlot(); shouldSortByArea = true; break; } @@ -108,21 +110,21 @@ public class Visit extends Command { } if (page == Integer.MIN_VALUE && user == null && MathMan.isInteger(args[0])) { page = Integer.parseInt(args[0]); - unsorted = PlotSquared.get().getBasePlots(player); + query.ownedBy(player).whereBasePlot(); break; } if (user != null) { - unsorted = PlotSquared.get().getBasePlots(user); + query.ownedBy(player).whereBasePlot(); } else { Plot plot = MainUtil.getPlotFromString(player, args[0], true); if (plot != null) { - unsorted = Collections.singletonList(plot.getBasePlot(false)); + query.withPlot(plot); } } break; case 0: page = 1; - unsorted = PlotSquared.get().getPlots(player); + query.ownedBy(player); break; default: @@ -130,25 +132,33 @@ public class Visit extends Command { if (page == Integer.MIN_VALUE) { page = 1; } - if (unsorted == null || unsorted.isEmpty()) { + + // 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 CompletableFuture.completedFuture(false); } - unsorted = new ArrayList<>(unsorted); + if (unsorted.size() > 1) { - unsorted.removeIf(plot -> !plot.isBasePlot()); + query.whereBasePlot(); } + if (page < 1 || page > unsorted.size()) { Captions.NOT_VALID_NUMBER.send(player, "(1, " + unsorted.size() + ")"); return CompletableFuture.completedFuture(false); } - List plots; + if (shouldSortByArea) { - plots = PlotSquared.get() - .sortPlots(unsorted, PlotSquared.SortType.CREATION_DATE, sortByArea); + query.relativeToArea(sortByArea).withSortingStrategy(SortingStrategy.SORT_BY_CREATION); } else { - plots = PlotSquared.get().sortPlotsByTemp(unsorted); + 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)) { @@ -177,6 +187,7 @@ public class Visit extends Command { return CompletableFuture.completedFuture(false); } } + confirm.run(this, () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { if (result) { whenDone.run(Visit.this, CommandResult.SUCCESS); 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/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java index 67abfd1fa..6c90e969f 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -38,6 +38,7 @@ 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; @@ -60,6 +61,7 @@ public final class PlotQuery { private PlotProvider plotProvider = new GlobalPlotProvider(); private SortingStrategy sortingStrategy = SortingStrategy.NO_SORTING; private PlotArea priorityArea; + private Comparator plotComparator; private PlotQuery() { } @@ -151,6 +153,17 @@ public final class PlotQuery { 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 * @@ -228,6 +241,19 @@ public final class PlotQuery { 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 @@ -313,6 +339,8 @@ public final class PlotQuery { }); } 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; } 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 index 2e6351dcc..7a70b46fd 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java @@ -48,5 +48,9 @@ public enum SortingStrategy { /** * Sort by creation date */ - SORT_BY_CREATION + SORT_BY_CREATION, + /** + * Sort using a comparator + */ + COMPARATOR; }