用户:MashKJo/1.12.2模组开发教程/4.Forge事件系统:修订间差异

→‎@HasResult:​ // Edit via Wikiplus
→‎Minecraft事件的注册、取消和优先级:​ // Edit via Wikiplus
→‎@HasResult:​ // Edit via Wikiplus
第81行: 第81行:
=== @HasResult ===
=== @HasResult ===
这个注解同样用于修饰一个事件类,表明:该事件有“结果”——没错,事件监听方法一定为void,但是事件本身可以有结果——Event.Result这个枚举类中的三个实例:ALLOW、DEFAULT和DENY。它们的含义随着具体事件的类型而变化。这个说实话,不太常用,可以直接忽略。
这个注解同样用于修饰一个事件类,表明:该事件有“结果”——没错,事件监听方法一定为void,但是事件本身可以有结果——Event.Result这个枚举类中的三个实例:ALLOW、DEFAULT和DENY。它们的含义随着具体事件的类型而变化。这个说实话,不太常用,可以直接忽略。
== 自定义Minecraft事件 ==
说实话,这个在几乎所有情况下都没必要。既然你要自定义Minecraft事件了,那显然是给你自己的游戏元素用的——但是你直接去对应的类中写相应的实现代码不就行了?何必多此一举搞个事件?就算你想让你的模组和其他模组的联动更容易,你也大可暴露一些公开方法即可。
然而,还是说说如何操作吧。
首先你需要根据你的事件发挥的具体作用来判断你的事件类到底该继承什么已有的事件类——直接继承Event类是非常非常罕见的。然后再思考:你的事件都需要有哪些getter和setter?你的事件类的父类又有哪些getter和setter?理清楚你的事件类的构造方法所需要的形参列表。
然后就要到你想发布事件的方法里去new一个你的事件类型了,然后再发布事件:<code>EventBus#post</code>这个方法用于发布某个事件。这个方法是有boolean返回值的,返回true代表事件被取消。所以你一般该这么写:<code>if(!MinecraftForge.EVENT_BUS.post(new MyCustomEvent(...)))</code>。这个if语句后的代码块中,写你期望的默认实现。它的意思即:事件若未被取消,则按照默认实现处理游戏逻辑,同时执行事件监听方法中的追加逻辑。很明显,如果取消了该事件,则可以彻底接管这里的游戏逻辑。
实际上,Forge发布事件的原理就是这样的。但Forge还把发布事件的过程进行了一些包装:对于可取消的事件,if语句中调用的并非post方法,而是位于ForgeHooks和ForgeHooksClient这两个类中的静态方法。这些静态方法先对传入的参数进行了一定的处理,再return post方法的返回值。对于不可取消的事件,post方法一定返回false,那就不会用if了,直接post,相关的静态工具方法的返回值类型也是void而非boolean了。另外有时候ForgeHooks和ForgeHooksClient中的静态方法,还会再把post方法的调用代理给ForgeEventFactory中的静态方法。
另外,很多事件都有子类型:Pre和Post(一般是以静态内部类的形式出现在其父类中)。它们的发布时机通常是这样:Pre发布在默认的游戏逻辑执行前,而Post发布在这之后。一般的规律是:Pre可取消,而Post不可取消——毕竟Post发布的时候,默认的游戏逻辑都执行完了,取消了也没用了,因此就干脆设定为不可取消。所以一般来说,如果我们监听事件只是为了给原版的某些机制附加额外行为,那么监听Pre或Post都没区别;但如果想彻底覆盖原版的游戏逻辑,那么监听Pre并取消是最好的:<code>Event#setCanceled</code>。
行政员、​优秀编辑者、​界面管理员、​监督员、​管理员、​小部件编辑者
3,417

个编辑