Solved Cooldown Command Issue

Discussion in 'Plugin Development' started by JBAvodas, Aug 28, 2015.

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

    JBAvodas

    Please understand my JAVA is awful so if you are going to suggest something please give me an example with the code you give for example; Saying use method this and that I won't get it I am a total fool!

    As of right now my cooldown command which I am trying to setup works 90% Until the cooldown is over in which it will not allow me to recast the command?
    This is how it goes :
    /Hunger
    Nom Nom
    /Hunger - You have to wait another 5 seconds to use /hunger again!
    5
    4
    3
    2
    1
    /Hunger - Nothing happens, Command registers in console but nothing happens in game.


    This is my code :
    Code:
    package com.avairu.basic;
    
    import java.util.HashMap;
    
    import org.bukkit.ChatColor;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    
    public class HungerC implements CommandExecutor {
            HashMap<String, Long> hunger = new HashMap<String, Long>();
            @SuppressWarnings("unused")
            private Avairu cooldown;
            public HungerC(Avairu cooldown) {
            this.cooldown = cooldown;
            }
    
            public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
                if(cmd.getName().equalsIgnoreCase("hunger")){
                int cooldown = 5;
                Player s = (Player)sender;
                if(sender instanceof Player){
                   if(args.length > 0){
                       sender.sendMessage(ChatColor.RED + "Too many arguments!");
                       return false;
                   }
                   if (hunger.containsKey(s.getName())) {
                      long diff = (System.currentTimeMillis() - hunger.get(s.getName()))/1000;
                          if (diff < cooldown) {
                               s.sendMessage(ChatColor.RED + "You have to wait another "+(cooldown - diff)+" seconds to use /hunger again!");
                           }
                   } else {
                      s.setFoodLevel(20);
                      s.setSaturation(10);
                      s.sendMessage(ChatColor.RED + "You scoff down a pie you found in your back pocket!");
                      hunger.put(s.getName(), System.currentTimeMillis());
                   }
                }else {
                        System.out.println("You must be a player to use /hunger!");
                        sender.sendMessage(ChatColor.RED + "You must be a player to use /hunger!");
                        return false;
                }
                return true;
                }
                return false;
            }
    }
    
     
    Last edited by a moderator: Aug 28, 2015
  2. Offline

    au2001

    @JBAvodas Maybe your Java is awful, but we can't really read it that way.
    Please put [ code=java ] and [ /code ] tags around it (without spaces of course) and don't forget to indent it.

    EDIT: After trying to read it like this, I found your problem:
    Code:
    if (hunger.containsKey(s.getName())) {
        long diff = (System.currentTimeMillis() - hunger.get(s.getName()))/1000;
        if (diff < cooldown) {
            s.sendMessage(ChatColor.RED + "You have to wait another "+(cooldown - diff)+" seconds to use /hunger again!");
        }
    } else {
        s.setFoodLevel(20);
        s.setSaturation(10);
        s.sendMessage(ChatColor.RED + "You scoff down a pie you found in your back pocket!");
        hunger.put(s.getName(), System.currentTimeMillis());
    }
    Remove the else part, and add one to the "diff < cooldown" if, where you remove the player from the hashmap.
     
  3. Offline

    JBAvodas

    Sorry for the code error, I don't understand this website just yet sorry!

    So what your saying is to make it instead of else change it to

    if (diff < 1) { ???
     
  4. Offline

    au2001

    @JBAvodas No, do it like that:
    Code:
    if (something) {
        if (something_else) {
            // Code here
        } else {
            // Code here
        }
    }
    // Code here
     
  5. Offline

    JBAvodas

    So does this make more sense?
    Code:
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
                if(cmd.getName().equalsIgnoreCase("hunger")){
                int cooldown = 5;
                Player s = (Player)sender;
                long diff = (System.currentTimeMillis() - hunger.get(s.getName()))/1000;
                if(sender instanceof Player){
                    if(args.length > 0){
                        sender.sendMessage(ChatColor.RED + "Too many arguments!");
                        return false;
                    }
                    if (hunger.containsKey(s.getName())) {
                            if (diff < cooldown) {
                                s.sendMessage(ChatColor.RED + "You have to wait another "+(cooldown - diff)+" seconds to use /hunger again!");
                            }else{
                                s.setFoodLevel(20);
                                s.setSaturation(10);
                                s.sendMessage(ChatColor.RED + "You scoff down a pie you found in your back pocket!");
                                hunger.put(s.getName(), System.currentTimeMillis());
                            }
                        }
                    }
                }
                return false;
            }
        }
     
  6. Offline

    stefvanschie

    Maybe you could try this:
    Code:
    HashMap<String, Integer> hunger = new HashMap<String, Integer>();
        
            public HungerC() {}
            public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
                if(cmd.getName().equalsIgnoreCase("hunger")){
                    if (!(sender instanceof Player)) {
                        sender.sendMessage(ChatColor.RED + "You must be a player to use /hunger!");
                        return false;
                    }
                
                    Player s = (Player) sender;
                
                    if (args.length > 0) {
                        s.sendMessage(ChatColor.RED + "Too many arguments!");
                        return false;
                    }
                
                    if (hunger.containsKey(s.getName())) {
                        s.sendMessage(ChatColor.RED + "You have to wait another " + hunger.get(s.getName()) + " seconds to use /hunger again");
                        return false;
                    }
                
                    s.setFoodLevel(20);
                    s.setSaturation(10);
                    s.sendMessage(ChatColor.RED + "You scoff down a pie you found in your back pocket!");
                    hunger.put(s.getName(), 5);
                    return true;
                }
                return false;
            }
    
            @SuppressWarnings("deprecation")
            @Override
            public void run() {
                for (String player : hunger.keySet()) {
                    if (Bukkit.getPlayer(player) != null) {
                        if (hunger.get(player) != 0) {
                            hunger.put(player, hunger.get(player) - 1);
                        } else {
                            hunger.remove(player);
                        }
                    } else {
                        hunger.remove(player);
                    }
                }
            }
    Put
    Code:
    Bukkit.getScheduler().runTaskTimer(this, new HungerC(), 20L, 20L);
    in your main class in your onEnable();
     
  7. Offline

    au2001

    @stefvanschie
    1. Spooonfeeed
    2. Some parts of your code aren't good
      e.g. "public HungerC(){}"
    3. Your method is poorly optimized, the original code is way faster
    4. His code will work fine if he changes what I said.
     
  8. Offline

    stefvanschie

    @au2001
    1. He said he was bad at Java and wanted to show him the code
    2. Because he made it not needed unless he doesn't want to call, forgot to remove.
    3. You think calling System.getCurrentMillis() is better?!
    4. Yes, but still the System.getCurrentMillis() is bothering me.
     
  9. Offline

    au2001

    @stefvanschie Yes, calling System.getCurrentMillis() once in a while is way better than calling a method every second.
     
    xMrPoi and bwfcwalshy like this.
  10. Offline

    stefvanschie

    @au2001 Calling a method once a second, shouldn't be a problem. If it would be he probably couldn't run the plugin. And because he's new to java (and I assume to Bukkit aswell) it's good to learn how schedulers work.
     
  11. Offline

    mrgreen33gamer

    Well I suppose if you're creating a cooldown system using commands, you can extend off of this code I made (tested):

    UPDATED: Should Work

    Code:java
    1.  
    2. package com.mrgreen33gamer.test;
    3.  
    4. import java.util.HashMap;
    5. import java.util.Map;
    6.  
    7. import org.bukkit.ChatColor;
    8. import org.bukkit.command.Command;
    9. import org.bukkit.command.CommandSender;
    10. import org.bukkit.entity.Player;
    11. import org.bukkit.plugin.java.JavaPlugin;
    12. import org.bukkit.scheduler.BukkitRunnable;
    13.  
    14. public class Main extends JavaPlugin {
    15.  
    16. public Main plugin;
    17.  
    18. @Override
    19. public void onEnable(){
    20. plugin = this;
    21. cooldownLoop();
    22. }
    23.  
    24. public HashMap<String, Integer> cooldown = new HashMap<String, Integer>();
    25.  
    26. public void cooldownLoop(){
    27. new BukkitRunnable(){
    28. @Override
    29. public void run() {
    30. if(cooldown.isEmpty()) return;
    31. for (Map.Entry<String, Integer> entry : cooldown.entrySet()) {
    32. String keyValues = entry.getKey();
    33. if(cooldown.get(keyValues) <= 0){
    34. cooldown.remove(keyValues);
    35. }
    36. cooldown.put(keyValues, cooldown.get(keyValues) - 1);
    37. }
    38. }
    39. }.runTaskTimer(this, 0, 20);
    40. }
    41.  
    42. public boolean onCommand(CommandSender sender, Command cmd, String lbl, String[] args){
    43. if(lbl.equalsIgnoreCase("test")){
    44. if(sender instanceof Player){
    45. Player player = (Player) sender;
    46. if(!cooldown.containsKey(player.getName())){
    47. cooldown.put(player.getName(), 10);
    48. player.sendMessage(ChatColor.GREEN + "You've used this command! You're on a 1 minute cooldown!");
    49. }else{
    50. player.sendMessage(ChatColor.RED + "You're on a cooldown of: " + cooldown.get(player.getName()));
    51. }
    52. }
    53. }
    54. return false;
    55. }
    56.  
    57. }
    58.  
    59.  
    60. [syntax][/syntax]
     
    Last edited: Aug 28, 2015
  12. Offline

    au2001

    @mrgreen33gamer Saving a long (unix time) would probably cause less lag and be clearer.
     
  13. Offline

    mrgreen33gamer

    @au2001 As long as HashMaps are not static, it shouldn't make a 1ms difference, and using HashMaps are more efficient then checking for System milliseconds.

    EDIT:

    On top of that, it makes your classes a little more less clustered.
     
  14. Offline

    JBAvodas

    Thanks guys! Got it fixed now just gotta work out this forum and how to change this one to solved xD :p
     
  15. Offline

    au2001

    @mrgreen33gamer "a little more less" that says it all :p
    I wasn't talking about HashMaps (since my method uses one too) but the Runnable.
     
Thread Status:
Not open for further replies.

Share This Page