修复智能阻挡多人游戏显示状态同步异常问题
This commit is contained in:
parent
fccf7b88a1
commit
6362c79a66
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = "<init>(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) {
|
||||
|
|
|
|||
|
|
@ -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<C extends PatternProviderMenu> extends AEBaseScreen<C> {
|
||||
|
||||
@Unique
|
||||
private ToggleButton eap$AdvancedBlockingToggle;
|
||||
private SettingToggleButton<YesNo> 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 = "<init>", 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<YesNo> 的外观(原版图标),但自定义悬停描述为“智能阻挡”
|
||||
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<net.minecraft.network.chat.Component> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<NetworkEvent.Context> 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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user