coremod 补丁
OpenModsLib 通过 FML coremod 机制在类加载阶段改写原版 Minecraft 类,为 OpenBlocks 系列提供底层能力。这是本 mod 最核心也最不可见的部分:6 个 ASM 补丁全部作用于 net.minecraft.* 类,玩家在游戏内看不到任何提示,但关掉任何一个都会让特定功能静默失效或崩溃。
类生成机制见类注入与 include,配置属性见OpenModsLib 配置。
基本信息
| 属性 | 值 |
|---|---|
| coremod 入口 | openmods.core.OpenModsCorePlugin(@SortingIndex(16)) |
| 核心 mod 容器 | openmods.core.OpenModsCore(继承 DummyModContainer,非 @Mod) |
| ASM 变换器 | openmods.core.OpenModsClassTransformer |
| 配置文件 | <游戏目录>/config/OpenModsLibCore.json |
| 补丁数 | 6(全部作用于 net.minecraft.*) |
| 黑板标记 | OpenModsCoreLoaded(OpenModsCorePlugin.java:20) |
@MCVersion |
"1.7.10"(OpenModsCorePlugin.java:16) |
功能
coremod 入口
OpenModsCorePlugin(src/main/java/openmods/core/OpenModsCorePlugin.java:15)实现 IFMLLoadingPlugin:
| 回调 | 返回 | 行 |
|---|---|---|
getASMTransformerClass() |
["openmods.core.OpenModsClassTransformer"] |
:29-32 |
getModContainerClass() |
"openmods.core.OpenModsCore" |
:34-37 |
getSetupClass() |
null |
:39-42 |
getAccessTransformerClass() |
null |
:48-51 |
injectData(Map) |
转发给 Bootstrap.injectData(data) |
:44-47 |
@SortingIndex(16)(:16)保证本 coremod 的排序值低于所有依赖它的 coremod(源码注释 // must be lower than all dependent ones)。
@TransformerExclusions(:17)声明 5 个前缀下的类不参与变换,避免自我递归:
openmods.asm. openmods.include. openmods.core. openmods.injector. openmods.Log
构造函数(:19-23)把版本号写入 LaunchWrapper 黑板,键 OpenModsCoreLoaded,供其它 coremod 检测 OpenModsLib 是否已加载。
核心 mod 容器
OpenModsCore(src/main/java/openmods/core/OpenModsCore.java:16)继承 DummyModContainer 而非使用 @Mod 注解 —— 这是 FML 提供给 coremod 的标准容器。构造时手工填充 ModMetadata(:21-29):
| 字段 | 值 |
|---|---|
modId / name |
"OpenModsCore" |
version |
Mods.OPEN_MODS_LIB_VERSION(Gradle 令牌,编译期替换) |
authorList |
Mikee、NeverCast、boq |
url |
https://openmods.info/ |
parent |
"OpenMods" |
description |
"This is where the magic happens" |
modConstruction 事件(:37)中调用 OpenModsClassTransformer.instance().injectAsmData(evt.getASMHarvestedData()) 把 FML 扫描到的 @IncludeInterface / @IncludeOverride 标注类名注入变换器(OpenModsClassTransformer.java:230-235)。
同一事件还注册 2 个崩溃报告条目(:41,54):"OpenModsLib class transformers"(输出各补丁的 DISABLED/ENABLED/ACTIVATED/FINISHED/FAILED 状态,:70-72 的 listStates)与 InjectorSanityChecker(检测失效的注入类)。
6 个原版类补丁
OpenModsClassTransformer.addConfigValues(src/main/java/openmods/core/OpenModsClassTransformer.java:96)为每个补丁注册一个 ConfigProcessor 条目,配置值默认为 "true"。激活时把 ClassVisitor 工厂放入 vanillaPatches 映射。
| # | 配置项 | 目标类 | 注入的 Visitor | 声明行 | 用途 | 已知使用方 |
|---|---|---|---|---|---|---|
| 1 | activate_movement_callback |
net.minecraft.client.entity.EntityPlayerSP |
openmods.movement.MovementPatcher |
:98-124 |
给玩家移动控制加回调钩子 | OpenBlocks 电梯 |
| 2 | activate_map_gen_fix |
net.minecraft.world.gen.structure.MapGenStructure |
openmods.world.MapGenStructureVisitor |
:125-146 |
修复原版查找附近结构的 bug | OpenBlocks 金眼 |
| 3 | activate_player_render_hook |
net.minecraft.client.renderer.entity.RenderPlayer |
openmods.renderer.PlayerRendererHookVisitor |
:147-169 |
给玩家渲染代码加钩子 | OpenBlocks 滑翔翼 |
| 4 | activate_stencil_patches |
net.minecraft.client.shader.Framebuffer |
openmods.stencil.FramebufferInjector |
:170-192 |
为 FBO 重新启用模板缓冲 | OpenBlocks 天空方块 |
| 5 | activate_gl_capabilities_hook |
net.minecraft.client.renderer.OpenGlHelper |
openmods.stencil.CapabilitiesHookInjector |
:193-215 |
钩取额外 OpenGL 能力检测 | OpenBlocks 天空方块 |
| 6 | activate_player_damage_hook |
net.minecraft.entity.player.EntityPlayer |
openmods.entity.PlayerDamageEventInjector |
:216-238 |
捕获护甲与药水结算后的玩家伤害 | Last Stand 附魔 |
每个条目的 activate_* 开关默认 "true",配置说明中明确写出了「已知使用方」(Known users)与「关闭后的后果」(When disabled)。其中:
- 关闭
activate_map_gen_fix→ 「features may not work (either silently fail or cause crash)」 - 关闭
activate_player_damage_hook→ 「Last Stand enchantment will not work」 - 关闭
activate_stencil_patches/activate_gl_capabilities_hook→ 「no stencil buffer available unless unlocked with Forge flag」
6 个补丁中有 4 个是纯客户端补丁(#1、#3、#4、#5 均在 net.minecraft.client.*),仅 #2(世界生成)和 #6(伤害事件)作用于服务端逻辑。
变换器状态机
每个补丁通过 StateTracker<TransformerState>(OpenModsClassTransformer.java:56)维护 5 态生命周期:
| 状态 | 含义 |
|---|---|
DISABLED |
初始态(StateTracker.create(TransformerState.DISABLED),:56) |
ENABLED |
配置值读到 "true",vanillaPatches 已填入 |
ACTIVATED |
transform() 命中该类,Visitor 已创建 |
FINISHED |
变换成功(IResultListener.onSuccess) |
FAILED |
变换失败(IResultListener.onFailure) |
listStates()(:70)把所有补丁状态用逗号连接,供崩溃报告定位问题。ConfigOption.valueSet(:66-71)只接受大小写不敏感的 "true",其它值保持 DISABLED。
变换器的类过滤
transform(:245)的判定顺序:
bytes == null→ 交给InjectedClassesManager.instance.tryGetBytecode(name),这是动态生成类的入口(见类注入)transformedName以net.minecraft.开头 → 查vanillaPatches,命中才变换,否则原样返回- 其它类 → 走
applyIncludes走 include 机制
IGNORED_PREFIXES(:44-52)列出 8 个永不 include 的前缀:cpw.mods.fml.、net.minecraftforge.、io.netty.、gnu.trove.、com.google.、com.mojang.、joptsimple.、tv.twitch.。
但一旦 injectAsmData 已执行(shouldTryIncluding,:239-241),白名单模式生效 —— 只处理 FML 扫描到的带 @IncludeInterface / @IncludeOverride 的类,上面的前缀黑名单不再起作用。
数值
| 数值名 | 值 |
|---|---|
| coremod 入口类数 | 1(OpenModsCorePlugin) |
IFMLLoadingPlugin 实现数 |
1 |
DummyModContainer 子类数 |
1(OpenModsCore,非 @Mod) |
| 原版类补丁数 | 6 |
| 其中客户端专用补丁数 | 4(#1 #3 #4 #5) |
@TransformerExclusions 前缀数 |
5 |
IGNORED_PREFIXES 前缀数 |
8 |
| 崩溃报告条目数 | 3(2 个在此类,1 个在客户端代理) |
| 变换器状态数 | 5(DISABLED/ENABLED/ACTIVATED/FINISHED/FAILED) |
交互
coremod 本身无玩家可见交互。玩家的唯一感知途径是崩溃报告中的 "OpenModsLib class transformers" 条目,可据此判断某个补丁是否成功应用。
配置文件 OpenModsLibCore.json 由 Bootstrap.injectData(src/main/java/openmods/core/Bootstrap.java:14)在 coremod 阶段创建:若 <游戏目录>/config/ 不存在则 mkdir(:18-19),随后用 ConfigProcessor 读取(:21-25)。读取失败会直接抛 RuntimeException 阻止游戏启动(:24),而非静默降级。
相关条目
- 类注入与 include —
transform()第 1、3 分支的动态类生成 - OpenModsLib 配置 — 与本 JSON 独立的
LibConfig4 个属性 - 指令总览 —
/om_source_*可诊断补丁相关类的来源