From 5001b2f5a261cd0aa5759716233c46859a3e8b11 Mon Sep 17 00:00:00 2001 From: Ap_Tx <3045929398@qq.com> Date: Tue, 6 Oct 2026 21:22:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20/slsboard=E6=94=B9=E5=8F=91=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=8C=85=EF=BC=8C=E6=9C=8D=E5=8A=A1=E7=AB=AF=E7=BB=99?= =?UTF-8?q?=E8=AF=A5=E7=8E=A9=E5=AE=B6=E5=8D=95=E7=8B=AC=E5=8F=91display?= =?UTF-8?q?=E5=8C=85=EF=BC=88per-player=E6=98=BE=E7=A4=BA=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 客户端本地setDisplayObjective会被服务端覆盖,改用C2S请求包,服务端单独发ClientboundSetDisplayObjectivePacket给请求者。 --- .../zly2006/carpetslsaddition/ServerMain.java | 7 ++++ .../carpetslsaddition/client/BoardClient.java | 42 ++++++------------- .../net/BoardRequestPayload.java | 35 ++++++++++++++++ .../carpetslsaddition/util/BoardManager.java | 16 ++++++- 4 files changed, 69 insertions(+), 31 deletions(-) create mode 100644 src/main/java/com/github/zly2006/carpetslsaddition/net/BoardRequestPayload.java diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java b/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java index 68b6666..edbe613 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java @@ -43,6 +43,13 @@ public class ServerMain implements ModInitializer, CarpetExtension { LOGGER.info("[SLSA] onInitialize: managing Carpet extension"); INSTANCE = this; CarpetServer.manageExtension(this); + com.github.zly2006.carpetslsaddition.net.BoardRequestPayload.register(); + // 客户端请求显示榜单 → 给该玩家单独发 display 包 + net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking.registerGlobalReceiver( + com.github.zly2006.carpetslsaddition.net.BoardRequestPayload.TYPE, + (payload, context) -> context.server().execute(() -> + com.github.zly2006.carpetslsaddition.util.BoardManager.onClientRequest( + context.player(), payload.objectiveName()))); } @Override diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/client/BoardClient.java b/src/main/java/com/github/zly2006/carpetslsaddition/client/BoardClient.java index 0f945bd..a8939c5 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/client/BoardClient.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/client/BoardClient.java @@ -1,5 +1,6 @@ package com.github.zly2006.carpetslsaddition.client; +import com.github.zly2006.carpetslsaddition.net.BoardRequestPayload; import com.mojang.brigadier.arguments.StringArgumentType; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.EnvType; @@ -7,15 +8,14 @@ import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.command.v2.ClientCommands; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.network.chat.Component; -import net.minecraft.world.scores.DisplaySlot; -import net.minecraft.world.scores.Objective; /** - * 客户端入口:/slsboard 命令,控制本地计分板侧边栏显示哪个榜。 + * 客户端入口:/slsboard 命令,请求服务端给自己显示某个榜单。 * - *
利用原版计分板侧边栏渲染(可靠),各玩家本地切换、互不影响。 + *
服务端收到请求后,给该玩家单独发 display 包,实现各玩家各自显示、互不影响。 * 数据由服务端从 stats 同步到 scoreboard objective(见 BoardManager)。 */ @Environment(EnvType.CLIENT) @@ -26,42 +26,24 @@ public class BoardClient implements ClientModInitializer { ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { dispatcher.register( ClientCommands.literal("slsboard") - .then(ClientCommands.literal("deaths").executes(c -> show(c.getSource(), "sls_deaths"))) - .then(ClientCommands.literal("mined").executes(c -> show(c.getSource(), "sls_mined"))) - .then(ClientCommands.literal("off").executes(c -> { clear(c.getSource()); return 1; })) + .then(ClientCommands.literal("deaths").executes(c -> request(c.getSource(), "sls_deaths"))) + .then(ClientCommands.literal("mined").executes(c -> request(c.getSource(), "sls_mined"))) + .then(ClientCommands.literal("off").executes(c -> request(c.getSource(), ""))) .then(ClientCommands.argument("board", StringArgumentType.word()) .suggests((c, b) -> SharedSuggestionProvider.suggest( new String[]{"deaths", "mined", "off"}, b)) .executes(c -> { String v = StringArgumentType.getString(c, "board"); - if ("off".equals(v)) { clear(c.getSource()); return 1; } - return show(c.getSource(), "sls_" + v); + return request(c.getSource(), "off".equals(v) ? "" : "sls_" + v); })) ); }); } - private static int show(FabricClientCommandSource source, String objectiveName) { - var mc = source.getClient(); - var level = mc.level; - if (level == null) { - return 0; - } - Objective obj = level.getScoreboard().getObjective(objectiveName); - if (obj == null) { - source.sendError(Component.literal("[SLSA] 找不到计分板 " + objectiveName + "(服务端规则未开启?)")); - return 0; - } - level.getScoreboard().setDisplayObjective(DisplaySlot.SIDEBAR, obj); - source.sendFeedback(Component.literal("[SLSA] 榜单显示:" + objectiveName)); + private static int request(FabricClientCommandSource source, String objectiveName) { + ClientPlayNetworking.send(new BoardRequestPayload(objectiveName)); + source.sendFeedback(Component.literal( + objectiveName.isEmpty() ? "[SLSA] 榜单已关闭" : "[SLSA] 请求显示:" + objectiveName)); return 1; } - - private static void clear(FabricClientCommandSource source) { - var level = source.getClient().level; - if (level != null) { - level.getScoreboard().setDisplayObjective(DisplaySlot.SIDEBAR, null); - } - source.sendFeedback(Component.literal("[SLSA] 榜单已关闭")); - } } \ No newline at end of file diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/net/BoardRequestPayload.java b/src/main/java/com/github/zly2006/carpetslsaddition/net/BoardRequestPayload.java new file mode 100644 index 0000000..d1f19c1 --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/net/BoardRequestPayload.java @@ -0,0 +1,35 @@ +package com.github.zly2006.carpetslsaddition.net; + +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.Identifier; + +/** + * 客户端 → 服务端:请求显示某个榜单(或关闭)。 + * + *
服务端收到后,给该玩家单独发送 {@code ClientboundSetDisplayObjectivePacket}, + * 实现"各玩家各自显示、互不影响"。 + * + *
{@code objectiveName} 为空字符串表示关闭。
+ */
+public record BoardRequestPayload(String objectiveName) implements CustomPacketPayload {
+
+ public static final CustomPacketPayload.Type