这篇文章会讲清楚 Minecraft 和 NeoForge 是怎么进行版本控制的,也会给模组的版本控制提一些建议。

Minecraft

Minecraft 使用语义化版本控制(semantic versioning),简称 "semver",其格式为 major.minor.patch

  • major(主版本号): 当进行重大更改并且可能不向后兼容时,主版本号会递增。

  • minor(次版本号): 当以向后兼容的方式添加新功能时,次版本号会递增。

  • patch(修订号): 当进行向后兼容的错误修复时,修订号会递增。

例如,Minecraft 1.20.2 的主版本号为 1,次版本号为 20,修订号为 2。

自从 2011 年推出 Minecraft 1.0 以来,Minecraft 一直使用 1 作为主版本号。在此之前,版本控制方案经常变化,例如 a1.1 (Alpha 1.1)、b1.7.3 (Beta 1.7.3),甚至还有完全没有清晰版本控制方案的 infdev 版本。由于 1 这个主版本号已经保持了十多年,而且“Minecraft 2”也只是个玩笑,所以人们普遍认为这种情况不太可能改变。

快照

快照版的版本号跟标准的版本号命名规则不太一样。它们用的是 YYwWWa 这样的格式。

  • YY 代表年份的后两位,比如 23 就代表 2023 年。

  • WW 代表这一年的第几周,比如 01 就代表第一周。

所以,举个例子,23w01a 就表示 2023 年第一周发布的快照版。

最后的 a 后缀是为了应对一周发布两个快照的情况(第二个快照就会命名为 23w01b 这样)。Mojang 以前偶尔会这么做。这个后缀也有一些例外用法,比如 20w14infinite,这是 2020 年愚人节的“无限维度”玩笑快照

预发布和候选发布

当一个快照周期快结束的时候,Mojang 就会开始发布所谓的“预发布版”。预发布版意味着这个版本的功能已经全部完成了,之后的工作重心就只剩下修复 bug 了。它们的版本号使用标准的版本号格式(也就是 semver),然后在后面加上 -preX 的后缀。举个例子,1.20.2 的第一个预发布版就叫 1.20.2-pre1。通常会有多个预发布版,它们会依次使用 -pre2-pre3 等后缀。

类似地,当预发布周期结束后,Mojang 会发布第一个候选发布版(在版本号后面加上 -rc1 后缀,比如 1.20.2-rc1)。Mojang 的目标是只发布一个候选发布版,如果没有发现新的 bug,这个版本就会直接作为正式版发布。但是,如果出现了意料之外的 bug,那么也可能会有 -rc2-rc3 等版本,跟预发布版的情况类似。

NeoForge

NeoForge 使用了一种调整过的 semver 系统:

  • 主版本号(Major version) 对应 Minecraft 的次版本号(Minor version)

  • 次版本号(Minor version) 对应 Minecraft 的补丁版本号(Patch version)

  • 补丁版本号(Patch version) 才是 NeoForge 真正的版本号。

举个例子,NeoForge 20.2.59 就表示 Minecraft 1.20.2 的第 60 个 NeoForge 版本(从 0 开始计数)。开头的“1”被省略了,因为基本上不可能改变,前面也解释过原因。

NeoForge 的一些地方也使用了 Maven 版本范围,比如 neoforge.mods.toml 文件中的 Minecraft 和 NeoForge 版本范围。这些范围大部分(但不是完全)兼容 semver(例如,它不考虑 pre-tag)。

Mods

没有绝对最好的版本控制系统。不同的开发风格、项目范围等等都会影响使用哪种版本控制系统的决定。有时,版本控制系统也可以组合使用。本节试图概述一些常用的版本控制系统,并提供一些实际的例子。

通常,模组的文件名看起来像 modid-<版本>.jar。因此,如果我们的模组 ID 是 examplemod,版本是 1.2.3,那么我们的模组文件将命名为 examplemod-1.2.3.jar

ℹ️注意

版本控制系统是建议,而不是严格执行的规则。对于何时更改(“递增”)版本以及以何种方式更改版本尤其如此。如果你想使用不同的版本控制系统,没有人会阻止你。

语义化版本控制

语义化版本控制(“semver”)由三个部分组成:主版本号.次版本号.补丁版本号。当代码库发生重大更改时,主版本号会递增,这通常与主要的新功能和错误修复相关。当引入次要功能时,次版本号会递增,而当更新仅包含错误修复时,补丁版本号会递增。

