第三方模组集成

基本信息

属性 值
宿主 mod Thaumcraft 4
宿主证据(@Mod) dependencies = "required-after:Forge@[10.13.2,);" + "required-after:Thaumcraft@[4.2.3.4,)"(common/ThaumicHorizons.java:271)
宿主证据(构建脚本) api('thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev')(dependencies.gradle)
宿主证据(mcmod.info) "dependencies": ["Thaumcraft","Baubles"](src/main/resources/mcmod.info)
宿主结论 Thaumcraft 4 是硬依赖,且是唯一的前置 mod。本模组未通过名称推断宿主,而是从 @Mod 依赖串与 dependencies.gradle 两处独立读出,两者一致

硬依赖

依赖 声明位置 说明
Minecraft Forge @Mod 依赖串 required-after:Forge@[10.13.2,)(common/ThaumicHorizons.java:271) 下限 10.13.2;gradle.properties 的 forgeVersion = 10.13.4.1614 为构建目标版本
Thaumcraft @Mod 依赖串 required-after:Thaumcraft@[4.2.3.4,)(common/ThaumicHorizons.java:271) 下限 4.2.3.4(注意:dependencies.gradle 锁定的编译版本是 4.2.3.5,比声明下限高一档)
Baubles-Expanded api('com.github.GTNewHorizons:Baubles-Expanded:2.2.24-GTNH:dev')(dependencies.gradle)+ mcmod.info 的 "Baubles" 源码层面无任何 isModLoaded 守卫,见下

Baubles 是事实上的硬依赖

尽管 @Mod(dependencies=…) 字符串里只写了 Forge 与 Thaumcraft、没有写 Baubles,但源码对 Baubles API 有无守卫的直接类引用:

引用点 导入的 Baubles 类型
common/items/ItemAmuletMirror.java:28-29 baubles.api.BaubleType、baubles.api.IBauble
common/items/lenses/ItemLensCase.java:23-24 baubles.api.BaubleType、baubles.api.IBauble
common/items/lenses/LensManager.java:22 baubles.api.BaublesApi
common/entities/EntityLunarWolf.java:15 baubles.api.BaublesApi
common/entities/EntityFamiliar.java:16 baubles.api.BaublesApi
client/lib/RenderEventHandler.java:45 baubles.api.BaublesApi(:136 以 BaublesApi.getBaubles(mc.thePlayer) 取饰品栏)
common/lib/EventHandlerEntity.java:70-71 baubles.common.container.InventoryBaubles、baubles.common.lib.PlayerHandler
common/lib/networking/PacketNoMoreItems.java:10 baubles.common.lib.PlayerHandler

共 8 个文件、11 条 import baubles.*(复核命令 grep -rn "^import baubles" src/main/java/)。

ItemAmuletMirror extends Item implements IBauble, IRunicArmor(common/items/ItemAmuletMirror.java:36)与 ItemLensCase extends Item implements IBauble(common/items/lenses/ItemLensCase.java:28)在类声明上直接实现 IBauble,且两者都在 preInit 中被无条件实例化(common/ThaumicHorizons.java:566、:554)。若 Baubles 缺失,这两个类的加载会在类解析阶段失败。因此 Baubles 属于运行时硬依赖,只是未写进 @Mod 依赖串——mcmod.info 与 Gradle api 声明补上了这一层。

模组未使用任何 @Optional.Interface 或 @Optional.Method 注解(全仓 0 命中),这 11 处引用均无注解级降级。

软依赖(可选且有完整回退)

GregTech 5

项 值
Gradle 声明 compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.168:dev') {transitive = false}(dependencies.gradle) —— compileOnly,不随 jar 发布
运行时门控 if (Loader.isModLoaded("gregtech") && !Loader.isModLoaded("gregapi"))(common/ThaumicHorizons.java:2076)
门控范围 2076–2163(if 分支 2077–2129,else 分支 2130–2162,闭合花括号在 :2163)
GT 类引用位置 common/ThaumicHorizons.java:2085-:2129,共 20 处 GTOreDictUnificator.get(...)
使用的 GT5 类型 Materials(Glass / InfusedOrder / Void / Titanium / Enderium / InfusedGold)、OrePrefixes(gemExquisite / lens / plateDense / screw)、GTOreDictUnificator(导入见 :243-:245)
其他文件的 GT 引用 0 —— grep -rl "gregtech" src/main/java/ 仅命中 ThaumicHorizons.java 一个文件

