配置(Configuration)
配置(Configuration)
配置用于定义模组的设置和用户偏好,可以在模组实例中应用。NeoForge 使用基于 TOML 文件的配置系统,并通过 NightConfig 进行读取。
创建配置
配置可以通过 IConfigSpec 的子类型创建。NeoForge 通过 ModConfigSpec 实现该类型,并通过 ModConfigSpec.Builder 进行构建。构建器可以通过 Builder#push 创建配置部分,并通过 Builder#pop 离开部分。之后,可以使用以下两种方法之一构建配置:
| 方法 | 描述 |
|---|---|
build | 创建 ModConfigSpec。 |
configure | 创建一个包含配置值类和 ModConfigSpec 的配对。 |
注意: ModConfigSpec.Builder#configure 通常与静态块和以 ModConfigSpec.Builder 为构造函数参数的类一起使用,以附加和保存配置值。
// 定义字段以保存配置和规范
public static final ExampleConfig CONFIG;
public static final ModConfigSpec CONFIG_SPEC;
// CONFIG 和 CONFIG_SPEC 从同一个构建器构建,因此使用静态块分离属性
static {
Pair<ExampleConfig, ModConfigSpec> pair =
new ModConfigSpec.Builder().configure(ExampleConfig::new);
// 存储结果值
CONFIG = pair.getLeft();
CONFIG_SPEC = pair.getRight();
}配置值(ConfigValue)
每个配置值都可以附加额外的上下文以提供额外行为。上下文必须在配置值完全构建之前定义:
| 方法 | 描述 |
|---|---|
comment | 提供配置值的描述。可以提供多个字符串以支持多行注释。 |
translation | 提供配置值名称的翻译键。 |
worldRestart | 必须重启世界才能更改配置值。 |
配置值可以通过提供的上下文(如果已定义)使用任何 #define 方法构建。所有配置值方法至少需要两个组件:
- 表示变量名称的路径:用
. 分隔的字符串,表示配置值所在的部分。 - 当没有有效配置时的默认值。
ConfigValue 特定方法还需要两个额外组件:
- 验证器,用于确保反序列化的对象有效。
- 表示配置值数据类型的类。
// 将配置属性存储为公共 final 字段
public final ModConfigSpec.ConfigValue<String> welcomeMessage;
private ExampleConfig(ModConfigSpec.Builder builder) {
// 定义每个属性
// 一个属性可以是游戏初始化时记录到控制台的消息
welcomeMessage = builder.define("welcome_message", "Hello from the config!");
}配置值可以通过 ConfigValue#get 获取。这些值会被缓存,以防止多次读取文件。
其他配置值类型
范围值(Range Values)
- 描述:值必须在定义的范围内。
- 类类型:
Comparable<T> - 方法名:
#defineInRange - 额外组件:最小值、最大值和表示数据类型的类。
注意:
DoubleValues、IntValues 和LongValues 是范围值,分别指定类为Double、Integer 和Long。白名单值(Whitelisted Values)
- 描述:值必须在提供的集合中。
- 类类型:
T - 方法名:
#defineInList - 额外组件:允许的配置值集合。
列表值(List Values)
- 描述:值是条目的列表。
- 类类型:
List<T> - 方法名:
#defineList、#defineListAllowEmpty(如果列表可以为空)。 - 额外组件:返回默认值的供应商、验证器(可选)和列表条目数量的验证器。
枚举值(Enum Values)
- 描述:集合中的枚举值。
- 类类型:
Enum<T> - 方法名:
#defineEnum - 额外组件:将字符串或整数转换为枚举的获取器,以及允许的配置值集合。
布尔值(Boolean Values)
- 描述:布尔值。
- 类类型:
Boolean - 方法名:
#define
注册配置
一旦构建了 ModConfigSpec,必须注册它以允许 NeoForge 根据需要加载、跟踪和同步配置设置。配置应在模组构造函数中通过 ModContainer#registerConfig 注册。配置可以注册为特定类型,表示配置所属的端,并可选地指定配置文件的名称。
// 在主模组文件中使用 ModConfigSpec CONFIG
public ExampleMod(ModContainer container) {
...
// 注册配置
container.registerConfig(ModConfig.Type.COMMON, ExampleConfig.CONFIG);
...
}配置类型
配置类型决定了配置文件的位置、加载时间以及是否通过网络同步。所有配置默认从物理客户端的 .minecraft/config 或物理服务器的 <server_folder>/config 加载。以下是每种配置类型的详细信息:
STARTUP
- 从配置文件夹加载到物理客户端和物理服务器。
- 注册时立即读取。
- 不通过网络同步。
- 默认后缀为
-startup。
警告:
STARTUP 类型的配置可能导致客户端和服务器之间的不同步,例如用于禁用内容注册的配置。因此,强烈建议不要在STARTUP 中使用启用或禁用功能的配置。CLIENT
- 仅从配置文件夹加载到物理客户端。
- 服务器没有此配置类型的位置。
- 在
FMLCommonSetupEvent 触发之前立即读取。 - 不通过网络同步。
- 默认后缀为
-client。
COMMON
- 从配置文件夹加载到物理客户端和物理服务器。
- 在
FMLCommonSetupEvent 触发之前立即读取。 - 不通过网络同步。
- 默认后缀为
-common。
SERVER
从配置文件夹加载到物理客户端和物理服务器。
可以通过以下路径为每个世界覆盖配置:
- 客户端:
.minecraft/saves/<world_name>/serverconfig - 服务器:
<server_folder>/world/serverconfig
- 客户端:
在
ServerAboutToStartEvent 触发之前立即读取。通过网络同步到客户端。
默认后缀为
-server。
配置事件
配置加载或重新加载时执行的操作可以通过 ModConfigEvent.Loading 和 ModConfigEvent.Reloading 事件完成。这些事件必须注册到模组事件总线。
注意: 这些事件为模组的所有配置调用;提供的 ModConfig 对象应用于标识正在加载或重新加载的配置。
配置屏幕
配置屏幕允许用户在游戏内编辑模组的配置值,而无需打开任何文件。屏幕会自动解析注册的配置文件并填充屏幕。
模组可以使用 NeoForge 提供的内置配置屏幕。模组可以扩展 ConfigurationScreen 以更改默认屏幕的行为,或创建自己的配置屏幕。模组还可以从头开始创建自己的屏幕,并通过以下扩展点将其提供给 NeoForge。
配置屏幕可以在客户端模组构造函数中通过注册 IConfigScreenFactory 扩展点来注册:
// 在主客户端模组文件中
public ExampleModClient(ModContainer container) {
...
// 这将使用 NeoForge 的 ConfigurationScreen 显示此模组的配置
container.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new);
...
}配置屏幕可以在游戏中通过进入“模组”页面,从侧边栏选择模组,然后点击“配置”按钮访问。Startup、Common 和 Client 配置选项始终可编辑。Server 配置仅在本地玩世界时可在屏幕中编辑。如果连接到服务器或其他人的局域网世界,Server 配置选项将在屏幕中禁用。模组配置屏幕的第一页将显示每个注册的配置文件,供玩家选择要编辑的文件。
警告: 如果创建屏幕,应为所有配置条目添加翻译键并在语言 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);为了简化翻译,打开配置屏幕并访问所有配置及其子部分,然后返回模组列表屏幕。此时,所有未翻译的配置条目将打印到控制台。这样可以更容易地知道需要翻译的内容以及翻译键是什么。