第三方兼容钩子

基本信息

属性 值
目标模组枚举 me.eigenraven.lwjgl3ify.mixins.TargetedMod
枚举项数 6
兼容钩子入口 CommonProxy.runCompatHooks() / ClientProxy.runCompatHooks()
由 mixin 门控的兼容条目 3(见 第三方模组兼容 Mixin)
声明式依赖 无(@Mod 无 dependencies 参数)

LWJGL3ify 不在 @Mod 注解中声明任何硬依赖。它与第三方模组的关系全部是"检测到就打补丁 / 没检测到就跳过",因此可以安全地出现在任何整合包里。

功能

TargetedMod 枚举的 6 个判定目标

TargetedMod.java:11 定义 6 项,各有独立的判定方式:

枚举项 判定方式 行 用途
FASTCRAFT_1_25 字节码常量扫描:在 fastcraft.a 的方法指令中查找连续的 LDC "fcVersion" + LDC "1.25" :13-26 STB_TEXTURE_STITCHING_FOR_FASCRAFT
FASTCRAFT_ANY setCoreModClass("fastcraft.Tweaker") :27 STB_TEXTURE_STITCHING 的排除 / _FORCE 的必需
OPTIFINE setCoreModClass("optifine.OptiFineForgeTweaker") :28 STB_TEXTURE_STITCHING_FOR_FASCRAFT 的必需
XAEROS_MINIMAP setModId("XaeroMinimap") :29 XAEROS_MINIMAP_SCROLL
XAEROS_WORLDMAP setModId("XaeroWorldMap") :30 XAEROS_WORLDMAP_SCROLL
OPENCOMPUTERS setCoreModClass("li.cil.oc.client.launch.TransformerLoader") + setModId("OpenComputers") 双重 :32-33 OPENCOMPUTERS_KEYBOARD_INPUT_FIX

FASTCRAFT_1_25 的判定尤其特殊:它不按 modId 或 coremod 类,而是打开 fastcraft.a 的 ASM 树,在每个方法的指令序列中找 "fcVersion" 后紧跟 "1.25" 的两个 LdcInsnNode(:17-24)。源码注释写明理由:“we look for the strings in the call”(:15),对应 FastCraft 自身的 Launch.blackboard.put("fcVersion", "1.25")。

OPENCOMPUTERS 的双重判定带注释"Support both the NH fork and upstream"(TargetedMod.java:31)——因为 NH 分支与上游 OpenComputers 的 TransformerLoader 位置不同。

CoFH AccessTransformer 修补

CommonProxy.runCompatHooks()(CommonProxy.java:11-24)是唯一的通用兼容钩子。它反射操作 COFHCore 的访问转换器:

  1. Class.forName("cofh.asm.CoFHAccessTransformer")(:14)。
  2. 取其静态字段 superClasses 并 setAccessible(true)(:15-16)。
  3. 往 HashMap 里塞两条映射(:18-19):
    • org/lwjgl/openal/OpenALException → java/lang/RuntimeException
    • org/lwjglx/openal/OpenALException → java/lang/RuntimeException
  4. 打 INFO 日志 "Installed CoFH AT compatibility"(:20)。

触发动机见 :12 注释:“Fix crash with OpenComputers/COFHCore due to a class extending OpenALException”。

这是刻意的静默降级:catch (ReflectiveOperationException e) 的 catch 块体只有一行注释 // ignore - cofh not present(:21-23),既不打日志也不重抛。装了 COFHCore 却修补失败时不会有任何提示。

该钩子在 preInit 最开始被调用——Lwjgl3ify.java:42 的 PROXY.runCompatHooks()。

ClientProxy 追加的客户端行为

ClientProxy.runCompatHooks()(ClientProxy.java:45-56)在 super.runCompatHooks() 之后:

  1. Config.DEBUG_REGISTER_OPENGL_LOGGER 为真时调 GLDebugLog.setupDebugMessageCallback()(:47-49)。
  2. Keyboard.populateKeyLookupTables() —— 填充依赖键盘布局的查表(:51)。
  3. registerKeybindHandler() —— 向 InputEvents 注册一个内部 McKeybindHandler(:52、:69-71)。该处理器 onKeyEvent 是空实现,onTextEvent 转发给 TextFieldHandler.onTextInput(:58-67)。
  4. FMLCommonHandler.instance().bus().register(this)(:53-55)。

声明依赖的真相

