refactor: 榜单改用原版计分板侧边栏显示
服务端读stats定期写入scoreboard objective;客户端/slsboard设本地sidebar display。删掉自绘HUD和网络包(GuiGraphicsExtractor渲染不走)。
This commit is contained in:
1 parent
2097a241aa
commit
870223bc1e
8 files changed
+78
-411
No files matched your search
@@ -1,7 +1,5 @@
|
||||
package com.github.zly2006.carpetslsaddition.client;
|
||||
|
||||
import com.github.zly2006.carpetslsaddition.net.BoardSyncPayload;
|
||||
import com.github.zly2006.carpetslsaddition.net.BoardTogglePayload;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.api.EnvType;
|
||||
@@ -9,75 +7,61 @@ 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.fabricmc.fabric.api.client.rendering.v1.hud.HudElementRegistry;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.Identifier;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.minecraft.world.scores.DisplaySlot;
|
||||
import net.minecraft.world.scores.Objective;
|
||||
|
||||
/**
|
||||
* 客户端入口:接收榜单数据、注册 /slsboard 命令、注册 HUD 渲染。
|
||||
* 客户端入口:/slsboard 命令,控制本地计分板侧边栏显示哪个榜。
|
||||
*
|
||||
* <p>纯客户端功能:显示哪个榜由本地状态决定,各玩家可不同步。
|
||||
* <p>利用原版计分板侧边栏渲染(可靠),各玩家本地切换、互不影响。
|
||||
* 数据由服务端从 stats 同步到 scoreboard objective(见 BoardManager)。
|
||||
*/
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class BoardClient implements ClientModInitializer {
|
||||
|
||||
public static final Identifier HUD_ID = Identifier.fromNamespaceAndPath("slsa", "board_hud");
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
// 1) 接收服务端下发的榜单数据
|
||||
ClientPlayNetworking.registerGlobalReceiver(BoardSyncPayload.TYPE, (payload, context) -> {
|
||||
List<BoardClientState.Entry> entries = new ArrayList<>();
|
||||
for (BoardSyncPayload.Entry e : payload.entries()) {
|
||||
entries.add(new BoardClientState.Entry(e.name(), e.score()));
|
||||
}
|
||||
com.github.zly2006.carpetslsaddition.ServerMain.LOGGER.info("[SLSA-BOARD-C] recv board={} entries={}", payload.board(), entries.size());
|
||||
context.client().execute(() -> BoardClientState.setBoard(payload.board(), entries));
|
||||
});
|
||||
|
||||
// 接收开关状态
|
||||
ClientPlayNetworking.registerGlobalReceiver(BoardTogglePayload.TYPE, (payload, context) -> {
|
||||
context.client().execute(() -> BoardClientState.enabled = payload.enabled());
|
||||
});
|
||||
|
||||
// 2) /slsboard 命令(纯客户端,非 OP 也能用)
|
||||
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
|
||||
dispatcher.register(
|
||||
ClientCommands.literal("slsboard")
|
||||
.then(ClientCommands.literal("deaths")
|
||||
.executes(c -> run(c.getSource(), () -> BoardClientState.toggle("deaths"))))
|
||||
.then(ClientCommands.literal("mined")
|
||||
.executes(c -> run(c.getSource(), () -> BoardClientState.toggle("mined"))))
|
||||
.then(ClientCommands.literal("off")
|
||||
.executes(c -> run(c.getSource(), () -> BoardClientState.set(""))))
|
||||
.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.argument("board", StringArgumentType.word())
|
||||
.suggests((c, b) -> SharedSuggestionProvider.suggest(
|
||||
new String[]{"deaths", "mined", "off"}, b))
|
||||
.executes(c -> {
|
||||
String v = StringArgumentType.getString(c, "board");
|
||||
return run(c.getSource(), () -> BoardClientState.set("off".equals(v) ? "" : v));
|
||||
if ("off".equals(v)) { clear(c.getSource()); return 1; }
|
||||
return show(c.getSource(), "sls_" + v);
|
||||
}))
|
||||
);
|
||||
});
|
||||
|
||||
// 3) HUD 渲染
|
||||
HudElementRegistry.addLast(HUD_ID, new BoardHudElement());
|
||||
}
|
||||
|
||||
/** 统一的命令入口:先检查服务端开关,再执行动作。 */
|
||||
private static int run(FabricClientCommandSource source, Runnable action) {
|
||||
if (!BoardClientState.enabled) {
|
||||
source.sendError(Component.literal("[SLSA] 榜单功能未开启(服务端 /carpet slsBoardEnabled true)"));
|
||||
private static int show(FabricClientCommandSource source, String objectiveName) {
|
||||
var mc = source.getClient();
|
||||
var level = mc.level;
|
||||
if (level == null) {
|
||||
return 0;
|
||||
}
|
||||
action.run();
|
||||
String d = BoardClientState.displaying;
|
||||
source.sendFeedback(Component.literal("[SLSA] 榜单显示:" + (d.isEmpty() ? "关闭" : d)));
|
||||
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));
|
||||
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] 榜单已关闭"));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user