Aspect Recipe Index

[!INFO] Git Commit: 4010c2e | Updated: 2026-09-08

Aspect Recipe Index(modid aspectrecipeindex)是 Thaumcraft 4 的一个纯客户端 NEI 增强模组。它把 Thaumcraft 的元素(Aspect)、研究进度与各类炼金配方接入 Not Enough Items,让玩家可以在 NEI 里用"元素"当搜索词,查询和浏览配方。

代码基础是 Time_Conqueror 的 TCNEIAdditions,GTNH 团队在 2020–2025 年间重写维护。mcmod.info 里的自述是 “New and improved compatibility for Thaumcraft in NEI.”

核心结论

问题 答案
它注册了什么方块 没有任何方块
它注册了什么实体 / TileEntity 没有
它注册了几个物品 1 个(aspectrecipeindex:aspect)
它有自己的网络包吗 没有,只复用 Thaumcraft 的 PacketAspectPool
它有热键吗 没有
它有指令吗 没有
它是 core mod 吗 不是(coreModClass 为空)
有多少个 NEI recipe handler 7 个(含 1 个继承自有序版的无序版)
有多少个 LATE mixin 2 个(全部客户端、全部打向 Thaumcraft)

元素配方索引机制

它没有维护任何长期存活的"配方索引表"。 尽管模组叫这个名字,实际机制是惰性查询 + 线性扫描 + 36 格链表分页:

  • 数据源是玩家自己的扫描记录(Thaumcraft.proxy.getScannedObjects()),不是全局表,所以结果按玩家不同,服务端无法预生成。
  • "某元素 → 含该元素的物品"每次查询都把扫描记录里的 hash 逐条 GuiResearchRecipe.getFromCache 反查成 ItemStack,叠加 object tags 与 bonus tags,再按含量降序排列。
  • 36 个物品一页,用 next 字段串成链表惰性创建下一页。
  • 其余 6 个 handler 更直接:每次都把 ThaumcraftApi.getCraftingRecipes() 全量扫一遍,靠 Util.getEssentiaFromItem 的结果做元素交集匹配。
  • 元素物品的"命中判定"发生在 CachedThaumRecipe.contains / containsWithNBT 的特判分支里,查的是内存中的 AspectList。

完整数据流、分页、进度与刷新策略见 元素配方索引机制。

加载与事件钩子

本模组不订阅任何 Forge 事件(MinecraftForge.EVENT_BUS、@SubscribeEvent、@Mod.EventBusSubscriber 全仓 grep 均无结果)。它只有 4 类钩子:

钩子 类型 触发时机
onMissingMappings(FMLMissingMappingsEvent) @Mod.EventHandler(static) 映射修复期;忽略 thaumcraftneiplugin:Aspect 物品映射
NEIConfig.loadConfig() NEI IConfigureNEI NEI 客户端加载配置时;注册 7 recipe + 7 usage + 4 GUI overlay + 4 overlay handler + 1 stringify handler
IMCForNEI.IMCSender() FML IMC FMLInitializationEvent(客户端);向 NEI 发 7 条 registerHandlerInfo + 8 条 registerCatalystInfo
2 个 LATE mixin UniMixins / GTNHLib Mixins Thaumcraft MappingThread.run() 与 ClientTickEventsFML.renderAspectsInGui

FML 生命周期:construct 为空 → preInit 注册物品 → init(客户端)发 IMC、注册渲染器与配置 → postInit 空。

Mixin 与 AT

gradle.properties 中 usesMixins = true、accessTransformersFile = aspectrecipeindex_at.cfg、coreModClass 为空。AT 只提升 net.minecraft.client.gui.inventory.GuiContainer 的 4 个 protected 字段为 public(SRG 原文 field_146999_f = xSize、field_147000_g = ySize、field_147003_i = guiLeft、field_147009_r = guiTop),供 mixin 做鼠标区域排除。

详见 Mixin 与 LATE 注入 与 Access Transformer。

配置项

配置框架是 GTNHLib 的 @Config(modid = "aspectrecipeindex"),共 5 个全部为布尔的选项,且只在客户端注册(注册调用写在 ClientProxy 里,ServerProxy 不注册)。

选项 类型 默认值 门控什么
showLockedRecipes boolean false 研究未完成的配方是否照常显示
showInstabilityNumber boolean true 注入不稳定性用数字还是分级文字
showResearchKey boolean true 研究控件绘制与 tooltip 悬停
showUndiscoveredAspectNames boolean false 未发现元素的名称与描述
showUndiscoveredAspectRecipes boolean false 未发现元素的组合 / 包含物品

另有 8 个 ColorResource 颜色常量(硬编码默认值 + 资源包 lang 覆盖,不在配置文件里)。详见 配置项 与 颜色常量。

兼容性门控

