Resource [API] Scoreboard Sidebar API

Discussion in 'Spigot Plugin Development' started by ColoredCarrot, Mar 31, 2016.

?

What should I add next to this API?

Poll closed Apr 2, 2016.
  1. Animated text (might take a while to add)

    9 vote(s)
    60.0%
  2. Storing auto-update data in configs

    2 vote(s)
    13.3%
  3. Team functionality

    4 vote(s)
    26.7%
  1. UPDATE VERSION 2.6: https://www.spigotmc.org/resources/scoreboard-sidebar-api.21042/
    + support for animated text
    + support for PlaceholderAPI

    This thread is not accurate for the new version.

    Hey guys!
    I just wanted to share an API with you that allows for each player to have their own individual scoreboard sidebar.
    It's very easy to use and consists of only one class.

    It's code:
    Code (Text):
    package com.yourname.pluginname.sidebarapi;

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    import org.bukkit.Bukkit;
    import org.bukkit.configuration.serialization.ConfigurationSerializable;
    import org.bukkit.configuration.serialization.ConfigurationSerialization;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.Plugin;
    import org.bukkit.scheduler.BukkitRunnable;
    import org.bukkit.scheduler.BukkitTask;
    import org.bukkit.scoreboard.DisplaySlot;
    import org.bukkit.scoreboard.Objective;
    import org.bukkit.scoreboard.Scoreboard;
    import org.bukkit.scoreboard.ScoreboardManager;

    public class Sidebar
    implements ConfigurationSerializable
    {

        private static transient ScoreboardManager bukkitManager = Bukkit.getScoreboardManager();

        static
        {
            ConfigurationSerialization.registerClass(Sidebar.class);
        }

        private List<String> entries;
        private transient Scoreboard bukkitScoreboard;
        private transient Objective bukkitObjective;
        private transient BukkitTask updateTask;
        private String title;

        public Sidebar(String title, String... entries)
        {
     
            bukkitScoreboard = bukkitManager.getNewScoreboard();
     
            bukkitObjective = bukkitScoreboard.registerNewObjective("obj", "dummy");
     
            this.entries = entries == null || entries.length == 0 ? new ArrayList<String>() : Arrays.asList(entries);
            this.title = title;
     
            update();
     
        }

        public Sidebar(String title, List<String> entries, Plugin plugin, int autoUpdateDelay)
        {
     
            bukkitScoreboard = bukkitManager.getNewScoreboard();
     
            bukkitObjective = bukkitScoreboard.registerNewObjective("obj", "dummy");
     
            this.entries = entries;
            this.title = title;
     
            update();
     
            startAutoUpdating(plugin, autoUpdateDelay);
     
        }

        /**
         * Auto-updating not supported!
         */
        @SuppressWarnings("unchecked")
        public Sidebar(Map<String, Object> map)
        {
     
            bukkitScoreboard = bukkitManager.getNewScoreboard();
     
            bukkitObjective = bukkitScoreboard.registerNewObjective("obj", "dummy");
     
            entries = (List<String>) map.get("entries");
     
            title = (String) map.get("title");
     
            update();
     
        }

        /**
         * Auto-updating not supported!
         */
        @Override
        public Map<String, Object> serialize()
        {
     
            Map<String, Object> map = new HashMap<String, Object>();
     
            map.put("title", title);
            map.put("entries", entries);
     
            return map;
     
        }

        public String getTitle()
        {
            return title;
        }

        public Sidebar setTitle(String title)
        {
            this.title = title;
            return this;
        }

        public List<String> getEntries()
        {
            return entries;
        }

        public Sidebar setEntries(List<String> entries)
        {
            this.entries = entries;
            return this;
        }

        public Sidebar addEntry(String... entries)
        {
            this.entries.addAll(Arrays.asList(entries));
            return this;
        }

        public Sidebar removeEntry(String entry)
        {
            entries.remove(entry);
            return this;
        }

        public Sidebar removeEntry(int num)
        {
            entries.remove(num);
            return this;
        }

        public Sidebar showTo(Player player)
        {
            player.setScoreboard(bukkitScoreboard);
            return this;
        }

        public Sidebar hideFrom(Player player)
        {
            player.setScoreboard(bukkitManager.getMainScoreboard());
            return this;
        }

        public Sidebar update()
        {
     
            redoBukkitObjective();
     
            for (int i = entries.size(); i > 0; i--)
                bukkitObjective.getScore(entries.get(entries.size() - i)).setScore(i);
     
            return this;
     
        }

        public Sidebar startAutoUpdating(Plugin plugin, int delayInTicks)
        {
     
            if (updateTask != null) updateTask.cancel();
     
            updateTask = (new BukkitRunnable()
            {

                @Override
                public void run()
                {
                    update();
                }
         
            }).runTaskTimer(plugin, delayInTicks, delayInTicks);
     
            return this;
     
        }

        public Sidebar stopAutoUpdating()
        {
     
            if (updateTask == null)
                throw new IllegalStateException("Auto-updating is not started!");
     
            updateTask.cancel();
            updateTask = null;
     
            return this;
     
        }

        private void redoBukkitObjective()
        {
     
            bukkitObjective.unregister();
            bukkitObjective = bukkitScoreboard.registerNewObjective("obj", "dummy");
     
            bukkitObjective.setDisplayName(title);
            bukkitObjective.setDisplaySlot(DisplaySlot.SIDEBAR);
     
        }

    }
     

    Although all the methods should be pretty self-explanatory, here's how to use it:
    To create a new Sidebar, use
    Code (Text):
    Sidebar mySidebar = new Sidebar(ChatColor.GREEN + "Sidebar Title", ChatColor.GOLD + "Line 1", " ", ChatColor.BLUE + "That was an " + ChatColor.RED + "empty" + ChatColor.BLUE + " line!");
    Please note that, because of how minecraft handles the scoreboards, you cannot have any lines be exactly the same, so in this case, for another empty line you would use " " (two spaces).

    To add a String to the sidebar, use
    Code (Text):
    mySidebar.addEntry("Another line");
    To remove a String from the sidebar, use one of the following methods:
    Code (Text):
    // Remove the string saying "Another line"
    mySidebar.removeEntry("Another line");

    // Remove the line 3
    mySidebar.removeEntry(3);
    To change the title, use
    Code (Text):
    mySidebar.setTitle("New Title");
    There are also getters for most of the above mentioned variables (such as "getEntries()" or "getTitle()").

    To now actually show the sidebar to a player, use
    Code (Text):
    mySidebar.showTo(player);
    To show the minecraft default sidebar to a player again (the one modified by /scoreboard), use
    Code (Text):
    mySidebar.hideFrom(player);
    And one last thing:
    When you modify the sidebar (by adding or removing lines), you have to use
    Code (Text):
    mySidebar.update();
    or activate auto-updating:
    Auto-updating means that the sidebar will be updated (using "mySidebar.update()") every x game ticks.
    To activate it, use
    Code (Text):
    mySidebar.startAutoUpdating(Plugin plugin, int delayInTicks);
    To stop it, use
    Code (Text):
    mySidebar.stopAutoUpdating();
    Note that this method will throw an IllegalStateException if auto-updating isn't enabled in the first place.

    You can also start auto-updating within the constructor:
    Code (Text):
    mySidebar2 = new Sidebar(String title, List<String> entries, Plugin plugin, int autoUpdateDelay);

    Note that the Sidebar class implements the interface ConfigurationSerializable which means that you can directly store it's data in a config using
    Code (Text):
    myFileConfiguration.set("mySidebar", mySidebar);
    and retrieve the data using
    Code (Text):
    Sidebar mySidebar = (Sidebar) myFileConfiguration.get("mySidebar");
    Note that that feature is not fully tested yet.
    Note also that data concerning auto-updating is not stored this way.

    Please let me know if you find a bug! :D
     
    #1 ColoredCarrot, Mar 31, 2016
    Last edited: Apr 10, 2016
    • Informative Informative x 1
    • Useful Useful x 1
  2. Wow looks good. I'll definitely be using this!
     
  3. Ah, i remember messing with the scoreboard api. I should have used this lol.
     
  4. Cool you like it :D
     
  5. Wonder who has the best Developer on his server.. think i`ve got a good one :)
     
  6. You w0t m8? o_O
     
  7. i meant he`s the developer on his server and i`m his builder :) and i think he´s a good developer.:confused:
     
  8. SidebarAPI.jar/doc/
    and in the source files themselves
     
  9. I asked why you would ever do that.
     
    • Agree Agree x 1
  10. Whoops, I read "where". Well, why would I not?
     
  11. Because it's a plugin? Why would I want html packaged in a plugin for my server? What use is it in the compiled jar?
     
  12. This is not a plugin man! No plugin.yml, no class that extends JavaPlugin. It's intended to be included in your project build path.
     
  13. Why would I want html in my jar?
     
  14. If you don't want it use WinRar or something, but stop complaining.
     
    • Funny Funny x 1
  15. What? Why would you ever put docs in your jar. I'm not just complaining, I'm trying for you to understand that there is no use to people of putting your docs in your jar.
     
  16. Look. You didn't want me to put the docs in the jar. I told you to use WinRar to get them out, if you don't like them. I understand that it doesn't really make sense for a plugin to have the docs in the jar, but I just left them in it. Why do you hate me so much for that?
     

Share This Page