🇰🇷 한국어 (Korean - South Korea)
🇰🇷 한국어 (Korean - South Korea)
Appearance
🇰🇷 한국어 (Korean - South Korea)
🇰🇷 한국어 (Korean - South Korea)
Appearance
인수는 대부분의 명령어에서 사용됩니다. 다시 말해, 어떤 인수는 값을 입력하지 않더라도 명령어가 정상 작동한다는 의미입니다. 하나의 노드는 여러 개의 타입을 가질 수 있지만, 타입이 모호해지면 오류의 원인이 될 수 있으므로 그런 경우는 최대한 피해야 합니다.
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;
})));
});
이런 경우에는, /argtater
명령어 다음에 정수를 입력해야 합니다. 예를 들어, 만약 /argtater 3
를 실행하면, Called /argtater with value = 3
라고 피드백 메세지를 받을 것입니다. 반대로 /argtater
를 아무런 인수 없이 실행하면, 명령어가 올바르게 작동하지 않을 것입니다.
이제 선택적인 두 번째 인수를 추가해보겠습니다.
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;
}))));
});
이렇게 하면 한 개 또는 두 개의 정수형을 입력할 수 있게 됩니다. 만약 한 개의 정수만 입력하면, 피드백 메세지에선 한 가지 값만 출력될 것입니다. 반대로 두 개의 정수을 모두 입력하면, 피드백 메세지에선 두 개의 값을 모두 출력할 것입니다.
비슷한 처리를 두 번이나 정의할 필요는 없습니다. 대신, 비슷한 처리를 하는 두 가지 인수는 이렇게 만들 수 있습니다.
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;
}
만약 바닐라에 사용하려는 인수 타입이 없다면, 직접 인수 타입을 만들 수도 있습니다. 만드는 방법을 알아보자면, 먼저 ArgumentType<T>
인터페이스를 상속하는 클래스를 만들어야 합니다.
이제 입력된 문자열을 원하는 타입으로 변환하기 위해 parse
메소드를 구현해야 합니다.
예를 들어, {x, y, z}
형태로 입력된 문자열을 BlockPos
로 변환해보겠습니다.
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
명령어를 올바르게 작동하게 하려면 서버와 클라이언트 모두에 사용자 정의 인수 타입을 등록해야 합니다!
모드 초기화 단계의 onInitialize
메소드 에서 ArgumentTypeRegistry
클래스를 통해 사용자 정의 인수 타입을 등록할 수 있습니다.
ArgumentTypeRegistry.registerArgumentType(
new Identifier("fabric-docs", "block_pos"),
BlockPosArgumentType.class,
ConstantArgumentSerializer.of(BlockPosArgumentType::new)
);
명령어 빌더의 .argument
메소드에 인스턴스를 입력하여 명령어에 사용자 정의 인수 타입을 사용할 수 있습니다.
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;
})
));
});
명령어를 실행하여 인수 형태가 작동하는지 여부를 확인할 수 있습니다.