Cancelling an event when a player dies

Discussion in 'Plugin Development' started by caledonian26, Feb 27, 2023.

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

    caledonian26

    Hey all,

    I have the following code.

    This will kill a player once 3900 ticks have passed.

    However, if the player dies before this point, I want to cancel this task. The code below somehow does not seem to work, despite me adding 'if(!event.getPlayer().isOnline())'.

    Would be so grateful for a helping hand!

    Code:
    final BukkitRunnable Br = new BukkitRunnable() {
              int count = 0;
    
              public void run() {
                if(!event.getPlayer().isOnline()) {
                      this.cancel();
                  }
                if (count == 0) cancel();
                event.getPlayer().setHealth(0);   
                count++;
              }
            };
          Br.runTaskTimer(this, 3900, 3900);
     
  2. Offline

    mehboss

    I would suggest utilizing an ArrayList to check to see if a player has died before the timer ends.
     
  3. Offline

    caledonian26

    Thank you so much for the suggestion, I have tried something like this, but it still doesn't work:

    Code:
    public void run() {
              Player thePlayer = event.getPlayer();
               
              @EventHandler
              public void onQuit(final PlayerQuitEvent event) {
                  if (event.getPlayer() == thePlayer) {
                      this.cancel();
                  }
              }
     
  4. Offline

    Strahan

    A dead player is still online. The appropriate thing to use is isDead()

    PS to clarify: I'd still leave the online check, because cancel is also desirable if they log off.
     
  5. Offline

    mehboss

    Efficient if the player hasn't respawned. I guess we need clarification on if the task should be cancelled if the player has died and then respawned before the timer executes (meaning they are once again alive) :)
     
  6. Offline

    caledonian26

    Yes, if the player has died and then respawned before the timer executes, the task should still be cancelled :)
     
  7. Offline

    mehboss

    Utilize an ArrayList. Found here: https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html
    • Create ArrayList
    • Add Player to ArrayList
    • PlayerDeathEvent will remove the player from the list if they are in it & they die (you can also remove them from the list if they logoff [PlayerQuitEvent] to kill two birds with one stone)
    • The timer will check if the player is still in the ArrayList. If they are not, the timer will cancel itself.
    I can try to give you more information if you still need help, but I would prefer not to spoonfeed! :) There are also tons of information on other existing forums that can help guide you in the correct direction.
     
  8. Offline

    caledonian26

    Thank you so much for all your help, and to those above! I have come up with my own solution that does not involve arrays. This ensures that the first bukkit runnable() 'br1' is cancelled if the player dies :))

    Code:
    final BukkitRunnable Br1 = new BukkitRunnable() {
            int count = 0;
            Material[] listofitems = {Material.SPONGE, Material.COBWEB, Material.CAKE, Material.RED_WOOL};
    
            public void run() {
              if(!event.getPlayer().isOnline()) {
                    this.cancel();
                }
              if(event.getPlayer().isDead()) {
                    this.cancel();
                }
              if (count == listofitems.length-1) cancel();
              Material nextItem = listofitems[count];
              ItemStack item = new ItemStack(nextItem);
              event.getPlayer().getInventory().addItem(item);    
              count++;
            }
          };
          Br1.runTaskTimer(this, 0, 900);
         
          new BukkitRunnable() {
    
              public void run() {
                if(!event.getPlayer().isOnline()) {
                      this.cancel();
                  }
                if(event.getPlayer().isDead()) {
                      this.cancel();
                  }
                event.getPlayer().setHealth(0);    
              }
            }.runTaskLater(this, 3900);
         
          new BukkitRunnable() {
    
              public void run() {
                if(!event.getPlayer().isOnline()) {
                      Br1.cancel();
                  }
                if(event.getPlayer().isDead()) {
                      Br1.cancel();
                  }
              }
            }.runTaskTimer(this,0,1);
     
  9. Offline

    mehboss

    Depending on the event, doing it this way can put a heavy load on your server CPU and cause lag if there becomes enough players due to the timer being a tick each time. But it is your choice.
     
    Strahan likes this.
  10. Offline

    Strahan

    Yea, I try to avoid using runnables unless it's absolutely necessary. No sense adding load to the server. Yea, it's likely negligible, but it can add up quick when it's tied to an uncertain factor like players.
     
Thread Status:
Not open for further replies.

Share This Page