拉取请求指南
模组构建在 Forge 之上,但 Forge 并不支持所有功能,这限制了模组能做的事情。遇到这种情况时,模组开发者可以修改 Forge 来提供支持,再将修改作为 GitHub 拉取请求(PR)提交。
原创说明图,依据 Forge 1.21.x 官方文档 绘制。
为了更有效地利用你和 Forge 团队的时间,准备 PR 时建议遵循一些基本指南。以下是编写优质 PR 时应牢记的重点。
Forge 究竟是什么?
从宏观角度看,Forge 是 Minecraft 上的一层模组兼容层。早期模组直接修改 Minecraft 代码(就像现在的核心模组一样),当它们修改同一部分时就会发生冲突;一个模组以其他模组无法预料的方式改变行为时,也会引发难以解释的问题。
使用 Forge 这样的工具,模组可以集中处理常见修改,避免冲突。Forge 还为能力、注册表等常见模组功能提供支持结构,让模组更好地协作。
编写优秀的 Forge PR 时,还需要理解其底层结构。Forge 主要有两类代码:Minecraft 补丁和 Forge 代码。
补丁
补丁直接修改 Minecraft 源代码,并力求尽量精简。每当 Minecraft 代码发生变化,都需要仔细检查全部 Forge 补丁并将其正确应用到新代码。因此,修改内容较多的大型补丁难以维护,Forge 力求避免它们,使补丁尽可能小。审查补丁时,除了检查代码是否合理,还会着重缩小补丁体积。
编写小型补丁有许多策略,审查者通常会指出更好的实现方式。Forge 补丁经常只插入一行来触发事件或代码钩子,在事件满足某个条件时影响后续代码。这样大部分代码便可放在补丁之外,使补丁保持小巧简单。
有关创建补丁的详情,请参阅 GitHub Wiki。
Forge 代码
除补丁外,Forge 代码就是普通 Java 代码。它可以是事件代码、兼容功能或其他不直接编辑 Minecraft 代码的内容。Minecraft 更新时,Forge 代码也必须随之更新,但由于它不直接与 Minecraft 代码交织,更新要容易得多。
由于这些代码独立存在,不像补丁那样有大小限制。审查时除了检查代码是否合理,还会关注代码是否整洁,包括正确的格式和 Java 文档。
解释你的修改
所有 PR 都需要回答:为什么需要这个修改?添加到 Forge 的代码都需要维护,代码越多,潜在缺陷也越多,因此必须有充分的理由。
一个常见问题是 PR 没有解释,或只给出晦涩的理论使用示例,这只会拖慢处理过程。清楚解释一般情况固然有帮助,但也应给出你的模组需要此 PR 的具体例子。
有时可能存在更好的方法,甚至无需 PR 就能实现目标。在这些可能性被充分排除之前,代码修改无法被接受。
展示它能够工作
提交给 Forge 的代码应当正常工作,而你需要说服审查者这一点。最好的方法之一是在 Forge 中添加使用新代码的示例模组或 JUnit 测试,展示其运行效果。
要配置并运行包含示例模组的 Forge 环境,请参阅此指南。
Forge 中的破坏性变更
Forge 不能作出破坏依赖它的模组的修改。这意味着 PR 必须确保不破坏与之前 Forge 版本的二进制兼容性。破坏二进制兼容性的修改称为破坏性变更。
有一些例外:
- 新 Minecraft 版本初期,Minecraft 本身已给模组开发者带来破坏性变更,此时 Forge 接受破坏性变更。
- 有时在上述时间窗口之外需要紧急破坏性变更,但这种情况很少,也可能给整个 Minecraft 模组社区带来依赖问题。
除这些特殊时期外,包含破坏性变更的 PR 不会被接受。它们必须调整为支持旧行为,或等待下一个 Minecraft 版本。
保持耐心、礼貌和同理心
提交 PR 后,通常需要经历代码审查并进行多次修改,才能尽可能完善。请记住,代码审查不是对你个人的评价;代码中的缺陷也不是针对个人的。没有人是完美的,这正是我们共同工作的原因。
消极态度无助于解决问题。威胁放弃 PR 并转而编写核心模组,只会让人不快并使模组生态变得更糟。协作时应相信审查者的善意,不要把反馈当成针对个人的评价。
审查
如果你尽力理解 PR 流程缓慢且追求完善的特点,团队也会尽力理解你的观点。当 PR 经审查并尽各方所能整理完善后,会被标记为由 Lex 进行最终审查;项目是否纳入该修改由他最终决定。