diff --git a/build.gradle b/build.gradle index 963f8a0..8aba2d8 100644 --- a/build.gradle +++ b/build.gradle @@ -127,8 +127,10 @@ sourceSets.main.resources { srcDir 'src/generated/resources' } // 暂时排除缺少依赖的可选联动源码,待补齐依赖后再启用 sourceSets.main.java { + // 让编译期能解析 ExtendedAE 的类(如 GuiExPatternProvider、ActionEPPButton 等),仅作编译期源引用 + // 运行期仍由 CurseMaven 依赖提供真实模组 Jar + srcDir 'othermods/ExtendedAE-1.21-2.2.21-neoforge/src/main/java' // 广泛屏蔽迁移中的旧源码,仅保留模板核心类(ExtendedAEPlus、ExtendedAEPlusClient、Config) - exclude 'com/extendedae_plus/NewIcon.java' // 注意:不要屏蔽 api/**,我们有选择性 include 的接口文件需要参与编译 include 'com/extendedae_plus/api/**' exclude 'com/extendedae_plus/client/**' @@ -146,10 +148,16 @@ sourceSets.main.java { include 'com/extendedae_plus/mixin/ae2/accessor/**' // 启用对 PatternProviderLogic 的功能混入(高级阻挡/智能翻倍开关的持久化与逻辑) include 'com/extendedae_plus/mixin/ae2/helpers/**' + // 启用 AEProcessingPattern 的 mixin(提供可缩放标记) + include 'com/extendedae_plus/mixin/ae2/AEProcessingPatternMixin.java' // GUI 方案A:解禁最小 GUI 混入 include 'com/extendedae_plus/mixin/ae2/client/gui/PatternProviderScreenMixin.java' include 'com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuAdvancedMixin.java' include 'com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuDoublingMixin.java' + // ExtendedAE GUI 混入(右侧外列按钮与翻页),以及其依赖的 NewIcon 类 + // 仅包含 Provider GUI 混入(不要使用广域 exclude,以免覆盖 include) + include 'com/extendedae_plus/mixin/extendedae/client/gui/GuiExPatternProviderMixin.java' + include 'com/extendedae_plus/NewIcon.java' // 注意:不要屏蔽 network/**,我们已选择性 include 需要的网络文件 // 仅解禁样板倍增核心所需的两个 util 文件 include 'com/extendedae_plus/util/PatternProviderDataUtil.java' @@ -161,6 +169,7 @@ sourceSets.main.java { include 'com/extendedae_plus/network/ModNetwork.java' include 'com/extendedae_plus/network/ToggleAdvancedBlockingC2SPacket.java' include 'com/extendedae_plus/network/ToggleSmartDoublingC2SPacket.java' + include 'com/extendedae_plus/network/ScalePatternsC2SPacket.java' // 仅 include 需要的 util 文件(不再对 util/** 做全局排除,以免误伤) include 'com/extendedae_plus/util/PatternProviderDataUtil.java' include 'com/extendedae_plus/util/PatternProviderUIHelper.java' @@ -205,9 +214,9 @@ dependencies { implementation "org.appliedenergistics:guideme:2.5.1" // jarJar configuration not set in this build; use implementation for API for now implementation "de.mari_023:ae2wtlib_api:19.2.0" - implementation "curse.maven:ex-pattern-provider-892005:6863556" implementation "curse.maven:curios-309927:6529130" + compileOnly "curse.maven:ex-pattern-provider-892005:6863556" compileOnly "curse.maven:applied-flux-965012:5614830" compileOnly "dev.emi:emi-neoforge:1.1.10+1.21" compileOnly "curse.maven:mega-cells-622112:6005043" @@ -229,6 +238,7 @@ dependencies { runtimeOnly "curse.maven:jade-324717:5427817" runtimeOnly "curse.maven:mega-cells-622112:6005043" runtimeOnly "mekanism:Mekanism:1.21.1-10.7.0.55" + runtimeOnly "curse.maven:ex-pattern-provider-892005:6863556" // setup Xei (EMI/REI/JEI) using project property 'use_Xei' switch (project.findProperty('use_Xei') ?: 'emi') { diff --git a/src/main/java/com/extendedae_plus/NewIcon.java b/src/main/java/com/extendedae_plus/NewIcon.java index 8535a1f..e8735ef 100644 --- a/src/main/java/com/extendedae_plus/NewIcon.java +++ b/src/main/java/com/extendedae_plus/NewIcon.java @@ -5,7 +5,9 @@ import net.minecraft.resources.ResourceLocation; public class NewIcon { @SuppressWarnings("all") - private static final ResourceLocation TEXTURE = new ResourceLocation(ExtendedAEPlus.MODID,"textures/gui/nicons.png"); + // 贴图当前存放于 assets/extendedae_plus/textures/gui/nicons.png + // 与 MODID (extendedaeplus) 不同,因此这里直接指定贴图所在命名空间 + private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath("extendedae_plus", "textures/gui/nicons.png"); diff --git a/src/main/java/com/extendedae_plus/mixin/extendedae/client/gui/GuiExPatternProviderMixin.java b/src/main/java/com/extendedae_plus/mixin/extendedae/client/gui/GuiExPatternProviderMixin.java index 42b1ce2..167a183 100644 --- a/src/main/java/com/extendedae_plus/mixin/extendedae/client/gui/GuiExPatternProviderMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/extendedae/client/gui/GuiExPatternProviderMixin.java @@ -10,9 +10,9 @@ import com.extendedae_plus.config.ModConfigs; import com.glodblock.github.extendedae.client.button.ActionEPPButton; import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider; import com.glodblock.github.extendedae.container.ContainerExPatternProvider; -import com.glodblock.github.extendedae.network.EPPNetworkHandler; -import com.glodblock.github.glodium.network.packet.CGenericPacket; import net.minecraft.network.chat.Component; +import net.minecraft.client.Minecraft; +import com.extendedae_plus.network.ScalePatternsC2SPacket; import net.minecraft.world.entity.player.Inventory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -196,34 +196,40 @@ public abstract class GuiExPatternProviderMixin extends PatternProviderScreen { - EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("multiply2")); + var conn = Minecraft.getInstance().getConnection(); + if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.MUL2)); }, NewIcon.MULTIPLY2); this.x2Button.setVisibility(true); this.divideBy2Button = new ActionEPPButton((b) -> { - EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("divide2")); + var conn = Minecraft.getInstance().getConnection(); + if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.DIV2)); }, NewIcon.DIVIDE2); this.divideBy2Button.setVisibility(true); this.x10Button = new ActionEPPButton((b) -> { - EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("multiply10")); + var conn = Minecraft.getInstance().getConnection(); + if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.MUL10)); }, NewIcon.MULTIPLY10); this.x10Button.setVisibility(true); this.divideBy10Button = new ActionEPPButton((b) -> { - EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("divide10")); + var conn = Minecraft.getInstance().getConnection(); + if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.DIV10)); }, NewIcon.DIVIDE10); this.divideBy10Button.setVisibility(true); this.divideBy5Button = new ActionEPPButton((b) -> { - EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("divide5")); + var conn = Minecraft.getInstance().getConnection(); + if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.DIV5)); }, NewIcon.DIVIDE5); this.divideBy5Button.setVisibility(true); this.x5Button = new ActionEPPButton((b) -> { - EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("multiply5")); + var conn = Minecraft.getInstance().getConnection(); + if (conn != null) conn.send(new ScalePatternsC2SPacket(ScalePatternsC2SPacket.Operation.MUL5)); }, NewIcon.MULTIPLY5); this.x5Button.setVisibility(true); @@ -357,119 +363,7 @@ public abstract class GuiExPatternProviderMixin extends PatternProviderScreen { - try { - // 直接基于容器槽位操作,完全绕开 PatternProviderLogic 及其内部字段 - if (!(serverPlayer.containerMenu instanceof com.glodblock.github.extendedae.container.ContainerExPatternProvider exMenu)) { - return; - } - - 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++; - } - } - } - - // 构造结果并回显 - 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); - } - - } catch (Exception ignored) { - } - }); - - } catch (Exception ignored) { - } - } - - @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; - } - } - } - } else { - for (var stack : stacks) { - if (stack != null) { - long upper = 999999L * stack.what().getAmountPerUnit(); - if (stack.amount() * scale > upper) { - return false; - } - } - } - } - 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); - } - } - } + // 本文件原包含本地样板缩放实现(单机模式)和 ExtendedAE 网络派发,已移除以兼容 1.21.1 与最小可构建集。 } \ No newline at end of file diff --git a/src/main/java/com/extendedae_plus/network/ModNetwork.java b/src/main/java/com/extendedae_plus/network/ModNetwork.java index 2c6a49a..ecd2d21 100644 --- a/src/main/java/com/extendedae_plus/network/ModNetwork.java +++ b/src/main/java/com/extendedae_plus/network/ModNetwork.java @@ -9,5 +9,6 @@ public class ModNetwork { var registrar = event.registrar(ExtendedAEPlus.MODID); registrar.playToServer(ToggleAdvancedBlockingC2SPacket.TYPE, ToggleAdvancedBlockingC2SPacket.STREAM_CODEC, ToggleAdvancedBlockingC2SPacket::handle); registrar.playToServer(ToggleSmartDoublingC2SPacket.TYPE, ToggleSmartDoublingC2SPacket.STREAM_CODEC, ToggleSmartDoublingC2SPacket::handle); + registrar.playToServer(ScalePatternsC2SPacket.TYPE, ScalePatternsC2SPacket.STREAM_CODEC, ScalePatternsC2SPacket::handle); } } diff --git a/src/main/java/com/extendedae_plus/network/ScalePatternsC2SPacket.java b/src/main/java/com/extendedae_plus/network/ScalePatternsC2SPacket.java new file mode 100644 index 0000000..586c10a --- /dev/null +++ b/src/main/java/com/extendedae_plus/network/ScalePatternsC2SPacket.java @@ -0,0 +1,91 @@ +package com.extendedae_plus.network; + +import appeng.helpers.patternprovider.PatternProviderLogic; +import appeng.menu.implementations.PatternProviderMenu; +import com.extendedae_plus.ExtendedAEPlus; +import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor; +import com.extendedae_plus.util.ExtendedAELogger; +import com.extendedae_plus.util.PatternProviderDataUtil; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.neoforged.neoforge.network.handling.IPayloadContext; + +/** + * C2S:请求对当前打开的样板供应器执行样板数量缩放(倍增或除法)。 + */ +public class ScalePatternsC2SPacket implements CustomPacketPayload { + public enum Operation { + MUL2, DIV2, MUL5, DIV5, MUL10, DIV10 + } + + public static final Type TYPE = new Type<>( + ResourceLocation.fromNamespaceAndPath(ExtendedAEPlus.MODID, "scale_patterns")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.of( + (buf, pkt) -> buf.writeEnum(pkt.op), + buf -> new ScalePatternsC2SPacket(buf.readEnum(Operation.class)) + ); + + private final Operation op; + + public ScalePatternsC2SPacket(Operation op) { + this.op = op; + } + + public Operation op() { + return op; + } + + @Override + public Type type() { + return TYPE; + } + + public static void handle(final ScalePatternsC2SPacket msg, final IPayloadContext ctx) { + ctx.enqueueWork(() -> { + if (!(ctx.player() instanceof ServerPlayer player)) return; + if (!(player.containerMenu instanceof PatternProviderMenu menu)) return; + + try { + var accessor = (PatternProviderMenuAdvancedAccessor) menu; + PatternProviderLogic logic = accessor.eap$logic(); + if (logic == null) return; + + double factor; + boolean multiply; + switch (msg.op) { + case MUL2 -> { factor = 2.0; multiply = true; } + case DIV2 -> { factor = 2.0; multiply = false; } + case MUL5 -> { factor = 5.0; multiply = true; } + case DIV5 -> { factor = 5.0; multiply = false; } + case MUL10 -> { factor = 10.0; multiply = true; } + case DIV10 -> { factor = 10.0; multiply = false; } + default -> { return; } + } + + PatternProviderDataUtil.PatternScalingResult result; + if (multiply) { + result = PatternProviderDataUtil.multiplyPatternAmounts(logic, factor); + } else { + result = PatternProviderDataUtil.dividePatternAmounts(logic, factor); + } + + logic.saveChanges(); + + // 回显结果到玩家 + String summary = String.format("样板缩放(%s x%.0f): 共%d, 成功%d, 失败%d", multiply ? "倍增" : "除法", + factor, result.getTotalPatterns(), result.getScaledPatterns(), result.getFailedPatterns()); + player.displayClientMessage(net.minecraft.network.chat.Component.literal("[EAP] " + summary), true); + + for (String err : result.getErrors()) { + ExtendedAELogger.LOGGER.debug("[EAP] scale error: {}", err); + } + } catch (Throwable t) { + ExtendedAELogger.LOGGER.error("[EAP] Handle ScalePatternsC2SPacket failed", t); + } + }); + } +} diff --git a/src/main/resources/extendedaeplus.mixins.json b/src/main/resources/extendedaeplus.mixins.json index fadf66c..f50ff9f 100644 --- a/src/main/resources/extendedaeplus.mixins.json +++ b/src/main/resources/extendedaeplus.mixins.json @@ -4,12 +4,15 @@ "compatibilityLevel": "JAVA_21", "mixins": [ "ae2.accessor.PatternProviderLogicAccessor", + "ae2.accessor.PatternProviderLogicPatternsAccessor", "ae2.accessor.PatternProviderMenuAdvancedAccessor", "ae2.client.gui.PatternProviderScreenMixin", "ae2.menu.PatternProviderMenuAdvancedMixin", "ae2.menu.PatternProviderMenuDoublingMixin", "ae2.helpers.PatternProviderLogicAdvancedMixin", - "ae2.helpers.PatternProviderLogicDoublingMixin" + "ae2.helpers.PatternProviderLogicDoublingMixin", + "ae2.AEProcessingPatternMixin", + "extendedae.client.gui.GuiExPatternProviderMixin" ], "injectors": { "defaultRequire": 1