变体系统
Variable Horizons 的全部功能都建立在一套可开关的「变体」(Variant)枚举上。mod 本身不添加任何方块、物品、实体、维度、附魔或成就——它做的是按开关改写世界生成、配方、维度与难度规则。
注册真源
com.LazyFlesh.variablehorizons.variants.VariantNames 是一个 21 项的枚举,是所有变体的唯一注册真源。配置、GUI、命令、mixin 全部读同一个枚举。
| 分类 | 数量 | 判定方式 |
|---|---|---|
组合变体(compositionVariant = true) |
4 | NORMAL、GARDEN_OF_GRIND、SKYBLOCK、DIMLOCKED |
| 子变体 / 修正项 | 17 | 其余全部 |
其中有 VariantLoader 实现类 |
12 | 见下表 |
| 仅靠 flag + mixin 生效(无实现类) | 9 | NO_RECIPE_ADDITIONS、VOID_WORLD、ALTERED_EFFICIENCY、CHEAP_MODE、EXPENSIVE_MODE、SUPERFLAT、MONOBLOCK、NORMAL、SKYBLOCK |
组合变体的判定来自构造器重载:
VariantNames(id, loaderClass, composedOf[], incompatible[])与VariantNames(id, true, composedOf[], incompatible[])都会把compositionVariant置为true。因此GARDEN_OF_GRIND与DIMLOCKED虽写作「4 参构造」,仍是组合变体而非子变体。
21 个变体
| 枚举名 | 对外 id | 实现类 | 分类 |
|---|---|---|---|
NO_RECIPE_ADDITIONS |
NO_RECIPE_ADDITIONS |
— | 子 |
VOID_WORLD |
VOID_WORLD |
— | 子 |
VOID_ISLAND |
VOID_ISLAND |
VoidIsland |
子 |
NO_ROCKET |
NO_ROCKET |
NoRocket |
子 |
NO_QUEST_REWARDS |
NO_QUEST_REWARDS |
NoQuestRewards |
子 |
NO_POLLUTION |
NO_POLLUTION |
NoPollution |
子 |
ALTERED_RECIPE_TIME |
⚠️ ALTERED_TIME |
AlteredRecipeTime |
子 |
ALTERED_EFFICIENCY |
ALTERED_EFFICIENCY |
— | 子 |
CHANCED_RECIPES |
CHANCED_RECIPES |
ChancedRecipes |
子 |
CHEAP_MODE |
CHEAP_MODE |
— | 子 |
EXPENSIVE_MODE |
EXPENSIVE_MODE |
— | 子 |
INFINITE_POWER |
INFINITE_POWER |
InfinitePower |
子 |
CUSTOM_DIM_START |
CUSTOM_DIM_START |
DiffDimStart |
子 |
SUPERFLAT |
SUPERFLAT |
— | 子 |
SKYGRID |
SKYGRID |
SkyGrid |
子 |
MONOBLOCK |
MONOBLOCK |
— | 子 |
CRIMSON_APOCALYPSE |
CRIMSON_APOCALYPSE |
CrimsonApocalypse |
子 |
NORMAL |
NORMAL |
— | 组合(什么都不做) |
GARDEN_OF_GRIND |
GARDEN_OF_GRIND |
GardenOfGrind |
组合 |
SKYBLOCK |
SKYBLOCK |
— | 组合 |
DIMLOCKED |
DIMLOCKED |
DimLocked |
组合 |
⚠️
ALTERED_RECIPE_TIME的枚举名与对外 idALTERED_TIME不一致。玩家实际使用的字符串是ALTERED_TIME(本地化键variants.ALTERED_TIME.name),见 源码缺陷。
组合与冲突
每个变体持有 3 个集合:composedOf(由哪些子变体组成)、partOf(自己属于哪些组合变体,反向填充)、incompatible(互斥集)。构造时用 addIncompatibility() 双向写入,因此互斥关系是对称的;组合变体还会继承其所有子变体的互斥项。
判定入口:
activeContains(String... ids)—— 直接命中activeVariants集合,或命中某个子变体的partOfcheckIncompatibility(a, b)—— 除双向incompatible外,还会展开双方的composedOf做交叉检查
加载时机
CommonProxy.serverStarted 中依次调用 CrimsonApocalypse.applyDifficultyToServer()、AlteredRecipeTime.applyToServer()、ChancedRecipes.applyToServer()。大部分 mixin 是 Phase.EARLY,需要重启游戏才能生效——这也是 mod 名里 “Horizons”(换天)的含义。