为me接口增加一个升级槽,并且兼容applied flux

This commit is contained in:
GaLicn 2025-09-23 19:03:23 +08:00
parent 66b581c2a7
commit 476b669472
5 changed files with 160 additions and 297 deletions

View File

@ -81,7 +81,7 @@ dependencies {
annotationProcessor "org.spongepowered:mixin:${mixin_version}:processor"
// modImplementation "curse.maven:applied-flux-965012:6755986"
modImplementation "curse.maven:applied-flux-965012:6755986"
modCompileOnly "curse.maven:mega-cells-622112:${mega_cells_version}"
modCompileOnly "curse.maven:jade-324717:${jade_version}"

View File

@ -0,0 +1,80 @@
package com.extendedae_plus.mixin.ae2;
import appeng.api.networking.IManagedGridNode;
import appeng.api.upgrades.IUpgradeInventory;
import appeng.api.upgrades.UpgradeInventories;
import appeng.helpers.InterfaceLogic;
import appeng.helpers.InterfaceLogicHost;
import com.extendedae_plus.compat.UpgradeSlotCompat;
import net.minecraft.world.item.Item;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* 为ME接口增加升级槽数量的Mixin
* 兼容Applied Flux模组避免冲突
*/
@Mixin(value = InterfaceLogic.class, remap = false, priority = 1500)
public class InterfaceLogicUpgradesMixin {
@Final
@Mutable
@Shadow
private IUpgradeInventory upgrades;
@Shadow
protected void onUpgradesChanged() {}
/**
* 在InterfaceLogic构造函数末尾注入增加升级槽数量
* 使用高优先级(1500)确保在Applied Flux之后执行
*/
@Inject(
method = "<init>(Lappeng/api/networking/IManagedGridNode;Lappeng/helpers/InterfaceLogicHost;Lnet/minecraft/world/item/Item;I)V",
at = @At("TAIL")
)
private void expandInterfaceUpgrades(IManagedGridNode gridNode, InterfaceLogicHost host, Item is, int slots, CallbackInfo ci) {
try {
System.out.println("[ExtendedAE_Plus] InterfaceLogic升级槽扩展开始");
// 检查Applied Flux是否已经修改了升级槽
if (UpgradeSlotCompat.isAppfluxPresent()) {
System.out.println("[ExtendedAE_Plus] 检测到Applied Flux存在");
// Applied Flux存在检查当前升级槽数量
int currentSlots = this.upgrades.size();
System.out.println("[ExtendedAE_Plus] 当前升级槽数量: " + currentSlots);
if (currentSlots >= 3) {
// Applied Flux已经增加了升级槽到3个或更多我们不需要再修改
System.out.println("[ExtendedAE_Plus] Applied Flux已经增加了足够的升级槽跳过修改");
return;
} else if (currentSlots == 2) {
// Applied Flux增加到2个我们再增加1个到3个
System.out.println("[ExtendedAE_Plus] Applied Flux增加到2个槽我们再增加到3个");
this.upgrades = UpgradeInventories.forMachine(is, 3, this::onUpgradesChanged);
} else {
// Applied Flux可能还没有生效我们直接增加到3个
System.out.println("[ExtendedAE_Plus] Applied Flux可能未生效直接增加到3个槽");
this.upgrades = UpgradeInventories.forMachine(is, 3, this::onUpgradesChanged);
}
} else {
System.out.println("[ExtendedAE_Plus] Applied Flux不存在");
// Applied Flux不存在我们将升级槽从1个增加到2个
int currentSlots = this.upgrades.size();
System.out.println("[ExtendedAE_Plus] 当前升级槽数量: " + currentSlots + "增加到2个");
this.upgrades = UpgradeInventories.forMachine(is, 2, this::onUpgradesChanged);
}
System.out.println("[ExtendedAE_Plus] InterfaceLogic升级槽扩展完成最终槽数: " + this.upgrades.size());
} catch (Exception e) {
// 发生异常时不修改升级槽确保不会崩溃
System.err.println("[ExtendedAE_Plus] Failed to expand interface upgrades: " + e.getMessage());
e.printStackTrace();
}
}
}

View File

@ -1,24 +0,0 @@
package com.extendedae_plus.mixin.ae2.helpers.patternprovider;
import appeng.api.upgrades.IUpgradeInventory;
import appeng.api.upgrades.IUpgradeableObject;
import appeng.helpers.patternprovider.PatternProviderLogic;
import appeng.helpers.patternprovider.PatternProviderLogicHost;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
/**
* PatternProviderLogicHost 作为 IUpgradeableObject 的代理菜单可从 host 获取升级槽
*/
@Mixin(value = PatternProviderLogicHost.class, priority = 2000, remap = false)
public interface PatternProviderLogicHostUpgradesMixin extends IUpgradeableObject {
@Shadow PatternProviderLogic getLogic();
@Override
default IUpgradeInventory getUpgrades() {
if (!com.extendedae_plus.compat.UpgradeSlotCompat.shouldEnableUpgradeSlots()) {
return appeng.api.upgrades.UpgradeInventories.empty();
}
return ((IUpgradeableObject) this.getLogic()).getUpgrades();
}
}

View File

@ -1,272 +0,0 @@
package com.extendedae_plus.mixin.ae2.helpers.patternprovider;
import appeng.api.networking.IManagedGridNode;
import appeng.api.networking.security.IActionSource;
import appeng.api.upgrades.IUpgradeInventory;
import appeng.api.upgrades.IUpgradeableObject;
import appeng.api.upgrades.UpgradeInventories;
import appeng.helpers.patternprovider.PatternProviderLogic;
import appeng.helpers.patternprovider.PatternProviderLogicHost;
import com.extendedae_plus.ae.items.ChannelCardItem;
import com.extendedae_plus.compat.UpgradeSlotCompat;
import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.wireless.WirelessSlaveLink;
import com.extendedae_plus.wireless.endpoint.GenericNodeEndpointImpl;
import com.extendedae_plus.bridge.InterfaceWirelessLinkBridge;
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;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
import java.util.List;
/**
* PatternProviderLogic 注入升级槽实现 IUpgradeableObject
* 仅负责升级槽的持久化/掉落/清空与初始化不改变原有逻辑
*/
@Mixin(value = PatternProviderLogic.class, priority = 2000, remap = false)
public abstract class PatternProviderLogicUpgradesMixin implements IUpgradeableObject, InterfaceWirelessLinkBridge {
@Unique
private IUpgradeInventory eap$upgrades = UpgradeInventories.empty();
@Unique
private WirelessSlaveLink eap$link;
@Unique
private long eap$lastChannel = -1;
@Unique
private boolean eap$clientConnected = false;
@Unique
private boolean eap$hasInitialized = false;
@Unique
private int eap$delayedInitTicks = 0;
@Final
@Shadow
private PatternProviderLogicHost host;
@Final
@Shadow
private IManagedGridNode mainNode;
@Final
@Shadow
private IActionSource actionSource;
@Unique
private void eap$onUpgradesChanged() {
this.host.saveChanges();
// 升级变更重置并尝试初始化
eap$lastChannel = -1;
eap$hasInitialized = false;
eap$initializeChannelLink();
}
@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) {
// 只有在应该启用升级卡槽时才初始化
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots()) {
return;
}
this.eap$upgrades = UpgradeInventories.forMachine(host.getTerminalIcon().getItem(), 1, this::eap$onUpgradesChanged);
}
@Inject(method = "writeToNBT", at = @At("TAIL"))
private void eap$saveUpgrades(CompoundTag tag, CallbackInfo ci) {
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots()) {
return;
}
this.eap$upgrades.writeToNBT(tag, "upgrades");
}
@Inject(method = "readFromNBT", at = @At("TAIL"))
private void eap$loadUpgrades(CompoundTag tag, CallbackInfo ci) {
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots()) {
return;
}
this.eap$upgrades.readFromNBT(tag, "upgrades");
// NBT 加载后重置并尝试初始化可能刚进入世界
eap$lastChannel = -1;
eap$hasInitialized = false;
eap$initializeChannelLink();
}
@Inject(method = "addDrops", at = @At("TAIL"))
private void eap$dropUpgrades(List<ItemStack> drops, CallbackInfo ci) {
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots()) {
return;
}
for (var stack : this.eap$upgrades) {
if (!stack.isEmpty()) {
drops.add(stack);
}
}
}
@Inject(method = "clearContent", at = @At("TAIL"))
private void eap$clearUpgrades(CallbackInfo ci) {
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots()) {
return;
}
this.eap$upgrades.clear();
}
@Override
public void eap$updateWirelessLink() {
if (eap$link != null) {
eap$link.updateStatus();
}
}
@Override
public IUpgradeInventory getUpgrades() {
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots()) {
return UpgradeInventories.empty();
}
return this.eap$upgrades;
}
// ===== 频道卡初始化与延迟重试服务端 =====
@Unique
public void eap$initializeChannelLink() {
// 客户端早退
if (host.getBlockEntity() != null && host.getBlockEntity().getLevel() != null && host.getBlockEntity().getLevel().isClientSide) {
return;
}
// 避免重复初始化
if (eap$hasInitialized) {
return;
}
// 等待网格完成引导
if (!mainNode.hasGridBooted()) {
// 安排短延迟等待后续 tick 再试
eap$delayedInitTicks = Math.max(eap$delayedInitTicks, 5);
try {
mainNode.ifPresent((grid, node) -> {
try { grid.getTickManager().wakeDevice(node); } catch (Throwable ignored) {}
});
} catch (Throwable ignored) {}
return;
}
try {
long channel = 0L;
boolean found = false;
for (ItemStack stack : this.eap$upgrades) {
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
channel = ChannelCardItem.getChannel(stack);
found = true;
break;
}
}
if (!found) {
// 无频道卡断开并视为初始化完成
if (eap$link != null) {
eap$link.setFrequency(0L);
eap$link.updateStatus();
}
eap$hasInitialized = true;
return;
}
if (eap$link == null) {
var endpoint = new GenericNodeEndpointImpl(() -> host.getBlockEntity(), () -> this.mainNode.getNode());
eap$link = new WirelessSlaveLink(endpoint);
}
eap$link.setFrequency(channel);
eap$link.updateStatus();
if (eap$link.isConnected()) {
eap$hasInitialized = true;
} else {
eap$hasInitialized = false;
eap$delayedInitTicks = Math.max(eap$delayedInitTicks, 5);
try {
mainNode.ifPresent((grid, node) -> {
try { grid.getTickManager().wakeDevice(node); } catch (Throwable ignored) {}
});
} catch (Throwable ignored) {}
}
} catch (Exception ignored) {
}
}
@Override
public void eap$setClientWirelessState(boolean connected) {
eap$clientConnected = connected;
}
@Override
public boolean eap$isWirelessConnected() {
if (host.getBlockEntity() != null && host.getBlockEntity().getLevel() != null && host.getBlockEntity().getLevel().isClientSide) {
return eap$clientConnected;
} else {
return eap$link != null && eap$link.isConnected();
}
}
@Override
public boolean eap$hasTickInitialized() {
return eap$hasInitialized;
}
@Override
public void eap$setTickInitialized(boolean initialized) {
eap$hasInitialized = initialized;
}
@Override
public void eap$handleDelayedInit() {
// 仅服务端
if (host.getBlockEntity() != null && host.getBlockEntity().getLevel() != null && host.getBlockEntity().getLevel().isClientSide) {
return;
}
if (!eap$hasInitialized) {
if (!mainNode.hasGridBooted()) {
if (eap$delayedInitTicks > 0) {
eap$delayedInitTicks--;
}
if (eap$delayedInitTicks == 0) {
eap$delayedInitTicks = 5;
try {
mainNode.ifPresent((grid, node) -> {
try { grid.getTickManager().wakeDevice(node); } catch (Throwable ignored) {}
});
} catch (Throwable ignored) {}
}
} else {
eap$initializeChannelLink();
}
}
}
// 当主节点状态变化例如 GRID_BOOT 完成安排一次延迟初始化并唤醒设备
@Inject(method = "onMainNodeStateChanged", at = @At("TAIL"))
private void eap$onMainNodeStateChangedTail(CallbackInfo ci) {
eap$lastChannel = -1;
eap$hasInitialized = false;
eap$delayedInitTicks = 10;
try {
mainNode.ifPresent((grid, node) -> {
try { grid.getTickManager().wakeDevice(node); } catch (Throwable ignored) {}
});
} catch (Throwable ignored) {}
}
}

