Compare commits

...
2 Commits
Author SHA1 Message Date
1820982382 8673074e60 [修正] 奥术配方研究 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 06:00:07 +08:00
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
32 changed files with 146 additions and 389 deletions
+1
View File
@@ -15,3 +15,4 @@ findings.md
progress.md progress.md
/modules/thaumicenergistics-neo/存储体系方案.md /modules/thaumicenergistics-neo/存储体系方案.md
/modules/thaumicenergistics-neo/计划书-配方溯源.md /modules/thaumicenergistics-neo/计划书-配方溯源.md
/.reasonix/
@@ -1,6 +1,7 @@
package thaumicenergistics; package thaumicenergistics;
import appeng.api.features.GridLinkables; import appeng.api.features.GridLinkables;
import appeng.api.features.P2PTunnelAttunement;
import appeng.api.parts.PartModels; import appeng.api.parts.PartModels;
import appeng.api.stacks.AEKeyType; import appeng.api.stacks.AEKeyType;
import appeng.api.stacks.AEKeyTypesInternal; import appeng.api.stacks.AEKeyTypesInternal;
@@ -19,7 +20,6 @@ import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import thaumicenergistics.common.container.*; import thaumicenergistics.common.container.*;
import thaumicenergistics.common.features.FeatureRegistry;
import thaumicenergistics.common.features.RecipeRegistration; import thaumicenergistics.common.features.RecipeRegistration;
import thaumicenergistics.common.integration.appeng.AEssentiaKeyType; import thaumicenergistics.common.integration.appeng.AEssentiaKeyType;
import thaumicenergistics.common.integration.appeng.ThEAppliedEnergistics; import thaumicenergistics.common.integration.appeng.ThEAppliedEnergistics;
@@ -107,12 +107,11 @@ public final class ThaumicEnergistics {
event.enqueueWork(() -> { event.enqueueWork(() -> {
RecipeRegistration.registerAll(); RecipeRegistration.registerAll();
ThEThaumcraft.init(); ThEThaumcraft.init();
P2PTunnelAttunement.registerAttunementTag(ModItems.VIS_INTERFACE.get());
GridLinkables.register(ModItems.GOLEM_WIFI_BACKPACK.get(), ItemGolemWirelessBackpack.LINKABLE_HANDLER); GridLinkables.register(ModItems.GOLEM_WIFI_BACKPACK.get(), ItemGolemWirelessBackpack.LINKABLE_HANDLER);
GridLinkables.register(ModItems.WIRELESS_ESSENTIA_TERMINAL.get(), GridLinkables.register(ModItems.WIRELESS_ESSENTIA_TERMINAL.get(),
appeng.items.tools.powered.WirelessTerminalItem.LINKABLE_HANDLER); appeng.items.tools.powered.WirelessTerminalItem.LINKABLE_HANDLER);
}); });
FeatureRegistry.registerAll();
} }
private void registerUpgrades(FMLCommonSetupEvent event) { private void registerUpgrades(FMLCommonSetupEvent event) {
@@ -1,21 +0,0 @@
package thaumicenergistics.common.features;
/**
* 功能:奥术自动合成。
* 启用奥术装配器及相关合成样板。
* 自 1.7.10 FeatureAutocrafting_Arcane 移植(约 7k 行)。
*/
public class FeatureAutocraftingArcane extends ThEFeatureBase {
public FeatureAutocraftingArcane() { super("arcane_crafting_terminal"); }
@Override
protected void doRegister() {
// Arcane Assembler 方块经 ModBlocks 注册
// TODO: Register arcane crafting pattern encoder, crafting CPU integration
}
@Override
protected void doPostInit() {
// TODO: Register arcane crafting recipes, research entries
}
}
@@ -1,20 +0,0 @@
package thaumicenergistics.common.features;
/**
* 源质存储元件功能。
* 注册 cell 物品、元件工作台与存储组件物品。
* 自 1.7.10 FeatureCells 移植(约 12k 行)。
*/
public class FeatureCells extends ThEFeatureBase {
public FeatureCells() { super("cells"); }
@Override
protected void doRegister() {
// 物品经 init 包的 ModItems 注册——本功能校验其存在
}
@Override
protected void doPostInit() {
// TODO: Register cell recipes, research entries, cell workbench functionality
}
}
@@ -1,35 +0,0 @@
package thaumicenergistics.common.features;
import thaumicenergistics.ThaumicEnergistics;
import thaumicenergistics.init.ModItems;
/**
* 功能:源质 IO 总线。
* 启用源质输入/输出/存储总线Part部件
* Part注册已移至模组主类ThaumicEnergistics构造方法中,
* 通过AE2官方PartHelper.registerPart() API完成,
* 本Feature负责功能开关、配方注册、研究数据等跨模组集成内容。
*/
public class FeatureEssentiaIOBuses extends ThEFeatureBase {
public FeatureEssentiaIOBuses() { super("io_buses"); }
@Override
protected void doRegister() {
// ===== Part核心注册已在ThaumicEnergistics构造方法中完成 =====
// 原因:AE2 PartHelper.registerPart()需要DeferredItem注册完成后立即调用,
// Feature.register()的调用时机同样满足,但为了集中管理Part注册入口,统一在主类中处理。
// ===== 以下登记本Feature涉及的物品,供跨模组引用追踪 =====
ThaumicEnergistics.LOG.info(" -> EssentiaImportBus PartItem: {} (ready)",
ModItems.ESSENTIA_IMPORT_BUS.getId());
ThaumicEnergistics.LOG.info(" -> EssentiaExportBus PartItem: {} (pending)",
ModItems.ESSENTIA_EXPORT_BUS.getId());
ThaumicEnergistics.LOG.info(" -> EssentiaStorageBus PartItem: {} (pending)",
ModItems.ESSENTIA_STORAGE_BUS.getId());
}
@Override
protected void doPostInit() {
// 后置初始化:注册神秘时代研究条目、AE2合成配方等
}
}
@@ -1,15 +0,0 @@
package thaumicenergistics.common.features;
/**
* 源质监控功能。
* 启用源质水平检测器、存储监控器与转换监控器部件。
* 自 1.7.10 FeatureEssentiaMonitoring 移植(约 6k 行)。
*/
public class FeatureEssentiaMonitoring extends ThEFeatureBase {
public FeatureEssentiaMonitoring() { super("monitoring"); }
@Override
protected void doRegister() {
// TODO: Register monitoring-related parts when AE2 part API is integrated
}
}
@@ -1,7 +0,0 @@
package thaumicenergistics.common.features;
/** 功能:源质供应器。从 AE 网络核心抽取源质。 */
public class FeatureEssentiaProvider extends ThEFeatureBase {
public FeatureEssentiaProvider() { super("essentia_provider"); }
@Override protected void doRegister() {}
}
@@ -1,21 +0,0 @@
package thaumicenergistics.common.features;
/**
* 功能:源质谐振仓。
* 启用基于源质的能量生产。
* 自 1.7.10 FeatureEssentiaVibrationChamber 移植(约 4k 行)。
*/
public class FeatureEssentiaVibrationChamber extends ThEFeatureBase {
public FeatureEssentiaVibrationChamber() { super("vibration_chamber"); }
@Override
protected void doRegister() {
// EVC 方块经 ModBlocks 注册
// TODO: Register fuel values for each essentia type
}
@Override
protected void doPostInit() {
// TODO: Register EVC recipe, research entry
}
}
@@ -1,11 +0,0 @@
package thaumicenergistics.common.features;
/** 功能:无线傀儡背包。启用傀儡访问 AE 网络。 */
public class FeatureGolemBackpack extends ThEFeatureBase {
public FeatureGolemBackpack() { super("golem_backpack"); }
@Override
protected void doRegister() {
// GridLinkables 注册在 commonSetup 阶段完成(需要物品已绑定)
}
}
@@ -1,16 +0,0 @@
package thaumicenergistics.common.features;
/**
* 功能:注魔供应器。
* 为 TC 注魔自动供应源质。
* 自 1.7.10 FeatureInfusionProvider 移植(约 4k 行)。
*/
public class FeatureInfusionProvider extends ThEFeatureBase {
public FeatureInfusionProvider() { super("infusion_provider"); }
@Override
protected void doRegister() {
// Infusion Provider 方块经 ModBlocks 注册
// TODO: Register infusion detection and essentia delivery logic
}
}
@@ -1,17 +0,0 @@
package thaumicenergistics.common.features;
import thaumicenergistics.ThaumicEnergistics;
public final class FeatureRegistry {
private FeatureRegistry() {}
private static final ThEFeatureBase[] FEATURES = {
new FeatureCells(), new FeatureEssentiaIOBuses(), new FeatureEssentiaMonitoring(),
new FeatureEssentiaVibrationChamber(), new FeatureInfusionProvider(),
new FeatureAutocraftingArcane(), new FeatureVisRelayInterface(),
new FeatureGolemBackpack(), new FeatureEssentiaProvider()
};
public static void registerAll() {
for (var f : FEATURES) { ThaumicEnergistics.LOG.info("Feature [{}] {}", f.getName(), f.isEnabled() ? "enabled":"disabled"); f.register(); }
}
public static void postInitAll() { for (var f : FEATURES) f.postInit(); }
}
@@ -1,17 +0,0 @@
package thaumicenergistics.common.features;
import appeng.api.features.P2PTunnelAttunement;
import thaumicenergistics.init.ModItems;
public class FeatureVisRelayInterface extends ThEFeatureBase {
public FeatureVisRelayInterface() { super("vis_interface"); }
@Override
protected void doRegister() {
P2PTunnelAttunement.registerAttunementTag(ModItems.VIS_INTERFACE.get());
}
@Override
protected void doPostInit() {
}
}
@@ -54,6 +54,8 @@ public final class RecipeRegistration {
public static CrucibleRecipe CERTUS_DUPE_RECIPE; public static CrucibleRecipe CERTUS_DUPE_RECIPE;
private static final TagKey<Item> WISP_ESSENCES = tag("thaumicenergistics", "wisp_essences"); private static final TagKey<Item> WISP_ESSENCES = tag("thaumicenergistics", "wisp_essences");
/** AE2 三种显示器(普通/暗/半暗)任一可用。 */
private static final TagKey<Item> MONITORS = tag("thaumicenergistics", "monitors");
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private static TagKey<Item> tag(String ns, String path) { private static TagKey<Item> tag(String ns, String path) {
@@ -80,7 +82,7 @@ public final class RecipeRegistration {
} }
private static void registerShapedArcane() { private static void registerShapedArcane() {
STORAGE_COMPONENT_1K = ThaumcraftApi.addArcaneCraftingRecipe("ESSENTIASTORAGE1K", stack(ModItems.STORAGE_COMPONENT_1K), STORAGE_COMPONENT_1K = ThaumcraftApi.addArcaneCraftingRecipe("ESSENTIASTORAGE", stack(ModItems.STORAGE_COMPONENT_1K),
new AspectList().add(Aspect.FIRE, 3).add(Aspect.ORDER, 1), new AspectList().add(Aspect.FIRE, 3).add(Aspect.ORDER, 1),
"EQ ", "EQ ",
"QPQ", "QPQ",
@@ -89,7 +91,7 @@ public final class RecipeRegistration {
'Q', ae("certus_quartz_crystal"), 'Q', ae("certus_quartz_crystal"),
'P', ae("logic_processor")); 'P', ae("logic_processor"));
STORAGE_COMPONENT_4K = ThaumcraftApi.addArcaneCraftingRecipe("ESSENTIASTORAGE4K", stack(ModItems.STORAGE_COMPONENT_4K), STORAGE_COMPONENT_4K = ThaumcraftApi.addArcaneCraftingRecipe("ESSENTIASTORAGE", stack(ModItems.STORAGE_COMPONENT_4K),
new AspectList().add(Aspect.FIRE, 3).add(Aspect.ORDER, 2), new AspectList().add(Aspect.FIRE, 3).add(Aspect.ORDER, 2),
"EPE", "EPE",
"1G1", "1G1",
@@ -99,7 +101,7 @@ public final class RecipeRegistration {
'1', stack(ModItems.STORAGE_COMPONENT_1K), '1', stack(ModItems.STORAGE_COMPONENT_1K),
'G', ae("quartz_glass")); 'G', ae("quartz_glass"));
STORAGE_COMPONENT_16K = ThaumcraftApi.addArcaneCraftingRecipe("ESSENTIASTORAGE16K", stack(ModItems.STORAGE_COMPONENT_16K), STORAGE_COMPONENT_16K = ThaumcraftApi.addArcaneCraftingRecipe("ESSENTIASTORAGE", stack(ModItems.STORAGE_COMPONENT_16K),
new AspectList().add(Aspect.FIRE, 3).add(Aspect.ORDER, 4), new AspectList().add(Aspect.FIRE, 3).add(Aspect.ORDER, 4),
"SPE", "SPE",
"4G4", "4G4",
@@ -110,7 +112,7 @@ public final class RecipeRegistration {
'G', ae("quartz_glass"), 'G', ae("quartz_glass"),
'E', WISP_ESSENCES); 'E', WISP_ESSENCES);
STORAGE_COMPONENT_64K = ThaumcraftApi.addArcaneCraftingRecipe("ESSENTIASTORAGE64K", stack(ModItems.STORAGE_COMPONENT_64K), STORAGE_COMPONENT_64K = ThaumcraftApi.addArcaneCraftingRecipe("ESSENTIASTORAGE", stack(ModItems.STORAGE_COMPONENT_64K),
new AspectList().add(Aspect.FIRE, 3).add(Aspect.ORDER, 8), new AspectList().add(Aspect.FIRE, 3).add(Aspect.ORDER, 8),
"SPS", "SPS",
"6G6", "6G6",
@@ -140,7 +142,7 @@ public final class RecipeRegistration {
'F', tc("fire_shard"), 'F', tc("fire_shard"),
'W', ae("certus_quartz_wrench")); 'W', ae("certus_quartz_wrench"));
GOLEM_WIFI_BACKPACK_RECIPE = ThaumcraftApi.addArcaneCraftingRecipe("GOLEMWIFI", stack(ModItems.GOLEM_WIFI_BACKPACK), GOLEM_WIFI_BACKPACK_RECIPE = ThaumcraftApi.addArcaneCraftingRecipe("GOLEMWIFIBACKPACK", stack(ModItems.GOLEM_WIFI_BACKPACK),
new AspectList().add(Aspect.AIR, 6).add(Aspect.FIRE, 4).add(Aspect.ORDER, 3), new AspectList().add(Aspect.AIR, 6).add(Aspect.FIRE, 4).add(Aspect.ORDER, 3),
"tIt", "tIt",
"nRn", "nRn",
@@ -189,58 +191,17 @@ public final class RecipeRegistration {
" T ", " T ",
"IPI", "IPI",
'I', new ItemStack(Items.IRON_INGOT, 4), 'I', new ItemStack(Items.IRON_INGOT, 4),
'L', ae("monitor"), 'L', MONITORS,
'T', tc("thaumonomicon"), 'T', tc("thaumonomicon"),
'P', ae("logic_processor")); 'P', ae("logic_processor"));
ThaumcraftApi.addArcaneCraftingRecipe("KNOWLEDGEINSCRIBER", stack(ModBlocks.KNOWLEDGE_INSCRIBER),
new AspectList().add(Aspect.WATER, 5).add(Aspect.EARTH, 5).add(Aspect.FIRE, 5).add(Aspect.AIR, 5).add(Aspect.ORDER, 5).add(Aspect.ENTROPY, 5),
"ILI",
" T ",
"IPI",
'I', new ItemStack(Items.IRON_INGOT, 4),
'L', ae("dark_monitor"),
'T', tc("thaumonomicon"),
'P', ae("logic_processor"));
ThaumcraftApi.addArcaneCraftingRecipe("KNOWLEDGEINSCRIBER", stack(ModBlocks.KNOWLEDGE_INSCRIBER),
new AspectList().add(Aspect.WATER, 5).add(Aspect.EARTH, 5).add(Aspect.FIRE, 5).add(Aspect.AIR, 5).add(Aspect.ORDER, 5).add(Aspect.ENTROPY, 5),
"ILI",
" T ",
"IPI",
'I', new ItemStack(Items.IRON_INGOT, 4),
'L', ae("semi_dark_monitor"),
'T', tc("thaumonomicon"),
'P', ae("logic_processor"));
DISTILLATION_ENCODER_BLOCK = ThaumcraftApi.addArcaneCraftingRecipe("DISTILLATIONENCODER", stack(ModBlocks.DISTILLATION_ENCODER), DISTILLATION_ENCODER_BLOCK = ThaumcraftApi.addArcaneCraftingRecipe("DISTILLATIONENCODER", stack(ModBlocks.DISTILLATION_ENCODER),
new AspectList().add(Aspect.ORDER, 5).add(Aspect.ENTROPY, 5).add(Aspect.FIRE, 3), new AspectList().add(Aspect.ORDER, 5).add(Aspect.ENTROPY, 5).add(Aspect.FIRE, 3),
"ILI", "ILI",
" G ", " G ",
"IPI", "IPI",
'I', new ItemStack(Items.IRON_INGOT, 4), 'I', new ItemStack(Items.IRON_INGOT, 4),
'L', ae("monitor"), 'L', MONITORS,
'G', tc("thaumometer"),
'P', ae("engineering_processor"));
ThaumcraftApi.addArcaneCraftingRecipe("DISTILLATIONENCODER", stack(ModBlocks.DISTILLATION_ENCODER),
new AspectList().add(Aspect.ORDER, 5).add(Aspect.ENTROPY, 5).add(Aspect.FIRE, 3),
"ILI",
" G ",
"IPI",
'I', new ItemStack(Items.IRON_INGOT, 4),
'L', ae("dark_monitor"),
'G', tc("thaumometer"),
'P', ae("engineering_processor"));
ThaumcraftApi.addArcaneCraftingRecipe("DISTILLATIONENCODER", stack(ModBlocks.DISTILLATION_ENCODER),
new AspectList().add(Aspect.ORDER, 5).add(Aspect.ENTROPY, 5).add(Aspect.FIRE, 3),
"ILI",
" G ",
"IPI",
'I', new ItemStack(Items.IRON_INGOT, 4),
'L', ae("semi_dark_monitor"),
'G', tc("thaumometer"), 'G', tc("thaumometer"),
'P', ae("engineering_processor")); 'P', ae("engineering_processor"));
} }
@@ -250,23 +211,23 @@ public final class RecipeRegistration {
// 1. 扩散核心 // 1. 扩散核心
DIFFUSION_CORE = ThaumcraftApi.addShapelessArcaneCraftingRecipe("DIGISENTIA", stack(ModItems.DIFFUSION_CORE), DIFFUSION_CORE = ThaumcraftApi.addShapelessArcaneCraftingRecipe("DIGISENTIA", stack(ModItems.DIFFUSION_CORE),
new AspectList().add(Aspect.WATER, 2).add(Aspect.ENTROPY, 2), new AspectList().add(Aspect.WATER, 2).add(Aspect.ENTROPY, 2),
tc("quicksilver"), tc("quicksilver_drop"),
tc("quicksilver"), tc("quicksilver_drop"),
tc("quicksilver"), tc("quicksilver_drop"),
tc("entropy_shard"), tc("entropy_shard"),
ae("annihilation_core")); ae("annihilation_core"));
// 2. 凝聚核心 // 2. 凝聚核心
COALESCENCE_CORE = ThaumcraftApi.addShapelessArcaneCraftingRecipe("DIGISENTIA", stack(ModItems.COALESCENCE_CORE), COALESCENCE_CORE = ThaumcraftApi.addShapelessArcaneCraftingRecipe("DIGISENTIA", stack(ModItems.COALESCENCE_CORE),
new AspectList().add(Aspect.WATER, 2).add(Aspect.ORDER, 2), new AspectList().add(Aspect.WATER, 2).add(Aspect.ORDER, 2),
tc("quicksilver"), tc("quicksilver_drop"),
tc("quicksilver"), tc("quicksilver_drop"),
tc("quicksilver"), tc("quicksilver_drop"),
tc("order_shard"), tc("order_shard"),
ae("formation_core")); ae("formation_core"));
// 3. 原质等级发射器 // 3. 原质等级发射器
ESSENTIA_LEVEL_EMITTER = ThaumcraftApi.addShapelessArcaneCraftingRecipe("ESSENTIAMONITORING", new ItemStack(ModItems.ESSENTIA_LEVEL_EMITTER.get(), 1), ESSENTIA_LEVEL_EMITTER = ThaumcraftApi.addShapelessArcaneCraftingRecipe("ESSENTIATERMINAL", new ItemStack(ModItems.ESSENTIA_LEVEL_EMITTER.get(), 1),
new AspectList().add(Aspect.FIRE, 4), new AspectList().add(Aspect.FIRE, 4),
ae("calculation_processor"), ae("calculation_processor"),
new ItemStack(Items.REDSTONE_TORCH), new ItemStack(Items.REDSTONE_TORCH),
@@ -275,26 +236,7 @@ public final class RecipeRegistration {
// 4. 原质终端 // 4. 原质终端
ESSENTIA_TERMINAL = ThaumcraftApi.addShapelessArcaneCraftingRecipe("ESSENTIATERMINAL", stack(ModItems.ESSENTIA_TERMINAL_ITEM), ESSENTIA_TERMINAL = ThaumcraftApi.addShapelessArcaneCraftingRecipe("ESSENTIATERMINAL", stack(ModItems.ESSENTIA_TERMINAL_ITEM),
new AspectList().add(Aspect.WATER, 5).add(Aspect.ORDER, 2).add(Aspect.FIRE, 1), new AspectList().add(Aspect.WATER, 5).add(Aspect.ORDER, 2).add(Aspect.FIRE, 1),
//'ae2:semi_dark_monitor' 'ae2:monitor' 'ae2:dark_monitor'三者任一 MONITORS,
ae("monitor"),
stack(ModItems.DIFFUSION_CORE),
stack(ModItems.COALESCENCE_CORE),
ae("logic_processor"),
tc("vis_filter"));
ThaumcraftApi.addShapelessArcaneCraftingRecipe("ESSENTIATERMINAL", stack(ModItems.ESSENTIA_TERMINAL_ITEM),
new AspectList().add(Aspect.WATER, 5).add(Aspect.ORDER, 2).add(Aspect.FIRE, 1),
//'ae2:semi_dark_monitor' 'ae2:monitor' 'ae2:dark_monitor'三者任一
ae("dark_monitor"),
stack(ModItems.DIFFUSION_CORE),
stack(ModItems.COALESCENCE_CORE),
ae("logic_processor"),
tc("vis_filter"));
ThaumcraftApi.addShapelessArcaneCraftingRecipe("ESSENTIATERMINAL", stack(ModItems.ESSENTIA_TERMINAL_ITEM),
new AspectList().add(Aspect.WATER, 5).add(Aspect.ORDER, 2).add(Aspect.FIRE, 1),
//'ae2:semi_dark_monitor' 'ae2:monitor' 'ae2:dark_monitor'三者任一
ae("semi_dark_monitor"),
stack(ModItems.DIFFUSION_CORE), stack(ModItems.DIFFUSION_CORE),
stack(ModItems.COALESCENCE_CORE), stack(ModItems.COALESCENCE_CORE),
ae("logic_processor"), ae("logic_processor"),
@@ -1,43 +0,0 @@
package thaumicenergistics.common.features;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import thaumicenergistics.ThaumicEnergistics;
import thaumicenergistics.config.ThEConfig;
import java.util.function.Supplier;
/**
* 所有功能模块的基类。每个功能可独立启停。
* 自 1.7.10 ThEFeatureBase 移植。
*/
public abstract class ThEFeatureBase {
private final String name;
protected boolean enabled;
protected ThEFeatureBase(String name) {
this.name = name;
this.enabled = ThEConfig.isFeatureEnabled(name);
}
public final String getName() { return name; }
public final boolean isEnabled() { return enabled; }
/** 模组构造期间调用,用于注册物品与方块。 */
public void register() {
if (!enabled) return;
ThaumicEnergistics.LOG.info("Feature [{}] loading...", name);
doRegister();
}
/** 所有功能注册完成后调用,用于跨功能设置。 */
public void postInit() {
if (!enabled) return;
doPostInit();
}
/** 覆写以注册本功能特有的方块/物品。 */
protected abstract void doRegister();
/** 覆写以进行注册后设置(配方、研究等)。 */
protected void doPostInit() {}
}
@@ -1,22 +0,0 @@
package thaumicenergistics.common.grid;
/**
* 表示连接到 AE2 网格的部件。
* 对应 1.7.10 AEPartGridBlock——为 1.21.1 简化。
* TODO: 通过 AE2 19.x API 完整连接 IGridNode。
*/
public class AEPartGridBlock {
private final Object part; // 占位 PartBase 或 IPartItem
public AEPartGridBlock(Object part) { this.part = part; }
public double getIdlePowerUsage() {
// TODO: Delegate to part
return 1.0;
}
public Object getGridNode() {
// TODO: AE2 IGridNode
return null;
}
}
@@ -4,7 +4,6 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import thaumcraft.api.ThaumcraftApi;
import thaumcraft.api.aspects.Aspect; import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList; import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.events.ResearchCompletedEvent; import thaumcraft.api.events.ResearchCompletedEvent;
@@ -60,8 +59,6 @@ public final class ThEThaumcraft {
ResourceLocation.fromNamespaceAndPath(MODID, "textures/research/tab_icon.png"), ResourceLocation.fromNamespaceAndPath(MODID, "textures/research/tab_icon.png"),
ResourceLocation.fromNamespaceAndPath(MODID, "textures/research/research_background.png")); ResourceLocation.fromNamespaceAndPath(MODID, "textures/research/research_background.png"));
registerScanEvent();
// ⚠ 必须先在当前 tab 注册伪前置节点(替代 TC 原版研究), // ⚠ 必须先在当前 tab 注册伪前置节点(替代 TC 原版研究),
// 否则 setParents 跨分类引用时线画不出来。 // 否则 setParents 跨分类引用时线画不出来。
registerPseudoParents(); registerPseudoParents();
@@ -69,45 +66,25 @@ public final class ThEThaumcraft {
// 注册事件监听:当 TC 原版研究解锁时,自动 complete 对应伪前置节点 // 注册事件监听:当 TC 原版研究解锁时,自动 complete 对应伪前置节点
registerPseudoSync(); registerPseudoSync();
// 严格按照 1.7.10 FeatureRegistry 构造函数中的注册顺序 // 注册顺序沿袭 1.7.10 移植(决定研究 tab 内节点坐标布局),勿随意调整。
// 1. FeatureThaumicEnergistics → BASEENERGISTICS (0,0)
registerBaseEnergistics(); registerBaseEnergistics();
// 2. FeatureAutocrafting_Arcane → ARCANE_ASSEMBLER + KNOWLEDGE_INSCRIBER
registerArcaneAssembler(); registerArcaneAssembler();
registerKnowledgeInscriber(); registerKnowledgeInscriber();
// 3. FeatureCells → ESSENTIASTORAGE (0,2) 向左延伸 1k/4k/16k/64k
registerEssentiaStorage(); registerEssentiaStorage();
// 4. FeatureACT → ARCANECRAFTINGTERMINAL (2,-1)
registerArcaneCraftingTerminal(); registerArcaneCraftingTerminal();
// 5. FeatureVisRelayInterface → VISINTERFACE (4,-1)
registerVisInterface(); registerVisInterface();
// 6. FeatureEssentiaIOBuses → ESSENTIABUSES (-2,-2)
registerEssentiaBuses(); registerEssentiaBuses();
// 7. FeatureInfusionProvider → INFUSIONPROVIDER (-5,-2)
registerInfusionProvider(); registerInfusionProvider();
// 8. FeatureEssentiaProvider → ESSENTIAPROVIDER (-2,-4)
registerEssentiaProvider(); registerEssentiaProvider();
// 9. FeatureEssentiaMonitoring → ESSENTIATERMINAL (-1,-4)
registerEssentiaTerminal(); registerEssentiaTerminal();
// 10. FeatureConversionCores → DIGISENTIA (0,-2)
registerDigisentia(); registerDigisentia();
// 12. FeatureWrenchFocus → FOCUS_AEWRENCH (-3,-7)
registerFocusAEWrench(); registerFocusAEWrench();
// 13. FeatureQuartzDupe → CERTUS_DUPE (-5,-5)
registerCertusDupe(); registerCertusDupe();
// 14. FeatureEssentiaVibrationChamber → VIBRATIONCHAMBER (1,-4)
registerEssentiaVibrationChamber(); registerEssentiaVibrationChamber();
// 15. FeatureAutocrafting_Essentia → DISTILLATIONENCODER (-4,-4)
registerDistillationEncoder(); registerDistillationEncoder();
// 16. FeatureGolemBackpack → GOLEMWIFIBACKPACK (0,-6)
registerGolemWifiBackpack(); registerGolemWifiBackpack();
LOG.info("ThaumicEnergistics research registered ({} nodes).", 13); LOG.info("ThaumicEnergistics research registered.");
}
private static void registerScanEvent() {
ThaumcraftApi.registerScanEventhandler((scanner, level, player) ->
java.util.Optional.empty());
} }
// ==================== 伪前置节点(跨分类引用 TC 原版研究) ==================== // ==================== 伪前置节点(跨分类引用 TC 原版研究) ====================
@@ -5,24 +5,38 @@ import java.util.List;
import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import appeng.api.implementations.items.IMemoryCard;
import appeng.api.implementations.items.MemoryCardMessages;
import appeng.api.ids.AEComponents;
import appeng.api.inventories.InternalInventory; import appeng.api.inventories.InternalInventory;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridNode;
import appeng.api.networking.ticking.IGridTickable;
import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest;
import appeng.api.parts.IPartItem; import appeng.api.parts.IPartItem;
import appeng.api.parts.IPartModel; import appeng.api.parts.IPartModel;
import appeng.core.AppEng; import appeng.core.AppEng;
import appeng.items.parts.PartModels; import appeng.items.parts.PartModels;
import appeng.me.service.P2PService;
import appeng.menu.locator.MenuLocators; import appeng.menu.locator.MenuLocators;
import appeng.menu.MenuOpener; import appeng.menu.MenuOpener;
import appeng.parts.PartModel; import appeng.parts.PartModel;
import appeng.parts.p2p.P2PTunnelPart;
import appeng.parts.reporting.AbstractTerminalPart; import appeng.parts.reporting.AbstractTerminalPart;
import appeng.util.inv.AppEngInternalInventory; import appeng.util.inv.AppEngInternalInventory;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.common.items.TCFunctionalItems;
import thaumicenergistics.ThaumicEnergistics; import thaumicenergistics.ThaumicEnergistics;
import thaumicenergistics.common.integration.tc.TCReflection;
import thaumicenergistics.init.ModMenuTypes; import thaumicenergistics.init.ModMenuTypes;
public class ArcaneCraftingTerminalPart extends AbstractTerminalPart { public class ArcaneCraftingTerminalPart extends AbstractTerminalPart implements IGridTickable {
public static final ResourceLocation INV_CRAFTING = AppEng.makeId("arcane_crafting_terminal_crafting"); public static final ResourceLocation INV_CRAFTING = AppEng.makeId("arcane_crafting_terminal_crafting");
public static final ResourceLocation INV_WAND = ThaumicEnergistics.id("arcane_crafting_terminal_wand"); public static final ResourceLocation INV_WAND = ThaumicEnergistics.id("arcane_crafting_terminal_wand");
@@ -42,12 +56,22 @@ public class ArcaneCraftingTerminalPart extends AbstractTerminalPart {
public static final int WAND_SLOT_INDEX = 0; public static final int WAND_SLOT_INDEX = 0;
/** 充能间隔:每 tick 抽取一次。与 TC 能量节点池子每 tick 重置的频率、原版充能中继一致;无需放大。 */
private static final int VIS_REPLENISH_INTERVAL = 1;
/** 每 tick 每要素最大充能 cV,与原版奥术工作台充能中继(MagicWorkbenchCharger)一致(5 cV/tick = 1 vis/s)。 */
private static final int MAX_CVIS_PER_TICK = 5;
private static final String NBT_KEY_VIS_SOURCE_FREQ = "visSourceFreq";
/** 内存卡设定的 vis 源 P2P 频率;0 = 未设置(不自动充能)。 */
private short visSourceFreq = 0;
private final AppEngInternalInventory craftingGrid = new AppEngInternalInventory(this, 9); private final AppEngInternalInventory craftingGrid = new AppEngInternalInventory(this, 9);
private final AppEngInternalInventory wandInv = new AppEngInternalInventory(this, 1); private final AppEngInternalInventory wandInv = new AppEngInternalInventory(this, 1);
public ArcaneCraftingTerminalPart(IPartItem<?> partItem) { public ArcaneCraftingTerminalPart(IPartItem<?> partItem) {
super(partItem); super(partItem);
this.getMainNode().setIdlePowerUsage(0.5); this.getMainNode().setIdlePowerUsage(0.5);
this.getMainNode().addService(IGridTickable.class, this);
} }
@Override @Override
@@ -63,6 +87,88 @@ public class ArcaneCraftingTerminalPart extends AbstractTerminalPart {
return true; return true;
} }
/**
* 内存卡右键终端:读取 Vis Interface 的 P2P 频率,设为法杖充能的 vis 源。
* 复刻奥术装配器 {@code TileArcaneAssembler.onMemoryCardActivate} 的行为:
* 卡上带 P2P 频率(从 vis_interface shift+右键复制来的)→ 设为 vis 源;
* 空白卡 → 清空;其它 → 交给 AE2 标准内存卡逻辑。
*/
@Override
public boolean onUseItemOn(ItemStack heldItem, Player player, InteractionHand hand, Vec3 pos) {
if (heldItem.getItem() instanceof IMemoryCard memoryCard) {
Short freq = heldItem.get(AEComponents.EXPORTED_P2P_FREQUENCY);
if (freq != null) {
this.visSourceFreq = freq;
getHost().markForSave();
memoryCard.notifyUser(player, MemoryCardMessages.SETTINGS_LOADED);
return true;
} else if (heldItem.get(AEComponents.EXPORTED_SETTINGS_SOURCE) == null) {
// 空白卡 → 清空 vis 源
if (this.visSourceFreq != 0) {
this.visSourceFreq = 0;
getHost().markForSave();
}
memoryCard.notifyUser(player, MemoryCardMessages.SETTINGS_CLEARED);
return true;
}
}
return super.onUseItemOn(heldItem, player, hand, pos);
}
// ===== 法杖自动充能(内存卡链接 Vis Interface 作为 vis 源) =====
@Override
public TickingRequest getTickingRequest(IGridNode node) {
return new TickingRequest(VIS_REPLENISH_INTERVAL, VIS_REPLENISH_INTERVAL, false);
}
@Override
public TickRateModulation tickingRequest(IGridNode node, int ticksSinceLastCall) {
if (visSourceFreq == 0) {
return TickRateModulation.SAME;
}
ItemStack wandStack = wandInv.getStackInSlot(0);
if (wandStack.isEmpty() || !(wandStack.getItem() instanceof TCFunctionalItems.WandCastingItem wand)) {
return TickRateModulation.SAME;
}
IGrid grid = node.getGrid();
if (grid == null) {
return TickRateModulation.SAME;
}
P2PService p2p = P2PService.get(grid);
if (p2p == null) {
return TickRateModulation.SAME;
}
P2PTunnelPart<?> input = p2p.getInput(visSourceFreq);
if (!(input instanceof VisInterfacePart visSource)) {
return TickRateModulation.SAME;
}
boolean changed = false;
int maxVis = wand.getMaxVis(wandStack);
for (Aspect primal : Aspect.getPrimalAspects()) {
int needed = maxVis - wand.getVis(wandStack, primal);
if (needed <= 0) {
continue;
}
ResourceLocation id = TCReflection.getAspectId(primal);
if (id == null) {
continue;
}
// 每 tick 申请真实量(与池子每 tick 重置对齐),充入真实量,vis 守恒
int got = visSource.consumeVis(id, Math.min(MAX_CVIS_PER_TICK, needed));
if (got > 0) {
wand.addRealVis(wandStack, primal, got, true);
changed = true;
}
}
if (changed) {
// 法杖 vis 存储在 ItemStack NBT,手动标记保存
getHost().markForSave();
}
return TickRateModulation.SAME;
}
@Override @Override
public MenuType<?> getMenuType(Player player) { public MenuType<?> getMenuType(Player player) {
return ModMenuTypes.ARCANE_CRAFTING_TERMINAL.get(); return ModMenuTypes.ARCANE_CRAFTING_TERMINAL.get();
@@ -95,6 +201,7 @@ public class ArcaneCraftingTerminalPart extends AbstractTerminalPart {
super.readFromNBT(data, registries); super.readFromNBT(data, registries);
this.craftingGrid.readFromNBT(data, "craftingGrid", registries); this.craftingGrid.readFromNBT(data, "craftingGrid", registries);
this.wandInv.readFromNBT(data, "wandInv", registries); this.wandInv.readFromNBT(data, "wandInv", registries);
this.visSourceFreq = data.contains(NBT_KEY_VIS_SOURCE_FREQ) ? data.getShort(NBT_KEY_VIS_SOURCE_FREQ) : 0;
} }
@Override @Override
@@ -102,6 +209,9 @@ public class ArcaneCraftingTerminalPart extends AbstractTerminalPart {
super.writeToNBT(data, registries); super.writeToNBT(data, registries);
this.craftingGrid.writeToNBT(data, "craftingGrid", registries); this.craftingGrid.writeToNBT(data, "craftingGrid", registries);
this.wandInv.writeToNBT(data, "wandInv", registries); this.wandInv.writeToNBT(data, "wandInv", registries);
if (visSourceFreq != 0) {
data.putShort(NBT_KEY_VIS_SOURCE_FREQ, visSourceFreq);
}
} }
@Override @Override
@@ -16,7 +16,6 @@ import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.Container;
import net.minecraft.world.SimpleContainer; import net.minecraft.world.SimpleContainer;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
@@ -47,7 +46,6 @@ import appeng.api.util.AECableType;
import thaumcraft.api.IVisDiscountGear; import thaumcraft.api.IVisDiscountGear;
import thaumcraft.api.IWarpingGear; import thaumcraft.api.IWarpingGear;
import thaumcraft.api.ThaumcraftApi;
import thaumcraft.api.aspects.Aspect; import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList; import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.crafting.IArcaneRecipe; import thaumcraft.api.crafting.IArcaneRecipe;
@@ -68,6 +66,8 @@ public class TileArcaneAssembler extends ThETileBase
Aspect.EARTH, Aspect.ORDER, Aspect.ENTROPY Aspect.EARTH, Aspect.ORDER, Aspect.ENTROPY
}; };
/** 基础 vis 折扣(0.8 = 80% 成本)。calculateVisDiscounts 从该值起再减护甲折扣;无护甲时即此值。 */
private static final float BASE_VIS_DISCOUNT = 0.8F;
private static final int CVIS_MULTIPLIER = 10; private static final int CVIS_MULTIPLIER = 10;
private static final int MAX_STORED_CVIS = 187 * CVIS_MULTIPLIER; private static final int MAX_STORED_CVIS = 187 * CVIS_MULTIPLIER;
private static final int BASE_TICKS_PER_CRAFT = 20; private static final int BASE_TICKS_PER_CRAFT = 20;
@@ -152,7 +152,7 @@ public class TileArcaneAssembler extends ThETileBase
actionSource = IActionSource.ofMachine(this); actionSource = IActionSource.ofMachine(this);
for (Aspect primal : PRIMALS) { for (Aspect primal : PRIMALS) {
visDiscount.put(primal, 0.8F); visDiscount.put(primal, BASE_VIS_DISCOUNT);
} }
} }
@@ -392,7 +392,7 @@ public class TileArcaneAssembler extends ThETileBase
private int getRequiredCvisForAspect(Aspect aspect) { private int getRequiredCvisForAspect(Aspect aspect) {
if (currentRecipeAspects == null) return 0; if (currentRecipeAspects == null) return 0;
int baseCost = currentRecipeAspects.getAmount(aspect) * CVIS_MULTIPLIER; int baseCost = currentRecipeAspects.getAmount(aspect) * CVIS_MULTIPLIER;
float discount = visDiscount.getOrDefault(aspect, 1.0F); float discount = visDiscount.getOrDefault(aspect, BASE_VIS_DISCOUNT);
return Math.max(0, Math.round(baseCost * discount)); return Math.max(0, Math.round(baseCost * discount));
} }
@@ -402,7 +402,7 @@ public class TileArcaneAssembler extends ThETileBase
private void calculateVisDiscounts() { private void calculateVisDiscounts() {
for (Aspect primal : PRIMALS) { for (Aspect primal : PRIMALS) {
float discount = 0.8F; float discount = BASE_VIS_DISCOUNT;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
ItemStack armor = internalInventory.getItem(ARMOR_SLOT_START + i); ItemStack armor = internalInventory.getItem(ARMOR_SLOT_START + i);
@@ -536,21 +536,6 @@ public class TileArcaneAssembler extends ThETileBase
return !isCrafting; return !isCrafting;
} }
@Nullable
public IArcaneRecipe findMatchingArcaneRecipe(Container craftingGrid) {
if (level == null) return null;
for (Object recipeObj : ThaumcraftApi.getCraftingRecipes()) {
if (recipeObj instanceof IArcaneRecipe recipe) {
try {
if (recipe.matches(craftingGrid, level, null)) {
return recipe;
}
} catch (Exception ignored) {}
}
}
return null;
}
public boolean isCrafting() { return isCrafting; } public boolean isCrafting() { return isCrafting; }
public int getSpeedUpgrades() { return speedUpgrades; } public int getSpeedUpgrades() { return speedUpgrades; }
public int getCraftTickCounter() { return craftTickCounter; } public int getCraftTickCounter() { return craftTickCounter; }
@@ -561,7 +546,7 @@ public class TileArcaneAssembler extends ThETileBase
} }
public AspectList getStoredVis() { return storedVis; } public AspectList getStoredVis() { return storedVis; }
public SimpleContainer getInternalInventory() { return internalInventory; } public SimpleContainer getInternalInventory() { return internalInventory; }
public float getVisDiscountForAspect(Aspect aspect) { return visDiscount.getOrDefault(aspect, 1.0F); } public float getVisDiscountForAspect(Aspect aspect) { return visDiscount.getOrDefault(aspect, BASE_VIS_DISCOUNT); }
public float getWarpPowerMultiplier() { return warpPowerMultiplier; } public float getWarpPowerMultiplier() { return warpPowerMultiplier; }
public void setSpeedUpgrades(int count) { public void setSpeedUpgrades(int count) {
@@ -1,10 +1,7 @@
package thaumicenergistics.config; package thaumicenergistics.config;
import java.util.Set;
public final class ThEConfig { public final class ThEConfig {
private ThEConfig() {} private ThEConfig() {}
public static final double EVC_POWER_PER_TICK = 5.0; public static final double EVC_POWER_PER_TICK = 5.0;
public static final int CELL_1K = 1024, CELL_4K = 4096, CELL_16K = 16384, CELL_64K = 65536; public static final int CELL_1K = 1024, CELL_4K = 4096, CELL_16K = 16384, CELL_64K = 65536;
public static final int CELL_MAX_TYPES = 12; public static final int CELL_MAX_TYPES = 12;
private static final Set<String> ENABLED = Set.of("cells","io_buses","monitoring","arcane_crafting_terminal","essentia_provider","infusion_provider","vibration_chamber","vis_interface","golem_backpack");
public static boolean isFeatureEnabled(String n) { return ENABLED.contains(n); }
} }
@@ -49,16 +49,8 @@
"tc.research_name.DIGISENTIA": "Digitized Essentia", "tc.research_name.DIGISENTIA": "Digitized Essentia",
"tc.research_text.DIGISENTIA.stage.1": "Though essentia is a mystical substance, you have discovered it can be processed using AE's digital technology. The key lies in two cores: a Diffusion Core to decompose essentia into digital signals, and a Coalescence Core to reassemble digital signals back into essentia.", "tc.research_text.DIGISENTIA.stage.1": "Though essentia is a mystical substance, you have discovered it can be processed using AE's digital technology. The key lies in two cores: a Diffusion Core to decompose essentia into digital signals, and a Coalescence Core to reassemble digital signals back into essentia.",
"tc.research_text.DIGISENTIA.stage.2": "You have successfully crafted the Diffusion Core and Coalescence Core. They will serve as the foundation of your entire Thaumic Energistics system.", "tc.research_text.DIGISENTIA.stage.2": "You have successfully crafted the Diffusion Core and Coalescence Core. They will serve as the foundation of your entire Thaumic Energistics system.",
"tc.research_name.ESSENTIASTORAGE1K": "Essentia Storage: 1k",
"tc.research_text.ESSENTIASTORAGE1K": "Using the Coalescence Core and wisp essences, you can create ME storage cells capable of storing essentia. The 1k cell is the most basic model, holding a modest amount of a single essentia type.",
"tc.research_name.ESSENTIASTORAGE": "Essentia Storage", "tc.research_name.ESSENTIASTORAGE": "Essentia Storage",
"tc.research_text.ESSENTIASTORAGE": "Using Coalescence Cores and wisp essences, you can create ME storage cells capable of storing essentia. Available in 1k, 4k, 16k, and 64k variants.", "tc.research_text.ESSENTIASTORAGE": "Using Coalescence Cores and wisp essences, you can create ME storage cells capable of storing essentia. Available in 1k, 4k, 16k, and 64k variants.",
"tc.research_name.ESSENTIASTORAGE4K": "Essentia Storage: 4k",
"tc.research_text.ESSENTIASTORAGE4K": "Building upon the 1k cell, you can create a larger 4k essentia storage cell.",
"tc.research_name.ESSENTIASTORAGE16K": "Essentia Storage: 16k",
"tc.research_text.ESSENTIASTORAGE16K": "The 16k essentia storage cell can hold a considerable amount of essentia.",
"tc.research_name.ESSENTIASTORAGE64K": "Essentia Storage: 64k",
"tc.research_text.ESSENTIASTORAGE64K": "The 64k essentia storage cell represents the current pinnacle of this technology, capable of storing vast quantities of essentia.",
"tc.research_name.ESSENTIABUSES": "Essentia Buses", "tc.research_name.ESSENTIABUSES": "Essentia Buses",
"tc.research_text.ESSENTIABUSES.stage.1": "Using Diffusion and Coalescence Cores, you can create three types of essentia buses: the Import Bus extracts essentia from external containers into the ME network, the Export Bus outputs essentia from the network into external containers, and the Storage Bus maps external containers as ME network storage units.", "tc.research_text.ESSENTIABUSES.stage.1": "Using Diffusion and Coalescence Cores, you can create three types of essentia buses: the Import Bus extracts essentia from external containers into the ME network, the Export Bus outputs essentia from the network into external containers, and the Storage Bus maps external containers as ME network storage units.",
"tc.research_text.ESSENTIABUSES.stage.2": "Essentia buses are the bridge between the physical world and the digital essentia realm. Attach them to an ME cable facing an essentia container to activate them.", "tc.research_text.ESSENTIABUSES.stage.2": "Essentia buses are the bridge between the physical world and the digital essentia realm. Attach them to an ME cable facing an essentia container to activate them.",
@@ -58,14 +58,6 @@
"tc.research_name.ESSENTIASTORAGE": "源质存储", "tc.research_name.ESSENTIASTORAGE": "源质存储",
"tc.research_text.ESSENTIASTORAGE": "利用凝聚核心和天域之华制造ME源质存储元件,有1k、4k、16k、64k四种容量。", "tc.research_text.ESSENTIASTORAGE": "利用凝聚核心和天域之华制造ME源质存储元件,有1k、4k、16k、64k四种容量。",
"tc.research_name.ESSENTIASTORAGE1K": "源质存储:1k",
"tc.research_text.ESSENTIASTORAGE1K": "利用凝聚核心和天域之华,你可以制造出能够存储源质的ME存储元件。1k元件是最基础的型号,可以存储少量单一类型的源质。",
"tc.research_name.ESSENTIASTORAGE4K": "源质存储:4k",
"tc.research_text.ESSENTIASTORAGE4K": "在1k元件的基础上,你可以制造容量更大的4k源质存储元件。",
"tc.research_name.ESSENTIASTORAGE16K": "源质存储:16k",
"tc.research_text.ESSENTIASTORAGE16K": "16k源质存储元件能够存储相当可观的源质。",
"tc.research_name.ESSENTIASTORAGE64K": "源质存储:64k",
"tc.research_text.ESSENTIASTORAGE64K": "64k源质存储元件是当前技术的极限,能够存储海量源质。",
"tc.research_name.ESSENTIABUSES": "源质总线", "tc.research_name.ESSENTIABUSES": "源质总线",
"tc.research_text.ESSENTIABUSES.stage.1": "通过扩散核心和凝聚核心,你可以制造出三种源质总线:输入总线从外部容器抽取源质进入ME网络,输出总线将网络中的源质输出到外部容器,存储总线则将外部容器映射为ME网络的存储单元。", "tc.research_text.ESSENTIABUSES.stage.1": "通过扩散核心和凝聚核心,你可以制造出三种源质总线:输入总线从外部容器抽取源质进入ME网络,输出总线将网络中的源质输出到外部容器,存储总线则将外部容器映射为ME网络的存储单元。",
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@@ -0,0 +1,7 @@
{
"values": [
"ae2:monitor",
"ae2:dark_monitor",
"ae2:semi_dark_monitor"
]
}