Glitchy记分牌

时间:2015-10-27 04:41:31

标签: java plugins minecraft bukkit

我正在创建一个记分牌,其中包含一个每秒更新一次的计时器。它完美地运作问题是记分板每隔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 :)?我该怎么做才能阻止这个故障?谢谢! :)

3 个答案:

答案 0 :(得分:1)

在不必创建新的棋盘和/或目标的情况下更改记分牌中的得分值是完全可能的,并且消除了我所知道的闪烁(我假设创建了许多新的记分牌是导致闪烁)。您需要跟踪每个Objective的{​​{1}},然后您可以使用这些Player来检索和修改各个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次)以创建动画,它似乎工作得相当好,没有任何闪烁。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

您可以毫无理由地在runnable中创建新的记分板,因为它可以是在runnable外部定义但在runnable中更新的相同记分板。