模组文件与决定以何种方式将你的模组打包进你的JAR包,Mods菜单中要显示什么信息,你的模组应该怎样加载进游戏有关。

gradle.properties

gradle.properties文件里面有各种有关于你的模组的常见属性,例如模组id或者模组版本。在构建的时候,Gradle会读取这些文件中的值并且把他们内联到各个地方,例如neoforge.mods.toml文件。这样,你只需要在一处更改值,他们就会为你应用到任何别的地方。

大部分值也会在MDK的gradle.properties文件中以注释的形式来解释其作用。

属性

描述

例子

org.gradle.jvmargs

允许你传递给Gradle更多JVM参数。最常见的是用来为Gradle分配更多/更少的内存空间。注意这是为Gradle本身分配的,不是Minecraft。

org.gradle.jvmargs=-Xmx3G

org.gradle.daemon

决定了Gradle在构建的时候是否使用守护程序。

org.gradle.daemon=false

org.gradle.debug

决定了Gradle是否设置为debug模式。debug模式主要意味着更多的Gradle日志输出。注意,这是Gradle本身的设置,不是Minecraft的。

org.gradle.debug=false

minecraft_version

你的模组所基于的Minecraft版本。必须与neo_version相匹配。

minecraft_version=1.20.6

minecraft_version_range

本模组可以使用的Minecraft版本范围,作为一个Maven的版本命名范围。需要注意的是快照,预发布版本和正式版本候选并不能保证被正确的排序,因为他们并不遵循maven版本命名。

minecraft_version_range=[1.20.6,1.21)

neo_version

你的模组所基于的NeoForge版本。必须与minecraft_version相匹配。查看NeoForge版本命名规则以获取更多关于NeoForge如何定义版本号的信息。

neo_version=20.6.62

neo_version_range

本模组可以使用的NeoForge版本范围,以Maven版本范围

neo_version_range=[20.6.62,20.7)

loader_version_range

这个模组可以使用的模组加载器的版本范围,以Maven版本范围。要注意的是加载器的版本是与NeoForge的版本解耦的。

loader_version_range=[1,)

mod_id

查看模组ID

mod_id=examplemod

mod_name

你的模组在自然语言下的显示名称。默认情况下,这个值只能在mod列表中看到,但是一些例如JEI的模组也会在物品的工具提示中显示这个值。

mod_name=Example Mod

mod_license

你的模组提供了什么许可证。建议将其设置为你正在使用的SPDX identifier或者是一个通向许可证的链接。你可以访问https://choosealicense.com/来帮助你挑选你想要的许可证。

mod_license=MIT

mod_version

你的模组的版本,在模组列表中会显示这个值。参考版本命名页面获取更多信息。

mod_version=1.0

mod_group_id

请参考群组ID

mod_group_id=com.example.examplemod

mod_authors

模组的作者,会在模组列表中显示。

mod_authors=ExampleModder

mod_description

模组的介绍文字,在模组列表中显示的是一个多行的字符串。换行符\n可以正常使用。

mod_description=Example mod description.

模组ID

模组ID是你的模组与其他模组相区分的主要方式。它在很多不同的地方都有用到,包括作为你的模组注册时的命名空间,并作为你的资源包和数据包的命名空间。如有同时存在两个具有相同id的模组,游戏不会加载。

因此,你的模组ID应该是独特且好记的。通常,它会是你的模组的显示名称(但是是小写的),或者是一些变体。模组ID只能包含小写字母,数字和下划线,并且长度必须控制在2-64个字符之内(包含两侧)。

ℹ️info

改变gradle.properties文件中的这些属性会自动应用改动到任何地方,除了你的主要模组类中的@Mod 注释。因此你需要手动修改这些地方来与gradle.properties里面的这些值相匹配。

群组ID

build.gradle中的group属性只有在你打算将你的模组发布到maven的时候才有意义,不过正确的设置这些属性总是个好的练习。你可以通过gradle.properties中的mod_group_id属性来修改它。

群组id应该设置在你的顶级包中,参考打包来获取更多信息。

