diff --git a/src/main/java/com/extendedae_plus/bridge/InterfaceWirelessLinkBridge.java b/src/main/java/com/extendedae_plus/bridge/InterfaceWirelessLinkBridge.java index 023ee39..d200f77 100644 --- a/src/main/java/com/extendedae_plus/bridge/InterfaceWirelessLinkBridge.java +++ b/src/main/java/com/extendedae_plus/bridge/InterfaceWirelessLinkBridge.java @@ -19,4 +19,32 @@ public interface InterfaceWirelessLinkBridge { default void eap$setClientWirelessState(boolean connected) { // 默认实现为空 } + + /** + * 检查是否已经进行过tick初始化 + */ + default boolean eap$hasTickInitialized() { + return true; // 默认认为已初始化 + } + + /** + * 设置tick初始化状态 + */ + default void eap$setTickInitialized(boolean initialized) { + // 默认实现为空 + } + + /** + * 执行频道链接初始化 + */ + default void eap$initializeChannelLink() { + // 默认实现为空 + } + + /** + * 检查并处理延迟初始化 + */ + default void eap$handleDelayedInit() { + // 默认实现为空 + } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicChannelCardMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicChannelCardMixin.java index b8e7401..39cabad 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicChannelCardMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicChannelCardMixin.java @@ -6,6 +6,7 @@ import appeng.helpers.InterfaceLogicHost; import com.extendedae_plus.ae.items.ChannelCardItem; import com.extendedae_plus.bridge.InterfaceWirelessLinkBridge; import com.extendedae_plus.init.ModItems; +import com.extendedae_plus.util.ExtendedAELogger; import com.extendedae_plus.wireless.IWirelessEndpoint; import com.extendedae_plus.wireless.WirelessSlaveLink; import com.extendedae_plus.wireless.endpoint.InterfaceNodeEndpointImpl; @@ -26,19 +27,63 @@ public abstract class InterfaceLogicChannelCardMixin implements InterfaceWireles @Shadow(remap = false) public abstract appeng.api.networking.IGridNode getActionableNode(); @Shadow(remap = false) protected InterfaceLogicHost host; + + @Shadow(remap = false) protected appeng.api.networking.IManagedGridNode mainNode; @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; + + static { + ExtendedAELogger.LOGGER.info("[服务端] InterfaceLogicChannelCardMixin 已加载"); + } @Inject(method = "onUpgradesChanged", at = @At("TAIL"), remap = false) private void eap$onUpgradesChangedTail(CallbackInfo ci) { - handleChannelCardChange(); + // 升级变更时重置标志并尝试初始化 + eap$lastChannel = -1; + eap$hasInitialized = false; + eap$initializeChannelLink(); + } + + @Inject(method = "gridChanged", at = @At("TAIL"), remap = false) + private void eap$afterGridChanged(CallbackInfo ci) { + // 网格状态变化时重置标志并设置延迟初始化 + ExtendedAELogger.LOGGER.debug("[服务端] Interface gridChanged 触发,设置延迟初始化"); + eap$lastChannel = -1; + eap$hasInitialized = false; + eap$delayedInitTicks = 10; // 适当增加延迟tick,等待网格完成引导 + // 尝试唤醒设备,确保后续还能继续tick + if (mainNode != null) { + mainNode.ifPresent((grid, node) -> { + try { + grid.getTickManager().wakeDevice(node); + } catch (Throwable t) { + // 防御性日志,避免因这里的异常影响主流程 + ExtendedAELogger.LOGGER.debug("[服务端] Interface 唤醒设备失败: {}", t.toString()); + } + }); + } } @Inject(method = "readFromNBT", at = @At("TAIL"), remap = false) private void eap$afterReadNBT(net.minecraft.nbt.CompoundTag tag, CallbackInfo ci) { - // 重载后根据卡状态恢复连接 - handleChannelCardChange(); + // 从 NBT加载时重置标志 + eap$lastChannel = -1; + eap$hasInitialized = false; + // 直接尝试初始化 + eap$initializeChannelLink(); } @Inject(method = "clearContent", at = @At("HEAD"), remap = false) @@ -49,20 +94,95 @@ public abstract class InterfaceLogicChannelCardMixin implements InterfaceWireles } @Unique - private void handleChannelCardChange() { - var inv = getUpgrades(); - long channel = 0L; - for (ItemStack stack : inv) { - if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) { - channel = ChannelCardItem.getChannel(stack); - break; + public void eap$initializeChannelLink() { + ExtendedAELogger.LOGGER.debug("[服务端] Interface eap$initializeChannelLink 被调用"); + + // 防止在客户端执行 + if (host.getBlockEntity() != null && host.getBlockEntity().getLevel() != null && host.getBlockEntity().getLevel().isClientSide) { + ExtendedAELogger.LOGGER.debug("[服务端] Interface 在客户端,跳过初始化"); + return; + } + + // 检查是否已经初始化过 + if (eap$hasInitialized) { + ExtendedAELogger.LOGGER.debug("[服务端] Interface 已经初始化过,跳过"); + return; + } + + // 优先等待网格完成引导(比仅检查 isActive 更可靠) + if (!mainNode.hasGridBooted()) { + ExtendedAELogger.LOGGER.debug("[服务端] Interface 网格未完成引导(boot),等待后再初始化: ready={}, active={}, online={}", + mainNode.isReady(), mainNode.isActive(), mainNode.isOnline()); + return; + } + + try { + var inv = getUpgrades(); + long channel = 0L; + boolean found = false; + for (ItemStack stack : inv) { + if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) { + channel = ChannelCardItem.getChannel(stack); + found = true; + break; + } } + + ExtendedAELogger.LOGGER.debug("[服务端] Interface 初始化频道链接: found={}, channel={}", found, channel); + + if (!found) { + // 无频道卡则断开 + if (eap$link != null) { + eap$link.setFrequency(0L); + eap$link.updateStatus(); + ExtendedAELogger.LOGGER.debug("[服务端] Interface 断开频道链接"); + } + eap$hasInitialized = true; // 无频道卡也算初始化完成 + return; + } + + if (eap$link == null) { + // 使用mainNode而不是getActionableNode,因为后者可能返回null + IWirelessEndpoint endpoint = new InterfaceNodeEndpointImpl(host, () -> mainNode.getNode()); + eap$link = new WirelessSlaveLink(endpoint); + ExtendedAELogger.LOGGER.debug("[服务端] Interface 创建新的无线链接"); + } + + eap$link.setFrequency(channel); + eap$link.updateStatus(); + + // 调试信息:检查网格节点状态 + var gridNode = mainNode.getNode(); + var isActive = mainNode.isActive(); + ExtendedAELogger.LOGGER.debug("[服务端] Interface 设置频道: {}, 连接状态: {}, 网格节点: {}, 激活: {}, 在线: {}", + channel, eap$link.isConnected(), + gridNode != null ? "exists" : "null", + isActive, + gridNode != null ? gridNode.isOnline() : "N/A"); + + if (eap$link.isConnected()) { + eap$hasInitialized = true; // 设置初始化完成标志 + ExtendedAELogger.LOGGER.debug("[服务端] Interface 无线链接建立成功"); + } else { + ExtendedAELogger.LOGGER.warn("[服务端] Interface 无线链接建立失败,将继续重试"); + // 不标记为完成,允许后续tick重试 + eap$hasInitialized = false; + // 设置一个短延迟窗口,避免每tick刷屏 + eap$delayedInitTicks = Math.max(eap$delayedInitTicks, 5); + try { + mainNode.ifPresent((grid, node) -> { + try { + grid.getTickManager().wakeDevice(node); + } catch (Throwable t) { + ExtendedAELogger.LOGGER.debug("[服务端] Interface 初始化失败后唤醒设备失败: {}", t.toString()); + } + }); + } catch (Throwable ignored) { + } + } + } catch (Exception e) { + ExtendedAELogger.LOGGER.error("[服务端] Interface 初始化频道链接失败", e); } - if (eap$link == null) { - IWirelessEndpoint endpoint = new InterfaceNodeEndpointImpl(host, this::getActionableNode); - eap$link = new WirelessSlaveLink(endpoint); - } - eap$link.setFrequency(channel); } @Override @@ -71,4 +191,69 @@ public abstract class InterfaceLogicChannelCardMixin implements InterfaceWireles eap$link.updateStatus(); } } + + @Override + public boolean eap$isWirelessConnected() { + // InterfaceLogic没有isClientSide方法,需要通过host判断 + 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 void eap$setClientWirelessState(boolean connected) { + eap$clientConnected = connected; + } + + @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) { + // 重新设定一个短延迟窗口,并唤醒设备,以保证后续还能继续 tick + eap$delayedInitTicks = 5; + try { + mainNode.ifPresent((grid, node) -> { + try { + grid.getTickManager().wakeDevice(node); + } catch (Throwable t) { + ExtendedAELogger.LOGGER.debug("[服务端] Interface 延迟等待期间唤醒设备失败: {}", t.toString()); + } + }); + } catch (Throwable ignored) { + } + ExtendedAELogger.LOGGER.debug("[服务端] Interface 网格仍在引导,继续等待: ready={}, active={}, online={}", + mainNode.isReady(), mainNode.isActive(), mainNode.isOnline()); + } + } else { + // 网格已引导完成,执行初始化 + ExtendedAELogger.LOGGER.debug("[服务端] Interface 延迟初始化触发(网格已完成引导)"); + eap$initializeChannelLink(); + } + } + } + + // eap$initializeChannelLink方法已在上面实现 } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicTickerMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicTickerMixin.java index 50ac299..a2063d5 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicTickerMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/InterfaceLogicTickerMixin.java @@ -2,6 +2,7 @@ package com.extendedae_plus.mixin.ae2.helpers; import appeng.helpers.InterfaceLogic; import com.extendedae_plus.bridge.InterfaceWirelessLinkBridge; +import com.extendedae_plus.util.ExtendedAELogger; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -20,6 +21,20 @@ public abstract class InterfaceLogicTickerMixin { @Final private InterfaceLogic this$0; + @Inject(method = "tickingRequest", at = @At("HEAD"), remap = false) + private void eap$tickHead(appeng.api.networking.IGridNode node, int ticksSinceLastCall, + CallbackInfoReturnable cir) { + // 仅在服务端处理延迟初始化,避免客户端干扰 + if (node != null && node.getLevel() != null && node.getLevel().isClientSide) { + return; + } + + if (this$0 instanceof InterfaceWirelessLinkBridge bridge) { + // 处理延迟初始化 + bridge.eap$handleDelayedInit(); + } + } + @Inject(method = "tickingRequest", at = @At("TAIL"), remap = false) private void eap$tickTail(appeng.api.networking.IGridNode node, int ticksSinceLastCall, CallbackInfoReturnable cir) { diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/parts/automation/IOBusPartChannelCardMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/parts/automation/IOBusPartChannelCardMixin.java index b09b40d..b00c3e1 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/parts/automation/IOBusPartChannelCardMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/parts/automation/IOBusPartChannelCardMixin.java @@ -64,7 +64,7 @@ public abstract class IOBusPartChannelCardMixin implements InterfaceWirelessLink } @Unique - private void eap$initializeChannelLink() { + public void eap$initializeChannelLink() { // 防止重复调用 if (((appeng.parts.AEBasePart)(Object)this).isClientSide()) { return; diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/parts/storagebus/StorageBusPartChannelCardMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/parts/storagebus/StorageBusPartChannelCardMixin.java index 00b6626..50e4a71 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/parts/storagebus/StorageBusPartChannelCardMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/parts/storagebus/StorageBusPartChannelCardMixin.java @@ -61,7 +61,7 @@ public abstract class StorageBusPartChannelCardMixin implements InterfaceWireles } @Unique - private void eap$initializeChannelLink() { + public void eap$initializeChannelLink() { // 防止重复调用 if (((appeng.parts.AEBasePart)(Object)this).isClientSide()) { return;