本篇教程由作者设定未经允许禁止转载。
序
此篇文档(此篇文档还在更新中)为1.21.x NeoForge开发官方文档翻译,在阅读此文档时建议结合官方文档一起食用.(官方文档地址:https://docs.neoforged.net)
入门(Getting Started)
NeoForge入门(Getting Started with NeoForge)。
这部分介绍如何构建NeoForge工作区,以及如何运行及测试你的模组
准备(Prerequisites)
熟悉java,特别是它的面向对象,多态,泛型,和函数特征.
安装Java21开发工具包(JDK)和64位的java虚拟机(JVM).NeoForge推荐并支持微软版本的JDK( Microsoft builds of OpenJDK),但其他版本 的JDK也支持.
!警告 |
---|
请确保你使用的是64位的JVM.你可以通过在命令行窗口执行 java -version 进行查看.使用32位的JVM可能会引发一些问题,因为32位的 JVM对有些东西不支持. |
熟悉你所选择的集成开发环境(IDE),NeoForge支持 IntelliJ IDEA 和 Eclipse,两者都集成了Gradle的支持.然而任何的IDE都可以使用,包括
从Netbeans或 Visual Studio Code到Vim或Emacs.
熟悉Git和GitHub.虽然这在技术上并不要求,但会是你事半功倍.
构建工作区(Setting Up the Workspace)
打开模组开发包(Mod Developer Kit,简称MDK)(ModDevGradle或NeoGradle)GitHub仓库,点击 "Use this template" (使用此模版),
然后克隆最新的仓库到你本地的机器上.
- 如果你想不使用GitHub,或者你从其他社区获得模版,你可以下载这个仓库的ZIP(在Code下 - >Download ZIP)然后解压它.
打开你的IDE然后倒入Gradle项目.Eclipse 和 IntelliJ IDEA 会为你自动导入.如果你有IDE但并没有自动导入,你也可以通过"gradlew"
终端指令.
- 当第一次这么做时,Gradle将会下载NeoForge的所有依赖,包括Minecraft,并对其进行反编译.这会花费很长一段时间(最长一个小时
这取决于您的硬件和网络)
- 无论何时当你更改了Gradle文件时,你都要通过IDE的“重载Gradle按钮”去刷新Gradle文件,或者再次执行gradlew终端指令
自定义你的模组信息(Customizing Your Mod Information)
你模组大多数的基本属性都可以在gradle.properties文件中修改.如模组名字或模组版本.更多信息请看gradle.properties文件中的注解,
或者看gradle.properties文件的文档(即后文中的gradle.properties).
如果你想修改构建过程,你可以编辑build.gradle文件.NeoGradle是NeoForge的Gradle插件,提供了一下配置选择,其中一些选项由build.Gradle文件中的注释解释.有关完整文档,请参阅NeoGradle文档.
!警告 |
---|
仅编辑 build.gradle 和 settings.gradle文件除非你知道你在做什么.所有的基础属性都可以在gradle.properties文件中更改. |
构建和测试你的mod(Building and Testing Your Mod)
要构建你的模组,请执行gradlew build.这将会输出在build/libs文件里,并名为<archivesBaseName>-<version>.jar.<archivesBaseName>和<version>分别是由build.gradle设置的属性,默认为gradle.properties文件中的mod_id和mod_version值
如果需要,可以在build.gradle中更改.然后,可以将生成的JAR文件放置在有NeoForge的Minecraft的mods文件夹中,或上传到mod
平台上.
要在测试环境中运行你的模组,您可以使用生成的运行配置或使用相关的任务 (例如gradlew runClient).它将会从相应的启动目录启动
Minecraft(例如runs/client或runs/server),以及所有指定的源集(source sets).默认的MDK包括了main源集,因此所有写在src/main/java
中的代码都会被应用.
服务端测试(Server Testing)
如果您正在运行专用服务器,无论是通过run配置还是gradlew runServer,服务器都会立即关闭.你需要同意在运行文件夹(run directory)中eula.txt中的Minecraft EULA条约.
一旦同意,服务器将会被允许在localhost(本地上)(或默认为127.0.0.1)加载.然而你而然无法进入,因为服务器默认开启了在线模式,这需要一个身份验证(开发玩家并没有).为了解决这个问题,你的服务器需要在server.properties文件中将online-mode设置成false.再次启动,你就能进入了.
提示 |
---|
你需要在服务器环境中测试你的mod.这包括仅客户端mod,因为这些mod在服务端上加载时不会做任何事. |
模组文件(Mod Files)
mod文件将负责决定什么mod被打包到你的JAR中,什么信息显示在mods菜单中,以及你的mod应该如何在游戏中加载.
gradle.properties
gradle.properties文件有着你模组中大多数的属性,例如模组id或模组版本.在构建期间,Gradle将会在这些文件中读取这些值并内联到不同位置,例如neoforge.mods.toml文件.这样你只需要在一个地方更改值,其他地方将会自动更改
大多数值在MDK的gradle.properties文件有解释
以下是gradle.properties文件中各种属性的介绍
属性 | 描述 | 示例 |
---|---|---|
org.gradle.jvmargs | 允许你传递额外的JVM参数给Gradle. 通常,它用于分配最多/最少的内存给 Gradle.注意这是分配给Gradle,而不是 Minecraft. | org.gradle.jvmargs=-Xmx3G |
org.gradle.daemon | 在构建时Gradle是否应启用daemon | org.gradle.daemon=false |
org.gradle.debug | Gradle是否要设置成debug模式.debug 模式意味着有更多Gradle日志生成.注意这 是Gradle生成的日志,而不是Minecraft. | org.gradle.debug=false |
minecraft_version | 你正在使用的Minecraft版本. 且必须与neo_version(NeoForge的版本) 匹配 | minecraft_version=1.20.6 |
minecraft_version_range | 此mod可用的mc版本范围,以Maven Version Range格式书写 (如右侧的[1.20.6,1.21), '[' 和 ']' 表示闭区间; '(' 和 ')' 表示开区间) .注意snapshots, pre-releases 和 release candidates不能保证正 确的分类,因为它们不遵循maven versioning | minecraft_version_range=[1.20.6,1.21) |
neo_version | 你正在使用的NeoForge版本,必须与Minecraft 的版本匹配.看NeoForge Versioning部分可以 获取更多与NeaForge版本管理有关的信息 | neo_version=20.6.62 |
neo_version_range | 此mod可用的NeoForge版本范围 ,以Maven Version Range格式书写. | neo_version_range=[20.6.62,20.7) |
loader_version_range | 此mod可用的加载器的版本范围 以Maven Version Range格式书写.注意加载器的版本管理 与NeoForge的版本管理是相互独立的 | loader_version_range=[1,) |
mod_id | 看The Mod ID部分以获取更多信息 | mod_id=examplemod |
mod_name | 玩家可看到的你模组的名称.默认情况下,这只能在模组 列表中看见,然而,像JEI这样的模组会突出显示模组的名 称在物品的提示中 | mod_name=Example Mod |
mod_license | 你模组提供的许可证.建议将他设置成你正在使用的SPDX identifier 或有关的许可证.你可以在这个链接https://choosealicense.com/去 选择你想用的许可证. | mod_license=MIT |
mod_version | 你模组在模组列表中显示的版本.看the page on Versioning部分 以获取更多信息 | mod_version=1.0 |
mod_group_id | 看The Group ID部分以获取更多信息. | mod_group_id=com.example.examplemod |
mod_authors | 模组的作者(你的名字),这会在模组列表中显示出来 | mod_authors=ExampleModder |
mod_description | 模组的描述,会以用几行字符的形式显示在模组列表中.换行符\n | mod_description=Example mod description. |
模组id(The Mod ID)
模组id是将你模组与其他人模组区分的主要方法.它被使用在非常广泛的地方,包括你模组注册的命名空间(namespace),以及你资源和数据包的
命名空间(namespace).有两个相同id的模组同时加载,将会阻止游戏的加载.
因此,你模组的id必须独特且好记.通常,它将会是你模组的显示名(但只能是英文小写),或其变体.模组id仅包括小写字母,数字和下滑线,且必须
在2到64个字符之间.
!注意 |
---|
在gradle.properties文件中更改的属性会被自动应用到任何地方,除了你模组主类中的@Mod注释.因此,你需要手动将其与 gradle.properties文件中的值相匹配. |
组id(The Group ID)
只有你打算将模组发布的Maven,在build.gradle中的group属性才是必要的,正确的设置它是一种很好的习惯.你需要通过修改gradle.properties中的mod_group_id属性来完成修改
group id应该被设置成你的顶级包(top-level package),看后文的Packaging以获取更多信息.
// 你的gradle.properties文件
mod_group_id=com.example
包括你的java代码(src/main/java)也应该遵循这样的格式,其中一个内部包表示mod id:
com
- example (top-level package specified in group property)
- mymod (the mod id)
- MyMod.java (renamed ExampleMod.java)
neoforge.mods.toml
neoforge.mods.toml文件位于src/main/resources/META-INF/neoforge.mods.toml,是一个以 TOML格式来定义你模组元数据(metadata )的文件.它包括了你模组该如何被加载进游戏的额外信息,以及在“Mods”菜单中显示的信息.MDK提供的neoforge.mods.toml文件包含了每个条目的解释,这里将更详细地解释它们.
neoforge.mods.toml可以分成3个部分:non-mod-specific properties,与模组文件联系;mod properties,每个模组的一部分;dependency configurations,每个模组和模组依赖的一部分,一些与neoforge.mods.toml文件相关的属性是强制性的,强制性的属性要有一个指定的值,否则
就会抛出异常(exception).
!注意 |
---|
在默认MDK中,Gradle文件中的各种属性会被Gradle.properties文件中指定的值替换.例如,license="${mod_license}"意味着license 的值将会被gradle.properties文件中的mod_license所对应的值替换.像这样会被替换的值,应该在gradle.properties中修改,而不是在 Gradle中修改. |
Non-Mod-Specific Properties
Non-mod-specific properties(非模组特定属性)是与JAR有关的属性,表明如何加载模组和一些额外的全局元数据(global metadata).
属性 | 类型 | 默认 | 描述 | 例子 |
---|---|---|---|---|
modLoader | string(字符串) | mandatory | mod使用的语言加载器.可被用于支持其他语言框架.例如,主 文件的Kotlin objects,或确定入口点的不同方法,例如接口或 方法.NeoForge提供了java加载器"javafml"以及lowcode/ nocode加载器“lowcodefml”. | modLoader="javafml" |
loaderVersion | string(字符串) | mandatory | 语言加载器支持版的本范围,表示为Maven版本范围.对 于javafml和lowcodefml,这里的版本是1. | loaderVersion="[1,)" |
license | string(字符串) | mandatory | mod在jar中提供的许可证(The license the mod(s) in this JAR are provided under.).建议将他设置成你正在使用的SPDX identifier或有关的许可证.你可以在这个链接https:/ choosealicense.com/去选择你想用的许可证. | license="MIT" |
showAsResourcePack | boolean(布尔) | false | 当为true时,模组的资源将在'Resource Packs'菜单上显示为单独的资源包, 而不是与'Mod Resources'包组合. | showAsResourcePack=true |
showAsDataPack | boolean(布尔) | false | 当为true时,模组的数据文件将在'Data Packs' 菜单上显示为单独的资源包, 而不是与'Data Packs' 包组合. | showAsDataPack=true |
services | array(数组) | [] | 你的模组使用的一系列服务.这是NeoForge实现Java平台模块系统时为mod 创建的模块的一部分。 | services=["net.neoforged.neoforgespi. language.IModLanguageProvider"] |
properties | table(表) | [] | 一个取代属性(properties)的表格.它会被StringSubstitutor用于 将变量${file.<key>}替换为相应的值 | properties={"example"="1.2.3"} (can then be referenced by ${file.example}) |
issueTrackerURL | string(字符串) | nothing | 一个用于报告和追踪mod问题的位置的URL | "https://github.com/neoforged/NeoForge/issues" |
!注意 |
---|
services属性的功能等价于指定uses指令在模块中,这允许加载指定类型的服务. 或者,它可以在src/main/resources/META-INF/services文件夹内的服务文件中定义,其中服务的名字完是限定的,文件内容是 要加载的服务的名称(另请参阅来自AtlasViewer mod的例子) |
Mod-Specific Properties
用 [[mods]]开头将Mod-specific properties绑定到特定的模组.这是一个表数组;所有的键/值都将附加到该模组直到下一个标头.
# Properties for examplemod1(examplemod1的属性)
[[mods]]
modId = "examplemod1"
# Properties for examplemod2(examplemod2的属性)
[[mods]]
modId = "examplemod2"
属性 | 类型 | 默认 | 描述 | 例子 |
---|---|---|---|---|
modId | string | mandatory | 看上文的Mod ID | modId="examplemod" |
namespace | string | value of modId | mod的覆盖命名空间(namespace),必须是有效的mod ID,但可以添加点和破折 号.目前未使用. | namespace="example" |
version | string | "1" | 模组的版本,最好是Maven versioning的变体.当被设置为 ${file.jarVersion}, 它将会被在JAR's manifest中的Implementation-Version属性的值(在开发环境 中显示为0.0NONE)替换 | version="1.20.2-1.0.0" |
displayName | string | value of modId | 模组的显示名.在屏幕上表示mod时使用(例如模组列表,模组错配) | displayName="Example Mod" |
description | string | '''MISSING DESCRIPTION''' | 展示在模组列表的模组描述.推荐使用 多行字符串.描述值是允许被翻译的,看后文 的Translating Mod Metadata获取更多信息.. | description='''This is an example.''' |
logoFile | string | nothing | mod列表屏幕上使用的图像文件的名称和扩展名.logo 必须在JAR的底层(the root of the JAR)或者直接在资源集合的底层(the root of the source set)(例如,src/main/resources 是主要的资源集合). | logoFile="example_logo.png" |
logoBlur | boolean | true | 是否使用GL_LINEAR* (true) 或 GL_NEAREST* (false)去渲染logoFile.简单来说,当调整loge时 loge是否应该变得模糊 | logoBlur=false |
updateJSONURL | string | nothing | 使用在更新检测器的JSON URL,确保你游玩的模组是最新版 | updateJSONURL="https://example.github.io/update_checker.json" |
features | table | {} | 看features部分 | features={java_version="[17,)"} |
modproperties | table | {} | 联系模组的键/值表.未在NeoForge上使用,要使用于模组. | modproperties={example="value"} |
modUrl | string | nothing | 模组下载页面的URL,目前未使用. | modUrl="https://neoforged.net/" |
credits | string | nothing | 展示在模组列表的致谢. | credits="The person over here and there." |
authors | string | nothing | 展示在模组列表的模组作者. | authors="Example Person" |
displayURL | string | nothing | mod列表上显示mod页面的URL | displayURL="https://neoforged.net/" |
enumExtensions | string | nothing | 用于枚举扩展名(enum extension0可看enum extension部分)的JSON文件的文件路径. | enumExtensions="META_INF/enumextensions.json" |
功能(Features)
功能系统允许模组在加载时要求一些正确的可用软件或硬件的设置,.当其中一个功能不满足时,模组将会加载失败,并展示给用户需要的需求.目前NeoForge提供了一下功能:
功能 | 描述 | 示例 |
---|---|---|
javaVersion | 可用的Java版本范围,以Maven Version Range格式书写.这里应该是Minecraft使用的支持版本 | features={javaVersion="[17,)"} |
openGLVersion | 可用的OpenGL版本范围,以Maven Version Range格式书写.Minecraft需要OpenGL 3.2或以上.如果你想需要更新版的OpenGL,你可以在这里进行修改 | features={openGLVersion="[4.6,)"} |
Access Transformer-Specific Properties
Access Transformer-specific properties使用[[accessTransformers]]标头绑定到the specified access transformer.这是一个表数组;所有的键/值属性都附属于the specified access transformer直到下一个标头.The access transformer的标头是任意的;
但是,当被明确指定时,所有元素都是强制性的.
属性 | 类型 | 默认 | 描述 | 示例 |
---|---|---|---|---|
file | string | mandatory | 看Adding ATs部分 | file="at.cfg" |
Mixin Configuration Properties
Mixin Configuration Properties使用[[mixins]]标头绑定到the specified mixin config.这是一个表数组;所有的键/值属性都附属于mixin block 直到下一个标头.mixin 的标头是任意的;
但是,当被明确规定时,所有元素都是强制性的.
Dependency Configurations
模组可以规定它的依赖,neoforge在加载模组前会检查mod的依赖关系.这些配置使用[[dependencies.<modid>]]表数组创建,其中的modid使用的是依赖模组的标识符(identifier).
属性 | 类型 | 默认 | 描述 | 示例 |
---|---|---|---|---|
modId | string | mandatory | 用于添加依赖模组的标识符 | modId="jei" |
type | string | "required" | 规定依赖关系的属性:默认为"required",如果缺少依赖这会阻止模组加载;"optional",如果缺少依赖不会阻止模组加载 但人会确认依赖是否兼容;如果依赖存在"incompatible"将会阻止模组加载;如果依赖模组存在,"discouraged"仍然允许 模组加载,但将会展示一个警告给永用户. | type="incompatible" |
reason | string | nothing | 可选的面向用户的消息,解释为什么需要此依赖关系,或者为什么它不兼容。 | reason="integration" |
versionRange | string | "" | 语言加载器的可接受版本范围,以Maven Version Range格式书写.空字符串匹配任何版本.以Maven Version Range格式书写 空的字符串将匹配任何版本. | versionRange="[1, 2)" |
ordering | string | "NONE" | 定义模组是在依赖模组前还是依赖模组后加载.如果顺序并不重要,请写"NONE". | ordering="AFTER" |
side | string | "BOTH" | 以赖关系的The physical side必须被表为:"CLIENT", "SERVER", 或 "BOTH". | side="CLIENT" |
referralUrl | string | nothing | 依赖下载页面的URL.目前未使用. | referralUrl="https://library.example.com/" |
!危险 |
---|
两个模组的顺序将会发生崩溃由于循环依赖,例如A必须在B之前加载,同时B必须在A之前加载. |
Mod Entrypoints
neoforge.mods.toml已经填写完毕,我们需要为模组提供一个入口点.入口点本质上是执行mod的起点.入口点本身由neoforge.mods.toml中使用的语言加载器决定.
javafml and @Mod
javafml是NeoForge为Java编程语言提供的语言加载器.使用一个@Mod注释的公开类定义为入口点.@Mod的值必须包含neoforge.mods.toml中规定的Mod id之一.从这开始,所有的初始化逻辑(例如 registering events 或 adding DeferredRegisters)
都可以在类的构造器中规定.
这主要的模组类必须有一个唯一公开的构造器;否则将会抛出一个RuntimeException异常.构造器可以按任何顺序添加以下参数;这些都不是明确要求的.但是,不允许有重复的参数.
参数类型 | 描述 |
---|---|
IEventBus | The mod-specific event bus(注册,事件等需要)(看mod-specific event bus部分) |
ModContainer | 保存此模组元数据(metadata)的abstract container |
FMLModContainer | 由javafml定义的actual container,其中包含此mod的元数据;ModContainer的扩展 |
Dist | 此模组加载的物理端(看physical side部分) |
@Mod("examplemod") // 必须与neoforge.mods.toml中的模组id匹配
public class ExampleMod {
// 有效的构造器,仅使用两种参数类型
public ExampleMod(IEventBus modBus, ModContainer container) {
// 在此初始化逻辑
}
}
默认情况下@Mod注释会在两端都加载.可以通过指定dist的参数来更改:
// 必须与neoforge.mods.toml中的模组id匹配
// 此mod类将仅加载到物理客户端上
@Mod(value = "examplemod", dist = Dist.CLIENT)
public class ExampleModClient {
// Valid constructor
public ExampleModClient(FMLModContainer container, IEventBus modBus, Dist dist) {
// 在此初始化仅客户端逻辑
}
}
!注意 |
---|
neoforge.mods.toml中的条目不需要相应的@Mod注释.同样,neoforge.mods.toml中的条目可以有多个@Mod注释,例如,如果你想区分普通逻辑和仅客户端逻辑分开. |
lowcodefml
lowcodefml是一个用于分发数据包和资源包的语言加载器当模组不需要代码入口点(in-code entrypoint)时.明确规定为lowcodefml而不是nocodefml是由于将来可能需求一点代码的添加
结构化你的模组(Structuring Your Mod)
结构化的模组有利于维护,作出贡献,以及更清晰易懂的代码.下面列出了Java,Minecraft和NeoForge的一些建议.
!注意 |
---|
您不必遵循以下建议;你可以以你看着顺眼的方式结构化你的mod. 但是,还是强烈推荐你遵循以下建议 |
Packaging
在构建mod时,选择一个独特的顶级包(top-level package)结构.许多程序员会为不同的类,接口等使用相同的名称.Java允许类有相同的名称,只要它们不在同一个包中.例如,如果有两个相同名字的类在同一个包中,只有一个类会被加载,这很有可能会引发游戏崩溃
a.jar
- com.example.ExampleClass
b.jar
- com.example.ExampleClass //此类通常不会加载
在加载模块时,这一点更为重要.如果类文件在2个有相同名字但在不同模块的包,这将导致模组加载器在启动时崩溃由于mod的模块被导出了游戏和其他mod.
module A
- package X
- class I
- class J
module B
- package X // 这个包将导致模组加载器崩溃,因为已经有一个导出了有包X的模块
- class R
- class S
- class T
像这样,你的顶级包(top level package)应该有些属于你个人的东西:域名,邮箱地址,a网站(a的子域名)等.这也可以是你的名字或用户名只要你可以保证它在你的预期目标是唯一的.此外,顶级包(top-level package)也应该与你的group id匹配
类型 | 值 | Top-Level Package |
---|---|---|
Domain | example.com | com.example |
Subdomain | example.github.io | io.github.example |
example@gmail.com | com.gmail.example |
这下一级的包应该是你的mod的id(例如com.example.examplemod,examplemod为模组id).这能够保证,除非你有2个有相同名称的模组(想必也应该不会有这种情况),你的包在加载时应该不会有任何问题.
你可以在 Oracle's tutorial page中找到额外的命名公约.
子包(Sub-package Organization)
除了顶级包之外,强烈建议拆分你的mod到子包中.这有2种主要的方法:
●功能分类(Group By Function):为具有相同功能的类制作子包.例如,方块可以放在block包,物品放在item包,实体放在entity包,等等.我的世界 自己就使用了相似的结构(有些区别).
●逻辑分类(Group By Logic):为具有相同逻辑的类制作子包.例如,如果你制作了一个新类型的工作台,你可以将这个工作台的方块,菜单,物品以 及其他东西放在feature.crafting_table中.
Client, Server, and Data Packages(客户端,服务端,和数据包)
通常,仅用于特定的端或运行时间的代码应该被分在单独的子包中.例如,联系数据生成(看data generation部分)的代码应该在data的包中运行,以及只能服务器中运行的代码应该在server包中.
强烈建议仅客户端代码(看client-only code部分)应该被独立于client子包中.因为在我的世界中服务器无法访问任何仅客户端包,如果你的模组尝试以任何方式访问它们这将导致崩溃.像这样,有一个特定的包可以提供一个很好的检查,以验证你的mod并没有跨端.
类的命名方案(Class Naming Schemes)
一个普通的类的命名方案可以更容易的解读出类的目的或则简单地定位特定的类.
类通常以其类型作为后缀,例如:
●一个叫做PowerRing的物品(item) -> PowerRingItem.
●一个叫做NotDirt的方块(Block) -> NotDirtBlock.
●一个叫做Oven的菜单(menu)-> OvenMenu.
!注意 |
---|
Mojang通常对除实体之外的所有类遵循类似的结构.这由它们的名字代表(例如,猪,僵尸,等等) |
从多种方法中选择一种(Choose One Method from Many)
执行某项任务的方法有很多:注册一个物品,监听一些事件,等等.通常建议使用单一方法来完成给定的任务,以保持一致性.这提升了可读性以及避免了一些可能发生的奇怪的影响或多余(例如你的事件监听器运行了2次).
版本化(Versioning)
这篇文章会将会以我的世界和NeoForge如何版本化工作分成几部分,并会为mod的版本化提供一些建议.
我的世界(Minecraft)
我的世界使用semantic versioning版本化.Semantic versioning简称"semver",格式major.minor.patch.例如,我的世界1.20.2,主要版本为1,次要版本为20,补丁版本为2.
我的世界自2011年推出Minecraft 1.0以来一直使用1作为主要版本.在此之前,我的世界的版本化方案经常更换,有a1.1(Alpha 1.1),b1.7.3(Beta 1.7.3),甚至infdev版本,这些都没有遵循一个明确的版本化方案.由于1的主要版本已经持续10多年了,并且由于我的世界2(Minecraft 2)的笑话,
普遍认为这种情况不太可能改变.
快照(Snapshots)
快照不同于标准的semver(semantic versioning)方案.它们被编辑为YYwWWa,这里的YY代表当年的最后2个数子(例如23),WW代表当年的第几个星期(例如,01).例如,snapshot 23w01a表示这个快照发布于2023年的第一个星期.
a后缀的存在是为了当有2个快照版本发布在同一周时(第二个快照将命名为23w01b).Mojang在过去偶尔会使用.替代后缀也被用于像20w14infinite这样的快照,这是2020 infinite dimensions April Fool's joke.
Pre-releases and Release Candidates
当快照周期即将完成时,Mojang开始发布所谓的预发布.预发布版本被视为功能完整,且仅集中于错误修复.他们使用semver(semantic versioning)符号表示它所代表的版本,后缀为-preX.例如,1.20.2的第一个预发布版本被命名为1.20.2-pre1.通常会有多个预发布版本,因此后缀可以为-pre2, -pre3等等.
类似的,预发布版本周期完成时,Mojang会发布候选版本1(Release Candidate 1)(在版本后添加-rc1,例如1.20.2-rc1).Mojang的目的是如果将来没有bug出现,Mojang可以有一个候选版本可以发布.不过,如果有一个未预料的bug发生,这将会有 -rc2, -rc3等.与预发布版本类似.
NeoForge
NeoForge使用了一个被改变的semver体系:它的主要版本是mc的次要版本,它的次要版本是mc的补丁版本,补丁版本才是NeoForge的 "本身"版本.例如,NeoForge 20.2.59是Minecraft 1.20.2的第60个版本(我们开始于0).开头的1被省略了,因为它不太可能改变,请参阅上文,了解原因.在NeoForge的一些地方也使用了Maven version ranges,例如Minecraft和NeoForge在neoforge.mods.toml文件中的版本范围.这些大多与semver兼容,但并不完全兼容(例如,它不考pre-标签).
Mods
这并没有决定的最佳版本化系统.不同的开发风格,工程的范围,等等.都决定着该使用哪一种版本化体系.有时,版本化体系可以混合使用.本节试图通过现实生活中的例子概述一些常用的版本控制系统.
通常,一个模组文件的名字应该是modid-<version>.jar.因此,如果我们的mod id是examplemod,版本是1.2.3,那么我们的mod文件将命名为examplemod-1.2.3.jar.
!注意 |
---|
推荐使用版本化体系,但不是要严格执行的规则.对于版本何时更改("bumped"),以及以何种方式更改尤其如此.如果你想使用一种不同的版本体系 没有人会去管你. |
Copcepts
Blocks
Items
Block Entities
Resources
Data Storage
GUIs
Worldgen
Networking
Advanced Topics
Miscellaneous
Legacy