Getting Highest int from Config.yml

Discussion in 'Plugin Development' started by HCMatt, Apr 20, 2019.

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

    HCMatt

    I have searched high and low and tried everything I possibly can before posting this. Officially pulling my hair out.

    I am making a leader board plugin that works like this:

    1. Place a Sign
    2. 1st line = lboard
    3. 2nd line = 1 (position on leader board)
    4. Right Click the sign
    5. The plugin then goes into the config to get the person with the highest kills and displays it on the sign.

    Here is what I have so far:
    Code:
    public void createLeaderboardSign(final PlayerInteractEvent e) {
            Player p = e.getPlayer();
            Action a = e.getAction();
    
            if (a == Action.RIGHT_CLICK_BLOCK) {
                Block b = e.getClickedBlock();
                if (b.getType() == Material.SIGN_POST || b.getType() == Material.WALL_SIGN) {
                    Sign s = (Sign) b.getState();
                    if (s.getLine(0).equalsIgnoreCase("lboard")) {
                        if (s.getLine(1).isEmpty()) {
                            p.sendMessage(ChatColor.RED + "You must specify a position for this sign.");
                        } else if (s.getLine(1).equalsIgnoreCase("1")) {
                            if (!p.hasPermission("rev.lboard.createsign")) {
                                p.sendMessage(ChatColor.RED + "You do not have permission to create a Leaderboard Sign.");
                                return;
                            } else {
                                s.setLine(0, ChatColor.GREEN + "[Leaderboard]");
                                s.setLine(1, ChatColor.BLUE + "First Place");
                                s.setLine(2,ChatColor.AQUA + "Highest Kills"); //HIGHEST KILLS
                                s.update();
                                p.sendMessage(ChatColor.GREEN + "You created a sign for Leaderboard Rank: " + ChatColor.AQUA + "#1");
    
                             
                                for (Player online : Bukkit.getOnlinePlayers()) {
                                    for (String playerName : getConfig().getConfigurationSection("Revelation.Stats." + online.getName()).getKeys(false)) {
                                        int maxKills = 0;
                                        int kills = getConfig().getInt("Revelation.Stats." + playerName + ".Kills");
                                        if (kills > maxKills) {
                                            String maxKillsPlayer = "";
                                            maxKills = kills;
                                            maxKillsPlayer = playerName;
                                            p.sendMessage("Most Kills: " + playerName + " with " + maxKills + " kills.");
                                        } else {
                                            p.sendMessage("test");
                                            // I am getting this message every time!
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    My stats are stored like this:

    [​IMG]

    Thanks
     

    Attached Files:

  2. Offline

    Shqep

    Code:Java
    1. String playerName : getConfig().getConfigurationSection("Revelation.Stats." + online.getName()).getKeys(false)


    You're getting the keys at the Configuration section Revelation.Stats. + online.getName(), they'll return the array {DeathStreak, Deaths, Kills}. So playerName will be DeathStreak, Deaths or Kills.
    Therefore, .getInt("Revelation.Stats." + playerName + "Kills") will always return 0 (Since the path doesn't exist), which is always equal to the variable maxKills.

    I hope I made sense.
     
  3. Offline

    HCMatt

    It Sorta made sense, I'm still stuck though xD How do i get it to loop through everyone's kills?

    Thanks
     
  4. Offline

    Shqep

    Remove the online.getName()? For the .getKeys() loop.
     
  5. Offline

    HCMatt

    Okay so I tried this:

    Code:
    for (Player online : Bukkit.getOnlinePlayers()) {
                                    for (String playerName : getConfig().getConfigurationSection("Revelation.Stats.").getKeys(false)) {
                                        int maxKills = 0;
                                        int kills = getConfig().getInt("Revelation.Stats." + playerName + ".Kills");
                                        if (kills > maxKills) {
                                            String maxKillsPlayer = "";
                                            maxKills = kills;
                                            maxKillsPlayer = playerName;
                                            p.sendMessage("Most Kills: " + playerName + " with " + maxKills + " kills.");
                                        } else {
                                            p.sendMessage("test");
                                            // I am getting this message every time!
                                        }
                                    }
                                }
    Which now sends me the "Most Kills: " + playerName + " with " + maxKills + " kills." Message which is a step in the right direction.. However it is sending me the message for everyone.. I set the kills of 'fisherpranks to 11' but got this message: (see attached image)
     

    Attached Files:

  6. Offline

    Shqep

    Because for every playerName,
    you make maxKills 0 again.
     
  7. Offline

    HCMatt

    So what do I do to just figure out the top kills?
     
  8. Offline

    Shqep

    First, this for loop
    Code:Java
    1. for(Player online : Bukkit.getOnlinePlayers()) {}

    is not really necessary when you already stored values in config. Really recommend storing UUIDs instead of Names tho.

    You can just declare the variable maxKills and maxKillsPlayer outside the for loop, if I'm not wrong.
     
  9. Offline

    HCMatt

    Okay so I've removed that for loop.

    Still the same issue with sending me the message for all players though :c
     
  10. Offline

    Shqep

    Can you post the new code?
     
  11. Offline

    HCMatt

    Code:
    for (String playerName : getConfig().getConfigurationSection("Revelation.Stats.").getKeys(false)) {
                                    int maxKills = 0;
                                    int kills = getConfig().getInt("Revelation.Stats." + playerName + ".Kills");
                                    if (kills > maxKills) {
                                        String maxKillsPlayer = "";
                                        maxKills = kills;
                                        maxKillsPlayer = playerName;
                                        p.sendMessage("Most Kills: " + playerName + " with " + maxKills + " kills.");
                                    } else {
                                        p.sendMessage("test");
                                    }
                                }
     
  12. Offline

    Shqep

    I did say to declare variables maxKills and maxKillPlayers outside the for loop right?
    Test the new code after that ^ and tell me the results?
     
  13. Offline

    HCMatt

    The int maxkills = 0;
    and
    maxKillsPlayer = "";

    ??
     
  14. Offline

    Shqep

    Yes, move them outside the for loop and test.
     
  15. Offline

    HCMatt

    Code:
                                int maxKills = 0;
                                String maxKillsPlayer = "";
                               
                                for (String playerName : getConfig().getConfigurationSection("Revelation.Stats.").getKeys(false)) {
                                    int kills = getConfig().getInt("Revelation.Stats." + playerName + ".Kills");
                                    if (kills > maxKills) {
                                        maxKills = kills;
                                        maxKillsPlayer = playerName;
                                        p.sendMessage("Most Kills: " + playerName + " with " + maxKills + " kills.");
                                    } else {
                                        p.sendMessage("test");
                                        // I am getting this message every time!
                                    }
                               
                                
    Still the same issue
     
  16. Offline

    Shqep

    You still have p.sendMessage("blah blah"); in the for loop.
    Move it outside, after the for loop is done.
     
  17. Offline

    HCMatt

    Code:
                                int maxKills = 0;
                                String maxKillsPlayer = "";
                               
                                for (String playerName : getConfig().getConfigurationSection("Revelation.Stats.").getKeys(false)) {
                                    int kills = getConfig().getInt("Revelation.Stats." + playerName + ".Kills");
                                    if (kills > maxKills) {
                                        maxKills = kills;
                                        maxKillsPlayer = playerName;
                                    }
                                    p.sendMessage("Most Kills: " + maxKillsPlayer + " with " + maxKills + " kills.");
                                }
    Tested this, still the same problem .-.
     
  18. Offline

    Shqep

    Code:Java
    1.  
    2. //HCMatt's code
    3. for (String playerName : getConfig().getConfigurationSection("Revelation.Stats.").getKeys(false)) {
    4. int kills = getConfig().getInt("Revelation.Stats." + playerName + ".Kills");
    5. if (kills > maxKills) {
    6. maxKills = kills;
    7. maxKillsPlayer = playerName;
    8. }
    9. p.sendMessage("Most Kills: " + maxKillsPlayer + " with " + maxKills + " kills.");
    10. // Is this still in the for loop? Yes it's still in the for loop
    11. }
    12.  
    13. //Move about here.
    14.  
     
  19. Offline

    HCMatt

    Wait.. it wasnt outside the loop fully!
    It works now!
    Code:
    int maxKills = 0;
                                String maxKillsPlayer = "";
                               
                                for (String playerName : getConfig().getConfigurationSection("Revelation.Stats.").getKeys(false)) {
                                    int kills = getConfig().getInt("Revelation.Stats." + playerName + ".Kills");
                                    if (kills > maxKills) {
                                        maxKills = kills;
                                        maxKillsPlayer = playerName;
                                    }
                                }
                                p.sendMessage("Most Kills: " + maxKillsPlayer + " with " + maxKills + " kills.");
    That makes sense to me now.. I was trying to send the message with the new 'maxKillsPlayer' value before it had finished changing it (outside the loop)... Thanks a lot man!
     
  20. Offline

    Shqep

    So solved? If so, mark this as "solved".

    Glad I could help?
     
  21. Offline

    HCMatt

    Yes, thanks again!
     
  22. Offline

    HCMatt

    Didn't want to create a new thread for this as it would probably get merged anyway...

    Basically Everything I wanted to be able to do for 1st place on the leaderboards works. The only issue is I have no idea how to get 2nd and 3rd place now.. Could anybody please help with this?

    Thanks
     
  23. Offline

    KarimAKL

    @HCMatt Maybe something like this will work?
    Code:Java
    1. // 'kills' is a map where the key is the player UUID and the value is the amount of kills
    2. // 'top' is an integer of how many players you want returned in the array
    3. public UUID[] getTopKills(Map<UUID, Integer> kills, int maxTop) {
    4. List<Entry<UUID, Integer>> entries = new ArrayList<>(kills.entrySet()); // Make list of entries
    5. Collections.sort(entries, new Comparator<Entry<UUID, Integer>>() { // Sort list
    6. public int compare(Entry<UUID, Integer> entry1, Entry<UUID, Integer> entry2) {
    7. return entry1.getValue().compareTo(entry2.getValue());
    8. }
    9. }.reversed()); // Reverse list to get highest first instead of lowest
    10. UUID[] top = new UUID[maxTop]; // Make array with length of 'maxTop'
    11. for (int i = 0; i < maxTop; i++) { // Give values to 'top'
    12. try {
    13. top = entries.get(i).getKey(); // Assign value to top
    14. // Catch 'IndexOutOfBoundsException' in case the map has less entries than 'maxTop'
    15. break; // Break out of the loop in case this happens
    16. }
    17. }
    18. return top; // Return the top players
    19. }

    This is not tested code and it might not work.
    Also, if i'm not mistaken, you could use a TreeMap aswell, pretty sure that's what it's made for.

    Usage of above method:
    Code:Java
    1. Map<UUID, Integer> killsMap = new HashMap<>(); // Map with your players and kills
    2. UUID[] top3 = getTopKills(killsMap, 3);
    3. for (int i = 0; i < top3.length; i++) {
    4. UUID uuid = top3[i];
    5. if (uuid == null) break;
    6. Player player = Bukkit.getPlayer(uuid);
    7. if (player == null) continue;
    8. System.out.println("#"+(i+1)+" "+player.getName());
    9. }[/i]
     
    Last edited by a moderator: May 8, 2019
  24. Offline

    HCMatt

    Okay so I managed to get second place to work. I had to fully change the way it all worked to get there but I did it.

    I still cant get 3rd place to work... Here is what I Have:

    1st Place:
    Code:
                                                    int maxKills1 = 0;
                            int maxKills2 = 0;
                            int maxKills3 = 0;
                           
                            String maxKillsPlayer1 = "";
                            String maxKillsPlayer2 = "";
                            String maxKillsPlayer3 = "";
                           
                            for (String playerName : getConfig().getConfigurationSection("Revelation.Stats.").getKeys(false)) {
                                int kills = getConfig().getInt("Revelation.Stats." + playerName + ".Kills");
                                if (kills > maxKills1) {
                                    maxKills1 = kills;
                                    maxKillsPlayer1 = playerName;
                                }
                                if(kills > 0 && maxKills1 > kills) {
                                    maxKills2 = kills;
                                    maxKillsPlayer2 = playerName;
                                }
                                if(kills > 0 && maxKills2 > kills) {
                                    maxKills3 = kills;
                                    maxKillsPlayer3 = playerName;
                                }
                            }
                            String name1 = maxKillsPlayer1;
                            String killsString1 = String.valueOf(maxKills1);
                           
                            String name2 = maxKillsPlayer2;
                            String killsString2 = String.valueOf(maxKills2);
                           
                            String name3 = maxKillsPlayer3;
                            String killsString3 = String.valueOf(maxKills3);
                           
                           
                            if (s.getLine(1).equalsIgnoreCase("create")) {
                                    s.setLine(0, ChatColor.GREEN + "[Leaderboard]");
                                    s.setLine(1, ChatColor.BLUE + "First Place");
                                    p.sendMessage(ChatColor.GREEN + "You created the Leaderboard Signs");
                                   
    
                                    Location loc2 = new Location (b.getWorld(), b.getX()-1, b.getY()-1, b.getZ());
                                    loc2.getBlock().setType(Material.WALL_SIGN);
                                    Block b2 = loc2.getBlock();
                                    Sign s2 = (Sign) b2.getState();
                                    Location loc3 = new Location (b.getWorld(), b.getX()+1, b.getY()-1, b.getZ());
                                    loc3.getBlock().setType(Material.WALL_SIGN);
                                    Block b3 = loc3.getBlock();
                                    Sign s3 = (Sign) b3.getState();
                                   
                                   
                                    Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
                                        @Override
                                        public void run() {
                                            Bukkit.broadcastMessage(ChatColor.GRAY + "[" + ChatColor.DARK_AQUA + "Leaderboard" + ChatColor.GRAY + "]" + ChatColor.AQUA + " The Leaderboard has been updated!");
                                            s.setLine(2, ChatColor.AQUA + name1);
                                            s.setLine(3, ChatColor.DARK_AQUA + killsString1);
                                            s.update(true);
                                           
                                            s2.setLine(0, ChatColor.GREEN + "[Leaderboard]");
                                            s2.setLine(1, ChatColor.BLUE + "Second Place");
                                            s2.setLine(2, ChatColor.AQUA + name2);
                                            s2.setLine(3, ChatColor.DARK_AQUA + killsString2);
                                            s2.update(true);
                                           
                                            s3.setLine(0, ChatColor.GREEN + "[Leaderboard]");
                                            s3.setLine(1, ChatColor.BLUE + "Third Place");
                                            s3.setLine(2, ChatColor.AQUA + name3);
                                            s3.setLine(3, ChatColor.DARK_AQUA + killsString3);
                                            s3.update(true);
                                           
                                            p.sendMessage("First Place = " + name1 + " with " + killsString1);
                                            p.sendMessage("Second Place = " + name2 + " with " + killsString2);
                                            p.sendMessage("Third Place = " + name3 + " with " + killsString3);
                                            return;
                                        }
                                    }, 20, 200);                           
                            }
                        }
                    }
                }
            }
        }
    1st and 2nd place works perfectly. The sign gets created and 2nd place is displayed on it and updates when its supposed to. 3rd place does not work.. The sign gets created, and the first and second line get set right but it is not picking up the person with the 3rd highest kills or displaying it.

    No errors are showing in the console.

    Could anyone help?

    Thanks

    Mat
     
  25. Offline

    KarimAKL

    @HCMatt Using your code, if i write down some examples of 3 players with 3 different amount of kills, i come up with this:
    Example 1:
    Code:Java
    1. // Kills
    2. Player1: 20
    3. Player2: 10
    4. Player3: 5
    5.  
    6. // Placement
    7. Player1: #1
    8. Player2: #2
    9. Player3: #2

    Example 2:
    Code:Java
    1. // Kills
    2. Player1: 10
    3. Player2: 20
    4. Player3: 5
    5.  
    6. // Placement
    7. Player1: #1
    8. Player2: #1
    9. Player3: #2

    (It's getting late so i'm pretty tired, please let me know if i made a mistake)
    Did you try the code i posted? It should work for what you want. If there's something you don't understand about it you can just ask.
     
  26. Offline

    HCMatt

    I have not tried the code you posted as I have no idea how I would implement it in.

    Thanks
     
  27. Offline

    KarimAKL

  28. Offline

    HCMatt

    Basically, what i am asking is how would I put the code you gave me into my plugin so that it still works with everything thats already there?

    Thanks
     
  29. Offline

    KarimAKL

    @HCMatt I don't know your current code but i would guess something like this:
    Code:Java
    1. UUID[] top = getTopKills(map, 3);
    2. if (sign.getLine(1).equals("1")) {
    3. OfflinePlayer player = Bukkit.getOfflinePlayer(top[0]);
    4. sign.setLine(2, player.getName());
    5. } else if (sign.getLine(1).equals("2")) {
    6. OfflinePlayer player = Bukkit.getOfflinePlayer(top[1]);
    7. sign.setLine(2, player.getName());
    8. }

    I just wrote this quickly, but something along those lines.
     
  30. Offline

    HCMatt

    I was storing stats by name in the config which is why I hadn't been able to test your code.

    I have went through the whole plugin and changed it to use UUID now.

    How would I get the UUID and kills and put it into the map?

    Thanks
     
Thread Status:
Not open for further replies.

Share This Page