桃渊林
本帖最后由 hcrgm1 于 2018-8-10 12:10 编辑

现在编程版的插件开发教程早已“落地生根,枝繁叶茂”,相信大家都能够学会开发插件的一些步骤,这次我就来个不同的,扩展一下大家的知识。
学过如何开发插件的童鞋们也都知道事件api的使用,这会我就发个高级货——自定义事件。
BukkitAPI提供的event包已经包含了我们可能用到的绝大多数事件,但是,可能遇到没有想要的事件的情况,或者想扩展一个事件供某些插件使用(比如这个玩家用某装备插件的一个命令修理了一个装备,这个装备插件就能传唤一个事件,供其它插件响应这个事件)。下面开始正文吧
我们就先新建一个类,用来描述这个自定义事件,确定好名字后就新建,然后使这个类继承org.bukkit.event.Event类(如果有多个事件是统一种类,那你也可新建一个抽象类继承Event类,表示这个种类的事件,写上需要用到的变量和方法,然后子事件类继承这个类就可以了,也可以提高代码重用性)
然后,写上必须写的一段代码(再次强调这个不能丢!!),如下代码块所示:
  1. private static final HandlerList handlers = new HandlerList();
  2. @Override
  3. public HandlerList getHandlers() {
  4.     return handlers;
  5. }
  6. public static HandlerList getHandlerList() {
  7.     return handlers;
  8. }
复制代码

HandlerList干什么用的?就是用来存储事件的,还有如果要注销事件也要用到HandlerList,具体就自己探讨吧
然后这个事件的雏形基本就出来了,这时已经定义好了一个事件,不过还没有任何用处。接下来只需写好可能会用到的方法,比如获取这个事件涉及的玩家啊(比如getPlayer()),这个事件发生在哪个事件啊(比如getWorld()),等等,这些我形象地称这些方法为getter,当然setter有时是必不可少的,千万不要忘记。
然后就大功告成,成功写好了自定义事件。我写的如下,友友们可以参考下:
  1. import org.bukkit.event.Event;
  2. import org.bukkit.event.HandlerList;

  3. public class MyEvent extends Event {
  4.     private static final HandlerList handlers = new HandlerList();
  5.     private Player player;

  6.     /* 这是类的构造器,按事件要实现的功能来取舍 */
  7.     public MyEvent(final Player player) {
  8.         this.player = player;
  9.     }

  10.     /* 获取这个事件涉及的玩家 */
  11.     public Player getPlayer() {
  12.         return player;
  13.     }

  14.     public void setMoney(double money) {
  15.         // 这个调用胡扯的哈,不要直接复制,怎么实现还得您自己码哈,而且这个方法也不是必要的,要看什么场合用
  16.         player.setMoney(money, true);
  17.     }

  18.     /* 这就是我在强调的要加上的两个方法 */
  19.     @Override
  20.     public HandlerList getHandlers() {
  21.         return handlers;
  22.     }

  23.     public static HandlerList getHandlerList() {
  24.         return handlers;
  25.     }
  26. }
复制代码

写好了,然而并没有结束,因为这个事件总得被传唤嘛!没有传唤就永远都不会响应,接下来教你如何传唤(调用)事件
org.bukkit.plugin.PluginManager类下有一个callEvent方法,其唯一的参数为Event event,你只需要创建你的Event的实例传入这个参数就可以了
怎么获取PluginManager对象呢?Bukkit.getServer().getPluginManager()这个方**返回PluginManager对象,然后就很简单了
语句大概就是这样:
  1. MyEvent event = new MyEvent(player);
  2. Bukkit.getServer().getPluginManager().callEvent(event);
复制代码

注意:你必须时刻牢记传唤你的事件,否则将不起作用!!!!注意:该方法使线程安全的,也就是说你可以放心地在异步线程/任务中调用此方法.
有些人就可能在这里问:“事件的取消呢!!”,别急,其实很简单,只要让你的事件实现Cancellable类,定义一个表示事件取消的布尔值然后写上下面的两个方法即可。
  1. public boolean isCancelled() {
  2.     return cancelled;
  3. }
  4. public void setCancelled(boolean cancel) {
  5.     this.cancelled = cancel;
  6. }
