构建一个命令

第一步是获取一个新的 CommandSpec Builder。这一 Builder 提供用于编辑命令的帮助信息、参数、以及命令逻辑的一些方法。这些方法可以使用链式调用的方式调用。

最后你需要使用 CommandSpec.Builder#build() 方法生成一个命令。

然后你需要注册命令。

示例:创建一个简单的命令

import org.spongepowered.api.Sponge;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.command.spec.CommandSpec;

CommandSpec myCommandSpec = CommandSpec.builder()
    .description(Text.of("Hello World Command"))
    .permission("myplugin.command.helloworld")
    .executor(new HelloWorldCommand())
    .build();

Sponge.getCommandManager().register(plugin, myCommandSpec, "helloworld", "hello", "test");

对于 CommandSpec Builder 的方法概述

方法

说明

executor

定义命令的逻辑(详见“编写一个命令执行器(Command Executor)”一节)。

如果没有子命令,那么必须设置一个执行器。

arguments

设置这个命令的参数描述(详见 参数解析 )。

permission

设置这个命令运行前将会检查的权限。

description

对于这个命令的目的的一个简短的描述,这一描述将用于命令的帮助信息中。

extendedDescription

设置一个用于较长的帮助信息的扩展说明。该说明将被追加到简短的描述后。

child

将子命令添加到这个命令和它的别名中(详见 子命令 )。

children

设置这个命令的所有子命令(详见 子命令 )。

inputTokenizer

定义如何解析参数。默认情况下,解析器将把参数按空格拆分,被双引号引起来的作为单个参数。

例如: /tpworld Notch "My World" 将会返回两个参数: NotchMy World

build

生成这一命令。然后你需要注册你生成的命令。

编写一个命令执行器(Command Executor)

创建一个简单的命令唯一所需的组件就是命令执行器,它负责整个命令的主逻辑。

这个命令执行器必须实现一个 CommandExecutor 接口,这一接口定义了 CommandExecutor#execute(CommandSource, CommandContext) 方法,用于在命令执行时调用并传入两个参数:

  • 执行命令的对象(Source),如服务端命令行、命令方块或者一个玩家

  • 命令上下文(Context),其中包含了被处理过的参数(详见 参数解析

示例:一个简单的命令执行器

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.spec.CommandExecutor;

public class HelloWorldCommand implements CommandExecutor {

    @Override
    public CommandResult execute(CommandSource src, CommandContext args) throws CommandException {
        src.sendMessage(Text.of("Hello World!"));
        return CommandResult.success();
    }
}

小技巧

你可以使用 匿名类 以在创建命令的时候定义一个命令执行器(参见 参数解析 中的示例)。

只允许玩家使用的命令

有的时候需要只允许玩家执行一个命令(例如 /suicide 命令)。

可以通过一个 instanceof 检查来确定 CommandSource 的类型:

import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.command.source.CommandBlockSource;
import org.spongepowered.api.command.source.ConsoleSource;

if(src instanceof Player) {
    Player player = (Player) src;
    player.sendMessage(Text.of("Hello " + player.getName() + "!"));
}
else if(src instanceof ConsoleSource) {
    src.sendMessage(Text.of("Hello GLaDOS!"));
    // The Cake Is a Lie
}
else if(src instanceof CommandBlockSource) {
    src.sendMessage(Text.of("Hello Companion Cube!"));
    // <3
}

注解

我们建议你添加一个可选的 [player] 参数以使命令 对服务端命令行也足够友好 (例如 /suicide [player] )。

最简单的解决方案应该是附加一个 playerOrSource 元素(参见 参数解析)。

命令执行结果

CommandExecutor#execute() 方法必须返回一个 CommandResult,也就是命令执行结果。在大多数情况下,命令执行成功时返回一个 CommandResult#success() ,失败时返回一个 CommandResult#empty() ,是足够用的。如果需要传达更多信息,我们需要一个提供了若干个分别传入一个整数的用于设置属性的方法的 CommandResult#builder() 来解决问题。所有没有被 CommandResult#builder() 设置的属性将会为空。

命令方块可以使用这些值来修改记分板(Scoreboard)的数据统计,然后可以用于在多个命令方块的组合中发挥作用。如果想要了解这些数据是如何访问的,可以参见 这里

示例:创建一个命令执行结果

CommandResult result = CommandResult.builder()
    .affectedEntities(42)
    .successCount(1)
    .build();

这个示例使用一个 Builder 以创建一个 CommandResult 用于使该命令影响到四十二个实体,并表现为成功。

错误处理

execute() 方法可能会抛出一个 CommandException 用于表示命令执行时出了错。如果抛出了这样一个异常,那么其消息会被以错误消息的形式呈现给执行命令的对象。如果一个命令的参数没有办法解析,那么会自动抛出一个 ArgumentParseException 异常,这个异常是 CommandException 的子类。