Fabric MC服务器端计分板团队更新不显示给玩家问题排查
问题:Fabric Lifesteal模组计分板团队颜色不生效
我正在为Fabric开发一款服务器端的Lifesteal模组,希望通过计分板团队的颜色来显示玩家剩余的生命数。目前遇到了问题:日志显示玩家已被分配到对应团队,但玩家看不到这个颜色变化。除了自动生成的无解释Javadocs外找不到合适文档,猜测是计分板没正确更新,想请教如何实现正确更新?
public class ScoreboardUtils { public static void updatePlayerTeam(ServerPlayerEntity p) { MinecraftServer server = p.getServer(); if (server == null) return; int lives = PlayerDataManager.loadPlayerInt(p, "lives"); ServerScoreboard sb = server.getScoreboard(); String teamName = Integer.toString(lives); Formatting teamColor = getColorFromValue(lives); Team team = sb.getTeam(teamName); if(team == null) { team = sb.addTeam(teamName); team.setColor(teamColor); } String playername = p.getUuidAsString(); removePlayerFromOtherTeams(playername, sb); team.getPlayerList().add(playername); Lifeanarchy.LOGGER.info(team.getPlayerList().toString() + " for " + teamName); } private static void removePlayerFromOtherTeams(String playerName, ServerScoreboard scoreboard) { for (Team team : scoreboard.getTeams()) { if (team.getPlayerList().contains(playerName)) { team.getPlayerList().remove(playerName); } } } private static Formatting getColorFromValue(int lives) { if (lives > 3) return Formatting.DARK_GREEN; else if (lives == 3) return Formatting.GREEN; else if (lives == 2) return Formatting.YELLOW; else if (lives == 1) return Formatting.RED; else return Formatting.GRAY; } }
解决方案
问题核心在于直接操作team.getPlayerList()的增删不会触发客户端同步,Minecraft要求必须使用计分板提供的官方方法修改团队成员,才能让客户端感知到变化。
修改后的代码如下:
public class ScoreboardUtils { public static void updatePlayerTeam(ServerPlayerEntity p) { MinecraftServer server = p.getServer(); if (server == null) return; int lives = PlayerDataManager.loadPlayerInt(p, "lives"); ServerScoreboard sb = server.getScoreboard(); String teamName = Integer.toString(lives); Formatting teamColor = getColorFromValue(lives); Team team = sb.getTeam(teamName); if (team == null) { team = sb.addTeam(teamName); team.setColor(teamColor); // 可选:根据模组需求设置团队属性,比如禁用友伤 team.setAllowFriendlyFire(false); team.setShowFriendlyInvisibles(false); } String playerId = p.getUuidAsString(); removePlayerFromOtherTeams(playerId, sb); // 使用官方方法添加玩家到团队,自动同步到客户端 sb.addPlayerToTeam(playerId, team); Lifeanarchy.LOGGER.info("玩家 {} 已加入团队 {} (剩余生命数: {})", playerId, teamName, lives); } private static void removePlayerFromOtherTeams(String playerId, ServerScoreboard scoreboard) { // 直接获取玩家当前所在团队,比遍历所有团队更高效 Team currentTeam = scoreboard.getPlayerTeam(playerId); if (currentTeam != null) { // 使用官方方法移除玩家,自动同步到客户端 scoreboard.removePlayerFromTeam(playerId, currentTeam); } } private static Formatting getColorFromValue(int lives) { if (lives > 3) return Formatting.DARK_GREEN; else if (lives == 3) return Formatting.GREEN; else if (lives == 2) return Formatting.YELLOW; else if (lives == 1) return Formatting.RED; else return Formatting.GRAY; } }
关键修改点
- 用官方方法同步成员:
scoreboard.addPlayerToTeam()和scoreboard.removePlayerFromTeam()会自动向所有在线玩家发送团队更新数据包,确保客户端能实时看到颜色变化。 - 优化团队移除逻辑:用
scoreboard.getPlayerTeam(playerId)直接定位玩家当前团队,避免遍历所有团队的低效操作。 - 可选属性配置:根据模组需求添加团队属性(如禁用友伤),提升玩家体验。
如果你的需求是在计分板显示栏中直接显示带颜色的生命数字(而非玩家名称颜色),还需要额外创建计分板Objective并关联分数显示逻辑,但根据现有代码逻辑,上述修改已能解决团队颜色不显示的问题。
内容的提问来源于stack exchange,提问作者phil-not-funny
相关产品推荐
相关产品推荐