模组 强度 门控的代码路径
Thaumcraft required-after 全部功能(且大量使用其内部 API)
GTNHLib required-after @Config 配置框架、ColorResource
gtnhmixins required-after LATE mixin 加载
TC4Tweaks / TC4RecipeLib / InfusionRecipeLib required-after(三者之一) 注入配方的 EnhancedInfusionRecipe 转换
NotEnoughItems 编译期 api + IMC 目标 全部 7 个 handler 与 GUI 覆盖
Automagy after Loader.isModLoaded("Automagy") + 研究分类为 AUTOMAGY 时,tooltip 追加"击杀并扫描"要求
GTNH-TC-Wands 编译期 compileOnly Loader.isModLoaded("gtnhtcwands") 切换魔杖配方生成路径(wrapper API ↔ 杖柄×杖帽笛卡尔积)
Baubles-Expanded 仅 runtimeOnlyNonPublishable 不参与任何门控,只是 runClient 依赖
TCNEIPlugin / TCNEIAdditions 冲突但可共存 会导致配方重复,README 建议移除

Loader.isModLoaded 门控之外还有一处降级:API.registerStackStringifyHandler 被 try / catch (NoSuchMethodError ignored) 包住,NEI 缺该 API 时静默跳过。

详见 兼容性。

NEI 集成总览

7 个 recipe handler,同时全部注册为 usage handler:

Overlay 标识 展示内容
thaumcraft.items_containing_aspect 含指定元素的已扫描物品(36 格分页)
thaumcraft.aspects 元素组合关系(父元素 / Primal)
thaumcraft.alchemy 坩埚与神秘机器的炼金配方
thaumcraft.infusion 奥法注入配方 + 不稳定性 + Runic 护甲强化
thaumcraft.arcane.shaped 有序奥法合成
thaumcraft.arcane.shapeless 无序奥法合成
thaumcraft.wands 魔杖与法杖合成

外加奥法工作台的 NEI 自动摆放覆盖(含 vis 不足时自动换杖),以及元素物品的 NBT 序列化扩展。逐条见下列条目。

物品列表

  • Aspect 物品 - aspectrecipeindex:aspect,NBT 存元素 tag,metadata 0/1/2+ 控制图标可见性

物品效果

  • Aspect 研究点 - 右键消耗元素物品,+1 aspect pool 即 +1 研究点,服务端到客户端单播

游戏设定

NEI 处理器

本 mod 没有的内容(附 grep 证据)

以下维度在源码中确认不存在,因此没有创建对应目录。

没有方块、多方块、TileEntity

$ grep -rn "registerBlock\|EntityRegistry\|registerTileEntity\|registerEntity" src/main/java
(无输出)
$ grep -rn "class Block\b\|TileEntity\|Multiblock" src/main/java
(无输出)

没有实体

$ grep -rln "EntityLiving\|IWorldGenerator" src/main/java
(无输出)

ItemAspect.onItemRightClick 里出现的 EntityPlayer / EntityPlayerMP / FakePlayer 是判定接收者类型,不是本模组定义的实体。

没有热键

$ grep -rn "new KeyBinding" src/main/java
(无输出)
$ grep -rn "KeyBinding" src/main/java
(无输出)

连 import 都没有。模组的全部交互都在 NEI 界面内完成。

没有指令

$ grep -rn "ICommand\|CommandHandler\|CommandBase\|registerCommand" src/main/java
(无输出)

没有 addChatCommand,也没有任何权限节点。

没有网络包

$ grep -rn "SimpleNetworkWrapper\|NetworkRegistry\|IMessage\|IMessageHandler\|sendToServer" src/main/java
(无输出)
$ grep -rn "sendTo(" src/main/java
./com/gtnewhorizons/aspectrecipeindex/common/items/ItemAspect.java:58:                PacketHandler.INSTANCE.sendTo(

唯一的发包点是复用 Thaumcraft 的 PacketAspectPool,不是自建通道。

没有 Forge 事件订阅

$ grep -rn "@SubscribeEvent\|@Mod.EventBusSubscriber\|MinecraftForge.EVENT_BUS" src/main/java
(无输出)

没有附魔、药水效果、群系、维度、结构、成就

$ for kw in Enchantment Potion BiomeGen WorldProvider DimensionManager WorldGenerator IWorldGenerator ChestGenOre Achievement; do ... done
每一个都是 NONE

不是 core mod

gradle.properties 中 coreModClass =(空值),仓库内没有实现 IFMLLoadingPlugin 的类。

只注册了 1 个物品,没有方块物品 / 机器 / Tile

$ grep -rn "GameRegistry.register" src/main/java
./com/gtnewhorizons/aspectrecipeindex/ModItems.java:15:        GameRegistry.registerItem(itemAspect, "aspect");

ModItems 类里只有 itemAspect 一个字段。

相关条目