Package dev.architectury.loom.forge
Class ForgeMemberNameFixer
java.lang.Object
dev.architectury.loom.forge.ForgeMemberNameFixer
把最终 MC jar 里「对 Forge 成员的未翻译引用」改写成 Forge 侧的最终名字.
为什么需要这一步
legacy Forge 的 binpatch 会把 Forge 自己的调用写进 MC 类。这些调用在补丁里以 srg 名 出现(如ModelLoader.a()),而 Forge universal jar 随后被重映射到 named
(同方法改叫 setupModelRegistry)。MC jar 的重映射表只含 MC 自身成员,
查不到 Forge 成员,于是这些引用被原样保留,运行期抛
NoSuchMethodError: ModelLoader.a()Lnet/minecraft/util/registry/IRegistry;。
映射从哪来
Forge 会同时提供forge-universal.jar(srg 空间)与重映射后的 forge jar(named 空间)。
两份 jar 由同一份源码编译,同类内成员的出现顺序一致,因此按顺序对齐即可得到
「srg 名 → named 名」的对应关系。这条映射不依赖 MC 映射表,所以能覆盖 MC 表里没有的 Forge 成员。
为什么按 owner+name 匹配而不是按描述符
最终 jar 里这些引用的描述符可能已经是 named 形 (()Lnet/minecraft/util/registry/IRegistry;),而映射键里的描述符是 srg 形
(()Lfm;),两者不等。若按「名字+描述符」精确匹配会静默失效
(实测:仅 2 个 class 被改写且目标引用未变)。故这里忽略描述符、只按 owner + name 匹配。
该匹配方式的前提:同一 owner 下的同名重载会映射到同一个目标名。 对 1.12.2 的 Forge 实测结果正确(重载在 srg 与 named 两版间保持同序,且改名后不与其他成员冲突)。 若将来 Forge 引入「同名重载被改成不同名字」的情况,这里会改错,需改为携带描述符的匹配。
字段引用:直接表 + 继承链
上面两张表只含 Forge 类自己声明的成员。但 Forge 代码也会读从 MC 父类继承的字段, 例如World.initCapabilities 里的 WorldCapabilityData.a(= WorldSavedData.mapName)。
Forge 类不在 MC 映射表里,TinyRemapper 解析不到这类引用,名字会原样留成官方名。
因此字段引用还额外沿类层次向上查 MC 映射表,详见 ForgeMemberNameFixer.FieldResolver;
字段声明则只查直接表,详见 ForgeMemberNameFixer.DeclarationSafeClassRemapper。-
Nested Class Summary
Nested Classes -
Method Summary
-
Method Details
-
fix
public static ForgeMemberNameFixer.Stats fix(Path targetJar, Path srgForgeJar, Path namedForgeJar, @Nullable net.fabricmc.mappingio.tree.MappingTree mappings, String fromNamespace, String toNamespace) throws IOException 改写targetJar中对 Forge 成员的 srg 名引用.就地改写:读原文件、写同目录临时文件、成功后替换。任一步失败时原文件保持不动。
- Parameters:
targetJar- 待改写的 jar(最终 MC jar,已处于目标命名空间)srgForgeJar- Forge 的 universal jar(srg 空间)namedForgeJar- 已重映射到 named 的 Forge jarmappings- MC 映射树;为null时不做继承字段解析(退化成「只改直接表」)fromNamespace- 重映射的源命名空间——targetJar里没被翻译的引用保持的就是这个空间的名字toNamespace- 重映射的目标命名空间- Returns:
- 改写统计;两份 Forge jar 缺失或对不上时返回全零
- Throws:
IOException- 读写失败
-