feat: 修改为服务端向目标玩家发送样板高亮包,移除全局高亮

This commit is contained in:
C-H716 2025-09-02 02:36:07 +08:00
parent f254da43f4
commit 29b92e4ee1
6 changed files with 104 additions and 10 deletions

View File

@ -0,0 +1,34 @@
package com.extendedae_plus.content;
import appeng.api.stacks.AEKey;
import appeng.api.crafting.IPatternDetails;
import appeng.client.gui.me.patternaccess.PatternContainerRecord;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* 客户端本地的高亮存储仅作用于接收该客户端
* 使用 AEKey 作为标识渲染时可通过 AEKey 与本地解码的 IPatternDetails 比对
*/
public final class ClientPatternHighlightStore {
private static final Set<AEKey> HIGHLIGHTS = Collections.synchronizedSet(new HashSet<>());
private ClientPatternHighlightStore() {}
public static void setHighlight(AEKey key, boolean highlight) {
if (key == null) return;
if (highlight) HIGHLIGHTS.add(key);
else HIGHLIGHTS.remove(key);
}
public static boolean hasHighlight(AEKey key) {
if (key == null) return false;
return HIGHLIGHTS.contains(key);
}
public static void clearAll() { HIGHLIGHTS.clear(); }
}

View File

@ -13,7 +13,7 @@ import appeng.client.gui.style.Text;
import appeng.client.gui.style.TextAlignment; import appeng.client.gui.style.TextAlignment;
import appeng.menu.slot.AppEngSlot; import appeng.menu.slot.AppEngSlot;
import com.extendedae_plus.api.ExPatternPageAccessor; import com.extendedae_plus.api.ExPatternPageAccessor;
import com.extendedae_plus.content.PatternHighlightStore; import com.extendedae_plus.content.ClientPatternHighlightStore;
import com.extendedae_plus.network.CraftingMonitorJumpC2SPacket; import com.extendedae_plus.network.CraftingMonitorJumpC2SPacket;
import com.extendedae_plus.network.CraftingMonitorOpenProviderC2SPacket; import com.extendedae_plus.network.CraftingMonitorOpenProviderC2SPacket;
import com.extendedae_plus.network.ModNetwork; import com.extendedae_plus.network.ModNetwork;
@ -182,11 +182,16 @@ public abstract class AEBaseScreenMixin {
try { try {
var details = PatternDetailsHelper.decodePattern(itemStack, Minecraft.getInstance().level, false); var details = PatternDetailsHelper.decodePattern(itemStack, Minecraft.getInstance().level, false);
if (PatternHighlightStore.getHighlight(details)) { try {
try { if (details != null && details.getOutputs() != null && details.getOutputs().length > 0) {
GuiUtil.drawSlotRainbowHighlight(guiGraphics, s.x, s.y); AEKey key = details.getOutputs()[0].what();
} catch (Throwable ignored) {} if (key != null && ClientPatternHighlightStore.hasHighlight(key)) {
} try {
GuiUtil.drawSlotRainbowHighlight(guiGraphics, s.x, s.y);
} catch (Throwable ignored) {}
}
}
} catch (Throwable ignore) {}
} catch (Throwable ignore) {} } catch (Throwable ignore) {}
} }

View File

