New Event System

Discussion in 'Resources' started by md_5, Jan 17, 2012.

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

    md_5

    Some of you may have noticed that we have introduced a new way of handling events in Bukkit. Those of you that haven't noticed sure will when you next open your IDE and find a bunch of big yellow deprecation warnings :p
    Anyway lets start with the old way of using listeners, or more specifically how I do it in all of my projects.
    Code:java
    1. package com.md_5.noclip.listeners;
    2.  
    3. import org.bukkit.Bukkit;
    4. import org.bukkit.event.Event;
    5. import org.bukkit.event.EventHandler;
    6. import org.bukkit.event.EventPriority;
    7. import org.bukkit.event.player.PlayerJoinEvent;
    8. import org.bukkit.event.player.PlayerListener;
    9.  
    10. public class NoClipPlayerListener extends PlayerListener{
    11.  
    12. public NoClipPlayerListener() {
    13. Bukkit.getServer().getPluginManager().registerEvent(Event.Type.PLAYER_JOIN, this, Event.Priority.Normal, plugin);
    14. }
    15. @Override
    16. public void onPlayerJoin(final PlayerJoinEvent event) {
    17. }
    18. }
    19.  

    Looking at the code we have a listening class that extends PlayerListener, we then have a constructor which registers the events and some methods to execute the events. The way I use this class is to simply call: new NoClipPlayerListener() : In my onEnable() method. But now how do we replace this with the new event system you ask? Well lets take a look at the same method again:

    Code:java
    1. package com.md_5.noclip.listeners;
    2.  
    3. import org.bukkit.Bukkit;
    4. import org.bukkit.event.EventHandler;
    5. import org.bukkit.event.EventPriority;
    6. import org.bukkit.event.Listener;
    7. import org.bukkit.event.player.PlayerJoinEvent;
    8.  
    9. public class NoClipPlayerListener implements Listener {
    10.  
    11. public NoClipPlayerListener() {
    12. Bukkit.getServer().getPluginManager().registerEvents(this, plugin);
    13. }
    14.  
    15. @EventHandler(priority = EventPriority.LOW)
    16. public void onPlayerJoin(final PlayerJoinEvent event) {
    17. }
    18. }
    19.  

    Well aside from the lack of big warnings several things have changed. The first being we no longer extend PlayerListener, instead all Listeners, no matter what their type implement Listener. Now instead of registering each event individually in the constructor we can simply call registerEvents() and get all the events we use registered for us. Another bonus of this system is you can name your methods anything you like. Now how do we actually go about registering these new events? Well instead of using the @Override tag to replace the listening methods you add a new tag:
    @EventHandler();
    The syntax goes like this:
    Code:
        @EventHandler(event = NAMEOFEVENT.class, priority = EventPriority.WHATPRIORITY)
    So say I wanted to add a new event, say playermove it is as simple as adding this method:
    Code:java
    1. @EventHandler(priority = EventPriority.LOW)
    2. public void whenThePlayerMoves(final PlayerMoveEvent event) {
    3. }
    4.  

    Notice here how I can call the method anything I like. Using these new listeners in your plugin is exactly the same as before: new MYListener();

    I hope this is a brief tutorial on how to upgrade your plugins to the new event system.
     
  2. Offline

    -_Husky_-

    Thanks, much appreciated
     
  3. Offline

    BloodShura

    Hello!

    I can only put one EventHandler per listener? Because it's saying "Duplicate annotation @EventHandler"
     
  4. Offline

    md_5

    No, you can put more
    Code:
        @EventHandler(event = ItemSpawnEvent.class, priority = EventPriority.NORMAL)
        public void onItemSpawn(final ItemSpawnEvent event) {
            Handler.toHandle.add((Item) event.getEntity());
        }
     
        @EventHandler(event = ItemDespawnEvent.class, priority = EventPriority.NORMAL)
        public void onItemDespawn(final ItemDespawnEvent event) {
            Handler.handle((Item) event.getEntity());
        }
    Thats what I am using in one class
     
  5. Offline

    xpansive

    Glad this got pulled, It's a massive improvement. Bukkit is still full of things that could use refactoring though...
     
  6. Offline

    CXdur

    Nice, so I can just remove all my registerEvents in the main class?
     
  7. Offline

    Zacherl

    Is that:
    Show Spoiler
    Code:
    05:57:17 [SCHWERWIEGEND] Error occurred while enabling CHDistantFarm v1.04 (Is i
    t up to date?): null
    java.lang.NullPointerException
            at org.bukkit.event.HandlerList.register(HandlerList.java:82)
            at org.bukkit.event.HandlerList.registerAll(HandlerList.java:90)
            at org.bukkit.plugin.SimplePluginManager.registerEvents(SimplePluginMana
    ger.java:438)
            at me.zacherl.distantfarm.DistantFarm.onEnable(DistantFarm.java:446)
            at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:232)
            at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader
    .java:1034)
            at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManage
    r.java:252)
            at org.bukkit.craftbukkit.CraftServer.loadPlugin(CraftServer.java:190)
            at org.bukkit.craftbukkit.CraftServer.enablePlugins(CraftServer.java:173
    )
            at org.bukkit.craftbukkit.CraftServer.reload(CraftServer.java:443)
            at org.bukkit.Bukkit.reload(Bukkit.java:188)
            at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:
    22)
            at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:16
    8)
            at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:3
    85)
            at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:3
    81)
            at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:573)
            at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:550)
            at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:434)
            at net.minecraft.server.ThreadServerApplication.run(SourceFile:465)

    my fault or is it caused by some kind of bug in the new event handler implementation? This message shows up all the time i try to reload the server.
     
  8. Offline

    md_5

    zml2008
    I told him how to fix it, its a bug on reload
     
    Zacherl likes this.
  9. Offline

    zml2008

    That bug is fixed, waiting in a pull request (#489)
     
    Zacherl likes this.
  10. Offline

    BloodShura

    Hey...

    Event Handler isn't working with EntityDamageByEntityEvent.

    2012-01-18 02:56:122012-01-18 02:56:12 [GRAVE] Error occurred while enabling ShuraCore v1.5 (Is it up to date?): Unable to find handler list for event org.bukkit.event.entity.EntityDamageByEntityEvent
    org.bukkit.plugin.IllegalPluginAccessException: Unable to find handler list for event org.bukkit.event.entity.EntityDamageByEntityEvent
    at org.bukkit.plugin.SimplePluginManager.getRegistrationClass(SimplePluginManager.java:477)
    at org.bukkit.plugin.SimplePluginManager.registerEvents(SimplePluginManager.java:433)
    at shura.commands.ShuraCore.Setup(ShuraCore.java:157)
    at shura.commands.ShuraCore.onEnable(ShuraCore.java:88)
    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:232)
    at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:1034)
    at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:252)
    at org.bukkit.craftbukkit.CraftServer.loadPlugin(CraftServer.java:190)
    at org.bukkit.craftbukkit.CraftServer.enablePlugins(CraftServer.java:173)
    at net.minecraft.server.MinecraftServer.t(MinecraftServer.java:356)
    at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:343)
    at net.minecraft.server.MinecraftServer.init(MinecraftServer.java:175)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:407)
    at net.minecraft.server.ThreadServerApplication.run(SourceFile:465)
     
  11. Offline

    CXdur

    Tried to update, still a few errors left for me tho.
    Code:
    06:11:07 [SEVERE] Could not load 'plugins\ClosedDoors.jar' in folder 'plugins':
     
    java.lang.reflect.InvocationTargetException
            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
     
            at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
     
            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Sou
    rce)
            at java.lang.reflect.Constructor.newInstance(Unknown Source)
            at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.j
    ava:183)
            at org.bukkit.plugin.SimplePluginManager.loadPlugin(SimplePluginManager.
    java:187)
            at org.bukkit.plugin.SimplePluginManager.loadPlugins(SimplePluginManager
    .java:108)
            at org.bukkit.craftbukkit.CraftServer.loadPlugins(CraftServer.java:155)
            at org.bukkit.craftbukkit.CraftServer.reload(CraftServer.java:441)
            at org.bukkit.Bukkit.reload(Bukkit.java:188)
            at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:
    22)
            at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:16
    8)
            at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:3
    85)
            at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:3
    81)
            at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:573)
            at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:550)
            at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:434)
            at net.minecraft.server.ThreadServerApplication.run(SourceFile:465)
    Caused by: org.bukkit.plugin.IllegalPluginAccessException: Plugin attempted to r
    egister me.powerking.ClosedDoors.listeners.ClosedDoorsBlockListener@5d612394 whi
    le not enabled
            at org.bukkit.plugin.SimplePluginManager.registerEvents(SimplePluginMana
    ger.java:430)
            at me.powerking.ClosedDoors.listeners.ClosedDoorsBlockListener.<init>(Cl
    osedDoorsBlockListener.java:30)
            at me.powerking.ClosedDoors.ClosedDoors.<init>(ClosedDoors.java:108)
     
  12. Offline

    Zacherl

    Move your registerEvents() call to the onEnabled() event.
     
  13. Offline

    zml2008

  14. Offline

    jogeta_masude

    Sorry I'm confused as to what goes in the onEnable now, it used to be




    Code:
     public void onEnable() {
        PluginManager pm = getServer().getPluginManager();
        pm.registerEvent(Event.Type.PLAYER_INTERACT, this.playerListener, Event.Priority.Normal, this);
        pm.registerEvent(Event.Type.PLAYER_JOIN, this.playerListener, Event.Priority.Normal, this);

    }

    But now that this is in the listener


    Code:
      public MyPlayerListener() {
      Bukkit.getServer().getPluginManager().registerEvents(this, plugin);
      }
    my onEnable should look like this?

    Code:
       public void onEnable() {
         MyPlayerListener.registerEvents(this, plugin);
       }
     
  15. I have had a look at the commit.

    Am I right in thinking the new way for custom events is:
    Code:
    MyEvent extends Event {
    ......
     
    HandlerList() stuff here as well.
    }
     
    
    Code:
    CustomEventListener extends Listener{
     
    Public CustomEventListener(Plugin plugin){
    Bukkit.getServer().getPluginManager().registerEvents(this, plugin);
    }
    @EventHandler(event =  MyEvent .class, priority = EventPriority.NORMAL)
    pubic void onMyEvent(MyEvent event){
     
    }
    
    also, it's now possible for us (plugins) to disable our events w/o a reload?
     
  16. Offline

    md_5

    You can put it in onEnable, but it is a habit of mine to put it in the constructor.
    Just replace pm.registerEvent(...) with pm.registerEvents(mylistener, this) if doing it in onEnable
    tehbeard
     
  17. Offline

    jogeta_masude

    Awesome thanks for that :D



    I've done that but I'm getting this error on on server startup, sorry I'm not that great with java, took me forever to get it working with the old code.

    Show Spoiler

    [SEVERE] Error occurred while enabling HuxstonAdmin v1.0 (Is it up to date?): null
    java.lang.NullPointerException
    at org.bukkit.plugin.SimplePluginManager.registerEvents(SimplePluginManager.java:429)
    at me.huxston.HuxstonAdmin.HuxstonAdmin.onEnable(HuxstonAdmin.java:46)
    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:232)
    at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:1034)
    at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:252)
    at org.bukkit.craftbukkit.CraftServer.loadPlugin(CraftServer.java:190)
    at org.bukkit.craftbukkit.CraftServer.enablePlugins(CraftServer.java:173)
    at net.minecraft.server.MinecraftServer.t(MinecraftServer.java:356)
    at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:343)
    at net.minecraft.server.MinecraftServer.init(MinecraftServer.java:175)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:407)
    at net.minecraft.server.ThreadServerApplication.run(SourceFile:465)

    and this is how i've done my onEnable
    Show Spoiler

    PluginManager pm = getServer().getPluginManager();
    pm.registerEvents(blockListener, plugin);
    pm.registerEvents(serverListener, plugin);
    pm.registerEvents(playerListener, plugin);
    pm.registerEvents(entityListener, plugin);
    }


    :'(

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 23, 2016
  18. Offline

    Zeerix

    Replace plugin with this.
     
    iKeirNez and jogeta_masude like this.
  19. Offline

    jogeta_masude

    Ohhh, thankyou! It works perfect again. Lifesavers :D
     
  20. Offline

    CXdur

    So this is my on enable
    Code:
    PluginManager pm = getServer().getPluginManager();
            pm.registerEvents(blockListener, this);
            pm.registerEvents(playerListener, this);
            pm.registerEvents(entityListener, this);
    and this is one of the listeners:
    Code:
    public class ClosedDoorsBlockListener implements Listener {
     
        public static ClosedDoors plugin;
     
        public ClosedDoorsBlockListener(final ClosedDoors plugin) {
        Bukkit.getServer().getPluginManager().registerEvents(this, plugin);
        }
    @SuppressWarnings("static-access")
    @EventHandler(event = BlockFormEvent.class, priority = EventPriority.NORMAL)
    public void onBlockForm(final BlockFormEvent e) {
    
    but i still get the error while enabling but nothing in eclipse? :S
     
  21. Offline

    feildmaster

  22. Offline

    bergerkiller

    I has a question :p

    I made a global event listener plugin a week ago (to monitor the amount of calls, processing duration times and finally, get the plugins that have registered for certain priority events). How can I double-register my event?

    Say, I have onPlayerMove with a counter. When counter = 0 I handle the lowest coding, when counter = 1 it monitors and resets the counter. Previously I could simply register my listener 5x, how will this work now? Adding the same code 5x for every possible event will be a serious pain...

    Code:
    package com.bergerkiller.bukkit.eventmonitor;
     
    import org.bukkit.event.block.BlockBreakEvent;
    import org.bukkit.event.block.BlockBurnEvent;
    import org.bukkit.event.block.BlockCanBuildEvent;
    import org.bukkit.event.block.BlockDamageEvent;
    import org.bukkit.event.block.BlockDispenseEvent;
    import org.bukkit.event.block.BlockFadeEvent;
    import org.bukkit.event.block.BlockFormEvent;
    import org.bukkit.event.block.BlockFromToEvent;
    import org.bukkit.event.block.BlockIgniteEvent;
    import org.bukkit.event.block.BlockListener;
    import org.bukkit.event.block.BlockPhysicsEvent;
    import org.bukkit.event.block.BlockPistonExtendEvent;
    import org.bukkit.event.block.BlockPistonRetractEvent;
    import org.bukkit.event.block.BlockPlaceEvent;
    import org.bukkit.event.block.BlockRedstoneEvent;
    import org.bukkit.event.block.BlockSpreadEvent;
    import org.bukkit.event.block.LeavesDecayEvent;
    import org.bukkit.event.block.SignChangeEvent;
     
    public class EventBlockListener extends BlockListener {
     
        @Override
        public void onBlockBreak(BlockBreakEvent event) {
            EventListener.BLOCKBREAK.next();
        }
     
        @Override
        public void onBlockBurn(BlockBurnEvent event) {
            EventListener.BLOCKBURN.next();
        }
     
        @Override
        public void onBlockCanBuild(BlockCanBuildEvent event) {
            EventListener.BLOCKCANBUILD.next();
        }
     
        @Override
        public void onBlockDamage(BlockDamageEvent event) {
            EventListener.BLOCKDAMAGE.next();
        }
     
        @Override
        public void onBlockDispense(BlockDispenseEvent event) {
            EventListener.BLOCKDISPENSE.next();
        }
     
        @Override
        public void onBlockFade(BlockFadeEvent event) {
            EventListener.BLOCKFADE.next();
        }
     
        @Override
        public void onBlockForm(BlockFormEvent event) {
            EventListener.BLOCKFORM.next();
        }
     
        @Override
        public void onBlockFromTo(BlockFromToEvent event) {
            EventListener.BLOCKFROMTO.next();
        }
     
        @Override
        public void onBlockIgnite(BlockIgniteEvent event) {
            EventListener.BLOCKIGNITE.next();
        }
     
        @Override
        public void onBlockPhysics(BlockPhysicsEvent event) {
            EventListener.BLOCKPHYSICS.next();
        }
     
        @Override
        public void onBlockPistonExtend(BlockPistonExtendEvent event) {
            EventListener.BLOCKPISTONEXTEND.next();
        }
     
        @Override
        public void onBlockPistonRetract(BlockPistonRetractEvent event) {
            EventListener.BLOCKPISTONRETRACT.next();
        }
     
        @Override
        public void onBlockPlace(BlockPlaceEvent event) {
            EventListener.BLOCKPLACE.next();
        }
     
        @Override
        public void onBlockRedstoneChange(BlockRedstoneEvent event) {
            EventListener.BLOCKREDSTONECHANGE.next();
        }
     
        @Override
        public void onBlockSpread(BlockSpreadEvent event) {
            EventListener.BLOCKSPREAD.next();
        }
     
        @Override
        public void onLeavesDecay(LeavesDecayEvent event) {
            EventListener.BLOCKLEAVESDECAY.next();
        }
     
        @Override
        public void onSignChange(SignChangeEvent event) {
            EventListener.BLOCKSIGNCHANGE.next();
        }
       
       
     
    }
    
     
  23. Offline

    md_5

    bergerkiller
    Code:
    pm.registerEvents(blockListener, this);
    pm.registerEvents(blockListener, this);
    pm.registerEvents(blockListener, this);
    pm.registerEvents(blockListener, this);
    pm.registerEvents(blockListener, this);
    That should work.
     
  24. Offline

    bergerkiller

    md_5 but they are different priorities (I register all five priorities and check the time in between, to see what priority took longest to execute. It's as a closest you can get to monitoring events)
     
  25. Offline

    md_5

    Check out the plugin Bukkit-Insider on BukkitDev, it uses an alternate plugin manager to monitor events. Otherwise Tahg has added a monitoring function to Bukkit, although it only displays total time, not averages.
     
  26. Offline

    bergerkiller

    md_5 Ah ok so it is already getting added internally, then I'll just keep that project alone and use Bukkits' features in the near future :)
     
  27. Offline

    md_5

    It is added, I think the command is /timings
     
  28. Offline

    Don Redhorse

    Nice post, two things though:

    a) Please also put up a post how the wiki explains registering a event... it is a little bit different than your approach... which I like because I think it is better.
    b) Please update the wiki :)

    THANKS!
     
  29. Offline

    md_5

    Don Redhorse
    Ill update the wiki. I think my approach is the best, but thats just me :)
     
  30. Offline

    Don Redhorse

    ähmm after reading my posting again.. that's what I meant..
     
Thread Status:
Not open for further replies.

Share This Page