跳转至

原文:MinecraftForge/Documentation · 目标版本:Forge 1.20.1

配置(Configuration)

配置(Configuration)定义了可应用于模组实例的设置和用户偏好。Forge 使用基于 TOML 文件的配置系统,并通过 NightConfig 读取。

创建配置(Creating a Configuration)

可以使用 IConfigSpec 的子类型来创建配置。Forge 通过 ForgeConfigSpec(配置规格)实现该类型,并借助 ForgeConfigSpec$Builder(构建器)来构建它。构建器可以通过 Builder#push 将配置值划分到各个分区(section)中,再通过 Builder#pop 离开某个分区。之后,可以使用以下两种方法之一来构建配置:

方法 描述
build 创建 ForgeConfigSpec
configure 创建「持有配置值的类」与 ForgeConfigSpec 的组合(pair)。

Note

ForgeConfigSpec$Builder#configure 通常与 static 代码块以及一个在构造函数中接收 ForgeConfigSpec$Builder 的类配合使用,用于将配置值挂载并保存在类中:

// 在某个配置类中
ExampleConfig(ForgeConfigSpec.Builder builder) {
  // 在 final 字段中定义配置值
}

// 在可访问构造函数的地方
static {
  Pair<ExampleConfig, ForgeConfigSpec> pair = new ForgeConfigSpec.Builder()
    .configure(ExampleConfig::new);
  // 将 pair 中的值存储在某个常量字段中
}

每个配置值都可以附带额外的上下文(context),以提供额外的行为。上下文必须在配置值完全构建之前定义:

方法 描述
comment 提供该配置值作用的描述。可以传入多个字符串以形成多行注释。
translation 提供该配置值名称的翻译键(translation key)。
worldRestart 更改该配置值之前必须重启世界。

配置值(ConfigValue)

可以使用任意 #define 方法,结合已提供的上下文(若已定义)来构建配置值。

所有配置值方法至少接受两个组成部分:

  • 表示变量名称的路径:一个以 . 分隔的字符串,表示该配置值所在的分区
  • 当不存在有效配置时的默认值

ConfigValue 特有的方法还接受两个额外的组成部分:

  • 一个校验器(validator),用于确保反序列化得到的对象是有效的
  • 一个表示配置值数据类型的类
// 对于某个 ForgeConfigSpec$Builder 构建器
ConfigValue<T> value = builder.comment("Comment")
  .define("config_value_name", defaultValue);

配置值本身可以通过 ConfigValue#get 获取。这些值还会被缓存,以避免重复从文件中读取。

其他配置值类型(Additional Config Value Types)

  • 范围值(Range Values)
    • 描述:值必须在定义的上下界之间
    • 类类型:Comparable<T>
    • 方法名:#defineInRange
    • 附加组成部分:
    • 配置值允许的最小值和最大值
    • 一个表示配置值数据类型的类

Note

FloatValueDoubleValueByteValueShortValueIntValueLongValue 都是范围值,分别将类指定为 FloatDoubleByteShortIntegerLong

  • 白名单值(Whitelisted Values)

    • 描述:值必须在所提供的集合中
    • 类类型:T
    • 方法名:#defineInList
    • 附加组成部分:
    • 配置允许的值的集合
  • 列表值(List Values)

    • 描述:值是一个条目的列表
    • 类类型:List<T>
    • 方法名:#defineList;如果列表可以为空,则使用 #defineListAllowEmpty
    • 附加组成部分:
    • 一个校验器,用于确保列表中的反序列化元素是有效的
  • 枚举值(Enum Values)

    • 描述:所提供集合中的一个枚举值
    • 类类型:Enum<T>
    • 方法名:#defineEnum
    • 附加组成部分:
    • 一个用于将字符串或整数转换为枚举的获取器(getter)
    • 配置允许的值的集合
  • 布尔值(Boolean Values)

    • 描述:一个 boolean
    • 类类型:Boolean
    • 方法名:#define

注册配置(Registering a Configuration)

一旦构建完成 ForgeConfigSpec,就必须注册它,以便 Forge 按需加载、追踪和同步配置设置。配置应在模组构造函数中通过 ModLoadingContext#registerConfig 注册。注册配置时需要指定:一个表示配置所属逻辑端(side)的类型、ForgeConfigSpec,以及可选的配置专用文件名。

// 在模组构造函数中,CONFIG 为已构建好的 ForgeConfigSpec 实例
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, CONFIG);

以下是可用的配置类型列表:

类型(Type) 加载位置 同步到客户端 客户端位置 服务器位置 默认文件后缀
CLIENT 仅客户端 .minecraft/config N/A -client
COMMON 双端 .minecraft/config <server_folder>/config -common
SERVER 仅服务端 .minecraft/saves/<level_name>/serverconfig <server_folder>/world/serverconfig -server

Tip

Forge 在其代码库中记录了配置类型

配置事件(Configuration Events)

每当配置被加载或重新加载时发生的操作,可以通过 ModConfigEvent$LoadingModConfigEvent$Reloading 事件完成。这些事件必须注册到模组事件总线(mod event bus)上。

Warning

这些事件会针对该模组的所有配置被调用;应使用事件提供的 ModConfig 对象来判断当前正在加载或重新加载的是哪个配置。

待复核清单

  • 已按术语表校准:ForgeConfigSpecnet.minecraftforge.common.ForgeConfigSpec)+ ModLoadingContext.get().registerConfig(...) 注册,与 1.20.1 一致。
  • 原文代码示例用 FMLJavaModLoadingContextcontext.registerConfig(Type.COMMON, CONFIG);1.20.1 中 registerConfigModLoadingContext 的实例方法(FMLJavaModLoadingContext 继承自 ModLoadingContext),译文统一改为 ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, CONFIG),类型常量写全为 ModConfig.Type.COMMON
  • 包位置说明:ModLoadingContext 实际位于 net.minecraftforge.fml 包,net.minecraftforge.fml.config 包下的是 ModConfig(其 Type 枚举即 CLIENT/COMMON/SERVER);任务说明中「ModLoadingContext 在 net.minecraftforge.fml.config 下」与真实 API 略有出入,译文按真实包名处理,请主会话复核。
  • Builder#push/#pop 分区、#define 系列方法(define/defineInRange/defineInList/defineList/defineListAllowEmpty/defineEnum)、comment/translation/worldRestart 上下文,以及 ModConfigEvent$Loading/ModConfigEvent$Reloading(挂载模组事件总线)均与 1.20.1 API 一致,无需改动。
  • 配置类型表与 1.20.1 一致:CLIENT 仅客户端加载且不同步;COMMON 双端加载且不同步;SERVER 仅服务端加载并同步到客户端;默认文件后缀分别为 -client/-common/-server