优化appflux升级槽兼容
This commit is contained in:
parent
9d73964196
commit
9d126e65a0
|
|
@ -0,0 +1,7 @@
|
|||
package com.extendedae_plus.api.bridge;
|
||||
|
||||
import appeng.api.upgrades.IUpgradeInventory;
|
||||
|
||||
public interface PatternProviderLogicAppfluxBridge {
|
||||
IUpgradeInventory eap$ensureAppfluxUpgradeSlots();
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) { }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<C extends PatternProvid
|
|||
|
||||
@Inject(method = "<init>", at = @At("TAIL"), remap = false)
|
||||
private void eap$initUpgrades(PatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
|
||||
|
||||
if (!UpgradeSlotCompat.shouldAddUpgradePanelToScreen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 若已安装 AppliedFlux,则由 AE2/AppliedFlux 自己负责渲染升级面板,避免我们重复添加导致界面显示两个槽
|
||||
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots()) {
|
||||
if (!UpgradeSlotCompat.shouldManageLocalUpgradeInventory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用改进的AppliedFlux兼容性检测
|
||||
@SuppressWarnings("unchecked")
|
||||
PatternProviderScreen<PatternProviderMenu> screen = (PatternProviderScreen<PatternProviderMenu>) (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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ItemStack> 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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = "<init>(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<IUpgradeInventory> 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<ItemStack> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = "<init>(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 = "<init>(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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user