New Event System

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

Thread Status:
Not open for further replies.
  1. 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 (Text):
    1.     @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. Thanks, much appreciated
     
  3. Offline

    BloodShura

    Hello!

    I can only put one EventHandler per listener? Because it's saying "Duplicate annotation @EventHandler"
     
  4. No, you can put more
    Code (Text):
    1.     @EventHandler(event = ItemSpawnEvent.class, priority = EventPriority.NORMAL)
    2.     public void onItemSpawn(final ItemSpawnEvent event) {
    3.         Handler.toHandle.add((Item) event.getEntity());
    4.     }
    5.  
    6.     @EventHandler(event = ItemDespawnEvent.class, priority = EventPriority.NORMAL)
    7.     public void onItemDespawn(final ItemDespawnEvent event) {
    8.         Handler.handle((Item) event.getEntity());
    9.     }
    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. Nice, so I can just remove all my registerEvents in the main class?
     
  7. Offline

    Zacherl

    Is that:
    Show Spoiler
    Code (Text):
    1. 05:57:17 [SCHWERWIEGEND] Error occurred while enabling CHDistantFarm v1.04 (Is i
    2. t up to date?): null
    3. java.lang.NullPointerException
    4.         at org.bukkit.event.HandlerList.register(HandlerList.java:82)
    5.         at org.bukkit.event.HandlerList.registerAll(HandlerList.java:90)
    6.         at org.bukkit.plugin.SimplePluginManager.registerEvents(SimplePluginMana
    7. ger.java:438)
    8.         at me.zacherl.distantfarm.DistantFarm.onEnable(DistantFarm.java:446)
    9.         at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:232)
    10.         at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader
    11. .java:1034)
    12.         at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManage
    13. r.java:252)
    14.         at org.bukkit.craftbukkit.CraftServer.loadPlugin(CraftServer.java:190)
    15.         at org.bukkit.craftbukkit.CraftServer.enablePlugins(CraftServer.java:173
    16. )
    17.         at org.bukkit.craftbukkit.CraftServer.reload(CraftServer.java:443)
    18.         at org.bukkit.Bukkit.reload(Bukkit.java:188)
    19.         at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:
    20. 22)
    21.         at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:16
    22. 8)
    23.         at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:3
    24. 85)
    25.         at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:3
    26. 81)
    27.         at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:573)
    28.         at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:550)
    29.         at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:434)
    30.         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. zml2008
    I told him how to fix it, its a bug on reload
     
    Zacherl likes this.
  9. 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. Tried to update, still a few errors left for me tho.
    Code (Text):
    1. 06:11:07 [SEVERE] Could not load 'plugins\ClosedDoors.jar' in folder 'plugins':
    2.  
    3. java.lang.reflect.InvocationTargetException
    4.         at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    5.  
    6.         at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    7.  
    8.         at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Sou
    9. rce)
    10.         at java.lang.reflect.Constructor.newInstance(Unknown Source)
    11.         at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.j
    12. ava:183)
    13.         at org.bukkit.plugin.SimplePluginManager.loadPlugin(SimplePluginManager.
    14. java:187)
    15.         at org.bukkit.plugin.SimplePluginManager.loadPlugins(SimplePluginManager
    16. .java:108)
    17.         at org.bukkit.craftbukkit.CraftServer.loadPlugins(CraftServer.java:155)
    18.         at org.bukkit.craftbukkit.CraftServer.reload(CraftServer.java:441)
    19.         at org.bukkit.Bukkit.reload(Bukkit.java:188)
    20.         at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:
    21. 22)
    22.         at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:16
    23. 8)
    24.         at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:3
    25. 85)
    26.         at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:3
    27. 81)
    28.         at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:573)
    29.         at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:550)
    30.         at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:434)
    31.         at net.minecraft.server.ThreadServerApplication.run(SourceFile:465)
    32. Caused by: org.bukkit.plugin.IllegalPluginAccessException: Plugin attempted to r
    33. egister [email protected]394 whi
    34. le not enabled
    35.         at org.bukkit.plugin.SimplePluginManager.registerEvents(SimplePluginMana
    36. ger.java:430)
    37.         at me.powerking.ClosedDoors.listeners.ClosedDoorsBlockListener.<init>(Cl
    38. osedDoorsBlockListener.java:30)
    39.         at me.powerking.ClosedDoors.ClosedDoors.<init>(ClosedDoors.java:108)
     
  12. Offline

    Zacherl

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

    jogeta_masude

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




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

    }

    But now that this is in the listener


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

    Code (Text):
    1.  
    2.    public void onEnable() {
    3.      MyPlayerListener.registerEvents(this, plugin);
    4.    }
     
  14. I have had a look at the commit.

    Am I right in thinking the new way for custom events is:
    Code (Text):
    1.  
    2. MyEvent extends Event {
    3. ......
    4.  
    5. HandlerList() stuff here as well.
    6. }
    7.  
    8.  
    Code (Text):
    1.  
    2. CustomEventListener extends Listener{
    3.  
    4. Public CustomEventListener(Plugin plugin){
    5. Bukkit.getServer().getPluginManager().registerEvents(this, plugin);
    6. }
    7. @EventHandler(event =  MyEvent .class, priority = EventPriority.NORMAL)
    8. pubic void onMyEvent(MyEvent event){
    9.  
    10. }
    11.  
    also, it's now possible for us (plugins) to disable our events w/o a reload?
     
  15. 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
     
  16. Offline

    jogeta_masude

    Awesome thanks for that :D
     
  17. Offline

    jogeta_masude



    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);
    }


    :'(
     
  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. So this is my on enable
    Code (Text):
    1. PluginManager pm = getServer().getPluginManager();
    2.         pm.registerEvents(blockListener, this);
    3.         pm.registerEvents(playerListener, this);
    4.         pm.registerEvents(entityListener, this);
    and this is one of the listeners:
    Code (Text):
    1. public class ClosedDoorsBlockListener implements Listener {
    2.  
    3.     public static ClosedDoors plugin;
    4.  
    5.     public ClosedDoorsBlockListener(final ClosedDoors plugin) {
    6.     Bukkit.getServer().getPluginManager().registerEvents(this, plugin);
    7.     }
    8. @SuppressWarnings("static-access")
    9. @EventHandler(event = BlockFormEvent.class, priority = EventPriority.NORMAL)
    10. public void onBlockForm(final BlockFormEvent e) {
    11.  
    but i still get the error while enabling but nothing in eclipse? :S
     
  21. 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 (Text):
    1. package com.bergerkiller.bukkit.eventmonitor;
    2.  
    3. import org.bukkit.event.block.BlockBreakEvent;
    4. import org.bukkit.event.block.BlockBurnEvent;
    5. import org.bukkit.event.block.BlockCanBuildEvent;
    6. import org.bukkit.event.block.BlockDamageEvent;
    7. import org.bukkit.event.block.BlockDispenseEvent;
    8. import org.bukkit.event.block.BlockFadeEvent;
    9. import org.bukkit.event.block.BlockFormEvent;
    10. import org.bukkit.event.block.BlockFromToEvent;
    11. import org.bukkit.event.block.BlockIgniteEvent;
    12. import org.bukkit.event.block.BlockListener;
    13. import org.bukkit.event.block.BlockPhysicsEvent;
    14. import org.bukkit.event.block.BlockPistonExtendEvent;
    15. import org.bukkit.event.block.BlockPistonRetractEvent;
    16. import org.bukkit.event.block.BlockPlaceEvent;
    17. import org.bukkit.event.block.BlockRedstoneEvent;
    18. import org.bukkit.event.block.BlockSpreadEvent;
    19. import org.bukkit.event.block.LeavesDecayEvent;
    20. import org.bukkit.event.block.SignChangeEvent;
    21.  
    22. public class EventBlockListener extends BlockListener {
    23.  
    24.     @Override
    25.     public void onBlockBreak(BlockBreakEvent event) {
    26.         EventListener.BLOCKBREAK.next();
    27.     }
    28.  
    29.     @Override
    30.     public void onBlockBurn(BlockBurnEvent event) {
    31.         EventListener.BLOCKBURN.next();
    32.     }
    33.  
    34.     @Override
    35.     public void onBlockCanBuild(BlockCanBuildEvent event) {
    36.         EventListener.BLOCKCANBUILD.next();
    37.     }
    38.  
    39.     @Override
    40.     public void onBlockDamage(BlockDamageEvent event) {
    41.         EventListener.BLOCKDAMAGE.next();
    42.     }
    43.  
    44.     @Override
    45.     public void onBlockDispense(BlockDispenseEvent event) {
    46.         EventListener.BLOCKDISPENSE.next();
    47.     }
    48.  
    49.     @Override
    50.     public void onBlockFade(BlockFadeEvent event) {
    51.         EventListener.BLOCKFADE.next();
    52.     }
    53.  
    54.     @Override
    55.     public void onBlockForm(BlockFormEvent event) {
    56.         EventListener.BLOCKFORM.next();
    57.     }
    58.  
    59.     @Override
    60.     public void onBlockFromTo(BlockFromToEvent event) {
    61.         EventListener.BLOCKFROMTO.next();
    62.     }
    63.  
    64.     @Override
    65.     public void onBlockIgnite(BlockIgniteEvent event) {
    66.         EventListener.BLOCKIGNITE.next();
    67.     }
    68.  
    69.     @Override
    70.     public void onBlockPhysics(BlockPhysicsEvent event) {
    71.         EventListener.BLOCKPHYSICS.next();
    72.     }
    73.  
    74.     @Override
    75.     public void onBlockPistonExtend(BlockPistonExtendEvent event) {
    76.         EventListener.BLOCKPISTONEXTEND.next();
    77.     }
    78.  
    79.     @Override
    80.     public void onBlockPistonRetract(BlockPistonRetractEvent event) {
    81.         EventListener.BLOCKPISTONRETRACT.next();
    82.     }
    83.  
    84.     @Override
    85.     public void onBlockPlace(BlockPlaceEvent event) {
    86.         EventListener.BLOCKPLACE.next();
    87.     }
    88.  
    89.     @Override
    90.     public void onBlockRedstoneChange(BlockRedstoneEvent event) {
    91.         EventListener.BLOCKREDSTONECHANGE.next();
    92.     }
    93.  
    94.     @Override
    95.     public void onBlockSpread(BlockSpreadEvent event) {
    96.         EventListener.BLOCKSPREAD.next();
    97.     }
    98.  
    99.     @Override
    100.     public void onLeavesDecay(LeavesDecayEvent event) {
    101.         EventListener.BLOCKLEAVESDECAY.next();
    102.     }
    103.  
    104.     @Override
    105.     public void onSignChange(SignChangeEvent event) {
    106.         EventListener.BLOCKSIGNCHANGE.next();
    107.     }
    108.    
    109.    
    110.  
    111. }
    112.  
     
  22. bergerkiller
    Code (Text):
    1. pm.registerEvents(blockListener, this);
    2. pm.registerEvents(blockListener, this);
    3. pm.registerEvents(blockListener, this);
    4. pm.registerEvents(blockListener, this);
    5. pm.registerEvents(blockListener, this);
    That should work.
     
  23. 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)
     
  24. 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.
     
  25. 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 :)
     
  26. It is added, I think the command is /timings
     
  27. 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!
     
  28. Don Redhorse
    Ill update the wiki. I think my approach is the best, but thats just me :)
     
Thread Status:
Not open for further replies.

Share This Page