diff --git a/plugin/src/main/java/org/battleplugins/arena/ArenaLoader.java b/plugin/src/main/java/org/battleplugins/arena/ArenaLoader.java index f898dce0..2ce02ceb 100644 --- a/plugin/src/main/java/org/battleplugins/arena/ArenaLoader.java +++ b/plugin/src/main/java/org/battleplugins/arena/ArenaLoader.java @@ -5,6 +5,7 @@ import org.battleplugins.arena.config.ParseException; import org.battleplugins.arena.event.arena.ArenaCreateExecutorEvent; import org.battleplugins.arena.event.arena.ArenaInitializeEvent; +import org.battleplugins.arena.util.CommandInjector; import org.bukkit.Bukkit; import org.bukkit.command.PluginCommand; import org.bukkit.configuration.Configuration; @@ -46,6 +47,8 @@ public void load() { command.setExecutor(executor); + CommandInjector.registerPermissions(arena.getName().toLowerCase(Locale.ROOT), executor); + new ArenaInitializeEvent(arena).callEvent(); this.battleArena.info("Loaded arena: {}.", arena.getName()); diff --git a/plugin/src/main/java/org/battleplugins/arena/BattleArena.java b/plugin/src/main/java/org/battleplugins/arena/BattleArena.java index 7102dfb7..a4b2b7fd 100644 --- a/plugin/src/main/java/org/battleplugins/arena/BattleArena.java +++ b/plugin/src/main/java/org/battleplugins/arena/BattleArena.java @@ -584,6 +584,8 @@ public Set getFailedModules() { public void registerExecutor(String commandName, BaseCommandExecutor executor, String... aliases) { PluginCommand command = CommandInjector.inject(commandName, commandName.toLowerCase(Locale.ROOT), aliases); command.setExecutor(executor); + + CommandInjector.registerPermissions(commandName.toLowerCase(Locale.ROOT), executor); } /** diff --git a/plugin/src/main/java/org/battleplugins/arena/command/BaseCommandExecutor.java b/plugin/src/main/java/org/battleplugins/arena/command/BaseCommandExecutor.java index b23ccce1..c9a0ec5b 100644 --- a/plugin/src/main/java/org/battleplugins/arena/command/BaseCommandExecutor.java +++ b/plugin/src/main/java/org/battleplugins/arena/command/BaseCommandExecutor.java @@ -47,7 +47,7 @@ public class BaseCommandExecutor implements TabExecutor { protected final String parentCommand; protected final String permissionSubNode; - private final Map> commandMethods = new HashMap<>(); + private final Map> commandWrappers = new HashMap<>(); private final List subCommandExecutors = new ArrayList<>(); @@ -142,20 +142,20 @@ private void registerCommands() { CommandWrapper wrapper = new CommandWrapper(this, method, this.getUsage(method)); for (String cmd : arenaCommand.commands()) { - Set wrappers = this.commandMethods.getOrDefault(cmd, new HashSet<>()); + Set wrappers = this.commandWrappers.getOrDefault(cmd, new HashSet<>()); wrappers.add(wrapper); - this.commandMethods.put(cmd, wrappers); + this.commandWrappers.put(cmd, wrappers); } } } public void injectWrapper(CommandWrapper wrapper) { for (String cmd : wrapper.getCommand().commands()) { - Set wrappers = this.commandMethods.getOrDefault(cmd, new HashSet<>()); + Set wrappers = this.commandWrappers.getOrDefault(cmd, new HashSet<>()); wrappers.add(wrapper); - this.commandMethods.put(cmd, wrappers); + this.commandWrappers.put(cmd, wrappers); } } @@ -317,7 +317,7 @@ public void sendHeader(CommandSender sender) { public void sendHelpMessage(CommandSender sender, int page) { // Compile all the command arguments Map commandWrappers = new HashMap<>(); - for (Map.Entry> entry : this.commandMethods.entrySet()) { + for (Map.Entry> entry : this.commandWrappers.entrySet()) { for (CommandWrapper wrapper : entry.getValue()) { commandWrappers.put(wrapper.usage, wrapper); } @@ -404,8 +404,8 @@ public void sendUsageMessage(CommandSender sender, Method method) { private List getCommandWrappers(String command, String subCommand) { List wrappers = new ArrayList<>(); - for (String cmd : this.commandMethods.keySet()) { - for (CommandWrapper wrapper : this.commandMethods.get(cmd)) { + for (String cmd : this.commandWrappers.keySet()) { + for (CommandWrapper wrapper : this.commandWrappers.get(cmd)) { ArenaCommand arenaCommand = wrapper.getCommand(); if (!Arrays.asList(arenaCommand.commands()).contains(command)) { @@ -658,8 +658,8 @@ public final List onTabComplete(CommandSender sender, Command command, S try { if (args.length == 1) { List commands = new ArrayList<>(); - for (String cmd : this.commandMethods.keySet()) { - CommandWrapper wrapper = this.commandMethods.get(cmd).iterator().next(); + for (String cmd : this.commandWrappers.keySet()) { + CommandWrapper wrapper = this.commandWrappers.get(cmd).iterator().next(); ArenaCommand arenaCommand = wrapper.getCommand(); if (!arenaCommand.permissionNode().isEmpty() && !this.hasPermission(sender, this.getPermissionNode(arenaCommand.permissionNode()))) { @@ -677,7 +677,7 @@ public final List onTabComplete(CommandSender sender, Command command, S } if (args.length > 1) { - Set wrappers = this.commandMethods.get(args[0]); + Set wrappers = this.commandWrappers.get(args[0]); for (CommandWrapper wrapper : wrappers) { ArenaCommand arenaCommand = wrapper.getCommand(); if (!arenaCommand.permissionNode().isEmpty() && !this.hasPermission(sender, this.getPermissionNode(arenaCommand.permissionNode()))) { @@ -714,7 +714,11 @@ public final List onTabComplete(CommandSender sender, Command command, S return completions; } - protected String getPermissionNode(String node) { + public Map> getCommandWrappers() { + return this.commandWrappers; + } + + public String getPermissionNode(String node) { return "battlearena.command." + (this.permissionSubNode == null ? "" : this.permissionSubNode + ".") + node; } diff --git a/plugin/src/main/java/org/battleplugins/arena/util/CommandInjector.java b/plugin/src/main/java/org/battleplugins/arena/util/CommandInjector.java index cc1a644f..e0c161d8 100644 --- a/plugin/src/main/java/org/battleplugins/arena/util/CommandInjector.java +++ b/plugin/src/main/java/org/battleplugins/arena/util/CommandInjector.java @@ -1,13 +1,21 @@ package org.battleplugins.arena.util; import org.battleplugins.arena.BattleArena; +import org.battleplugins.arena.command.BaseCommandExecutor; import org.bukkit.Bukkit; import org.bukkit.command.PluginCommand; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.HashSet; import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; public class CommandInjector { @@ -31,4 +39,48 @@ public static PluginCommand inject(String headerName, String commandName, String throw new RuntimeException("Failed to construct PluginCommand " + headerName, e); } } + + public static void registerPermissions(String commandName, BaseCommandExecutor executor) { + String rootPermissionNode = "battlearena.command." + commandName.toLowerCase(Locale.ROOT); + String wildcardPermissionNode = rootPermissionNode + ".*"; + + PluginManager pluginManager = Bukkit.getServer().getPluginManager(); + + // Register the root permission so it shows up in things such as LuckPerms UI. + // Set to true by default so the user can see the command, however this is intentionally + // done so server owners can fully revoke the permission, and it will not show up in tab complete. + Permission rootPermission = pluginManager.getPermission(rootPermissionNode); + if (rootPermission == null) { + pluginManager.addPermission(rootPermission = new Permission(rootPermissionNode, PermissionDefault.TRUE)); + } + + Permission wildcardPermission = pluginManager.getPermission(wildcardPermissionNode); + if (wildcardPermission == null) { + pluginManager.addPermission(wildcardPermission = new Permission(wildcardPermissionNode, PermissionDefault.OP)); + } + + Set childPermissions = new HashSet<>(); + for (Map.Entry> entry : executor.getCommandWrappers().entrySet()) { + for (BaseCommandExecutor.CommandWrapper wrapper : entry.getValue()) { + String node = wrapper.getCommand().permissionNode(); + String permissionNode = executor.getPermissionNode(node); + + // Add our permission node to the parent permission + if (permissionNode != null) { + childPermissions.add(permissionNode); + } + } + } + + // Add all child permissions to the parent permission + for (String childPermissionNode : childPermissions) { + Permission childPermission = pluginManager.getPermission(childPermissionNode); + if (childPermission == null) { + pluginManager.addPermission(childPermission = new Permission(childPermissionNode, PermissionDefault.OP)); + } + + // For wildcard permissions, set to true as we want all permissions granted when the wildcard is present + childPermission.addParent(wildcardPermission, true); + } + } }