// 在你的gradle.properties文件中
mod_group_id=com.example

在你的Java源文件(src/main/java)中的包也应该遵循这个构造,带着一个子包代表模组id:

com
- example (群组属性中指定的顶级包)
    - mymod (模组id)
        - MyMod.java (由ExampleMod.java重命名而来)

neoforge.mods.toml

位于src/main/resources/META-INF/neoforge.mods.tomlneoforge.mods.toml文件,是一个TOML格式来定义模组元数据的文件。它也包含了一些关于模组该怎样加载进游戏的额外信息,同时也是显示在Mods菜单里面的信息。由MDK提供的neoforge.mods.toml文件包含了解释每个入口的注释,在这里这些解释更详细。

neoforge.mods.toml 文件可以被分为三个部分:非模组特定属性(被链接到模组文件);模组属性(每个模组都有一个小节);以及依赖配置。一些与neoforge.mods.toml相关联的属性是强制的;强制属性需要一个特定的值,不然会抛出一个异常。

ℹ️注意

在默认的MDK中,Gradle用gradle.properties文件中的特定值替换了这个文件中的各种属性。例如,license="${mod_license}"一行的意思是license字段被替换成了来自gradle.propertiesmod_license属性。像这样被替换掉的值应该在gradle.properties中改变,而不是这里

非模组特定属性

非模组特定属性是与JAR本身有关系的,指示了如何加载模组和任何附加的全局元数据。

属性

类型

默认

描述

例子

modLoader

string

强制的

模组使用的语言加载器。可以用来支持主动语言结构,像是主文件的Kotlin目标,或者决定入点的不同方式,像是一个接口或者方法。NeoForge提供了Java加载器“javafml”以及低代码/无代码加载器“lowcodefml”。

modLoader="javafml"

loaderVersion

string

强制的

语言加载器可以接受的版本范围,以Maven版本范围的方式表达。对于javafmllowcodefml来说,目前版本是1。

loaderVersion="[1,)"

license

string

强制的

这个JAR中的模组使用的许可证。建议将其设置为你正在使用的SPDX identifier或者是一个通向许可证的链接。你可以访问https://choosealicense.com/ 来帮助你挑选你想要的许可证。

license="MIT"

showAsResourcePack

boolean

false

当设置为true的时候,模组的资源在资源包菜单会被显示为一个独立的资源包,而不是被合并到“Mod Resources”资源包里面。

showAsResourcePack=true

showAsDataPack

boolean

false

当设置为true的时候,模组的资源在数据包菜单会被显示为一个独立的数据包,而不是被合并到“Mod Data”数据包里面。

showAsDataPack=true

services

array

[]

这是你的模组用到的一组服务。它会被用在为你的模组创建的模块里,这个模块是基于NeoForge实现的Java平台模块系统

services=["net.neoforged.neoforgespi.language.IModLanguageProvider"]

properties

table

{}

这是一个用于替换的属性表。StringSubstitutor 会用它来把 ${file.<key>} 替换成对应的内容。

properties={"example"="1.2.3"} (can then be referenced by ${file.example})

issueTrackerURL

string

nothing

用于报告和追踪模组bug的网址。

"https://github.com/neoforged/NeoForge/issues"

ℹ️注意

services 属性的作用和在模块里写 uses 指令是一样的,都是用来加载某种类型的服务。

另一种方法是在 src/main/resources/META-INF/services 文件夹里创建一个服务文件。文件名要用服务的完整名称,文件内容则是要加载的服务的名称(可以参考 AtlasViewer 模组的例子)。

模组特定属性

模组的专属属性要用 [[mods]] 标题来指定。这是一个表格的数组;在这个标题下面的所有键值对都会归到这个模组,直到遇到下一个标题为止。

# examplemod1的属性
[[mods]]
modId = "examplemod1"

# examplemod2的属性
[[mods]]
modId = "examplemod2"

属性

类型

默认

描述

例子

modId

string

强制的

查阅模组ID

modId="examplemod"

namespace