@ -1,7 +1,7 @@
package com.extendedae_plus.mixin.ae2.client.gui; package com.extendedae_plus.mixin.ae2.client.gui;
import appeng.client.gui.implementations.PatternProviderScreen; import appeng.client.gui.implementations.PatternProviderScreen;
import com.extendedae_plus.content.PatternHighlightStore; import com.extendedae_plus.content.ClientPatternHighlightStore;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -20,7 +20,7 @@ public class PatternProviderCloseMixin {
private void onRemoved(CallbackInfo ci) { private void onRemoved(CallbackInfo ci) {
try { try {
if (((Object) this) instanceof PatternProviderScreen) { if (((Object) this) instanceof PatternProviderScreen) {
PatternHighlightStore.clearAll(); ClientPatternHighlightStore.clearAll();
} }
} catch (Throwable ignored) { } catch (Throwable ignored) {
} }

View File

@ -94,6 +94,12 @@ public class CraftingMonitorOpenProviderC2SPacket {
// 直接打开供应器自身的 UI调用 Host 默认方法 // 直接打开供应器自身的 UI调用 Host 默认方法
try { try {
// 告知目标玩家客户端高亮该 AEKey避免全局服务端状态污染
try {
AEKey key = pattern.getOutputs()[0].what();
ModNetwork.CHANNEL.sendTo(new SetPatternHighlightS2CPacket(key, true), player.connection.connection, net.minecraftforge.network.NetworkDirection.PLAY_TO_CLIENT);
} catch (Throwable t) {}
// 部件与方块实体分别选择定位器 // 部件与方块实体分别选择定位器
if (host instanceof AEBasePart part) { if (host instanceof AEBasePart part) {
host.openMenu(player, MenuLocators.forPart(part)); host.openMenu(player, MenuLocators.forPart(part));
@ -101,8 +107,6 @@ public class CraftingMonitorOpenProviderC2SPacket {
host.openMenu(player, MenuLocators.forBlockEntity(pbe)); host.openMenu(player, MenuLocators.forBlockEntity(pbe));
} }
PatternHighlightStore.setHighlight(pattern, true);
context.setPacketHandled(true); context.setPacketHandled(true);
return; return;
} catch (Throwable t) { } catch (Throwable t) {

View File

@ -60,6 +60,12 @@ public class ModNetwork {
.consumerNetworkThread(ProvidersListS2CPacket::handle) .consumerNetworkThread(ProvidersListS2CPacket::handle)
.add(); .add();
CHANNEL.messageBuilder(SetPatternHighlightS2CPacket.class, nextId(), NetworkDirection.PLAY_TO_CLIENT)
.encoder(SetPatternHighlightS2CPacket::encode)
.decoder(SetPatternHighlightS2CPacket::decode)
.consumerNetworkThread(SetPatternHighlightS2CPacket::handle)
.add();
CHANNEL.messageBuilder(ToggleAdvancedBlockingC2SPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER) CHANNEL.messageBuilder(ToggleAdvancedBlockingC2SPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER)
.encoder(ToggleAdvancedBlockingC2SPacket::encode) .encoder(ToggleAdvancedBlockingC2SPacket::encode)
.decoder(ToggleAdvancedBlockingC2SPacket::decode) .decoder(ToggleAdvancedBlockingC2SPacket::decode)

View File

@ -0,0 +1,45 @@
package com.extendedae_plus.network;
import appeng.api.stacks.AEKey;
import com.extendedae_plus.content.ClientPatternHighlightStore;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
/**
* S2C: 指示客户端对某个 AEKey 的样板进行高亮/取消高亮仅作用于接收该包的客户端
*/
public class SetPatternHighlightS2CPacket {
private final AEKey key;
private final boolean highlight;
public SetPatternHighlightS2CPacket(AEKey key, boolean highlight) {
this.key = key;
this.highlight = highlight;
}
public static void encode(SetPatternHighlightS2CPacket msg, FriendlyByteBuf buf) {
AEKey.writeKey(buf, msg.key);
buf.writeBoolean(msg.highlight);
}
public static SetPatternHighlightS2CPacket decode(FriendlyByteBuf buf) {
AEKey key = AEKey.readKey(buf);
boolean h = buf.readBoolean();
return new SetPatternHighlightS2CPacket(key, h);
}
public static void handle(SetPatternHighlightS2CPacket msg, Supplier<NetworkEvent.Context> ctxSupplier) {
var ctx = ctxSupplier.get();
ctx.enqueueWork(() -> {
try {
ClientPatternHighlightStore.setHighlight(msg.key, msg.highlight);
} catch (Throwable ignored) {
}
});
ctx.setPacketHandled(true);
}
}