diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/permissions/BukkitPermissionHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/permissions/BukkitPermissionHandler.java
index 2f003418f..18341309c 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/permissions/BukkitPermissionHandler.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/permissions/BukkitPermissionHandler.java
@@ -92,6 +92,16 @@ public class BukkitPermissionHandler implements PermissionHandler {
return player != null && player.hasPermission(permission);
}
+ @Override
+ public boolean hasKeyedPermission(
+ final @Nullable String world,
+ final @NonNull String stub,
+ final @NonNull String key
+ ) {
+ final Player player = this.playerReference.get();
+ return player != null && (player.hasPermission(stub + "." + key) || player.hasPermission(stub + ".*"));
+ }
+
}
}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/permissions/VaultPermissionHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/permissions/VaultPermissionHandler.java
index e7f6401d1..43afa09f3 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/permissions/VaultPermissionHandler.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/permissions/VaultPermissionHandler.java
@@ -117,6 +117,26 @@ public class VaultPermissionHandler implements PermissionHandler {
return permissions.playerHas(world, offlinePlayer, permission);
}
+ @Override
+ public boolean hasKeyedPermission(
+ final @Nullable String world,
+ final @NonNull String stub,
+ final @NonNull String key
+ ) {
+ if (permissions == null) {
+ return false;
+ }
+ if (world == null && offlinePlayer instanceof BukkitPlayer) {
+ return permissions.playerHas(
+ ((BukkitPlayer) offlinePlayer).getPlatformPlayer(),
+ stub + ".*"
+ ) || permissions.playerHas(((BukkitPlayer) offlinePlayer).getPlatformPlayer(), stub + "." + key);
+ }
+ return permissions.playerHas(world, offlinePlayer, stub + ".*") || permissions.playerHas(world, offlinePlayer,
+ stub + "." + key
+ );
+ }
+
}
}
diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitOfflinePlayer.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitOfflinePlayer.java
index 461ce1f71..f758c19cb 100644
--- a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitOfflinePlayer.java
+++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitOfflinePlayer.java
@@ -82,4 +82,14 @@ public class BukkitOfflinePlayer implements OfflinePlotPlayer {
return this.permissionProfile.hasPermission(world, permission);
}
+ @Override
+ public boolean hasKeyedPermission(
+ final @Nullable String world,
+ final @NonNull String stub,
+ final @NonNull String key
+ ) {
+ return this.permissionProfile.hasPermission(world, stub + "." + key) || this.permissionProfile.hasPermission(world,
+ stub + ".*");
+ }
+
}
diff --git a/Bukkit/src/main/resources/plugin.yml b/Bukkit/src/main/resources/plugin.yml
index cbee6f866..8b2cfd094 100644
--- a/Bukkit/src/main/resources/plugin.yml
+++ b/Bukkit/src/main/resources/plugin.yml
@@ -319,45 +319,78 @@ permissions:
plots.flag.remove: true
plots.flag.list: true
plots.flag.info: true
+ plots.set.flag.titles: true
plots.set.flag.titles.*: true
- plots.set.flag.greeting.*: true
- plots.set.flag.farewell.*: true
+ plots.set.flag.description: true
+ plots.set.flag.greeting: true
+ plots.set.flag.farewell: true
+ plots.set.flag.notify-enter: true
plots.set.flag.notify-enter.*: true
+ plots.set.flag.notify-leave: true
plots.set.flag.notify-leave.*: true
+ plots.set.flag.feed: true
plots.set.flag.feed.*: true
+ plots.set.flag.heal: true
plots.set.flag.heal.*: true
+ plots.set.flag.invincible: true
plots.set.flag.invincible.*: true
+ plots.set.flag.instabreak: true
plots.set.flag.instabreak.*: true
+ plots.set.flag.fly: true
plots.set.flag.fly.*: true
plots.set.flag.gamemode: true
plots.set.flag.gamemode.creative: true
plots.set.flag.gamemode.survival: true
plots.set.flag.gamemode.adventure: true
- plots.set.flag.time.*: true
+ plots.set.flag.time: true
+ plots.set.flag.weather: true
plots.set.flag.weather.*: true
+ plots.set.flag.music: true
plots.set.flag.music.*: true
+ plots.set.flag.disable-physics: true
plots.set.flag.disable-physics.*: true
+ plots.set.flag.pve: true
plots.set.flag.pve.*: true
+ plots.set.flag.pvp: true
plots.set.flag.pvp.*: true
+ plots.set.flag.explosion: true
plots.set.flag.explosion.*: true
+ plots.set.flag.hostile-interact: true
plots.set.flag.hostile-interact.*: true
+ plots.set.flag.hostile-attack: true
plots.set.flag.hostile-attack.*: true
+ plots.set.flag.player-interact: true
plots.set.flag.player-interact.*: true
+ plots.set.flag.animal-interact: true
plots.set.flag.animal-interact.*: true
+ plots.set.flag.animal-attack: true
plots.set.flag.animal-attack.*: true
+ plots.set.flag.tamed-interact: true
plots.set.flag.tamed-interact.*: true
+ plots.set.flag.tamed-attack: true
plots.set.flag.tamed-attack.*: true
+ plots.set.flag.misc-interact: true
plots.set.flag.misc-interact.*: true
+ plots.set.flag.hanging-place: true
plots.set.flag.hanging-place.*: true
+ plots.set.flag.hanging-break: true
plots.set.flag.hanging-break.*: true
+ plots.set.flag.vehicle-use: true
plots.set.flag.vehicle-use.*: true
+ plots.set.flag.vehicle-place: true
plots.set.flag.vehicle-place.*: true
+ plots.set.flag.vehicle-break: true
plots.set.flag.vehicle-break.*: true
+ plots.set.flag.place: true
plots.set.flag.place.*: true
+ plots.set.flag.break: true
plots.set.flag.break.*: true
+ plots.set.flag.use: true
plots.set.flag.use.*: true
+ plots.set.flag.forcefield: true
plots.set.flag.forcefield.*: true
- plots.set.flag.price.*: true
+ plots.set.flag.price: true
+ plots.set.flag.no-worldedit: true
plots.set.flag.no-worldedit.*: true
plots.permpack.basicinbox:
default: false
diff --git a/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java b/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java
index 6b23111f6..7801cfdcc 100644
--- a/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java
+++ b/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java
@@ -102,22 +102,23 @@ public final class FlagCommand extends Command {
try {
int numeric = Integer.parseInt(value);
perm = perm.substring(0, perm.length() - value.length() - 1);
+ boolean result = false;
if (numeric > 0) {
int checkRange = PlotSquared.get().getPlatform().equalsIgnoreCase("bukkit") ?
numeric :
Settings.Limit.MAX_PLOTS;
- final boolean result = player.hasPermissionRange(perm, checkRange) >= numeric;
- if (!result) {
- player.sendMessage(
- TranslatableCaption.of("permission.no_permission"),
- Template.of(
- "node",
- Permission.PERMISSION_SET_FLAG_KEY_VALUE.format(key.toLowerCase(), value.toLowerCase())
- )
- );
- }
- return result;
+ result = player.hasPermissionRange(perm, checkRange) >= numeric;
}
+ if (!result) {
+ player.sendMessage(
+ TranslatableCaption.of("permission.no_permission"),
+ Template.of(
+ "node",
+ perm
+ )
+ );
+ }
+ return result;
} catch (NumberFormatException ignore) {
}
} else if (flag instanceof final ListFlag, ?> listFlag) {
@@ -147,7 +148,14 @@ public final class FlagCommand extends Command {
}
return true;
}
- final boolean result = Permissions.hasPermission(player, perm);
+ boolean result;
+ String basePerm = Permission.PERMISSION_SET_FLAG_KEY.format(key.toLowerCase());
+ if (flag.isValuedPermission()) {
+ result = Permissions.hasKeyedPermission(player, basePerm, value);
+ } else {
+ result = Permissions.hasPermission(player, basePerm);
+ perm = basePerm;
+ }
if (!result) {
player.sendMessage(TranslatableCaption.of("permission.no_permission"), Template.of("node", perm));
}
diff --git a/Core/src/main/java/com/plotsquared/core/permissions/ConsolePermissionProfile.java b/Core/src/main/java/com/plotsquared/core/permissions/ConsolePermissionProfile.java
index fac9ce251..714499b5f 100644
--- a/Core/src/main/java/com/plotsquared/core/permissions/ConsolePermissionProfile.java
+++ b/Core/src/main/java/com/plotsquared/core/permissions/ConsolePermissionProfile.java
@@ -39,4 +39,13 @@ public enum ConsolePermissionProfile implements PermissionProfile {
return true;
}
+ @Override
+ public boolean hasKeyedPermission(
+ final @Nullable String world,
+ final @NonNull String permission,
+ final @NonNull String key
+ ) {
+ return true;
+ }
+
}
diff --git a/Core/src/main/java/com/plotsquared/core/permissions/NullPermissionProfile.java b/Core/src/main/java/com/plotsquared/core/permissions/NullPermissionProfile.java
index 441e38f29..68274fbe5 100644
--- a/Core/src/main/java/com/plotsquared/core/permissions/NullPermissionProfile.java
+++ b/Core/src/main/java/com/plotsquared/core/permissions/NullPermissionProfile.java
@@ -39,4 +39,13 @@ public enum NullPermissionProfile implements PermissionProfile {
return false;
}
+ @Override
+ public boolean hasKeyedPermission(
+ final @Nullable String world,
+ final @NonNull String permission,
+ final @NonNull String key
+ ) {
+ return false;
+ }
+
}
diff --git a/Core/src/main/java/com/plotsquared/core/permissions/PermissionHolder.java b/Core/src/main/java/com/plotsquared/core/permissions/PermissionHolder.java
index 952b43a04..c1ec4a0c8 100644
--- a/Core/src/main/java/com/plotsquared/core/permissions/PermissionHolder.java
+++ b/Core/src/main/java/com/plotsquared/core/permissions/PermissionHolder.java
@@ -45,6 +45,21 @@ public interface PermissionHolder {
return hasPermission(null, permission);
}
+ /**
+ * Check if the owner of the profile has a given (global) keyed permission. Checks both {@code permission.key}
+ * and {@code permission.*}
+ *
+ * @param permission Permission
+ * @param key Permission "key"
+ * @return {@code true} if the owner has the given permission, else {@code false}
+ */
+ default boolean hasKeyedPermission(
+ final @NonNull String permission,
+ final @NonNull String key
+ ) {
+ return hasKeyedPermission(null, permission, key);
+ }
+
/**
* Check the highest permission a PlotPlayer has within a specified range.
* - Excessively high values will lag
@@ -92,4 +107,15 @@ public interface PermissionHolder {
*/
boolean hasPermission(@Nullable String world, @NonNull String permission);
+ /**
+ * Check if the owner of the profile has a given keyed permission. Checks both {@code permission.key}
+ * and {@code permission.*}
+ *
+ * @param world World name
+ * @param permission Permission
+ * @param key Permission "key"
+ * @return {@code true} if the owner has the given permission, else {@code false}
+ */
+ boolean hasKeyedPermission(@Nullable String world, @NonNull String permission, @NonNull String key);
+
}
diff --git a/Core/src/main/java/com/plotsquared/core/permissions/PermissionProfile.java b/Core/src/main/java/com/plotsquared/core/permissions/PermissionProfile.java
index 2670b2e3b..b2b92b94d 100644
--- a/Core/src/main/java/com/plotsquared/core/permissions/PermissionProfile.java
+++ b/Core/src/main/java/com/plotsquared/core/permissions/PermissionProfile.java
@@ -52,4 +52,33 @@ public interface PermissionProfile {
*/
boolean hasPermission(final @Nullable String world, @NonNull String permission);
+ /**
+ * Check if the owner of the profile has a given (global) keyed permission. Checks both {@code permission.key}
+ * and {@code permission.*}
+ *
+ * @param permission Permission
+ * @param key Permission "key"
+ * @return {@code true} if the owner has the given permission, else {@code false}
+ */
+ default boolean hasKeyedPermission(
+ final @NonNull String permission,
+ final @NonNull String key
+ ) {
+ return hasKeyedPermission(null, permission, key);
+ }
+
+ /**
+ * Check if the owner of the profile has a given keyed permission. Checks both {@code permission.key}
+ * and {@code permission.*}
+ *
+ * @param world World name
+ * @param permission Permission
+ * @param key Permission "key"
+ * @return {@code true} if the owner has the given permission, else {@code false}
+ */
+ boolean hasKeyedPermission(
+ @Nullable String world, final @NonNull String permission,
+ final @NonNull String key
+ );
+
}
diff --git a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java
index 8792e8a95..496126019 100644
--- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java
+++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java
@@ -197,6 +197,15 @@ public abstract class PlotPlayer
implements CommandCaller, OfflinePlotPlayer,
return this.permissionProfile.hasPermission(world, permission);
}
+ @Override
+ public final boolean hasKeyedPermission(
+ final @Nullable String world,
+ final @NonNull String permission,
+ final @NonNull String key
+ ) {
+ return this.permissionProfile.hasKeyedPermission(world, permission, key);
+ }
+
public abstract Actor toActor();
public abstract P getPlatformPlayer();
diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java b/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java
index 185a3cd19..1de1eb686 100644
--- a/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java
+++ b/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java
@@ -158,6 +158,15 @@ public abstract class PlotFlag