MathOperation arguments

An image of the math operation argument, with suggestions "%=", "*=", "+=", "-=", "/=", "<", "=", ">" and "><"

The CommandAPI's MathOperationArgument is used to represent the Minecraft scoreboard arithmetic operation to alter scoreboard scores. Since there is no default representation in the Bukkit API, the CommandAPI provides the MathOperation class to represent each operation:

Symbol (in Minecraft)MathOperation enum value
\(+=\)MathOperation.ADD
\(-=\)MathOperation.SUBTRACT
\(*=\)MathOperation.MULTIPLY
\(/=\)MathOperation.DIVIDE
\(\%=\)MathOperation.MOD
\(=\)MathOperation.ASSIGN
\(<\)MathOperation.MIN
\(>\)MathOperation.MAX
\(><\)MathOperation.SWAP

The MathOperation also has two methods:

public int apply(int val1, int val2);
public float apply(float val1, float val2);

These methods are used to provide a basic implementation of these math operations on a given input. Given the values val1 and val2, these are the operation that the apply(val1, val2) method performs:

MathOperation enum valueResult
MathOperation.ADDval1 + val2
MathOperation.SUBTRACTval1 - val2
MathOperation.MULTIPLYval1 * val2
MathOperation.DIVIDEval1 / val2
MathOperation.MODval1 % val2
MathOperation.ASSIGNval2
MathOperation.MINMath.min(val1, val2)
MathOperation.MAXMath.max(val1, val2)
MathOperation.SWAPval2

Example - Changing a player's level

Say we wanted to create a player's level. Typically, this is implemented in the following manner:

/xp set <player> <level>
/xp add <player> <levels>

Using the MathOperationArgument, we can extend the functionality of adding and setting a player's level by allowing the user to choose what operation they desire. To do this, we'll use the following syntax:

/changelevel <player> <operation> <value>

As with any command, we declare our arguments, cast them properly and then we write our main code. In this example, we use the apply(int, int) method from our MathOperation to calculate the player's new level.

new CommandAPICommand("changelevel")
    .withArguments(new PlayerArgument("player"))
    .withArguments(new MathOperationArgument("operation"))
    .withArguments(new IntegerArgument("value"))
    .executes((sender, args) -> {
        Player target = (Player) args.get("player");
        MathOperation op = (MathOperation) args.get("operation");
        int value = (int) args.get("value");

        target.setLevel(op.apply(target.getLevel(), value));
    })
    .register();
CommandAPICommand("changelevel")
    .withArguments(PlayerArgument("player"))
    .withArguments(MathOperationArgument("operation"))
    .withArguments(IntegerArgument("value"))
    .executes(CommandExecutor { _, args ->
        val target = args["player"] as Player
        val op = args["operation"] as MathOperation
        val value = args["value"] as Int

        target.level = op.apply(target.level, value)
    })
    .register()
commandAPICommand("changelevel") {
    playerArgument("player")
    mathOperationArgument("operation")
    integerArgument("value")
    anyExecutor { _, args ->
        val target = args["player"] as Player
        val op = args["operation"] as MathOperation
        val value = args["value"] as Int

        target.level = op.apply(target.level, value)
    }
}

There are various applications for the changelevel command based on what the user inputs. For example:

  • To set the player Notch to level 10:

    /changelevel Notch = 10
    
  • To double the player Notch's level:

    /changelevel Notch *= 2
    
  • To set the player Notch's level to 20, or keep it as their current level if it is higher than 20:

    /changelevel Notch > 20