Парсинг аргументов

API builder’а команд имеет мощный парсер аргументов. Он преобразует введённые данные в базовые типы Java (целочисленные, булевые, строки), либо же игровые объекты (игроки, миры, типы блоков, и т. д.). Парсер поддерживает необязательные аргументы и флаги. А также может совершать автозавершение аргументов при нажатии клавиши TAB.

Прошедшие парсинг аргументы сохраняются в объекты типа CommandContext. Если парсер возвращает один объект, то можно получить его при помощи args.<T>getOne(String key) (вместо T введите тип значения). Необязательные и слабые аргументы могут возвращать Optional.empty().

Многие парсеры могут возвращать более одного объекта (например, несколько игроков с соответствующим именем). В этом случае, Вам необходимо использовать метод args.<T>getAll(String key) для получения коллекции Collection возможных вариантов. Если этого не сделать, будет сгенерировано исключение!

Совет

You can use the GenericArguments#onlyOne(CommandElement) element to limit the amount of returned values to a single one, so you can safely use args.<T>getOne(String).

Для создания новых CommandElement (аргументы команды), используете фабричный класс GenericArguments. Многие элементы команды требуют короткий текстовый ключ, который отображается в ошибках и в сообщениях помощи.

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.

Пример: Создание команды с несколькими аргументами

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

Overview of the GenericArguments command elements

Элемент команды

Описание

Количество и тип значения

none

Не требует аргументов. Это обычное поведение CommandSpec.

Базовые типы Java

string

Требует аргумент типа String.

один String

remainingJoinedStrings

Соединяет все оставшиеся аргументы разделенные пробелами (может быть использовано для команд-сообщений).

один String

bool

Требует аргумент типа boolean.

один Boolean

integer

Требует аргумент типа integer.

один Integer

doubleNum

Требует аргумент типа double.

один Double

Игровые объекты

player

Ожидает аргумент в виде онлайн-игрока. Может возвращать несколько игроков!

несколько экземпляров Player

playerOrSource

Как player, но возвращает отправителя команды, если соответствующий игрок не был найден.

несколько экземпляров Player

userOrSource

Как playerOrSource, но возвращает пользователя, а не игрока.

несколько экземпляров User

world

Ожидает аргумент в виде мира (также включает выгруженные миры).

несколько WorldProperties

dimension

Ожидает аргумент в виде измерения (END, NETHER, OVERWORLD).

несколько экземпляров DimensionType

location

Ожидает аргумент в виде Location.

один Location

vector3d

Ожидает аргумент в виде Vector3d.

один Vector3d

catalogedElement

Expect an argument that is a member of the specified CatalogType.

multiple matching elements of the specified catalog type

Шаблоны

choices

Return an argument that allows selecting from a limited set of values.

one specified value

literal

Expect a literal sequence of arguments (e.g. "i", "luv", "u": /cmd i luv u). Throws an error if the arguments do not match.

one specified value

enumValue

Require the argument to be a key under the provided enum.

multiple matching elements of the specified enum

Утилиты

Can be wrapped around command elements. The value type is inherited from the wrapped element.

seq

Builds a sequence of command elements (e.g. /cmd <arg1> <arg2> <arg3>).

унаследованное

repeated

Require a given command element to be provided a certain number of times.

несколько унаследованных

allOf

Require all remaining args to match the provided command element.

несколько унаследованных

optional

Make the provided command element optional. Throws an error if the argument is of invalid format and there are no more args.

унаследованное

optionalWeak

Сделайте предоставленный командный элемент необязательным. Не выдает ошибку, если аргумент имеет недопустимый формат и больше нет аргументов.

унаследованное

firstParsing

Возвращает элемент команды, который соответствует первому предоставленному элементу (полезно для перегруженных команд, таких как /settime <day|night|<number>>).

унаследованное

onlyOne

Restricts the given command element to only insert one value into the context at the provided key.

унаследованное

flags

Returns a builder for command flags (e.g. /cmd [-a] [-b <value>]).

См. Флаги команд

Short Flag: one Boolean

Long Flag: one String

Value Flag: inherited

requiringPermission

Requires the command sender to have the specified permission in order to use the given command argument

унаследованное

Совет

Больше информации доступно в Javadoc: GenericArguments.

Пользовательские CommandElement’ы

Можно создать пользовательские командные элементы (например, URL-парсер или элемент Vector2i), расширив абстрактный класс CommandElement.

Метод CommandElement#parseValue(CommandSource, CommandArgs) должен получить необработанный аргумент в виде строки с помощью CommandArgs#next() и конвертировать его в объект. Если парсинг окажется неудачным, метод должен сгенерировать исключение ArgumentParseException.

Метод The CommandElement#complete(CommandSource, CommandArgs, CommandContext) должен использовать CommandArgs#peek() для прочтения следующего исходного аргумента. Этот метод возвращает список аргументов для автозавершения при нажатии клавиши TAB.

Пример: определение командного элемента Vector2i

В этом примере парсер читает два входных аргумента и преобразует их в вектор.

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

Пример: использование командного элемента Vector2i`

// /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();

Совет

Просмотрите исходный код класса GenericArguments, чтобы увидеть больше примеров.