反射¶
本篇内容具体表现在以下顶级函数:
/**
* 已注册的 ReflexRemapper
* 直接添加到改容器即可完成注册,起初用于转换 1.17 版本的混淆字段名称
*/
val remapper = ArrayList<ReflexRemapper>()
/**
* 不通过构造函数实例化对象
*/
fun <T> Class<T>.unsafeInstance(): Any
/**
* 通过构造方法实例化对象
*/
fun <T> Class<T>.invokeConstructor(vararg parameter: Any?): T
/**
* 执行方法
* @param name 方法名称
* @param parameter 方法参数
* @param fixed 是否为静态方法
*/
fun <T> Any.invokeMethod(name: String, vararg parameter: Any?, fixed: Boolean = false): T?
/**
* 获取字段
* @param path 字段名称,使用 "/" 符号进行递归获取
* @param fixed 是否为静态字段
*/
fun <T> Any.getProperty(path: String, fixed: Boolean = false): T?
/**
* 修改字段
* @param path 字段名称,使用 "/" 符号进行递归获取
* @param value 值
* @param fixed 是否为静态字段
*/
fun Any.setProperty(path: String, value: Any?, fixed: Boolean = false)
无论是对于方法还是字段的反射,都会缓存并对所有父类及接口进行递归检查。了解过 Bukkit 逆向的同学参考以下代码。
// 获取 CraftPlayer 中的 entity 字段,并继续获取 locale 字段。
player.getProperty<String>("entity/locale")