🇬🇧 English
🇬🇧 English
Appearance
🇬🇧 English
🇬🇧 English
Appearance
This page is written for version:
1.21
This page is written for version:
1.21
Arguments are used in most of the commands. Sometimes they can be optional, which means if you do not provide that argument, the command will also run. One node may have multiple argument types, but be aware that there is a possibility of ambiguity, which should be avoided.
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("command_with_arg")
.then(CommandManager.argument("value", IntegerArgumentType.integer())
.executes(FabricDocsReferenceCommands::executeCommandWithArg)));
});
private static int executeCommandWithArg(CommandContext<ServerCommandSource> context) {
int value = IntegerArgumentType.getInteger(context, "value");
context.getSource().sendFeedback(() -> Text.literal("Called /command_with_arg with value = %s".formatted(value)), false);
return 1;
}
In this case, after the command text /command_with_arg
, you should type an integer. For example, if you run /command_with_arg 3
, you will get the feedback message:
Called /command_with_arg with value = 3
If you type /command_with_arg
without arguments, the command cannot be correctly parsed.
Then we add an optional second argument:
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("command_with_two_args")
.then(CommandManager.argument("value_one", IntegerArgumentType.integer())
.executes(FabricDocsReferenceCommands::executeWithOneArg)
.then(CommandManager.argument("value_two", IntegerArgumentType.integer())
.executes(FabricDocsReferenceCommands::executeWithTwoArgs))));
});
private static int executeWithOneArg(CommandContext<ServerCommandSource> context) {
int value1 = IntegerArgumentType.getInteger(context, "value_one");
context.getSource().sendFeedback(() -> Text.literal("Called /command_with_two_args with value one = %s".formatted(value1)), false);
return 1;
}
private static int executeWithTwoArgs(CommandContext<ServerCommandSource> context) {
int value1 = IntegerArgumentType.getInteger(context, "value_one");
int value2 = IntegerArgumentType.getInteger(context, "value_two");
context.getSource().sendFeedback(() -> Text.literal("Called /argtater2 with value one = %s and value two = %s".formatted(value1, value2)),
false);
return 1;
}
Now you can type one or two integers. If you give one integer, a feedback text with a single value is printed. If you provide two integers, a feedback text with two values will be printed.
You may find it unnecessary to specify similar executions twice. Therefore, we can create a method that will be used in both executions.
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("command_with_common_exec")
.then(CommandManager.argument("value_one", IntegerArgumentType.integer())
.executes(context -> executeCommon(IntegerArgumentType.getInteger(context, "value_one"), 0, context))
.then(CommandManager.argument("value_two", IntegerArgumentType.integer())
.executes(context -> executeCommon(
IntegerArgumentType.getInteger(context, "value_one"),
IntegerArgumentType.getInteger(context, "value_two"),
context)))));
});
private static int executeCommon(int value1, int value2, CommandContext<ServerCommandSource> context) {
context.getSource().sendFeedback(() -> Text.literal("Called /command_with_common_exec with value 1 = %s and value 2 = %s".formatted(value1, value2)), false);
return 1;
}
If vanilla does not have the argument type you need, you can create your own. To do this, you need to create a class that inherits the ArgumentType<T>
interface where T
is the type of the argument.
You will need to implement the parse
method, which will parse the input string into the desired type.
For example, you can create an argument type that parses a BlockPos
from a string with the following format: {x, y, z}
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}");
}
}
}
WARNING
You need to register the custom argument type on both the server and the client or else the command will not work!
You can register your custom argument type in the onInitialize
method of your mod's initializer using the ArgumentTypeRegistry
class:
ArgumentTypeRegistry.registerArgumentType(
Identifier.of("fabric-docs", "block_pos"),
BlockPosArgumentType.class,
ConstantArgumentSerializer.of(BlockPosArgumentType::new)
);
We can use our custom argument type in a command - by passing an instance of it into the .argument
method on the command builder.
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(CommandManager.literal("command_with_custom_arg").then(
CommandManager.argument("block_pos", new BlockPosArgumentType())
.executes(FabricDocsReferenceCommands::executeCustomArgCommand)
));
});
private static int executeCustomArgCommand(CommandContext<ServerCommandSource> context) {
BlockPos arg = context.getArgument("block_pos", BlockPos.class);
context.getSource().sendFeedback(() -> Text.literal("Called /command_with_custom_arg with block pos = %s".formatted(arg)), false);
return 1;
}
Running the command, we can test whether or not the argument type works: