可选 mod 集成
基本信息
| 属性 | 值 |
|---|---|
| 检测真源 | compat/Mods.java(枚举 Mods implements 6 个常量) |
| 检测方式 | Loader.isModLoaded(modid),结果一次性缓存 |
| 可选 mod 数 | 6 |
| 产生 HUD 行的 | 5(BACKHAND 不产生信息行) |
@Mod 声明的依赖 |
无 —— InfoHUD.java:13-18 没有 dependencies 字段 |
@Mod(
modid = InfoHUD.MODID,
version = Tags.VERSION,
name = InfoHUD.MODNAME,
acceptedMinecraftVersions = "[1.7.10]",
acceptableRemoteVersions = "*")
(InfoHUD.java:13-18)
⚠️ 本 mod 没有任何硬依赖声明——全部集成都是运行时可选的。 但实际上有两处「事实上的硬依赖」没被声明(见下方缺陷)。
6 个枚举与 modid
compat/Mods.java:9-17:
| 枚举 | 实际 modid | 产生的 HUD 行 | 触发条件 |
|---|---|---|---|
BLOOD_MAGIC |
AWWayofTime |
InfoBloodMagic(LP) |
Mods.BLOOD_MAGIC.isLoaded()(Hud.java:74) |
THAUMCRAFT |
Thaumcraft |
InfoThaumcraft(扭曲值) |
Mods.THAUMCRAFT.isLoaded()(Hud.java:78) |
GREGTECH |
gregtech_nh |
InfoOreChunk(矿脉区块) |
Mods.GREGTECH.isLoaded()(Hud.java:82) |
FORESTRY |
Forestry |
InfoForestry(气候) |
Mods.FORESTRY.isLoaded()(Hud.java:86) |
NUTRIENT |
nutrition |
InfoNutrient(营养) |
Mods.NUTRIENT.isLoaded()(Hud.java:90) |
BACKHAND |
backhand |
无信息行(只影响护甲条) | 见下 |
⚠️ modid 陷阱
| 枚举 | 用的是 | 常见误用 | 说明 |
|---|---|---|---|
GREGTECH |
gregtech_nh |
❌ gregtech |
运行时 modid 带 _nh 后缀。wiki 分类名是 gregtech,但 modid 不是 |
BLOOD_MAGIC |
AWWayofTime |
❌ BloodMagic / bloodmagic |
1.7.10 fork 的 modid。首字母大写 + AW 前缀 |
THAUMCRAFT |
Thaumcraft |
❌ thaumcraft |
首字母大写 |
FORESTRY |
Forestry |
❌ forestry |
首字母大写 |
NUTRIENT |
nutrition |
— | 全小写 |
BACKHAND |
backhand |
— | 全小写 |
这 6 个字符串同时也是
HudConfig.hudItems里 3 个默认图标 ID 的域前缀 (AWWayofTime:weakBloodOrb、Thaumcraft:ItemEldritchObject、Forestry:beeDroneGE), 大小写与上表完全一致——改图标时别写成小写域。
isLoaded() 的缓存语义
public boolean isLoaded() {
if (loaded == null) {
if (supplier != null) {
loaded = supplier.get();
} else if (modid != null) {
loaded = Loader.isModLoaded(modid);
} else loaded = false;
}
return loaded;
}
(Mods.java:33-42)
首次调用即定型,永不失效(loaded 是 Boolean 字段,Mods.java:21)。
这在 mod 加载期是安全的。
⚠️ 源码缺陷(死代码):
Mods有一个Mods(Supplier<Boolean> supplier)构造器(Mods.java:28-31), 用于「modid 测不出时自定义判定」。但全部 6 个枚举都用了 String 构造器 (grep 确认Mods(...)在Mods.java之外零调用), 因此supplier恒为null,isLoaded()的supplier分支永不执行。
逐项细节
BLOOD_MAGIC(AWWayofTime)→ LP 行
InfoBloodMagic.java:16-24:
return tr("info_blood_magic", getCurrentLP(), getMaxLP());
...
return String.format("%,d", HudUtils.getPlayerLPTag(getPlayer()));
直接读玩家 NBT 的 LP 标签(HudUtils.getPlayerLPTag),
不经 Blood Magic API——这是本 mod 对它的全部耦合点。
另注册 BloodMagicEvent 到 MinecraftForge.EVENT_BUS
(Hud.java:49-51,同样以 Mods.BLOOD_MAGIC.isLoaded() 为条件)。
图标默认 AWWayofTime:weakBloodOrb。
THAUMCRAFT(Thaumcraft)→ 扭曲值行
InfoThaumcraft.java:19-24 显示 4 个值:
getWarpTotal / getWarpPerm / getWarpSticky / getWarpTemp。
HudUtils.getWarpTotal(HudUtils.java:60-63):
return Thaumcraft.proxy.getPlayerKnowledge()
.getWarpTotal(player.getCommandSenderName()) + getWarpFromGear(player);
getWarpFromGear(HudUtils.java:65-79)扫描手持 + 4 件护甲 + 4 个饰品槽:
int w = EventHandlerRunic.getFinalWarp(player.getCurrentEquippedItem(), player);
for (int a = 0; a < 4; ++a) {
w += EventHandlerRunic.getFinalWarp(player.inventory.armorItemInSlot(a), player);
}
IInventory baubles = BaublesApi.getBaubles(player);
for (int a = 0; a < 4; ++a) {
w += EventHandlerRunic.getFinalWarp(baubles.getStackInSlot(a), player);
}
⚠️ 缺陷:Baubles 无守卫的隐藏硬依赖
| 项 | 内容 |
|---|---|
| 位置 | hud/HudUtils.java:72(BaublesApi.getBaubles(player)) |
| 问题 | 没有 Loader.isModLoaded(...) 守卫,也不在 Mods 枚举里,更不在 @Mod(dependencies) |
| 触发条件 | 装了 Thaumcraft 但没装 Baubles(Expanded) 时,渲染 Warp 行会走到 getWarpFromGear → BaublesApi 类不存在 |
| 后果 | NoClassDefFoundError(类缺失)或 baubles == null 时的 NPE,在 HUD 渲染路径上抛异常 |
| 编译依赖 | compileOnly('com.github.GTNewHorizons:Baubles-Expanded:2.2.11-GTNH:dev')(dependencies.gradle)——compileOnly 意味着运行时可选,与实际用法矛盾 |
实际门控是 Thaumcraft 而不是 Baubles(Hud.java:78),
因此「Thaumcraft ✓ + Baubles ✗」是唯一会出问题的组合。
GREGTECH(gregtech_nh)→ 矿脉区块行
InfoOreChunk.java:
return tr("info_orechunk");
...
return HudConfig.hudEnabled.OreChunkEnable && isOreChunk();
(InfoOreChunk.java:17、30)
只在「当前区块是矿脉区块」时显示,否则整行消失。
图标默认 minecraft:iron_ore(不指向任何 GT 物品)。
FORESTRY(Forestry)→ 气候行
InfoForestry.java:20-27:
return AlleleManager.climateHelper.toDisplay(temperature) + ": " + ...
直接调用 Forestry 的 AlleleManager——文本与语言包由 Forestry 提供,
本 mod 不翻译。图标默认 Forestry:beeDroneGE。
NUTRIENT(nutrition)→ 营养行
InfoNutrient.java:23-43 用 StringBuilder 自行拼装,
并有 switch (nutrientName.toLowerCase())(InfoNutrient.java:58)做营养素名映射。
不用 lang 键。图标默认 minecraft:milk_bucket。
BACKHAND(backhand)→ 不产生信息行
只影响护甲条的物品来源,共 2 处:
| 位置 | 行 | 行为 |
|---|---|---|
mixins/early/GuiIngameMixin.java:244 |
244 |
if (Mods.BACKHAND.isLoaded() && BackhandHandler.getBackHandItemStack(mc.thePlayer) != null) —— 从副手取护甲值 |
hud/core/BackhandHandler.java:13 |
13 |
if (!Mods.BACKHAND.isLoaded()) return null; —— 守卫 |
未使用的编译依赖
dependencies.gradle 声明了 10 个 compileOnly / runtimeOnly,但:
| 依赖 | 源码引用数 | 状态 |
|---|---|---|
OverloadedArmorBar:1.1.1 |
1(ArmorBarRenderMixin) |
⚠️ 见 Mixin 与网络 的严重缺陷 |
Baubles-Expanded |
1(HudUtils.java) |
⚠️ 无守卫,见上 |
BloodMagic / Thaumcraft / Backhand / ForestryMC / GT5-Unofficial / Nutrition |
均有引用 | 正常 |
AppleCore:3.3.11-GTNH |
0 | ❌ 完全未使用,且不在 Mods 枚举里 |
GTNHLib:0.9.53 |
implementation(非 compileOnly) |
配置框架,运行时必需 |