Skip to content

Tham Số Câu Lệnh

Hầu hết các câu lệnh đều có tham số. Nhiều khi tham số đó không bắt buộc, bạn không cần phải đưa vào câu lệnh nhưng nó vẫn chạy. Một node có thể có nhiều loại tham số, nhưng bạn nên tránh xảy ra trường hợp kiểu dữ liệu của tham số không rõ.

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

Trong trường hợp này, sau /argtater, bạn cần đưa ra một số nguyên làm tham số. Chẳng hạn, khi bạn chạy /argtater 3, bạn sẽ nhận được thông báo Called /argtater with value = 3. Khị bạn nhập /argtater mà không đưa ra tham số, câu lệnh trên sẽ không chạy được.

Chúng ta có thể thêm vào đối số không bắt buộc thứ hai:

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

Giờ đây, bạn có thể nhập một hoặc hai số nguyên làm tham số. Nếu bạn đưa vào một số nguyên, bạn sẽ nhận được thông báo với một giá trị. Nếu là hai số nguyên, thông báo sẽ đưa ra hai giá trị.

Có thể bạn thấy việc viết hai quy trình xử lý dữ liệu giống nhau là không cần thiết. Ta có thể tạo một method sử dụng trong cả hai tham số.

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

Kiểu Tham Số Tùy Chỉnh

Nếu bạn không tìm thấy kiểu tham số bạn cần trong vanilla, bạn có thể tự tạo kiểu của riêng mình. Bạn cần tạo một class mà kế thừa interface ArgumentType<T>, với T là kiểu tham số.

Bạn cần phải thêm method parse để xử lý tham số từ kiểu xâu ký tự sang kiểu tham số mà bạn cần.

Giả sử bạn cần một kiểu tham số cho ra BlockPos khi người dùng nhập: {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}");
		}
	}
}

Đăng Ký Kiểu Tham Số Tùy Chỉnh

WARNING

Câu lệnh của bạn sẽ không hoạt động nếu bạn không đăng ký kiểu tham số tùy chỉnh trên cả máy chủ lẫn máy khách!

Bạn có thể đăng ký kiểu tham số tùy chỉnh trong khi mod của bạn đang khởi động trong method onInitialize, sử dụng class ArgumentTypeRegistry:

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

Sử Dụng Kiểu Tham Số Tùy Chỉnh

Bạn có thể sử dụng kiểu tham số tùy chỉnh trong một câu lệnh bằng cách đưa một instance của nó vào method .argument khi đang xây dựng một câu lệnh.

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

Thử chạy câu lệnh xem kiểu tham số của chúng ta có hoạt động không:

Tham số không hợp lệ.

Tham số hợp lệ.

Kết quả câu lệnh.