Potion fade event

Discussion in 'Plugin Development' started by Cjreek, Sep 23, 2012.

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

    Cjreek

    Hi,

    Is there an event thrown when a potion effect fades from a player?
    I need to know when potion effects end on some players.
     
  2. Offline

    Comphenix

    You can get a list of the player's active potion effects and their duration by calling getActivePotionEffects(). But you shouldn't call that too often, especially if you need this event for every player on the server.

    What you could do, is maintain a PriorityQueue of current effects and affected player, ordered by the time they will run out (by using System.currentTimeMillis(), for instance). Then you just have to make sure to update this list whenever players are hit by splash potions (PotionSplashEvent) or drink potions (PlayerInteractEvent - look for item actions on glass bottles).

    Add a regular check of this PriorityQueue in a synchronized task, and you should be good to go.
     
    MCForger likes this.
  3. Offline

    Waffletastic

    Or, instead of updating it and having to find every possible time a player gains a potion, and having tons of schedulers: just have a hashset for players with a potion effect, and a single scheduler set at like 1 second. Then in that scheduler loop through the players and if they have the potion effect: add them to the hashset. Also in the scheduler, check if the player is in the hashset, but has no potion effect on them. If that is true: they have lost their potion effect. It gets rid of a lot of variables that way. The only downside is that if you want to do this for different potion effects, you will need multiple hashsets. Sorry I can't paste an example of the code, because I'm stuck to my iPad at the moment, but hopefully you get the idea. :)
     
  4. Offline

    Cjreek

    Yes, that's what I found out, too. Thanks nonetheless :)
    I needed to renew potion effects when they run out. But I simply set the duration of the effect to Integer.MAX_VALUE. This works fine for me.
     
  5. Offline

    Comphenix

    Sure, that will work, but it does require looping through every online player (certain servers can have close to 100 players), essentially recreating the of active potion effects for every player every second. Just take a look at the CraftBukkit source code and see for yourself.

    Now, is this really so bad as to warrant a more complex (but efficient) solution such as the one I suggested? I don't know - you would have to benchmark it to be sure. It may not be that noticeable even for large servers, but every wasted cycle and wasted object creation adds up. Especially if you always choose the easy solution over the efficient one.

    Also, I didn't really mean to use multiple schedulers. Here's a pseudocode of my solution:
    Code:
    class entry:
      long expireTime,
      PotionEffect effect,
      Player affectedPlayer;
      ordered by expire time
     
    PriorityQueue<entry> entries;
     
    on a splash potion event:
      for every affected player:
          add a new entry to the priority queue.
          expireTime = current time + duration
          remember to remove any previous potion effects of this type.
     
    on player interact event:
      if the previous interact event of the same slot was on a potion bottle,
      see if it is now a glass bottle. if so, the player has just consumed a potion:
        add a new entry like above, using the previous interaction event's potion bottle
     
    for every N ticks:
      see if the current head of the PriorityQueue has expired. if so, pull it and invoke
      a faded potion event, and repeat the check.
    
    Of course, you don't have to deduce the potion effect in the player interact event. You could do something like you suggested, and compare the current potion effect list with what you've recorded previously, but here in those events for each affected player, instead of every second in a scheduled event.

    EDIT: Ah, I suspected you just wanted to keep a potion effect running for longer than normal ... Oh well. I suppose this method is overkill then. At least for your purpose, but it may still be useful.
     
  6. Offline

    Waffletastic

    Oh and about what I said earlier, the only event you should have to deal with is a player quit event. Make sure to remove a player from the hashset when they log out, we don't want artifacts. :)
     
Thread Status:
Not open for further replies.

Share This Page