I am trying to cancel tasks when player dies

Discussion in 'Spigot Plugin Development' started by Alexalien, Jun 2, 2016.

  1. when one player dies the effects stops for all other players instead of just the player that died

    Main Class
    Code (Text):
    package me.alexalien;


    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.UUID;

    import org.bukkit.Bukkit;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.java.JavaPlugin;
    import org.bukkit.potion.PotionEffect;
    import org.bukkit.potion.PotionEffectType;
    import org.bukkit.scheduler.BukkitRunnable;
    import org.bukkit.scheduler.BukkitTask;

    import net.md_5.bungee.api.ChatColor;

    public class Flox extends JavaPlugin {
     
        public static Map<UUID, List<BukkitRunnable>> tasks = new HashMap<>();
     
        public static List<BukkitRunnable> task = new ArrayList<BukkitRunnable>();
     
     
        public static void infected(final Player player) {
         
            if (!tasks.containsKey(player.getUniqueId())) {
                  tasks.put(player.getUniqueId(), new ArrayList<BukkitRunnable>());
                }
         
            if(!(Disease.Infected.contains(player))) {
                Disease.Infected.add(player);
         
            player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_DIGGING,Integer.MAX_VALUE, 0));
            player.sendMessage(ChatColor.RED + "You have been infected");
         


            BukkitRunnable t1 = new BukkitRunnable() {

                public void run() {
                    player.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION,Integer.MAX_VALUE, 0));
                }
             
            };
            t1.runTaskLater(plugin, 60*20);
         
         
            task.add(t1);
         
            tasks.put(player.getUniqueId(), task);
         
            BukkitRunnable t2 = new BukkitRunnable() {

                public void run() {
                    player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,Integer.MAX_VALUE, 0));
                }
             
            };
            t2.runTaskLater(plugin, 110*20);
         
         
            task.add(t2);
         
            tasks.put(player.getUniqueId(), task);
         
            BukkitRunnable t3 = new BukkitRunnable() {

                public void run() {
                    player.addPotionEffect(new PotionEffect(PotionEffectType.POISON,Integer.MAX_VALUE, 4));
                    player.addPotionEffect(new PotionEffect(PotionEffectType.WITHER,Integer.MAX_VALUE, 4));
                 
                }
             
            };
            t3.runTaskLater(plugin, 290*20);
         

         
            task.add(t3);
         
            tasks.put(player.getUniqueId(), task);
         
         
            }
         
         
             
    }
     
     
     
     
     
     
        public static Flox plugin;
     
        public Flox() {
        plugin = this;
    }
     
        Disease logger;
     
     
        //When plugin is First Enabled
        @Override
        public void onEnable() {
            new Disease(this);
            getLogger().info("Enabled");
        }
        //When plugin is Disabled
        @Override
        public void onDisable() {
     
        }

     
     
     
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
         

             
         
         
            return false;

        }

     
    }
     


    Listener
    Code (Text):
    package me.alexalien;


    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.Timer;
    import java.util.TimerTask;

    import org.bukkit.Bukkit;
    import org.bukkit.Color;
    import org.bukkit.FireworkEffect;
    import org.bukkit.FireworkEffect.Type;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.EntityType;
    import org.bukkit.entity.Firework;
    import org.bukkit.entity.Item;
    import org.bukkit.entity.LivingEntity;
    import org.bukkit.entity.Player;
    import org.bukkit.entity.Snowball;
    import org.bukkit.entity.Zombie;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.EntityDamageByEntityEvent;
    import org.bukkit.event.entity.PlayerDeathEvent;
    import org.bukkit.event.player.PlayerItemConsumeEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerPickupItemEvent;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.FireworkMeta;
    import org.bukkit.potion.PotionEffect;
    import org.bukkit.potion.PotionEffectType;
    import org.bukkit.scheduler.BukkitRunnable;

    import com.avaje.ebean.RawSql;

    import net.md_5.bungee.api.ChatColor;



    public class Disease implements Listener{
     
        public static List<Player> Infected = new ArrayList<Player>();
     
     
     
        Flox flox;

        public Disease(Flox plugin) {
            plugin.getServer().getPluginManager().registerEvents(this, plugin);
        }
     
        @EventHandler
        public void onPlayerJoinEvent(PlayerJoinEvent event) {
            event.getPlayer().sendMessage(ChatColor.BLUE + "Flox is powered by Alexalien");
         
          }
       
        @EventHandler
        public void PlayerEatOrDrink(PlayerItemConsumeEvent e) {
            Player player = e.getPlayer();
            if(e.getItem().getType().equals(Material.POTION)) {
             
                Random rand = new Random();

                int  n = rand.nextInt(20) + 1;
             
                if(n == 20 ) {
                 
                    Flox.infected(player);
                }
             
             
            } else if(e.getItem().getType().equals(Material.ROTTEN_FLESH)) {
             
                Random rand = new Random();
             
                int n = rand.nextInt(5) + 1;
             
                if(n <= 4) {
                 
                    Flox.infected(player);
                }
             
             
            } else if(e.getItem().getType() == Material.RAW_BEEF | e.getItem().getType() == Material.RAW_CHICKEN | e.getItem().getType() == Material.RAW_FISH) {
             
                Random rand = new Random();
             
                int n = rand.nextInt(2) + 1;
             
                if(n == 1) {
                 
                    Flox.infected(player);
                }
            }
         
        }
        @EventHandler
        public void PlayerhitEvent(EntityDamageByEntityEvent e) {
            if (e.getDamager() instanceof LivingEntity && e.getDamager().equals(EntityType.ZOMBIE)) {
                Entity Hit = e.getEntity();
             
                if (Hit instanceof Player) {
                    Player player = (Player) Hit;
                    Random rand = new Random();

                    int  n = rand.nextInt(20) + 1;
                 
                    if(n == 20 ) {
                     

                     
                        Flox.infected(player);
                    }
                 
                 
                }
            }
         
        }
     
        @EventHandler
        public void Dead(PlayerDeathEvent e) {
            Player player = e.getEntity();
            Infected.remove(player);
            if (Flox.tasks.containsKey(player.getUniqueId())) {
                  for(BukkitRunnable b : Flox.tasks.get(player.getUniqueId())) {
                   
                   
                      b.cancel();
         
                  }
            }
        }
    }
     
     
  2. Why not just have a single repeating task that runs forever. This task should simply check a Set containing infected players and do whatever you want to them. Then you can simply add/remove infected players to/from that Set without any regard to the task. Much simpler solution, imo.
     
    • Agree Agree x 2
  3. We tried to use a while loop, but it crashed the server we tested it on.
     
  4. Choco

    Moderator

    That would be because your while loop is running on the main thread. Assuming you did while(true), that would prevent anything from running outside of the loop until you broke it. That's basic Java :p

    He meant use a singular BukkitRunnable rather than multiple BukkitRunnables
     
  5. Im not sure how that would work, could you elaborate.
     
  6. Code (Text):

    public class MyPlugin extends JavaPlugin {
        private Set<Player> infected = new HashSet<>();
        private BukkitRunnable task;

        @Override
        public void onEnable() {
            getServer().getPluginManager().registerEvents(this, this);

            task = new BukkitRunnable() {
                @Override
                public void run() {
                    Iterator iterator = infected.iterator();
                    while(iterator.hasNext()) {
                        Player player = iterator.next();

                        if (player == null || !player.isOnline()) {
                            iterator.remove();  // cleanup, just in case
                            return;
                        }

                        // do something to infected player here
                    }
                }
            }.runTaskTimer(this, 20L);
        }

        @Override
        public void onDisable() {
            if (task != null) {
                task.cancel();
            }
        }

        @EventHandler
        public void onQuit(PlayerQuitEvent event) {
            // this one is important so you dont get memory leaks and/or NPEs
            infected.remove(event.getPlayer());
        }

        @EventHandler
        public void onDeath(PlayerDeathEvent event) {
            infected.remove(event.getPlayer());
        }

        @EventHandler
        public void PlayerEatOrDrink(PlayerItemConsumeEvent event) {
            infected.add(event.getPlayer());
        }
    }
     
    etc etc.
     
    #6 BillyGalbreath, Jun 2, 2016
    Last edited: Jun 2, 2016
  7. But my aim is to give the player potion effects at different times, so would it be possiblle to put my existing code for giving the player poition effects inside your bukkitRunnable.
     
  8. Code (Text):
     public static Map<UUID, List<BukkitRunnable>> tasks = new HashMap<>();
    ...

    for(BukkitRunnable b : Flox.tasks.get(player.getUniqueId()))
                      b.cancel();
    You're getting a list of BukkitRunnables and then canceling the list instead of the single runnable?
     
    • Like Like x 1
  9. How can i fix this please, thank you, i can see that now.
     
  10. Instead of storing a list in your map just store the Runnable per uuid. That should work
     
  11. Im not certain how you would do that to be honest hash maps are not my strength.
     
  12. The way HashMaps work is that they store an object that's related to a specific key. In this case your UUID is the key while the Runnable is the value. So you would declare your map something like:
    Code (Text):
    Map<String, BukkitRunnable> thisIsMyHashMap = new HashMap<String, BukkitRunnable>();
    And then insert the values (however you plan on inserting them, via event listener or whatever) like:
    Code (Text):
    thisIsMyHashMap.put(playerUUIDString, whateverRunnableGoesHere);
     

  13. I did that but the death event now dosnt work
    Code (Text):
        @EventHandler
        public void Dead(PlayerDeathEvent e) {
            Player player = e.getEntity();
            Infected.remove(player);
            if (Flox.tasks.containsKey(player.getUniqueId())) {
                  for(BukkitRunnable b : Flox.tasks.get(player.getUniqueId())) {
                     
                      b.cancel();
           
                  }
            }
        }

    on the for loop i get the error
    Code (Text):
    Can only iterate over an array or an instance of java.lang.Iterable
     
  14. Looping is pointless in this case, since a HashMap has unique keys.

    Just use
    Code (Text):
    Flox.tasks.get(player.getUniqueId()).cancel();
     
  15. Will it cancel all the tasks with that id?
     
  16. Like I said, the keys in a HashMap are unique. If you put another BukkitTask in with the same UUID it will overwrite the old one. If you want to store multiple tasks you can use a HashMap<UUID, List<BukkitRunnable>>
     
  17. But then how do i add them to the list?
     
  18. Something like this:
    Code (Text):
    private static HashMap<UUID, List<BukkitRunnable>> timers = new HashMap<UUID, List<BukkitRunnable>>();

    public static void add(UUID uuid, BukkitRunnable runnable){
        List<BukkitRunnable> runnables;
        if (timers.containsKey(uuid)){
            runnables = timers.get(uuid);
        } else {
            runnables = new ArrayList<BukkitRunnable>();
        }
        runnables.add(runnable);
        timers.put(uuid, runnables);
    }

    public static void cancel(UUID uuid){
        for (BukkitRunnable runnable : timers.get(uuid)){
            runnable.cancel();
        }
    }
    Untested, but it should work.
     
    #18 Mrten, Jun 3, 2016
    Last edited: Jun 3, 2016
  19. JamesJ

    Supporter

    Map#put(id, List<Task>)....?
     
  20. i tried tasks.put(player.getUniqueId(), List<t2>); i get this error tasks.put(player.getUniqueId(), List<t2>);

    t2 = BukkitRunnable