View File

@ -0,0 +1,79 @@
package com.extendedae_plus.mixin.appflux;
import appeng.api.networking.IManagedGridNode;
import appeng.api.upgrades.IUpgradeInventory;
import appeng.api.upgrades.UpgradeInventories;
import appeng.helpers.patternprovider.PatternProviderLogic;
import appeng.helpers.patternprovider.PatternProviderLogicHost;
import com.extendedae_plus.compat.UpgradeSlotCompat;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
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;
/**
* 当appflux存在时修改PatternProviderLogic的升级槽数量为2个
* 优先级设置为2000确保在appflux之后应用
*/
@Mixin(value = PatternProviderLogic.class, priority = 2000, remap = false)
public class AppfluxPatternProviderLogicMixin {
/**
* 在appflux初始化升级槽之后替换为2个槽的版本
*/
@Inject(method = "<init>(Lappeng/api/networking/IManagedGridNode;Lappeng/helpers/patternprovider/PatternProviderLogicHost;I)V",
at = @At("TAIL"))
private void eap$modifyAppfluxUpgradeSlots(IManagedGridNode mainNode, PatternProviderLogicHost host, int patternInventorySize, CallbackInfo ci) {
try {
com.extendedae_plus.util.ExtendedAELogger.LOGGER.info("AppfluxPatternProviderLogicMixin被调用");
// 只有当appflux存在且不启用我们的升级槽时才修改数量
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots() && UpgradeSlotCompat.shouldEnableChannelCard()) {
com.extendedae_plus.util.ExtendedAELogger.LOGGER.info("尝试修改appflux升级槽数量为2个");
// 使用反射找到appflux的升级槽字段并替换
try {
Field upgradesField = this.getClass().getDeclaredField("af_$upgrades");
upgradesField.setAccessible(true);
IUpgradeInventory currentUpgrades = (IUpgradeInventory) upgradesField.get(this);
if (currentUpgrades != null) {
com.extendedae_plus.util.ExtendedAELogger.LOGGER.info("找到appflux升级槽当前大小: {}", currentUpgrades.size());
// 创建新的2槽升级槽
IUpgradeInventory newUpgrades = UpgradeInventories.forMachine(
host.getTerminalIcon().getItem(),
2,
() -> {
try {
// 调用appflux的升级变更方法
this.getClass().getDeclaredMethod("af_$onUpgradesChanged").invoke(this);
} catch (Exception e) {
com.extendedae_plus.util.ExtendedAELogger.LOGGER.error("调用appflux升级变更方法失败", e);
}
}
);
// 复制原有升级卡到新的升级槽
for (int i = 0; i < Math.min(currentUpgrades.size(), newUpgrades.size()); i++) {
if (!currentUpgrades.getStackInSlot(i).isEmpty()) {
newUpgrades.insertItem(i, currentUpgrades.getStackInSlot(i).copy(), false);
}
}
// 替换升级槽
upgradesField.set(this, newUpgrades);
com.extendedae_plus.util.ExtendedAELogger.LOGGER.info("成功将appflux升级槽替换为2个槽");
}
} catch (Exception e) {
com.extendedae_plus.util.ExtendedAELogger.LOGGER.error("反射修改appflux升级槽失败", e);
}
}
} catch (Exception e) {
com.extendedae_plus.util.ExtendedAELogger.LOGGER.error("AppfluxPatternProviderLogicMixin执行失败", e);
}
}
}