源码缺陷清单

以下均为读源码实测得到的问题,附文件与行号。

1. 总开关 disableVariants 覆盖不全

GeneralConfig.disableVariants(Config/GeneralConfig.java:16)被描述为 “Disables all changes made by Variable Horizons”,且全部 19 个 MixinBuilder 的条件都检查了它。

但全仓 grep -rn "disableVariants" src/main --include=*.java 显示,除 Mixins.java 外没有任何其它文件引用它。这意味着 CommonProxy.serverStarted 中运行时施加的改动不受总开关保护:

  • CrimsonApocalypse.applyDifficultyToServer() —— 强制难度 HARD、屏蔽难度按钮
  • AlteredRecipeTime.applyToServer() —— 全局配方时间乘数
  • ChancedRecipes.applyToServer() —— GT 配方概率改写

以及 12 个 VariantLoader 本身的行为(NoPollution 改 PollutionConfig.pollution、InfinitePower 发配方、GardenOfGrind 改 GT 配置等)。

结论:把 disableVariants 设为 true 并不能完整关掉本 mod。

2. 枚举名与对外 id 不一致

VariantNames.java 中:

ALTERED_RECIPE_TIME("ALTERED_TIME", new AlteredRecipeTime()),

枚举常量名是 ALTERED_RECIPE_TIME,但对外 id 是 ALTERED_TIME。玩家、配置文件与本地化键(variants.ALTERED_TIME.name)用的都是后者。

这是全 21 个枚举中唯一 id 与常量名不符的项(其余 20 个均相同)。查 getVariantFromID("ALTERED_RECIPE_TIME") 会返回 null。

3. 文档与源码不符

README.md:8 声称:

“the player can do a simple /island create (requires permission level 1)”

但 IslandCommands.getRequiredPermissionLevel() 返回 0,即所有玩家都能用 /island create 自建岛屿。以源码为准。

en_US.lang 中没有该描述——问题只出在 README。

4. 跨模组方块无存在性检查

util/islands/skyIslands.java 的 7 套岛屿模板用 GameRegistry.findBlock(modid, name) 硬编码字符串取用 11 个其它 mod 的方块(共 71 处引用):HardcoreEnderExpansion(16)、Thaumcraft(14)、BiomesOPlenty(13)、GalacticraftCore(7)、Natura(6)、chisel(5)、thaumicbases(3)、etfuturum(3)、Ztones(2)、miscutils(1)、OpenBlocks(1)、EnderIO(1)。

该文件内 == null / != null 判定共 0 处。整合包若缺少其中任一 mod,岛屿生成会异常。

util/blockUtils/BlocksRegistry.java 内部确有 checkIfBlacklisted() 黑名单跳过与 3 处 null 判定,但那是 SKYGRID 的 tileentity 白/黑名单机制(配合 skygridTEWhitelist / skygridBlacklist 配置),不覆盖岛屿模板。

注:这是 mod 合法引用外部内容,不属于「跨 mod 物品混入」类幻觉。

5. 仅 en_US 语言

src/main/resources/assets/variablehorizons/lang/ 下只有 en_US.lang(161 行),无任何其它语言。中文玩家看到的变体名与描述会全部退化为键名。

6. @Mod 的 dependencies 与 build 依赖不一致

@Mod(..., dependencies = "after:dreamcraft")

声明了 after:dreamcraft,但 dependencies.gradle 中没有 DreamCraft 条目。after: 只是加载顺序软依赖,不要求 DreamCraft 存在,但 DreamCraft 未收录于本 wiki,且该 mod 大量直接引用 GregTech API(GTMod、GTRecipe、Worldgen、WirelessNetworkManager、Materials),实际只能在 GTNH 整合包内运行。

7. 维度 ID 魔法数字

位置 值 含义
ADD_SEMINING_RECIPE 条件 startingDimID != 100 排除维度 ID 100,但源码无注释说明 100 是哪个维度
REMOVE_ORECHID_IGNEM_DIMRESTRICTION 条件 startingDimID != -1 排除下界(-1)

8. 仅 GUI 可写的空转配置

ALTERED_EFFICIENCY、CHEAP_MODE、EXPENSIVE_MODE 三个枚举项没有 VariantLoader 实现类,且在 Mixins.java 的 19 个 builder 条件中均未出现。

配置项 GeneralConfig.efficiencyMultiplier 的全部引用只在两处:

Config/GeneralConfig.java:32                      (声明)
selectionUI/VariantGuiMain.java:84, 92, 400, 403 (读取 / 写回 / 变更检测 / 文本框绑定)

即只有选择 GUI 在读写它,没有任何 VariantLoader 或 mixin 消费这个值。在 GUI 里改它会触发 hasChanged() 但不会改变任何游戏行为——属于未完成功能。

NO_RECIPE_ADDITIONS 同样是纯标志位,但确实作为 incompatible / composedOf 成员参与组合判定,并非完全无用。

9. 选择 GUI 的存在

selectionUI/VariantGuiMain.java 是单/多人世界选择界面的变体切换 GUI(README 称 “Variants are easily configurable using the new gui in the singleplayer world selection screen”),是除 /variants 命令外的第二个切换入口,并额外提供 recipeTimeMultiplier、efficiencyMultiplier 与 4 个概率乘数的滑块/文本框(见 VariantGuiMain.java:400 一带)。

10. getActiveVariantsToCheck() 的排除列表

VariantNames.getActiveVariantsToCheck() 会移除 3 个变体:

activeVariantsToCheck.remove(VariantNames.CHANCED_RECIPES.id);
activeVariantsToCheck.remove(VariantNames.NO_POLLUTION.id);
activeVariantsToCheck.remove(VariantNames.CRIMSON_APOCALYPSE.id);

这 3 个是直接改 GT 配置而非走 mixin 条件,故不需要参与 mixin 判定。逻辑自洽,不算缺陷,但调用方需注意传入的是过滤后的集合。

相关条目