人们普遍认为,任何 0.x.x 版本都是开发版本,并且在第一个(完整)版本发布时,版本号应递增到 1.0.0。

“次要功能使用次版本号,错误修复使用补丁版本号”的规则在实践中经常被忽略。一个流行的例子是 Minecraft 本身,它通过次版本号进行主要功能更新,通过补丁号进行次要功能更新,并在快照中进行错误修复(见上文)。

根据模组更新的频率,这些数字可以更小或更大。例如,Supplementaries 的版本为 2.6.31(在撰写本文时)。三位数甚至四位数的数字,尤其是在补丁版本号中,是完全有可能的。

“简化”和“扩展”语义化版本控制

有时,可以看到只有两个数字的 semver。这是一种“简化”的 semver,或“两部分”的 semver。它们的版本号只有主版本号.次版本号的格式。这通常用于只添加一些简单对象并且因此很少需要更新(除了 Minecraft 版本更新)的小型模组,它们通常永远停留在 1.0 版本。

“扩展”的 semver,或“四部分”的 semver,有四个数字(例如 1.0.0.0)。根据模组的不同,格式可以是主版本号.API 版本号.次版本号.补丁版本号,或主版本号.次版本号.补丁版本号.热修复版本号,或者完全不同的格式——没有标准的方法来做到这一点。

对于主版本号.API 版本号.次版本号.补丁版本号,主版本号与 API 版本号是分离的。这意味着主版本号(功能)部分和 API 部分可以独立递增。这通常用于为其他模组开发者提供 API 以供使用的模组。例如,通用机械(Mekanism)目前的版本是 10.4.5.19(在撰写本文时)。

对于主版本号.次版本号.补丁版本号.热修复版本号,补丁级别被分成两部分。这是 机械动力(Create) 模组使用的方法,它目前的版本是 0.5.1f(在撰写本文时)。请注意,Create 使用字母而不是第四个数字来表示热修复,以保持与常规 semver 的兼容性。

ℹ️简化 semver、扩展 semver、两部分 semver 和四部分 semver 无论如何都不是官方术语或标准化格式。

Alpha, Beta, 发布版

就像 Minecraft 本身一样,模组开发通常也遵循软件工程中经典的 alpha/beta/release 阶段,其中 alpha 表示不稳定/实验性版本(有时也称为 experimental 或 snapshot),beta 表示半稳定版本,而 release 表示稳定版本(有时称为 stable 而不是 release)。

一些模组使用它们的主版本号来表示 Minecraft 版本更新。一个例子是 JEI,它对 Minecraft 1.19.2 使用 13.x.x.x,对 1.19.4 使用 14.x.x.x,对 1.20.1 使用 15.x.x.x(没有 1.19.3 和 1.20.0 的版本)。其他模组将标签附加到模组名称,例如 Minecolonies 模组,在撰写本文时其版本为 1.1.328-BETA。

包含Minecraft版本

在文件名中包含模组所针对的 Minecraft 版本是很常见的做法。这使得最终用户更容易找到模组所适用的 Minecraft 版本。常见的做法是在模组版本的前面或后面加上 Minecraft 版本,前者比后者更普遍。例如,JEI 针对 1.20.2 的 16.0.0.28 版本(撰写本文时的最新版本)将变为 jei-1.20.2-16.0.0.28jei-16.0.0.28-1.20.2

包含模组加载器

正如您可能知道的,NeoForge 并不是唯一的模组加载器,许多模组开发者都在多个平台上进行开发。因此,需要一种方法来区分同一模组的相同版本但用于不同模组加载器的两个文件。

通常,这是通过在名称中的某个位置包含模组加载器来完成的。jei-neoforge-1.20.2-16.0.0.28jei-1.20.2-neoforge-16.0.0.28jei-1.20.2-16.0.0.28-neoforge 都是有效的做法。对于其他模组加载器,neoforge 部分将被替换为 forgefabricquilt 或您可能与 NeoForge 一起开发的其他任何不同的模组加载器。

关于Maven的一个注意事项

用于依赖项托管的系统 Maven 使用的版本控制系统在某些细节上与 semver 不同(尽管总体上的主版本号.次版本号.补丁版本号模式保持不变)。相关的 Maven 版本范围 (MVR) 系统在 NeoForge 的某些地方使用(见上文)。在选择版本控制方案时,应确保它与 MVR 兼容,否则,模组将无法依赖于你的模组的特定版本!

一个还在寻找自己的三流开发者