@Mod 注解(Lwjgl3ify.java:21-27)没有 dependencies 参数,acceptableRemoteVersions = "*"、acceptedMinecraftVersions = "[1.7.10]"。mcmod.info 的 requiredMods / dependencies / dependants 三个数组全为空(mcmod.info:15-17)。

实际依赖由 README 文字声明而非 FML 元数据表达:必须使用 UniMixins 0.1.23+ 的 GTNHMixins 模块;Hodgepodge 强烈推荐(README 说明它含 LWJGL3ify 无法在 GTNH 分支中直接修复的 Biomes’o’Plenty / Witchery / JourneyMap 等 mod 的 Java 17+ 兼容补丁)。

Hodgepodge 之所以不写成 FML 依赖,从源码可反推:两个 Xaeros mixin 明确用 expect = -1 容忍 Hodgepodge 的重复补丁(XaerosMinimapScrolling.java:19 的注释"Optional because an old hodgepodge patch might also do the same")。写成硬依赖反而会破坏这种可共存设计。

ModularUI2 的 API 消费

ModularUI2 通过 compileOnlyApi 依赖本模组的 :api 产物:

  • 依赖声明:com.github.GTNewHorizons:lwjgl3ify:3.0.34:api + transitive = false(ModularUI2/dependencies.gradle:33)
  • 使用的类型:me.eigenraven.lwjgl3ify.api.InputEvents(ModularPanel.java:39、ModularScreen.java:25、ModernInteractable.java:7、IMuiScreen.java:18、OverlayInputHandler.java:8、BaseTextFieldWidget.java:23)
  • 软绑定方式:@Optional.Interface(modid = "lwjgl3ify", iface = "me.eigenraven.lwjgl3ify.api.InputEvents$KeyboardListener")(IMuiScreen.java:36、OverlayInputHandler.java:13)
  • 实现接口:IMuiScreen extends InputEvents.KeyboardListener(IMuiScreen.java:39)、OverlayInputHandler implements InputEvents.KeyboardListener(OverlayInputHandler.java:14)

注意:这是 compileOnlyApi——编译期可见、运行期不强制。ModularUI2 用 @Optional.Interface 做软绑定,因此不装 lwjgl3ify 也能运行,只是收不到原始按键事件。这是本 mod 被其他 mod 依赖的典型形态,与硬依赖不同。

数值

数值 值
TargetedMod 枚举项 6
按 modId 判定 3(XaeroMinimap、XaeroWorldMap、OpenComputers 之一)
按 coremod 类判定 3(FastCraft、OptiFine、OpenComputers 之一)
按字节码常量判定 1(FASTCRAFT_1_25)
mcmod.info 声明的依赖数 0(三个依赖数组均为空)
@Mod(dependencies = ...) 未声明
README 声明的必需前置 UniMixins 0.1.23+(GTNHMixins 模块)
README 声明的强烈推荐 Hodgepodge
已知外部 API 消费者 1(ModularUI2)

已知静默失败点

位置 行为 后果
CommonProxy.java:21-23 catch (ReflectiveOperationException e) 块体仅有一行注释 装了 COFHCore 但修补失败时完全无日志
LwjglRedirectTransformer.java:106-108 catch (Exception e) 打 WARN 后 return false 该类以未转换状态继续加载
Lwjgl3ifyCoremod.java:31-36 catch (ClassCastException e) 打 warn 非 LaunchWrapper 启动时排除包失败
Lwjgl3ify.java:83-85 catch (ReflectiveOperationException e) 打 LOG.warn 排除项清单打印失败不影响启动

其中第一条是本条目内最值得注意的:它是唯一一条完全不留日志的兼容钩子失败路径。

交互

触发 行为
装有 CoFHCore preInit 时修补 OpenALException 继承关系(成功打 INFO)
未装 CoFHCore Class.forName 抛 ClassNotFoundException,静默跳过
装有 XaeroMinimap / XaeroWorldMap 启用对应滚轮归一化 mixin
装有 OpenComputers 启用 InputBuffer 键盘输入修复 mixin
装有 FastCraft(任意版本) 禁用 MixinStitcher,除非开 stbiIgnoreFastcraft
装了 Hodgepodge 重复补丁被 expect = -1 静默跳过
装了 ModularUI2 ModularUI2 获得 InputEvents.KeyboardListener 回调
未装 lwjgl3ify ModularUI2 仍可运行(软绑定)

相关条目