无敌三脚猫
本帖最后由 无敌三脚猫 于 2023-3-2 22:57 编辑

https://www.mcbbs.net/thread-874131-1-1.html
这边我看过很多次了,最近才发现一个问题
跟没接触过cnpc的人解释一下,这个mod有一个脚本系统,可以用Nashorn引擎写js脚本
上述脚本中出现了一个奇怪的东西
  1. var Event=Java.type("net.minecraftforge.event.ServerChatEvent");
  2. var event=new Event();
复制代码
咦?这哪儿来的无参构造?
如果在java里写new net.minecraftforge.event.ServerChatEvent(),会显示构造函数 ServerChatEvent()未定义
因为ServerChatEvent真的只有这一个构造函数
  1.     public ServerChatEvent(EntityPlayerMP player, String message, ITextComponent component)
  2.     {
  3.         super();
  4.         this.message = message;
  5.         this.player = player;
  6.         this.username = player.getGameProfile().getName();
  7.         this.component = component;
  8.     }
复制代码
可能不同版本具体的参数不一样,不过这不重要,这个类确实是在每个版本都没有无参构造,所以Nashorn是怎么把它new出来的?而且没有报错(我写过了)
不关nashorn的事,是forge干的

youyihj
Unsafe 的 allocateInstance 方法?没用过 Nashorn 盲猜的。

Neige
本帖最后由 Neige 于 2023-3-2 13:23 编辑

我拿bukkit的AsyncPlayerChatEvent试了一下,不行,会报they do not match any of its method signatures
你这很怪

美味的曲奇
Nashorn 调用无参构造会报出
TypeError: Can not create new object with constructor ClassA with the passed arguments; they do not match any of its method signatures.

Unsafe.allocateInstance 可以做到强制实例 但从我这里来看Nashorn 没有采用这个
也许是版本不同

无敌三脚猫
本帖最后由 无敌三脚猫 于 2023-3-2 22:26 编辑
美味的曲奇 发表于 2023-3-2 17:43
Nashorn 调用无参构造会报出
TypeError: Can not create new object with constructor ClassA with the pas ...

刚刚,我改我mod的字节码,改出了一句new ServerChatEvent()
new net/minecraftforge/event/ServerChatEvent
dup
invokespecial net/minecraftforge/event/ServerChatEvent <init> ()V
pop
然后,没有崩溃,也没有报错
我感觉forge可能干了什么不得了的事情,在游戏启动过程中强行给所有事件都加上了无参构造,但是为什么呢?
算了不管那个了,我现在想问问@Hueihuea是怎么发现这一神奇特性的
好了不用问了

youyihj
翻了一下 Forge 事件的实现,还真是。
用 ASM 给每个 Event 加了一个默认的无参构造器,因为 Forge 注册事件监听器的实现,就是用反射无参创建一个事件,好用 getListenerList 实例方法获取这个类的 ListenerList,往这个列表加监听器才算注册。和那个教程的写法一样。

但为啥不直接在 EventBus 记录一个 Map<Class<?>, ListenerList> 呢?怪哦。

无敌三脚猫
本帖最后由 无敌三脚猫 于 2023-3-3 10:19 编辑
youyihj 发表于 2023-3-2 22:08
翻了一下 Forge 事件的实现,还真是。
用 ASM 给每个 Event 加了一个默认的无参构造器,因为 Forge 注册事 ...

用ASM加无参构造就已经很怪了,明明可以直接写进源码的
我后来想到了一点,可能是因为有些final的成员变量,所以不能直接写无参构造