This commit is contained in:
1820982382
2026-08-03 19:25:28 +08:00
parent 7b341980bd
commit f9ddc599e1
69 changed files with 832 additions and 432 deletions
@@ -32,7 +32,7 @@ public class ContainerArcaneAssembler extends AbstractContainerMenu {
// ===== 坐标常量(1:1 对应1.7.10) =====
private static final int PLAYER_INV_X = 8;
private static final int PLAYER_INV_Y = 115;
private static final int PLAYER_INV_Y = 113;
private static final int HOTBAR_Y = PLAYER_INV_Y + 58; // 173
private static final int PATTERN_X = 26;
@@ -29,8 +29,8 @@ import java.util.List;
public class ContainerDistillationPatternEncoder extends AbstractContainerMenu {
private static final int PLAYER_INV_Y = 152;
private static final int HOTBAR_Y = 210;
private static final int PLAYER_INV_Y = 150;
private static final int HOTBAR_Y = 208;
private static final int PLAYER_INV_X = 8;
private static final int SLOT_SOURCE_X = 15;
@@ -48,8 +48,8 @@ public class ContainerEssentiaCellWorkbench extends AbstractContainerMenu {
IItemHandler cellHandler = workbench != null ? workbench.getCellInventory() : fallbackCell;
addSlot(new SlotItemHandler(cellHandler, 0, 152, 8));
for (int r = 0; r < 3; r++) for (int c = 0; c < 9; c++) addSlot(new Slot(inv, c + r * 9 + 9, 8 + c * 18, 169 + r * 18));
for (int c = 0; c < 9; c++) addSlot(new Slot(inv, c, 8 + c * 18, 227));
for (int r = 0; r < 3; r++) for (int c = 0; c < 9; c++) addSlot(new Slot(inv, c + r * 9 + 9, 8 + c * 18, 167 + r * 18));
for (int c = 0; c < 9; c++) addSlot(new Slot(inv, c, 8 + c * 18, 225));
}
/** 客户端打开菜单用(IMenuTypeExtension 注册);workbench 为 null,分区操作走 C2S 到服务端。 */
@@ -45,8 +45,8 @@ public class ContainerKnowledgeInscriber extends AbstractContainerMenu {
private static final int MAXIMUM_PATTERNS = HandlerKnowledgeCore.MAXIMUM_STORED_PATTERNS;
private static final int PLAYER_INV_Y = 162;
private static final int HOTBAR_Y = 220;
private static final int PLAYER_INV_Y = 160;
private static final int HOTBAR_Y = 218;
private static final int PLAYER_INV_X = 8;
private static final int KCORE_SLOT_X = 186;
@@ -25,7 +25,7 @@ public class GuiEssentiaCellWorkbench extends AbstractContainerScreen<ContainerE
private static final ResourceLocation TEX = ResourceLocation.fromNamespaceAndPath(ThaumicEnergistics.MODID, "textures/gui/essentia_cell_workbench.png");
private static final int GUI_WIDTH = 176, GUI_HEIGHT = 251;
/** 分区格布局常量(JEI ghost 拖拽也使用,故公开)。 */
public static final int WIDGET_POS_X = 7, WIDGET_POS_Y = 28;
public static final int WIDGET_POS_X = 8, WIDGET_POS_Y = 29;
public static final int WIDGETS_PER_ROW = 9, WIDGET_ROWS = 7, NUMBER_OF_WIDGETS = 63;
public static final int WIDGET_SIZE = 18;
@@ -50,6 +50,8 @@ public final class RecipeRegistration {
public static ShapelessArcaneRecipe ARCANE_CRAFTING_TERMINAL;
public static ShapelessArcaneRecipe VIS_INTERFACE;
public static ShapelessArcaneRecipe ESSENTIA_VIBRATION_CHAMBER;
/** 赛特斯石英复制(坩埚炼金配方——研究页关联)。 */
public static CrucibleRecipe CERTUS_DUPE_RECIPE;
private static final TagKey<Item> WISP_ESSENCES = tag("thaumicenergistics", "wisp_essences");
@@ -62,9 +64,21 @@ public final class RecipeRegistration {
registerShapedArcane();
registerShapelessArcane();
registerInfusion();
registerCrucible();
ThaumicEnergistics.LOG.info("ThaumicEnergistics recipes registered.");
}
/** 坩埚炼金配方:赛特斯石英复制(丢 1 赛特斯石英 + 水晶/交换要素 → 2 赛特斯石英)。 */
private static void registerCrucible() {
ItemStack quartz = ae("certus_quartz_crystal");
if (quartz.isEmpty()) return;
CERTUS_DUPE_RECIPE = ThaumcraftApi.addCrucibleRecipe(
"CERTUS_DUPE",
quartz.copyWithCount(2),
quartz.copyWithCount(1),
new AspectList().add(Aspect.CRYSTAL, 5).add(Aspect.EXCHANGE, 5));
}
private static void registerShapedArcane() {
STORAGE_COMPONENT_1K = ThaumcraftApi.addArcaneCraftingRecipe("ESSENTIASTORAGE1K", stack(ModItems.STORAGE_COMPONENT_1K),
new AspectList().add(Aspect.FIRE, 3).add(Aspect.ORDER, 1),
@@ -4,13 +4,14 @@ import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.jetbrains.annotations.Nullable;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.aspects.IAspectContainer;
import thaumicenergistics.ThaumicEnergistics;
import thaumcraft.common.essentia.EssentiaTransport;
import thaumicenergistics.api.storage.AspectStack;
public final class TCReflection {
@@ -18,16 +19,69 @@ public final class TCReflection {
/** aspect tag → ResourceLocation 缓存(tag 有界:6 个源质 + 已注册方面)。 */
private static final Map<String, ResourceLocation> ASPECT_ID_CACHE = new ConcurrentHashMap<>();
/** 荒古炼金炉类名(TC port;不实现 IAspectContainer,需反射抽内部源质)。 */
private static final String FURNACE_CLASS_NAME = "thaumcraft.common.blockentities.AlchemicalFurnaceBlockEntity";
/** 炼金炉 private aspects 字段(缓存 Field 避免每 tick getDeclaredField)。 */
private static volatile java.lang.reflect.Field furnaceAspectsField;
private TCReflection() {}
/** 从荒古炼金炉内部源质缓存直接抽取(替代蒸馏釜/罐子中转)。 */
@Nullable
private static AspectStack extractFromFurnace(BlockEntity be, int maxAmount) {
try {
if (furnaceAspectsField == null) {
furnaceAspectsField = be.getClass().getDeclaredField("aspects");
furnaceAspectsField.setAccessible(true);
}
AspectList furnaceAspects = (AspectList) furnaceAspectsField.get(be);
if (furnaceAspects != null && furnaceAspects.size() > 0) {
Aspect[] aspects = furnaceAspects.getAspects();
for (Aspect aspect : aspects) {
if (aspect == null) continue;
int amt = furnaceAspects.getAmount(aspect);
if (amt <= 0) continue;
int toExtract = Math.min(amt, maxAmount);
furnaceAspects.remove(aspect, toExtract);
be.setChanged();
ResourceLocation id = getAspectId(aspect);
return id != null ? new AspectStack(id, toExtract) : null;
}
}
} catch (Exception ignored) {
}
return null;
}
@Nullable
public static AspectStack extractEssentia(@Nullable BlockEntity be, int maxAmount) {
if (be == null) {
ThaumicEnergistics.LOG.debug("[TCReflection] extractEssentia: be is null");
return null;
}
// ===== 路径0: 荒古炼金炉直连(AlchemicalFurnaceBlockEntity 不实现 IAspectContainer,
// 源质在 private aspects 缓存——直接抽取,替代"必须经蒸馏釜/罐子")=====
if (FURNACE_CLASS_NAME.equals(be.getClass().getName())) {
AspectStack fromFurnace = extractFromFurnace(be, maxAmount);
if (fromFurnace != null) return fromFurnace;
}
// ===== 路径0b: TC 管道接口(EssentiaTransport——高级荒古炼金炉喷嘴/源质管道)=====
if (be instanceof EssentiaTransport transport) {
for (Direction face : Direction.values()) {
if (!transport.canOutputTo(face)) continue;
Aspect aspect = transport.getEssentiaType(face);
if (aspect == null) continue;
int amount = transport.getEssentiaAmount(face);
if (amount <= 0) continue;
int toExtract = Math.min(amount, maxAmount);
int taken = transport.takeEssentia(aspect, toExtract, face);
if (taken > 0) {
be.setChanged();
ResourceLocation id = getAspectId(aspect);
return id != null ? new AspectStack(id, taken) : null;
}
}
}
if (!(be instanceof IAspectContainer container)) {
ThaumicEnergistics.LOG.debug("[TCReflection] extractEssentia: {} does not implement IAspectContainer", be.getClass().getName());
return null;
}
@@ -36,7 +90,6 @@ public final class TCReflection {
if (aspectList != null && aspectList.size() > 0) {
Aspect[] aspects = aspectList.getAspects();
if (aspects != null) {
ThaumicEnergistics.LOG.debug("[TCReflection] extractEssentia: found {} aspects via getAspects()", aspects.length);
for (Aspect aspect : aspects) {
if (aspect == null) continue;
int amt = aspectList.getAmount(aspect);
@@ -45,7 +98,6 @@ public final class TCReflection {
if (container.takeFromContainer(aspect, toExtract)) {
be.setChanged();
ResourceLocation id = getAspectId(aspect);
ThaumicEnergistics.LOG.debug("[TCReflection] extractEssentia: SUCCESS (API) - extracted {} of {}", toExtract, id);
return id != null ? new AspectStack(id, toExtract) : null;
}
}
@@ -53,7 +105,6 @@ public final class TCReflection {
}
// ===== 路径B: TC 移植版反射回退 (getAspect/getAmount) =====
ThaumicEnergistics.LOG.debug("[TCReflection] extractEssentia: getAspects() empty, trying reflection fallback for {}", be.getClass().getName());
try {
java.lang.reflect.Method[] methods = getAspectMethods(be.getClass());
if (methods.length < 2) {
@@ -66,18 +117,12 @@ public final class TCReflection {
if (container.takeFromContainer(aspect, toExtract)) {
be.setChanged();
ResourceLocation id = getAspectId(aspect);
ThaumicEnergistics.LOG.debug("[TCReflection] extractEssentia: SUCCESS (reflection) - extracted {} of {}", toExtract, id);
return id != null ? new AspectStack(id, toExtract) : null;
}
ThaumicEnergistics.LOG.debug("[TCReflection] extractEssentia: takeFromContainer returned false for {} of {}", toExtract, aspect.getTag());
} else {
ThaumicEnergistics.LOG.debug("[TCReflection] extractEssentia: reflection got aspect={}, amount={}", aspect, amount);
}
} catch (Exception e) {
ThaumicEnergistics.LOG.debug("[TCReflection] extractEssentia: reflection fallback error: {}", e.getMessage());
} catch (Exception ignored) {
}
ThaumicEnergistics.LOG.debug("[TCReflection] extractEssentia: no extractable aspect found");
return null;
}
@@ -96,10 +141,8 @@ public final class TCReflection {
Aspect aspect = findAspectById(stack.aspectId());
if (aspect == null) return 0;
int toInsert = (int) stack.amount();
ThaumicEnergistics.LOG.debug("[TCReflection] insertEssentia: inserting {} of {} into {}", toInsert, stack.aspectId(), be.getClass().getName());
int leftover = container.addToContainer(aspect, toInsert);
int added = toInsert - leftover;
ThaumicEnergistics.LOG.debug("[TCReflection] insertEssentia: added={}, leftover={}", added, leftover);
if (added > 0) {
be.setChanged();
}
@@ -58,7 +58,7 @@ public final class ThEThaumcraft {
ResearchCategories.registerCategory(TAB,
ResourceLocation.fromNamespaceAndPath(MODID, "textures/research/tab_icon.png"),
ResourceLocation.fromNamespaceAndPath("thaumcraft", "textures/gui/gui_researchback.png"));
ResourceLocation.fromNamespaceAndPath(MODID, "textures/research/research_background.png"));
registerScanEvent();
@@ -346,7 +346,9 @@ public final class ThEThaumcraft {
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"))
.setPages(
new ResearchPage("tc.research_text.CERTUS_DUPE"),
new ResearchPage(RecipeRegistration.CERTUS_DUPE_RECIPE))
.registerResearchItem();
}
@@ -83,9 +83,10 @@ public class EssentiaExportBusPart extends IOBusPart
@Override
public void getBoxes(IPartCollisionHelper bch) {
bch.addBox(6, 6, 11, 10, 10, 13);
bch.addBox(5, 5, 13, 11, 11, 14);
bch.addBox(4, 4, 14, 12, 12, 16);
bch.addBox(4, 4, 12, 12, 12, 14);
bch.addBox(5, 5, 14, 11, 11, 15);
bch.addBox(6, 6, 15, 10, 10, 16);
bch.addBox(6, 6, 11, 10, 10, 12);
}
@Override