RetroFuturaBootstrap 加载插件

基本信息

属性 值
插件类 me.eigenraven.lwjgl3ify.rfb.Lwjgl3ifyRfbPlugin
注册方式 src/main/resources/META-INF/rfb-plugin/lwjgl3ify.properties
properties 中 name LWJGL3ify
transformerExclusions me.eigenraven.lwjgl3ify
实现接口 com.gtnewhorizons.retrofuturabootstrap.api.RfbPlugin
注册的转换器数量 4
提供的 RFB 转换器 见 RFB 字节码转换器

Lwjgl3ify 自身不是 RetroFuturaGradle 构建,而是 GTNH RetroFuturaGradle 体系下的构建(build.gradle.kts:1-4 导入 com.gtnewhorizons.retrofuturagradle.*)。它以 RFB 早期加载插件 形式被 java.system.class.loader=com.gtnewhorizons.retrofuturabootstrap.RfbSystemClassLoader(build.gradle.kts:66)引导,先于 FML coremod 执行。

功能

插件发现

RetroFuturaBootstrap 通过扫描 META-INF/rfb-plugin/*.properties 发现插件。lwjgl3ify.properties 的实际内容为(src/main/resources/META-INF/rfb-plugin/lwjgl3ify.properties:1-9):

name=LWJGL3ify
version=${version}
additionalVersions=
className=me.eigenraven.lwjgl3ify.rfb.Lwjgl3ifyRfbPlugin
transformerExclusions=me.eigenraven.lwjgl3ify
versionConstraints=
loadBefore=
loadAfter=
loadRequires=

${version} 是 Gradle 占位符,由构建脚本 expand(mapOf("version" to versionString)) 替换为 project.version(build.gradle.kts:165-169)。

onConstruction 阶段

onConstruction(@NotNull PluginContext ctx)(Lwjgl3ifyRfbPlugin.java:28-49)按序执行:

  1. 排除自身 EarlyConfig 不被转换(:29)。
  2. 写入黑板键:lwjgl3ify:rfb-booted = Boolean.TRUE 与 lwjgl3ify:major-version = 3(:30-31)。前者正是 FML coremod 构造器用来判断"RFB 是否已启动"的依据(Lwjgl3ifyCoremod.java:38)。
  3. 用 MethodHandles 反射调用 EarlyConfig.load()(:32-41),失败经 Throwables.propagate 抛出。
  4. 调用 verifyJavaVersion()(:42)。
  5. 追加 4 个类加载器排除与 2 个转换器排除(:43-48)。

类加载器与转换器排除

类型 目标 行
类加载器排除 org.openjdk.nashorn :43
类加载器排除 jakarta.xml.bind. :44
类加载器排除 org.glassfish.jaxb. :45
类加载器排除 com.sun.istack. :46
转换器排除 org.lwjgl. :47
转换器排除 org.lwjglx. :48

即:LWJGL 自身与 lwjgl3ify 生成的 org/lwjglx/** 兼容层都不再经过类转换器递归处理。

另在 LwjglRedirectTransformer.onRegistration 中还追加了 me.eigenraven.lwjgl3ify.pack200. 的类加载器排除(LwjglRedirectTransformer.java:65-70)。

Java 版本闸门

verifyJavaVersion()(Lwjgl3ifyRfbPlugin.java:57-97):

  • 若系统属性 lwjgl3ify.skipjavacheck 为 true,整段跳过(:58)。
  • 仅当 java.specification.version 恰好等于 "17" 时才做进一步判定(:60)。
  • 通过 MethodHandles 取 Runtime.version(),与解析出的 17.0.6 比较(:62-75)。
  • 版本低于 17.0.6 时:无图形环境则向 System.err 打印三行横幅,有图形环境则弹 JOptionPane 错误框,随后 System.exit(1)(:76-90)。
  • 内部 catch (Throwable e) 包成 RuntimeException 重抛(:92-94),即版本判定失败不会被静默吞掉。

Java 21/25 等更高版本不受此函数限制——README 声明支持 “17.0.6, 19.0.2, 20 or 21 (or newer)”(README.MD 客户端安装章节)。该声明对应的是 README 而非本次核验的源码逻辑,源码里对 ≥18 无任何版本断言。

转换器注册

makeTransformers()(Lwjgl3ifyRfbPlugin.java:52-55)返回 4 个 RfbClassTransformer,顺序固定:

  1. LwjglRedirectTransformer
  2. ExtensibleEnumTransformer
  3. UnfinalizeObjectHoldersTransformer
  4. ForgePatchTransformer

该数组顺序是字节码改写流水线的一部分:LwjglRedirectTransformer.sortAfter() 返回 {"*", "mixin:mixin"}(LwjglRedirectTransformer.java:47-49),即它必须排在所有其他转换器之后执行。

数值

数值 值
RFB 插件数 1
makeTransformers() 返回元素数 4(Lwjgl3ifyRfbPlugin.java:53-54)
写入的黑板键 2(lwjgl3ify:rfb-booted、lwjgl3ify:major-version)
类加载器排除总数 6(插件 4 + 转换器 2)
转换器排除总数 2
Java 闸门最低版本 17.0.6(仅对 spec version 为 17 的运行时生效)
rfb-plugin properties 行数 9

交互

触发 行为
JVM 启动(RFB 引导) 插件被发现 → onConstruction → 注册 4 个转换器
Java 17 且 < 17.0.6 打印/弹窗后 System.exit(1),游戏无法启动
Java 17.0.6+ / Java 21 / Java 25 正常通过
设置了 -Dlwjgl3ify.skipjavacheck=true 跳过版本闸门

相关条目