string

模组id的值

这是用来覆盖的模组命名空间。它必须是一个合法的模组ID,但可以加上点或短横线。目前还没用到。

namespace="example"

version

string

"1"

这是模组的版本号,最好用类似 Maven 的版本格式。如果设成 ${file.jarVersion},它就会被 JAR 文件清单里的 Implementation-Version 属性值替换掉(开发环境会显示 0.0NONE)。

version="1.20.2-1.0.0"

displayName

string

value of modId

这是模组在屏幕上显示的名字(比如模组列表、模组不兼容提示里)。

displayName="Example Mod"

description

string

'''MISSING DESCRIPTION'''

这是模组的介绍,会在模组列表里显示。最好用多行文本字符串来写。这段文字还可以翻译成其他语言,想了解更多可以看“翻译模组元数据”这部分。

description='''This is an example.'''

logoFile

string

nothing

这是模组列表上用的图片的文件名和扩展名。文件位置必须从 JAR 文件或源代码根目录开始的绝对路径(比如主源代码的 src/main/resources)。文件名只能包含小写字母(a-z)、数字(0-9)、斜杠(/)、下划线(_)、点(.)和短横线(-)。所有允许的字符是 [a-z0-9_.-]

logoFile="test/example_logo.png"

logoBlur

boolean

true

GL_LINEAR*(true)还是 GL_NEAREST*(false)来渲染 logo 图片。简单地说,就是缩放 logo 的时候要不要让它变模糊。

logoBlur=false

updateJSONURL

string

nothing

这是个网址,指向一个 JSON 文件,用来给更新检查器用的,它可以检查你玩的模组是不是最新的。

updateJSONURL="https://example.github.io/update_checker.json"

features

table

{}

请查阅特性

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

这是模组在模组列表里显示的那个介绍页面的网址。

displayURL="https://neoforged.net/"

enumExtensions

string

nothing

这是用来扩展枚举的 JSON 文件的路径。

enumExtensions="META_INF/enumextensions.json"

featureFlags

string

nothing

用于特性标志的 JSON 文件的文件路径。

featureFlags="META-INF/feature_flags.json"

特性

这个特性系统让模组可以要求在加载的时候,某些设置、软件或者硬件必须可用。如果哪个要求没达到,模组就加载不了,还会告诉用户缺了什么。现在 NeoForge 提供了这些特性:

特性

描述

例子

javaVersion

允许使用的 Java 版本范围,用的是 Maven 的版本表示法。这应该和 Minecraft 支持的版本一致。

features={javaVersion="[17,)"}

openGLVersion

允许使用的 OpenGL 版本范围,用的是 Maven 的版本表示法。Minecraft 最低要求是 OpenGL 3.2。如果你的模组需要更新的 OpenGL 版本,就在这里设置。

features={openGLVersion="[4.6,)"}

访问转换器的专用属性

访问转换器的专属属性要用 [[accessTransformers]] 标题来指定。这是一个表格的数组;在这个标题下面的所有键值对都会归到这个访问转换器,直到遇到下一个标题为止。访问转换器标题可以不写;但是一旦写了,里面的东西就都得填上。

属性

类型

默认

描述

例子

file

string

强制的

参阅添加AT

file="at.cfg"

Mixin 的配置属性

Mixin 的配置属性要用 [[mixins]] 标题来指定。这是一个表格的数组;在这个标题下面的所有键值对都会归到这个 Mixin 配置,直到遇到下一个标题为止。[[mixins]] 标题可以不写;但是一旦写了,里面的东西就都得填上。

属性

类型

默认

描述

例子

config

string

强制的

mixin配置文件的位置

config="examplemod.mixins.json"

依赖配置

模组可以设置它们需要哪些其他模组才能运行,NeoForge 会在加载模组前检查这些依赖。这些依赖配置要用 [[dependencies.<modid>]] 这种表格数组来写,其中 modid 是指需要这个依赖的模组的 ID。

属性

类型

默认

描述

例子

modId

string

mandatory

这是作为依赖加进来的模组的 ID。

