Argumentos de comandos 26.2
Aprenda como criar comandos com argumentos complexos.
Argumentos são usados na maioria dos comandos. Algumas vezes eles podem ser opcionais, o que significa que se você não colocar esse argumento, o comando ainda vai rodar. Um nó pode incluir vários tipos de argumentos, mas é preciso ter cuidado para evitar ambiguidades, que devem ser evitadas.
java
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(Commands.literal("command_with_arg")
.then(Commands.argument("value", IntegerArgumentType.integer())
.executes(ExampleModCommands::executeCommandWithArg)));
});1
2
3
4
5
2
3
4
5
java
private static int executeCommandWithArg(CommandContext<CommandSourceStack> context) {
int value = IntegerArgumentType.getInteger(context, "value");
context.getSource().sendSuccess(() -> Component.literal("Called /command_with_arg with value = %s".formatted(value)), false);
return 1;
}1
2
3
4
5
2
3
4
5
Nesse caso, após o texto do comando /command_with_arg, você deve digitar um número inteiro. Por exemplo, se você executar /command_with_arg 3, você vai receber a mensagem de feedback:
Called /command_with_arg with value = 3
Se você digitar /command_with_arg sem argumentos, o comando não poderá ser analisado corretamente.
Então, adicionamos um segundo argumento opcional:
java
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(Commands.literal("command_with_two_args")
.then(Commands.argument("value_one", IntegerArgumentType.integer())
.executes(ExampleModCommands::executeWithOneArg)
.then(Commands.argument("value_two", IntegerArgumentType.integer())
.executes(ExampleModCommands::executeWithTwoArgs))));
});1
2
3
4
5
6
7
2
3
4
5
6
7
java
private static int executeWithOneArg(CommandContext<CommandSourceStack> context) {
int value1 = IntegerArgumentType.getInteger(context, "value_one");
context.getSource().sendSuccess(() -> Component.literal("Called /command_with_two_args with value one = %s".formatted(value1)), false);
return 1;
}
private static int executeWithTwoArgs(CommandContext<CommandSourceStack> context) {
int value1 = IntegerArgumentType.getInteger(context, "value_one");
int value2 = IntegerArgumentType.getInteger(context, "value_two");
context.getSource().sendSuccess(() -> Component.literal("Called /argtater2 with value one = %s and value two = %s".formatted(value1, value2)),
false);
return 1;
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Agora você pode digitar um ou dois números inteiros. Se você fornecer um inteiro, um texto de feedback com um único valor será impresso. Se você fornecer dois inteiros, um texto de feedback com dois valores será impresso.
Você pode achar desnecessário especificar execuções semelhantes duas vezes. Portanto, podemos criar um método que será usado em ambas as execuções.
java
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(Commands.literal("command_with_common_exec")
.then(Commands.argument("value_one", IntegerArgumentType.integer())
.executes(context -> executeCommon(IntegerArgumentType.getInteger(context, "value_one"), 0, context))
.then(Commands.argument("value_two", IntegerArgumentType.integer())
.executes(context -> executeCommon(
IntegerArgumentType.getInteger(context, "value_one"),
IntegerArgumentType.getInteger(context, "value_two"),
context)))));
});1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
java
private static int executeCommon(int value1, int value2, CommandContext<CommandSourceStack> context) {
context.getSource().sendSuccess(() -> Component.literal("Called /command_with_common_exec with value 1 = %s and value 2 = %s".formatted(value1, value2)), false);
return 1;
}1
2
3
4
2
3
4
Tipos de Argumento Personalizados
Se o vanilla não tiver o tipo de argumento que você precisa, você pode criar o seu próprio. Para fazer isso, é necessário criar uma classe que herde da interface ArgumentType<T>, onde T é o tipo de argumento.
Você precisará implementar o método parse, que irá analisar a string de entrada para o tipo desejado.
Por exemplo, você pode criar um tipo de argumento que analise um BlockPos a partir de uma string no seguinte formato: {x, y, z}`
java
public class BlockPosArgumentType implements ArgumentType<BlockPos> {
/**
* Parse the BlockPos from the reader in the {x, y, z} format.
*/
@Override
public BlockPos parse(StringReader reader) throws CommandSyntaxException {
try {
// This requires the argument to be surrounded by quotation marks.
// eg: "{1, 2, 3}"
String string = reader.readString();
// Remove the { and } from the string using regex.
string = string.replace("{", "").replace("}", "");
// Split the string into the x, y, and z values.
String[] split = string.split(",");
// Parse the x, y, and z values from the split string.
int x = Integer.parseInt(split[0].trim());
int y = Integer.parseInt(split[1].trim());
int z = Integer.parseInt(split[2].trim());
// Return the BlockPos.
return new BlockPos(x, y, z);
} catch (Exception e) {
// Throw an exception if anything fails inside the try block.
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException().create("Invalid BlockPos format. Expected {x, y, z}");
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Registrando Tipos de Argumento Personalizados
WARNING
Você precisa registrar o tipo de argumento personalizado tanto no servidor quanto no cliente, caso contrário, o comando não funcionará!
Você pode registrar seu tipo de argumento personalizado no método onInitialize do inicializador do seu mod, usando a classe ArgumentTypeRegistry:
java
ArgumentTypeRegistry.registerArgumentType(
ExampleMod.id("block_pos"),
BlockPosArgumentType.class,
SingletonArgumentInfo.contextFree(BlockPosArgumentType::new)
);1
2
3
4
5
2
3
4
5
Usando Tipos de Argumento Personalizados
Podemos usar nosso tipo de argumento personalizado em um comando — basta passar uma instância dele par o método .argument no builder do comando.
java
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(Commands.literal("command_with_custom_arg").then(
Commands.argument("block_pos", new BlockPosArgumentType())
.executes(ExampleModCommands::executeCustomArgCommand)
));
});1
2
3
4
5
6
2
3
4
5
6
java
private static int executeCustomArgCommand(CommandContext<CommandSourceStack> context) {
BlockPos arg = context.getArgument("block_pos", BlockPos.class);
context.getSource().sendSuccess(() -> Component.literal("Called /command_with_custom_arg with block pos = %s".formatted(arg)), false);
return 1;
}1
2
3
4
5
2
3
4
5
Ao executar o comando, podemos testar se o tipo de argumento funciona:



