Unregistering events

Discussion in 'Plugin Development' started by Bone008, Jun 15, 2011.

Thread Status:
Not open for further replies.
  1. Is there a way to unregister events in bukkit?
    I think it would be a great improvement to performance if you could only have your listeners registered when you actually need them. When you have a plugin that somewhere needs to listen to the PLAYER_MOVE-event, which is called incredibly often as you know, it would be handy to be able to only register it when you need it (same for block break and place etc.).
    Let's say you have a command-based plugin and only if someone enters a specific command his movements will be watched and charted until he has finished his task.

    Wouldn't it improve the performance if the listener to PLAYER_MOVE could be registered only when a player is tracked and unregistered afterwards?
    Of course you should always cancel your function if the event isn't what you need (like the wrong player etc.) but when you have a ton of plugins that all passively listen to PLAYER_MOVE without actually doing anything (until they get activated) it isn't really that great imo ...

    There doesn't seem to be a way in the API to unregister an event (there is only PluginManager.registerEvent) and probably every plugin registers their events in the onEnable-method.

    Can you manually do anything about this?
     
  2. Offline

    zonedabone

    If you want functionality like that, the best way to implement it would be to check if the vent should be enabled on the first line, and return otherwise. Because of the way bukkit is programmed, it would probably take FEWER resources to do this than to rely on a system to unregister events, especially if you're turning them on and off a lot.
     
  3. The thought is that the handler wouldn't even be called if not necessary. The way it's implemented now is that you always have to check wether to return or not in every registered handler.

    Seriously, is it heavier to delete a handler from a list once or to call it a thousands of times per second, comparing stuff and returning again?
     
  4. Offline

    nisovin

    I think this is a good idea, if only because of the player move event. Unfortunately, Bukkit currently doesn't have anything like this. I suppose you could attempt to access the PluginManager fields directly to do this, but it wouldn't really be ideal. The best thing right now is to just return from the listener method as quickly as possible and submit a feature request to leaky.bukkit.org.
     
  5. Offline

    Borch

    THIS
     
  6. Offline

    krisrok

    i don't know if i missed something, but i had the same problem (meanwhile craftbukkit 1.1 and a new event system(!)) and wrote this helper class. maybe someone else can make some use of this. it uses reflection, unsafe casting and carelessly disregards all of the various possible exceptions :) so handle with care.

    Code:
    import java.lang.reflect.Method;
     
    import org.bukkit.event.Event;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.HandlerList;
    import org.bukkit.event.Listener;
    import org.bukkit.plugin.Plugin;
    import org.bukkit.plugin.RegisteredListener;
     
    /**
    * @author krisrok
    */
    public class BukkitEventHelper
    {
        @SuppressWarnings("unchecked")
        public static void unregisterEvents(Listener listener, Plugin plugin)
        {
            try
            {
                for(Method method : listener.getClass().getMethods())
                {
                    if(method.getAnnotation(EventHandler.class) != null)
                    {
                        unregisterEvent((Class<? extends Event>)method.getParameterTypes()[0], listener, plugin);
                    }
           
                }
            }
            catch(Exception e){}
        }
     
        public static void unregisterEvent(Class<? extends Event> eventClass, Listener listener, Plugin plugin)
        {
            for(RegisteredListener regListener : HandlerList.getRegisteredListeners(plugin))
            {
                if(regListener.getListener() == listener)
                {
                    try
                    {
                        ((HandlerList)eventClass.getMethod("getHandlerList").invoke(null)).unregister(regListener);
                    }
                    catch(Exception e){}
                }
            }
        }
    }
    
    usage:

    Code:
    BukkitEventHelper.unregisterEvents(myBlockListener, myPlugin); // unregisters all available events of myBlockListener
    BukkitEventHelper.unregisterEvent(BlockBreakEvent.class, myBlockListener, myPlugin); // unregisters all BlockBreakEvents of myBlockListener
     
    Xp10d3 and MrMag518 like this.
Thread Status:
Not open for further replies.

Share This Page