From 6362c79a666bf6d04f919dc67892487d5b44a8b5 Mon Sep 17 00:00:00 2001 From: GaLi <3096147684@qq.com> Date: Fri, 22 Aug 2025 12:00:06 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=99=BA=E8=83=BD=E9=98=BB?= =?UTF-8?q?=E6=8C=A1=E5=A4=9A=E4=BA=BA=E6=B8=B8=E6=88=8F=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E5=90=8C=E6=AD=A5=E5=BC=82=E5=B8=B8=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle.properties | 2 +- .../ae2/PatternProviderMenuAdvancedMixin.java | 12 +- .../mixin/ae2/PatternProviderScreenMixin.java | 126 ++++++------------ .../ToggleAdvancedBlockingC2SPacket.java | 13 +- 4 files changed, 48 insertions(+), 105 deletions(-) diff --git a/gradle.properties b/gradle.properties index 25a6e90..36d7385 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G loom.platform = forge # Mod properties -mod_version = 1.3.2-beta +mod_version = 1.3.2-fix1 maven_group = com.extendedae_plus archives_name = extendedae_plus diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderMenuAdvancedMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderMenuAdvancedMixin.java index 2809ac4..719fcaa 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderMenuAdvancedMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderMenuAdvancedMixin.java @@ -2,6 +2,7 @@ package com.extendedae_plus.mixin.ae2; import appeng.helpers.patternprovider.PatternProviderLogic; import appeng.helpers.patternprovider.PatternProviderLogicHost; +import appeng.menu.AEBaseMenu; import appeng.menu.guisync.GuiSync; import appeng.menu.implementations.PatternProviderMenu; import com.extendedae_plus.api.AdvancedBlockingHolder; @@ -20,9 +21,6 @@ import static com.extendedae_plus.util.ExtendedAELogger.LOGGER; @Mixin(PatternProviderMenu.class) public abstract class PatternProviderMenuAdvancedMixin implements PatternProviderMenuAdvancedSync { - @Shadow - protected abstract boolean isServerSide(); - @Shadow protected PatternProviderLogic logic; @@ -33,18 +31,16 @@ public abstract class PatternProviderMenuAdvancedMixin implements PatternProvide @Inject(method = "broadcastChanges", at = @At("HEAD")) private void eap$syncAdvancedBlocking(CallbackInfo ci) { - if (this.isServerSide()) { + // 避免@Shadow父类方法,改用公共API:AEBaseMenu#isClientSide() + if (!((AEBaseMenu) (Object) this).isClientSide()) { var l = this.logic; if (l instanceof AdvancedBlockingHolder holder) { this.eap$AdvancedBlocking = holder.eap$getAdvancedBlocking(); + LOGGER.debug("[EAP] Menu broadcastChanges HEAD: eap$AdvancedBlocking={}", this.eap$AdvancedBlocking); } } } - @Inject(method = "broadcastChanges", at = @At("TAIL")) - private void eap$syncAdvancedBlockingTail(CallbackInfo ci) { - } - // 构造器尾注入(public ctor) @Inject(method = "(ILnet/minecraft/world/entity/player/Inventory;Lappeng/helpers/patternprovider/PatternProviderLogicHost;)V", at = @At("TAIL")) private void eap$initAdvancedSync_Public(int id, Inventory playerInventory, PatternProviderLogicHost host, CallbackInfo ci) { diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderScreenMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderScreenMixin.java index 99db84b..4d3fc71 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderScreenMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/PatternProviderScreenMixin.java @@ -4,12 +4,11 @@ import appeng.client.gui.AEBaseScreen; import appeng.client.gui.Icon; import appeng.client.gui.implementations.PatternProviderScreen; import appeng.client.gui.style.ScreenStyle; -import appeng.client.gui.widgets.ToggleButton; +import appeng.client.gui.widgets.SettingToggleButton; +import appeng.api.config.YesNo; +import appeng.api.config.Settings; import appeng.menu.implementations.PatternProviderMenu; import com.extendedae_plus.api.PatternProviderMenuAdvancedSync; -import com.extendedae_plus.client.ClientAdvancedBlockingState; -import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicAccessor; -import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor; import com.extendedae_plus.network.ModNetwork; import com.extendedae_plus.network.ToggleAdvancedBlockingC2SPacket; import net.minecraft.network.chat.Component; @@ -21,122 +20,79 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import static com.extendedae_plus.util.ExtendedAELogger.LOGGER; + /** - * 为 AE2 原版样板供应器界面添加“高级阻挡模式”按钮(仅客户端UI反馈)。 + * 为 AE2 原版样板供应器界面添加“高级阻挡模式”按钮。 * - 位于左侧工具栏 - * - 点击后切换图标(YES/NO)并切换 tooltip 提示 - * - 当前不做任何网络/服务端逻辑 + * - 点击仅发送 C2S 切换请求;状态由 AE2 @GuiSync 回传决定 */ @Mixin(PatternProviderScreen.class) public abstract class PatternProviderScreenMixin extends AEBaseScreen { @Unique - private ToggleButton eap$AdvancedBlockingToggle; + private SettingToggleButton eap$AdvancedBlockingToggle; @Unique private boolean eap$AdvancedBlockingEnabled = false; - @Unique - private String eap$ProviderKey = null; - public PatternProviderScreenMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) { super(menu, playerInventory, title, style); } @Inject(method = "", at = @At("RETURN")) private void eap$initAdvancedBlocking(C menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) { - // 计算供应器唯一键:维度ID + 方块坐标 + // 使用 @GuiSync 初始化 try { - var logic = ((PatternProviderMenuAdvancedAccessor) menu).eap$logic(); - var host = ((PatternProviderLogicAccessor) logic).eap$host(); - var be = host.getBlockEntity(); - var level = be.getLevel(); - String dimId = level.dimension().location().toString(); - long posLong = be.getBlockPos().asLong(); - this.eap$ProviderKey = ClientAdvancedBlockingState.key(dimId, posLong); + if (menu instanceof PatternProviderMenuAdvancedSync sync) { + this.eap$AdvancedBlockingEnabled = sync.eap$getAdvancedBlockingSynced(); + } } catch (Throwable t) { LOGGER.error("Error initializing advanced sync", t); } - // 优先使用该供应器最近一次 S2C 状态;否则回退读取 @GuiSync 初始化 - if (this.eap$ProviderKey != null && ClientAdvancedBlockingState.has(this.eap$ProviderKey)) { - this.eap$AdvancedBlockingEnabled = ClientAdvancedBlockingState.get(this.eap$ProviderKey); - } else if (menu instanceof PatternProviderMenuAdvancedSync sync) { - this.eap$AdvancedBlockingEnabled = sync.eap$getAdvancedBlockingSynced(); - } - // 使用 ToggleButton 以便在 YES/NO 图标与提示之间动态切换 - this.eap$AdvancedBlockingToggle = new ToggleButton( - Icon.BLOCKING_MODE_YES, - Icon.BLOCKING_MODE_NO, - // 提示文本:名称与说明 - Component.literal("高级阻挡模式"), - Component.literal("高级阻挡模式:当开启时,执行更严格的阻挡判定"), - (state) -> { - // 客户端立即反馈:切换图标/提示 - this.eap$AdvancedBlockingEnabled = state; - this.eap$AdvancedBlockingToggle.setState(state); - // 发送 C2S 切换请求 + // 使用 SettingToggleButton 的外观(原版图标),但自定义悬停描述为“智能阻挡” + this.eap$AdvancedBlockingToggle = new SettingToggleButton<>( + Settings.BLOCKING_MODE, + this.eap$AdvancedBlockingEnabled ? YesNo.YES : YesNo.NO, + (btn, backwards) -> { + // 不做本地切换,点击仅发送自定义C2S,显示由@GuiSync回传 + LOGGER.debug("[EAP] Click advanced blocking toggle: send C2S"); ModNetwork.CHANNEL.sendToServer(new ToggleAdvancedBlockingC2SPacket()); - // 可根据状态调整提示文本(演示性:开启/关闭不同第二行) - if (state) { - this.eap$AdvancedBlockingToggle.setTooltipOn(java.util.List.of( - Component.literal("高级阻挡模式"), - Component.literal("高级阻挡模式:已开启"))); - this.eap$AdvancedBlockingToggle.setTooltipOff(java.util.List.of( - Component.literal("高级阻挡模式"), - Component.literal("高级阻挡模式:已开启"))); - } else { - this.eap$AdvancedBlockingToggle.setTooltipOn(java.util.List.of( - Component.literal("高级阻挡模式"), - Component.literal("高级阻挡模式:已关闭"))); - this.eap$AdvancedBlockingToggle.setTooltipOff(java.util.List.of( - Component.literal("高级阻挡模式"), - Component.literal("高级阻挡模式:已关闭"))); - } } - ); - this.eap$AdvancedBlockingToggle.setState(this.eap$AdvancedBlockingEnabled); - // 初始 tooltip - this.eap$AdvancedBlockingToggle.setTooltipOn(java.util.List.of( - Component.literal("高级阻挡模式"), - Component.literal(this.eap$AdvancedBlockingEnabled ? "高级阻挡模式:已开启" : "高级阻挡模式:已关闭") - )); - this.eap$AdvancedBlockingToggle.setTooltipOff(java.util.List.of( - Component.literal("高级阻挡模式"), - Component.literal(this.eap$AdvancedBlockingEnabled ? "高级阻挡模式:已开启" : "高级阻挡模式:已关闭") - )); + ) { + @Override + public java.util.List getTooltipMessage() { + boolean enabled = eap$AdvancedBlockingEnabled; + var title = net.minecraft.network.chat.Component.literal("智能阻挡"); + var line = enabled + ? net.minecraft.network.chat.Component.literal("已启用:YES") + : net.minecraft.network.chat.Component.literal("已禁用:NO"); + return java.util.List.of(title, line); + } + }; + // 初始化后立刻对齐当前@GuiSync状态,避免首帧显示不一致 + LOGGER.debug("[EAP] Screen init: initial synced={} -> set button", this.eap$AdvancedBlockingEnabled); + this.eap$AdvancedBlockingToggle.set(this.eap$AdvancedBlockingEnabled ? YesNo.YES : YesNo.NO); this.addToLeftToolbar(this.eap$AdvancedBlockingToggle); } - // 每帧刷新:从菜单同步布尔值,保持按钮状态一致 - @Inject(method = "updateBeforeRender", at = @At("TAIL"), remap = false) + // 每帧刷新:仅从菜单(@GuiSync)同步布尔值,保持按钮状态一致 + @Inject(method = "updateBeforeRender", at = @At("HEAD"), remap = false) private void eap$updateAdvancedBlocking(CallbackInfo ci) { - // 打印一条轻量 tick 日志以确认该方法被调用(频繁输出可在验证后移除) - // System.out.println("[EPP][CLIENT] updateBeforeRender tick, local=" + this.eppAdvancedBlockingEnabled); - if (this.eap$AdvancedBlockingToggle == null) return; boolean desired = this.eap$AdvancedBlockingEnabled; - // 优先使用该供应器最近一次 S2C 值 - if (this.eap$ProviderKey != null && ClientAdvancedBlockingState.has(this.eap$ProviderKey)) { - desired = ClientAdvancedBlockingState.get(this.eap$ProviderKey); - } else if (this.menu instanceof PatternProviderMenuAdvancedSync sync) { + if (this.menu instanceof PatternProviderMenuAdvancedSync sync) { desired = sync.eap$getAdvancedBlockingSynced(); } - if (desired != this.eap$AdvancedBlockingEnabled) { - this.eap$AdvancedBlockingEnabled = desired; - this.eap$AdvancedBlockingToggle.setState(desired); - // 同步 tooltip 二行提示 - this.eap$AdvancedBlockingToggle.setTooltipOn(java.util.List.of( - Component.literal("高级阻挡模式"), - Component.literal(desired ? "高级阻挡模式:已开启" : "高级阻挡模式:已关闭") - )); - this.eap$AdvancedBlockingToggle.setTooltipOff(java.util.List.of( - Component.literal("高级阻挡模式"), - Component.literal(desired ? "高级阻挡模式:已开启" : "高级阻挡模式:已关闭") - )); + // 与AE2一致:每帧无条件对齐按钮状态至@GuiSync(使用YesNo以获得原版图标与提示) + LOGGER.debug("[EAP] updateBeforeRender tick: desired={}", desired); + if (this.eap$AdvancedBlockingEnabled != desired) { + LOGGER.debug("[EAP] updateBeforeRender: desired changed {} -> {}", this.eap$AdvancedBlockingEnabled, desired); } + this.eap$AdvancedBlockingEnabled = desired; + this.eap$AdvancedBlockingToggle.set(desired ? YesNo.YES : YesNo.NO); } } diff --git a/src/main/java/com/extendedae_plus/network/ToggleAdvancedBlockingC2SPacket.java b/src/main/java/com/extendedae_plus/network/ToggleAdvancedBlockingC2SPacket.java index 49ed237..74bfdea 100644 --- a/src/main/java/com/extendedae_plus/network/ToggleAdvancedBlockingC2SPacket.java +++ b/src/main/java/com/extendedae_plus/network/ToggleAdvancedBlockingC2SPacket.java @@ -2,11 +2,9 @@ package com.extendedae_plus.network; import appeng.menu.implementations.PatternProviderMenu; import com.extendedae_plus.api.AdvancedBlockingHolder; -import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicAccessor; import com.extendedae_plus.mixin.ae2.accessor.PatternProviderMenuAdvancedAccessor; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; @@ -22,7 +20,7 @@ public class ToggleAdvancedBlockingC2SPacket { public static ToggleAdvancedBlockingC2SPacket decode(FriendlyByteBuf buf) { return new ToggleAdvancedBlockingC2SPacket(); - } + } public static void handle(ToggleAdvancedBlockingC2SPacket msg, Supplier ctxSupplier) { var ctx = ctxSupplier.get(); @@ -38,15 +36,8 @@ public class ToggleAdvancedBlockingC2SPacket { boolean current = holder.eap$getAdvancedBlocking(); boolean next = !current; holder.eap$setAdvancedBlocking(next); - // 关键:保存持久化,触发 AE2 写入逻辑(writeToNBT),并由菜单 @GuiSync 同步回客户端 + // 保存并触发 AE2 的菜单 @GuiSync 广播到所有观看该菜单的玩家 logic.saveChanges(); - // 直接下发 S2C 强制同步(带供应器标识:维度+方块坐标) - var host = ((PatternProviderLogicAccessor) logic).eap$host(); - var be = host.getBlockEntity(); - var level = be.getLevel(); - String dimId = level.dimension().location().toString(); - long posLong = be.getBlockPos().asLong(); - ModNetwork.CHANNEL.sendTo(new AdvancedBlockingSyncS2CPacket(dimId, posLong, next), player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); } }); ctx.setPacketHandled(true);