跳到主要内容

生命周期API

生命周期API可用于生命周期相关的注册。它目前被Brigadier命令API使用。它也计划用于注册修改API。 通常,在启动过程很早就初始化的系统可以利用这个事件系统。

实验性

生命周期API及其使用的任何内容目前都是实验性的,将来可能会发生变化。

LifecycleEventManager

LifecycleEventManagerPlugin实例或 BootstrapContext绑定,具体取决于你从哪里访问它。例如在你的插件的主类中:

TestPlugin.java
@Override
public void onEnable() {
final LifecycleEventManager<Plugin> lifecycleManager = this.getLifecycleManager();
}

或者,使用引导程序:

TestPluginBootstrap.java
@Override
public void bootstrap(BootstrapContext context) {
final LifecycleEventManager<BootstrapContext> lifecycleManager = context.getLifecycleManager();
}

LifecycleEvents

获取正确的LifecycleEventManager后,通过从LifecycleEvents中选择事件类型来创建事件处理器:

TestPlugin.java
@Override
public void onEnable() {
final LifecycleEventManager<Plugin> lifecycleManager = this.getLifecycleManager();
PrioritizedLifecycleEventHandlerConfiguration<LifecycleEventOwner> config = LifecycleEvents.SOME_EVENT.newHandler((event) -> {
// 事件的处理器
});
}

配置

每个创建的处理器都可以通过多种方式进行配置。可用的配置选项 取决于事件类型本身,并且会因事件类型而异。

优先级

设置处理器的优先级可以确定它相对于同一事件类型的其他处理器的运行位置。 数字越小,运行越早。默认优先级是0。

监视器

将处理器标记为监视器将导致它在所有其他非监视器处理器 被调用后才被调用。只使用这个来检查事件中的某些状态。不要在 处理器中修改任何状态。

优先级和监视器状态是互斥选项,设置一个将重置另一个。

TestPlugin.java
@Override
public void onEnable() {
final LifecycleEventManager<Plugin> lifecycleManager = this.getLifecycleManager();
PrioritizedLifecycleEventHandlerConfiguration<LifecycleEventOwner> config = LifecycleEvents.SOME_EVENT.newHandler((event) -> {
// 事件的处理器
});
config.priority(10); // 设置优先级为10
// 或
config.monitor(); // 将处理器标记为监视器
}

注册

一旦处理器配置完成,就可以向生命周期管理器注册:

TestPlugin.java
@Override
public void onEnable() {
final LifecycleEventManager<Plugin> lifecycleManager = this.getLifecycleManager();
PrioritizedLifecycleEventHandlerConfiguration<LifecycleEventOwner> config = LifecycleEvents.SOME_EVENT.newHandler((event) -> {
// 事件的处理器
}).priority(10);
lifecycleManager.registerEventHandler(config);
}

还有一种不进行任何配置就直接注册处理器的简便方法:

TestPlugin.java
@Override
public void onEnable() {
final LifecycleEventManager<Plugin> lifecycleManager = this.getLifecycleManager();
lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS, (event) -> {
// 事件的处理器
});
}
备注

某些事件类型具有限制某些机制的特殊行为。如果插件在某些情况下注册处理器, 重新加载插件功能(通过/bukkit:reloadServer#reload())将被禁用。这是因为插件重新加载必须完全卸载插件及其 类,如果事件必须在插件卸载时运行,这就是一个问题。

为什么需要这个?

我们已经有了一个事件系统,为什么还需要另一个?这是一个合理的问题。答案是 有些事件在JavaPlugin实例创建之前就触发了,在MinecraftServer实例创建之前,就在服务器启动的最开始。这可以是在 所有注册表初始化之前,这是原版服务器上最先发生的事情之一。现有的Bukkit事件系统不是为在这个时间存在而设计的, 修改它以支持这个环境比仅仅为特定事件有一个单独的系统更麻烦。

技术解释

这里是一个不断扩展的列表,列出了为什么我们不能仅仅修改现有事件 系统来满足这个新需求的具体原因:

  • 你不能在Bukkit事件上使用泛型,因为它们是通过反射注册的,所以没有编译时检查。这是一个问题,因为事件大多会遵循一个非常 相似的模式,特别是注册表修改事件。如果我们不能使用泛型,就会有很多无用的类。

  • 另一个原因是现有系统有优先级,但总是有优先级。对于生命周期事件,可能有一些事件我们不想支持优先级(那么它将 仅基于插件加载顺序)。

  • 存在得太晚。HandlerList和事件注册都使用Plugin实例,而这在引导程序期间不存在,也不能存在。改变这一点将需要对现有系统进行大量重写, 并可能让期望所有RegisteredListeners都附加了Plugin的API用户感到困惑。

  • 新系统让我们可以使用接口和服务器实现来实现事件,这大大简化了它们。在Bukkit系统中,你可以通过让服务器实现事件 扩展API事件来实现这一点,但接口更灵活。

  • 新系统让我们可以在编译时强制执行基于注册上下文的事件注册位置。所以你甚至不能在错误的地方注册事件处理器, 这将是一个编译器错误,这要归功于我们使用泛型的实现。