EventHandler Suggestions

Two things that I thought would make a lot of sense but I never saw back in Bukkit.

Instance EventHandlers: There were times ware I wanted a single object to listen for when a single player did something. Rather than listen for when every player did that something, I always thought giving each Player object (external or within) their own personal event manager for registering PlayerEvent EventHandlers.

When player related events are fired and the global EventManager knows which player caused it, so why couldn’t pass through the global EventHandlers than make a pass through the handlers local to that player as well?

The same logic could be made with Block and BlockEvents, World and WorldEvents. etc.

Static EventHandlers: With Bukkit I understood why this wouldn’t be possible due to the Listener interface requirement, however I noticed in the sponge api docs currently out there that this isn’t the case. The same way you pass in an Object to register events the way the current api shows, could you not pass in a Class<?> object as well? looking for static methods with the @SpongeEventHandler annotation

2 Likes

That’s also something I saw missing in Bukkit. I always wondered, “This event only applies to this player why must every player raise it? It just slows down the whole thing” There are many occurences when you’d only want a listener/event to work on just 1 or 2 players.

For example when they have entered a command which changes their mode. So instead of checking if the player has enabled that mode in the listener, the command would add or remove that listener from them.

2 Likes

This sounds nice in theory, but I can see it going bad very quickly.

First, having Instance EventHandlers wouldn’t make raising the event any faster. With this system, when the player does something (ex: chat), the API has to raise a global EventHandler (for plugins listening for chat events by all players), then check to see if any plugins just want that player’s events, then raise the event again. So now 2 events have been fired, which is more than 1.
If we removed global EventHandlers and just had Instance EventHandlers, you lose the functionally of global EventHandlers, and to get the same effect, you have to tell the API you want to listen to the chat event for all players on the server, all players that join the server, and stop listening for players that quit. (For example, a plugin that logs chat)

Now, if we ignore the first issue I pointed out, there clearly wont be a big performance hit for small servers. But on a really big server (200 - 800 players at any given time), if half of the players use a command that creates an Instance EventHandler for said player, then the performance hit would be noticeable.

However, these are only my thoughts…the idea sounds nice, but I see a lot of initial problems with it.

But it wouldn’t be two events, just one that also gets passed into the instance handlers.

the comparison here is an extra list to iterate over vs getting the player UUID from a global event to get your instance class from a map to call what you wanted to do in the first place.

I realized a little while after I posted how you could do this system by simply filtering which listeners are invoked and which are not (based on whether the listener is listening to all events or if the listener is listening to events caused by the player in question).

The memory footprint it would leave still leaves me a bit worried though, in the case where you have a new listener object for each player you’re listening for (for convenience sake), and the server is well populated (200+ players) and there are multiple plugins using this method…you can see it add up.

But that could just be me being a worry wart : p

I cant see the memory footprint being any worse than the alternative for what you would use it for.

Say you have a skill system ware when you equip a skill. You create a player local listener for PlayerInteract to act as the skill trigger. Then perhaps you equip a different skill that triggers off of EntityInteract that replaces the other listener with this new one. The listeners of course containing the logic of the skill.

With the alternative you would have a single listener that listens for both PlayerInteract and EntityInteract ware you look up and obtain which skill the player is equipped with if any. Then use that skill object to figure out what logic to execute passing in information obtained from the event.

You are seeking something akin to an Entity Component System. In such a system, you would attach components to an object (Entity) and then a ComponentSystem would filter out objects who don’t have a certain series of components.

This is currently planned for as an addition to Sponge but no ETA.

Will the components be able to listen for events?

ComponentSystems could handle an event if you want

Components are just data holders, nothing more

This is going a bit off topic as I can see how one might do this. However I have one question about using components as event handlers under the statement that components are data holders only.

In the case of my above example the data the component has at this point is a method to be called when the skill is active. Under this scenario is the logic considered within the ComponentSystem calling such a method or the Component that contains said method.

It’s basically a question of is event logic considered “data” for the purposes of being an event handler within a component.