补丁注册框架
基本信息
| 属性 | 值 |
|---|---|
| 注册表 | mixins/Mixins.java(815 行,枚举 Mixins) |
| 注册接口 | com.gtnewhorizon.gtnhmixins.builders.IMixins |
| 枚举常量数 | 153 |
| 引用的 mixin 类 | 206 处引用,去重后 204 个 |
| 磁盘上的 mixin 类 | 204(mixins/early 4 个 + mixins/late 200 个) |
| 构建器 | Mixins.SalisBuilder(Mixins.java:764 起) |
| 目标模组表 | mixins/TargetedMod.java(13 个常量) |
功能
三个 mixins.*.json 里的 mixins 数组全是空的——它们只声明了
package(如 dev.rndmorris.salisarcana.mixins.late),
清单由注解处理器在编译期生成。真正的清单是 Mixins 枚举本身:
{
"required": true,
"minVersion": "0.7.10",
"refmap": "mixins.salisarcana.refmap.json",
"package": "dev.rndmorris.salisarcana.mixins.late",
"target": "@env(DEFAULT)",
"compatibilityLevel": "JAVA_8",
"mixinextras": {"minVersion": "0.5.0"}
}
——src/main/resources/mixins.salisarcana.late.json。
Mixins 实现 GTNHLib 的 IMixins,由框架反射读取枚举常量,每个常量通过
SalisBuilder 声明自己的条件与混入类。这是本模组唯一的内容注册表。
上述
IMixins形参类型取自Mixins.java:5的真实 importcom.gtnewhorizon.gtnhmixins.builders.IMixins。 附带说明:mirror/UniMixins中的com/gtnewhorizon/gtnhmixins/包 只有GTNHMixins、IEarlyMixinLoader、ILateMixinLoader、LateMixin等, 没有builders/子包与IMixins.java——本地 UniMixins 镜像与本模组 编译所依赖的版本(README 要求 0.1.23+)布局不同。 因此该接口类是否存在于所依赖的确切版本中无法本地核实; 可核实的只有 import 语句本身。同目录下的IEarlyMixinLoader则确实存在。
完整性校验
Mixins.java 中以字符串形式引用的 mixin 类,与磁盘上的 .java 文件做了双向比对:
| 方向 | 结果 |
|---|---|
| 注册表引用 → 磁盘文件 | 204 个引用全部存在,悬空引用 0 |
| 磁盘文件 → 注册表引用 | 204 个文件全部被引用,孤儿文件 0 |
| 阶段一致性 | 全部匹配(early 包中的类只被 Phase.EARLY 常量引用,反之亦然) |
被两个枚举常量共同引用的类有 2 个(属有意为之,类内部会同时读取两组设置):
| 类 | 被引用的常量 |
|---|---|
thaumcraft.client.gui.MixinGuiResearchBrowser_Creative_Scroll |
CTRL_SCROLL_NAVIGATION、CREATIVE_OP_THAUMONOMICON |
thaumcraft.common.lib.world.MixinThaumcraftWorldGenerator_NodeGenerationWeights |
NODE_GENERATION_MODIFIER_WEIGHTS、NODE_GENERATION_TYPE_WEIGHTS |
因此 206 = 204 + 2。
构建器 API
SalisBuilder extends MixinBuilder(Mixins.java:764)在枚举体内被调用的方法:
| 方法 | 出现次数 | 作用 |
|---|---|---|
addRequiredMod(TargetedMod.X) |
152 | 要求目标模组已加载 |
applyIf(Setting) |
137 | 直接以某个设置为条件 |
addCommonMixins(String...) |
123 | 公共侧混入类 |
addClientMixins(String...) |
40 | 客户端混入类 |
setApplyIf(BooleanSupplier) |
12 | 以 lambda 为条件(需要组合多个条件时使用) |
addExcludedMod(TargetedMod.X) |
1 | 目标模组存在时不应用 |
setRequired() |
1 | 声明本补丁必须应用 |
applyIf 与 setRequired 都只是对父类 setApplyIf 的薄封装:
public MixinBuilder applyIf(Setting config) {
return super.setApplyIf(config::isEnabled);
}
public MixinBuilder setRequired() {
return super.setApplyIf(() -> true);
}
——Mixins.java:774-780。这正是 applyIf 的形参类型可以直接是 Setting
(137 处调用中绝大多数只写一个 SalisConfig.xxx.yyy)的原因。
Mixins.java:787-813 另有 4 段被注释掉的覆写(addServerMixins、
addClientMixins、addCommonMixins 与 assertClassesExist)。它们是开发期校验工具,
按「注释掉的注册计为零」的规则不计入上表。Mixins.java:747-749 还有一个
被注释掉的 INTENTIONAL_FAILURE 枚举常量(故意指向不存在的类名),
同样不计入 153 之数。源码注释(Mixins.java:745-746、Mixins.java:782-785)
明确写了这套校验「仅供开发期使用,合并进 main 时不应取消注释」,
属于有明确意图证据的注释,不是缺陷。
阶段
只有 2 个常量使用 Phase.EARLY(Mixins.java:17、Mixins.java:19),
其余 151 个走默认的 LATE 阶段:
| 枚举常量 | 行 | 混入类 | 条件 | 排除 |
|---|---|---|---|---|
ACCESSORS |
17 | accessor.AccessorGuiContainer、accessor.AccessorMinecraft、accessor.AccessorCreativeSlot |
始终应用 | — |
VANILLA_GUI_KEY_TYPED |
19 | gui.MixinGuiContainer_HandleKeyTyped |
始终应用 | NotEnoughItems |
VANILLA_GUI_KEY_TYPED 是全仓唯一使用 addExcludedMod 的补丁:NEI 会自行接管
按键处理,装了 NEI 就必须让开。
不受配置开关控制的条件
以下 9 个常量的条件里没有 SalisConfig 引用,或引用方式特殊:
| 枚举常量 | 行 | 条件 | 依赖 | 混入类 |
|---|---|---|---|---|
ACCESSORS |
17 | 始终应用 | — | 3 个访问器 |
VANILLA_GUI_KEY_TYPED |
19 | 始终应用 | — | gui.MixinGuiContainer_HandleKeyTyped |
THAUM_ACCESSORS |
27 | 始终应用 | Thaumcraft |
thaumcraft.common.container.AccessorContainerFocusPouch |
CAPTURE_FOCUS_KEYBIND |
30 | () -> !MixinModCompat.multiKeyBindsPermitted() |
Thaumcraft |
thaumcraft.common.lib.events.MixinKeyHandler_CaptureFocusKeybind |
ADD_VISCONTAINER_INTERFACE |
737 | 始终应用(setRequired()) |
Thaumcraft |
thaumcraft.common.items.MixinAmuletWand_AddInterface |
AUTOMAGY_BOILER_FAKEPLAYER |
301 | SalisConfig.addons.automagyBoilerFakePlayer |
Automagy |
automagy.blocks.MixinBlockBoiler_FakePlayer |
DEBUG_LOG_WARP_STACK_TRACE |
731 | SalisConfig.debug.logWarpSources |
Thaumcraft |
thaumcraft.common.lib.research.MixinPlayerKnowledge_DebugLogWarp |
FOCUS_POUCH_SLOT |
645 | SalisConfig.modCompat.baublesExpanded.focusPouchSlot |
Thaumcraft、Baubles|Expanded |
thaumcraft.common.items.wands.MixinItemFocusPouchBauble_ExpandedBaublesSlot |
MIXIN_ANGELICA_FONTRENDERER |
717 | () -> SalisConfig.modCompat.angelica.replaceTCFontRenderer.isEnabled() && TargetedMod.ANGELICA.isLoaded() && AngelicaConfig.enableFontRenderer |
Thaumcraft、angelica |
thaumcraft.client.lib.MixinTCFontRenderer_AngelicaFontRenderer |
其中 MIXIN_ANGELICA_FONTRENDERER 的条件是三重与:不仅要设置开启、
Angelica 已加载,还要求 AngelicaConfig.enableFontRenderer 自身为真。
AUTOMAGY_BOILER_FAKEPLAYER 的混入目标也不在 Thaumcraft 包里,
而是 automagy.blocks.MixinBlockBoiler_FakePlayer。
ACCESSORS 与 THAUM_ACCESSORS 的源码注释说明了「始终应用」的理由:这些访问器
不改变 Thaumcraft 代码的执行过程,冲突概率极低,且始终应用使得次元袋快捷存入
可以在运行时动态开关(Mixins.java:24-26)。
按配置分组统计
153 个常量按其 applyIf 指向的 SalisConfig 分组归类:
| 分组 | 常量数 | 引用 mixin 类数 | 对应页面 |
|---|---|---|---|
SalisConfig.bugfixes.* |
73 | 106 | 缺陷修复补丁 |
SalisConfig.features.* |
53 | 70 | 功能增强补丁 |
SalisConfig.thaum.* |
18 | 19 | 神秘时代配置补丁 |
SalisConfig.modCompat.* |
2 | 2 | 见上表 |
SalisConfig.addons.* |
1 | 1 | 见上表 |
SalisConfig.debug.* |
1 | 1 | 见上表 |
| 无配置条件 | 5 | 7 | 见上表 |
| 合计 | 153 | 206 |
「无配置条件」= 4 个始终应用 +
CAPTURE_FOCUS_KEYBIND(条件为!MixinModCompat.multiKeyBindsPermitted(),不含SalisConfig)。 各组引用数之和 106+70+19+2+1+1+7 = 206。
目标模组
TargetedMod(mixins/TargetedMod.java:12-24)列出 13 个可被补丁定向的模组,
modId 字段即真实 modid,isLoaded() 走 Loader.isModLoaded(modId) 并缓存结果。
其中 NotEnoughItems 是本模组唯一声明了核心模组类的目标:
| 常量 | modid | 核心模组类 |
|---|---|---|
NOT_ENOUGH_ITEMS |
NotEnoughItems |
codechicken.nei.asm.NEICorePlugin |
其余 12 个常量使用单参构造,无核心模组类。13 个常量全部被引用,
无未使用的死枚举项(THAUMCRAFT 被引用 147 次,TC4_TWEAKS、NOT_ENOUGH_ITEMS、
ANGELICA 各 3 次,其余各 1–2 次)。
相关条目
- 缺陷修复补丁 · 功能增强补丁 · 神秘时代配置补丁
- 核心模组与 ASM 变换器 —
SalisArcanaCore与SalisArcanaClassTransformer - 模组兼容 — 13 个
TargetedMod的兼容行为 - 配置框架 —
applyIf所依赖的 204 项设置 - Salis Arcana — 模组总览