Befehlsargumente
Parameter werden in den meisten Befehlen verwendet. Manchmal sind sie optional, das heißt, wenn du diesen Parameter nicht angibst, wird der Befehl dennoch ausgeführt. Ein Knoten kann mehrere Parametertypen haben, aber es ist zu beachten, dass die Möglichkeit einer Mehrdeutigkeit besteht, die vermieden werden sollte.
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 diesem Fall musst du nach dem Befehlstext /argtater
eine ganze Zahl eingeben. Zum Beispiel, wenn du /argtater 3
ausführst, erhaltest du die Rückmeldung Called /argtater with value = 3
. Wenn du /argtater
ohne Argumente eingibst, kann der Befehl nicht korrekt geparst werden.
Dann fügen wir ein optionales zweites Argument hinzu:
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;
}))));
});
Jetzt kannst du eine oder zwei ganze Zahlen eingeben. Wenn du eine ganze Zahl eingibst, wird ein Feedback-Text mit einem einzigen Wert ausgegeben. Wenn du zwei Ganzzahlen angibst, wird ein Feedback-Text mit zwei Werten ausgegeben.
Du kannst es unnötig finden, ähnliche Ausführungen zweimal anzugeben. Daher können wir eine Methode erstellen, die in beiden Ausführungen verwendet wird.
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;
}
Benutzerdefinierte Argumenttypen
Wenn Vanilla nicht den von dir benötigten Argumenttyp verfügt, kannst du deinen eigenen erstellen. Dazu musst du eine Klasse erstellen, die das Interface ArgumentType<T>
erbt, wobei T
der Typ des Arguments ist.
Du musst die Methode "parse" implementieren, die die Eingabezeichenfolge zu dem gewünschten Typ parst.
Du kannst zum Beispiel einen Argumenttyp erstellen, der eine BlockPos
aus einer Zeichenkette mit dem folgenden Format parst: {x, y, z}
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;
}
Benutzerdefinierte Argumenttypen registrieren
WARNING
Du musst den benutzerdefinierten Argumenttyp sowohl im Server als auch im Client registrieren, sonst wird der Befehl nicht funktionieren!
Du kannst deinen benutzerdefinierten Argumenttyp in der Methode onInitialize
deines Mod-Initialisierers mit der Klasse ArgumentTypeRegistry
registrieren:
java
ArgumentTypeRegistry.registerArgumentType(
new Identifier("fabric-docs", "block_pos"),
BlockPosArgumentType.class,
ConstantArgumentSerializer.of(BlockPosArgumentType::new)
);
Benutzerdefinierte Argumenttypen verwenden
Wir können unseren benutzerdefinierten Argumenttyp in einem Befehl verwenden, indem wir eine Instanz davon an die Methode .argument
im Builder des Befehls übergeben.
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;
})
));
});
Durch das Ausführen des Befehls, können wir testen, ob der Argumenttyp funktioniert oder nicht: