diff --git a/src/main/java/com/extendedae_plus/bridge/InterfaceWirelessLinkBridge.java b/src/main/java/com/extendedae_plus/bridge/InterfaceWirelessLinkBridge.java index 097b091..11b9013 100644 --- a/src/main/java/com/extendedae_plus/bridge/InterfaceWirelessLinkBridge.java +++ b/src/main/java/com/extendedae_plus/bridge/InterfaceWirelessLinkBridge.java @@ -5,4 +5,18 @@ package com.extendedae_plus.bridge; */ public interface InterfaceWirelessLinkBridge { void extendedae_plus$updateWirelessLink(); + + /** + * 获取无线连接状态(服务端返回真实状态,客户端返回同步状态) + */ + default boolean extendedae_plus$isWirelessConnected() { + return false; + } + + /** + * 设置客户端的无线连接状态(仅在客户端使用) + */ + default void extendedae_plus$setClientWirelessState(boolean connected) { + // 默认实现为空 + } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/CraftingCPUClusterMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/CraftingCPUClusterMixin.java index 8faf483..7c76d90 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/CraftingCPUClusterMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/CraftingCPUClusterMixin.java @@ -1,36 +1,48 @@ package com.extendedae_plus.mixin.ae2; import appeng.blockentity.crafting.CraftingBlockEntity; +import appeng.blockentity.crafting.CraftingMonitorBlockEntity; import appeng.me.cluster.implementations.CraftingCPUCluster; +import appeng.me.helpers.MachineSource; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Constant; -import org.spongepowered.asm.mixin.injection.ModifyConstant; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; @Mixin(value = CraftingCPUCluster.class, remap = false, priority = 2000) public abstract class CraftingCPUClusterMixin { - // 1) 提升“单方块线程上限”的常量,避免抛出 IAE 的 IllegalArgumentException - @ModifyConstant( - method = "addBlockEntity(Lappeng/blockentity/crafting/CraftingBlockEntity;)V", - constant = @Constant(intValue = 16) - ) - private int extendedae_plus$raisePerUnitLimit(int original) { - // 放宽到极大值,完全取消单方块 16 线程的硬限制 - return Integer.MAX_VALUE; - } + + @Shadow private List blockEntities; + @Shadow private List status; + @Shadow private MachineSource machineSrc; + @Shadow private long storage; + @Shadow private int accelerator; + + /** + * 完全重写addBlockEntity方法,移除16线程的硬限制 + * @author ExtendedAE_Plus + * @reason 移除单方块16线程的硬限制,允许更高的线程数 + */ + @Overwrite + void addBlockEntity(CraftingBlockEntity te) { + if (this.machineSrc == null || te.isCoreBlock()) { + this.machineSrc = new MachineSource(te); + } - // 2) 保持统计使用原始线程值(若存在多处调用),不再返回固定 16 - @Redirect( - method = "addBlockEntity(Lappeng/blockentity/crafting/CraftingBlockEntity;)V", - at = @At( - value = "INVOKE", - target = "Lappeng/blockentity/crafting/CraftingBlockEntity;getAcceleratorThreads()I", - ordinal = 1 - ) - ) - private int extendedae_plus$onGetThreadsForLimitCheck(CraftingBlockEntity te) { - // 返回原始线程数,确保总并行单元不被错误下限 - return te.getAcceleratorThreads(); + te.setCoreBlock(false); + te.saveChanges(); + this.blockEntities.add(0, te); + + if (te instanceof CraftingMonitorBlockEntity) { + this.status.add((CraftingMonitorBlockEntity) te); + } + if (te.getStorageBytes() > 0) { + this.storage += te.getStorageBytes(); + } + if (te.getAcceleratorThreads() > 0) { + // 移除原来的16线程限制,直接添加线程数 + this.accelerator += te.getAcceleratorThreads(); + } } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/parts/AEBasePartClientSyncMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/parts/AEBasePartClientSyncMixin.java new file mode 100644 index 0000000..2ae0175 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/ae2/parts/AEBasePartClientSyncMixin.java @@ -0,0 +1,68 @@ +package com.extendedae_plus.mixin.ae2.parts; + +import appeng.parts.AEBasePart; +import com.extendedae_plus.bridge.InterfaceWirelessLinkBridge; +import net.minecraft.network.FriendlyByteBuf; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +/** + * 为所有AE2 Part添加无线连接状态的客户端同步功能 + */ +@Mixin(value = AEBasePart.class, remap = false) +public class AEBasePartClientSyncMixin { + + @Inject(method = "writeToStream", at = @At("TAIL")) + private void extendedae_plus$writeWirelessState(FriendlyByteBuf data, CallbackInfo ci) { + // 检查是否实现了无线链接桥接接口 + if (this instanceof InterfaceWirelessLinkBridge) { + InterfaceWirelessLinkBridge bridge = (InterfaceWirelessLinkBridge) this; + // 同步无线连接状态到客户端 + boolean connected = false; + try { + // 只在服务端获取真实连接状态 + AEBasePart part = (AEBasePart)(Object)this; + if (!part.isClientSide()) { + connected = bridge.extendedae_plus$isWirelessConnected(); + // 调试日志:记录写入的状态 + if (part.getClass().getSimpleName().contains("IOBus")) { + System.out.println("[写入状态] IOBus 无线连接状态: " + connected); + } + } + } catch (Exception e) { + // 忽略异常,默认为false + System.err.println("获取无线连接状态失败: " + e.getMessage()); + } + data.writeBoolean(connected); + } else { + // 不是无线链接Part,写入false + data.writeBoolean(false); + } + } + + @Inject(method = "readFromStream", at = @At("TAIL")) + private void extendedae_plus$readWirelessState(FriendlyByteBuf data, CallbackInfoReturnable cir) { + // 读取无线连接状态 + boolean connected = data.readBoolean(); + + // 检查是否实现了无线链接桥接接口 + if (this instanceof InterfaceWirelessLinkBridge) { + InterfaceWirelessLinkBridge bridge = (InterfaceWirelessLinkBridge) this; + try { + // 调试日志:记录读取的状态 + AEBasePart part = (AEBasePart)(Object)this; + if (part.getClass().getSimpleName().contains("IOBus")) { + System.out.println("[读取状态] IOBus 无线连接状态: " + connected); + } + // 更新客户端状态 + bridge.extendedae_plus$setClientWirelessState(connected); + } catch (Exception e) { + // 忽略异常 + System.err.println("设置客户端无线连接状态失败: " + e.getMessage()); + } + } + } +} 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 c556c8f..cf21f1d 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 @@ -5,11 +5,14 @@ import appeng.api.upgrades.IUpgradeInventory; import appeng.api.upgrades.IUpgradeableObject; import appeng.helpers.InterfaceLogicHost; import appeng.parts.automation.IOBusPart; +import net.minecraft.nbt.CompoundTag; +import com.extendedae_plus.util.ExtendedAELogger; import com.extendedae_plus.ae.items.ChannelCardItem; import com.extendedae_plus.bridge.InterfaceWirelessLinkBridge; import com.extendedae_plus.init.ModItems; import com.extendedae_plus.wireless.WirelessSlaveLink; import com.extendedae_plus.wireless.endpoint.GenericNodeEndpointImpl; +import net.minecraft.network.FriendlyByteBuf; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -24,36 +27,105 @@ public abstract class IOBusPartChannelCardMixin implements InterfaceWirelessLink @Unique private WirelessSlaveLink extendedae_plus$link; + + @Unique + private long extendedae_plus$lastChannel = -1; + + @Unique + private boolean extendedae_plus$clientConnected = false; + + @Unique + private boolean extendedae_plus$hasTickInitialized = false; @Inject(method = "upgradesChanged", at = @At("TAIL")) private void extendedae_plus$onUpgradesChanged(CallbackInfo ci) { - IUpgradeInventory inv = this.getUpgrades(); - long channel = 0L; - boolean found = false; - for (var stack : inv) { - if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) { - channel = ChannelCardItem.getChannel(stack); - found = true; - break; - } + // 只在服务端初始化频道链接 + if (!((appeng.parts.AEBasePart)(Object)this).isClientSide()) { + extendedae_plus$initializeChannelLink(); } - if (!found) { - // 无频道卡则断开 - if (extendedae_plus$link != null) { - extendedae_plus$link.setFrequency(0L); - extendedae_plus$link.updateStatus(); - } + } + + @Inject(method = "tickingRequest", at = @At("HEAD")) + private void extendedae_plus$beforeTick(appeng.api.networking.IGridNode node, int ticksSinceLastCall, org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable cir) { + // 在第一次tick时初始化频道链接(此时网格节点已经在线) + if (!extendedae_plus$hasTickInitialized && !((appeng.parts.AEBasePart)(Object)this).isClientSide()) { + extendedae_plus$hasTickInitialized = true; + extendedae_plus$initializeChannelLink(); + } + } + + @Inject(method = "readFromNBT", at = @At("TAIL")) + private void extendedae_plus$afterReadFromNBT(CompoundTag extra, CallbackInfo ci) { + // 从NBT加载时重置频道缓存和tick初始化标志 + if (!((appeng.parts.AEBasePart)(Object)this).isClientSide()) { + extendedae_plus$lastChannel = -1; + extendedae_plus$hasTickInitialized = false; // 重置标志,允许再次初始化 + } + } + + @Unique + private void extendedae_plus$initializeChannelLink() { + // 防止重复调用 + if (((appeng.parts.AEBasePart)(Object)this).isClientSide()) { return; } - if (extendedae_plus$link == null) { - var endpoint = new GenericNodeEndpointImpl( - () -> ((appeng.parts.AEBasePart)(Object)this).getHost().getBlockEntity(), - () -> ((IActionHost)(Object)this).getActionableNode() - ); - extendedae_plus$link = new WirelessSlaveLink(endpoint); + + try { + IUpgradeInventory inv = this.getUpgrades(); + long channel = 0L; + boolean found = false; + for (var stack : inv) { + if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) { + channel = ChannelCardItem.getChannel(stack); + found = true; + break; + } + } + + // 频道没有变化则跳过 + if (extendedae_plus$lastChannel == channel) { + return; + } + extendedae_plus$lastChannel = channel; + + ExtendedAELogger.LOGGER.debug("[服务端] IOBus 初始化频道链接: found={}, channel={}", found, channel); + + if (!found) { + // 无频道卡则断开 + if (extendedae_plus$link != null) { + extendedae_plus$link.setFrequency(0L); + extendedae_plus$link.updateStatus(); + ExtendedAELogger.LOGGER.debug("[服务端] IOBus 断开频道链接"); + // 立即通知客户端状态变化(断开连接无需延迟) + ((appeng.parts.AEBasePart)(Object)this).getHost().markForUpdate(); + } + return; + } + + if (extendedae_plus$link == null) { + var endpoint = new GenericNodeEndpointImpl( + () -> ((appeng.parts.AEBasePart)(Object)this).getHost().getBlockEntity(), + () -> ((IActionHost)(Object)this).getActionableNode() + ); + extendedae_plus$link = new WirelessSlaveLink(endpoint); + ExtendedAELogger.LOGGER.debug("[服务端] IOBus 创建新的无线链接"); + } + + extendedae_plus$link.setFrequency(channel); + extendedae_plus$link.updateStatus(); + + // 调试信息:检查网格节点状态 + var gridNode = ((IActionHost)(Object)this).getActionableNode(); + ExtendedAELogger.LOGGER.debug("[服务端] IOBus 设置频道: {}, 连接状态: {}, 网格节点: {}, 在线: {}", + channel, extendedae_plus$link.isConnected(), + gridNode != null ? "exists" : "null", + gridNode != null ? gridNode.isOnline() : "N/A"); + + // 通知客户端状态变化 + ((appeng.parts.AEBasePart)(Object)this).getHost().markForUpdate(); + } catch (Exception e) { + ExtendedAELogger.LOGGER.error("[服务端] IOBus 初始化频道链接失败", e); } - extendedae_plus$link.setFrequency(channel); - extendedae_plus$link.updateStatus(); } @Override @@ -62,4 +134,18 @@ public abstract class IOBusPartChannelCardMixin implements InterfaceWirelessLink extendedae_plus$link.updateStatus(); } } + + @Override + public boolean extendedae_plus$isWirelessConnected() { + if (((appeng.parts.AEBasePart)(Object)this).isClientSide()) { + return extendedae_plus$clientConnected; + } else { + return extendedae_plus$link != null && extendedae_plus$link.isConnected(); + } + } + + @Override + public void extendedae_plus$setClientWirelessState(boolean connected) { + extendedae_plus$clientConnected = connected; + } } 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 2abb221..e4cc287 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 @@ -1,9 +1,13 @@ package com.extendedae_plus.mixin.ae2.parts.storagebus; +import appeng.api.networking.IGridNodeListener; import appeng.api.networking.security.IActionHost; import appeng.api.upgrades.IUpgradeInventory; import appeng.api.upgrades.IUpgradeableObject; import appeng.parts.storagebus.StorageBusPart; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import com.extendedae_plus.util.ExtendedAELogger; import com.extendedae_plus.ae.items.ChannelCardItem; import com.extendedae_plus.bridge.InterfaceWirelessLinkBridge; import com.extendedae_plus.init.ModItems; @@ -23,35 +27,101 @@ public abstract class StorageBusPartChannelCardMixin implements InterfaceWireles @Unique private WirelessSlaveLink extendedae_plus$link; + + @Unique + private long extendedae_plus$lastChannel = -1; + + @Unique + private boolean extendedae_plus$clientConnected = false; @Inject(method = "upgradesChanged", at = @At("TAIL")) private void extendedae_plus$onUpgradesChanged(CallbackInfo ci) { - IUpgradeInventory inv = this.getUpgrades(); - long channel = 0L; - boolean found = false; - for (var stack : inv) { - if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) { - channel = ChannelCardItem.getChannel(stack); - found = true; - break; - } + // 只在服务端初始化频道链接 + if (!((appeng.parts.AEBasePart)(Object)this).isClientSide()) { + extendedae_plus$initializeChannelLink(); } - if (!found) { - if (extendedae_plus$link != null) { - extendedae_plus$link.setFrequency(0L); - extendedae_plus$link.updateStatus(); - } + } + + @Inject(method = "onMainNodeStateChanged", at = @At("TAIL")) + private void extendedae_plus$onMainNodeStateChanged(IGridNodeListener.State reason, CallbackInfo ci) { + // 在节点状态变化时(包括加载后的GRID_BOOT)重新初始化频道链接 + if (reason == IGridNodeListener.State.GRID_BOOT && !((appeng.parts.AEBasePart)(Object)this).isClientSide()) { + extendedae_plus$initializeChannelLink(); + } + } + + @Inject(method = "readFromNBT", at = @At("TAIL")) + private void extendedae_plus$afterReadFromNBT(CompoundTag extra, CallbackInfo ci) { + // 从NBT加载后也重新初始化频道链接(只在服务端) + if (!((appeng.parts.AEBasePart)(Object)this).isClientSide()) { + // 从NBT加载时重置频道缓存,强制重新初始化 + extendedae_plus$lastChannel = -1; + extendedae_plus$initializeChannelLink(); + } + } + + @Unique + private void extendedae_plus$initializeChannelLink() { + // 防止重复调用 + if (((appeng.parts.AEBasePart)(Object)this).isClientSide()) { return; } - if (extendedae_plus$link == null) { - var endpoint = new GenericNodeEndpointImpl( - () -> ((appeng.parts.AEBasePart)(Object)this).getHost().getBlockEntity(), - () -> ((IActionHost)(Object)this).getActionableNode() - ); - extendedae_plus$link = new WirelessSlaveLink(endpoint); + + try { + IUpgradeInventory inv = this.getUpgrades(); + long channel = 0L; + boolean found = false; + for (var stack : inv) { + if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) { + channel = ChannelCardItem.getChannel(stack); + found = true; + break; + } + } + + // 频道没有变化则跳过 + if (extendedae_plus$lastChannel == channel) { + return; + } + extendedae_plus$lastChannel = channel; + + ExtendedAELogger.LOGGER.debug("[服务端] StorageBus 初始化频道链接: found={}, channel={}", found, channel); + + if (!found) { + if (extendedae_plus$link != null) { + extendedae_plus$link.setFrequency(0L); + extendedae_plus$link.updateStatus(); + ExtendedAELogger.LOGGER.debug("[服务端] StorageBus 断开频道链接"); + // 通知客户端状态变化 + ((appeng.parts.AEBasePart)(Object)this).getHost().markForUpdate(); + } + return; + } + + if (extendedae_plus$link == null) { + var endpoint = new GenericNodeEndpointImpl( + () -> ((appeng.parts.AEBasePart)(Object)this).getHost().getBlockEntity(), + () -> ((IActionHost)(Object)this).getActionableNode() + ); + extendedae_plus$link = new WirelessSlaveLink(endpoint); + ExtendedAELogger.LOGGER.debug("[服务端] StorageBus 创建新的无线链接"); + } + + extendedae_plus$link.setFrequency(channel); + extendedae_plus$link.updateStatus(); + + // 调试信息:检查网格节点状态 + var gridNode = ((IActionHost)(Object)this).getActionableNode(); + ExtendedAELogger.LOGGER.debug("[服务端] StorageBus 设置频道: {}, 连接状态: {}, 网格节点: {}, 在线: {}", + channel, extendedae_plus$link.isConnected(), + gridNode != null ? "exists" : "null", + gridNode != null ? gridNode.isOnline() : "N/A"); + + // 通知客户端状态变化 + ((appeng.parts.AEBasePart)(Object)this).getHost().markForUpdate(); + } catch (Exception e) { + ExtendedAELogger.LOGGER.error("[服务端] StorageBus 初始化频道链接失败", e); } - extendedae_plus$link.setFrequency(channel); - extendedae_plus$link.updateStatus(); } @Override @@ -60,4 +130,18 @@ public abstract class StorageBusPartChannelCardMixin implements InterfaceWireles extendedae_plus$link.updateStatus(); } } + + @Override + public boolean extendedae_plus$isWirelessConnected() { + if (((appeng.parts.AEBasePart)(Object)this).isClientSide()) { + return extendedae_plus$clientConnected; + } else { + return extendedae_plus$link != null && extendedae_plus$link.isConnected(); + } + } + + @Override + public void extendedae_plus$setClientWirelessState(boolean connected) { + extendedae_plus$clientConnected = connected; + } } diff --git a/src/main/resources/extendedae_plus.mixins.json b/src/main/resources/extendedae_plus.mixins.json index 48e0c2e..ab3d360 100644 --- a/src/main/resources/extendedae_plus.mixins.json +++ b/src/main/resources/extendedae_plus.mixins.json @@ -67,6 +67,7 @@ "ae2.helpers.patternprovider.PatternProviderLogicHostUpgradesMixin", "ae2.menu.PatternProviderMenuUpgradesMixin", "ae2.helpers.patternprovider.PatternProviderLogicTickerMixin", + "ae2.parts.AEBasePartClientSyncMixin", "ae2.parts.automation.IOBusPartChannelCardMixin", "ae2.parts.automation.IOBusPartTickerChannelCardMixin", "ae2.parts.storagebus.StorageBusPartChannelCardMixin",