From e5493eb2ca5069093bc98473d0f860ba1ac2ed25 Mon Sep 17 00:00:00 2001 From: GaLi <3096147684@qq.com> Date: Sun, 10 Aug 2025 22:54:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BD=BB=E5=BA=95=E5=AE=8C=E6=88=90=E6=A0=B7?= =?UTF-8?q?=E6=9D=BF=E5=80=8D=E5=A2=9E=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mixin/GuiExPatternProviderMixin.java | 218 +++++++++--------- .../util/PatternProviderDataUtil.java | 59 ++--- 2 files changed, 128 insertions(+), 149 deletions(-) diff --git a/src/main/java/com/extendedae_plus/mixin/GuiExPatternProviderMixin.java b/src/main/java/com/extendedae_plus/mixin/GuiExPatternProviderMixin.java index dd02f11..bef6c36 100644 --- a/src/main/java/com/extendedae_plus/mixin/GuiExPatternProviderMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/GuiExPatternProviderMixin.java @@ -294,131 +294,119 @@ public abstract class GuiExPatternProviderMixin extends PatternProviderScreen 0) { - message = String.format("✅ ExtendedAE Plus: 样板%s成功!处理了 %d 个样板,跳过 %d 个样板", - "MULTIPLY".equals(scalingType) ? "倍增" : "除法", - result.getScaledPatterns(), result.getFailedPatterns()); - } else { - message = String.format("✅ ExtendedAE Plus: 样板%s成功!处理了 %d 个样板", - "MULTIPLY".equals(scalingType) ? "倍增" : "除法", - result.getScaledPatterns()); + // 将实际逻辑切换到服务端主线程执行,避免跨线程访问导致读取到空库存 + serverPlayer.getServer().execute(() -> { + try { + // 直接基于容器槽位操作,完全绕开 PatternProviderLogic 及其内部字段 + if (!(serverPlayer.containerMenu instanceof com.glodblock.github.extendedae.container.ContainerExPatternProvider exMenu)) { + System.out.println("ExtendedAE Plus: 当前容器不是 ExPatternProvider,无法执行样板缩放"); + return; } - } else { - message = String.format("❌ ExtendedAE Plus: 样板%s失败!错误: %s", - "MULTIPLY".equals(scalingType) ? "倍增" : "除法", - String.join("; ", result.getErrors())); - } - - // 显示消息到动作栏 - minecraft.player.displayClientMessage(net.minecraft.network.chat.Component.literal(message), true); - System.out.println("ExtendedAE Plus: " + message); - } - - } catch (Exception e) { - System.out.println("ExtendedAE Plus: 服务器端执行样板缩放时发生错误: " + e.getMessage()); - e.printStackTrace(); - } - } - - /** - * 获取服务器端的样板供应器逻辑 - */ - @Unique - private appeng.helpers.patternprovider.PatternProviderLogic getServerSidePatternProvider(net.minecraft.server.level.ServerPlayer serverPlayer) { - try { - if (serverPlayer.containerMenu != null) { - // 检查是否是样板供应器菜单 - String menuClassName = serverPlayer.containerMenu.getClass().getSimpleName(); - System.out.println("ExtendedAE Plus: 服务器端菜单类名: " + menuClassName); - - if (menuClassName.contains("PatternProvider")) { - // 尝试多种可能的字段名称 - String[] possibleFieldNames = {"logic", "patternProvider", "host", "provider"}; - - for (String fieldName : possibleFieldNames) { - try { - var field = findFieldInHierarchy(serverPlayer.containerMenu.getClass(), fieldName); - if (field != null) { - field.setAccessible(true); - Object fieldValue = field.get(serverPlayer.containerMenu); - - if (fieldValue instanceof appeng.helpers.patternprovider.PatternProviderLogic) { - System.out.println("ExtendedAE Plus: 通过字段 '" + fieldName + "' 找到PatternProviderLogic"); - return (appeng.helpers.patternprovider.PatternProviderLogic) fieldValue; - } - - // 如果字段值是host,尝试从host获取logic - if (fieldValue != null && fieldName.equals("host")) { - try { - var logicMethod = fieldValue.getClass().getMethod("getLogic"); - Object logic = logicMethod.invoke(fieldValue); - if (logic instanceof appeng.helpers.patternprovider.PatternProviderLogic) { - System.out.println("ExtendedAE Plus: 通过host.getLogic()找到PatternProviderLogic"); - return (appeng.helpers.patternprovider.PatternProviderLogic) logic; - } - } catch (Exception hostException) { - // 忽略host方法调用失败 + + int scaled = 0; + int failed = 0; + int total = 0; + final int scale = (int) Math.round(scaleFactor); + final boolean div = !"MULTIPLY".equals(scalingType); + + java.util.List slots = exMenu.getSlots(appeng.menu.SlotSemantics.ENCODED_PATTERN); + for (var slot : slots) { + var stack = slot.getItem(); + if (stack.getItem() instanceof appeng.crafting.pattern.EncodedPatternItem patternItem) { + total++; + var detail = patternItem.decode(stack, serverPlayer.level(), false); + if (detail instanceof appeng.crafting.pattern.AEProcessingPattern process) { + var input = process.getSparseInputs(); + var output = process.getOutputs(); + + // 检查是否可修改(来源:ExtendedAE ContainerPatternModifier.checkModify) + if (checkModifyLikeExtendedAE(input, scale, div) && checkModifyLikeExtendedAE(output, scale, div)) { + var mulInput = new appeng.api.stacks.GenericStack[input.length]; + var mulOutput = new appeng.api.stacks.GenericStack[output.length]; + modifyStacksLikeExtendedAE(input, mulInput, scale, div); + modifyStacksLikeExtendedAE(output, mulOutput, scale, div); + var newPattern = appeng.api.crafting.PatternDetailsHelper.encodeProcessingPattern(mulInput, mulOutput); + if (slot instanceof appeng.menu.slot.AppEngSlot as) { + as.set(newPattern); + } else { + slot.set(newPattern); } + scaled++; + } else { + failed++; } + } else { + // 非处理样板:跳过 + failed++; } - } catch (Exception fieldException) { - // 继续尝试下一个字段名 } } - - // 如果直接字段访问失败,尝试通过方法获取 - try { - var getLogicMethod = serverPlayer.containerMenu.getClass().getMethod("getLogic"); - Object logic = getLogicMethod.invoke(serverPlayer.containerMenu); - if (logic instanceof appeng.helpers.patternprovider.PatternProviderLogic) { - System.out.println("ExtendedAE Plus: 通过getLogic()方法找到PatternProviderLogic"); - return (appeng.helpers.patternprovider.PatternProviderLogic) logic; - } - } catch (Exception methodException) { - // 方法调用失败,继续其他尝试 + + // 构造结果并回显 + String message; + if (scaled == 0) { + message = String.format( + "ℹ️ ExtendedAE Plus: 样板%s完成,但未处理任何样板。共发现 %d 个样板,失败 %d 个(可能全为合成样板或数量不满足条件)", + div ? "除法" : "倍增", total, failed); + } else if (failed > 0) { + message = String.format("✅ ExtendedAE Plus: 样板%s完成!处理了 %d 个,跳过 %d 个", div ? "除法" : "倍增", scaled, failed); + } else { + message = String.format("✅ ExtendedAE Plus: 样板%s成功!处理了 %d 个", div ? "除法" : "倍增", scaled); + } + + var minecraft = net.minecraft.client.Minecraft.getInstance(); + if (minecraft.player != null) { + minecraft.player.displayClientMessage(net.minecraft.network.chat.Component.literal(message), true); + } + System.out.println("ExtendedAE Plus: " + message); + + } catch (Exception e) { + System.out.println("ExtendedAE Plus: 服务器端执行样板缩放时发生错误: " + e.getMessage()); + e.printStackTrace(); + } + }); + + } catch (Exception e) { + System.out.println("ExtendedAE Plus: 调度到服务器主线程时发生错误: " + e.getMessage()); + e.printStackTrace(); + } + } + + @Unique + private boolean checkModifyLikeExtendedAE(appeng.api.stacks.GenericStack[] stacks, int scale, boolean div) { + if (div) { + for (var stack : stacks) { + if (stack != null) { + if (stack.amount() % scale != 0) { + return false; } } } - } catch (Exception e) { - System.out.println("ExtendedAE Plus: 获取服务器端样板供应器逻辑时发生错误: " + e.getMessage()); - e.printStackTrace(); - } - return null; - } - - /** - * 在类继承层次中查找字段 - */ - @Unique - private java.lang.reflect.Field findFieldInHierarchy(Class clazz, String fieldName) { - Class currentClass = clazz; - while (currentClass != null && currentClass != Object.class) { - try { - return currentClass.getDeclaredField(fieldName); - } catch (NoSuchFieldException e) { - currentClass = currentClass.getSuperclass(); + } else { + for (var stack : stacks) { + if (stack != null) { + long upper = 999999L * stack.what().getAmountPerUnit(); + if (stack.amount() * scale > upper) { + return false; + } + } } } - return null; + return true; } + + @Unique + private void modifyStacksLikeExtendedAE(appeng.api.stacks.GenericStack[] stacks, + appeng.api.stacks.GenericStack[] des, + int scale, + boolean div) { + for (int i = 0; i < stacks.length; i++) { + if (stacks[i] != null) { + long amt = div ? stacks[i].amount() / scale : stacks[i].amount() * scale; + des[i] = new appeng.api.stacks.GenericStack(stacks[i].what(), amt); + } + } + } + + } \ No newline at end of file diff --git a/src/main/java/com/extendedae_plus/util/PatternProviderDataUtil.java b/src/main/java/com/extendedae_plus/util/PatternProviderDataUtil.java index 8727d12..c003042 100644 --- a/src/main/java/com/extendedae_plus/util/PatternProviderDataUtil.java +++ b/src/main/java/com/extendedae_plus/util/PatternProviderDataUtil.java @@ -20,6 +20,7 @@ import java.util.Arrays; * 用于获取样板供应器中的所有样板数据,包括输入输出物品的数量信息 */ public class PatternProviderDataUtil { + private static final boolean DEBUG = true; // 临时诊断开关,发布可设为 false /** * 样板数据类,包含样板的输入输出信息 @@ -101,8 +102,9 @@ public class PatternProviderDataUtil { * 通过检查实现类型来判断 */ public boolean isCraftingPattern() { - // 根据AE2源码,制作样板使用AECraftingPattern类 - return patternDetails.getClass().getSimpleName().equals("AECraftingPattern"); + // 使用样板定义判断,避免依赖类名(发布版会被混淆) + String def = String.valueOf(patternDetails.getDefinition()).toLowerCase(); + return def.contains("crafting"); } /** @@ -110,8 +112,9 @@ public class PatternProviderDataUtil { * 通过检查实现类型来判断 */ public boolean isProcessingPattern() { - // 处理样板使用AEProcessingPattern类 - return patternDetails.getClass().getSimpleName().equals("AEProcessingPattern"); + // 使用样板定义判断处理类样板(含处理/石切/锻造等非合成) + String def = String.valueOf(patternDetails.getDefinition()).toLowerCase(); + return def.contains("processing") || def.contains("stonecutting") || def.contains("smithing"); } /** @@ -785,34 +788,23 @@ public class PatternProviderDataUtil { */ private static ItemStack scalePattern(IPatternDetails originalPattern, double scaleFactor, Level level) { try { - // 检查样板类型 - boolean isCraftingPattern = originalPattern.getClass().getSimpleName().equals("AECraftingPattern"); - boolean isProcessingPattern = originalPattern.getClass().getSimpleName().equals("AEProcessingPattern"); + // 基于定义字符串进行类型判断,避免类名混淆问题 + String def = String.valueOf(originalPattern.getDefinition()).toLowerCase(); + boolean isCrafting = def.contains("crafting"); - if (isCraftingPattern) { - // 合成样板不参与缩放,直接返回null表示跳过 + if (isCrafting) { + // 合成样板不参与缩放 return null; - } else if (isProcessingPattern) { - // 如果是除法操作(scaleFactor < 1),需要检查是否可以除 - if (scaleFactor < 1.0) { - double divisor = 1.0 / scaleFactor; - if (!canDivideProcessingPattern(originalPattern, divisor)) { - // 不能被除,返回null表示跳过 - return null; - } - } - // 只有处理样板才进行缩放 - return scaleProcessingPattern(originalPattern, scaleFactor); - } else { - // 对于未知类型的样板,也尝试作为处理样板处理 - if (scaleFactor < 1.0) { - double divisor = 1.0 / scaleFactor; - if (!canDivideProcessingPattern(originalPattern, divisor)) { - return null; - } - } - return scaleProcessingPattern(originalPattern, scaleFactor); } + + // 非合成(处理/石切/锻造等)按处理样板流程处理 + if (scaleFactor < 1.0) { + double divisor = 1.0 / scaleFactor; + if (!canDivideProcessingPattern(originalPattern, divisor)) { + return null; + } + } + return scaleProcessingPattern(originalPattern, scaleFactor); } catch (Exception e) { return null; } @@ -954,11 +946,10 @@ public class PatternProviderDataUtil { */ private static boolean isPatternScalable(IPatternDetails pattern) { if (pattern == null) return false; - - String className = pattern.getClass().getSimpleName(); - // 只有处理样板可以缩放,合成样板不支持 - return "AEProcessingPattern".equals(className) || - (!className.equals("AECraftingPattern") && pattern.getOutputs().length > 0); + String def = String.valueOf(pattern.getDefinition()).toLowerCase(); + boolean isCrafting = def.contains("crafting"); + // 非合成且有输出,认为可缩放(包含处理/石切/锻造等) + return !isCrafting && pattern.getOutputs().length > 0; } /**