[Tutorial] Scoreboards/Teams with the Bukkit API

Discussion in 'Resources' started by chasechocolate, Apr 5, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    macmc

    Yes exactly, I would like to be able to add whatever formatting I want without having a mandatory score for my objective, so basically only showing the display name.
    What I don't like about scores is that I didn't find a way to add some text after the score, which means that you'll always get a number at the end of your sidebar, even though you don't want it.
    I'm wondering if there could be a way to bypass this.
     
  2. Offline

    vasil7112

    What if instead of just 1 variable(Kills) We wanted 2?(Kills + Deaths).
    I am talking about this
    [​IMG]
    How can we add under kills, 1 more or even more variables?
     
  3. Offline

    chasechocolate

    Simply add a new score:
    Code:java
    1. Score scoreKills = objective.getScore(Bukkit.getOfflinePlayer(ChatColor.GREEN + "Kills:"));
    2. Score scoreDeaths = objective.getScore(Bukkit.getOfflinePlayer(ChatColor.GREEN + "Deaths:"));
    3.  
    4. scoreKills.setScore(1);
    5. scoreDeaths.setScore(3);
     
  4. Offline

    hawkfalcon

    Something important.
    player.getScoreboard();
    :p
     
  5. Offline

    etaxi341

    How can I show the same scoreboard to different Players? So they all have different things in the Scoreboard.

    Player 1:

    Statistics:
    Level: 1
    Money: 100

    Player 2:

    Statistics:
    Level: 10
    Money: 20

    Sorry for my Bad English

    Edit: I haven't found a way to store the scoreboards in Hashmaps. I know how to store them but its no different if i use the Saved Scoreboard or the not saved one. Because If I modify the scoreboard with this name It will modify the saved Scoreboard too...

    Please I need your Help! Thanks!
     
  6. Offline

    Rockslide

    @chasechocolate

    I still haven't been able to fix this problem. Please help:

     
    etaxi341 likes this.
  7. Offline

    chasechocolate

    etaxi341 like you mentioned, create a HashMap<String, Scoreboard> and save player scoreboards in there:
    Code:java
    1. HashMap<String, Scoreboard> playerScoreboards = new HashMap<String, Scoreboard>();
    2.  
    3. //Creating a new scoreboard for a player
    4. Scoreboard board = manager.getNewScoreboard();
    5. //Register objectives and scores
    6.  
    7. player.setScoreboard(board);
    8. playerScoreboards.put(player.getName(), board);

    And then I would create an update() method to change the player's stats.

    Rockslide a bug possibly? It works fine for me.
     
  8. Offline

    etaxi341

    Thank you! I got it working by using this code (Coded by me)
    Code:java
    1. public static HashMap<String, Scoreboard> UsedScoreboard = new HashMap<String, Scoreboard>();
    2. public static HashMap<String, Score> levelscore = new HashMap<String, Score>();
    3. public static HashMap<String, Score> moneyscore = new HashMap<String, Score>();
    4.  
    5. public static void create(Player p, String BoardName, String BoardDisplayName){
    6. ScoreboardManager manager = Bukkit.getScoreboardManager();
    7. Scoreboard board = manager.getNewScoreboard();
    8.  
    9. Objective objective = board.registerNewObjective(BoardName, "dummy");
    10.  
    11. objective.setDisplaySlot(DisplaySlot.SIDEBAR);
    12. objective.setDisplayName(BoardDisplayName);
    13.  
    14. Score level = objective.getScore(Bukkit.getOfflinePlayer(ChatColor.GREEN + "Level" + ChatColor.GRAY + ":"));
    15. Score money = objective.getScore(Bukkit.getOfflinePlayer(ChatColor.GREEN + "Money" + ChatColor.GRAY + ":"));
    16.  
    17. level.setScore(0);
    18. money.setScore(0);
    19.  
    20. levelscore.put(p.getName(), level);
    21. moneyscore.put(p.getName(), money);
    22.  
    23. UsedScoreboard.put(p.getName(), board);
    24. }
    25.  
    26. public static void update(Player p){
    27.  
    28. Score level = levelscore.get(p.getName());
    29. Score money = moneyscore.get(p.getName());
    30.  
    31. level.setScore(PlayerDataListener.getLevel(p.getName()));
    32. money.setScore(PlayerDataListener.getMoney(p));
    33.  
    34. }
    35.  
    36. public static void set(Player p){
    37.  
    38. p.setScoreboard(UsedScoreboard.get(p.getName()));
    39.  
    40. }
     
    KeshSyndney and The Fancy Whale like this.
  9. Offline

    Sebi

    Hi, I've got a problem with the sidebar scoreboard. I've probably missed something but it appears grayed out and barely visible. Anyone else had this problem?
    [​IMG]

    I don't use any fancy code:
    Code:
    // When player goes into a state where they should have info displayed:
    ply.sboard = Bukkit.getScoreboardManager().getNewScoreboard();
     
    Objective sobjective = ply.sboard.registerNewObjective("status", "dummy");
    sobjective.setDisplayName(ChatColor.GREEN+ply.getName()+":");
    sobjective.setDisplaySlot(DisplaySlot.SIDEBAR);
     
    updatePlayerScore(ply);
    pl.setScoreboard(ply.sboard);
     
     
    // updatePlayerScore:
    updatePlayerScore(PlayerDescriptor ply) {
        Objective sobjective = ply.sboard.getObjective("status");
        sobjective.getScore(Bukkit.getOfflinePlayer(ChatColor.YELLOW+"Punkty: ")).setScore(ply.ranking);
        sobjective.getScore(Bukkit.getOfflinePlayer(ChatColor.YELLOW+"PieniÄ…dze: ")).setScore(ply.cash/100);
    }
    EDIT: Sorry, it was a fault of MinecraftIM client mod, after disabling it everything works fine :)
     
  10. Offline

    kreashenz

    How to check if the scoreboard exists then add on to it? Is it possible or what?
     
  11. Offline

    xCyanide

    How would I update the scoreboard without having to create a new scoreboard for it to update. Like I have timer with and it will basically countdown,but my scoreboard won't update and I also want it to update whenever a player join. Creating a new scoreboard all the time makes it look really nasty(I am really picky about things :p. and every time I set a new scoreboard it removes the current scoreboard and it looks like it is flashing if I do it every second)
     
  12. Offline

    etaxi341

    xCyanide
    Look at my Post above. I made an Update Method so you just need to trigger the scoreboard creating once if a player joins and then about every seconds / 20 Ticks you use the update() method by me

    kreashenz
    On scoreboard create you could save this data in an hashmap so you can check if the hashmap already contains this player or not. If not you could create the scoreboard for this Player
     
  13. Offline

    xCyanide

    etaxi341
    Do you have a method that will update the displayname of the scoreboard as well becuase I forgot to mention my time is in my header of the scoreboard and your method works wonders :)
     
  14. Offline

    etaxi341

    You just need to rename the objective like this:

    The first time when you create the Scoreboard you need to use this
    Code:java
    1. Objective objective = board.registerNewObjective(BoardName, "dummy");
    2. objective.setDisplayName("StartDisplayName");


    And to update the name every Second you need this
    Code:java
    1. objective.setDisplayName("NewDisplayName");


    I haven't tested it but i think it should work like this.
     
  15. Offline

    xCyanide

    etaxi341
    I have a method that will create a scoreboard for me, but when I made the objective and scoreboard and scoreboard manager a class variable it gave me a null pointer exception
     
  16. Offline

    etaxi341

    xCyanide
    Could you show me the piece of code where you create and manage the scoreboard and the line where the null pointer is ?
     
  17. Offline

    xCyanide

    etaxi341 likes this.
  18. Offline

    timtower Administrator Administrator Moderator

    chasechocolate How about using multiple scoreboards per player, is this possible?
     
  19. Offline

    etaxi341

    timtower I think it's a bug. It should be possible to do this because it is possible with CommandBlocks. But I haven't found a way to use 2 Scoreboards at once too!
     
  20. Offline

    timtower Administrator Administrator Moderator

    Kinda hate it, now you can only have 1 scoreboard at the time...
     
  21. Offline

    timtower Administrator Administrator Moderator

    chasechocolate, any way to reset the scoreboard? ATM I am using this code:
    Code:
    package nl.timdebrouwer.top10scoreboards;
     
    import java.util.HashMap;
    import java.util.Set;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.configuration.ConfigurationSection;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.plugin.java.JavaPlugin;
    import org.bukkit.scoreboard.*;
     
    public class Top10ScoreBoards extends JavaPlugin implements Listener{
        private ScoreboardManager manager;
        private Scoreboard board;
        private Team team;
        private Objective objective;
        private HashMap<String,Integer> scorelist;
       
       
        public void onEnable(){
            scorelist = new HashMap<String,Integer>();
            this.saveDefaultConfig();
            this.getConfig().options().copyDefaults(true);
            this.saveConfig();
            manager = this.getServer().getScoreboardManager();
            board = manager.getMainScoreboard();/*manager.getNewScoreboard();*/
            team = board.registerNewTeam("Top10");
            board.clearSlot(DisplaySlot.SIDEBAR);
            objective = board.registerNewObjective("Top10", "dummy");
            objective.setDisplaySlot(DisplaySlot.SIDEBAR);
            objective.setDisplayName("Top votes");
            team.setCanSeeFriendlyInvisibles(false);
            team.setAllowFriendlyFire(true);
            this.getServer().getPluginManager().registerEvents(this, this);
            loadMap();
            updateMap();
        }
        public void onDisable(){
            saveMap();
            team.unregister();
            objective.unregister();
        }
       
        @EventHandler
        public void onJoin(PlayerJoinEvent event){
            updateMap();
        }
        private void updateMap() {
            HashMap<String,Integer> tempscore = scorelist;
            for(String name:tempscore.keySet()){
                board.resetScores(this.getServer().getOfflinePlayer(name));
            }
            int teller = 0;
            while(tempscore.size()!=0 && teller<10){
                String name = "";
                int number = -1;
                for(String nametemp:tempscore.keySet()){
                    if(tempscore.get(nametemp)>number){
                        number = tempscore.get(nametemp);
                        name = nametemp;
                    }
                }
                tempscore.remove(name);
                teller++;
                if(name.length()>16){
                    name = name.substring(0, 15);
                }
                Score score = objective.getScore(this.getServer().getOfflinePlayer(name));
                score.setScore(number);
            }
            for(Player player:this.getServer().getOnlinePlayers()){
                player.setScoreboard(board);
            }
        }
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
            if(args.length!=2){
                sender.sendMessage("Need an name and score to add to do something");
                return true;
            }
            if(args[0].equalsIgnoreCase("reset") && args[1].equalsIgnoreCase("confirm")){
                for(String name:scorelist.keySet()){
                    board.resetScores(this.getServer().getOfflinePlayer(name));
                }
                this.getConfig().set("score", null);
                this.getConfig().createSection("score");
                this.saveConfig();
                updateMap();
                return true;
            }
            int adding = Double.valueOf(args[1]).intValue();
            int source = getNumber(args[0]);
            int result = adding+source;
            setNumber(args[0],result);
            saveMap();
            updateMap();
            return true;
        }
        private void saveMap() {
            ConfigurationSection config = this.getConfig().getConfigurationSection("score");
            Set<String> list = scorelist.keySet();
            for(String name:list){
                config.set(name, scorelist.get(name));
            }
            this.saveConfig();
        }
       
        private void loadMap() {
            ConfigurationSection config = this.getConfig().getConfigurationSection("score");
            Set<String> list = config.getKeys(false);
            scorelist = new HashMap<String,Integer>();
            for(String name:list){
                scorelist.put(name, config.getInt(name));
            }
        }
     
        private void setNumber(String name,int number){
            scorelist.put(name, number);
        }
       
       
        private int getNumber(String name){
            loadMap();
            if(!scorelist.containsKey(name)){
                return 0;
            }
            return scorelist.get(name);
        }
       
    }
    
    Still prefer compatibility with other plugins
     
  22. Offline

    NLGamingBross

    This code dont work for me!
    Code:java
    1. ScoreboardManager manager = Bukkit.getScoreboardManager();
    2. Scoreboard board = manager.getNewScoreboard();
    3.  
    4. Objective objective = board.registerNewObjective("showhealth", "health");
    5. objective.setDisplaySlot(DisplaySlot.BELOW_NAME);
    6. objective.setDisplayName("/ 20");
    7.  
    8. for(Player online : Bukkit.getOnlinePlayers()){
    9. online.setScoreboard(board);
    10. online.setHealth(online.getHealth()); //Update their health
    11. }


    Or i paste it in an event? How it works to use that
     
  23. Offline

    xCyanide

    etaxi341
    Hey, do you know how I can fix this? When there are 2 players online it will only update the time for one of the players
    Code:java
    1. public void updateTime() {
    2. plugin.staskID = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable(){
    3. public void run(){
    4. objective.setDisplayName(GameMOTD.motdPrefix + ChatColor.GOLD + " Time: " + GameTimer.formattedTime());
    5. }
    6. }, 20, 20);
    7. }
     
  24. Offline

    Anchll

    MCPVP ruined the invisibility potion on their hardcore server by using the scoreboard. EVERYBODY using the invisibility potion can be seen. Just to be fancy.
     
  25. Offline

    etaxi341

    Where do you call this Method? If Its in the onEnable() you should update it for everyone like this:
    Code:java
    1. for (Player p : Bukkit.getServer().getOnlinePlayers(){
    2. updateTime();
    3. set(p);
    4. }


    The set(p) method is from my post at page 8. I think it should work like this.

    Or if this won't work could you tell me where you created the objective ? because you use objective.setDisplay...
    You need to set the DisplayName of the Scoreboard for the right Person because if you use my Methods at Page 8 you need to save the Objective in a Hashmap.
     
  26. Offline

    xCyanide

    etaxi341
    Well this is my class for the scoreboards and I create the scoreboard when the player joins
    Code:java
    1. public class ScoreboardHandler {
    2.  
    3. private static Main plugin;
    4. public Map<String, Score> killscore = new HashMap<String, Score>();
    5. public Map<String, Score> alivescore = new HashMap<String, Score>();
    6. public Map<String, Score> specscore = new HashMap<String, Score>();
    7.  
    8. ScoreboardManager manager;
    9. Scoreboard board;
    10. Objective objective;
    11.  
    12. public ScoreboardHandler(Main plugin) {
    13. ScoreboardHandler.plugin = plugin;
    14. }
    15.  
    16. public void createScoreboard(Player p) {
    17. manager = Bukkit.getScoreboardManager();
    18. board = manager.getNewScoreboard();
    19. objective = board.registerNewObjective("SGStats", "dummy");
    20. objective.setDisplaySlot(DisplaySlot.SIDEBAR);
    21. objective.setDisplayName(GameMOTD.motdPrefix + ChatColor.GOLD + " Time: " + GameTimer.formattedTime());
    22.  
    23. Score score = objective.getScore(Bukkit.getOfflinePlayer(ChatColor.GREEN + "Kills:"));
    24. score.setScore(0);
    25.  
    26. plugin.kills.put(p.getName(), 0);
    27. killscore.put(p.getName(), score);
    28.  
    29. Score score2 = objective.getScore(Bukkit.getOfflinePlayer(ChatColor.GREEN + "Alive:"));
    30. score2.setScore(plugin.gplayers.size());
    31.  
    32. alivescore.put(p.getName(), score2);
    33.  
    34. Score score3 = objective.getScore(Bukkit.getOfflinePlayer(ChatColor.GREEN + "Spectators:"));
    35. score3.setScore(plugin.spectators.size());
    36.  
    37. specscore.put(p.getName(), score3);
    38.  
    39. p.setScoreboard(board);
    40.  
    41. }
    42.  
    43. public void update(Player p) {
    44.  
    45. Score alive = alivescore.get(p.getName());
    46. Score specs = specscore.get(p.getName());
    47.  
    48. alive.setScore(plugin.sgplayers.size());
    49. specs.setScore(plugin.spectators.size());
    50. }
    51.  
    52. public void updateKill(Player p) {
    53.  
    54. Score kills = killscore.get(p.getName());
    55.  
    56. kills.setScore(plugin.kills.get(p.getName()));
    57. }
    58.  
    59. public void updateTime() {
    60. plugin.staskID = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable(){
    61. public void run(){
    62. objective.setDisplayName(GameMOTD.motdPrefix + ChatColor.GOLD + " Time: " + GameTimer.formattedTime());
    63. }
    64. }, 20, 20);
    65. }
    66. }


    And I update the time in this class
    Code:java
    1. public void run() {
    2. if (time == 900 || time == 300 || time == 60 && time > 0) {
    3. Bukkit.getServer().broadcastMessage(Main.prefix + ChatColor.AQUA + getMinutes() + ChatColor.GOLD + " minutes until death match begins");
    4. }
    5. if(time == 600) {
    6. Bukkit.getServer().broadcastMessage(Main.prefix + ChatColor.AQUA + getMinutes() + ChatColor.GOLD + " minutes until death match begins");
    7. }
    8. if(time == 500) {
    9. plugin.getServer().getScheduler().cancelTask(plugin.taskID);
    10. }
    11. if(time == 50 || time == 40 || time == 30 || time == 20) {
    12. Bukkit.getServer().broadcastMessage(Main.prefix + ChatColor.AQUA + getSeconds() + ChatColor.GOLD + " seconds until death match begins");
    13. }
    14. if(time <= 10 && time > 1) {
    15. Bukkit.getServer().broadcastMessage(Main.prefix + ChatColor.AQUA + getSeconds() + ChatColor.GOLD + " seconds until death match begins");
    16. }
    17. if(time == 1) {
    18. Bukkit.getServer().broadcastMessage(Main.prefix + ChatColor.AQUA + getSeconds() + ChatColor.GOLD + " second until death match begins");
    19. TaskHandler.cancelGameTimer(plugin);
    20. plugin.setGameStatus(GameStatus.DEATHMATCH);
    21. Bukkit.broadcastMessage(Main.prefix + ChatColor.DARK_RED + "The death match begins!");
    22. TaskHandler.startDeathMatchTimer(plugin);
    23. }
    24. time -= 1;
    25. plugin.sh.updateTime();
    26. }
     
  27. Offline

    etaxi341

    xCyanide
    I think I found your Problem. You need to save the scoreboard in a Hashmap too because if you won't do this you will only update the score of the last joined player. And there is another thing. When you create a Scoreboard you gave the Scoreboard a Name and a DisplayName. The Name can only exist once. So the best way is to call the scoreboard like the PlayerName and just let the DisplayName of The Scoreboard the same in every Scoreboard.

    Here is what you need to Change:

    First you need to add at the top of your Method Class a new Hashmap:
    Code:java
    1. public static HashMap<String, Scoreboard> playerScoreboards = new HashMap<String, Scoreboard>
    2. ();
    3. public static HashMap<String, Objective> playerObjectives = new HashMap<String, Objective>();


    Then you need to modify your create Method like this:
    Code:java
    1. public void createScoreboard(Player p) {
    2.  
    3. if (!playerScoreboards.containsKey(p.getName())){
    4.  
    5. manager = Bukkit.getScoreboardManager();
    6.  
    7. board = manager.getNewScoreboard();
    8.  
    9. objective = board.registerNewObjective(p.getName(), "dummy");
    10.  
    11. objective.setDisplaySlot(DisplaySlot.SIDEBAR);
    12.  
    13. objective.setDisplayName(GameMOTD.motdPrefix + ChatColor.GOLD + " Time: " + GameTimer.formattedTime());
    14.  
    15.  
    16.  
    17. Score score = objective.getScore(Bukkit.getOfflinePlayer(ChatColor.GREEN + "Kills:"));
    18.  
    19. score.setScore(0);
    20.  
    21.  
    22.  
    23. plugin.kills.put(p.getName(), 0);
    24.  
    25. killscore.put(p.getName(), score);
    26.  
    27.  
    28.  
    29. Score score2 = objective.getScore(Bukkit.getOfflinePlayer(ChatColor.GREEN + "Alive:"));
    30.  
    31. score2.setScore(plugin.gplayers.size());
    32.  
    33.  
    34.  
    35. alivescore.put(p.getName(), score2);
    36.  
    37.  
    38.  
    39. Score score3 = objective.getScore(Bukkit.getOfflinePlayer(ChatColor.GREEN + "Spectators:"));
    40.  
    41. score3.setScore(plugin.spectators.size());
    42.  
    43. specscore.put(p.getName(), score3);
    44.  
    45. playerScoreboards.put(p.getName(), board);
    46. playerObjectives.put(p.getName(), objective);
    47. }
    48. }


    Then you need to add a new Method called set(Player p)
    Code:java
    1. public static void set(Player p){
    2.  
    3. p.setScoreboard(playerScoreboards.get(p.getName()));
    4.  
    5. }


    on Player Join you need to call first the createScoreboard Method and then the set Method.

    Then you need to modify the UpdateTime Method a little bit. Like this:
    Code:java
    1. public void updateTime(Player p) {
    2. plugin.staskID = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable(){
    3. public void run(){
    4. objective = playerObjectives.get(p.getName());
    5. objective.setDisplayName(GameMOTD.motdPrefix + ChatColor.GOLD + " Time: " + GameTimer.formattedTime());
    6. }
    7. }, 20, 20);
    8. }
     
  28. Offline

    xCyanide

    etaxi341
    It works :), Thanks for your help!
     
  29. Offline

    michael566

    Is there a way for it to check for a player that has ten kills?
     
  30. is there a way to display different "scores for different people?"
    like a villager will see "villager" under everyones name except for a mayor which would have "Mayor" under it and a bandit can see "bandit" under bandits, "villager" under villager and "mayor" under mayors?
     
Thread Status:
Not open for further replies.

Share This Page