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 WorksCommand Doesn't Work
Success Value10
Result Valueresult defined in your code0

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