Resulting command executors
Resulting command executors are very similar to normal command executors, except they can return an integer result value.
(sender, args) -> {
//Code here
return /*some integer here*/ ;
};
Similarly, these will return a success value of 1 if it runs successfully, and a success value of 0 if it runs unsuccessfully. If a success value of 0 occurs, the result value will be 0. In short:
Command Works | Command Doesn't Work | |
---|---|---|
Success Value | 1 | 0 |
Result Value | result defined in your code | 0 |
The concept of result values are better explained through examples:
Example - Random number result command
Say we want a command that returns a random number as a result. This can then be used by vanilla Minecraft's /execute store result ...
command, which can be used for other command block chains.
new CommandAPICommand("randnum")
.executes((sender, args) -> {
return ThreadLocalRandom.current().nextInt();
})
.register();
CommandAPICommand("randnum")
.executes(ResultingCommandExecutor { _, _ ->
Random.nextInt()
})
.register()
commandAPICommand("randnum") {
anyResultingExecutor { _, _ ->
Random.nextInt()
}
}
This returns a success value of 1 (Because no errors or CommandAPI.failWithString(String)
was thrown) and a result value of a random number.
Example - Lootbox system with /execute
command
We can store state using /execute store
and we can perform conditional checks using /execute if
. By combining these, we can create a system which can be used with commandblocks to say, give players random lootboxes and redeem them. The concept is to create a command that generates a random number from 1 to 100. If the number is 1 (thus, the chance of being chosen is \(\frac{1}{100}\)), then we award a player with some reward, say 64 diamonds.
To do this, we'll declare two commands:
/randomnumber - returns a random number between 1 and 99 (inclusive)
/givereward <player> - gives a player 64 diamonds and broadcasts it in the chat
Since we're declaring commands that are to be used in /execute
, we must ensure that these commands are registered in your plugin's onLoad()
method. First, we write our implementation for /randomnumber
. It is fairly straight forward using Java's ThreadLocalRandom
to generate a random number:
// Register random number generator command from 1 to 99 (inclusive)
new CommandAPICommand("randomnumber")
.executes((sender, args) -> {
return ThreadLocalRandom.current().nextInt(1, 100); // Returns random number from 1 <= x < 100
})
.register();
// Register random number generator command from 1 to 99 (inclusive)
CommandAPICommand("randomnumber")
.executes(ResultingCommandExecutor { _, _ ->
(1..100).random() // Returns random number from 1 <= x < 100
})
.register()
// Register random number generator command from 1 to 99 (inclusive)
commandAPICommand("randomnumber") {
anyResultingExecutor { _, _ ->
(1..100).random()
}
}
Now we write our implementation for /givereward
. In this example, we use the EntitySelectorArgument
to select a single player. We cast it to Player
and then add the items to their inventory.
// Register reward giving system for a target player
new CommandAPICommand("givereward")
.withArguments(new EntitySelectorArgument.OnePlayer("target"))
.executes((sender, args) -> {
Player player = (Player) args.get("target");
player.getInventory().addItem(new ItemStack(Material.DIAMOND, 64));
Bukkit.broadcastMessage(player.getName() + " won a rare 64 diamonds from a loot box!");
})
.register();
// Register reward giving system for a target player
CommandAPICommand("givereward")
.withArguments(EntitySelectorArgument.OnePlayer("target"))
.executes(CommandExecutor { _, args ->
val player = args["target"] as Player
player.inventory.addItem(ItemStack(Material.DIAMOND, 64))
Bukkit.broadcastMessage("${player.name} won a rare 64 diamonds from a loot box!")
})
.register()
// Register reward giving system for a target player
commandAPICommand("givereward") {
entitySelectorArgumentOnePlayer("target")
anyExecutor { _, args ->
val player = args["target"] as Player
player.inventory.addItem(ItemStack(Material.DIAMOND, 64))
Bukkit.broadcastMessage("${player.name} won a rare 64 diamonds from a loot box!")
}
}
Now that we've declared these commands, we can now use them in practice. We can use a command block to store a random number under the scoreboard score randVal
for a player called SomePlayer
, by executing the command /randomnumber
. Since /randomnumber
returns an integer, this value is stored in the scoreboard score:
/execute store result score SomePlayer randVal run randomnumber
To check if the random number is equal to 1, we can use the /execute if
command. If their score stored in randVal
matches 1, then we run the /givereward
command.
/execute if score SomePlayer randVal matches 1 run givereward SomePlayer