这条集成写得非常干净:所有 GT 类引用全部落在门控内部,且 else 分支提供了完整的原版回退配方(:2130-2162),把基座插槽 / 平面基石的注入材料从 GT 的高级材料换成原版石英、钻石、金锭与 TC4 资源。因此不装 GT5 也能完整游玩。

需要注意的是门控条件本身:它要求 isModLoaded("gregtech") 且 !isModLoaded("gregapi"),即仅在纯 GT5(无旧版 GregAPI) 环境下才启用 GT 材料配方。

门控块外(:2164-2165)的两行 ThaumcraftApi.addWarpToResearch("pocketPlane", 4) 与 ("planarKeystone", 5) 无条件执行,因此传送点在有无 GT5 时都注册。

门控带来的耦合:planarKeystone 研究本身在 if (enablePocket) 块内无条件注册(:2208),但其页面引用的注入配方在无 GT5 时来自 else 分支。若 enablePocket=true 而 GT5 未安装,配方仍会被 else 分支正常注册,不会出现空配方——回退设计覆盖了这一情形。

仅构建期 / 声明级依赖

依赖 Gradle 配置 源码引用
AspectRecipeIndex runtimeOnlyNonPublishable('com.github.GTNewHorizons:AspectRecipeIndex:1.1.5:dev')(dependencies.gradle) 0 处 —— grep -rn "aspectrecipeindex|AspectRecipeIndex" 全仓 0 命中

AspectRecipeIndex 在本模组中没有任何源码调用,仅作为 GTNH 约定插件要求的运行时依赖存在,用于让 NEI 等工具能索引模组注册的要素配方。因此它不是代码层面的集成,仅是构建约定。

未集成的常见附属

以下 GTNH 常见的附属 mod 在本仓中无任何证据支持集成,不应臆测其存在:

  • WAILA / Jade:无任何 Waila / Jade / Hwyla 字符串命中
  • Not Enough Items (NEI):无源码引用(NEI 通过元数据而非 API 集成,故不出现也属正常)
  • Thaumic Energistics / Botania / Blood Magic:无任何引用

全仓唯一的 Loader.isModLoaded 调用就是 common/ThaumicHorizons.java:2076 这一处(用于 GregTech 门控)。

身份字符串的大小写分歧

本模组的 modid、资源域与网络通道名三者大小写不一致,均已从源码独立确认:

字符串 实际值 证据
modid ThaumicHorizons(首字母大写) common/ThaumicHorizons.java:275 的 public static final String MODID = "ThaumicHorizons";gradle.properties 的 modId = ThaumicHorizons
资源域 thaumichorizons(全小写) 目录 src/main/resources/assets/thaumichorizons/;gradle.properties 的 modGroup = com.kentington.thaumichorizons
网络通道名 thaumichorizons(全小写) common/lib/networking/PacketHandler.java:60 的 "ThaumicHorizons".toLowerCase()
创造标签字符串 thaumichorizons(全小写) common/ThaumicHorizons.java:4073
方块注册名前缀 ThaumicHorizons:(首字母大写) 23 个方块类的 setBlockTextureName("ThaumicHorizons:…")
研究分类 key ThaumicHorizons(首字母大写) common/ThaumicHorizons.java:812
配置热重载 modID ThaumicHorizons(首字母大写) common/ThaumicHorizons.java:4066
jar 名 ThaumicHorizons.jar gradle.properties 未设置 customArchiveBaseName(该行是注释状态),故沿用默认的 modName

作者显然清楚这个分歧:网络通道名处显式写了 .toLowerCase() 做转换,说明这是有意为之而非疏漏。

相关条目

  • 配置 - onConfigChanged 使用大写 modID 比对
  • 网络封包 - 通道名的 .toLowerCase() 转换
  • 口袋世界 - pocket_plane_dim 与 GT5 门控的实际作用点