modId="jei"

type

string

"required"

这个选项用来设置依赖的类型:“required”是默认的,意思是如果缺了这个依赖,模组就加载不了;“optional”意思是即使缺了这个依赖,模组也能加载,但是还是会检查一下这个依赖是不是兼容的;“incompatible”意思是如果装了这个依赖,模组就不能加载;“discouraged”意思是即使装了这个依赖,模组也能加载,但是会给用户一个警告。

type="incompatible"

reason

string

nothing

这是一个可选的给用户看的消息,用来解释为什么需要这个依赖,或者为什么它不兼容。

reason="integration"

versionRange

string

""

允许使用的语言加载器版本范围,用的是 Maven 的版本表示法。如果是空字符串,就表示匹配所有版本。

versionRange="[1, 2)"

ordering

string

"NONE"

这个设置用来决定模组是必须在这个依赖之前("BEFORE")还是之后("AFTER")加载。如果顺序无所谓,就写 "NONE"。

ordering="AFTER"

side

string

"BOTH"

这个依赖需要在哪个地方存在:“CLIENT”(客户端)、“SERVER”(服务器)或者“BOTH”(两边都要)。

side="CLIENT"

referralUrl

string

nothing

指向依赖项下载页面的 URL。目前未使用。

referralUrl="https://library.example.com/"

❗危险

两个模组的加载顺序可能由于循环依赖而导致崩溃,例如,如果模组 A 必须在模组 B 之前(“BEFORE”)加载,同时模组 B 又必须在模组 A 之前(“BEFORE”)加载。

模组入口点

搞定了 neoforge.mods.toml 之后,我们得给模组弄个入口点。入口点其实就是模组开始运行的地方。用哪个入口点是由 neoforge.mods.toml 里用的语言加载器决定的。

javafml@Mod

javafml 是 NeoForge 给 Java 用的一个语言加载器。入口点要用一个带 @Mod 注解的公共类来定义。@Mod 里面的值必须是 neoforge.mods.toml 文件里写好的模组 ID 之一。然后,所有的初始化代码(比如注册事件或者添加 DeferredRegisters)都写在这个类的构造函数里面。

主模组类只能有一个 public 的构造函数,不然会抛出 RuntimeException 错误。构造函数可以随便用下面这些参数,顺序也无所谓,而且这些参数也不是一定要有。但是,不能有重复的参数。

类型

描述

IEventBus

这是模组专用的事件总线(用来注册东西、处理事件之类的)。

ModContainer

保存此模组元数据的抽象容器

FMLModContainer

这是 javafml 实际用来装模组元数据的容器,它是 ModContainer 的扩展。

Dist

模组当前运行的物理环境

@Mod("examplemod") // 必须与neoforge.mods.toml中的一个mod id匹配
public class ExampleMod {
    // 这是一个有效的构造函数,它只用了两种参数类型。
    public ExampleMod(IEventBus modBus, ModContainer container) {
        // 在此写初始化逻辑
    }
}

默认情况下,@Mod 注解会在客户端和服务器都加载。你可以通过设置 dist 参数来改变这个行为。

// 必须与neoforge.mods.toml中的一个mod id匹配
// 这个模组的类只会在客户端加载
@Mod(value = "examplemod", dist = Dist.CLIENT) 
public class ExampleModClient {
    // 有效的构造函数
    public ExampleModClient(FMLModContainer container, IEventBus modBus, Dist dist) {
        // 在此写客户端逻辑
    }
}

ℹ️注意

neoforge.mods.toml 里写的一个条目不一定需要有个对应的 @Mod 注解。反过来,neoforge.mods.toml 里的一个条目也可以对应好几个 @Mod 注解,比如说你想把通用的代码和只有客户端才用的代码分开写。

lowcodefml

lowcodefml 是一种语言加载器,它可以让你把数据包和资源包当成模组来发布,不需要写任何代码。之所以叫 lowcodefml 而不是 nocodefml,是因为以后可能会加一些只需要写一点点代码的功能。

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