Skip to main content

杂项


循环执行逻辑

在《灭》中,我们需要监测世界上新增的火焰,如果没有对应的自动消防水炮能够立即处理,则将新增的火焰存入缓存中,在之后重复检查,直至火焰熄灭或者被自动消防水炮处理;

在R6MS中,我们需要常常检测正在等待匹配的玩家,通过一定的算法选择合适的玩家,建立一局新的对战。

这些需要一直重复做的事情,我们当然应该放在tick中去执行。

TickEvent类下,有五种不同的子类可供选择:

TODO


两个不同的类的实例要是各自注册了一个一模一样的事件监听器,事件响应的时候会报ClassCastException


重复继承问题

这种情况在造轮子时更容易遇到。你的mod在开发环境下一切正常,但却在生产环境下崩溃,错误报告中有这样一行:

Caused by: java.lang.AbstractMethodError: Receiver class cn.ussshenzhou.t88.gui.widegt.TButton does not define or inherit an implementation of the resolved method 'abstract int getX()' of interface cn.ussshenzhou.t88.gui.widegt.TWidget.

这是典型的重复继承后混淆产生的问题,它的大体原理是这样:

你出于某种目的让YourClass继承了一个原版类VanillaClass,又实现了一个新接口IYourInterface,但是恰好这个新接口内的foo()方法在VanillaClass中也有一个同名的方法。

在开发环境下不会有任何问题,yourClass.foo()调用的就是YourClass#foo(),不会有任何毛病;在生产环境可就不一样了:在你构建mod时,所有的原版方法都会被重混淆——很不幸的是,混淆工具并不知道此foo()非彼foo()

假如VanillaClass#foo()的SRG名是bar(),那你的YourClass#foo()就会被混淆成为YourClass#bar()(因为看起来是从原版父类那里继承来的),但是yourClass.foo()却不会被改变(因为看起来是从新接口实现的)。然后等到生产环境运行yourClass.foo()的时候——找不到foo()了。

一种简单而高效的补救措施是把你的新方法改个名,就像T88里的tickT()isVisibleT()getXT()getYT()一样:

info

另一种比较沙雕的办法是反向改名:

显然,由于SRG名没有可读性而不推荐。

你应该可以感觉到,这种错误在编写阶段很难发现——开发环境完成测试不代表生产环境就万事大吉了。