Files
thaumicenergistics-neo/路径.md
T
2026-08-19 00:17:24 +08:00

214 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ThaumicEnergistics 代码位置速查表
> 说明:本文件所有路径均相对于 `modules/thaumicenergistics-neo/src/main/`。
> 若文件路径以 `java/` 开头 → Java 源码;以 `resources/assets/` 开头 → 资源/JSON。
---
## 一、物品 / 方块 Java 注册
| 你想找什么 | 文件 | 关键行 | 备注 |
|---|---|---|---|
| 物品总注册器入口 | `java/thaumicenergistics/init/ModItems.java` | **12** | `DeferredRegister.Items REGISTRY` |
| 1k/4k/16k/64k 源质存储单元(带容量的 Cell) | `ModItems.java` | 14~18 | `ESSENTIA_CELL_1K ~ ESSENTIA_CELL_CREATIVE` |
| 1k/4k/16k/64k 存储组件(Storage Component) | `ModItems.java` | 19~22 | `STORAGE_COMPONENT_1K ~ 64K` |
| 聚变核心 / 扩散核心 | `ModItems.java` | 23~24 | `COALESCENCE_CORE` / `DIFFUSION_CORE` |
| 铁齿轮 / 知识核心 / AE扳手核心 | `ModItems.java` | 25~27 | `IRON_GEAR` / `KNOWLEDGE_CORE` / `FOCUS_AEWRENCH` |
| 无线源质终端 / 傀儡WiFi背包 | `ModItems.java` | 28~29 | `WIRELESS_ESSENTIA_TERMINAL` / `GOLEM_WIFI_BACKPACK` |
| 源质IO总线/存储总线/终端/LevelEmitter/Vis接口/共鸣器 | `ModItems.java` | 30~37 | `ESSENTIA_IMPORT_BUS` 等一整套 |
| 方块对应物品(BlockItem) | `ModItems.java` | 39~47 | `ESSENTIA_PROVIDER_ITEM`、`KNOWLEDGE_INSCRIBER_ITEM` 等,与 ModBlocks 一一对应 |
| 方块总注册器入口 | `java/thaumicenergistics/init/ModBlocks.java` | **17** | `DeferredRegister.Blocks REGISTRY` |
| 源质提供器 Essentia Provider | `ModBlocks.java` | 20 | `ESSENTIA_PROVIDER` |
| 注入提供器 Infusion Provider | `ModBlocks.java` | 21 | `INFUSION_PROVIDER` |
| 奥术组装机 Arcane Assembler | `ModBlocks.java` | 22 | `ARCANE_ASSEMBLER`(Tile: TileArcaneAssembler) |
| 源质振动室 Essentia Vibration Chamber | `ModBlocks.java` | 23 | `ESSENTIA_VIBRATION_CHAMBER`(Tile: TileEssentiaVibrationChamber) |
| 知识刻印机 Knowledge Inscriber | `ModBlocks.java` | 24 | `KNOWLEDGE_INSCRIBER`(纯方块,无BE) |
| 精馏编码器 Distillation Encoder | `ModBlocks.java` | 25 | `DISTILLATION_ENCODER`(纯方块,无BE) |
| 齿轮箱 / 傀儡齿轮箱 | `ModBlocks.java` | 26~27 | `GEAR_BOX` / `GOLEM_GEAR_BOX` |
| 源质单元工作台 Essentia Cell Workbench(含 GUI 打开逻辑) | `ModBlocks.java` | 28~38 | 里面直接写了 `useItemOn` 和 `getMenuProvider` |
| 方块实体(BlockEntity)注册器 | `java/thaumicenergistics/init/ModBlockEntities.java` | — | (与 ModBlocks 里带 Tile 的对应) |
| 菜单类型 / 屏幕注册 | `java/thaumicenergistics/init/ModMenuTypes.java` + `ThaumicEnergistics.java:40~46` | — | `registerScreens` 方法里绑定 GuiXXX::new |
---
## 二、配方注册(1k/4k/16k/64k 组件、奥术、注入、坩埚)
| 你想找什么 | 文件 | 关键行 | 备注 |
|---|---|---|---|
| 配方总入口(commonSetup 里触发) | `java/thaumicenergistics/ThaumicEnergistics.java` | **36~38** | `commonSetup(event) { event.enqueueWork(RecipeRegistration::registerAll); }` |
| 配方注册总开关 | `java/thaumicenergistics/common/features/RecipeRegistration.java` | **247~253** | `registerAll()` 调 4 个子方法 + 打日志 |
| 有形状奥术合成(1k/4k/16k/64k、齿轮箱、刻印机等 14 条) | `RecipeRegistration.java` | **255~417** | `registerShapedArcane()` |
| ⭐ 1k Storage Component(任意天域之华版,for 循环展开) | `RecipeRegistration.java` | 256~267 | `wisps1k.get(i)` 当 'E' |
| ⭐ 4k Storage Component(任意天域之华版) | `RecipeRegistration.java` | 269~281 | `wisps4k.get(i)` 当 'E' |
| ⭐ 16k Storage Component(任意天域之华版) | `RecipeRegistration.java` | 283~296 | `wisps16k.get(i)` 当 'E' |
| 64k Storage Component | `RecipeRegistration.java` | 298~307 | 单配方,不用循环 |
| 天域之华名称表 + wispEssenceStacks()(不用 Tag,硬编码 ID 绕过时序) | `RecipeRegistration.java` | **Tag 常量区 + WISP_ESSENCE_VARIANTS 数组**(第 227 行起) | 这是配方「任意天域之华」能生效的核心 |
| 无形状奥术合成(核心、总线、终端等 7 条) | `RecipeRegistration.java` | 419~473 | `registerShapelessArcane()` |
| 注入配方(Essentia/Infusion Provider、奥术组装机) | `RecipeRegistration.java` | 475~514 | `registerInfusion()` |
| 坩埚配方(傀儡齿轮箱 = 齿轮箱熔炼) | `RecipeRegistration.java` | 516~523 | `registerCrucible()` |
| 3 个 helper:`stack()` 物品封装 / `tc()` 取 Thaumcraft 物品 / `ae()` 取 AE2 物品 | `RecipeRegistration.java` | 525~537 | 配方里所有 `'X', ae(...)`、`'X', tc(...)` 都走这里 |
| 配方乱码前缀 | `RecipeRegistration.java` | 所有 `addXxxRecipe` 第一个参数 | `"th_a€‰"` / `"th_b€‰"` / `"th_c€‰"` / `"th_d€‰"`(不影响功能但建议后续统一换成 `R + "xxx"`) |
---
## 三、资源引用链(材质 / 模型 / BlockState)
> 根目录:`resources/assets/thaumicenergistics/`
> 规则:**注册名 = 文件名(不含 .json/.png)**。物品/方块在 ModItems/ModBlocks 里用什么 `register("xxx")`,
> 下面 4 层 JSON/PNG 就必须都叫 `xxx`。
| 层 | 路径 | 它引用谁 | 关键字段 |
|---|---|---|---|
| ① BlockState(方块状态→方块模型) | `blockstates/<注册名>.json`(共 9 个) | 指向 `models/block/xxx.json` | `"model": "thaumicenergistics:block/<注册名>"` |
| ② Block Model(方块模型→PNG 贴图) | `models/block/<注册名>.json`(共 9 个) | 指向 `textures/block/xxx.png` | `"textures": { "up": "...", "down": "...", "north": "...", ... }` |
| ③ Item Model(物品模型→方块模型 **或** 物品 PNG) | `models/item/<注册名>.json`(物品 23 个 + 方块物品 9 个 = 32 个) | 方块物品:parent 到 ②;纯物品:直接写 layer0 | 方块物品:`"parent": "thaumicenergistics:block/<注册名>"`;纯物品:`"textures": { "layer0": "thaumicenergistics:item/<注册名>" }` |
| ④ PNG 贴图 | `textures/block/*.png`(9 套方块面)、`textures/item/*.png`(23 个物品贴图) | 被 ② ③ 引用 | 直接对应文件名 |
---
## 四、几个你最常问的具体定位(直接跳)
| 问题 | 去哪看 |
|---|---|
| 1k/4k/16k 组件配方「任意天域之华」怎么实现的 | `RecipeRegistration.java:227~244`(名称表 + `wispEssenceStacks()`) + `255~296`(for 循环注册) |
| 为什么要写死 `WISP_ESSENCE_VARIANTS` 数组,不能用 Tag 吗 | Tag 要到 DataPack 加载(比 commonSetup 晚)才填充,commonSetup 里 `getTag()` 返回空 → for 循环 0 次 → 配方直接没了。所以**注册阶段必须绕开 Tag 用硬编码 ID**。 |
| 「JEI 里完全没配方」排查顺序 | ① `latest.log` 里搜 `Wisp essence variants loaded` 看数字是不是 0;② 搜 `Invalid arcane recipe ingredient`(Ingredient 传进去就崩);③ 搜 `Mod loading has failed` 看 FMLCommonSetupEvent 是不是中途崩了;④ 确认 `commonSetup` 里是不是 `event.enqueueWork(RecipeRegistration::registerAll)` |
| Essentia Provider / Infusion Provider / Knowledge Inscriber / Gear Box「完全没材质」排查顺序 | 层 ①→②→③→④ 依次看:① blockstates 里 model 指向对不对;② models/block 里 textures 每个面都写了且 PNG 存在;③ models/item 里 parent 指回方块模型;④ textures 目录下 PNG 真实存在且命名一致。 |
| Essentia Cell Workbench「顶面材质没了,侧面正常」 | 直接打开 `models/block/essentia_cell_workbench.json` 看 `"textures"` 里 `"up"` 字段是不是写对了(应该指向 `textures/block/essentia_cell_workbench_top.png`) |
| 想加一个新物品/新方块 | ① 先在 ModItems / ModBlocks 里 `register("xxx", ...)`;② 想办法给物品弄一个 `models/item/xxx.json` + `textures/item/xxx.png`;如果是方块再加 `blockstates/xxx.json` + `models/block/xxx.json` + `textures/block/xxx.png`;③ 想进创造模式 Tab 要去 `ModCreativeTab.java` 里加 `output.accept(ModItems.XXX.get())`;④ 有配方去 `RecipeRegistration.java` 对应子方法里加一条 |
| 汉化文本 | `resources/assets/thaumicenergistics/lang/zh_cn.json` |
| 创造模式 Tab 物品顺序 | `java/thaumicenergistics/init/ModCreativeTab.java` |
| 源质单元容量实现(1k/4k/16k/64k 各自多少字节) | `java/thaumicenergistics/common/items/ItemEssentiaCell.java` 里的 `create1k / create4k / create16k / create64k` 静态工厂 |
| 天域之华 Tag 文件(防止主模组未来注册同名产生冲突) | `resources/data/thaumicenergistics/tags/items/wisp_essences.json` (里面写了 `"replace": false` 且包含 `{ "id": "#thaumcraft:wisp_essences", "required": false }` 作为兼容占位) |
| 启动崩 `Invalid arcane recipe ingredient: Ingredient@xxxx` | 一定是配方里把 Ingredient 传进了字符映射表(`'E', xxx` 的 xxx 必须是 ItemStack / Item / ResourceLocation,**不能是 Ingredient**),去 `registerShapedArcane()` 里搜 `wispEssenceIngredient`,有就立刻改成 `wisps.get(i)`(ItemStack) |
| Gradle 警告 `Space-assignment syntax ... init.gradle:10` | 这个是**全局 Gradle 初始化脚本**(`D:\GradleCache\init.gradle`)里的老写法,把 `url "https://..."` 改成 `url = "https://..."` 就好,跟模组代码无关 |
---
## 五、注册一个方块 — 从 Java 代码 → 材质 PNG 的完整 5 步引用链
> 🎯 例子用现成的 `knowledge_inscriber`(知识刻印机),你加新方块时直接把所有 `knowledge_inscriber` 替换成你的新注册 id 即可。
>
> 核心铁律:**注册 id 必须全局一致** — ModBlocks、ModItems、blockstates 文件名、models/block 文件名、models/item 文件名、textures 引用名,**全部都是同一个字符串**(大小写全小写,单词间下划线)。
### 第 1 步:Java 注册方块本体(决定注册 id)
**文件**:`java/thaumicenergistics/init/ModBlocks.java`
```java
public static final DeferredBlock<Block> KNOWLEDGE_INSCRIBER =
REGISTRY.register("knowledge_inscriber", () -> new Block(P));
// ^^^^^^^^^^^^^^^^^^^ ← 这里是「注册 id」,下面 4 层必须全一致
```
如果方块有 GUI(比如 Essentia Cell Workbench),就在 `new Block(P) { ... }` 里覆写 `useItemOn` + `getMenuProvider`。
如果方块有 BlockEntity(比如 Essentia Provider),就用 `ThEBaseEntityBlock(P)` 并实现 `newBlockEntity`。
### 第 2 步:Java 注册方块物品(拿在手里的那个 Item)
**文件**:`java/thaumicenergistics/init/ModItems.java`
```java
public static final DeferredItem<blockitem> KNOWLEDGE_INSCRIBER_ITEM =
REGISTRY.registerSimpleBlockItem(ModBlocks.KNOWLEDGE_INSCRIBER);
// ^^^^^^^^^^^^^^^^^^^ ← 直接绑定第 1 步的方块</blockitem>
```
`registerSimpleBlockItem` 是 NeoForge 封装好的,它会自动用**同一个注册 id**(这里就是 `knowledge_inscriber`)来生成 BlockItem,所以下面第 5 步「物品模型」的文件名也必须是 `knowledge_inscriber.json`。
### 第 3 步:BlockState(方块状态 → 方块模型的路由表)
**文件**:`resources/assets/thaumicenergistics/blockstates/knowledge_inscriber.json`
```json
{
"variants":
{
"":
{
"model": "thaumicenergistics:block/knowledge_inscriber"
}
}
}
```
> 📌 解释:Minecraft 渲染一个方块时,先看方块状态属性(朝向、开关等),再查 blockstates 找到该状态对应哪个**方块模型 JSON**。
> 知识刻印机没有状态属性(不区分朝向),所以用 `""` 表示「默认变体」;如果是有朝向的方块(比如 Essentia Provider),那要写 `facing=north/south/east/west/up/down` 六个变体。
### 第 4 步:Block Model(方块模型 → 每个面用哪张 PNG)
**文件**:`resources/assets/thaumicenergistics/models/block/knowledge_inscriber.json`
```json
{
"parent": "minecraft:block/cube_bottom_top",
"textures": {
"top": "thaumicenergistics:block/knowledge_inscriber_top",
"bottom": "thaumicenergistics:block/knowledge_inscriber_bottom",
"side": "thaumicenergistics:block/knowledge_inscriber_side"
}
}
```
> 📌 解释:`particle` 是「破坏方块时飞溅的粒子贴图」,一般跟 `north` 用同一张。上面 6 个面(`up/down/north/south/east/west`)的字符串,**不要加 `.png` 后缀**,游戏会自动去 `textures/` 目录下找对应的 PNG。
>
> 📌 对应的 3 张贴图必须真实存在:
> - `resources/assets/thaumicenergistics/textures/block/knowledge_inscriber_top.png`(顶面)
> - `resources/assets/thaumicenergistics/textures/block/knowledge_inscriber_bottom.png`(底面)
> - `resources/assets/thaumicenergistics/textures/block/knowledge_inscriber_side.png`(四个侧面共用一张)
### 第 5 步:Item Model(物品模型 — 方块物品最简单写法:直接「继承」方块模型)
**文件**:`resources/assets/thaumicenergistics/models/item/knowledge_inscriber.json`
```json
{
"parent": "thaumicenergistics:block/knowledge_inscriber"
}
```
> 📌 解释:99% 的方块物品**不需要独立物品贴图**,直接 `parent` 指回第 4 步的方块模型,Minecraft 会自动把方块渲染器缩放成 3D 物品形态(就是你在背包、物品栏、地上掉落物看到的样子)。
>
> 只有当你想让「物品形态」跟「方块形态」长得不一样时(比如 AE2 的接口物品是 2D 图标),才需要单独写 layer0 引用物品 PNG(写法参考下一节纯物品)。
### ✅ 新方块加完后**还要做的 2 件事**(别漏)
1. **进创造 Tab**:`java/thaumicenergistics/init/ModCreativeTab.java` 的 `displayItems` 里补一行 `output.accept(ModItems.KNOWLEDGE_INSCRIBER_ITEM.get());`(不然拿不到)
2. **汉化**:`resources/assets/thaumicenergistics/lang/zh_cn.json` 里补 `","block.thaumicenergistics.knowledge_inscriber":"知识刻印机"`
3. (可选)**有配方**:去 `RecipeRegistration.java` 的 `registerShapedArcane()` 或 `registerInfusion()` 里加一条。
---
## 六、注册一个纯物品(不是方块) — 从 Java 代码 → 材质 PNG 的完整 3 步引用链
> 🎯 例子用现成的 `storage_component_1k`(1k 存储组件),加新物品时直接替换 id 即可。
> 核心铁律同上:注册 id = 模型文件名 = PNG 文件名(不加后缀)。
### 第 1 步:Java 注册物品本体
**文件**:`java/thaumicenergistics/init/ModItems.java`
```java
public static final DeferredItem<item> STORAGE_COMPONENT_1K = REGISTRY.registerSimpleItem("storage_component_1k");
// ^^^^^^^^^^^^^^^^^^^^^ ← 注册 id,下面 2 层必须一致</item>
```
如果物品有自定义逻辑(比如源质 Cell 带容量读写 NBT、右键使用、背包叠加数量 1 等),就不用 `registerSimpleItem`,改用:
```java
public static final DeferredItem<itemessentiacell> ESSENTIA_CELL_1K =
REGISTRY.registerItem("essentia_cell_1k", ItemEssentiaCell::create1k);
```
本质上只是把 `new Item()` 换成你自己的自定义物品构造函数 / 静态工厂。
### 第 2 步:Item Model(物品模型 → layer0 指向物品 PNG)
**文件**:`resources/assets/thaumicenergistics/models/item/storage_component_1k.json`
```json
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "thaumicenergistics:item/storage_component_1k"
}
}
```
> 📌 解释:所有「普通 2D 贴图物品」的 parent 都是 `item/generated`(MC 内置的平面图标渲染器)。
> `layer0` 就是「主贴图」。字符串**不要加 `.png` 后缀**,游戏会自动找 `textures/item/storage_component_1k.png`。
>
> 少数物品有动画(比如 `knowledge_core.png.mcmeta`),那是在 PNG 旁边放一个 `.mcmeta` JSON 描述帧动画,模型文件写法不变。
### 第 3 步:放真实贴图 PNG
**文件**:`resources/assets/thaumicenergistics/textures/item/storage_component_1k.png`
> 📌 要求:16×16 或 32×32 或 64×64 的 PNG(尺寸必须是 2 的幂),**文件名必须跟 layer0 写的一样**。