Solved Reset Delayed Task

Discussion in 'Plugin Development' started by HCMatt, Apr 4, 2020.

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

    HCMatt

    Hi,

    So I am adding Combat Tag into my plugin. So when a player attacks another player, they are both added to an Array List. A Delayed task is then run to remove both players after a set amount of seconds and a message is sent to both to say they are out of combat.

    This aspect of it works fine. However, since this is for a PVP server, a player isn't just going to hit someone once. So at the minute, if the delayed task runs after 5 seconds, and a player keeps hitting a player, they will both get a message every 5 seconds for each hit saying they are out of combat.

    I need a way to, in a way, restart the delayed task so it ignored previous hits and focuses on the last hit.

    Here is my code:

    Code:
       
        @SuppressWarnings("deprecation")
        @EventHandler
        public void onTag(EntityDamageByEntityEvent e) {
    
            Entity damagerEntity = e.getDamager();
            Entity damagedEntity = e.getEntity();
    
            if (damagedEntity instanceof Player) {
                Player p = (Player) e.getEntity();
                if (damagerEntity instanceof Player) {
                    Player dmg = (Player) e.getDamager();
     
                    tagged.add(p);
                    tagged.add(dmg);
    
                    int tag = (int) getConfig().getInt("Tag length from config");
    
                    Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
    
                        @Override
                        public void run() {
                            p.sendMessage(ChatColor.GREEN + "You are no longer in combat.");
                            dmg.sendMessage(ChatColor.GREEN + "You are no longer in combat.");
                            tagged.remove(p);
                            tagged.remove(dmg);
                        }
                    }, 20 * tag);
                }
            }
        }
    

    Thanks in advance,

    Matt.
     
  2. Offline

    Sensevx

    You can just make a global runnable that runs every second to check when was the last time the player hits another player and if 5 seconds have passed, you remove that player.
     
  3. Offline

    HCMatt

    How would I do that?
     
  4. Offline

    Sensevx

    Last edited: Apr 4, 2020
  5. Offline

    HCMatt

    Can you give me a bit more guidance on how I would write it please?
     
  6. Offline

    Sensevx

    @HCMatt

    You already have your runnable. Just run it on server starts and instead of a delayed task, make it a runTaskTimer that runs every second. Make a hashmap with Player as the key or UUID and current time in millesecond as the key.

    Listen to EntityDamageByEntityEvent and put the player or player's uuid as the key and current time as the value.

    Then the runnable should check every second how much time passed since the player in the hashmap has damage another player, if it's greater than 5 seconds, remove the player since they are no longer in combat.


    I know this is not the solution that you want but this what I will do.
     
  7. Offline

    HCMatt


    Okay so..

    so far I have temporarily removed a lot of my code to try this.

    So I have this HashMap:
    Code:
    HashMap<Player, Integer> tagg = new HashMap<Player, Integer>();
    Then in my EntityDamageByEntityEvent I have this:
    Code:
    @EventHandler
        public void onTag(EntityDamageByEntityEvent e) {
    
            Entity damagerEntity = e.getDamager();
            Entity damagedEntity = e.getEntity();
    
            if ((damagedEntity instanceof Player) && damagerEntity instanceof Player) {
                Player p = (Player) e.getEntity();
                Player dmg = (Player) e.getDamager();
               
                Integer time = (int) System.currentTimeMillis();
               
                tagg.put(p, time);
                tagg.put(dmg, time);
            }
    }
    

    So what would I need to put in my onEnable() ?

    Thanks

    Okay, I managed to figure it out.

    For anyone else wondering how this is possible, @Sensevx was right.

    You need a hashmap that contains <Player, Integer>:
    Code:
    HashMap<Player, Integer> tag = new HashMap<Player, Integer>();
    Then in your EntityDamageByEntityEvent you need to put both the damager and the damaged in the hashmap and the time they were both hit:

    Code:
       
    @EventHandler
        public void onTag(EntityDamageByEntityEvent e) {
    
            Entity damagerEntity = e.getDamager();
            Entity damagedEntity = e.getEntity();
    
            if ((damagedEntity instanceof Player) && damagerEntity instanceof Player) {
                Player p = (Player) e.getEntity();
                Player dmg = (Player) e.getDamager();
              
                Integer time = (int) System.currentTimeMillis();
          
              
                tag.put(p, time);
                tag.put(dmg, time);
            }
        }
    
    And in your onEnable() you will need a runnable to check every second that the current time is 5 seconds after the time that they were hit which will be stored in the map:

    Code:
          
    
    for (Player p : Bukkit.getOnlinePlayers()) {
    
                Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
    
                    @Override
                    public void run() {
                        if (tag.containsKey(p)) {
                          
                            Integer tagTime = getConfig().getInt("Revelation.CombatTag"); //This is a custom time that can be changed and stored in the config.
                            Integer taggedSince = tag.get(p).intValue();
                            Integer currentTime = (int) System.currentTimeMillis();
                            if (currentTime > taggedSince + tagTime * 1000) { //For a set time like 5 seconds, replace tagTime with 5. You Multiply by 1000 as it is working in milliseconds.
                                p.sendMessage(ChatColor.GREEN + "You are no longer in combat.");
                                tag.remove(p);
                            }
                        }
                    }
    
                }, 20, 20);
            }
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Apr 5, 2020
Thread Status:
Not open for further replies.

Share This Page