复制代码

而且,这两个方法不写IDE也会提醒你“Cancellable 接口的方法 xxx 未实现”
另外,我建议你在处理之前检测这个事件有没有被取消,没取消就执行相应动作,比如以下代码:
  1. if(!event.isCancelled()) {
  2.     // do sth......
  3. } else {
  4.     // do sth......
  5. }
复制代码

嗯。。写完了,接下来就跟普通事件一样去监听啦~
  1. public class MyListener implements Listener {
  2.     @EventHandler//(priority=EventPriority.等级,LOWEST最先执行但对事件产生地影响等级最低,MONITIR最后执行但对事件产生地影响等级最高,如果保持默认等级就不需要注释后的内容)
  3.     public voud onxxx(MyEvent event) {
  4.         // 自己写啦
  5.     }
  6. }
复制代码

上一个空白事件模板,大家可以偷偷懒
  1. import org.bukkit.event.Event;
  2. import org.bukkit.event.HandlerList;

  3. /* 一个简简单单的自定义事件模板,能够取消(如果您不希望你的事件能被取消,请不要实现Cancellable接口以及删去与此相关的一切代码) */
  4. public class EmptyEvent extends Event implements Cancellable {
  5.     private static final HandlerList handlers = new HandlerList();
  6.     private String mes;
  7.     private boolean cancelled; // 如果您希望你的事件能被取消这行不要删

  8.     public EmptyEvent(String mes) {
  9.         this.mes = mes;
  10.     }

  11.     public String getMessage() {
  12.         return mes;
  13.     }

  14.     public void setMessage(String mes) {
  15.         this.mes = mes;
  16.     }

  17.     /* 这两个方法绝对不能少 */
  18.     @Override
  19.     public HandlerList getHandlers() {
  20.         return handlers;
  21.     }

  22.     public static HandlerList getHandlerList() {
  23.         return handlers;
  24.     }

  25.     /* 如果您希望你的事件能被取消以下两个方法不要删去 */
  26.     public boolean isCancelled() {
  27.         return cancelled;
  28.     }

  29.     public void setCancelled(boolean cancel) {
  30.         this.cancelled = cancel;
  31.     }

  32. }
复制代码

顺便给点人气金粒嘛@( ̄- ̄)@

来自群组: 上古之石美工工作组

可可可可可乐
感谢,刚刚还在问人怎么自定义

MC_Miter
感谢教程
但是看不懂诶!

4one_R
一直用PluginManager注册listener,现在发现原来callEvent在这里…学习了!

Syro
请问语言?

EndOfStreamly
_(:зゝ∠)_蛮不错的,支持一下!

t9044
非常不错的教程贴~
编程开发帖就需要更多你这样的进阶的、非基础性教学的教学帖

yanggexuyang
感谢教程!终于明白我自定义事件不行的原因是没有getHandlerList了

2571612311
楼楼,有一个问题想请教一下
举个例子onPlayerJoin这个是在玩家加入的时候触发
但自定义事件我比如说要让两个玩家在一起时监听器触发
又该怎么做呢

w_cn
MyEvent event = new MyEvent(player);
Bukkit.getServer().getPluginManager().callEvent(event);
这两句代码 一般放在哪里?

TRLLolita
支持楼主一下!

w_cn
自定义事件的触发 一般都是放在 Bukkit自带的事件里面吗?
感觉没有好的例子 想不出来。。。
大佬们教导小弟一下

404565377
    public voud onxxx(MyEvent event) {
        // 自己写啦
    }

voud可还行(各种刁钻)

猿汐
学到了,感谢。

MT_meng
看不懂。。。

第一页 上一页 下一页 最后一页