重写mixin plugin, 修正逻辑, 去掉无用内容
This commit is contained in:
parent
4dfba61426
commit
1d115c46e0
|
|
@ -1,23 +1,9 @@
|
|||
package com.extendedae_plus.compat;
|
||||
|
||||
import appeng.api.upgrades.IUpgradeInventory;
|
||||
import appeng.api.upgrades.IUpgradeableObject;
|
||||
import appeng.client.gui.style.ScreenStyle;
|
||||
import appeng.client.gui.widgets.ToolboxPanel;
|
||||
import appeng.client.gui.widgets.UpgradesPanel;
|
||||
import appeng.core.localization.GuiText;
|
||||
import appeng.helpers.patternprovider.PatternProviderLogicHost;
|
||||
import appeng.menu.AEBaseMenu;
|
||||
import appeng.menu.SlotSemantics;
|
||||
import appeng.menu.ToolboxMenu;
|
||||
import com.extendedae_plus.util.Logger;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 升级卡槽兼容性管理类
|
||||
* 检测ExtendedAE-appflux模组是否存在,如果存在则使用其升级卡槽功能
|
||||
|
|
@ -59,140 +45,7 @@ public class UpgradeSlotCompat {
|
|||
public static boolean shouldAddUpgradePanelToScreen() {
|
||||
return shouldEnableUpgradeSlots();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化菜单升级功能(如果需要的话)
|
||||
* @param menu 目标菜单
|
||||
* @param host 样板供应器逻辑主机
|
||||
* @return 是否成功初始化
|
||||
*/
|
||||
public static boolean initMenuUpgrades(AEBaseMenu menu, PatternProviderLogicHost host) {
|
||||
if (!shouldEnableUpgradeSlots()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 创建工具箱菜单
|
||||
ToolboxMenu toolbox = new ToolboxMenu(menu);
|
||||
|
||||
// 设置升级槽
|
||||
if (host instanceof IUpgradeableObject upgradeableHost) {
|
||||
// 使用反射调用protected的setupUpgrades方法
|
||||
try {
|
||||
var setupUpgradesMethod = AEBaseMenu.class.getDeclaredMethod("setupUpgrades", IUpgradeInventory.class);
|
||||
setupUpgradesMethod.setAccessible(true);
|
||||
setupUpgradesMethod.invoke(menu, upgradeableHost.getUpgrades());
|
||||
} catch (Exception e) {
|
||||
Logger.EAP$LOGGER.error("反射调用setupUpgrades失败", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 使用反射或接口设置工具箱
|
||||
if (menu instanceof IUpgradeableMenuCompat compatMenu) {
|
||||
compatMenu.setCompatToolbox(toolbox);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.EAP$LOGGER.error("初始化PatternProviderMenu升级功能时出错", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为Screen添加升级面板(如果需要的话)
|
||||
* @param widgets 小部件映射
|
||||
* @param menu 菜单实例
|
||||
* @param style 屏幕样式
|
||||
* @return 是否成功添加
|
||||
*/
|
||||
public static boolean addUpgradePanelToScreen(Object widgets, Object menu, ScreenStyle style) {
|
||||
if (!shouldAddUpgradePanelToScreen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (menu instanceof IUpgradeableMenuCompat compatMenu) {
|
||||
try {
|
||||
// 使用反射获取widgets的add方法 - 尝试不同的方法签名
|
||||
var widgetsClass = widgets.getClass();
|
||||
var addMethod = widgetsClass.getDeclaredMethod("add", String.class, Object.class);
|
||||
addMethod.setAccessible(true);
|
||||
|
||||
// 获取升级槽位
|
||||
var menuClass = menu.getClass();
|
||||
var getSlotsMethod = menuClass.getMethod("getSlots", SlotSemantics.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Slot> upgradeSlots = (List<Slot>) getSlotsMethod.invoke(menu, SlotSemantics.UPGRADE);
|
||||
|
||||
// 添加升级面板
|
||||
UpgradesPanel upgradesPanel = new UpgradesPanel(upgradeSlots, () -> getCompatibleUpgrades(compatMenu));
|
||||
addMethod.invoke(widgets, "upgrades", upgradesPanel);
|
||||
|
||||
// 添加工具箱面板(如果存在)
|
||||
ToolboxMenu toolbox = compatMenu.getCompatToolbox();
|
||||
if (toolbox != null && toolbox.isPresent()) {
|
||||
ToolboxPanel toolboxPanel = new ToolboxPanel(style, toolbox.getName());
|
||||
addMethod.invoke(widgets, "toolbox", toolboxPanel);
|
||||
}
|
||||
return true;
|
||||
} catch (NoSuchMethodException e) {
|
||||
// 尝试其他可能的方法签名
|
||||
try {
|
||||
var widgetsClass = widgets.getClass();
|
||||
var putMethod = widgetsClass.getDeclaredMethod("put", String.class, Object.class);
|
||||
putMethod.setAccessible(true);
|
||||
|
||||
// 获取升级槽位
|
||||
var menuClass = menu.getClass();
|
||||
var getSlotsMethod = menuClass.getMethod("getSlots", SlotSemantics.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Slot> upgradeSlots = (List<Slot>) getSlotsMethod.invoke(menu, SlotSemantics.UPGRADE);
|
||||
|
||||
// 添加升级面板
|
||||
UpgradesPanel upgradesPanel = new UpgradesPanel(upgradeSlots, () -> getCompatibleUpgrades(compatMenu));
|
||||
putMethod.invoke(widgets, "upgrades", upgradesPanel);
|
||||
|
||||
// 添加工具箱面板(如果存在)
|
||||
ToolboxMenu toolbox = compatMenu.getCompatToolbox();
|
||||
if (toolbox != null && toolbox.isPresent()) {
|
||||
ToolboxPanel toolboxPanel = new ToolboxPanel(style, toolbox.getName());
|
||||
putMethod.invoke(widgets, "toolbox", toolboxPanel);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e2) {
|
||||
Logger.EAP$LOGGER.error("反射调用widgets方法失败", e2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.EAP$LOGGER.error("为PatternProviderScreen添加升级面板时出错", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取兼容的升级列表
|
||||
*/
|
||||
private static List<Component> getCompatibleUpgrades(IUpgradeableMenuCompat menu) {
|
||||
var list = new ArrayList<Component>();
|
||||
list.add(GuiText.CompatibleUpgrades.text());
|
||||
|
||||
try {
|
||||
IUpgradeInventory upgrades = menu.getCompatUpgrades();
|
||||
if (upgrades != null) {
|
||||
list.addAll(appeng.api.upgrades.Upgrades.getTooltipLinesForMachine(upgrades.getUpgradableItem()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.EAP$LOGGER.error("获取兼容升级列表时出错", e);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 兼容性升级菜单接口
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.extendedae_plus.mixin;
|
||||
|
||||
import com.extendedae_plus.util.ModCheckUtils;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
|
|
@ -24,70 +25,33 @@ public class MixinConditions implements IMixinConfigPlugin {
|
|||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
// 对于升级相关的Mixin,检查appflux是否存在
|
||||
if (mixinClassName.contains("PatternProviderMenuUpgradesMixin") ||
|
||||
mixinClassName.contains("PatternProviderLogicUpgradesMixin") ||
|
||||
mixinClassName.contains("PatternProviderLogicHostUpgradesMixin")) {
|
||||
|
||||
try {
|
||||
// 检查ModList是否已初始化
|
||||
if (net.minecraftforge.fml.ModList.get() == null) {
|
||||
System.out.println("[ExtendedAE_Plus] ModList未初始化,默认应用升级Mixin: " + mixinClassName);
|
||||
return true; // 修改策略:未初始化时默认应用,运行时再检查
|
||||
}
|
||||
|
||||
boolean appfluxExists = net.minecraftforge.fml.ModList.get().isLoaded("appflux");
|
||||
boolean shouldApply = !appfluxExists;
|
||||
|
||||
System.out.println("[ExtendedAE_Plus] 升级Mixin检查: " + mixinClassName +
|
||||
", appflux存在: " + appfluxExists +
|
||||
", 应用Mixin: " + shouldApply);
|
||||
|
||||
try {
|
||||
// === MAE2 兼容 ===
|
||||
if (mixinClassName.contains("CraftingCPUClusterMixin")) {
|
||||
boolean shouldApply = !ModCheckUtils.isLoaded(ModCheckUtils.MODID_MAE2);
|
||||
log(mixinClassName, "MAE2", shouldApply);
|
||||
return shouldApply;
|
||||
} catch (Exception e) {
|
||||
System.out.println("[ExtendedAE_Plus] ModList检查失败,默认应用升级Mixin: " + mixinClassName);
|
||||
return true; // 修改策略:出错时默认应用,运行时再检查
|
||||
}
|
||||
}
|
||||
|
||||
// 对于appflux相关的Mixin,总是加载但在运行时检查条件
|
||||
if (mixinClassName.contains("AppfluxPatternProviderLogicMixin")) {
|
||||
System.out.println("[ExtendedAE_Plus] 总是加载appflux Mixin,运行时检查条件: " + mixinClassName);
|
||||
return true; // 总是加载,在Mixin内部进行运行时检查
|
||||
}
|
||||
|
||||
// 对于InterfaceLogicUpgradesMixin,总是加载但在运行时检查条件
|
||||
if (mixinClassName.contains("InterfaceLogicUpgradesMixin")) {
|
||||
System.out.println("[ExtendedAE_Plus] 总是加载Interface升级Mixin,运行时检查条件: " + mixinClassName);
|
||||
return true; // 总是加载,在Mixin内部进行运行时检查
|
||||
}
|
||||
|
||||
// 对于CraftingCPUClusterMixin,检查MAE2是否存在
|
||||
if (mixinClassName.contains("CraftingCPUClusterMixin")) {
|
||||
try {
|
||||
// 检查ModList是否已初始化
|
||||
if (net.minecraftforge.fml.ModList.get() == null) {
|
||||
System.out.println("[ExtendedAE_Plus] ModList未初始化,默认应用CraftingCPU Mixin: " + mixinClassName);
|
||||
return true; // 未初始化时默认应用
|
||||
}
|
||||
|
||||
boolean mae2Exists = net.minecraftforge.fml.ModList.get().isLoaded("mae2");
|
||||
boolean shouldApply = !mae2Exists;
|
||||
|
||||
System.out.println("[ExtendedAE_Plus] CraftingCPU Mixin检查: " + mixinClassName +
|
||||
", MAE2存在: " + mae2Exists +
|
||||
", 应用Mixin: " + shouldApply);
|
||||
|
||||
|
||||
// === AAE 兼容 ===
|
||||
if (mixinClassName.startsWith("com.extendedae_plus.mixin.advancedae")) {
|
||||
boolean shouldApply = ModCheckUtils.isLoaded(ModCheckUtils.MODID_AAE);
|
||||
log(mixinClassName, "aae", shouldApply);
|
||||
return shouldApply;
|
||||
} catch (Exception e) {
|
||||
System.out.println("[ExtendedAE_Plus] ModList检查失败,默认跳过CraftingCPU Mixin: " + mixinClassName);
|
||||
return false; // 出错时默认跳过,避免冲突
|
||||
}
|
||||
|
||||
// === GuideME 版本兼容 ===
|
||||
if (mixinClassName.startsWith("com.extendedae_plus.mixin.guideme.")) {
|
||||
boolean shouldApply = ModCheckUtils.isLoadedAndLowerThan(ModCheckUtils.MODID_GUIDEME, "20.1.14");
|
||||
logVersion(mixinClassName, "GuideME", ModCheckUtils.getVersion(ModCheckUtils.MODID_GUIDEME), "20.1.14", shouldApply);
|
||||
return shouldApply;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
System.err.println("[ExtendedAE_Plus] 检查 Mixin 条件时出错: " + e.getMessage());
|
||||
return true; // 出错默认加载,避免意外禁用
|
||||
}
|
||||
|
||||
// 其他Mixin正常应用
|
||||
System.out.println("[ExtendedAE_Plus] 加载Mixin: " + mixinClassName);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -109,4 +73,15 @@ public class MixinConditions implements IMixinConfigPlugin {
|
|||
public void postApply(String targetClassName, org.objectweb.asm.tree.ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
// 应用后调用
|
||||
}
|
||||
|
||||
// === 日志方法 ===
|
||||
private void log(String mixin, String mod, boolean apply) {
|
||||
System.out.printf("[ExtendedAE_Plus] 模组 %s 存在: %s, 应用 Mixin: %s, Mixin类:%s%n",
|
||||
mod, ModCheckUtils.isLoaded(mod), apply, mixin);
|
||||
}
|
||||
|
||||
private void logVersion(String mixin, String mod, String detected, String target, boolean apply) {
|
||||
System.out.printf("[ExtendedAE_Plus] 模组 %s 版本检测: 当前 %s, 目标 < %s, 应用 Mixin: %s%n",
|
||||
mod, detected, target, apply);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
package com.extendedae_plus.mixin.ae2.menu;
|
||||
|
||||
import appeng.api.upgrades.IUpgradeInventory;
|
||||
import appeng.api.upgrades.IUpgradeableObject;
|
||||
import appeng.helpers.patternprovider.PatternProviderLogic;
|
||||
import appeng.helpers.patternprovider.PatternProviderLogicHost;
|
||||
import appeng.menu.AEBaseMenu;
|
||||
import appeng.menu.ToolboxMenu;
|
||||
import appeng.menu.implementations.PatternProviderMenu;
|
||||
import com.extendedae_plus.api.bridge.IUpgradableMenu;
|
||||
import com.extendedae_plus.compat.UpgradeSlotCompat;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
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;
|
||||
|
||||
@Mixin(value = PatternProviderMenu.class, priority = 2000, remap = false)
|
||||
public abstract class PatternProviderMenuUpgradesMixin extends AEBaseMenu implements IUpgradableMenu {
|
||||
@Final
|
||||
@Shadow protected PatternProviderLogic logic;
|
||||
|
||||
@Unique
|
||||
private ToolboxMenu eap$toolbox;
|
||||
|
||||
@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()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.eap$toolbox = new ToolboxMenu(this);
|
||||
this.setupUpgrades(((IUpgradeableObject) host).getUpgrades());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ToolboxMenu getToolbox() {
|
||||
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots()) {
|
||||
return null;
|
||||
}
|
||||
return this.eap$toolbox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUpgradeInventory getUpgrades() {
|
||||
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots()) {
|
||||
return appeng.api.upgrades.UpgradeInventories.empty();
|
||||
}
|
||||
return ((IUpgradeableObject) this.logic).getUpgrades();
|
||||
}
|
||||
|
||||
public PatternProviderMenuUpgradesMixin(MenuType<?> menuType, int id, Inventory playerInventory, Object host) {
|
||||
super(menuType, id, playerInventory, host);
|
||||
}
|
||||
}
|
||||
81
src/main/java/com/extendedae_plus/util/ModCheckUtils.java
Normal file
81
src/main/java/com/extendedae_plus/util/ModCheckUtils.java
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package com.extendedae_plus.util;
|
||||
|
||||
import net.minecraftforge.fml.loading.LoadingModList;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||
|
||||
/**
|
||||
* Forge 加载阶段的 Mod 检测工具
|
||||
* 适用于 MixinConfigPlugin 阶段使用
|
||||
* 包含版本比较工具
|
||||
*/
|
||||
public class ModCheckUtils {
|
||||
|
||||
private static final LoadingModList MOD_LIST = LoadingModList.get();
|
||||
|
||||
public static final String
|
||||
MODID_JEI = "jei",
|
||||
MODID_EMI = "emi",
|
||||
MODID_AE = "ae2",
|
||||
MODID_AAE = "advanced_ae",
|
||||
MODID_AE2WTLIB = "ae2wtlib",
|
||||
MODID_FTB_TEAMS = "ftbteams",
|
||||
MODID_APPFLUX = "appflux",
|
||||
MODID_GUIDEME = "guideme",
|
||||
MODID_MAE2 = "mae2";
|
||||
|
||||
/**
|
||||
* 检查指定模组是否存在
|
||||
*/
|
||||
public static boolean isLoaded(String modid) {
|
||||
return MOD_LIST != null && MOD_LIST.getModFileById(modid) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模组版本号(x.x.x),若不存在则返回 "0.0.0"
|
||||
*/
|
||||
public static String getVersion(String modid) {
|
||||
if (MOD_LIST == null) return "0.0.0";
|
||||
ModFileInfo file = MOD_LIST.getModFileById(modid);
|
||||
if (file == null || file.getMods().isEmpty()) return "0.0.0";
|
||||
return file.getMods().get(0).getVersion().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查模组是否存在且版本低于指定版本
|
||||
*/
|
||||
public static boolean isLoadedAndLowerThan(String modid, String targetVersion) {
|
||||
if (!isLoaded(modid)) return false;
|
||||
return isVersionLower(getVersion(modid), targetVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个版本号
|
||||
*
|
||||
* @param current 当前版本号,格式 x.x.x
|
||||
* @param target 目标版本号,格式 x.x.x
|
||||
* @return true 如果 current < target,否则 false
|
||||
*/
|
||||
public static boolean isVersionLower(String current, String target) {
|
||||
if (current == null || target == null) return false;
|
||||
|
||||
String[] curParts = current.split("\\.");
|
||||
String[] tarParts = target.split("\\.");
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int curNum = i < curParts.length ? parse(curParts[i]) : 0;
|
||||
int tarNum = i < tarParts.length ? parse(tarParts[i]) : 0;
|
||||
|
||||
if (curNum < tarNum) return true;
|
||||
if (curNum > tarNum) return false;
|
||||
}
|
||||
return false; // 相等则不小于
|
||||
}
|
||||
|
||||
private static int parse(String s) {
|
||||
try {
|
||||
return Integer.parseInt(s.replaceAll("[^0-9]", ""));
|
||||
} catch (Exception e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user