From 692ffb7396f1c6053d1cc158de346993fe4b8dba Mon Sep 17 00:00:00 2001 From: C-H716 <1536152356@qq.com> Date: Fri, 29 Aug 2025 13:35:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DScaledProcessingPattern?= =?UTF-8?q?=E6=9C=AA=E6=8C=89=E7=85=A7=E5=AE=9E=E9=99=85=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E9=87=8F=E7=BC=A9=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- gradle.properties | 2 +- .../CraftingServiceGetProvidersMixin.java | 1 - .../autopattern/CraftingTreeNodeMixin.java | 30 ++++++++ .../autopattern/CraftingTreeProcessMixin.java | 62 ++++++++++------ ...ernProviderLogicContainsRedirectMixin.java | 3 +- .../extendedae_plus/util/PatternScaler.java | 17 ++--- .../util/RequestedAmountHolder.java | 71 +++++++++++++++++++ .../resources/extendedae_plus.mixins.json | 3 +- 9 files changed, 155 insertions(+), 36 deletions(-) create mode 100644 src/main/java/com/extendedae_plus/mixin/autopattern/CraftingTreeNodeMixin.java rename src/main/java/com/extendedae_plus/mixin/{ae2 => autopattern}/PatternProviderLogicContainsRedirectMixin.java (89%) create mode 100644 src/main/java/com/extendedae_plus/util/RequestedAmountHolder.java diff --git a/build.gradle b/build.gradle index d31f0f1..a3e41cd 100644 --- a/build.gradle +++ b/build.gradle @@ -103,7 +103,7 @@ dependencies { modCompileOnly "curse.maven:just-enough-characters-250702:6680042" //mae2 - modRuntimeOnly "curse.maven:modern-ae2-additions-1028068:6342203" +// modRuntimeOnly "curse.maven:modern-ae2-additions-1028068:6342203" modCompileOnly "curse.maven:modern-ae2-additions-1028068:6342203" } diff --git a/gradle.properties b/gradle.properties index d28f3d4..b3b0a9f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G loom.platform = forge # Mod properties -mod_version = 1.3.3 +mod_version = 1.3.4-beta maven_group = com.extendedae_plus archives_name = extendedae_plus diff --git a/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingServiceGetProvidersMixin.java b/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingServiceGetProvidersMixin.java index fc6ea61..5604bbb 100644 --- a/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingServiceGetProvidersMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingServiceGetProvidersMixin.java @@ -20,7 +20,6 @@ public class CraftingServiceGetProvidersMixin { IPatternDetails base = null; if (original instanceof ScaledProcessingPattern scaledProcessingPattern) { base = scaledProcessingPattern.getOriginal(); - System.out.println("[extendedae_plus] CraftingService.getProviders mixin invoked for: " + base); } return base == null ? original : base; } diff --git a/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingTreeNodeMixin.java b/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingTreeNodeMixin.java new file mode 100644 index 0000000..d792687 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingTreeNodeMixin.java @@ -0,0 +1,30 @@ +package com.extendedae_plus.mixin.autopattern; + +import appeng.api.stacks.KeyCounter; +import appeng.crafting.CraftingTreeNode; +import appeng.crafting.inv.CraftingSimulationState; +import com.extendedae_plus.util.RequestedAmountHolder; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(value = CraftingTreeNode.class,remap = false) +public class CraftingTreeNodeMixin { + @Inject(method = "request(Lappeng/crafting/inv/CraftingSimulationState;JLappeng/api/stacks/KeyCounter;)V", + at = @At(value = "INVOKE", + target = "Lappeng/crafting/CraftingTreeNode;addContainerItems(Lappeng/api/stacks/AEKey;JLappeng/api/stacks/KeyCounter;)V"), + locals = LocalCapture.CAPTURE_FAILHARD) + private void captureRequestedAmount(CraftingSimulationState inv, long requestedAmount, KeyCounter containerItems, CallbackInfo ci) { + // push the requestedAmount before addContainerItems is called + RequestedAmountHolder.push(requestedAmount); + } + + @Inject(method = "request(Lappeng/crafting/inv/CraftingSimulationState;JLappeng/api/stacks/KeyCounter;)V", + at = @At(value = "RETURN")) + private void clearRequestedAmountOnReturn(CraftingSimulationState inv, long requestedAmount, KeyCounter containerItems, CallbackInfo ci) { + // pop the pushed requested amount on return + RequestedAmountHolder.pop(); + } +} diff --git a/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingTreeProcessMixin.java b/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingTreeProcessMixin.java index cada53a..5a1e0aa 100644 --- a/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingTreeProcessMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/autopattern/CraftingTreeProcessMixin.java @@ -1,34 +1,52 @@ package com.extendedae_plus.mixin.autopattern; +import appeng.api.crafting.IPatternDetails; +import appeng.api.networking.crafting.ICraftingService; +import appeng.api.stacks.AEKey; +import appeng.crafting.CraftBranchFailure; +import appeng.crafting.CraftingCalculation; +import appeng.crafting.CraftingTreeNode; import appeng.crafting.CraftingTreeProcess; +import appeng.crafting.inv.CraftingSimulationState; +import appeng.crafting.pattern.AEProcessingPattern; +import com.extendedae_plus.util.PatternScaler; +import com.extendedae_plus.util.RequestedAmountHolder; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import static com.extendedae_plus.util.ExtendedAELogger.LOGGER; /** * 注入 CraftingTreeProcess 构造器尾部:将 AEProcessingPattern 替换为 ScaledProcessingPattern * 以确保后续执行使用放大后的输入/输出视图。 */ @Mixin(CraftingTreeProcess.class) -public class CraftingTreeProcessMixin { +public abstract class CraftingTreeProcessMixin { -// @ModifyVariable(method = "(Lappeng/api/networking/crafting/ICraftingService;Lappeng/crafting/CraftingCalculation;Lappeng/api/crafting/IPatternDetails;Lappeng/crafting/CraftingTreeNode;)V", -// at = @At("HEAD"), argsOnly = true) -// private static IPatternDetails extendedae_plus$replaceDetailsAtHead(IPatternDetails original, ICraftingService cc, CraftingCalculation job, IPatternDetails details, CraftingTreeNode craftingTreeNode) { -// try { -// if (!(details instanceof AEProcessingPattern proc)) return original; -// -// CraftingCalculationAccessor jobAcc = (CraftingCalculationAccessor) job; -// long requested = jobAcc.extendedae_plus$getRequestedAmount(); -// -// CraftingTreeNodeAccessor parentAcc = (CraftingTreeNodeAccessor) craftingTreeNode; -// AEKey parentTarget = parentAcc.extendedae_plus$getWhat(); -// -// System.out.println("[extendedae_plus] Replacing constructor details at HEAD for: " + parentTarget + " x " + requested); -// -// return PatternScaler.scale(proc, parentTarget, requested); -// } catch (Exception e) { -// System.err.println("[extendedae_plus] Error replacing pattern at HEAD: " + e.getMessage()); -// e.printStackTrace(); -// return original; -// } -// } + @Shadow abstract void request(CraftingSimulationState inv, long times) throws CraftBranchFailure, InterruptedException; + + @ModifyVariable( + method = "(Lappeng/api/networking/crafting/ICraftingService;Lappeng/crafting/CraftingCalculation;Lappeng/api/crafting/IPatternDetails;Lappeng/crafting/CraftingTreeNode;)V", + at = @At("HEAD"), + argsOnly = true + ) + private static IPatternDetails extendedae_plus$replaceDetailsAtHead(IPatternDetails original, ICraftingService cc, CraftingCalculation job, IPatternDetails details, CraftingTreeNode craftingTreeNode) { + try { + if (!(details instanceof AEProcessingPattern proc)) return original; + + CraftingTreeNodeAccessor parentAcc = (CraftingTreeNodeAccessor) craftingTreeNode; + AEKey parentTarget = parentAcc.extendedae_plus$getWhat(); + long requested = RequestedAmountHolder.get(); + // 记录所使用的请求数量和当前线程堆栈快照,便于诊断 PatternScaler.scale 使用了哪个值以及何时清理 + LOGGER.info("[extendedae_plus] 在 CraftingTreeProcess 构造中使用请求数量: {} ; stackDepth={} ; stackSnapshot={}", requested, RequestedAmountHolder.depth(), RequestedAmountHolder.snapshot()); + // 使用当前线程栈顶的值进行缩放,不在此处清理;构造完成后应该由调用方的 pop 恢复状态 + return PatternScaler.scale(proc, parentTarget, requested); + } catch (Exception e) { + LOGGER.warn("构建倍增样板出错", e); + e.printStackTrace(); + return original; + } + } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderLogicContainsRedirectMixin.java b/src/main/java/com/extendedae_plus/mixin/autopattern/PatternProviderLogicContainsRedirectMixin.java similarity index 89% rename from src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderLogicContainsRedirectMixin.java rename to src/main/java/com/extendedae_plus/mixin/autopattern/PatternProviderLogicContainsRedirectMixin.java index ec589d9..2bb8107 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderLogicContainsRedirectMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/autopattern/PatternProviderLogicContainsRedirectMixin.java @@ -1,4 +1,4 @@ -package com.extendedae_plus.mixin.ae2; +package com.extendedae_plus.mixin.autopattern; import appeng.api.crafting.IPatternDetails; import appeng.helpers.patternprovider.PatternProviderLogic; @@ -26,7 +26,6 @@ public class PatternProviderLogicContainsRedirectMixin { if (o instanceof ScaledProcessingPattern scaled) { IPatternDetails base = scaled.getOriginal(); if (base != null && list.indexOf(base) != -1) { - System.out.println("[extendedae_plus] contains-redirect: matched base pattern for scaled pattern"); return true; } } diff --git a/src/main/java/com/extendedae_plus/util/PatternScaler.java b/src/main/java/com/extendedae_plus/util/PatternScaler.java index 13712e9..46abac6 100644 --- a/src/main/java/com/extendedae_plus/util/PatternScaler.java +++ b/src/main/java/com/extendedae_plus/util/PatternScaler.java @@ -8,6 +8,8 @@ import com.extendedae_plus.content.ScaledProcessingPattern; import java.util.Arrays; +import static com.extendedae_plus.util.ExtendedAELogger.LOGGER; + public final class PatternScaler { private PatternScaler() { } @@ -103,14 +105,13 @@ public final class PatternScaler { /* Debug 输出 */ - System.out.println("[extendedae_plus] 正在缩放样板:"); - System.out.println(" 原始样板: " + base); - System.out.println(" 目标物品: " + target); - System.out.println(" 请求数量: " + requestedAmount); - System.out.println(" 缩放后输入: " + Arrays.toString(scaledInputs)); - System.out.println(" 缩放后输出: " + Arrays.toString(scaledCondensedOutputs)); - System.out.println(" 缩放后稀疏输入: " + Arrays.toString(scaledSparseInputs)); - System.out.println(" 缩放后稀疏输出: " + Arrays.toString(scaledSparseOutputs)); + LOGGER.info("[extendedae_plus] 正在缩放样板: 目标物品: {} 请求数量: {} 缩放后输入: {} 缩放后输出: {} 缩放后稀疏输入: {} 缩放后稀疏输出: {}", + target, + requestedAmount, + Arrays.toString(scaledInputs), + Arrays.toString(scaledCondensedOutputs), + Arrays.toString(scaledSparseInputs), + Arrays.toString(scaledSparseOutputs)); return new ScaledProcessingPattern(base, diff --git a/src/main/java/com/extendedae_plus/util/RequestedAmountHolder.java b/src/main/java/com/extendedae_plus/util/RequestedAmountHolder.java new file mode 100644 index 0000000..88336dd --- /dev/null +++ b/src/main/java/com/extendedae_plus/util/RequestedAmountHolder.java @@ -0,0 +1,71 @@ +package com.extendedae_plus.util; + +import java.util.ArrayDeque; +import java.util.Deque; +import static com.extendedae_plus.util.ExtendedAELogger.LOGGER; + +/** + * Thread-local stack holder for requested amounts to support nested requests. + */ +public final class RequestedAmountHolder { + private static final ThreadLocal> HOLDER = ThreadLocal.withInitial(ArrayDeque::new); + + private RequestedAmountHolder() { + } + + /** + * Push a requested amount onto the thread-local stack. + */ + public static void push(long v) { + Deque dq = HOLDER.get(); + dq.push(v); + LOGGER.info("[extendedae_plus] 请求数量已推入堆栈: {} ; depth={}", v, dq.size()); + } + + /** + * Pop the top value from the thread-local stack. Safe if empty. + */ + public static void pop() { + Deque dq = HOLDER.get(); + if (dq.isEmpty()) { + LOGGER.info("[extendedae_plus] 请求数量堆栈为空,无法弹出"); + return; + } + Long popped = dq.pop(); + LOGGER.info("[extendedae_plus] 请求数量已弹出堆栈: {} ; depth={}", popped, dq.size()); + } + + /** + * Peek the current requested amount or return 0 if none. + */ + public static long get() { + Deque dq = HOLDER.get(); + Long v = dq.peek(); + LOGGER.info("[extendedae_plus] 当前请求数量: {} ; depth={}", v, dq.size()); + return v == null ? 0L : v; + } + + /** + * Clear the entire stack for this thread. + */ + public static void clearAll() { + HOLDER.get().clear(); + LOGGER.info("[extendedae_plus] 请求数量堆栈已清空"); + } + + /** + * 返回当前线程堆栈深度(仅供日志/诊断使用)。 + */ + public static int depth() { + return HOLDER.get().size(); + } + + /** + * 返回当前线程堆栈的字符串表示(仅供日志/诊断使用)。 + */ + public static String snapshot() { + return HOLDER.get().toString(); + } +} + + diff --git a/src/main/resources/extendedae_plus.mixins.json b/src/main/resources/extendedae_plus.mixins.json index a5eb682..52f97e1 100644 --- a/src/main/resources/extendedae_plus.mixins.json +++ b/src/main/resources/extendedae_plus.mixins.json @@ -32,7 +32,6 @@ "ae2.MEStorageMenuMixin", "ae2.PatternEncodingTermMenuMixin", "ae2.PatternProviderLogicAdvancedMixin", - "ae2.PatternProviderLogicContainsRedirectMixin", "ae2.PatternProviderMenuAdvancedMixin", "ae2.accessor.MEStorageMenuAccessor", "ae2.accessor.PatternEncodingTermMenuAccessor", @@ -43,7 +42,9 @@ "autopattern.CraftingCalculationAccessor", "autopattern.CraftingServiceGetProvidersMixin", "autopattern.CraftingTreeNodeAccessor", + "autopattern.CraftingTreeNodeMixin", "autopattern.CraftingTreeProcessMixin", + "autopattern.PatternProviderLogicContainsRedirectMixin", "extendedae.ContainerExPatternProviderMixin", "extendedae.ContainerExPatternTerminalMixin", "extendedae.ContainerWirelessExPatternTerminalMixin",