事件监听器
要监听一个事件,必须要注册一个事件监听器。方法是创建一个方法,方法名任意,将方法的第一个参数定义为目标事件类型,然后给该方法附上 Listener 注解,如下所示。
import org.spongepowered.api.event.Listener;
@Listener
public void onSomeEvent(SomeEvent event) {
// Do something with the event
}
此外,包含这些方法的类必须在事件管理器注册:
小技巧
如果你的主类(即附有 Plugin 注解的类)有事件监听器,则你不需要注册事件对象,因为 Sponge 会自动执行此操作。
注解
事件总线 支持父类型 。例如, ChangeBlockEvent.Break 继承自 ChangeBlockEvent 。因此,一个监听了 ChangeBlockEvent
事件的插件可以收到来自 ChangeBlockEvent.Break
事件的通知。但是,一个监听了 ChangeBlockEvent.Break
事件的插件却不会收到来自 ChangeBlockEvent
事件的任何其他子类型事件的通知。
注册或取消事件监听器
在插件主类之外,添加注解``@Listener``来对事件监听器进行注册,你可以通过使用 EventManager#registerListeners(Object, Object) 方法来注册这个事件监听器,该方法需要一个插件主类的引用以及事件监听类的实例。
示例:在其他类中注册事件监听器
import org.spongepowered.api.Sponge;
public class ExampleListener {
@Listener
public void onSomeEvent(SomeEvent event) {
// Do something with the event
}
}
Sponge.getEventManager().registerListeners(this, new ExampleListener());
动态注册事件监听器
一些像脚本插件的插件或许会希望有动态注册事件监听器的功能。这是指事件监听器不是单纯通过 @Listener
来注册的,而是让保有监听器的类实现 EventListener
接口。这个事件监听器可以通过调用 EventManager#registerListener
来注册,该方法需要插件主类的引用,被监听的事件类和这个实现了 EventListener
类的实例作为参数。同时,你可以将 Order 参数放在监听器参数之前,来指定该事件监听器的执行 Order
。或者在监听器类参数之前传入一个额外的布尔值参数,来决定这个监听器是否在服务器启动之前被调用。
示例:实现 EventListener
import org.spongepowered.api.event.EventListener;
import org.spongepowered.api.event.block.ChangeBlockEvent;
public class ExampleListener implements EventListener<ChangeBlockEvent.Break> {
@Override
public void handle(ChangeBlockEvent.Break event) throws Exception {
[...]
}
}
示例:动态注册事件监听器
EventListener<ChangeBlockEvent.Break> listener = new ExampleListener();
Sponge.getEventManager().registerListener(this, ChangeBlockEvent.Break.class, listener);
小技巧
通过 @Listener
注解注册的监听器可自行决定其执行顺序(参见 关于 @Listener 部分的内容)。对于动态注册的事件监听器,可通过向 EventManager#registerListener
传入第三个参数 Order
来实现一样的效果。
取消注册事件监听器
你可以通过使用 EventManager#unregisterListeners(Object) 方法来去取消一个事件监听器的注册,该方法接受一个事件监听器类的实例作为参数。
EventListener listener = ...;
Sponge.getEventManager().unregisterListeners(listener);
或者,你可以通过传入一个插件的引用,调用 EventManager#unregisterPluginListeners(Object) 方法来取消掉所有该插件注册的事件监听器。请务必注意这个方法会移除 所有 此插件的事件监听器,包括那些用 @Listener
注册的监听器。
PluginContainer plugin = ...;
Sponge.getEventManager().unregisterPluginListeners(plugin);
关于 @Listener
注解 @Listener
有若干个可配置的字段:
order
用于设置事件监听器的执行优先级。参见 SpongeAPI 中 Order 这一枚举以获取可能的order
选项。beforeModifications
指定事件监听器是否在服务端 Mod ,如 Forge Mod 之前执行,默认为 false 。
默认情况下, @Listener
将会被配置成当事件是可取消而且已被(例如另一个插件)取消时,你的事件监听器 不 会被执行。
GameReloadEvent
为了防止所有的插件提供其自己的重新加载(Reload)命令。Sponge 提供了一个内置的回调方法用于插件监听,并在执行时,执行任何重新加载的操作。重新加载的操作到底是什么样子的完全由插件自己去决定。当诸如 /sponge plugins reload
这样的命令被执行时,事件 GameReloadEvent 将会被触发。重新加载这一操作并不一定局限于重新加载配置。
import org.spongepowered.api.event.game.GameReloadEvent;
@Listener
public void reload(GameReloadEvent event) {
// Do reload stuff
}
注意这和一般理解上的“重新加载”不同,这个事件仅仅是用于插件的回调,实际上其他的什么事情都没有做。
发布事件
为了调度一个事件,你需要一个实现了 Event 接口的对象。
你可以通过事件总线( EventManager )触发事件:
boolean cancelled = Sponge.getEventManager().post(theEventObject);
如果该事件被取消,则返回 true
,否则为 false
。
发布 Sponge 事件
内建的事件实例可以通过 SpongeEventFactory
静态生成。这个类的代码是自动生成的,因此并没有相关的 JavaDocs。你可以通过你的 IDE 的自动补全,列出已有的方法。一个事件实例通过 SpongeEventFactory
生成后,将会被作为 EventManager#post(Event) 方法的参数传入。
示例:发布 LightningEvent(闪电事件)
import org.spongepowered.api.event.action.LightningEvent;
import org.spongepowered.api.event.cause.Cause;
import org.spongepowered.api.event.cause.EventContext;
import org.spongepowered.api.event.cause.EventContextKeys;
import org.spongepowered.api.event.SpongeEventFactory;
PluginContainer plugin = ...;
EventContext eventContext = EventContext.builder().add(EventContextKeys.PLUGIN, plugin).build();
LightningEvent lightningEvent = SpongeEventFactory.createLightningEventPre(Cause.of(eventContext, plugin));
Sponge.getEventManager().post(lightningEvent);
警告
Cause 不能为空,它至少应该包含你的插件主类。