diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle
index 61ae5e54f..1036e1089 100644
--- a/Bukkit/build.gradle
+++ b/Bukkit/build.gradle
@@ -23,7 +23,6 @@ dependencies {
compile("org.bstats:bstats-bukkit:1.7")
compile(project(":PlotSquared-Core"))
compile("com.destroystokyo.paper:paper-api:1.16.1-R0.1-SNAPSHOT")
- //implementation 'com.onarandombox.multiversecore:Multiverse-Core:3.0.0-SNAPSHOT'
implementation("org.spigotmc:spigot-api:1.16.1-R0.1-SNAPSHOT")
compile(group: "com.sk89q.worldedit", name: "worldedit-bukkit", version: "7.1.0") {
exclude(module: "bukkit")
@@ -36,7 +35,9 @@ dependencies {
}
implementation("me.clip:placeholderapi:2.10.6")
implementation("net.luckperms:api:5.1")
- implementation("net.ess3:EssentialsX:2.17.2")
+ implementation("net.ess3:EssentialsX:2.17.2") {
+ exclude(group: "io.papermc", module: "paperlib")
+ }
implementation("net.alpenblock:BungeePerms:4.0-dev-106")
compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false }
compile('com.sk89q:squirrelid:1.0.0-SNAPSHOT'){ transitive = false }
diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml
index d70af5d57..13e2e6fcf 100644
--- a/Bukkit/pom.xml
+++ b/Bukkit/pom.xml
@@ -21,7 +21,7 @@
com.plotsquared
PlotSquared-Core
- 5.12.2
+ 5.12.3
compile
@@ -163,6 +163,12 @@
EssentialsX
2.17.2
runtime
+
+
+ paperlib
+ io.papermc
+
+
net.alpenblock
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java
index 13e22685d..e4461ad90 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java
@@ -43,6 +43,7 @@ import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotHandler;
import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.plot.PlotInventory;
+import com.plotsquared.core.plot.flag.FlagContainer;
import com.plotsquared.core.plot.flag.implementations.AnimalAttackFlag;
import com.plotsquared.core.plot.flag.implementations.AnimalCapFlag;
import com.plotsquared.core.plot.flag.implementations.AnimalInteractFlag;
@@ -226,8 +227,8 @@ import java.util.regex.Pattern;
@SuppressWarnings("unused")
public class PlayerEvents extends PlotListener implements Listener {
- public static final com.sk89q.worldedit.world.entity.EntityType FAKE_ENTITY_TYPE
- = new com.sk89q.worldedit.world.entity.EntityType("plotsquared:fake");
+ public static final com.sk89q.worldedit.world.entity.EntityType FAKE_ENTITY_TYPE =
+ new com.sk89q.worldedit.world.entity.EntityType("plotsquared:fake");
private boolean pistonBlocks = true;
private float lastRadius;
@@ -342,6 +343,9 @@ public class PlayerEvents extends PlotListener implements Listener {
}
Plot plot = location.getOwnedPlot();
if (plot == null) {
+ if (area.isRoadFlags() && area.getRoadFlag(RedstoneFlag.class)) {
+ event.setNewCurrent(0);
+ }
return;
}
if (!plot.getFlag(RedstoneFlag.class)) {
@@ -361,7 +365,8 @@ public class PlayerEvents extends PlotListener implements Listener {
}
}
} else {
- disable = PlotSquared.platform().getPlayerManager().getPlayerIfExists(plot.getOwnerAbs()) == null;
+ disable = PlotSquared.platform().getPlayerManager().getPlayerIfExists(plot.getOwnerAbs())
+ == null;
}
}
if (disable) {
@@ -373,7 +378,8 @@ public class PlayerEvents extends PlotListener implements Listener {
}
if (disable) {
event.setNewCurrent(0);
- plot.debug("Redstone event was cancelled because no trusted player was in the plot");
+ plot.debug(
+ "Redstone event was cancelled because no trusted player was in the plot");
return;
}
}
@@ -464,7 +470,8 @@ public class PlayerEvents extends PlotListener implements Listener {
Plot newPlot = area.getOwnedPlotAbs(location);
if (!plot.equals(newPlot)) {
event.setCancelled(true);
- plot.debug("Prevented piston update because of invalid edge piston detection");
+ plot.debug(
+ "Prevented piston update because of invalid edge piston detection");
return;
}
}
@@ -569,11 +576,13 @@ public class PlayerEvents extends PlotListener implements Listener {
return;
}
}
- if (plot == null) {
+ if (plot == null && !area.isRoadFlags()) {
return;
}
- List blockedCommands = plot.getFlag(BlockedCmdsFlag.class);
+ List blockedCommands = plot != null ?
+ plot.getFlag(BlockedCmdsFlag.class) :
+ area.getFlag(BlockedCmdsFlag.class);
if (!blockedCommands.isEmpty() && !Permissions
.hasPermission(plotPlayer, Captions.PERMISSION_ADMIN_INTERACT_BLOCKED_CMDS)) {
String part = parts[0];
@@ -618,10 +627,10 @@ public class PlayerEvents extends PlotListener implements Listener {
}
if (pattern.matcher(msg).matches()) {
String perm;
- if (plot.isAdded(plotPlayer.getUUID())) {
+ if (plot != null && plot.isAdded(plotPlayer.getUUID())) {
perm = "plots.admin.command.blocked-cmds.shared";
} else {
- perm = "plots.admin.command.blocked-cmds.other";
+ perm = "plots.admin.command.blocked-cmds.road";
}
if (!Permissions.hasPermission(plotPlayer, perm)) {
MainUtil.sendMessage(plotPlayer, Captions.COMMAND_BLOCKED);
@@ -638,11 +647,11 @@ public class PlayerEvents extends PlotListener implements Listener {
final UUID uuid;
if (Settings.UUID.OFFLINE) {
if (Settings.UUID.FORCE_LOWERCASE) {
- uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" +
- event.getName().toLowerCase()).getBytes(Charsets.UTF_8));
+ uuid = UUID.nameUUIDFromBytes(
+ ("OfflinePlayer:" + event.getName().toLowerCase()).getBytes(Charsets.UTF_8));
} else {
- uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" +
- event.getName()).getBytes(Charsets.UTF_8));
+ uuid = UUID.nameUUIDFromBytes(
+ ("OfflinePlayer:" + event.getName()).getBytes(Charsets.UTF_8));
}
} else {
uuid = event.getUniqueId();
@@ -1328,8 +1337,8 @@ public class PlayerEvents extends PlotListener implements Listener {
.hasPermission(plotPlayer, Captions.PERMISSION_ADMIN_DESTROY_OTHER)) {
return;
}
- plot.debug(player.getName() + " could not break " + block.getType() +
- " because it was not in the break flag");
+ plot.debug(player.getName() + " could not break " + block.getType()
+ + " because it was not in the break flag");
event.setCancelled(true);
return;
}
@@ -1438,7 +1447,8 @@ public class PlayerEvents extends PlotListener implements Listener {
return;
}
if (plot.getFlag(DisablePhysicsFlag.class)) {
- plot.debug(event.getBlock().getType() + " could not update because disable-physics = true");
+ plot.debug(event.getBlock().getType()
+ + " could not update because disable-physics = true");
event.setCancelled(true);
return;
}
@@ -1719,13 +1729,24 @@ public class PlayerEvents extends PlotListener implements Listener {
if (event.getClick() == ClickType.CREATIVE) {
final Plot plot = pp.getCurrentPlot();
- if (plot != null &&
- plot.getFlag(PreventCreativeCopyFlag.class) &&
- !plot.isAdded(player.getUniqueId()) &&
- !Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_INTERACT_OTHER)) {
- final ItemStack newStack = new ItemStack(newItem.getType(), newItem.getAmount());
- event.setCursor(newStack);
- plot.debug(player.getName() + " could not creative-copy an item because prevent-creative-copy = true");
+ if (plot != null) {
+ if (plot.getFlag(PreventCreativeCopyFlag.class) && !plot
+ .isAdded(player.getUniqueId()) && !Permissions
+ .hasPermission(pp, Captions.PERMISSION_ADMIN_INTERACT_OTHER)) {
+ final ItemStack newStack =
+ new ItemStack(newItem.getType(), newItem.getAmount());
+ event.setCursor(newStack);
+ plot.debug(player.getName()
+ + " could not creative-copy an item because prevent-creative-copy = true");
+ }
+ } else {
+ PlotArea area = pp.getPlotAreaAbs();
+ if (area != null && area.isRoadFlags() && area
+ .getRoadFlag(PreventCreativeCopyFlag.class)) {
+ final ItemStack newStack =
+ new ItemStack(newItem.getType(), newItem.getAmount());
+ event.setCursor(newStack);
+ }
}
return;
}
@@ -1842,7 +1863,8 @@ public class PlayerEvents extends PlotListener implements Listener {
Plot plot = location.getPlotAbs();
BukkitPlayer pp = BukkitUtil.getPlayer(e.getPlayer());
if (plot == null) {
- if (!Permissions.hasPermission(pp, "plots.admin.interact.road")) {
+ if (!area.isRoadFlags() && !area.getRoadFlag(MiscInteractFlag.class)
+ && !Permissions.hasPermission(pp, "plots.admin.interact.road")) {
MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, "plots.admin.interact.road");
e.setCancelled(true);
}
@@ -1855,7 +1877,8 @@ public class PlayerEvents extends PlotListener implements Listener {
return;
}
}
- if (!plot.hasOwner()) {
+ if (!plot.hasOwner() && !area.isRoadFlags() && !area
+ .getRoadFlag(MiscInteractFlag.class)) {
if (!Permissions.hasPermission(pp, "plots.admin.interact.unowned")) {
MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT,
"plots.admin.interact.unowned");
@@ -1873,7 +1896,8 @@ public class PlayerEvents extends PlotListener implements Listener {
MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT,
"plots.admin.interact.other");
e.setCancelled(true);
- plot.debug(pp.getName() + " could not interact with " + entity.getType() + " bcause misc-interact = false");
+ plot.debug(pp.getName() + " could not interact with " + entity.getType()
+ + " bcause misc-interact = false");
}
}
}
@@ -2205,7 +2229,9 @@ public class PlayerEvents extends PlotListener implements Listener {
Plot plot = location.getOwnedPlot();
if (plot == null || !plot.getFlag(BlockBurnFlag.class)) {
- plot.debug("Block burning was cancelled because block-burn = false");
+ if (plot != null) {
+ plot.debug("Block burning was cancelled because block-burn = false");
+ }
event.setCancelled(true);
}
@@ -2510,7 +2536,8 @@ public class PlayerEvents extends PlotListener implements Listener {
MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT,
Captions.PERMISSION_ADMIN_DESTROY_OTHER);
event.setCancelled(true);
- plot.debug(p.getName() + " could not break hanging entity because hanging-break = false");
+ plot.debug(p.getName()
+ + " could not break hanging entity because hanging-break = false");
}
}
} else if (remover instanceof Projectile) {
@@ -2539,7 +2566,8 @@ public class PlayerEvents extends PlotListener implements Listener {
MainUtil.sendMessage(player, Captions.NO_PERMISSION_EVENT,
Captions.PERMISSION_ADMIN_DESTROY_OTHER);
event.setCancelled(true);
- plot.debug(player.getName() + " could not break hanging entity because hanging-break = false");
+ plot.debug(player.getName()
+ + " could not break hanging entity because hanging-break = false");
}
}
}
@@ -2560,57 +2588,66 @@ public class PlayerEvents extends PlotListener implements Listener {
Player p = event.getPlayer();
BukkitPlayer pp = BukkitUtil.getPlayer(p);
Plot plot = area.getPlot(location);
- if (plot == null) {
+ if (plot == null && !area.isRoadFlags()) {
if (!Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_INTERACT_ROAD)) {
MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT,
Captions.PERMISSION_ADMIN_INTERACT_ROAD);
event.setCancelled(true);
}
- } else if (!plot.hasOwner()) {
+ } else if (plot != null && !plot.hasOwner()) {
if (!Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_INTERACT_UNOWNED)) {
MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT,
Captions.PERMISSION_ADMIN_INTERACT_UNOWNED);
event.setCancelled(true);
}
- } else if (!plot.isAdded(pp.getUUID())) {
+ } else if ((plot != null && !plot.isAdded(pp.getUUID())) || area
+ .isRoadFlags()) {
final Entity entity = event.getRightClicked();
final com.sk89q.worldedit.world.entity.EntityType entityType =
BukkitAdapter.adapt(entity.getType());
- if (EntityCategories.HOSTILE.contains(entityType) && plot
- .getFlag(HostileInteractFlag.class)) {
+ FlagContainer flagContainer;
+ if (plot == null) {
+ flagContainer = area.getRoadFlagContainer();
+ } else {
+ flagContainer = plot.getFlagContainer();
+ }
+
+ if (EntityCategories.HOSTILE.contains(entityType) && flagContainer
+ .getFlag(HostileInteractFlag.class).getValue()) {
return;
}
- if (EntityCategories.ANIMAL.contains(entityType) && plot
- .getFlag(AnimalInteractFlag.class)) {
+ if (EntityCategories.ANIMAL.contains(entityType) && flagContainer
+ .getFlag(AnimalInteractFlag.class).getValue()) {
return;
}
// This actually makes use of the interface, so we don't use the
// category
- if (entity instanceof Tameable && ((Tameable) entity).isTamed() && plot
- .getFlag(TamedInteractFlag.class)) {
+ if (entity instanceof Tameable && ((Tameable) entity).isTamed() && flagContainer
+ .getFlag(TamedInteractFlag.class).getValue()) {
return;
}
- if (EntityCategories.VEHICLE.contains(entityType) && plot
- .getFlag(VehicleUseFlag.class)) {
+ if (EntityCategories.VEHICLE.contains(entityType) && flagContainer
+ .getFlag(VehicleUseFlag.class).getValue()) {
return;
}
- if (EntityCategories.PLAYER.contains(entityType) && plot
- .getFlag(PlayerInteractFlag.class)) {
+ if (EntityCategories.PLAYER.contains(entityType) && flagContainer
+ .getFlag(PlayerInteractFlag.class).getValue()) {
return;
}
- if (EntityCategories.VILLAGER.contains(entityType) && plot
- .getFlag(VillagerInteractFlag.class)) {
+ if (EntityCategories.VILLAGER.contains(entityType) && flagContainer
+ .getFlag(VillagerInteractFlag.class).getValue()) {
return;
}
if ((EntityCategories.HANGING.contains(entityType) || EntityCategories.OTHER
- .contains(entityType)) && plot.getFlag(MiscInteractFlag.class)) {
+ .contains(entityType)) && flagContainer.getFlag(MiscInteractFlag.class)
+ .getValue()) {
return;
}
@@ -2658,7 +2695,8 @@ public class PlayerEvents extends PlotListener implements Listener {
MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT,
"plots.admin.vehicle.break.other");
event.setCancelled(true);
- plot.debug(pp.getName() + " could not break vehicle because vehicle-break = false");
+ plot.debug(pp.getName()
+ + " could not break vehicle because vehicle-break = false");
}
}
}
@@ -2760,12 +2798,14 @@ public class PlayerEvents extends PlotListener implements Listener {
Plot plot;
String stub;
+ boolean isPlot = true;
if (dplot == null && vplot == null) {
if (dArea == null) {
return true;
}
plot = null;
stub = "road";
+ isPlot = false;
} else {
// Prioritize plots for close to seamless pvp zones
if (victim.getTicksLived() > damager.getTicksLived()) {
@@ -2795,6 +2835,8 @@ public class PlayerEvents extends PlotListener implements Listener {
stub = "unowned";
}
}
+ boolean roadFlags = vArea != null ? vArea.isRoadFlags() : dArea.isRoadFlags();
+ PlotArea area = vArea != null ? vArea : dArea;
Player player;
if (damager instanceof Player) { // attacker is player
@@ -2828,8 +2870,8 @@ public class PlayerEvents extends PlotListener implements Listener {
}
if (EntityCategories.HANGING.contains(entityType)) { // hanging
- if (plot != null && (plot.getFlag(HangingBreakFlag.class)) || plot
- .isAdded(plotPlayer.getUUID())) {
+ if (plot != null && (plot.getFlag(HangingBreakFlag.class) || plot
+ .isAdded(plotPlayer.getUUID()))) {
if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) {
if (!Permissions
.hasPermission(plotPlayer, Captions.PERMISSION_ADMIN_BUILD_OTHER)) {
@@ -2854,47 +2896,63 @@ public class PlayerEvents extends PlotListener implements Listener {
MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT,
"plots.admin.destroy." + stub);
if (plot != null) {
- plot.debug(player.getName() + " could not break armor stand because misc-break = false");
+ plot.debug(player.getName()
+ + " could not break armor stand because misc-break = false");
}
return false;
}
} else if (EntityCategories.HOSTILE.contains(entityType)) {
- if (plot != null && (plot.getFlag(HostileAttackFlag.class) || plot
- .getFlag(PveFlag.class) || plot.isAdded(plotPlayer.getUUID()))) {
+ if (isPlot) {
+ if (plot.getFlag(HostileAttackFlag.class) || plot.getFlag(PveFlag.class) || plot
+ .isAdded(plotPlayer.getUUID())) {
+ return true;
+ }
+ } else if (roadFlags && (area.getRoadFlag(HostileAttackFlag.class) || area
+ .getFlag(PveFlag.class))) {
return true;
}
if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) {
MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT,
"plots.admin.pve." + stub);
if (plot != null) {
- plot.debug(player.getName() + " could not attack " + entityType + " because pve = false OR hostile-attack = false");
+ plot.debug(player.getName() + " could not attack " + entityType
+ + " because pve = false OR hostile-attack = false");
}
return false;
}
} else if (EntityCategories.TAMEABLE.contains(entityType)) { // victim is tameable
- if (plot != null && (plot.getFlag(TamedAttackFlag.class) || plot
- .getFlag(PveFlag.class) || plot.isAdded(plotPlayer.getUUID()))) {
+ if (isPlot) {
+ if (plot.getFlag(TamedAttackFlag.class) || plot.getFlag(PveFlag.class) || plot
+ .isAdded(plotPlayer.getUUID())) {
+ return true;
+ }
+ } else if (roadFlags && (area.getRoadFlag(TamedAttackFlag.class) || area
+ .getFlag(PveFlag.class))) {
return true;
}
if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) {
MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT,
"plots.admin.pve." + stub);
if (plot != null) {
- plot.debug(player.getName() + " could not attack " + entityType + " because pve = false OR tamned-attack = false");
+ plot.debug(player.getName() + " could not attack " + entityType
+ + " because pve = false OR tamned-attack = false");
}
return false;
}
} else if (EntityCategories.PLAYER.contains(entityType)) {
- if (plot != null) {
+ if (isPlot) {
if (!plot.getFlag(PvpFlag.class) && !Permissions
.hasPermission(plotPlayer, "plots.admin.pvp." + stub)) {
MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT,
"plots.admin.pvp." + stub);
- plot.debug(player.getName() + " could not attack " + entityType + " because pve = false");
+ plot.debug(player.getName() + " could not attack " + entityType
+ + " because pve = false");
return false;
} else {
return true;
}
+ } else if (roadFlags && area.getRoadFlag(PvpFlag.class)) {
+ return true;
}
if (!Permissions.hasPermission(plotPlayer, "plots.admin.pvp." + stub)) {
MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT,
@@ -2902,29 +2960,38 @@ public class PlayerEvents extends PlotListener implements Listener {
return false;
}
} else if (EntityCategories.ANIMAL.contains(entityType)) { // victim is animal
- if (plot != null && (plot.getFlag(AnimalAttackFlag.class) || plot
- .getFlag(PveFlag.class) || plot.isAdded(plotPlayer.getUUID()))) {
- plot.debug(player.getName() + " could not attack " + entityType + " because pve = false OR animal-attack = false");
- return true;
- }
- if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) {
- MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT,
- "plots.admin.pve." + stub);
- return false;
+ if (isPlot) {
+ if (plot.getFlag(AnimalAttackFlag.class) || plot.getFlag(PveFlag.class) || plot
+ .isAdded(plotPlayer.getUUID())) {
+ plot.debug(player.getName() + " could not attack " + entityType
+ + " because pve = false OR animal-attack = false");
+ return true;
+ }
+ } else if (roadFlags && (area.getRoadFlag(AnimalAttackFlag.class) || area
+ .getFlag(PveFlag.class))) {
+ if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) {
+ MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT,
+ "plots.admin.pve." + stub);
+ return false;
+ }
}
} else if (EntityCategories.VEHICLE
.contains(entityType)) { // Vehicles are managed in vehicle destroy event
return true;
} else { // victim is something else
- if (plot != null && (plot.getFlag(PveFlag.class) || plot
- .isAdded(plotPlayer.getUUID()))) {
+ if (isPlot) {
+ if (plot.getFlag(PveFlag.class) || plot.isAdded(plotPlayer.getUUID())) {
+ return true;
+ }
+ } else if (roadFlags && area.getRoadFlag(PveFlag.class)) {
return true;
}
if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) {
MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT,
"plots.admin.pve." + stub);
if (plot != null) {
- plot.debug(player.getName() + " could not attack " + entityType + " because pve = false");
+ plot.debug(player.getName() + " could not attack " + entityType
+ + " because pve = false");
}
return false;
}
@@ -2941,6 +3008,9 @@ public class PlayerEvents extends PlotListener implements Listener {
return false;
}
}
+ if (vplot == null && roadFlags && area.getRoadFlag(PveFlag.class)) {
+ return true;
+ }
return ((vplot != null && vplot.getFlag(PveFlag.class)) || !(damager instanceof Arrow
&& !(victim instanceof Creature)));
}
@@ -3030,7 +3100,8 @@ public class PlayerEvents extends PlotListener implements Listener {
Block block = event.getBlockPlaced();
if (block.getType().hasGravity()) {
sendBlockChange(block.getLocation(), block.getBlockData());
- plot.debug(event.getBlock().getType() + " did not fall because of disable-physics = true");
+ plot.debug(event.getBlock().getType()
+ + " did not fall because of disable-physics = true");
}
}
} else if (!Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_BUILD_ROAD)) {
@@ -3044,12 +3115,21 @@ public class PlayerEvents extends PlotListener implements Listener {
if (event.getEntityType() != EntityType.PLAYER) {
return;
}
- Plot plot = BukkitUtil.getLocation(event.getEntity()).getOwnedPlot();
+ Location location = BukkitUtil.getLocation(event.getEntity());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = location.getOwnedPlot();
if (plot == null) {
+ if (area.isRoadFlags() && area.getRoadFlag(InvincibleFlag.class)) {
+ event.setCancelled(true);
+ }
return;
}
if (plot.getFlag(InvincibleFlag.class)) {
- plot.debug(event.getEntity().getName() + " could not take damage because invincible = true");
+ plot.debug(
+ event.getEntity().getName() + " could not take damage because invincible = true");
event.setCancelled(true);
}
}
@@ -3057,8 +3137,16 @@ public class PlayerEvents extends PlotListener implements Listener {
@EventHandler public void onItemDrop(PlayerDropItemEvent event) {
Player player = event.getPlayer();
BukkitPlayer pp = BukkitUtil.getPlayer(player);
- Plot plot = BukkitUtil.getLocation(player).getOwnedPlot();
+ Location location = pp.getLocation();
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = location.getOwnedPlot();
if (plot == null) {
+ if (area.isRoadFlags() && area.getRoadFlag(ItemDropFlag.class)) {
+ event.setCancelled(true);
+ }
return;
}
UUID uuid = pp.getUUID();
@@ -3075,24 +3163,46 @@ public class PlayerEvents extends PlotListener implements Listener {
if (ent instanceof Player) {
Player player = (Player) ent;
BukkitPlayer pp = BukkitUtil.getPlayer(player);
- Plot plot = BukkitUtil.getLocation(player).getOwnedPlot();
+ Location location = pp.getLocation();
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = location.getOwnedPlot();
if (plot == null) {
+ if (area.isRoadFlags() && area.getRoadFlag(DropProtectionFlag.class)) {
+ event.setCancelled(true);
+ }
return;
}
UUID uuid = pp.getUUID();
if (!plot.isAdded(uuid) && plot.getFlag(DropProtectionFlag.class)) {
- plot.debug(player.getName() + " could not pick up item because of drop-protection = true");
+ plot.debug(
+ player.getName() + " could not pick up item because of drop-protection = true");
event.setCancelled(true);
}
}
}
@EventHandler public void onDeath(final PlayerDeathEvent event) {
- final Plot plot = BukkitUtil.getPlayer(event.getEntity()).getCurrentPlot();
- if (plot != null && plot.getFlag(KeepInventoryFlag.class)) {
- plot.debug(event.getEntity().getName() + " kept their inventory because of keep-inventory = true");
- event.setKeepInventory(true);
+ Location location = BukkitUtil.getLocation(event.getEntity());
+ PlotArea area = location.getPlotArea();
+ if (area == null) {
+ return;
+ }
+ Plot plot = location.getOwnedPlot();
+ if (plot == null) {
+ if (area.isRoadFlags() && area.getRoadFlag(KeepInventoryFlag.class)) {
+ event.setCancelled(true);
+ }
+ return;
+ }
+ if (plot.getFlag(KeepInventoryFlag.class)) {
+ if (plot.getFlag(KeepInventoryFlag.class)) {
+ plot.debug(event.getEntity().getName()
+ + " kept their inventory because of keep-inventory = true");
+ event.setKeepInventory(true);
+ }
}
}
-
}
diff --git a/Core/src/main/java/com/plotsquared/core/command/HomeCommand.java b/Core/src/main/java/com/plotsquared/core/command/HomeCommand.java
new file mode 100644
index 000000000..b72276026
--- /dev/null
+++ b/Core/src/main/java/com/plotsquared/core/command/HomeCommand.java
@@ -0,0 +1,202 @@
+/*
+ * _____ _ _ _____ _
+ * | __ \| | | | / ____| | |
+ * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
+ * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
+ * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
+ * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
+ * | |
+ * |_|
+ * 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.command;
+
+import com.plotsquared.core.PlotSquared;
+import com.plotsquared.core.configuration.Captions;
+import com.plotsquared.core.events.TeleportCause;
+import com.plotsquared.core.player.PlotPlayer;
+import com.plotsquared.core.plot.Plot;
+import com.plotsquared.core.plot.PlotArea;
+import com.plotsquared.core.plot.PlotId;
+import com.plotsquared.core.util.MainUtil;
+import com.plotsquared.core.util.MathMan;
+import com.plotsquared.core.util.Permissions;
+import com.plotsquared.core.util.TabCompletions;
+import com.plotsquared.core.util.query.PlotQuery;
+import com.plotsquared.core.util.query.SortingStrategy;
+import com.plotsquared.core.util.task.RunnableVal2;
+import com.plotsquared.core.util.task.RunnableVal3;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+@CommandDeclaration(command = "home",
+ description = "Teleport to your plot(s)",
+ permission = "plots.home",
+ usage = "/plot home [||| | ]",
+ aliases = {"h"},
+ requiredType = RequiredType.PLAYER,
+ category = CommandCategory.TELEPORT)
+public class HomeCommand extends Command {
+ public HomeCommand() {
+ super(MainCommand.getInstance(), true);
+ }
+
+ private void home(@NotNull final PlotPlayer> player,
+ @NotNull final PlotQuery query, final int page,
+ final RunnableVal3 confirm,
+ final RunnableVal2 whenDone) {
+ List plots = query.asList();
+ if (plots.isEmpty()) {
+ Captions.FOUND_NO_PLOTS.send(player);
+ return;
+ } else if (plots.size() < page) {
+ MainUtil.sendMessage(player,
+ String.format(Captions.NUMBER_NOT_IN_RANGE.getTranslated(), "1", plots.size()));
+ return;
+ }
+ Plot plot = plots.get(page - 1);
+ confirm.run(this, () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> {
+ if (result) {
+ whenDone.run(this, CommandResult.SUCCESS);
+ } else {
+ whenDone.run(HomeCommand.this, CommandResult.FAILURE);
+ }
+ }), () -> whenDone.run(HomeCommand.this, CommandResult.FAILURE));
+ }
+
+ @NotNull private PlotQuery query(@NotNull final PlotPlayer> player) {
+ // everything plots need to have in common here
+ return PlotQuery.newQuery().ownedBy(player).whereBasePlot();
+ }
+
+ @Override public CompletableFuture execute(PlotPlayer> player, String[] args,
+ RunnableVal3 confirm,
+ RunnableVal2 whenDone) throws CommandException {
+ // /plot home (or page, whatever it's called)
+ // /plot home
+ // /plot home <[area;]x;y>
+ // /plot home
+ // /plot home
+ if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OWNED) && !Permissions
+ .hasPermission(player, Captions.PERMISSION_HOME)) {
+ Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OWNED);
+ return CompletableFuture.completedFuture(false);
+ }
+ if (args.length > 2) {
+ Captions.COMMAND_SYNTAX.send(player, getUsage());
+ return CompletableFuture.completedFuture(false);
+ }
+ PlotQuery query = query(player);
+ int page = 1; // page = index + 1
+ String identifier;
+ switch (args.length) {
+ case 1:
+ identifier = args[0];
+ if (MathMan.isInteger(identifier)) {
+ try {
+ page = Integer.parseInt(identifier);
+ } catch (NumberFormatException ignored) {
+ Captions.NOT_A_NUMBER.send(player, identifier);
+ return CompletableFuture.completedFuture(false);
+ }
+ query.withSortingStrategy(SortingStrategy.SORT_BY_CREATION);
+ break;
+ }
+ // either plot id or alias
+ Plot fromId = MainUtil.getPlotFromString(player, identifier, false);
+ if (fromId != null && fromId.isOwner(player.getUUID())) {
+ // it was a valid plot id
+ query.withPlot(fromId);
+ break;
+ }
+ // it wasn't a valid plot id, trying to find plot by alias
+ query.withAlias(identifier);
+ break;
+ case 2:
+ // we assume args[0] is a plot area and args[1] an identifier
+ PlotArea plotArea = PlotSquared.get().getPlotAreaByString(args[0]);
+ identifier = args[1];
+ if (plotArea == null) {
+ // invalid command, therefore no plots
+ query.noPlots();
+ break;
+ }
+ query.inArea(plotArea);
+ if (MathMan.isInteger(identifier)) {
+ // identifier is a page number
+ try {
+ page = Integer.parseInt(identifier);
+ } catch (NumberFormatException ignored) {
+ Captions.NOT_A_NUMBER.send(player, identifier);
+ return CompletableFuture.completedFuture(false);
+ }
+ query.withSortingStrategy(SortingStrategy.SORT_BY_CREATION);
+ break;
+ }
+ // identifier needs to be a plot id then
+ PlotId id = PlotId.fromStringOrNull(identifier);
+ if (id == null) {
+ // invalid command, therefore no plots
+ query.noPlots();
+ break;
+ }
+ // we can try to get this plot
+ Plot plot = plotArea.getPlot(id);
+ if (plot == null) {
+ query.noPlots();
+ break;
+ }
+ // as the query already filters by owner, this is fine
+ query.withPlot(plot);
+ break;
+ case 0:
+ query.withSortingStrategy(SortingStrategy.SORT_BY_CREATION);
+ break;
+ }
+ home(player, query, page, confirm, whenDone);
+ return CompletableFuture.completedFuture(true);
+ }
+
+ @Override
+ public Collection tab(PlotPlayer player, String[] args, boolean space) {
+ final List completions = new ArrayList<>();
+ switch (args.length - 1) {
+ case 0:
+ completions.addAll(
+ TabCompletions.completeAreas(args[0]));
+ if (args[0].isEmpty()) {
+ // if no input is given, only suggest 1 - 3
+ completions.addAll(
+ TabCompletions.asCompletions("1", "2", "3"));
+ break;
+ }
+ // complete more numbers from the already given input
+ completions.addAll(
+ TabCompletions.completeNumbers(args[0], 10, 999));
+ break;
+ case 1:
+ completions.addAll(
+ TabCompletions.completeNumbers(args[1], 10, 999));
+ break;
+ }
+ return completions;
+ }
+}
diff --git a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java
index a5c42b117..0df008815 100644
--- a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java
+++ b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java
@@ -77,6 +77,7 @@ public class MainCommand extends Command {
new RegenAllRoads();
new Claim();
new Auto();
+ new HomeCommand();
new Visit();
new Set();
new Clear();
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 35d038e1f..85da0a807 100644
--- a/Core/src/main/java/com/plotsquared/core/command/Visit.java
+++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java
@@ -40,12 +40,11 @@ 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.uuid.UUIDMapping;
import org.jetbrains.annotations.NotNull;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@@ -54,8 +53,8 @@ import java.util.concurrent.TimeoutException;
@CommandDeclaration(command = "visit",
permission = "plots.visit",
description = "Visit someones plot",
- usage = "/plot visit [|||] [#]",
- aliases = {"v", "tp", "teleport", "goto", "home", "h", "warp"},
+ usage = "/plot visit || [area]|[#] [#]",
+ aliases = {"v", "tp", "teleport", "goto", "warp"},
requiredType = RequiredType.PLAYER,
category = CommandCategory.TELEPORT)
public class Visit extends Command {
@@ -153,9 +152,9 @@ public class Visit extends Command {
int page = Integer.MIN_VALUE;
switch (args.length) {
- // /p v [...] [...]
+ // /p v
case 3:
- if (!MathMan.isInteger(args[1])) {
+ if (!MathMan.isInteger(args[2])) {
Captions.NOT_VALID_NUMBER.send(player, "(1, ∞)");
Captions.COMMAND_SYNTAX.send(player, getUsage());
return CompletableFuture.completedFuture(false);
@@ -188,24 +187,13 @@ public class Visit extends Command {
}
page = Integer.parseInt(args[1]);
// /p v [page]
- // /p v [page]
// /p v [page]
// /p v [page]
+ // /p v
case 1:
final String[] finalArgs = args;
int finalPage = page;
- // Try to determine whether the given argument is a username
- // or an ordinal
- boolean isNumber = false;
- if (args[0].length() < 2) {
- isNumber = true;
- } else if (args[0].length() <= 4 && MathMan.isInteger(args[0])) {
- // Check if it's an all-digit username that is stored in cache
- final UUIDMapping mapping = PlotSquared.get().getImpromptuUUIDPipeline().getImmediately(args[0]);
- // If no UUID could be found, then we assume it's a number and not a username
- isNumber = mapping == null;
- }
- if (!isNumber && args[0].length() >= 2 && !args[0].contains(";") && !args[0].contains(",")) {
+ if (args[0].length() >= 2 && !args[0].contains(";") && !args[0].contains(",")) {
PlotSquared.get().getImpromptuUUIDPipeline().getSingle(args[0], (uuid, throwable) -> {
if (throwable instanceof TimeoutException) {
// The request timed out
@@ -214,79 +202,61 @@ public class Visit extends Command {
// It was a valid UUID but the player has no plots
MainUtil.sendMessage(player, Captions.PLAYER_NO_PLOTS);
} else if (uuid == null) {
- if (finalPage == Integer.MIN_VALUE && MathMan.isInteger(finalArgs[0])) {
- // The argument was a number, so we assume it's the page number
- int parsedPage;
- try {
- parsedPage = Integer.parseInt(finalArgs[0]);
- } catch (final Throwable t) {
- MainUtil.sendMessage(player, Captions.NOT_A_NUMBER, finalArgs[0]);
- return;
- }
- this.visit(player, PlotQuery.newQuery().ownedBy(player).whereBasePlot(), null,
- confirm, whenDone, parsedPage);
+ // player not found, so we assume it's an alias if no page was provided
+ if (finalPage == Integer.MIN_VALUE) {
+ this.visit(player, PlotQuery.newQuery().withAlias(finalArgs[0]), player.getApplicablePlotArea(), confirm, whenDone, 1);
} else {
- // Try to parse a plot
- final Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true);
- if (plot == null) {
- MainUtil.sendMessage(player, Captions.NOT_VALID_PLOT_ID);
- return;
- }
- this.visit(player, PlotQuery.newQuery().withPlot(plot), null, confirm, whenDone, 1);
+ MainUtil.sendMessage(player, Captions.INVALID_PLAYER, finalArgs[0]);
}
} else {
this.visit(player, PlotQuery.newQuery().ownedBy(uuid).whereBasePlot(), null, confirm, whenDone, finalPage);
}
});
} else {
- if (finalPage == Integer.MIN_VALUE && MathMan.isInteger(finalArgs[0])) {
- // The argument was a number, so we assume it's the page number
- int parsedPage;
- try {
- parsedPage = Integer.parseInt(finalArgs[0]);
- this.visit(player, PlotQuery.newQuery().ownedBy(player).whereBasePlot(), null, confirm,
- whenDone, parsedPage);
- } catch (final Throwable throwable) {
- MainUtil.sendMessage(player, Captions.NOT_A_NUMBER, finalArgs[0]);
- }
- } else {
- // Try to parse a plot
- final Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true);
- if (plot != null) {
- this.visit(player, PlotQuery.newQuery().withPlot(plot), null, confirm, whenDone, 1);
- }
+ // Try to parse a plot
+ final Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true);
+ if (plot != null) {
+ this.visit(player, PlotQuery.newQuery().withPlot(plot), null, confirm, whenDone, 1);
}
}
break;
case 0:
- // /p v
- this.visit(player, PlotQuery.newQuery().ownedBy(player), null, confirm, whenDone);
- break;
+ // /p v is invalid
+ Captions.COMMAND_SYNTAX.send(player, getUsage());
+ return CompletableFuture.completedFuture(false);
default:
}
return CompletableFuture.completedFuture(true);
}
- public Collection tab(PlotPlayer player, String[] args, boolean space) {
- final List completions = new LinkedList<>();
+ @Override public Collection tab(PlotPlayer player, String[] args, boolean space) {
+ final List completions = new ArrayList<>();
switch (args.length - 1) {
case 0:
- this.completeNumbers(completions, args[0], 0);
completions.addAll(TabCompletions.completePlayers(args[0], Collections.emptyList()));
- break;
+ break;
case 1:
- if (MathMan.isInteger(args[0])) {
+ completions.addAll(
+ TabCompletions.completeAreas(args[1]));
+ if (args[1].isEmpty()) {
+ // if no input is given, only suggest 1 - 3
+ completions.addAll(
+ TabCompletions.asCompletions("1", "2", "3"));
break;
}
- this.completeNumbers(completions, args[1], 0);
- this.completeAreas(completions, args[1]);
+ completions.addAll(
+ TabCompletions.completeNumbers(args[1], 10, 999));
break;
case 2:
- if (MathMan.isInteger(args[1])) {
+ if (args[2].isEmpty()) {
+ // if no input is given, only suggest 1 - 3
+ completions.addAll(
+ TabCompletions.asCompletions("1", "2", "3"));
break;
}
- this.completeNumbers(completions, args[2], 0);
+ completions.addAll(
+ TabCompletions.completeNumbers(args[2], 10, 999));
break;
}
diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java b/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java
index fc2c12453..08ac2f962 100644
--- a/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java
+++ b/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java
@@ -118,6 +118,7 @@ public abstract class PlotArea {
@Getter private GameMode gameMode = GameModes.CREATIVE;
@Getter private Map> prices = new HashMap<>();
@Getter(AccessLevel.PROTECTED) private List schematics = new ArrayList<>();
+ @Getter private boolean roadFlags = false;
private boolean worldBorder = false;
private boolean useEconomy = false;
private int hash;
@@ -127,7 +128,9 @@ public abstract class PlotArea {
/**
* Area flag container
*/
- @Getter private FlagContainer flagContainer =
+ @Getter private final FlagContainer flagContainer =
+ new FlagContainer(GlobalFlagContainer.getInstance());
+ @Getter private final FlagContainer roadFlagContainer =
new FlagContainer(GlobalFlagContainer.getInstance());
public PlotArea(@NotNull final String worldName, @Nullable final String id,
@@ -370,6 +373,40 @@ public abstract class PlotArea {
this.spawnEggs = config.getBoolean("event.spawn.egg");
this.spawnCustom = config.getBoolean("event.spawn.custom");
this.spawnBreeding = config.getBoolean("event.spawn.breeding");
+
+ List roadflags = config.getStringList("flags.default");
+ if (roadflags.isEmpty()) {
+ roadflags = config.getStringList("road.flags");
+ if (roadflags.isEmpty()) {
+ roadflags = new ArrayList<>();
+ ConfigurationSection section = config.getConfigurationSection("road.flags");
+ Set keys = section.getKeys(false);
+ for (String key : keys) {
+ if (!"default".equals(key)) {
+ roadflags.add(key + ';' + section.get(key));
+ }
+ }
+ }
+ }
+ this.getRoadFlagContainer().addAll(parseFlags(roadflags));
+
+ StringBuilder roadFlagBuilder = new StringBuilder();
+ Collection> roadFlagCollection = this.getFlagContainer().getFlagMap().values();
+ if (roadFlagCollection.isEmpty()) {
+ roadFlagBuilder.append(Captions.NONE.getTranslated());
+ } else {
+ roadFlags = true;
+ String prefix = " ";
+ for (final PlotFlag, ?> flag : roadFlagCollection) {
+ Object value = flag.toString();
+ roadFlagBuilder.append(prefix).append(CaptionUtility
+ .format(null, Captions.PLOT_FLAG_LIST.getTranslated(), flag.getName(),
+ CaptionUtility.formatRaw(null, value.toString(), "")));
+ prefix = ", ";
+ }
+ }
+ PlotSquared.log(Captions.PREFIX + "&3 - road flags: &7" + roadFlagBuilder.toString());
+
loadConfiguration(config);
}
@@ -413,6 +450,7 @@ public abstract class PlotArea {
options.put("world.max_height", this.getMaxBuildHeight());
options.put("world.min_height", this.getMinBuildHeight());
options.put("world.gamemode", this.getGameMode().getName().toLowerCase());
+ options.put("road.flags.default", null);
if (this.getType() != PlotAreaType.NORMAL) {
options.put("generator.terrain", this.getTerrain());
@@ -434,6 +472,9 @@ public abstract class PlotArea {
config.set("flags.use",
"63,64,68,69,71,77,96,143,167,193,194,195,196,197,77,143,69,70,72,147,148,107,183,184,185,186,187,132");
}
+ if (!config.contains("road.flags")) {
+ config.set("road.flags.liquid-flow", false);
+ }
}
@NotNull @Override public String toString() {
@@ -1069,4 +1110,52 @@ public abstract class PlotArea {
}
return flags;
}
+
+ /**
+ * Get the value associated with the specified flag. This will look at
+ * the default values stored in {@link GlobalFlagContainer}.
+ *
+ * @param flagClass The flag type (Class)
+ * @return The flag value
+ */
+ public T getFlag(final Class extends PlotFlag> flagClass) {
+ return this.flagContainer.getFlag(flagClass).getValue();
+ }
+
+ /**
+ * Get the value associated with the specified flag. This will look at
+ * the default values stored in {@link GlobalFlagContainer}.
+ *
+ * @param flag The flag type (Any instance of the flag)
+ * @return The flag value
+ */
+ public > T getFlag(final V flag) {
+ final Class> flagClass = flag.getClass();
+ final PlotFlag, ?> flagInstance = this.flagContainer.getFlagErased(flagClass);
+ return FlagContainer.castUnsafe(flagInstance).getValue();
+ }
+
+ /**
+ * Get the value associated with the specified road flag. This will look at
+ * the default values stored in {@link GlobalFlagContainer}.
+ *
+ * @param flagClass The flag type (Class)
+ * @return The flag value
+ */
+ public T getRoadFlag(final Class extends PlotFlag> flagClass) {
+ return this.roadFlagContainer.getFlag(flagClass).getValue();
+ }
+
+ /**
+ * Get the value associated with the specified road flag. This will look at
+ * the default values stored in {@link GlobalFlagContainer}.
+ *
+ * @param flag The flag type (Any instance of the flag)
+ * @return The flag value
+ */
+ public > T getRoadFlag(final V flag) {
+ final Class> flagClass = flag.getClass();
+ final PlotFlag, ?> flagInstance = this.roadFlagContainer.getFlagErased(flagClass);
+ return FlagContainer.castUnsafe(flagInstance).getValue();
+ }
}
diff --git a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java
index ebff5c94f..ac30a4922 100644
--- a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java
+++ b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java
@@ -34,6 +34,7 @@ import com.plotsquared.core.command.RequiredType;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
+import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.uuid.UUIDMapping;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
@@ -136,6 +137,65 @@ public class TabCompletions {
return Collections.emptyList();
}
+ /**
+ * Get a list of integer numbers matching the given input. If the input string
+ * is empty, nothing will be returned. The list is unmodifiable.
+ *
+ * @param input Input to filter with
+ * @param amountLimit Maximum amount of suggestions
+ * @param highestLimit Highest number to include
+ * @return Unmodifiable list of number completions
+ */
+ @NotNull public List completeNumbers(@NotNull final String input,
+ final int amountLimit, final int highestLimit) {
+ if (input.isEmpty() || input.length() > highestLimit || !MathMan.isInteger(input)) {
+ return Collections.emptyList();
+ }
+ int offset;
+ try {
+ offset = Integer.parseInt(input) * 10;
+ } catch (NumberFormatException ignored) {
+ return Collections.emptyList();
+ }
+ final List commands = new ArrayList<>();
+ for (int i = offset; i < highestLimit && (offset - i + amountLimit) > 0; i++) {
+ commands.add(String.valueOf(i));
+ }
+ return asCompletions(commands.toArray(new String[0]));
+ }
+
+ /**
+ * Get a list of plot areas matching the given input.
+ * The list is unmodifiable.
+ *
+ * @param input Input to filter with
+ * @return Unmodifiable list of area completions
+ */
+ @NotNull public List completeAreas(@NotNull final String input) {
+ final List completions = new ArrayList<>();
+ for (final PlotArea area : PlotSquared.get().getPlotAreas()) {
+ String areaName = area.getWorldName();
+ if (area.getId() != null) {
+ areaName += ";" + area.getId();
+ }
+ if (!areaName.toLowerCase().startsWith(input.toLowerCase())) {
+ continue;
+ }
+ completions.add(new Command(null, false, areaName, "",
+ RequiredType.NONE, null) {});
+ }
+ return Collections.unmodifiableList(completions);
+ }
+
+ @NotNull public List asCompletions(String... toFilter) {
+ final List completions = new ArrayList<>();
+ for (String completion : toFilter) {
+ completions.add(new Command(null, false, completion, "",
+ RequiredType.NONE, null) {});
+ }
+ return Collections.unmodifiableList(completions);
+ }
+
/**
* @param cacheIdentifier Cache key
* @param input Command input
diff --git a/build.gradle b/build.gradle
index c55d34847..a841bb030 100644
--- a/build.gradle
+++ b/build.gradle
@@ -30,7 +30,7 @@ ext {
git = Grgit.open(dir: new File(rootDir.toString() + "/.git"))
}
-def ver = "5.12.2"
+def ver = "5.12.3"
def versuffix = ""
ext {
if (project.hasProperty("versionsuffix")) {