Paramenterverarbeitung

Die Command-Builder API verfügt über einen starken Argument Parser. Dieser konvertiert die Stringeingaben zu Java Basistypen (Integer, Booleans, Zeichenketten) oder Spielobjekte (Spieler, Welten, Blocktypen,…). Der Parser unterstützt optionale Argumente und Flags. Er stellt auch die TAB-Autovervollständigung zur Verfügung.

Die Analysierten Argumente werden im CommandContext Objekt gespeichert. Wenn der Parser ein einzelnes Objekt zurückgibt, kann man es mit CommandContext#getOne(String). Optionale und schwache Argumente können Optional.empty() zurückgeben.

Viele der Parser können mehr als ein Objekt (z.B. mehrere Spieler mit einem übereinstimmendem Usernamen) zurückgeben. In diesem Fall muss man die CommandContext#getAll(String) Methode benutzen, um die Collection mit möglichen übereinstimmungen zu bekommen. Andernfalls wirft das Content Objekt eine Exception!

Tipp

Man kann das GenericArguments#onlyOne(CommandElement) Element benutzen, um die Anzahl der zurückgegebenen Werte auf eins zu Limitieren, so kann man sicher args.<T>getOne(String key) benutzen.

Um ein neues CommandElement (Argument) zu erstellen, benutze die GenericArguments Factory Klasse. Viele Befehlselemente benötigen einen kurzen Text key, welcher in einer Error- und Hilfenachricht angezeigt wird.

Wenn das CommandElement auf den Befehles Builder mit der CommandSpec.Builder#arguments(CommandElement…) Methode an. Es ist möglich, mehr als ein CommandElement an die Methode zu übergeben und damit mehrere Argumente (z.B. /msg <player> <msg>) zu verketten. Dies hat die gleichen Auswirkungen, wie wenn du die CommandElemente mit einem GenericArguments#seq(CommandElement…) Element umgibst.

Beispiel: Erstellen eines Befehls mit mehreren Argumenten

import org.spongepowered.api.Sponge;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.command.CommandException;
import org.spongepowered.api.command.CommandResult;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.command.args.CommandContext;
import org.spongepowered.api.command.args.GenericArguments;
import org.spongepowered.api.command.spec.CommandExecutor;
import org.spongepowered.api.command.spec.CommandSpec;

CommandSpec myCommandSpec = CommandSpec.builder()
        .description(Text.of("Send a message to a player"))
        .permission("myplugin.command.message")

        .arguments(
                GenericArguments.onlyOne(GenericArguments.player(Text.of("player"))),
                GenericArguments.remainingJoinedStrings(Text.of("message")))

        .executor(new CommandExecutor() {
            @Override
            public CommandResult execute(CommandSource src, CommandContext args) throws CommandException {

                Player player = args.<Player>getOne("player").get();
                String message = args.<String>getOne("message").get();

                player.sendMessage(Text.of(message));

                return CommandResult.success();
            }
        })
        .build();

Sponge.getCommandManager().register(plugin, myCommandSpec, "message", "msg", "m");

Übersicht über die GenericArguments (vielseitigen) Befehlselemente

Befehlselemente

Beschreibung

Werttyp und Betrag

none

Erwartet keine Argumente. Dies ist das Standardverhalten einer CommandSpec.

Java-Basis-Typen

string

Erwartet von einem Argument ein String zu sein.

ein String

remainingJoinedStrings

Verbindet die verbleibenden, durch Leerzeichen getrennten, Argumente (Nützlich für Nachrichten Befehle).

ein String

bool

Erwartet von einem Argument ein Boolean zu sein.

ein Boolean

integer

Erwartet von einem Argument ein Integer zu sein.

ein Integer (eine Zahl ohne Kommastellen)

doubleNum

Erwartet von einem Argument ein Double zu sein.

ein Double

Spielobjekte

Spieler

Erwartet von einem Argument einen Online Spieler zu sein. Kann mehrere Spieler zurückliefern!

mehrere Player Instanzen

playerOrSource

Ähnlich wie player, aber gibt den Sender des Befehls zurück, falls keine passender Spieler gefunden wurde.

mehrere Player Instanzen

userOrSource

Ähnlich wie playerOrSource, aber gibt User statt Playern zurück.

mehrere User Instanzen

Welt

Erwartet von einem Argument eine Welt zu sein (enthält auch nicht geladende Welten).

mehrere WorldProperties

Dimension

Erwartet von einem Argument eine Dimension (END, NETHER, OVERWORLD) zu sein.

mehrere DimensionType Instanzen

Standort

Erwartet von einem Argument eine Location zu sein.

one Location

vector3d

Erwartet von einem Argument ein Vector3d zu sein.

ein Vector3d

catalogedElement

Erwartet von einem Argument, dass es Teil des angegeben CatalogTypen ist.

mehrere passende Elemente des angegebenen CatalogTypen

Suche

choices

Gibt ein Argument aus einer begrenzten Anzahl von Möglichkeiten zurück.

