配置框架
基本信息
| 属性 | 值 |
|---|---|
| 根文件 | config/salisarcana.cfg |
| 分组文件目录 | config/salisarcana/ |
| 分组数 | 7 |
| 设置总数 | 204 |
| 根源文件 | config/SalisConfig.java(90 行) |
| 组基类 | config/ConfigGroup.java |
| 设置基类 | config/settings/Setting.java |
功能
Salis Arcana 的配置系统是它唯一的主体内容——本模组自己只注册 1 个方块、2 个物品与 4 条研究,其余全部是对 Thaumcraft 4 的行为改写。理解这套框架是理解本模组的前提。
配置分两层:
config/salisarcana.cfg是根配置,只放两个东西:一个全局开关enableversionChecking,以及modules分类下 7 个「整组开关」 (键名形如Enable enhancements group)。config/salisarcana/<分组名>.cfg是分组配置,每组一个文件,真正的 204 项设置都在这里。
分组被关闭时,其配置文件根本不会被读取——SalisConfig.synchronizeConfiguration()
在 SalisConfig.java:50-52 处直接 continue,既不加载也不写出该文件。因此一个被整组
关闭的分组,其 .cfg 会在下次启动时被保留原样而不会同步。
分组注册机制
分组不是通过枚举或循环注册的,而是靠构造函数自注册:
public ConfigGroup() {
SalisConfig.groups.add(this);
}
——ConfigGroup.java:23-25。
七个分组则在 SalisConfig 中以 static final 字段实例化(SalisConfig.java:25-31)。
Java 的类初始化保证了这些字段在任何 Setting 被访问前就已构造完毕,因此
groups 列表在使用时必定已经填满 7 项。
| Java 字段 | 分组类 | 分组名(= 文件名) | 设置数 | 根配置中的整组开关键 |
|---|---|---|---|---|
addons |
ConfigAddons |
addons |
1 | Enable addons group |
bugfixes |
ConfigBugfixes |
bugfixes |
79 | Enable bugfixes group |
commands |
ConfigCommands |
commands |
10 | Enable commands group |
features |
ConfigFeatures |
enhancements |
75 | Enable enhancements group |
modCompat |
ConfigModCompat |
mod_integrations |
6 | Enable mod_integrations group |
thaum |
ConfigThaumcraft |
thaumcraft_configuration |
32 | Enable thaumcraft_configuration group |
debug |
ConfigDebug |
debug |
1 | Enable debug group |
⚠️ 分组名与类名系统性不一致:ConfigFeatures → enhancements、
ConfigModCompat → mod_integrations、ConfigThaumcraft → thaumcraft_configuration。
文件名取自 ConfigGroup.getGroupName()(SalisConfig.java:68),不是类名。找配置文件时
必须用分组名。
设置类型体系
所有设置继承自 Setting,按取值方式分出若干子类:
| 类型 | 源文件 | 写入的 Forge 键类型 | 说明 |
|---|---|---|---|
ToggleSetting |
config/settings/ToggleSetting.java |
getBoolean |
布尔开关,最常用 |
IntSetting |
config/settings/IntSetting.java |
getInt |
整数,可带上下限 |
FloatSetting |
config/settings/FloatSetting.java |
getFloat |
浮点数 |
StringSetting |
config/settings/StringSetting.java |
getString |
字符串 |
StringArraySetting |
config/settings/StringArraySetting.java |
getStringList |
字符串列表 |
IntArraySetting |
config/settings/IntArraySetting.java |
getIntList |
整数列表,可固定长度 |
EnumSetting<E> |
config/settings/EnumSetting.java |
getString + 校验 |
枚举,可指定「禁用值」 |
CustomResearchSetting |
config/settings/CustomResearchSetting.java |
多个键 | 自定义研究,详见 自定义研究 |
ReplaceWandComponentSettings |
config/settings/ReplaceWandComponentSettings.java |
多个键 | 上一行的子类,键名加 Research 后缀 |
BeaconBlockFixSetting |
config/settings/BeaconBlockFixSetting.java |
getIntList |
额外维护一个 16 位布尔表 |
CommandSettings |
config/settings/CommandSettings.java |
多个键 | 命令,详见 命令 |
BaseCompatSetting |
config/settings/compat/BaseCompatSetting.java |
多个键 | 兼容块,可挂子设置 |
IntSetting 与 FloatSetting 的上下限通过链式 .setMinValue(...) / .setMaxValue(...)
声明,写入 .cfg 时由 Forge 强制约束——读入越界值会被夹回边界。
依赖(IEnabler)机制
每项设置的第一个构造参数都是它的依赖。Setting.isEnabled() 的语义是
「自身为真 且 依赖为真」。因此存在两层开关:
- 整组开关(根配置)→ 分组
isEnabled() - 父设置 → 子设置
典型例子是 salisarcana.enhancements.cfg 里的
_enabledreplaceWandCapsResearch:它的父依赖是 replaceWandCapsSettings,
所以即使显式写入 true,只要父设置被关掉,它仍然不生效。
Setting.setCategory(...) 决定键在 .cfg 中落入哪个分类。绝大多数设置用
general,但复合设置会重设分类——例如 BaseCompatSetting 在
BaseCompatSetting.java:27 把子设置的分类强制改写成所属 modid,
这是 mod_integrations.cfg 里能看到 angelica、gtnhtcwands 等分类的原因。
关闭的设置不写入文件
凡调用了 .setEnabled(false) 的设置,其默认值即为关闭。这类设置在 .cfg 中
不会出现对应条目(getBoolean 只在值与默认不同时才落盘)。全仓共 17 项如此:
| 分组 | 数量 | 键(注意:部分键名与 Java 字段名不同) |
|---|---|---|
| 缺陷修复组 | 2 | unOredictGoldCoin、wardingDontStoreNBTMeta |
| 调试组 | 1 | logWarpSources |
| 功能增强组 | 8 | nodeModifierWeights、nodeTypeWeights、Inverse Scrolling、Save Thaumonomicon Page、researchDuplicationFree、useStabilizerRewrite、mobVisDropWhitelist、bannerFreePatterns |
| 神秘时代配置组 | 6 | hungryDynamicReach、pureDynamicReach、sinisterDynamicReach、taintedDynamicReach、_uncapped_potion_ids、disableAspectTint |
键名取自构造函数的第 2 个参数,不是
public final的字段名。差异示例: 字段nomiconInvertedScrolling的配置键是Inverse Scrolling, 字段stabilizerRewrite的配置键是useStabilizerRewrite, 字段mobVisWhitelist的配置键是mobVisDropWhitelist, 字段potionIdLimitRaised的配置键是_uncapped_potion_ids。
数值
全部 204 项设置由程序化解析 config/group/*.java 中 7 个文件的
public final ... = new ...Setting( 声明得到,并用两种独立表述交叉校验:
- 表述 A:正则匹配
= new [A-Za-z]+(Setting|Settings)\(→ 1+79+10+1+75+6+32 = 204 - 表述 B:Python 解析构造调用并做括号配平 → 204
两种表述结果一致。第三种表述(^ public final [A-Za-z]+ [a-zA-Z]+ = new )得出 203,
差额已定位:该正则的 [a-zA-Z]+ 不接受数字,漏掉了字段名含数字的
tc4tweakScrollPages(ConfigModCompat.java:22)。这是校验脚本的缺陷,不是内容缺陷。
「外部读取者」检查:204 项设置中有 203 项能在 config/group/ 以外的源码里找到引用。
唯一「查无读者」的 allowSingleWandReplacement(ConfigFeatures.java:60)经人工复核
并非死代码:它在本类内被 singleWandReplacementEnabled()(ConfigFeatures.java:497)
读取,而该方法作为 setApplyIf 条件被 Mixins.java:537 使用,属同包引用导致的
初筛误报。
交互
配置文件不在 preInit 阶段加载,而是在核心模组的构造函数中加载:
SalisArcanaCore() 直接调用 SalisConfig.synchronizeConfiguration()
(SalisArcanaCore.java:25-27)。这早于任何模组的 preInit,
正是补丁条件能在 Mixins 枚举求值时被安全查询的前提。
根配置路径由 SalisConfig.java:36-37 拼出(config + modid + .cfg),
分组配置路径由 SalisConfig.java:68 拼出(config + modid + 目录 + 分组名 + .cfg)。