Skip to content

Command Arguments

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.

java
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
	dispatcher.register(CommandManager.literal("argtater1")
			.then(CommandManager.argument("value", IntegerArgumentType.integer())
					.executes(context -> {
						int value = IntegerArgumentType.getInteger(context, "value");
						context.getSource()
								.sendFeedback(
										() -> Text.literal(
												"Called /argtater1 with value = %s".formatted(value)),
										false);
						return 1;
					})));
});

In this case, after the command text /argtater, you should type an integer. For example, if you run /argtater 3, you will get the feedback message Called /argtater with value = 3. If you type /argtater without arguments, the command cannot be correctly parsed.

Then we add an optional second argument:

java
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
	dispatcher.register(CommandManager.literal("argtater2")
			.then(CommandManager.argument("value1", IntegerArgumentType.integer())
					.executes(context -> {
						int value1 = IntegerArgumentType.getInteger(context, "value1");
						context.getSource()
								.sendFeedback(
										() -> Text.literal(
												"Called /argtater2 with value 1 = %s".formatted(value1)),
										false);
						return 1;
					})
					.then(CommandManager.argument("value2", IntegerArgumentType.integer())
							.executes(context -> {
								int value1 = IntegerArgumentType.getInteger(context, "value1");
								int value2 = IntegerArgumentType.getInteger(context, "value2");
								context.getSource()
										.sendFeedback(
												() -> Text.literal(
														"Called /argtater2 with value 1 = %s and value 2 = %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.

java
	CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
		dispatcher.register(CommandManager.literal("argtater3")
				.then(CommandManager.argument("value1", IntegerArgumentType.integer())
						.executes(context ->
								printValues(IntegerArgumentType.getInteger(context, "value1"), 0, context))
						.then(CommandManager.argument("value2", IntegerArgumentType.integer())
								.executes(context -> printValues(
										IntegerArgumentType.getInteger(context, "value1"),
										IntegerArgumentType.getInteger(context, "value2"),
										context)))));
	});

private static int printValues(int value1, int value2, CommandContext<ServerCommandSource> context) {
	context.getSource()
			.sendFeedback(
					() -> Text.literal(
							"Called /argtater3 with value 1 = %s and value 2 = %s".formatted(value1, value2)),
					false);
	return 1;
}

Custom Argument Types

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}

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}");
		}
	}
}

Registering Custom Argument Types

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 initializer using the ArgumentTypeRegistry class:

java
ArgumentTypeRegistry.registerArgumentType(
		new Identifier("fabric-docs", "block_pos"),
		BlockPosArgumentType.class,
		ConstantArgumentSerializer.of(BlockPosArgumentType::new)
);

Using Custom Argument Types

We can use our custom argument type in a command - by passing an instance of it into the .argument method on the command builder.

java
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
	dispatcher.register(CommandManager.literal("parse_pos").then(
			CommandManager.argument("pos", new BlockPosArgumentType())
					.executes(context -> {
						BlockPos arg = context.getArgument("pos", BlockPos.class);
						context.getSource().sendFeedback(
								() -> Text.literal("Called /parse_pos with BlockPos: ")
										.append(Text.of(arg.toString())),
								false);
						return 1;
					})
	));
});

Running the command, we can test whether or not the argument type works:

Invalid argument.

Valid argument.

Command result.