|
|
| + | <code>Events</code>(事件)是在游戏中监听某一特定行为发生的有效方式。它们可以被服务器(或插件)触发。<br /> |
| + | 例如某名玩家加入了服务器,抑或是某个方块被破坏时,都将触发对应事件。<br /> |
| + | 插件能够触发自定义事件,例如玩家完成了某个插件自定义的任务,以供其它插件监听。 |
| | | |
| + | == 你的监听器类 == |
| + | |
| + | 要进行监听,你需要创建一个类并实现 <code>Listener</code> 接口。<br /> |
| + | 类名可任取,不过建议使用与该类所监听的事件相关的名称。 |
| + | |
| + | <syntaxhighlight lang="java">public class ExampleListener implements Listener { |
| + | // ... |
| + | }</syntaxhighlight> |
| + | <span id="eventhandler"></span> |
| + | == <code>@EventHandler</code> == |
| + | |
| + | 要监听某一个事件,你需要创建一个含有 <code>@EventHandler</code> 注解 ( <code>annotation</code> ) 的方法。<br /> |
| + | 同理,方法名可任取,不过建议使用与该方法所监听的事件相关的名称,并避免无意义方法名。 |
| + | |
| + | == 监听器方法 == |
| + | |
| + | 方法体无需返回任何值,因此建议使用 <code>void</code> 作为返回类型。<br /> |
| + | 监听器方法有且仅有一个参数,其类型为该方法所监听的事件的类型。 |
| + | |
| + | <syntaxhighlight lang="java"> |
| + | public class ExampleListener implements Listener { |
| + | |
| + | @EventHandler |
| + | public void onPlayerJoin(PlayerJoinEvent event) { |
| + | // ... |
| + | } |
| + | } |
| + | </syntaxhighlight> |
| + | <blockquote>由于插件可以自定义事件,这里无法列出一份包括所有可监听事件的列表。不过在[https://jd.papermc.io/paper/1.19/org/bukkit/event/Event.html 这里]可以了解 Paper 所提供的 <code>Event</code> 类的全部子类。 |
| + | |
| + | 仅有实现了静态 <code>getHandlerList</code> 方法的事件才能被监听。 |
| + | </blockquote> |
| + | == 注册监听器 == |
| + | |
| + | 要注册监听器,你需要调用 <code>Bukkit.getPluginManager().registerEvents()</code> 并传入监听器类的实例和你的插件主类的实例。 |
| + | |
| + | 这一方法将会注册监听器,并允许它监听事件。<br /> |
| + | 这一方法通常写在你的插件主类的 <code>onEnable()</code> 方法中,此时监听器将在服务器开始计算游戏刻 (tick) 时注册。 |
| + | |
| + | <syntaxhighlight lang="java"> |
| + | public class ExamplePlugin extends JavaPlugin { |
| + | |
| + | @Override |
| + | public void onEnable() { |
| + | getServer().getPluginManager().registerEvents(new ExampleListener(), this); |
| + | } |
| + | } |
| + | </syntaxhighlight> |
| + | <span id="eventpriority"></span> |
| + | == EventPriority == |
| + | |
| + | 你也可以指定事件监听器的优先级。 |
| + | |
| + | <pre> |
| + | public class ExampleListener implements Listener { |
| + | |
| + | @EventHandler(priority = EventPriority.HIGH) |
| + | public void onPlayerJoin(PlayerJoinEvent event) { |
| + | // ... |
| + | } |
| + | } |
| + | </pre> |
| + | 你可以选择六个不同的优先级: - <code>EventPriority.LOWEST</code> - <code>EventPriority.LOW</code> - <code>EventPriority.NORMAL</code> - <code>EventPriority.HIGH</code> - <code>EventPriority.HIGHEST</code> - <code>EventPriority.MONITOR</code> |
| + | |
| + | 实际上优先级的顺序与直觉相反。优先级 '''越高''',事件被调用就 '''越晚'''。<br /> |
| + | 例如:你的插件需要对某个事件一锤定音,此后不希望被其他监听器再作覆盖,则需要使用<code>EventPriority.HIGHEST</code>。 |
| + | |
| + | <blockquote>'''注意'''<br /> |
| + | <code>MONITOR</code> 的优先级常常用于获得其他插件对事件的修改结果,而不是亲自修改它。具有此优先级的监听器在所有监听器中排在最后。<br /> |
| + | 因此这样的监听器可获悉先前插件对事件的修改,例如事件是否被取消(cancellation)和对事件中某些字段的修改(modification)。 |
| + | </blockquote> |
| + | == 取消事件 == |
| + | |
| + | 一些事件可以取消,阻止某些行为发生。这些事件类实现了 <code>Cancellable</code>。 |
| + | |
| + | 译注:事件的触发时机是在某个行为发生以前,当事件监听器全部运行完毕后,被插件所修改过的事件结果才会真正发生。 |
| + | |
| + | <syntaxhighlight lang="java"> |
| + | public class ExampleListener implements Listener { |
| + | |
| + | @EventHandler |
| + | public void onPlayerJoin(PlayerJoinEvent event) { |
| + | event.setCancelled(true); |
| + | } |
| + | } |
| + | </syntaxhighlight> |
| + | <blockquote>在你的插件取消某事件之前,请思考一下其它插件是否已经取消或更改了该事件。<br /> |
| + | 请先检查事件的各个字段再进行修改! |
| + | </blockquote> |
| + | 上面的例子会取消事件,这意味着玩家无法加入到服务器中。当一个事件被取消后,其他监听器将继续按顺序被调用下去,除非某个监听器在 <code>@EventHandler</code> 注解中添加了 <code>ignoreCancelled = true</code> 以忽略已取消的事件。 |
| + | |
| + | 如欲忽略已取消的事件,可以这样写: |
| + | |
| + | <pre> |
| + | public class ExampleListener implements Listener { |
| + | |
| + | @EventHandler(ignoreCancelled = true) |
| + | public void onPlayerJoin(PlayerJoinEvent event) { |
| + | // ... |
| + | } |
| + | } |
| + | </pre> |