Paramenterverarbeitung

The Command Builder API comes with a powerful argument parser. It converts the string input to java base types (integers, booleans, strings) or game objects (players, worlds, block types, …). The parser supports optional arguments and flags. It also handles TAB completion of arguments.

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!

When creating a command, consider whether the argument could return multiple values, for example, whether a player argument could support multiple players when using a selector. If you support multiple values the users need to type only one command and can use an easier command syntax. Example: /tell @a Who took the cookies?

Tipp

You can use the GenericArguments#onlyOne(CommandElement) element to restrict the amount of returned values to a single one, so you can safely use args.<T>getOne(String). However the user will still get a message, if they try to select more than one value.

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.

Apply the CommandElement to the command builder with the CommandSpec.Builder#arguments(CommandElement…) method. It is possible to pass more than one CommandElement to the method, thus chaining multiple arguments (e.g. /msg <player> <msg>). This has the same effect as wrapping the CommandElement objects in a GenericArguments#seq(CommandElement…) element.

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;

PluginContainer plugin = ...;

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((CommandSource src, CommandContext args) -> {

            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

requiringPermissionWeak

Requires the command sender to have the specified permission in order to use the given command argument. Does not throw an error if the user does not have the permission.

geerbt

Tipp

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

Warnung

Don’t expect that a CommandElements will only ever return a single value, a lot of them support multiple return values; some might even support regular expressions or use a command selector. This is intentional as it makes commands easier to use. Example: /tell @a BanditPlayer has the cookies!. If you want to make sure to only get a single value use GenericArguments#onlyOne(CommandElement).

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 {

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

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

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

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

        return new Vector2i(x, y);
    }

    private int parseInt(String input, CommandArgs args) throws ArgumentParseException {
        try {
            return Integer.parseInt(input);
        } catch(NumberFormatException e) {
            throw args.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.

Using Selectors in Custom Command Elements

Sponge provides support for parsing selectors, meaning that you can make use of them in your custom elements. There are two steps in using selectors, parsing (getting a Selector from the string) and resolving (getting a set of Entity objects selected by the selector).

To parse a selector string, use the Selector#parse(String) method, passing the entire selector, including the @ symbol. This will turn the string into a Selector object that can be queried or resolved. Note that if the string is not a valid selector, an IllegalArgumentException will be thrown.

To resolve this selector, use Selector#resolve(CommandSource). This will return a set of Entity objects selected by the selector.

The following parseValue method from the CommandElement class attempts to parse a selector and return a set of entities based on the location of the CommandSource. If the passed string does not start with @, an exception will be thrown indicating that the passed argument is not a selector.

@Override
protected Object parseValue(CommandSource source, CommandArgs args) throws ArgumentParseException {
    String nextArg = args.next();
    if (nextArg.startsWith("@")) {
        Set<Entity> selectedEntities;
        try {
            selectedEntities = Selector.parse(nextArg).resolve(source);
        } catch (IllegalArgumentException e) {
            throw args.createError(Text.of("Could not parse selector."));
        }

        if (selectedEntities.isEmpty()) {
            throw args.createError(Text.of("No entities selected."));
        }

        return selectedEntities;
    }

    throw args.createError(Text.of("Not a selector."));
}

Tipp

Look at the SelectorCommandElement source code for an example of how selector parsing is performed in the standard Sponge CommandElements.