配置
配置定义可应用于某个 Mod 实例的设置和用户偏好。NeoForge 的配置系统使用 TOML 文件,并通过 NightConfig 读取。
创建配置
配置可以通过 IConfigSpec 的子类型创建。NeoForge 使用 ModConfigSpec 实现它,并提供 ModConfigSpec.Builder 构造配置。构建器通过 Builder#push 创建并进入区段,通过 Builder#pop 离开区段,从而将配置值分组。之后可以用以下两种方法之一构建配置:
| 方法 | 说明 |
|---|---|
build |
创建 ModConfigSpec。 |
configure |
创建一个 pair,包含持有配置值的类与 ModConfigSpec。 |
提示
ModConfigSpec.Builder#configure通常与静态代码块配合使用,并让持有配置值的类通过构造函数接受ModConfigSpec.Builder,以定义和保存这些值://Define a field to keep the config and spec for later public static final ExampleConfig CONFIG; public static final ModConfigSpec CONFIG_SPEC; //CONFIG and CONFIG_SPEC are both built from the same builder, so we use a static block to seperate the properties static { Pair<ExampleConfig, ModConfigSpec> pair = new ModConfigSpec.Builder().configure(ExampleConfig::new); //Store the resulting values CONFIG = pair.getLeft(); CONFIG_SPEC = pair.getRight(); }
每个配置值都可以提供额外上下文以增加行为。上下文必须在配置值完全构建之前定义:
| 方法 | 说明 |
|---|---|
comment |
描述配置值的用途。可提供多个字符串形成多行注释。 |
translation |
为配置值名称提供翻译键。 |
worldRestart |
修改配置值前必须重启世界。 |
ConfigValue
可以使用任意 #define 方法,结合已定义的上下文创建配置值。
所有配置值方法至少接受两个组成部分:
- 表示变量名称的路径:使用点分隔的字符串,表示配置值所属区段。
- 没有有效配置时使用的默认值。
专门用于 ConfigValue 的方法还接受:
- 验证器:确保反序列化得到的对象有效。
- 表示配置值数据类型的类。
//Store the config properties as public finals
public final ModConfigSpec.ConfigValue<String> welcomeMessage;
private ExampleConfig(ModConfigSpec.Builder builder) {
//Define each property
//One property could be a message to log to the console when the game is initialised
welcomeMessage = builder.define("welcome_message", "Hello from the config!");
}
可通过 ConfigValue#get 获取实际值。值还会被缓存,以免重复读取文件。
其他配置值类型
- 范围值:必须位于指定边界之间。
- 类类型:
Comparable<T>;方法:#defineInRange。 - 额外参数:允许的最小值、最大值,以及表示数据类型的类。
- 类类型:
提示
DoubleValue、IntValue、LongValue是分别将类指定为Double、Integer、Long的范围值。
- 白名单值:必须包含在给定集合中。
- 类类型:
T;方法:#defineInList。 - 额外参数:允许值的集合。
- 类类型:
- 列表值:值是一组条目组成的列表。
- 类类型:
List<T>;方法:#defineList,若允许空列表则使用#defineListAllowEmpty。 - 额外参数:在配置界面添加新条目时提供默认值的 supplier;确保反序列化后的列表元素有效的验证器;可选的列表条目数量验证器,防止条目过少或过多。
- 类类型:
- 枚举值:给定集合中的枚举值。
- 类类型:
Enum<T>;方法:#defineEnum。 - 额外参数:将字符串或整数转换为枚举的 getter,以及允许值的集合。
- 类类型:
- 布尔值:
boolean值。- 类类型:
Boolean;方法:#define。
- 类类型:
注册配置
构建 ModConfigSpec 后必须注册,以便 NeoForge 按需加载、跟踪和同步配置。应在 Mod 构造函数中通过 ModContainer#registerConfig 注册,参数包括表示配置所属端的配置类型、ModConfigSpec,以及可选的配置文件名。
// In the main mod file with a ModConfigSpec CONFIG_SPEC
public ExampleMod(ModContainer container) {
...
//Register the config
container.registerConfig(ModConfig.Type.COMMON, ExampleConfig.CONFIG_SPEC);
...
}
配置类型
配置类型决定文件位置、加载时机以及是否通过网络同步。默认情况下,物理客户端从 .minecraft/config 加载,物理服务端从 <server_folder>/config 加载。各类型的区别如下。
建议 NeoForge 在代码库中提供了配置类型的说明。
STARTUP- 物理客户端和物理服务端均从 config 文件夹加载。
- 注册时立即读取。
- 不会通过网络同步。
- 默认文件后缀为
-startup。
警告
STARTUP配置可能造成客户端与服务端不同步,例如用配置禁用内容注册。因此,强烈建议不要用此类配置启用或禁用会改变 Mod 内容的功能。
CLIENT- 仅在物理客户端从 config 文件夹加载,服务端没有此类配置的位置。
- 在
FMLCommonSetupEvent触发前立即读取。 - 不会通过网络同步。
- 默认文件后缀为
-client。
COMMON- 物理客户端和物理服务端均从 config 文件夹加载。
- 在
FMLCommonSetupEvent触发前立即读取。 - 不会通过网络同步。
- 默认文件后缀为
-common。
SERVER- 物理客户端和物理服务端均从 config 文件夹加载。
- 可在每个世界中覆盖:客户端路径为
.minecraft/saves/<world_name>/serverconfig,服务端路径为<server_folder>/world/serverconfig。 - 在
ServerAboutToStartEvent触发前立即读取。 - 通过网络同步到客户端。
- 默认文件后缀为
-server。
配置事件
可以通过 ModConfigEvent.Loading 和 ModConfigEvent.Reloading 处理每次配置加载或重载时的操作。事件必须注册到 Mod 事件总线。
注意 这些事件会为 Mod 的所有配置触发。应使用提供的
ModConfig对象判断正在加载或重载哪份配置。
配置界面
配置界面允许用户在游戏中修改 Mod 配置值,无需打开文件。界面会自动解析已注册的配置文件并填充内容。
Mod 可以使用 NeoForge 的内置配置界面,也可以继承 ConfigurationScreen 修改默认行为或制作自己的界面。还可以从零创建界面,并通过下述扩展点交给 NeoForge。
在客户端的 Mod 构造过程中注册 IConfigScreenFactory 扩展点,即可注册配置界面:
// In the main client mod file
public ExampleModClient(ModContainer container) {
...
// This will use NeoForge's ConfigurationScreen to display this mod's configs
container.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new);
...
}
进入游戏的“Mods”页面,在侧栏选择 Mod,再点击“Config”按钮即可打开。Startup、Common、Client 配置选项始终可编辑。Server 配置仅在本地世界中游玩时可编辑;连接服务器或其他人的局域网世界时,界面会禁用 Server 配置。该 Mod 的配置首页会显示全部已注册文件,供玩家选择。
警告 制作界面时,应为所有配置条目添加翻译键,并在语言 JSON 中提供译文。
可通过
ModConfigSpec$Builder#translation指定翻译键,例如扩展前面的代码:ConfigValue<T> value = builder.comment("This value is called 'config_value_name', and is set to defaultValue if no existing config is present") .translation("modid.config.config_value_name") .define("config_value_name", defaultValue);为了便于翻译,可以打开配置界面并访问所有配置及子区段,再返回 Mod 列表界面。此时,遇到的所有未翻译条目都会打印到控制台,方便确认要翻译的内容及翻译键。
来源: NeoForged/Documentation(1.21.1)。中文翻译依据提交
4a680cdd4d15。