From 9d126e65a0279bb57a02bb2c426561d8c01c2685 Mon Sep 17 00:00:00 2001 From: GaLi <3096147684@qq.com> Date: Thu, 26 Mar 2026 12:02:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96appflux=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E6=A7=BD=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PatternProviderLogicAppfluxBridge.java | 7 + .../compat/UpgradeSlotCompat.java | 129 ++++++--- .../mixin/ExtendedAEPlusMixinPlugin.java | 9 +- .../PatternProviderScreenUpgradesMixin.java | 65 ++--- .../PatternProviderLogicCompatMixin.java | 78 ++--- .../helpers/InterfaceLogicUpgradesMixin.java | 2 +- .../PatternProviderLogicUpgradesMixin.java | 267 ++++-------------- .../PatternProviderMenuUpgradesMixin.java | 13 +- .../PatternProviderLogicAppfluxAccessor.java | 19 ++ .../resources/extendedae_plus.mixins.json | 1 + 10 files changed, 253 insertions(+), 337 deletions(-) create mode 100644 src/main/java/com/extendedae_plus/api/bridge/PatternProviderLogicAppfluxBridge.java create mode 100644 src/main/java/com/extendedae_plus/mixin/appflux/accessor/PatternProviderLogicAppfluxAccessor.java diff --git a/src/main/java/com/extendedae_plus/api/bridge/PatternProviderLogicAppfluxBridge.java b/src/main/java/com/extendedae_plus/api/bridge/PatternProviderLogicAppfluxBridge.java new file mode 100644 index 0000000..365878b --- /dev/null +++ b/src/main/java/com/extendedae_plus/api/bridge/PatternProviderLogicAppfluxBridge.java @@ -0,0 +1,7 @@ +package com.extendedae_plus.api.bridge; + +import appeng.api.upgrades.IUpgradeInventory; + +public interface PatternProviderLogicAppfluxBridge { + IUpgradeInventory eap$ensureAppfluxUpgradeSlots(); +} diff --git a/src/main/java/com/extendedae_plus/compat/UpgradeSlotCompat.java b/src/main/java/com/extendedae_plus/compat/UpgradeSlotCompat.java index 5b549ce..8b981eb 100644 --- a/src/main/java/com/extendedae_plus/compat/UpgradeSlotCompat.java +++ b/src/main/java/com/extendedae_plus/compat/UpgradeSlotCompat.java @@ -1,72 +1,123 @@ package com.extendedae_plus.compat; -import net.neoforged.fml.loading.FMLLoader; import net.neoforged.fml.ModList; +/** + * 升级卡槽兼容性管理类 + * 统一管理: + * 1. 是否由我们自己提供升级槽 + * 2. appflux存在时是否复用其升级槽 + */ public final class UpgradeSlotCompat { - private static Boolean APPFLUX_LOADED; - private static Boolean APPFLUX_PATTERN_PROVIDER_MIXIN_ACTIVE; + private static final String APPFLUX_MOD_ID = "appflux"; + private static final String APPFLUX_SCREEN_MIXIN = "com.glodblock.github.appflux.mixins.MixinPatternProviderScreen"; + private static final int LOCAL_PATTERN_PROVIDER_UPGRADE_SLOTS = 2; + private static final int APPFLUX_PATTERN_PROVIDER_UPGRADE_SLOTS = 2; - private UpgradeSlotCompat() {} + private static Boolean appfluxLoaded; + private static Boolean appfluxPatternProviderMixinActive; - private static boolean isAppfluxLoaded() { - if (APPFLUX_LOADED == null) { - try { - APPFLUX_LOADED = ModList.get().isLoaded("appflux"); - } catch (Throwable t) { - // 早期阶段或运行环境差异 - APPFLUX_LOADED = false; - } - } - return APPFLUX_LOADED; + private UpgradeSlotCompat() { } /** - * 检测AppliedFlux的PatternProviderScreen mixin是否活跃 - * 这比简单检查模组是否加载更准确 + * 检测 Applied Flux 模组是否存在 */ - private static boolean isAppfluxPatternProviderMixinActive() { - if (APPFLUX_PATTERN_PROVIDER_MIXIN_ACTIVE == null) { + public static boolean isAppfluxPresent() { + if (appfluxLoaded == null) { try { - if (!isAppfluxLoaded()) { - APPFLUX_PATTERN_PROVIDER_MIXIN_ACTIVE = false; - } else { - // 尝试检测AppliedFlux的mixin类是否存在 - Class.forName("com.glodblock.github.appflux.mixins.MixinPatternProviderScreen"); - APPFLUX_PATTERN_PROVIDER_MIXIN_ACTIVE = true; - } - } catch (ClassNotFoundException e) { - APPFLUX_PATTERN_PROVIDER_MIXIN_ACTIVE = false; + appfluxLoaded = ModList.get().isLoaded(APPFLUX_MOD_ID); } catch (Throwable t) { - APPFLUX_PATTERN_PROVIDER_MIXIN_ACTIVE = false; + appfluxLoaded = false; } } - return APPFLUX_PATTERN_PROVIDER_MIXIN_ACTIVE; + return appfluxLoaded; } - // 是否由我们提供升级槽(当未安装 appflux 时) + /** + * 是否由我们自己提供升级槽实现。 + */ + public static boolean usesDedicatedUpgradeSlots() { + return !isAppfluxPresent(); + } + + /** + * 是否应当复用 appflux 注入到 PatternProviderLogic 上的升级槽。 + */ + public static boolean usesAppfluxUpgradeSlots() { + return isAppfluxPresent(); + } + + /** + * 检测是否应该启用我们的升级卡槽功能 + */ public static boolean shouldEnableUpgradeSlots() { - return !isAppfluxLoaded(); + return usesDedicatedUpgradeSlots(); } - // 是否启用频道卡支持(两种情况下都启用) + /** + * 是否需要持久化和管理我们本地创建的升级槽。 + */ + public static boolean shouldManageLocalUpgradeInventory() { + return usesDedicatedUpgradeSlots(); + } + + /** + * 频道卡是我们独有的功能,即使 appflux 存在也应该启用。 + */ public static boolean shouldEnableChannelCard() { return true; } - // 客户端界面是否需要显示升级面板 - // 如果AppliedFlux的mixin活跃,我们降低优先级让它处理 - public static boolean shouldAddUpgradePanelToScreen() { - return true; // 总是尝试添加,但在代码中检测冲突 + /** + * appflux 存在时,我们仍然需要监听其升级槽变化来驱动额外的兼容逻辑。 + */ + public static boolean shouldListenToAppfluxUpgrades() { + return usesAppfluxUpgradeSlots(); } - // 是否应该使用低优先级模式(当AppliedFlux存在时) + /** + * 客户端界面是否需要显示升级面板。 + */ + public static boolean shouldAddUpgradePanelToScreen() { + return usesDedicatedUpgradeSlots(); + } + + public static int getPatternProviderLocalUpgradeSlots() { + return LOCAL_PATTERN_PROVIDER_UPGRADE_SLOTS; + } + + public static int getPatternProviderAppfluxUpgradeSlots() { + return APPFLUX_PATTERN_PROVIDER_UPGRADE_SLOTS; + } + + /** + * 兼容主工程现有调用:当 appflux 的 PatternProvider Screen mixin 会接管 UI 时,返回低优先级模式。 + */ public static boolean shouldUseLowPriorityMode() { return isAppfluxPatternProviderMixinActive(); } - // 获取推荐的mixin优先级 + /** + * 兼容主工程现有调用:保留旧的优先级推荐接口。 + */ public static int getRecommendedMixinPriority() { - return isAppfluxPatternProviderMixinActive() ? 1500 : 2000; + return shouldUseLowPriorityMode() ? 1500 : 2000; + } + + private static boolean isAppfluxPatternProviderMixinActive() { + if (appfluxPatternProviderMixinActive == null) { + try { + if (!isAppfluxPresent()) { + appfluxPatternProviderMixinActive = false; + } else { + Class.forName(APPFLUX_SCREEN_MIXIN); + appfluxPatternProviderMixinActive = true; + } + } catch (Throwable t) { + appfluxPatternProviderMixinActive = false; + } + } + return appfluxPatternProviderMixinActive; } } diff --git a/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java b/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java index 1b56ca2..76996bb 100644 --- a/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java +++ b/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java @@ -38,6 +38,10 @@ public class ExtendedAEPlusMixinPlugin implements IMixinConfigPlugin { return isClassPresent("lu.kolja.expandedae.ExpandedAE"); } + private static boolean isAppfluxPresent() { + return isClassPresent("com.glodblock.github.appflux.AppFlux"); + } + @Override public void onLoad(String mixinPackage) { } @@ -46,6 +50,9 @@ public class ExtendedAEPlusMixinPlugin implements IMixinConfigPlugin { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if (!isAppfluxPresent() && mixinClassName.startsWith("com.extendedae_plus.mixin.appflux.")) { + return false; + } if (!isJeiPresent()) { // Disable all JEI package mixins and any mixins that reference JEI-only helpers if (mixinClassName.startsWith("com.extendedae_plus.mixin.jei")) return false; @@ -81,4 +88,4 @@ public class ExtendedAEPlusMixinPlugin implements IMixinConfigPlugin { @Override public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } -} \ No newline at end of file +} diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternProviderScreenUpgradesMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternProviderScreenUpgradesMixin.java index 01ca55f..d52c7c9 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternProviderScreenUpgradesMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternProviderScreenUpgradesMixin.java @@ -16,7 +16,6 @@ import appeng.menu.AEBaseMenu; import appeng.menu.SlotSemantics; import appeng.menu.implementations.PatternProviderMenu; import com.extendedae_plus.api.IStyleAccessor; -import com.extendedae_plus.compat.AppliedFluxCompat; import com.extendedae_plus.compat.UpgradeSlotCompat; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; @@ -38,57 +37,43 @@ public abstract class PatternProviderScreenUpgradesMixin screen = (PatternProviderScreen) (Object) this; + try { + this.widgets.add("upgrades", new UpgradesPanel(menu.getSlots(SlotSemantics.UPGRADE), this::eap$getCompatibleUpgrades)); + } catch (IllegalStateException e) { + com.extendedae_plus.util.ExtendedAELogger.LOGGER.warn("[样板供应器][界面] 升级面板已存在,跳过添加: {}", e.getMessage()); + return; + } - boolean shouldSkip = AppliedFluxCompat.shouldSkipOurUpgradePanel(screen); + var sp = new SlotPosition(); + sp.setBottom(84); + sp.setRight(1); + sp.setGrid(SlotGridLayout.BREAK_AFTER_3COLS); + var ws = new WidgetStyle(); + ws.setRight(2); + ws.setBottom(90); + ws.setWidth(59); + ws.setHeight(66); + style.getSlots().put("TOOLBOX", sp); + ((IStyleAccessor) style).getImages().put("toolbox", Blitter.texture("guis/extra_panels.png", 128, 128).src(69, 62, 59, 66)); + ((IStyleAccessor) style).getWidgets().put("toolbox", ws); - if (shouldSkip) { - } else { - - // 检查是否已经存在upgrades widget + if (menu instanceof AEBaseMenu base + && base instanceof com.extendedae_plus.api.bridge.IUpgradableMenu upg + && upg.eap$getToolbox() != null + && upg.eap$getToolbox().isPresent()) { try { - // 尝试添加升级面板 - this.widgets.add("upgrades", new UpgradesPanel(menu.getSlots(SlotSemantics.UPGRADE), this::eap$getCompatibleUpgrades)); + this.widgets.add("toolbox", new ToolboxPanel(style, upg.eap$getToolbox().getName())); } catch (IllegalStateException e) { - com.extendedae_plus.util.ExtendedAELogger.LOGGER.warn("[样板供应器][界面] 升级面板已存在,跳过添加: {}", e.getMessage()); - return; // 如果升级面板已存在,不继续添加其他内容 + com.extendedae_plus.util.ExtendedAELogger.LOGGER.warn("[样板供应器][界面] 工具箱面板已存在,跳过添加: {}", e.getMessage()); } - - // 设置TOOLBOX样式(完全按照AppliedFlux的方式) - var sp = new SlotPosition(); - sp.setBottom(84); - sp.setRight(1); - sp.setGrid(SlotGridLayout.BREAK_AFTER_3COLS); - var ws = new WidgetStyle(); - ws.setRight(2); - ws.setBottom(90); - ws.setWidth(59); - ws.setHeight(66); - style.getSlots().put("TOOLBOX", sp); - ((IStyleAccessor) style).getImages().put("toolbox", Blitter.texture("guis/extra_panels.png", 128, 128).src(69, 62, 59, 66)); - ((IStyleAccessor) style).getWidgets().put("toolbox", ws); - - // 添加工具箱面板 - if (menu instanceof AEBaseMenu base && base instanceof com.extendedae_plus.api.bridge.IUpgradableMenu upg && upg.eap$getToolbox() != null && upg.eap$getToolbox().isPresent()) { - try { - this.widgets.add("toolbox", new ToolboxPanel(style, upg.eap$getToolbox().getName())); - } catch (IllegalStateException e) { - com.extendedae_plus.util.ExtendedAELogger.LOGGER.warn("[样板供应器][界面] 工具箱面板已存在,跳过添加: {}", e.getMessage()); - } - } - } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicCompatMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicCompatMixin.java index 8286760..225a7ce 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicCompatMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/compat/PatternProviderLogicCompatMixin.java @@ -23,6 +23,7 @@ import com.extendedae_plus.init.ModItems; import com.extendedae_plus.items.materials.ChannelCardItem; import com.extendedae_plus.mixin.ae2.accessor.CraftingCpuLogicAccessor; import com.extendedae_plus.mixin.ae2.accessor.ExecutingCraftingJobAccessor; +import com.extendedae_plus.mixin.appflux.accessor.PatternProviderLogicAppfluxAccessor; import com.extendedae_plus.util.ExtendedAELogger; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.Item; @@ -41,7 +42,7 @@ import java.util.UUID; /** * 样板供应器频道卡兼容实现: - * - 未安装 appflux 时,提供 1 个升级槽并读取频道卡; + * - 未安装 appflux 时,提供 2 个升级槽并读取频道卡; * - 安装 appflux 时,优先从 appflux 提供的升级槽读取频道卡; * - 建立到无线主站的网格连接。 */ @@ -85,13 +86,12 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr at = @At("TAIL")) private void eap$compatInit(IManagedGridNode mainNode, PatternProviderLogicHost host, int size, CallbackInfo ci) { try { - if (UpgradeSlotCompat.shouldEnableUpgradeSlots()) { - // 未安装AppliedFlux,我们需要提供升级槽 + if (UpgradeSlotCompat.shouldManageLocalUpgradeInventory()) { this.eap$compatUpgrades = UpgradeInventories.forMachine( - host.getTerminalIcon().getItem(), 2, this::eap$compatOnUpgradesChanged); - } else { - // 安装了AppliedFlux,我们不提供升级槽,保留空的兼容槽用于备用 - // AppFlux 的升级槽变更会通过 PatternProviderLogicUpgradesMixin 的 bridge 回调到我们 + host.getTerminalIcon().getItem(), + UpgradeSlotCompat.getPatternProviderLocalUpgradeSlots(), + this::eap$compatOnUpgradesChanged); + } else if (!UpgradeSlotCompat.shouldEnableChannelCard()) { this.eap$compatUpgrades = UpgradeInventories.empty(); } } catch (Throwable t) { @@ -113,20 +113,15 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr } } - /** - * 实现 PatternProviderLogicUpgradeCompatBridge 接口 - * 由 PatternProviderLogicUpgradesMixin 在升级槽变更时调用 - */ @Override public void eap$onCompatUpgradesChangedHook() { this.eap$compatOnUpgradesChanged(); } - @Inject(method = "writeToNBT", at = @At("TAIL")) private void eap$compatWrite(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) { try { - if (UpgradeSlotCompat.shouldEnableUpgradeSlots()) { + if (UpgradeSlotCompat.shouldManageLocalUpgradeInventory()) { this.eap$compatUpgrades.writeToNBT(tag, "compat_upgrades", registries); } } catch (Throwable t) { @@ -137,7 +132,7 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr @Inject(method = "readFromNBT", at = @At("TAIL")) private void eap$compatRead(CompoundTag tag, net.minecraft.core.HolderLookup.Provider registries, CallbackInfo ci) { try { - if (UpgradeSlotCompat.shouldEnableUpgradeSlots()) { + if (UpgradeSlotCompat.shouldManageLocalUpgradeInventory()) { this.eap$compatUpgrades.readFromNBT(tag, "compat_upgrades", registries); } // 无论哪种模式都重新初始化 @@ -153,7 +148,7 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr @Inject(method = "addDrops", at = @At("TAIL")) private void eap$compatDrops(List drops, CallbackInfo ci) { try { - if (UpgradeSlotCompat.shouldEnableUpgradeSlots()) { + if (UpgradeSlotCompat.shouldManageLocalUpgradeInventory()) { for (var s : this.eap$compatUpgrades) { if (!s.isEmpty()) drops.add(s); } @@ -166,7 +161,7 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr @Inject(method = "clearContent", at = @At("TAIL")) private void eap$compatClear(CallbackInfo ci) { try { - if (UpgradeSlotCompat.shouldEnableUpgradeSlots()) { + if (UpgradeSlotCompat.shouldManageLocalUpgradeInventory()) { this.eap$compatUpgrades.clear(); } } catch (Throwable t) { @@ -282,33 +277,15 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr boolean found = false; UUID owner = null; - IUpgradeInventory upgrades = null; - - // 优先尝试从AppliedFlux获取升级槽(如果安装了的话) - if (!UpgradeSlotCompat.shouldEnableUpgradeSlots()) { - // 安装了appflux:优先使用appflux的升级槽 - try { - // 更安全的方式获取AppliedFlux升级槽 - upgrades = this.eap$getAppliedFluxUpgrades(); - if (upgrades != null) { - } else { - ExtendedAELogger.LOGGER.warn("[样板供应器] 无法获取 appflux 升级槽,回退到兼容槽"); - upgrades = this.eap$compatUpgrades; - } - } catch (Throwable t) { - ExtendedAELogger.LOGGER.error("[样板供应器] 获取 appflux 升级槽失败,回退到兼容槽", t); - upgrades = this.eap$compatUpgrades; - } - } else { - // 未安装appflux:使用我们的兼容升级槽 + IUpgradeInventory upgrades = UpgradeSlotCompat.shouldListenToAppfluxUpgrades() + ? this.eap$getAppliedFluxUpgrades() + : this.eap$compatUpgrades; + if (upgrades == null) { upgrades = this.eap$compatUpgrades; } - // 双重保险:如果主要方式失败,尝试备用方式 if (upgrades == null || !this.eap$hasChannelCard(upgrades)) { - - if (UpgradeSlotCompat.shouldEnableUpgradeSlots()) { - // 如果我们的槽无频道卡,尝试检查是否有AppliedFlux的槽 + if (UpgradeSlotCompat.shouldManageLocalUpgradeInventory()) { try { IUpgradeInventory backupUpgrades = this.eap$getAppliedFluxUpgrades(); if (backupUpgrades != null && this.eap$hasChannelCard(backupUpgrades)) { @@ -317,7 +294,6 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr } catch (Throwable t) { } } else { - // 如果AppliedFlux的槽无频道卡,尝试我们的兼容槽 if (this.eap$compatUpgrades != null && this.eap$hasChannelCard(this.eap$compatUpgrades)) { upgrades = this.eap$compatUpgrades; } @@ -434,21 +410,23 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr */ @Unique private IUpgradeInventory eap$getAppliedFluxUpgrades() { + if (!UpgradeSlotCompat.shouldListenToAppfluxUpgrades()) { + return null; + } + try { - - // 检查当前对象是否实现了IUpgradeableObject接口 - if (this instanceof IUpgradeableObject upgradeableObject) { + if ((Object) this instanceof IUpgradeableObject upgradeableObject) { IUpgradeInventory upgrades = upgradeableObject.getUpgrades(); - - // 确保这不是我们自己的兼容升级槽 if (upgrades != null && upgrades != this.eap$compatUpgrades) { return upgrades; - } else { } - } else { } - } catch (Throwable t) { - ExtendedAELogger.LOGGER.error("[样板供应器] 获取AppliedFlux升级槽时出错", t); + + IUpgradeInventory upgrades = ((PatternProviderLogicAppfluxAccessor) (Object) this).eap$getAppfluxUpgrades(); + if (upgrades != null && upgrades != this.eap$compatUpgrades) { + return upgrades; + } + } catch (Throwable ignored) { } return null; } @@ -547,7 +525,7 @@ public abstract class PatternProviderLogicCompatMixin implements CompatUpgradePr @Unique private IUpgradeInventory eap$compatGetEffectiveUpgrades() { IUpgradeInventory upgrades; - if (UpgradeSlotCompat.shouldEnableUpgradeSlots()) { + if (UpgradeSlotCompat.shouldManageLocalUpgradeInventory()) { upgrades = this.eap$compatUpgrades; } else { upgrades = this.eap$getAppliedFluxUpgrades(); diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicUpgradesMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicUpgradesMixin.java index 21a5f35..5cb5e98 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicUpgradesMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicUpgradesMixin.java @@ -56,7 +56,7 @@ public abstract class InterfaceLogicUpgradesMixin implements CompatUpgradeProvid this.upgrades = UpgradeInventories.forMachine(is, targetSlots, this::eap$onUpgradesChanged); // 设置兼容升级槽 - if (UpgradeSlotCompat.shouldEnableUpgradeSlots()) { + if (UpgradeSlotCompat.shouldManageLocalUpgradeInventory()) { this.eap$compatUpgrades = this.upgrades; } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicUpgradesMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicUpgradesMixin.java index e8c94bd..6fc73ef 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicUpgradesMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/PatternProviderLogicUpgradesMixin.java @@ -5,11 +5,12 @@ import appeng.api.upgrades.IUpgradeInventory; import appeng.api.upgrades.UpgradeInventories; import appeng.helpers.patternprovider.PatternProviderLogic; import appeng.helpers.patternprovider.PatternProviderLogicHost; +import com.extendedae_plus.api.bridge.PatternProviderLogicAppfluxBridge; +import com.extendedae_plus.compat.UpgradeSlotCompat; +import com.extendedae_plus.mixin.appflux.accessor.PatternProviderLogicAppfluxAccessor; import com.extendedae_plus.util.ExtendedAELogger; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; -import net.neoforged.fml.ModList; +import org.spongepowered.asm.mixin.Dynamic; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -17,20 +18,13 @@ import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.List; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; /** - * 为样板供应器添加升级槽支持 - * - 没有 AppliedFlux 时:添加 1 个升级槽 - * - 有 AppliedFlux 时:在其基础上再增加 1 个(总共 2 个) - * - * 优先级 1100 确保在 AppliedFlux (默认优先级 1000) 之后执行 + * 当 appflux 存在时,把它的样板供应器升级槽扩展到我们需要的槽位数。 */ -@Mixin(value = PatternProviderLogic.class, priority = 1100, remap = false) -public abstract class PatternProviderLogicUpgradesMixin { +@Mixin(value = PatternProviderLogic.class, priority = 500, remap = false) +public abstract class PatternProviderLogicUpgradesMixin implements PatternProviderLogicAppfluxBridge { @Final @Shadow @@ -42,111 +36,74 @@ public abstract class PatternProviderLogicUpgradesMixin { @Unique private IUpgradeInventory eap$upgrades = UpgradeInventories.empty(); - - @Unique - private boolean eap$hasAppliedFlux = false; - - @Unique - private boolean eap$upgradesInitialized = false; @Inject(method = "(Lappeng/api/networking/IManagedGridNode;Lappeng/helpers/patternprovider/PatternProviderLogicHost;I)V", at = @At("TAIL")) private void eap$initUpgrades(IManagedGridNode mainNode, PatternProviderLogicHost host, int patternInventorySize, CallbackInfo ci) { try { - // 检测是否安装了 AppliedFlux - this.eap$hasAppliedFlux = ModList.get().isLoaded("appflux"); - - if (eap$hasAppliedFlux) { - // AppliedFlux 已安装,尝试获取并扩展其升级槽 - eap$extendAppliedFluxUpgrades(); - } // 未安装 AppliedFlux 的情况由 CompatMixin 负责创建兼容升级槽 + if (UpgradeSlotCompat.shouldListenToAppfluxUpgrades()) { + this.eap$ensureAppliedFluxUpgradeSlots(); + } } catch (Throwable t) { ExtendedAELogger.LOGGER.error("[样板供应器][升级槽] 初始化失败", t); } } + + @Dynamic("AppFlux mixin adds IUpgradeableObject#getUpgrades to PatternProviderLogic") + @Inject(method = "getUpgrades", at = @At("RETURN"), cancellable = true, remap = false, require = 0) + private void eap$wrapAppfluxGetUpgrades(CallbackInfoReturnable cir) { + if (!UpgradeSlotCompat.shouldListenToAppfluxUpgrades()) { + return; + } + + IUpgradeInventory ensured = this.eap$ensureAppliedFluxUpgradeSlots(cir.getReturnValue()); + if (ensured != null && ensured != cir.getReturnValue()) { + cir.setReturnValue(ensured); + } + } + @Override + public IUpgradeInventory eap$ensureAppfluxUpgradeSlots() { + return this.eap$ensureAppliedFluxUpgradeSlots(); + } + @Unique - private void eap$extendAppliedFluxUpgrades() { + private IUpgradeInventory eap$ensureAppliedFluxUpgradeSlots() { + return this.eap$ensureAppliedFluxUpgradeSlots(null); + } + + @Unique + private IUpgradeInventory eap$ensureAppliedFluxUpgradeSlots(IUpgradeInventory currentUpgrades) { try { - // 通过反射直接读取 AppliedFlux Mixin 注入的字段:af_upgrades - IUpgradeInventory existingUpgrades = null; - try { - Field f = this.getClass().getDeclaredField("af_upgrades"); - f.setAccessible(true); - existingUpgrades = (IUpgradeInventory) f.get(this); - } catch (Throwable t) { + PatternProviderLogicAppfluxAccessor accessor = (PatternProviderLogicAppfluxAccessor) (Object) this; + IUpgradeInventory existingUpgrades = currentUpgrades != null ? currentUpgrades : accessor.eap$getAppfluxUpgrades(); + int targetSlots = UpgradeSlotCompat.getPatternProviderAppfluxUpgradeSlots(); + + if (existingUpgrades != null && existingUpgrades.size() >= targetSlots) { + this.eap$upgrades = existingUpgrades; + return existingUpgrades; } - - if (existingUpgrades != null && existingUpgrades != UpgradeInventories.empty()) { - // AppliedFlux 已经创建了升级槽 - int currentSlots = existingUpgrades.size(); - int targetSlots = 2; // AppliedFlux 1个 + 我们 1个 = 2个 - - - if (currentSlots < targetSlots) { - // 需要扩展升级槽 - // 先保存现有物品 - ItemStack[] savedItems = new ItemStack[currentSlots]; - for (int i = 0; i < currentSlots; i++) { - savedItems[i] = existingUpgrades.getStackInSlot(i).copy(); - } - - // 创建新的升级槽(更多槽位) - this.eap$upgrades = UpgradeInventories.forMachine( - host.getTerminalIcon().getItem(), - targetSlots, - this::eap$onUpgradesChanged - ); - - // 恢复原有物品 - for (int i = 0; i < savedItems.length; i++) { - this.eap$upgrades.setItemDirect(i, savedItems[i]); - } - // 将 AF 的字段指向我们新的升级槽,保持其服务与 NBT 钩子一致 - try { - Field f = this.getClass().getDeclaredField("af_upgrades"); - f.setAccessible(true); - f.set(this, this.eap$upgrades); - } catch (Throwable t) { - } - - this.eap$upgradesInitialized = true; - } else { - // AppliedFlux 或其他模组已经提供了足够的槽位 - this.eap$upgrades = existingUpgrades; - this.eap$upgradesInitialized = true; - } - } else { - // AppliedFlux 还没初始化升级槽,或者出了问题,我们创建默认的 - this.eap$upgrades = UpgradeInventories.forMachine( - host.getTerminalIcon().getItem(), - 2, + + this.eap$upgrades = UpgradeInventories.forMachine( + host.getTerminalIcon().getItem(), + targetSlots, this::eap$onUpgradesChanged - ); - // 同步 AF 字段 - try { - Field f = this.getClass().getDeclaredField("af_upgrades"); - f.setAccessible(true); - f.set(this, this.eap$upgrades); - } catch (Throwable t) { + ); + + if (existingUpgrades != null) { + for (int i = 0; i < Math.min(existingUpgrades.size(), this.eap$upgrades.size()); i++) { + ItemStack stack = existingUpgrades.getStackInSlot(i).copy(); + if (!stack.isEmpty()) { + this.eap$upgrades.insertItem(i, stack, false); + } } - this.eap$upgradesInitialized = true; } + + accessor.eap$setAppfluxUpgrades(this.eap$upgrades); + return this.eap$upgrades; } catch (Throwable t) { ExtendedAELogger.LOGGER.error("[样板供应器][升级槽] 扩展 AppliedFlux 升级槽失败", t); - // 失败时创建默认数量 - this.eap$upgrades = UpgradeInventories.forMachine( - host.getTerminalIcon().getItem(), - 2, - this::eap$onUpgradesChanged - ); - // 同步 AF 字段(最佳努力) - try { - Field f = this.getClass().getDeclaredField("af_upgrades"); - f.setAccessible(true); - f.set(this, this.eap$upgrades); - } catch (Throwable ignored) {} - this.eap$upgradesInitialized = true; + return currentUpgrades; } } @@ -154,116 +111,16 @@ public abstract class PatternProviderLogicUpgradesMixin { private void eap$onUpgradesChanged() { try { this.host.saveChanges(); - - // 如果 AppliedFlux 安装了,也调用其原始的 onUpgradesChanged 方法 - if (eap$hasAppliedFlux) { - try { - Method afMethod = this.getClass().getDeclaredMethod("af_onUpgradesChanged"); - afMethod.setAccessible(true); - afMethod.invoke(this); - } catch (NoSuchMethodException e) { - // AppliedFlux 的方法不存在,这是正常的 - } catch (Throwable t) { - } + try { + ((PatternProviderLogicAppfluxAccessor) (Object) this).eap$invokeAppfluxUpgradesChanged(); + return; + } catch (Throwable ignored) { } - - // 通过 Bridge 接口通知 CompatMixin 升级槽已变更 - // 这样无论是否安装 AppFlux,所有升级槽变更都会触发频道卡/虚拟合成卡的重新检测 if ((Object) this instanceof com.extendedae_plus.api.bridge.PatternProviderLogicUpgradeCompatBridge bridge) { bridge.eap$onCompatUpgradesChangedHook(); } - } catch (Throwable t) { ExtendedAELogger.LOGGER.error("[样板供应器][升级槽] onUpgradesChanged 处理失败", t); } } - - - - @Inject(method = "writeToNBT", at = @At("TAIL")) - private void eap$saveUpgrades(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) { - try { - // 已安装 AF 时交由 AF 的 mixin 处理,避免重复写入 - if (eap$hasAppliedFlux) { - return; - } - if (eap$upgradesInitialized && this.eap$upgrades != null && this.eap$upgrades != UpgradeInventories.empty()) { - // 根据是否有 AppliedFlux 使用不同的 NBT 键 - if (eap$hasAppliedFlux) { - // AppliedFlux 使用 "upgrades" 键,我们使用 "eap_upgrades" 避免冲突 - this.eap$upgrades.writeToNBT(tag, "eap_upgrades", registries); - } else { - // 没有 AppliedFlux,使用标准键 - this.eap$upgrades.writeToNBT(tag, "upgrades", registries); - } - } - } catch (Throwable t) { - ExtendedAELogger.LOGGER.error("[样板供应器][升级槽] 保存升级槽失败", t); - } - } - - @Inject(method = "readFromNBT", at = @At("TAIL")) - private void eap$loadUpgrades(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) { - try { - // 重新检测 AppliedFlux 状态(可能在世界加载时状态有变化) - this.eap$hasAppliedFlux = ModList.get().isLoaded("appflux"); - - if (!eap$upgradesInitialized) { - // 如果还没初始化,先初始化 - if (eap$hasAppliedFlux) { - eap$extendAppliedFluxUpgrades(); - } else { - this.eap$upgrades = UpgradeInventories.forMachine( - host.getTerminalIcon().getItem(), - 1, - this::eap$onUpgradesChanged - ); - this.eap$upgradesInitialized = true; - } - } - - // 已安装 AF 时,由 AF 自行从 "upgrades" 读取;我们只处理无 AF 情况 - if (!eap$hasAppliedFlux && this.eap$upgrades != null && this.eap$upgrades != UpgradeInventories.empty()) { - if (tag.contains("upgrades")) { - this.eap$upgrades.readFromNBT(tag, "upgrades", registries); - } - } - } catch (Throwable t) { - ExtendedAELogger.LOGGER.error("[样板供应器][升级槽] 加载升级槽失败", t); - } - } - - @Inject(method = "addDrops", at = @At("TAIL")) - private void eap$dropUpgrades(List drops, CallbackInfo ci) { - try { - // AF 已安装时交由其自身处理掉落 - if (eap$hasAppliedFlux) { - return; - } - if (eap$upgradesInitialized && this.eap$upgrades != null) { - for (var is : this.eap$upgrades) { - if (!is.isEmpty()) { - drops.add(is); - } - } - } - } catch (Throwable t) { - ExtendedAELogger.LOGGER.error("[样板供应器][升级槽] 添加掉落失败", t); - } - } - - @Inject(method = "clearContent", at = @At("TAIL")) - private void eap$clearUpgrades(CallbackInfo ci) { - try { - // AF 已安装时交由其自身处理清理 - if (eap$hasAppliedFlux) { - return; - } - if (eap$upgradesInitialized && this.eap$upgrades != null) { - this.eap$upgrades.clear(); - } - } catch (Throwable t) { - ExtendedAELogger.LOGGER.error("[样板供应器][升级槽] 清空升级槽失败", t); - } - } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuUpgradesMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuUpgradesMixin.java index 1b6b271..1882eaf 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuUpgradesMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/menu/PatternProviderMenuUpgradesMixin.java @@ -7,6 +7,7 @@ import appeng.menu.ToolboxMenu; import appeng.menu.implementations.PatternProviderMenu; import com.extendedae_plus.api.bridge.CompatUpgradeProvider; import com.extendedae_plus.api.bridge.IUpgradableMenu; +import com.extendedae_plus.api.bridge.PatternProviderLogicAppfluxBridge; import com.extendedae_plus.compat.UpgradeSlotCompat; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.MenuType; @@ -30,10 +31,20 @@ public abstract class PatternProviderMenuUpgradesMixin extends AEBaseMenu implem super(menuType, id, playerInventory, host); } + @Inject(method = "(Lnet/minecraft/world/inventory/MenuType;ILnet/minecraft/world/entity/player/Inventory;Lappeng/helpers/patternprovider/PatternProviderLogicHost;)V", + at = @At(value = "INVOKE", target = "Lappeng/menu/implementations/PatternProviderMenu;createPlayerInventorySlots(Lnet/minecraft/world/entity/player/Inventory;)V"), + remap = false) + private void eap$ensureAppfluxUpgrades(MenuType menuType, int id, Inventory playerInventory, PatternProviderLogicHost host, CallbackInfo ci) { + if (UpgradeSlotCompat.shouldListenToAppfluxUpgrades() + && (Object) this.logic instanceof PatternProviderLogicAppfluxBridge bridge) { + bridge.eap$ensureAppfluxUpgradeSlots(); + } + } + @Inject(method = "(Lnet/minecraft/world/inventory/MenuType;ILnet/minecraft/world/entity/player/Inventory;Lappeng/helpers/patternprovider/PatternProviderLogicHost;)V", at = @At("TAIL")) private void eap$initUpgrades(MenuType menuType, int id, Inventory playerInventory, PatternProviderLogicHost host, CallbackInfo ci) { - if (UpgradeSlotCompat.shouldEnableUpgradeSlots()) { + if (UpgradeSlotCompat.shouldManageLocalUpgradeInventory()) { this.eap$toolbox = new ToolboxMenu(this); this.setupUpgrades(((CompatUpgradeProvider) this.logic).eap$getCompatUpgrades()); } diff --git a/src/main/java/com/extendedae_plus/mixin/appflux/accessor/PatternProviderLogicAppfluxAccessor.java b/src/main/java/com/extendedae_plus/mixin/appflux/accessor/PatternProviderLogicAppfluxAccessor.java new file mode 100644 index 0000000..e5eb584 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/appflux/accessor/PatternProviderLogicAppfluxAccessor.java @@ -0,0 +1,19 @@ +package com.extendedae_plus.mixin.appflux.accessor; + +import appeng.api.upgrades.IUpgradeInventory; +import appeng.helpers.patternprovider.PatternProviderLogic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(value = PatternProviderLogic.class, priority = 500, remap = false) +public interface PatternProviderLogicAppfluxAccessor { + @Accessor(value = "af_upgrades", remap = false) + IUpgradeInventory eap$getAppfluxUpgrades(); + + @Accessor(value = "af_upgrades", remap = false) + void eap$setAppfluxUpgrades(IUpgradeInventory upgrades); + + @Invoker(value = "af_onUpgradesChanged", remap = false) + void eap$invokeAppfluxUpgradesChanged(); +} diff --git a/src/main/resources/extendedae_plus.mixins.json b/src/main/resources/extendedae_plus.mixins.json index 45fffd5..5068161 100644 --- a/src/main/resources/extendedae_plus.mixins.json +++ b/src/main/resources/extendedae_plus.mixins.json @@ -53,6 +53,7 @@ "ae2.parts.automation.IOBusPartChannelCardMixin", "ae2.parts.storagebus.StorageBusPartChannelCardMixin", "ae2WTlib.ContainerUWirelessExPatternTerminalMixin", + "appflux.accessor.PatternProviderLogicAppfluxAccessor", "extendedae.accessor.TileAssemblerMatrixCrafterAccessor", "extendedae.accessor.TileAssemblerMatrixPatternAccessor", "extendedae.common.PartExPatternProviderMixin",