ein angegebener Wert

literal

Erwartet die wörtliche Abfolge von Argumenten (z.B. "i", "luv", "u": /cmd i luv u). Wirft einen Fehler, wenn die Argumente nicht übereinstimmen.

ein angegebener Wert

enumValue

Erwartet ein Argument, dass der Schlüssel zu dem angegebenen Enum ist.

mehrere passenden Elemente des angegebenen Enums

Hilfen

Können um ein Befehlselement gewickelt werden. Die Art des Wertes wird von dem umwickelten Element abgeleitet.

seq

Baut eine Sequenz von Befehlselementen (z.B. /cmd <arg1> <arg2> <arg3>).

geerbt

repeated

Erfordert, dass das angegebene Befehlselement mindestens eine bestimmte Anzahl von Malen auftaucht.

mehrere Werte passend zum Umwickelten

allOf

Erwartet, dass alle folgenden Argumente zu dem angegeben Befehlselement passen.

mehrere Werte passend zum Umwickelten

optional

Macht das angegebene Befehlselement optional. Wirft einen Fehler, wenn das Argument das falsche Format hat und es keine weiteren Argumente gibt.

geerbt

optionalWeak

Macht das angegebene Befehlselement optional. Wirft keinen Fehler, wenn das Argument das falsche Format hat und es keine weiteren Argumente gibt.

geerbt

firstParsing

Gibt ein Befehlselement zurück, dass dem ersten passenden Element entspricht (Nützlich zum Übersteuern von Befehlen, z.B. /settime <day|night|number>).

geerbt

onlyOne

Beschränkt das gegebene Befehlselement darauf, mit dem angegebenen Schlüssel nur einen Wert in den Kontext zu setzen.

geerbt

flags

Liefert einen Builder zur Erstellung von Befehlsoptionen (z.B. /cmd [-a] [-b <value>]) zurück.

Siehe Befehlsoptionen

Befehlsoption: ein Boolean

Befehlsoption mit Wert: ein String

Befehlsoption mit Wert: wie das Eingebettete

requiringPermission

Erfordert von der Befehlsquelle die entsprechende Berechtigung zu haben, um das gegebene Befehlsargument verwenden zu können

geerbt

Tipp

Schau dir die Javadocs von GenericArguments an, wenn du weitere Informationen brauchst.

Benutzerdefinierte Befehlselemente

Es ist möglich, benutzerdefinierte Befehlselemente (z.B. einen URL Parser oder ein Vector2i Element) zu erstellen, indem die abstrakte CommandElement Klasse erweitert wird.

Die CommandElement#parseValue(CommandSource, CommandArgs) Methode sollte einen bisher unverarbeitetes String Argument mit Hilfe von CommandArgs#next() holen und dieses in das gewünschte Objekt konvertieren. Die Methode sollte im Falle eines Fehlschlages eine ArgumentParseException werden.

Die CommandElement#complete(CommandSource, CommandArgs, CommandContext) Methode sollte CommandArgs#peek() verwenden, um das nächste unverarbeitete Argument auszulesen. Sie gibt eine Liste von Vorschlägen für die TAB-Autovervollständigung aus.

Beispiel: Definition des Vector2i Befehlselementes

Der Parser in diesem Beispiel liest zwei Eingabe-Argumente und konvertiert diese in einen Vektor.

import com.flowpowered.math.vector.Vector2i;
import org.spongepowered.api.command.args.ArgumentParseException;
import org.spongepowered.api.command.args.CommandArgs;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.command.args.CommandElement;

import java.util.Collections;
import java.util.List;

public class Vector2iCommandElement extends CommandElement {
    CommandArgs errorargs;

    protected Vector2iCommandElement(Text key) {
        super(key);
    }

    @Override
    protected Object parseValue(CommandSource source, CommandArgs args) throws ArgumentParseException {

        // <x> <y>
        errorargs=args;

        String xInput = args.next();
        int x = parseInt(xInput);

        String yInput = args.next();
        int y = parseInt(yInput);

        return new Vector2i(x, y);
    }

    private int parseInt(String input) throws ArgumentParseException {
        try {
            return Integer.parseInt(input);
        } catch(NumberFormatException e) {
            throw errorargs.createError(Text.of("'" + input + "' is not a valid number!"));
        }
    }

    @Override
    public List<String> complete(CommandSource src, CommandArgs args, CommandContext context) {
        return Collections.emptyList();
    }

    @Override
    public Text getUsage(CommandSource src) {
        return Text.of("<x> <y>");
    }
}

Beispiel: Verwendung des Vector2i Befehlselementes

// /plottp <x> <y>
CommandSpec myCommandSpec = CommandSpec.builder()
        .description(Text.of("Teleport to a plot"))
        .permission("myplugin.command.plot.tp")

        .arguments(new Vector2iCommandElement(Text.of("coordinates")))

        .executor(new MyCommandExecutor())
        .build();

Tipp

Wirf einen Blick auf den Quellcode der GenericArguments-Klasse für weitere Beispiele.