Files
thaumicenergistics-neo/src/main/java/thaumicenergistics/common/integration/tc/ThEThaumcraft.java
T
1820982382 0e85bfc303 [修正] 奥术配方研究 key 修复与奥术合成终端充能完善
- 配方: 1k/4k/16k/64k 存储组件、无线傀儡背包、源质发信器
  研究 key 改为实际注册节点 (ESSENTIASTORAGE / GOLEMWIFIBACKPACK / ESSENTIATERMINAL)
- 配方: 扩散/凝聚核心材料 quicksilver → quicksilver_drop
- 配方: 知识记录仪/蒸馏编码台/源质终端 显示器三变体合并为
  thaumicenergistics:monitors tag (9 份重复配方 → 3 份)
- 终端: 新增法杖自动充能 (内存卡链接 Vis Interface P2P 频率,
  IGridTickable 每 tick 抽取, 速率与原版充能中继一致 5 cV/tick)
- 装配器: 删除无调用方且会静默失败的 findMatchingArcaneRecipe;
  vis 折扣魔法值统一为 BASE_VIS_DISCOUNT 常量
- 清理: 删除 Feature 空壳层/ThEFeatureBase/AEPartGridBlock 等死代码
  (-362 行), 删除空 registerScanEvent, 硬编码节点数, lang 死键
- 编译: IDEA 全项目通过 (problems: [])
2026-08-09 05:58:22 +08:00

