Java版将取消代码混淆,对Mod开发有何影响?
作者:teddyxlandlee | 本文以CC BY-NC-SA 4.0协议发布
原文:Removing obfuscation in Java Edition
参考视频: [McJava] 突发!去除混淆对我们有什么影响? by @WisW
简单解释一下发生了什么:
- 从下个快照起,Mojang在发布常规版本快照的同时,将同步发布未混淆版本的Minecraft JAR,作为“实验性版本”(experimental release)
- 群骑纷争(1.21.11或1.22)正式版的下一个快照的JAR将不再混淆。
虽然这并不意味着将Minecraft开源,但这意味着:
- 模组开发和模组加载器安装时,将不再需要反混淆
- 模组编译时,将不再需要重混淆。
前情提要:Mod社区的反混淆史
自2019年起,Mojang在发布版本的同时会附带混淆映射表(Obfuscation Map),即模组社区俗称的MojMaps。在此之前,模组社区已经出现了MCP、Fabric Yarn等反混淆方案。受版权因素和社区惯性等影响,MojMaps并未受到广泛使用,社区的反混淆表和MojMaps处于并存的状态。
2020年,Mojang更新了MojMaps的许可证,更改了部分用词,被认为对模组开发更友好。
在此之后,Forge于1.17弃用MCP,在开发环境中全面转向MojMaps,在生产环境中使用MojMaps的类名,仍使用类似m_1234_、f_5678_这类名称(中间名)。Forge在1.20.6在生产环境下也全面转向了MojMaps。
NeoForge自其从Forge分家起(1.20.2),就全面使用了MojMaps。当时在NeoForge社区内部就使用MojMaps的法律问题达成了共识,认为法律风险很低。
Fabric的开发工具链虽然支持使用MojMaps,但其团队及贡献者一直在维护Fabric的中间名(intermediary)和反混淆表(Yarn),在Fabric API等官方项目中也一直使用Yarn。
至此,除Fabric仍在使用/维护其自家反混淆表以外,其余主流Mod加载器已完全使用Mojang的官方混淆映射表。此外,相当多的Fabric模组也使用官方混淆映射表。官方混淆映射表正逐渐成为主流。
“扶正”官方符号表,Fabric的反混淆体系何去何从
随着Mojang移除混淆,“混淆后的名称”(obfuscated names / obfname)这一概念将不复存在,第三方的反混淆方案将失去其存在的意义。
笔者早上看到这则新闻时以为自己起猛了,带着一个问题去上了早八:Fabric会继续把intermediary和Yarn维护下去吗?
一开始我觉得会:
- Yarn是CC0协议的(发布者放弃其本应拥有的版权),且不允许借鉴MCP、MojMaps等具有版权的反混淆符号表;而为了维持Yarn的“纯洁性”(purity),仍需要在MojMaps和Yarn之间设置一道机器生成、无自然语义的中间名(intermediary);
- 为最大限度保证旧版本Mod在1.21.11仍能运行,intermediary依然需要存在,但在生产环境下,旧版本Mod会被重映射(remap)至官方符号表。
之后我登录了Fabric的Discord服务器,发现事情并非如此。大部分Fabric开发者并不是抱着“开放协议”不放的原教旨主义者,坚持使用Yarn符号表的开发者主要是因为不喜欢Mojang的符号命名,或习惯于Yarn的符号命名。总而言之,Fabric社区的反应与当年NeoForge社区比较类似,都认为使用官方符号表没啥风险。
后来,Fabric的发起者modmuss确认称,intermediary和Yarn都将停更,但工具链不会移除对第三方映射的支持。
The big plan is to leave intermediary and yarn behind, but still provide an option for those that want to use custom mappings. Actually doing that is much easier said than done though.
同时,Fabric API将迁移至官方符号表(此时说“MojMaps”可能不太合适了,因为这个“Map”不复存在了,姑且称为MojNames吧)。大概会分以下几个步骤:
- 先处理高优先级的Pull Requests,如需要大改的GameRule API;
- 把Fabric API的代码库从Yarn迁移到MojMaps;
- 从内部实现到对外接口,逐步将Fabric API本身的命名调整为官方命名(如
ScreenHandlerRegistry会被改成MenuRegistry)。
modmuss一开始认为,由于重映射源码的工具Mercury并不支持Mixins,Step 2将需要花费相当大的精力完成对Mixins的修正,即需要“人海战术”。
用户Cassian指出,信雅互联(Sinytra)所依赖的Forgified API的上游项目FAPI-MojMaps,就使用了MercuryMixin(Sinytra的分支版本)将Fabric API的仓库整体映射至官方符号表。笔者尝试使用该工具进行迁移,但由于该项目使用的旧版工具链(Loom)已不再兼容最新版快照的Yarn映射格式,且该项目调用了大量Loom的内部实现,迁移难度很高。
于是笔者借鉴FAPI-MojMaps的实现思路,Fork了一份Loom,将Sinytra的MercuryMixin引入作为依赖,为migrateMappings任务添加了Mixin processor。用Fork后的Loom替换Fabric API使用的Loom进行migrateMappings时,Mixin类的Shadow字段、target字符串等都能被正确地重映射。总之,经过笔者的验证,此方案可行性很强。该方案得到了modmuss的认可。
我是Fabric模组开发者,对我有什么影响
首先,1.21.10之前的Fabric Mod将不会兼容1.21.11,因为生产环境中将使用未混淆的符号表(MojNames),而非中间名(intermediary),后者将不复存在。可以说,把NeoForge上能跑的Mod缝缝补补之后在Fabric上跑起来的概率,甚至会比让1.21.10下的Fabric Mod在1.21.11上跑还要高一些。
官方符号表的命名不兼容只是一方面。由于Fabric API全面转向官方符号表,它的命名风格也会随之更改,这种修改是破坏性的。我们姑且期待一下,Fabric在正式版发布时应该会发表迁移指南。
如果你的Mod打算继续跟进Minecraft的更新,强烈建议迁移到MojMaps。Fabric官方将放弃对Yarn的维护,如果坚持使用Yarn,在新版本下开发可能会比较困难。
我是Fabric模组玩家,1.21.10会成为下一个1.7.10吗?
大概率不会。
1.7.10、1.12.2、1.16.5等“Mod黄金版本”的出现,有一个共同的重要原因:难以向上迁移,背后都有Mojang对代码的大改。而由于这些大改,Forge也需要跟着大改,Forge大改之前还需要等MCP命名映射的完善……这导致Mod作者滞留在大改前的版本,逐渐催生该版本Mod生态的繁荣。
1.21.10的情况比较类似:Yarn映射原地爆炸,官方符号表被当场扶正,旧版Fabric模组在新版能跑起来零个(不与Minecraft本体交互的除外)。但1.21.11的难迁移性有个前提:使用Yarn。官方符号表并不是什么新事物,而是许多Mod开发者已经在使用的东西,他们无非就是需要适配一下作出命名更改后的Fabric API而已,迁移难度比1.7.10、1.12.2(Forge磨叽)、1.16.5(Java 8升Java 17导致脏反射当场爆炸、Forge加载器底层大改)这些版本要小很多。Fabric的主要贡献者对Mojang去除混淆的响应是相当积极的,大家不必过于担心。
但这里建议有能力的开发者帮助Fabric API完成这次迁移。更改命名(Step 3)的工作量会比较大。modmuss称,他欢迎贡献者协助完成这次迁移。
官方符号表被扶正,Mojang是否有意推动Mod社区大一统?
We hope that, with this change, we can pave a future for Minecraft: Java Edition where it’s easier to create, update, and debug mods.
可以看出,Mojang的初心就是让Mod的制作、更新和调试更简单。
关于“Mod社区大一统”这件事,Mojang没有给出确切的答案。
但可以肯定的是,随着符号命名的统一,越来越多的跨平台Mod将会涌现,同一个文件既能用Fabric跑,又能用NeoForge跑的情况将会更加常见。
笔者编写的Mod中有不少是跨平台的。相信下一个正式版后,跨平台开发将会变得更加简单。
- 内容版权许可
- CC BY-NC-SA 署名-非商业性使用-相同方式共享