神秘时代集成(Thaumcraft)

基本信息

属性 值
判定 modid Thaumcraft(Wawla.java:65,大写 T)
条件 Loader.isModLoaded("Thaumcraft")
文件 src/main/java/net/darkhax/wawla/addons/thaumcraft/AddonThaumcraftTiles.java(241 行)
实现接口 IWailaDataProvider
配置分类 Thaumcraft(9 个键)
跨 mod 依赖 零编译期依赖——12 个 Class.forName
GTNH 状态 整合包含 Thaumcraft,此 addon 会加载

反射缓存的 12 个类

字段 目标类 static?
classTileJarFillable thaumcraft.common.tiles.TileJarFillable ❌ 实例字段
classTileJarFillableVoid thaumcraft.common.tiles.TileJarFillableVoid ❌ 实例
classTileMirror thaumcraft.common.tiles.TileMirror ❌ 实例
classTileMirrorEssentia thaumcraft.common.tiles.TileMirrorEssentia ❌ 实例
classTileJarBrain thaumcraft.common.tiles.TileJarBrain ❌ 实例
classTileWandPedestal thaumcraft.common.tiles.TileWandPedestal ❌ 实例
classTilePedestal thaumcraft.common.tiles.TilePedestal ❌ 实例
classTileDeconstructionTable thaumcraft.common.tiles.TileDeconstructionTable ❌ 实例
classBlockJar thaumcraft.common.blocks.BlockJar ✅ public static
classBlockMirror thaumcraft.common.blocks.BlockMirror ✅ public static
classBlockStoneDevice thaumcraft.common.blocks.BlockStoneDevice ✅ public static
classBlockTable thaumcraft.common.blocks.BlockTable ✅ public static

⚠️ 8 个 TileEntity 类是实例字段(public Class 非 static),4 个 Block 类是 static(:229-240)。全部在构造函数里赋值(:23-48)。这个混用能工作(registerAddon 先 new 再用),但同一批字段用两套生命周期,是明确的风格不一致。

注册的 4 个方块

registerAddon(:209-216)对 4 个 Block 类各注册 body + NBT:

Block 类 覆盖的 TileEntity
BlockJar 精华罐 / 虚空精华罐 / 脑缸
BlockMirror 魔镜 / 精华魔镜
BlockStoneDevice 基座 / 法杖基座
BlockTable 解构台

⚠️ 4 个 body provider 全部只注册了 Block,没有注册对应的 TileEntity 类。这符合 WAILA 1.7.10 的 API(注册粒度是 Block,handler 内部自行 compareTileEntityByClass)。

5 组 HUD 行

整体前置守卫:data.getBlock() != null && data.getTileEntity() != null(:67)。5 组之间是平行的 if,不是 else if。

1. 精华罐 / 虚空精华罐

compareTileEntityByClass(te, classTileJarFillable) || ...(te, classTileJarFillableVoid)

门控键 输出 数据 附加条件
wawla.thaumcraft.jarAspect 要素: <首字母大写> tag.getString("Aspect") !aspect.isEmpty()
wawla.thaumcraft.jarAmount 数量: <N> tag.getShort("Amount") amount > 0

⚠️ 两行的 if 条件里都硬编码了 true &&(:76 与 :80)——if (true && aspect != null && ...)。aspect 来自 getString,永不为 null(不存在的键返回空串),所以 aspect != null 判定也是死代码。这两个 true && 明显是调试时留下的残留。

2. 魔镜 / 精华魔镜

前置:... || ... 且 tag.getBoolean("linked")

门控键 输出 数据
wawla.thaumcraft.mirrorLink 链接: X:<x> Y:<y> Z:<z> tag.getInteger("linkX"/"linkY"/"linkZ")
wawla.thaumcraft.mirrorDim 维度: <维度名> DimensionManager.getProvider(tag.getInteger("linkDim")).getDimensionName()

⚠️ DimensionManager.getProvider(dimId) 无效 ID 会返回 null → .getDimensionName() NPE。linkDim 来自存档 NBT,跨维度传送或存档损坏时可能取到未注册的 ID。

3. 脑缸

wawla.thaumcraft.jarEXP 开启时输出 经验: <XP>,读 tag.getInteger("XP")。

⚠️ lang 键是 tooltip.wawla.thaumcraft.experience=经验,但 zh_CN 的选项文案是 是否显示缸中经验?(“缸”),而代码与 tooltip 键都用 “jar”(罐)。中英用词不一致。

4. 基座

wawla.thaumcraft.pedestalItem 开启时,用 Utilities.getInventoryStacks(tag, 1)[0] 取物品,非空则输出 物品: <名>。

⚠️ 必 NPE:getInventoryStacks 在 NBT 无 Items 键时返回 null,[0] 立即越界。空基座是常态。

5. 法杖基座(最复杂的一组)

⚠️ 外层也是 if (true)(:136)。

门控键 输出 附加条件
wawla.thaumcraft.wandItem 只有法杖名,没有"物品: "前缀 pedestalStack.hasTagCompound()
wawla.thaumcraft.wandCharge 6 种要素充能,用 | 分隔 额外要求 stackTagCompound.hasKey("aqua")

6 种要素的着色与换算:

顺序 要素 颜色 换算
1 aer(气) YELLOW /100f
2 terra(地) DARK_GREEN ⚠️ / 100(整除)
3 ignis(火) RED /100f
4 aqua(水) DARK_AQUA /100f
5 ordo(秩序) GRAY /100f
6 perditio(否定) DARK_GRAY /100f

⚠️ 缺陷:地元素充能因整除永远显示 0.0

AddonThaumcraftTiles.java:153:

+ (float) (pedestalStack.stackTagCompound.getInteger("terra") / 100)

其余 5 个都是 / 100f,唯独 terra 漏了 f 后缀。getInteger 返回 int,/ 100 是整型除法(结果 0),再转 float 恒为 0.0。

后果:任何法杖的地元素充能在 HUD 上永远显示 0.0,而其他 5 种正常。这是一处确定的 copy-paste 笔误(与 通用实体 里的 childDurationMultiplier 赋值错误同属一类)。

⚠️ 缺陷:整行用 (float) 强转会暴露 float 精度误差

getInteger("aer") / 100f 先做 int→float 的除法再强转回 float,例如 75 / 100f = 0.75f(可表示),但 1 / 100f = 0.01f(float 无法精确表示 0.01),HUD 上会显示 0.01 或 0.009999999。正确做法是保留 double。

⚠️ 缺陷:法杖名没有前缀

tip.add(pedestalStack.getDisplayName())(:142)——直接推物品名,没有 物品: 前缀,与基座那行(tooltip.wawla.item + ": ")风格不一致,玩家难以分辨这一行是什么。

⚠️ 其它缺陷

DimensionManager.getProvider 返回 null 未处理

见魔镜部分。

registerBodyProvider 收到 null 类的可能

:209-216 传 4 个 static Block 字段,Class.forName 失败时它们仍是 null(catch 只 printStackTrace,:45)。Thaumcraft 若换了包名(不同版本),这 4 次注册会全部传入 null。

upperCase 对空串不安全

:78 的 Utilities.upperCase(aspect) 有 !aspect.isEmpty() 守卫,安全;:117 由 hasKey("Aspect") 守卫——但 hasKey 为真时值仍可能是空串(写了空 Aspect),此时 Utilities.java:209 的 charAt(0) 会抛 StringIndexOutOfBoundsException。见 工具类 缺陷 5。

相关条目