Permissions
Permissions let you control which players are allowed to execute which commands. This is handled using the CommandPermission class, which has the following uses:
| Permission | What it does |
|---|---|
CommandPermission.OP | Requires OP to execute the command |
CommandPermission.NONE | Anyone can execute the command |
CommandPermission.fromString("my.permission") | Requires a specific permission node to execute the command |
In addition to the CommandPermission class, there are two different ways to assign permissions (compared to the simple CommandSender.hasPermission() method that is provided by Bukkit), by using the withPermission method for arguments or for commands.
The withPermission method can take two values:
- A
CommandPermission, which represents a permission such asOPorNONE - A
String, which will be converted automatically to aCommandPermissionusingCommandPermission.fromString()
Adding permissions to commands
To add a permission to a command, you can use the withPermission(CommandPermission) or withPermission(String) method when declaring a command.
Example – `/god` command with permissions
Example – /god command with permissions
Say we created a command /god that sets a player as being invulnerable. Since this is a pretty non-survival command, we want to restrict who can run this command. As such, we want our player to have the permission command.god in order to run this command. To do this, we simply use the withPermission(CommandPermission) method from our command builder:
// Register the /god command with the permission node "command.god"
new CommandAPICommand("god")
.withPermission(CommandPermission.fromString("command.god"))
.executesPlayer((player, args) -> {
player.setInvulnerable(true);
player.sendMessage("God mode enabled");
})
.register();As stated above, it is possible to assign a permission using a String instead of using CommandPermission.fromString():
// Register the /god command with the permission node "command.god", without creating a CommandPermission
new CommandAPICommand("god")
.withPermission("command.god")
.executesPlayer((player, args) -> {
player.setInvulnerable(true);
player.sendMessage("God mode enabled");
})
.register();Adding permissions to arguments
For further fine-tuning of permission management, the CommandAPI allows you to add permissions to individual arguments. This prevents the user from executing a command with a specific argument if they do not have a specific permission.
This is done by using the withPermission(CommandPermission) method at the end of an argument.
If a player does not have the required permission:
- The argument hover text which suggests what the command is will not be shown
- The player will receive an error if they try to type something in for that argument
- Suggestions, such as a list of materials or players, will not be shown
Example - `/kill` command with argument permissions
Example - /kill command with argument permissions
For example, say we're registering a command /kill:
/kill - Kills yourself
/kill <target> - Kills a target playerWe first declare the command as normal. Nothing fancy is going on here:
// Register /kill command normally. Since no permissions are applied, anyone can run this command
new CommandAPICommand("kill")
.executesPlayer((player, args) -> {
player.setHealth(0);
})
.register();Now we declare our command with arguments. We use a EntitySelectorArgument.OnePlayer and apply the permission to the argument. After that, we register our command as normal:
// Adds the OP permission to the "target" argument. The sender requires OP to execute /kill <target>
new CommandAPICommand("kill")
.withArguments(new EntitySelectorArgument.OnePlayer("target").withPermission(CommandPermission.OP))
.executesPlayer((player, args) -> {
((Player) args.get("target")).setHealth(0);
})
.register();Developer's Note:
As you can see, there are multiple ways of applying permissions to commands with arguments. In the /god command shown above, the permission was applied to the whole command. In the /kill command shown above, the permission was applied to the argument.
There's not really much difference between the two methods, but I personally would use argument permissions as it has greater control over arguments.
Child-based permissions
Child-based permissions allow you to group permissions together. We achieve this by laying out our permission groups in the plugin.yml file which Bukkit registers as valid permissions. When the CommandAPI checks if our player has a permission, Bukkit considers if they have the child of a permission as well. This not only keeps permissions easier to manage, it also makes your code cleaner and gives you a nice place to lay out all of your permissions, detailing what they do and what other permissions inherit them.
Example – `/economy` command with argument permissions
Example – /economy command with argument permissions
For example, say we're registering a command /economy:
/economy - shows your own balance | economy.self
/economy <target> - shows you another players balance | economy.other
/economy give <target> <amount> - gives the target a set amount of money | economy.admin.give
/economy reset <target> - resets the targets balance | economy.admin.resetWe first declare the command as normal. Nothing fancy is going on here:
// /economy - requires the permission "economy.self" to execute
new CommandAPICommand("economy")
.withPermission("economy.self") // The important part of this example
.executesPlayer((player, args) -> {
// send the executor their own balance here.
})
.register();
// /economy <target> - requires the permission "economy.other" to execute
new CommandAPICommand("economy")
.withPermission("economy.other") // The important part of this example
.withArguments(new EntitySelectorArgument.OnePlayer("target"))
.executesPlayer((player, args) -> {
Player target = (Player) args.get("target");
// Send a message to the executor with the target's balance
player.sendMessage(target.getName() + "'s balance: " + Economy.getBalance(target));
})
.register();
// /economy give <target> <amount> - requires the permission "economy.admin.give" to execute
new CommandAPICommand("economy")
.withPermission("economy.admin.give") // The important part of this example
.withArguments(new LiteralArgument("give"))
.withArguments(new EntitySelectorArgument.OnePlayer("target"))
.withArguments(new DoubleArgument("amount"))
.executesPlayer((player, args) -> {
Player target = (Player) args.get("target");
double amount = (Double) args.get("amount");
// Update the target player's balance
Economy.updateBalance(target, amount);
})
.register();
// /economy reset <target> - requires the permission "economy.admin.reset" to execute
new CommandAPICommand("economy")
.withPermission("economy.admin.reset") // The important part of this example
.withArguments(new LiteralArgument("reset"))
.withArguments(new EntitySelectorArgument.OnePlayer("target"))
.executesPlayer((player, args) -> {
Player target = (Player) args.get("target");
// Reset target balance
Economy.resetBalance(target);
})
.register();In our plugin.yml we can also set up our permissions, for example...
permissions:
economy.*:
description: Gives the user full access to the economy commands
children:
economy.other: true
economy.admin.*: true
economy.self:
description: Allows the user to view their own balance
economy.other:
description: Allows the user to another players balance
children:
economy.self: true
economy.admin.*:
description: Gives the user access to all of the admin commands
children:
economy.admin.give: true
economy.admin.reset: true
economy.admin.give:
description: Gives the user access to /economy give <target> <amount>
economy.admin.reset:
description: Gives the user access to /economy reset <target>This setup of children allows us to give a player less permissions, but have them access more features. Since economy.* inherits economy.admin.* which inherits economy.admin.give, a player with the permission economy.* will be able to execute /economy give <target> <amount> without them directly having the economy.admin.give permission node. This also works with economy.other, if a player has economy.other they will inherit economy.