Solved Cooldown-Time is not working; Maybe because of the hashmap?

Discussion in 'Plugin Development' started by ServerfromMinecraft, Apr 3, 2013.

Thread Status:
Not open for further replies.
  1. Hi!

    To make a cooldown after x amount of seconds, i use a custom class (Old Methods are included, but useless - Now i've tryed to do it with the sheduler ..)

    My Class:

    Code:
    public class TimeStamp {
     
    private long before, after;
    public TimeStamp(long old, long now){
    before = old; after = now;
    }
     
    public void setOld(long o){
    before = o;
    }
    public void setNew(long n){
    after = n;
    }
    public long getOld(){
    return before;
    }
    public long getNew(){
    return after;
    }
    public void reset(){
    before = 0;after = 0;
    }
    public int calculateDifference(){
    return (int) ((double)((after - before) / 1000000000.0));
    }
     
    private boolean ready = true;
     
    public boolean isReady(){
    return ready;
    }
     
    public void cooldown(JavaPlugin jp, int sec){
    ready = false;
    Bukkit.getScheduler().runTaskLaterAsynchronously(jp, new Runnable(){
    public void run(){
    ready = true;
    }
    }, sec);
    }
     
    }
    
    I use the cooldown & isReady method here:
    Code:
    void repairInv(Player p){
    int max = mc.timeperms.keySet().size();
    int c = 0;
    for(String perm : mc.timeperms.keySet()){
    if(p.hasPermission("RepairAll." + perm)){
    TimeStamp ts = getTS(p);
    if(ts.isReady()){
    reloadTimestamp(p, perm);
    ItemStack[] il = p.getInventory().getContents().clone();
    for(ItemStack is : il){
    if(is != null && is.getTypeId() != 0){
    ItemStack isn = new ItemStack(is.getTypeId(), is.getAmount());
    isn.addEnchantments(is.getEnchantments());
    p.getInventory().remove(is);
    p.getInventory().addItem(isn);
    }
    }
    p.sendMessage("YEAH!");
    break;
    }else{
    p.sendMessage("WAIT!");
    break;
    }
    }
    c++;
    }
    if( c != max - 1 ){
    p.sendMessage("NOPERM!");
    }
    }
     
    TimeStamp getTS(Player p){
    if(mc.pt.containsKey(p.getName())){
    return mc.pt.get(p.getName());
    }else{
    return new TimeStamp(0,0);
    }
    }
    void reloadTimestamp(Player p, String perm){
    TimeStamp ts = new TimeStamp(0,0);
    ts.cooldown(mc, mc.timeperms.get(perm).intValue());
    mc.pt.put(p.getName(), ts);
    }
    But even if i call the right methods, there is no cooldown.. Why?
    And how can i do a cooldown with x seconds with System.milliTime() ? I'm a little bit confused right now...
    Kindly regards,
    -
     
  2. Offline

    MrSparkzz

    Here's a very simple way to add cooldowns

    Step 1 - Make an ArrayList:
    Code:java
    1.  
    2. ArrayList<Player> cooldown =new ArrayList<Player>();
    3.  

    Step 2 - Add player to cooldown:
    Code:java
    1.  
    2. cooldown.add(p);
    3. Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
    4. public void run() {
    5. cooldown.remove(p);
    6. }
    7. }, (100 * 20)); // multiply by 20 because that's the amount of ticks in Minecraft
    8.  

    Step 3 - Get cooldown from config:
    Code:java
    1.  
    2. } (getConfig().getInt("cooldown.time") * 20));
    3.  
     
  3. A Map<String, Integer> is enough for this, no need for delayed tasks or stuff like that.

    You can also easily save the map to config in onDisable().

    Code:
    Integer cooldown = map.get(player.getName());
    int time = (int)(System.currentTimeMilis() / 1000);
    
    if(cooldown == null || cooldown >= (time + 60))
    {
        // do stuff
        map.put(player.getName(), time);
    }
    It would also be better by using a mutable class for storing that value, but you don't need more than one value.

    The posted code is hard to read because of the lack of indentation so I can't offer you advice on that.
     
  4. Offline

    fireblast709

    A even simpler method, free of schedulers and thus saving a bit of CPU:
    Code:
    Map<String, Long> cooldown = new HashMap<String, Long>();
     
    // Constant for the cooldown, 10 seconds
    private final long COOLDOWN = 10000L;
     
    // Player parameter is just a placeholder, 
    // you could use any event where you need a cooldown
    // and you would have a player (for example the PlayerEvents)
    public void letsHeal(Player player)
    {
        // Fetch the planned timestamp from the Map
        Long l = cooldown.get(player.getName());
        
        // If our current time is past that timestamp, we allow
        // the action. We also allow null, as that means he has 
        // never performed the action before
        if(l == null || System.currentTimeMillis() > l.longValue())
        {
            // Now we know he doesn't have a cooldown, so actually do something here
            player.setHealth(player.getHealth() < 15 ? player.getHealth() + 5 : 20);
            
            // Then store the next timestamp in the cooldown Map
            // This means: take the current time, add the cooldown time
            // and we know after what moment in the future he is able to
            // act again.
            //
            // Also, the + COOLDOWN saves some calculations afterwards. A bit of
            // low level optimalization
            cooldown.put(player.getName(), System.currentTimeMillis() + COOLDOWN);
        }
        else
        {
            // Optionally sending a message, including the remaining waiting time in rounded seconds
            player.sendMessage(ChatColor.RED+"Please wait another "+(l.longValue() / 1000)+" seconds before performing this action again");
        }
    }
     
    xxMOxMOxx likes this.
  5. Offline

    Tirelessly

    Here's the least efficient way to add cooldowns - ftfy

    Don't store player objects, you can't say how much time is left, and you're using way more memory than necessary
     
  6. Offline

    MrSparkzz

    Tirelessly
    I was just giving the most simplified way. But yes there are other ways of adding cooldowns. If you want him to use a different way, post some code giving him an example to set him in the right track.
     
  7. Offline

    Tirelessly

  8. Offline

    MrSparkzz

Thread Status:
Not open for further replies.

Share This Page