[Util] Game Leaderboards *UPDATED (7/13/14)*

Discussion in 'Resources' started by Squid_Boss, Mar 18, 2014.

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

    Squid_Boss

    Hello everybody! First and foremost I'd like to say that originally this was a tutorial, and now it is more developer friendly *Method to create a leaderboard*.

    So, as always, here is a picture to show this in action:
    Leaderboard (open)
    [​IMG]


    How to use:
    Add this class into your plugin (Click me (pastebin))
    Add this to wherever you want the leaderboard to be updated / created:
    Code:java
    1. new Leaderboard(firstPlaceBlockLocation, secondPlaceBlockLocation, thirdPlaceBlockLocation, firstPlaceBlockType, secondPlaceBlockType, thirdPlaceBlockType, blockFace, configurationFile, configurationStringFormat);


    Here is a little explanation for each parameter:
    1.) firstPlaceBlockLocation: Location of the firstPlaceBlock. In the picture it would be the diamond block beneath Squid_Boss's head.

    2.) secondPlaceBlockLocation: Location of the secondPlaceBlock. In the picture it would be the iron block beneath Notch's head.

    3.) thirdPlaceBlockLocation: Location of the thirdPlaceBlock. In the picture it would be the gold block beneath jeb_'s head.

    4.) firstPlaceBlockType: Material type of the firstPlaceBlock. In the picture, it would be Material.DIAMOND_BLOCK.

    5.) secondPlaceBlockType: Material type of the secondPlaceBlock. In the picture, it would be Material.IRON_BLOCK.

    6.) thirdPlaceBlockType: Material type of the thirdPlaceBlock. In the picture, it would be Material.GOLD_BLOCK.

    7.) blockFace: The direction that the heads and signs are facing. In the picture, it is set to BlockFace.NORTH. ** Only supports NORTH, SOUTH, EAST, and WEST as of now **


    8.) configurationFile: The configuration file that stores the player and the player's points. IE: getConfig();

    9.) configurationStringFormat: This is where it get's interesting. With the string format, you'd set this to however your configurationFile stores players and their points. IE: If your configurationFile stored information like this:
    Code:
    Player: points
    Then you'd set configurationStringFormat to this:
    Code:
    "player"
     
    ** Keep it as 'player' and not a player's name / UUID.
    The code needs to find the word 'player'. **
     
    
    However, if your configurationFile is a bit more complex IE:
    Code:
    Something:
        Something:
            Something:
                  Player:
                      Something:
                            Points:
    Then you'd set configurationStringFormat to this:
    Code:
    "Something.Something.Something.player.Something.integer"
     
    **Again, the code tries to find the words 'player' and 'integer',
    so do not replace them with any values **
     
    
    Also the configurationStringFormat DOES support UUIDs, so if you store a player's UUID in your configurationFile, then it will retrieve the UUID and convert it into that player's current name, and will set the skull and sign accordingly.

    So yeah, I think this is something that a lot of people would like to use, and personally I think it's pretty cool.

    If you have any questions as to how to work it, please put any questions below and I will help as best as I can.
     
  2. Offline

    xTrollxDudex

    Squid_Boss
    I'm surprised no one has replied yet, but this is a really, really well written turorial, it goes step by step, there is code example and screenshots, good voice, and most importantly - a unique topic. I actually was not prepared for something like this, but you really did change my course of thought at the end. Good job, you earned a like for your efforts.

    PS: Those aren't proper javadoc comments!
     
  3. Offline

    Squid_Boss

    xTrollxDudex Thanks! And PS: I don't know what I am doing half of the time! :p
     
  4. Offline

    unenergizer

    Squid_Boss Maybe you should mention about updating scores. Remember to only update about every 5 minutes. The higher the number the longer the wait but the better it is for your server. To do it just put the code that gets the score in a Bukkit Scheduler.

    Hope this helps.
     
  5. Offline

    jordanthehutt

    Squid_Boss I believe the Hive uses a system similar to this in their Survival Games which I find very clever. Although I couldn't see myself using this for a simpler minigame, I could see myself adding it into a Survival Games plugin or a something similar to it. Thanks for writing an amazing resource and I hope you keep writing amazing guides.
     
  6. Offline

    Squid_Boss

    unenergizer When I first came up with it, I originally had it in a task set for 5 minutes, but it ran into an issue with Collections.max() so now I just update it everytime my minigame ends.

    jordanthehutt Thanks, I hope to simplify it and I may have another resource planned soon ;)
     
  7. Offline

    LCastr0

    First of all, awesome tutorial :)
    Now, completly off-topic, aren't you (or weren'r you) a mod on... hypixel idk if I can say the name here... very famous server? :p
     
  8. Offline

    Squid_Boss

    LCastr0 No, I was never a mod, but I was a helper for 6+months.
     
  9. Offline

    LCastr0

    Oh :p You should be developer :3

    #Edit
    A little edit... YOU'RE PREGNANT?! :confused:
     
  10. Offline

    Squid_Boss

    Yea, I am a guy and pregnant. Dat twitter following tho. PS: Let's strafe from the irrelevant off topic stuff. :p
     
    LCastr0 likes this.
  11. Offline

    drtshock

    I love this idea. I have my own implementation of it that I wrote a month ago. You have quite a bit of redundant code and it looks like you get the sign and check the state every time that you update the signs. Why not save the signs and skulls in memory then just access them from there? And check the block break event to see if someone breaks them.

    I do like how you color the signs though with the place. I might have to do that :)
    My example. (open)
    [​IMG]
     
  12. Offline

    Squid_Boss

    drtshock Thanks, and yeah, I hope to revise it and simplify it soon. :)
     
  13. Offline

    Vidsify

    So how would I do it for exp levels?
     
  14. Offline

    bloodless2010

    You could save a lot of resources by using MySQL, if you did a query similar to:

    Code:
    SELECT name,score FROM players ORDER BY score DESC LIMIT 3
    You would get the top 3 players in score :) no need to loop through every player.. Other than that this is a really nice tutorial, keep it up !
     
  15. Offline

    Squid_Boss

    You're going to have to elaborate on what you mean...
    Oh damn...haha I haven't gotten into MySQL yet but boy is it looking more and more attractive now.
     
  16. Offline

    Vidsify

    Sure I'm creating a double exp plugin and I would like to add some sort of leaderboard so that players on the server can see who has the most exp levels. Also if the server owners etc don't want this feature they can disable it though the config.
     
  17. Offline

    Squid_Boss

    Vidsify Store the EXP levels from each player into a config (update accordingly) and then follow my tutorial to get the highest player, second highest, and third highest. Or if you know MySQL, do what bloodless2010 said.
     
  18. Offline

    Vidsify

  19. Offline

    matanrak

    Thanks for all! but when i tried it, it did not work it gave me an eror on keys so i changed the name of some so they wont be the same and it closed the error but THE hvsvpoints GIVES ME PROBLEMS the code dose not know them any help pleas?
    CODE:
    Code:
       
    /**HashMaps
    * Players stores PlayerName and their score from the configuration
    * Leaderboard just keeps the 1st, 2nd, and 3rd place stored and seperated
    */
    HashMap<String, Integer> Players = new HashMap<String, Integer>();
    HashMap<Integer, String> leaderboard = new HashMap<Integer, String>();
     
    /**Locations
    * You WILL have to specify
    */
    Location block1 = new Location(Bukkit.getWorld("map1"), 1133.5, 22, -568.5);
    Location block2 = new Location(Bukkit.getWorld("map1"), 1133.5, 22, -569.5);
    Location block3 = new Location(Bukkit.getWorld("map1"), 1133.5, 22, -570.5);
     
    Location leaderhead1 = new Location(Bukkit.getWorld("map1"), 1133.5, 23, -568.5);
    Location leaderhead2 = new Location(Bukkit.getWorld("map1"), 1133.5, 23, -569.5);
    Location leaderhead3 = new Location(Bukkit.getWorld("map1"), 1133.5, 23, -570.5);
     
    Location sign1 = new Location(Bukkit.getWorld("map1"), 1134.5, 22, -568.5);
    Location sign2 = new Location(Bukkit.getWorld("map1"), 1134.5, 22, -569.5);
    Location sign3 = new Location(Bukkit.getWorld("map1"), 1134.5, 22, -570.5);
     
    /**Blocks
    * Be careful when editing
    */
     
    block1.getBlock().setType(Material.ENDER_PORTAL_FRAME);
    block2.getBlock().setType(Material.ENDER_PORTAL_FRAME);
    block3.getBlock().setType(Material.ENCHANTMENT_TABLE);
     
    leaderhead1.getBlock().setType(Material.SKULL);
    leaderhead2.getBlock().setType(Material.SKULL);
    leaderhead3.getBlock().setType(Material.SKULL);
     
    sign1.getBlock().setType(Material.WALL_SIGN);
    sign2.getBlock().setType(Material.WALL_SIGN);
    sign3.getBlock().setType(Material.WALL_SIGN);
     
    /**BlockStates
    * Don't touch
    */
    BlockState state1 = leaderhead1.getBlock().getState();
    BlockState state2 = leaderhead2.getBlock().getState();
    BlockState state3 = leaderhead3.getBlock().getState();
     
    BlockState signstate1 = sign1.getBlock().getState();
    BlockState signstate2 = sign2.getBlock().getState();
    BlockState signstate3 = sign3.getBlock().getState();
     
    /**Setting the HashMaps
    * Loops through configuration and puts the player's name as keys, and their score as the int of the keys
    */
    for (String keys : hvsvpoints.getConfig().getKeys(false)) {
    Players.put(keys, hvsvpoints.getConfig().getInt(keys));
    }
     
    //This gets the FIRST leader, by using Collections.max() and sets the player as the first leader *leaderboard.put(1, keys);*
    int leader1 = Collections.max(Players.values());
    for (String keys1 : Players.keySet()) {
    if (Players.get(keys1) == leader1) {
    leaderboard.put(1, keys1);
    }
    }
    //Afterwards, we remove the highest player so the next time we do this, it would technically be the second highest player.
    Players.remove(leaderboard.get(1));
     
    //Gets the second leader, because the first leader isn't in the HashMap anymore and sets the player as the second leader *leaderboard.put(2, keys);*
    int leader2 = Collections.max(Players.values());
    for (String keys2 : Players.keySet()) {
    if (Players.get(keys2) == leader2) {
    leaderboard.put(2, keys2);
    }
    }
    //Removes again
    Players.remove(leaderboard.get(2));
     
    //Finally we get the third leader and set the player as the third leader *leaderboard.put(3, keys);*
    int leader3 = Collections.max(Players.values());
    for (String keys3 : Players.keySet()) {
    if (Players.get(keys3) == leader3) {
    leaderboard.put(3, keys3);
    }
    }
     
    /**Skulls
    * Updates the skulls of the first, second, and third leaders
    */
    if (state1 instanceof Skull) {
    Skull s = (Skull) state1;
    s.setSkullType(SkullType.PLAYER);
    s.setRawData((byte) 1);
    s.setRotation(BlockFace.EAST); //Will probably have to edit this to your liking
    s.setOwner(leaderboard.get(1)); //Sets the owner to the first leader
    leaderhead1.getBlock().getChunk().load();
    s.update(true);
    }
    if (state2 instanceof Skull) {
    Skull s = (Skull) state2;
    s.setSkullType(SkullType.PLAYER);
    s.setRawData((byte) 1);
    s.setRotation(BlockFace.EAST); //Will probably have to edit this to your liking
    s.setOwner(leaderboard.get(2)); //Sets the owner to the second leader
    leaderhead2.getBlock().getChunk().load();
    s.update(true);
    }
    if (state3 instanceof Skull) {
    Skull s = (Skull) state3;
    s.setSkullType(SkullType.PLAYER);
    s.setRawData((byte) 1);
    s.setRotation(BlockFace.EAST); //Will probably have to edit this to your liking
    s.setOwner(leaderboard.get(3)); //Sets the owner to the third leader
    leaderhead3.getBlock().getChunk().load();
    s.update(true);
    }
     
    /**Signs
    * Updates the signs with the correct information for the first, second, and third leaders
    * RawData sets rotation so North=2, South=3, East=5, West=4
    */
    if (signstate1 instanceof Sign) {
    Sign s = (Sign) signstate1;
    s.setRawData((byte) 5);
    s.setLine(0, ChatColor.AQUA + "" + ChatColor.BOLD + "1st");
    s.setLine(1, leaderboard.get(1));
    s.setLine(2, hvsvpoints.getConfig().getInt(leaderboard.get(1)) + " Points");
    s.update(true);
    }
    if (signstate2 instanceof Sign) {
    Sign s = (Sign) signstate2;
    s.setRawData((byte) 5);
    s.setLine(0, ChatColor.YELLOW + "" + ChatColor.BOLD + "2nd");
    s.setLine(1, leaderboard.get(2));
    s.setLine(2, hvsvpoints.getConfig().getInt(leaderboard.get(2)) + " Points");
    sign2.getBlock().getChunk().load();
    s.update(true);
    }
    if (signstate3 instanceof Sign) {
    Sign s = (Sign) signstate3;
    s.setRawData((byte) 5);
    s.setLine(0, ChatColor.DARK_RED + "" + ChatColor.BOLD + "3rd");
    s.setLine(1, leaderboard.get(3));
    s.setLine(2, hvsvpoints.getConfig().getInt(leaderboard.get(3)) + " Points");
    s.update(true);
    }
     
    //And finally we clear it all up at the end, just to be safe
    Players.clear();
    leaderboard.clear();
     
           
        }
     
  20. Offline

    Squid_Boss

    matanrak
    The "hvsvpoints" is a configuration file. You're supposed to replace the configuration file with your OWN configuration file. And this code was not meant to be copy and pasted, it's a TUTORIAL, and in the TUTORIAL I used my own ways of getting information (hvsvpoints). It's not really about helping you fix the code because the code is fine. Reread the tutorial, understand it. If you don't understand the TUTORIAL, I can help you, but I can't really help you if you just copy and paste the code.

    Anyways, this tutorial is...outdated and I hope to redo it soon.
     
  21. Offline

    matanrak

    ok i am sorry i am a noob XD, so my config file is config.yml so should i just put config there? And i will start to try to understand this! i did read all you wrote

    Ok i fixed that problem but it still wont work, any ideas?

    Please any ideas why it wont work?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 7, 2016
  22. Offline

    HeavyMine13

    Its outdated right? I can help do it!
     
  23. Offline

    matanrak

  24. Offline

    HeavyMine13

    matanrak
    It is look V
     
  25. Offline

    matanrak

    Any ideas why it still won't work?
    I changed:
    Code:
    s.setLine(2, hvsvpoints.getConfig().getInt(leaderboard.get(3)) + " Points");
    Into This:
    Code:
    s.setLine(2, getConfig().getInt(leaderboard.get(3)) + " Points");
     
  26. Offline

    HeavyMine13

    are you sure there is no console errors? If yes, please post it or PM me!
     
  27. Offline

    Squid_Boss

    matanrak
    The tutorial is built around the configuration file being set up a certain way, formatted like so:
    Code:
    PlayerName: int
     
    Ex.
    Squid_Boss: 2260
    If your configuration file isn't set up like that, you either have to change how your configuration file is set up, or change the "getInt(leaderboard.get(3)) + " Points");" to however the configuration file you have is set up.

    So, if your configuration file was set up like this:
    Code:
    random:
        Squid_Boss: 2260
    You'd make the getInt into this:
    Code:
    getInt("random." + leaderboard.get(3)) + " Points");
     
  28. Offline

    maved145

    Squid_Boss
    I get this error:
    Caused by: java.util.NoSuchElementException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:796) ~[?:1.6.0_65]
    at java.util.HashMap$ValueIterator.next(HashMap.java:822) ~[?:1.6.0_65]
    at java.util.Collections.max(Collections.java:638) ~[?:1.6.0_65]
    at me.Maved145.TopKillsScoreboard.main.onPlayerDeath(main.java:85) ~[?:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.6.0_65]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[?:1.6.0_65]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[?:1.6.0_65]
    at java.lang.reflect.Method.invoke(Method.java:597) ~[?:1.6.0_65]
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:292) ~[spigot.jar:git-Spigot-1487]

    ... 20 more
     
  29. Offline

    Squid_Boss

    maved145
    Is the code inside a task? Because I've personally experienced errors in tasks only.

    If it's not in a task, can you post line 85 of "main"?
     
  30. Offline

    maved145

    Squid_Boss
    Its on a PlayerDeathEvent.
    int leader3 = Collections.max(Players.values());
     
Thread Status:
Not open for further replies.

Share This Page