OvercastNetwork / SportBukkit

CraftBukkit and Bukkit modifications that improve stability and add new features
99 stars 84 forks source link

Always dispatch events to listeners of any superclass #164

Closed jedediah closed 9 years ago

jedediah commented 9 years ago

CraftBukkit does not guarantee that a listener for an event class will receive events of all of its subclasses. Events are dispatched only to the HandlerList of the most derived superclass that declares its own getHandlerList method. Any HandlerLists further up the class hiearchy will not receive the event. As such, receiving all events of a particular class is effectively impossible, because any subclass could declare its own getHandlerList. Indeed, many of CraftBukkit's own events do exactly this, so knowing exactly what events a listener will receive involves inspecting the source code of its entire class hiearchy.

This patch changes the method that searches for the HandlerList for an event class to use the least derived superclass instead of the most derived. Any HandlerLists in subclasses are completely unused. The event dispatch code is also changed to find its HandlerList in the same way, instead of calling Event#getHandlers. To make this fast, HandlerLists are cached by event class, so a typical dispatch does not require any reflection or iterating through superclasses.

The new method PluginManager#getHandlerList serves as a replacement for the (now unused) Event#getHandlers, and it uses the cache.