命令注册
在前面的章节中,我们详细了解了 Brigadier 的工作原理,但从未真正说明如何注册命令。所以我们现在就来做这件事!
LifecycleEventManager
在 Paper 中,Brigadier 命令是使用 LifecycleEventManager 注册的。这是一个特殊的类,它允许我们以一种方式注册命令,使我们永远不必
担心处理各种服务器重载事件,比如 /reload。相反,无论我们使用 LifecycleEventManager 注册什么,都会在需要时重新注册。
但如何获取能够注册命令的 LifecycleEventManager 呢?有两个"上下文"可以使用 LifecycleEventManager。第一个,
也是首选的,是在我们插件的 PluginBootstrap 类中。
在插件引导程序中注册
这需要你使用 paper-plugin.yml 插件。
如果你不使用 paper-plugin.yml,你可以在插件的主类中注册命令。
我们可以通过在引导方法中运行 context.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, commands -> {})
来获取能够注册命令的 LifecycleEventManager,像这样:
public class CustomPluginBootstrap implements PluginBootstrap {
@Override
public void bootstrap(BootstrapContext context) {
context.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, commands -> {
// 在这里注册你的命令...
});
}
}
快速回顾一下这一切的含义:
通过运行 context.getLifecycleManager(),我们获得一个 LifecycleEventManager<BootstrapContext> 对象。我们可以在其上调用
LifecycleEventManager#registerEventHandler(LifecycleEventType, LifecycleEventHandler) 来获取我们正确的生命周期事件。第一个参数声明
我们想要注册内容的生命周期事件类型,第二个参数是一个看起来像这样的接口:
@FunctionalInterface
public interface LifecycleEventHandler<E extends LifecycleEvent> {
void run(E event);
}
由于它是一个函数式接口,我们可以不实现它,而只是传入一个有一个参数 E 且没有返回值的 lambda。E 泛型类型是一个
ReloadableRegistrarEvent<Commands>,因此也是我们的 lambda 参数的类型。
ReloadableRegistrarEvent<Commands> 类有两个方法:ReloadableRegistrarEvent.Cause cause() 和 Commands registrar()。对我们来说更相关的方法是
registrar 方法。通过它我们可以注册我们的命令。
在插件主类中注册
在插件主类中获取用于命令的 LifecycleEventManager 与在 PluginBootstrap 类中访问它的方式非常相似,区别在于
我们不是使用在 PluginBootstrap 类的引导方法中提供给我们的 BootstrapContext 来获取 LifecycleEventManager,而是可以直接使用
JavaPlugin#getLifecycleManager 来检索它。
public final class PluginMainClass extends JavaPlugin {
@Override
public void onEnable() {
this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, commands -> {
// 在这里注册你的命令...
});
}
}
这遵循与 PluginBootstrap 相同的概念,只是我们不是得到一个 LifecycleEventManager<BootstrapContext>,而是得到一个
LifecycleEventManager<Plugin>。这对我们的用例来说并不重要,但你最好知道这一点。
其余的方法与 PluginBootstrap 参数化的 LifecycleEventManager 完全相同。
使用 Commands 类注册命令
现在我们通过事件处理程序中的 commands.registrar() 访问了 Commands 类的实例,我们可以访问 Commands#register
方法的几个重载。
注册 LiteralCommandNode
大多数情况下,你会使用 LiteralArgumentBuilder 来构建你的命令树。为了从该对象检索 LiteralCommandNode,我们需要调用
LiteralArgumentBuilder#build() 方法:
LiteralArgumentBuilder<CommandSourceStack> command = Commands.literal("testcmd")
.then(Commands.literal("argument_one"))
.then(Commands.literal("argument_two"));
LiteralCommandNode<CommandSourceStack> buildCommand = command.build();
或者简短一点:
LiteralCommandNode<CommandSourceStack> buildCommand = Commands.literal("testcmd")
.then(Commands.literal("argument_one"))
.then(Commands.literal("argument_two"))
.build();
现在我们已经检索到了 LiteralCommandNode,我们可以注册它。为此我们有多个重载,它们可以选择设置别名和/或描述。
注册我们的 "testcmd" 可能看起来像这样:
this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, commands -> {
commands.registrar().register(buildCommand);
});
注册 BasicCommand
BasicCommand 是一种类似 Bukkit 的定义命令的方式。我们不是构建命令树,
而是允许所有用户输入并将参数作为简单的字符串数组检索。这种类型的命令对于非常简单的基于文本的命令特别有用,
比如 /broadcast 命令。你可以在这里阅读更多关于基本命令的详细信息。
假设你已经有了你的 BasicCommand 对象,我们可以这样注册它:
final BasicCommand basicCommand = ...;
this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, commands -> {
commands.registrar().register("commandname", basicCommand);
});
与 LiteralCommandNode 类似,我们也有重载来为我们的命令设置各种附加信息。
进一步参考
- 关于 LifecycleEventManager 的快速参考,请点击这里。