故障记分牌

Glitchy Scoreboard

我正在创建一个带有每秒更新一次的计时器的记分牌。它工作得很好,问题是记分牌大约每 2-5 秒就会出现一次故障(闪烁)。这是我的代码:

    Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() { 
        public void run() {
             ScoreboardManager manager = Bukkit.getScoreboardManager();
                final Scoreboard board = manager.getNewScoreboard();
                final Objective o = board.registerNewObjective("Timer", "dummy");

            o.setDisplayName(ChatColor.DARK_GRAY + "" + ChatColor.BOLD + "-- " + ChatColor.DARK_RED + ChatColor.BOLD + "Minecraft" + ChatColor.DARK_GRAY + ChatColor.BOLD + " --");
            o.setDisplaySlot(DisplaySlot.SIDEBAR);  

            Score score = o.getScore(ChatColor.GOLD + "Chest Restock in:");
            score.setScore(10);

            if (seconds < 0 ){
                seconds = 118;
                minutes--;
            }

            long second = seconds/2;
            int s = Math.round(second);

            if (seconds > 18 ){
                Score score1 = o.getScore(minutes+":"+s);
                score1.setScore(9);
            } else {
                Score score1 = o.getScore(minutes+":0"+s);
                score1.setScore(9);
            }

            Score score2 = o.getScore(" ");
            score2.setScore(8);

            Score scoreName = o.getScore(""+ChatColor.GOLD + ChatColor.BOLD + player.getName());
            scoreName.setScore(7);

            Score score3 = o.getScore("  ");
            score3.setScore(6);

            int kills = kdData.getInt(player.getName() + ".Kills");

            Score score4 = o.getScore("Kills: " + ChatColor.DARK_RED + kills);
            score4.setScore(5);

            Score score5 = o.getScore("   ");
            score5.setScore(4);

            int deaths = kdData.getInt(player.getName() + ".Deaths");

            Score score6 = o.getScore("Deaths: " + ChatColor.DARK_RED + deaths);
            score6.setScore(3);

            Score score7 = o.getScore("    ");
            score7.setScore(2);


            double killsD = kdData.getInt(player.getName() + ".Kills");
            double deathsD = kdData.getInt(player.getName() + ".Deaths");

            if( kills >= 0 && deaths == 0){ 
            double kd = killsD/1;
            Score score8 = o.getScore("KD Ratio: " + ChatColor.GOLD + kd);
            score8.setScore(1);
            }
            if( kills >= 0 && deaths > 0){
                double kd = killsD/deathsD;
                double kdRounded = Math.round(kd * 100.0) / 100.0;

                Score score8 = o.getScore("KD Ratio: " + ChatColor.GOLD + String.valueOf(kdRounded));
                score8.setScore(1); 
            }

            Score score9 = o.getScore("     ");
            score9.setScore(0);
            player.setScoreboard(board);

        }

    }, 0, 20L);

}   

基本上我每秒都在创建一个新的记分牌。是否可以每秒仅更新计时器(Chest Restock in:)?我该怎么做才能阻止这种故障?谢谢! :)

计分板故障是由客户端或服务器延迟引起的,除非您对计分板代码非常清楚,否则无法解决此问题。任何更大的 server/network 都会有记分板故障。

无需创建新板即可更改记分板中的得分值 and/or objective 是完全可能的,并且据我所知消除了闪烁(我假设创建了很多新板记分牌是闪烁的主要原因)。您需要跟踪每个 PlayerObjective,然后您可以使用它来检索和编辑各个 Score 值。更改值后,显示将自动为客户端更新,无需重新设置玩家的记分牌。这是一个任务示例,可以在任何时间间隔 运行 更新具有多个分数的一般显示(不应闪烁):

public class ScoreboardUpdater implements Runnable {

    // A map that associates a player's ID to their objective (you can of course use something completely different)
    private static HashMap<UUID, Objective> playerObjectiveMap = new HashMap<UUID, Objective>();

    public void run() {
        for (Player player : Bukkit.getOnlinePlayers()) { // Loop through all plauers
            UUID id = player.getUniqueId(); // Get their unique ID

            if (!playerObjectiveMap.containsKey(id)) { // If they don't have an objective yet
                Scoreboard board = Bukkit.getScoreboardManager().getNewScoreboard(); // Get a new scoreboard
                Objective objective = board.registerNewObjective("test", "dummy"); // Create the objective that will contain the scores
                objective.setDisplaySlot(DisplaySlot.SIDEBAR); // Move the display to the sidebar
                objective.setDisplayName("Name of Display"); // Name the display something
                // Here you can optionally initialize the score values for the player by using the getScore() method like below
                player.setScoreboard(board); // Display the initial scoreboard to the player
                playerObjectiveMap.put(id, objective); // Add the objective to the map
            }

            Objective objective = playerObjectiveMap.get(id); // Retrieve objective for the player from map

            // Now that you have the player's objective, you can change the value of any scores!
            Score score = objective.getScore("Example Score: "); // Create a score
            score.setScore((int) (Math.random() * 10)); // Set a value (automatically updates for the client)
            Score score2 = objective.getScore("Another Score: "); // Create another score
            score2.setScore((int) (Math.random() * 50)); // Update
        }
    }
}

然后您可以像这样安排此任务:

Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new ScoreboardUpdater(), 0, 20L);

我将这种方法用于记分牌,每个刻度(每秒 20 次)更新一个值来创建动画,它似乎工作得相当好,没有任何闪烁。

您无缘无故地在可运行对象中创建了一个新记分板,因为它可以是在可运行对象之外定义但在可运行对象中更新的相同记分板。