371 lines
19 KiB
Java
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.
package thaumicenergistics.common.integration.tc;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.events.ResearchCompletedEvent;
import thaumcraft.api.research.ResearchCategories;
import thaumcraft.api.research.ResearchItem;
import thaumcraft.api.research.ResearchPage;
import thaumcraft.api.crafting.IArcaneRecipe;
import thaumcraft.api.crafting.InfusionRecipe;
import thaumcraft.api.crafting.CrucibleRecipe;
import thaumcraft.common.research.TCResearchManager;
import net.neoforged.neoforge.common.NeoForge;
import thaumicenergistics.ThaumicEnergistics;
import thaumicenergistics.common.features.RecipeRegistration;
import thaumicenergistics.init.ModBlocks;
import thaumicenergistics.init.ModItems;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 神秘能源 魔导手册研究注册
* 严格按照 1.7.10 ResearchRegistry 布局移植
*
* 1.7.10 伪前置(TC原版)映射:
* DISTILESSENTIA = 要素蒸馏
* TUBEFILTER = 高级源质管道
* MIRROR = 魔镜
* INFUSION = 注魔
* WARDEDARCANA = 守护之奥术
* ALCHEMICALDUPLICATION = 炼金复制
* FOCUSFIRE = 法杖核心
* VISPOWER = 掌控魔力
* SCEPTRE = 工艺权杖
* COREUSE = 傀儡核心:使用
* COREGATHER = 傀儡核心:聚集
*/
public final class ThEThaumcraft {
private static final Logger LOG = LoggerFactory.getLogger("ThE-TC");
static final String TAB = "THAUMICENERGISTICS";
static final String MODID = ThaumicEnergistics.MODID;
/**
* 原版研究 key → 伪前置 key 的映射。
* 用于 ResearchCompletedEvent 事件监听:当原版研究解锁时,自动 complete 对应伪前置。
*/
private static final Map<String, String> REAL_TO_PSEUDO = new HashMap<>();
private ThEThaumcraft() {}
public static void init() {
LOG.info("Registering ThaumicEnergistics research...");
ResearchCategories.registerCategory(TAB,
ResourceLocation.fromNamespaceAndPath(MODID, "textures/research/tab_icon.png"),
ResourceLocation.fromNamespaceAndPath(MODID, "textures/research/research_background.png"));
// ⚠ 必须先在当前 tab 注册伪前置节点(替代 TC 原版研究),
// 否则 setParents 跨分类引用时线画不出来。
registerPseudoParents();
// 注册事件监听:当 TC 原版研究解锁时,自动 complete 对应伪前置节点
registerPseudoSync();
// 注册顺序沿袭 1.7.10 移植(决定研究 tab 内节点坐标布局),勿随意调整。
registerBaseEnergistics();
registerArcaneAssembler();
registerKnowledgeInscriber();
registerEssentiaStorage();
registerArcaneCraftingTerminal();
registerVisInterface();
registerEssentiaBuses();
registerInfusionProvider();
registerEssentiaProvider();
registerEssentiaTerminal();
registerDigisentia();
registerFocusAEWrench();
registerCertusDupe();
registerEssentiaVibrationChamber();
registerDistillationEncoder();
registerGolemWifiBackpack();
LOG.info("ThaumicEnergistics research registered.");
}
// ==================== 伪前置节点(跨分类引用 TC 原版研究) ====================
// 在 ThE 研究 tab 中创建占位节点,使跨分类连线正常。
// 坐标来自 1.7.10 ResearchRegistry.PseudoResearchTypes
//SCEPTRE(工艺权杖)、DISTILESSENTIA(要素蒸馏) 、WARDEDARCANA(守护之奥术)、VISPOWER(掌控魔力)、
// TUBEFILTER(高级源质管道)、INFUSION(注魔) 、MIRROR(魔镜)、COREUSE(傀儡核心:使用)
private static void registerPseudoParents() {
// ALCHEMY
registerPseudo("DISTILESSENTIA", "ALCHEMY", -2, 0);
registerPseudo("TUBEFILTER", "ALCHEMY", -3, 0);
registerPseudo("ALCHEMICALDUPLICATION", "ALCHEMY", -5, -6);
// ARTIFICE
registerPseudo("MIRROR", "ARTIFICE", -4, 0);
registerPseudo("INFUSION", "ARTIFICE", -6, 0);
registerPseudo("WARDEDARCANA", "ARTIFICE", 1, 2);
// THAUMATURGY
registerPseudo("FOCUSFIRE", "THAUMATURGY", -4, -7);
registerPseudo("VISPOWER", "THAUMATURGY", 4, 0);
registerPseudo("SCEPTRE", "THAUMATURGY", 5, 0);
// GOLEMANCY
registerPseudo("COREGATHER", "GOLEMANCY", 1, -6);
}
private static void registerPseudo(String realKey, String realCategory, int col, int row) {
String pseudoKey = "PSEUDO_" + realKey;
try {
PseudoResearchItem.newPseudo(pseudoKey, TAB, realKey, realCategory, col, row)
.registerResearchItem();
// 记录映射,供事件监听使用
REAL_TO_PSEUDO.put(realKey, pseudoKey);
} catch (Exception e) {
LOG.warn("伪前置注册失败: PSEUDO_{} (TC:{}/{})", realKey, realCategory, realKey);
}
}
/**
* 注册事件监听:当 TC 原版研究被 complete 时,自动 complete 对应的伪前置节点。
* 替代 1.7.10 的 sibling 机制——在 NeoForge 版本中 sibling 机制失效,
* 因为 {@code TCResearchIndex.Entry} 是不可变 record,
* 修改 {@code ResearchItem.siblings} 不会更新到 {@code TCResearchIndex}。
*/
private static void registerPseudoSync() {
NeoForge.EVENT_BUS.addListener(ResearchCompletedEvent.class, (ResearchCompletedEvent rc) -> {
String completedKey = rc.researchKey();
// 跳过 clue 解锁(key 以 @ 开头)
if (completedKey.startsWith("@")) return;
// 跳过 PSEUDO_ 节点完成事件,防止 complete() 触发二次事件造成连锁
if (completedKey.startsWith("PSEUDO_")) return;
String pseudoKey = REAL_TO_PSEUDO.get(completedKey);
if (pseudoKey == null) return;
// 自动 complete 伪前置节点(不通知玩家)
try {
TCResearchManager.complete(rc.player(), pseudoKey, false);
} catch (Exception e) {
LOG.debug("伪前置自动解锁失败: {} → {}", completedKey, pseudoKey);
}
});
}
// ==================== 1. (0,0) BASEENERGISTICS 基础能源学====================
//无前置
private static void registerBaseEnergistics() {
new ResearchItem("BASEENERGISTICS", TAB,
new AspectList(),
0, 0,
0,
ResourceLocation.fromNamespaceAndPath(MODID, "textures/research/tab_icon.png"))
.setRound().setAutoUnlock()
.setPages(new ResearchPage("tc.research_text.BASEENERGISTICS"))
.registerResearchItem();
}
// ==================== 2. (6,-1) ARCANE_ASSEMBLER 奥术装配器====================
// 前置: VISINTERFACE(要素中继接口) + SCEPTRE(工艺权杖)
private static void registerArcaneAssembler() {
new ResearchItem("ARCANEASSEMBLER", TAB,
new AspectList().add(Aspect.CRAFT, 10).add(Aspect.MAGIC, 10)
.add(Aspect.MECHANISM, 5).add(Aspect.ORDER, 5),
6, -1, 3, new ItemStack(ModItems.ARCANE_ASSEMBLER_ITEM.get()))
.setRound().setParents("VISINTERFACE", "PSEUDO_SCEPTRE")
.setPages(
new ResearchPage("tc.research_text.ARCANEASSEMBLER.stage.1"),
new ResearchPage(RecipeRegistration.ARCANE_ASSEMBLER),
new ResearchPage("tc.research_text.ARCANEASSEMBLER.stage.2"))
.registerResearchItem();
}
// ==================== 2. (6,0) KNOWLEDGE_INSCRIBER 知识记录仪====================
// 前置: ARCANEASSEMBLER(奥术装配器)
private static void registerKnowledgeInscriber() {
new ResearchItem("KNOWLEDGEINSCRIBER", TAB,
new AspectList().add(Aspect.MIND, 10).add(Aspect.MECHANISM, 5).add(Aspect.MAGIC, 5),
6, 0, 3, new ItemStack(ModItems.KNOWLEDGE_INSCRIBER_ITEM.get()))
.setRound().setParents("ARCANEASSEMBLER")
.setPages(
new ResearchPage("tc.research_text.KNOWLEDGEINSCRIBER"),
new ResearchPage(RecipeRegistration.KNOWLEDGE_CORE_ITEM),
new ResearchPage(RecipeRegistration.KNOWLEDGE_INSCRIBER_BLOCK))
.registerResearchItem();
}
// ==================== 3. (0,2) ESSENTIASTORAGE 源质存储====================
// 前置: BASEENERGISTICS(基础能源学) + DISTILESSENTIA(要素蒸馏) + WARDEDARCANA(守护之奥术)
private static void registerEssentiaStorage() {
new ResearchItem("ESSENTIASTORAGE", TAB,
new AspectList().add(Aspect.ORDER, 1).add(Aspect.MAGIC, 1),
0, 2, 2, new ItemStack(ModItems.ESSENTIA_CELL_1K.get()))
.setRound().setParents("BASEENERGISTICS", "PSEUDO_DISTILESSENTIA", "PSEUDO_WARDEDARCANA")
.setPages(
new ResearchPage("tc.research_text.ESSENTIASTORAGE"),
new ResearchPage(RecipeRegistration.STORAGE_COMPONENT_1K),
new ResearchPage(new IArcaneRecipe[]{RecipeRegistration.STORAGE_COMPONENT_4K, RecipeRegistration.STORAGE_COMPONENT_16K, RecipeRegistration.STORAGE_COMPONENT_64K}))
.registerResearchItem();
}
// ==================== 4. (2,-1) ARCANECRAFTINGTERMINAL 奥术合成终端====================
// 前置: BASEENERGISTICS(基础能源学)
private static void registerArcaneCraftingTerminal() {
new ResearchItem("ARCANECRAFTINGTERMINAL", TAB,
new AspectList().add(Aspect.CRAFT, 10).add(Aspect.MAGIC, 10).add(Aspect.MECHANISM, 5),
2, -1, 2, new ItemStack(ModItems.ARCANE_CRAFTING_TERMINAL_ITEM.get()))
.setRound().setParents("BASEENERGISTICS")
.setPages(
new ResearchPage("tc.research_text.ARCANECRAFTINGTERMINAL.stage.1"),
new ResearchPage(RecipeRegistration.ARCANE_CRAFTING_TERMINAL),
new ResearchPage("tc.research_text.ARCANECRAFTINGTERMINAL.stage.2"))
.registerResearchItem();
}
// ==================== 5. (4,-1) VISINTERFACE 要素中继接口====================
// 前置: ARCANECRAFTINGTERMINAL(奥术合成终端) + VISPOWER(掌控魔力)
private static void registerVisInterface() {
new ResearchItem("VISINTERFACE", TAB,
new AspectList().add(Aspect.AURA, 10).add(Aspect.MAGIC, 5).add(Aspect.MECHANISM, 5),
4, -1, 3, new ItemStack(ModItems.VIS_INTERFACE.get()))
.setRound().setParents("ARCANECRAFTINGTERMINAL", "PSEUDO_VISPOWER")
.setPages(
new ResearchPage("tc.research_text.VISINTERFACE"),
new ResearchPage(RecipeRegistration.VIS_INTERFACE))
.registerResearchItem();
}
// ==================== 6. (-2,-2) ESSENTIABUSES 源质总线====================
// 前置: DIGISENTIA(数字化源质) + TUBEFILTER(高级源质管道)
private static void registerEssentiaBuses() {
new ResearchItem("ESSENTIABUSES", TAB,
new AspectList().add(Aspect.MECHANISM, 5).add(Aspect.EXCHANGE, 5).add(Aspect.MAGIC, 3),
-2, -2, 2, new ItemStack(ModItems.ESSENTIA_IMPORT_BUS.get()))
.setRound().setParents("DIGISENTIA", "PSEUDO_TUBEFILTER")
.setPages(
new ResearchPage("tc.research_text.ESSENTIABUSES.stage.1"),
new ResearchPage(RecipeRegistration.ESSENTIA_IMPORT_BUS),
new ResearchPage(RecipeRegistration.ESSENTIA_EXPORT_BUS),
new ResearchPage(RecipeRegistration.ESSENTIA_STORAGE_BUS),
new ResearchPage("tc.research_text.ESSENTIABUSES.stage.2"))
.registerResearchItem();
}
// ==================== 7. (-5,-2) INFUSIONPROVIDER 注魔供应器====================
// 前置: ESSENTIABUSES(源质总线) + INFUSION(注魔) + MIRROR(魔镜)
private static void registerInfusionProvider() {
new ResearchItem("INFUSIONPROVIDER", TAB,
new AspectList().add(Aspect.MECHANISM, 10).add(Aspect.MAGIC, 10)
.add(Aspect.ORDER, 8).add(Aspect.EXCHANGE, 5),
-5, -2, 3, new ItemStack(ModItems.INFUSION_PROVIDER_ITEM.get()))
.setRound().setParents("ESSENTIABUSES", "PSEUDO_INFUSION", "PSEUDO_MIRROR")
.setPages(
new ResearchPage("tc.research_text.INFUSIONPROVIDER.stage.1"),
new ResearchPage(RecipeRegistration.INFUSION_PROVIDER),
new ResearchPage("tc.research_text.INFUSIONPROVIDER.stage.2"))
.registerResearchItem();
}
// ==================== 8. (-2,-4) ESSENTIAPROVIDER 源质供应器====================
// 前置: ESSENTIABUSES(源质总线)
private static void registerEssentiaProvider() {
new ResearchItem("ESSENTIAPROVIDER", TAB,
new AspectList().add(Aspect.MECHANISM, 8).add(Aspect.MAGIC, 8).add(Aspect.EXCHANGE, 5),
-2, -4, 3, new ItemStack(ModItems.ESSENTIA_PROVIDER_ITEM.get()))
.setRound().setParents("ESSENTIABUSES")
.setPages(
new ResearchPage("tc.research_text.ESSENTIAPROVIDER.stage.1"),
new ResearchPage(RecipeRegistration.ESSENTIA_PROVIDER),
new ResearchPage("tc.research_text.ESSENTIAPROVIDER.stage.2"))
.registerResearchItem();
}
// ==================== 9. (-1,-4) ESSENTIATERMINAL 源质终端====================
// 前置: DIGISENTIA(数字化源质)
private static void registerEssentiaTerminal() {
new ResearchItem("ESSENTIATERMINAL", TAB,
new AspectList().add(Aspect.MAGIC, 5).add(Aspect.ORDER, 3).add(Aspect.MIND, 3),
-1, -4, 2, new ItemStack(ModItems.ESSENTIA_TERMINAL_ITEM.get()))
.setRound().setParents("DIGISENTIA")
.setPages(
new ResearchPage("tc.research_text.ESSENTIATERMINAL.stage.1"),
new ResearchPage(RecipeRegistration.ESSENTIA_TERMINAL),
new ResearchPage(RecipeRegistration.ESSENTIA_LEVEL_EMITTER),
new ResearchPage("tc.research_text.ESSENTIATERMINAL.stage.2"))
.registerResearchItem();
}
// ==================== 10. (0,-2) DIGISENTIA 数字化源质====================
// 前置: BASEENERGISTICS(基础能源学) + DISTILESSENTIA(要素蒸馏)
private static void registerDigisentia() {
new ResearchItem("DIGISENTIA", TAB,
new AspectList().add(Aspect.ORDER, 5).add(Aspect.ENTROPY, 5).add(Aspect.MAGIC, 3),
0, -2, 1, new ItemStack(ModItems.DIFFUSION_CORE.get()))
.setRound().setParents("BASEENERGISTICS", "PSEUDO_DISTILESSENTIA")
.setPages(
new ResearchPage("tc.research_text.DIGISENTIA.stage.1"),
new ResearchPage(RecipeRegistration.DIFFUSION_CORE),
new ResearchPage(RecipeRegistration.COALESCENCE_CORE),
new ResearchPage("tc.research_text.DIGISENTIA.stage.2"))
.registerResearchItem();
}
// ==================== 12. (-3,-7) FOCUS_AEWRENCH 法杖核心 AE扳手====================
// 前置: BASEENERGISTICS(基础能源学) + FOCUSFIRE(法杖核心)
private static void registerFocusAEWrench() {
new ResearchItem("FOCUS_AEWRENCH", TAB,
new AspectList().add(Aspect.TOOL, 5).add(Aspect.ENERGY, 5).add(Aspect.MECHANISM, 3),
-3, -7, 3, new ItemStack(ModItems.FOCUS_AEWRENCH.get()))
.setRound().setParents("PSEUDO_FOCUSFIRE").setParentsHidden("BASEENERGISTICS")
.setPages(
new ResearchPage("tc.research_text.FOCUS_AEWRENCH"),
new ResearchPage(RecipeRegistration.FOCUS_AEWRENCH_RECIPE))
.registerResearchItem();
}
// ==================== 13. (-5,-5) CERTUS_DUPE 赛特斯石英复制====================
// 前置: ALCHEMICALDUPLICATION(炼金复制) + BASEENERGISTICS(基础能源学)
private static void registerCertusDupe() {
new ResearchItem("CERTUS_DUPE", TAB,
new AspectList().add(Aspect.CRYSTAL, 5).add(Aspect.MAGIC, 5).add(Aspect.EXCHANGE, 5),
-5, -5, 2, new ItemStack(appeng.core.definitions.AEItems.CERTUS_QUARTZ_CRYSTAL.asItem()))
.setRound().setParents("PSEUDO_ALCHEMICALDUPLICATION").setParentsHidden("BASEENERGISTICS")
.setPages(
new ResearchPage("tc.research_text.CERTUS_DUPE"),
new ResearchPage(RecipeRegistration.CERTUS_DUPE_RECIPE))
.registerResearchItem();
}
// ==================== 14. (1,-4) VIBRATIONCHAMBER 源质谐振仓====================
// 前置: DIGISENTIA
private static void registerEssentiaVibrationChamber() {
new ResearchItem("ESSENTIAVIBRATIONCHAMBER", TAB,
new AspectList().add(Aspect.ENERGY, 8).add(Aspect.MECHANISM, 5).add(Aspect.FIRE, 3),
1, -4, 3, new ItemStack(ModItems.ESSENTIA_VIBRATION_CHAMBER_ITEM.get()))
.setRound().setParents("DIGISENTIA")
.setPages(
new ResearchPage("tc.research_text.ESSENTIAVIBRATIONCHAMBER"),
new ResearchPage(RecipeRegistration.ESSENTIA_VIBRATION_CHAMBER))
.registerResearchItem();
}
// ==================== 15. (-4,-4) DISTILLATIONENCODER 蒸馏编码台====================
// 前置: ESSENTIABUSES
private static void registerDistillationEncoder() {
new ResearchItem("DISTILLATIONENCODER", TAB,
new AspectList().add(Aspect.MECHANISM, 5).add(Aspect.ORDER, 5).add(Aspect.ENTROPY, 5),
-4, -4, 3, new ItemStack(ModItems.DISTILLATION_ENCODER_ITEM.get()))
.setRound().setParents("ESSENTIABUSES")
.setPages(
new ResearchPage("tc.research_text.DISTILLATIONENCODER"),
new ResearchPage(RecipeRegistration.DISTILLATION_ENCODER_BLOCK))
.registerResearchItem();
}
// ==================== 16. (0,-6) GOLEMWIFIBACKPACK 无线傀儡背包====================
// 前置: DIGISENTIA + COREGATHER(傀儡核心:聚集)
private static void registerGolemWifiBackpack() {
new ResearchItem("GOLEMWIFIBACKPACK", TAB,
new AspectList().add(Aspect.MAGIC, 5).add(Aspect.MECHANISM, 5).add(Aspect.MIND, 3),
0, -6, 3, new ItemStack(ModItems.GOLEM_WIFI_BACKPACK.get()))
.setRound().setParents("PSEUDO_COREGATHER").setParentsHidden("DIGISENTIA")
.setPages(
new ResearchPage("tc.research_text.GOLEMWIFI"),
new ResearchPage(RecipeRegistration.GOLEM_WIFI_BACKPACK_RECIPE))
.registerResearchItem();
}
}