Gamua / Starling-Framework

The Cross Platform Game Engine
http://www.starling-framework.org
Other
2.84k stars 819 forks source link

Sticky events #933

Closed harry248 closed 6 years ago

harry248 commented 7 years ago

Would be nice if you could add sticky events (like event bus libraries on other platforms have).

PrimaryFeather commented 7 years ago

I must admit I'm not familiar with that term. Could you describe what sticky events would do?

harry248 commented 7 years ago

Currently a listener receives an event only after it has registered for that particular event. But when there were events of interest before the the listener registered, those events are lost. An event marked sticky will instead be retained and dispatched as soon as the listener registers. For example I have a Beacon manager singleton. It dispatches various related events (entry, exit, update). I would like some of those events to be sticky, so whenever another component registers as an event listener it will receive the latest events.

I currently can only achieve it by overriding the addEventListener() method and it looks like this:

override public function addEventListener(type:String, listener:Function):void { super.addEventListener(type, listener); if (type == EVENT_BEACON_CHANGE && listener !== null) { const event:Event = Event.fromPool(EVENT_BEACON_CHANGE); listener(event); Event.toPool(event); } }

harry248 commented 7 years ago

As a reference - the "EventBus" library on Android implements such behaviour: http://greenrobot.org/eventbus/documentation/configuration/sticky-events/

b005t3r commented 7 years ago

Sounds like a terrible idea, if I'm honest.

Consider this. You've got two events: ACTIVATE and DEACTIVATE, both sticky. ACTIVATE is dispatched, after a while DEACTIVATE is dispatched and then you register for both. Is your onActivate() handler still valid to be called at this point? You can't expect the system to be active, because you have no idea if it hasn't been deactivated already.

This makes the whole event handling system not only overly complicated but less reliable. Currently, if you register for an event you are guaranteed to be notified in the exact moment it was dispatched. With your idea there's no guarantee that this event can be handled with no problems.

harry248 commented 7 years ago

@b005t3r Sticky events are optional (and can be canceled). They have to be marked as such and definitely have their use cases. It is even implemented in the android sdk itself - sticky broadcasts are basically the same: https://developer.android.com/reference/android/Manifest.permission.html#BROADCAST_STICKY

b005t3r commented 7 years ago

I really don't think defending a point by saying "it's already implemented somewhere, so it has to be reasonable". In my opinion this particular idea is simply broken.

kaikoga commented 7 years ago

You won't need it, because what sticky events offer is basically a notification of public state change, and you'll get the same functionality by e.g. dispatching an Event and store the current state to a field like public var lastEvent, which is way more simple. (You may also notice AS3 is single-threaded and therefore you don't have to think of something like "we must handle this later because we're not on the UI thread now")

harry248 commented 7 years ago

@kaikoga Are you sure you understand the purpose and benefits of sticky events? It is just about notifying listeners of events (marked as sticky) that have been dispatched before the listener registered. It has absolutely nothing to do with threading.

JohnBlackburne commented 7 years ago

Seems a bad idea to me too. The events in Flash and Starling are based on concrete 'events' in-game: a touch, a new frame, something finished loading or being added to the stage. It makes little sense to have them stick around in case something else wants to handle them.

They are already complex enough, in that they are the source of numerous bugs and problems; adding more complexity to them could just make this worse.

And there’s nothing to stop you implementing this yourself: just store any events you want to keep around to check later, disposing of them when you are done with them. I do this myself, for certain sorts of messages; not with Starling events but in a simpler and more lightweight way.

PrimaryFeather commented 7 years ago

Thanks a lot for explaining the details about it, Harald, and for the all the others for chiming in! I can totally see that such a system would be useful in certain situations — but I tend to agree with the others, that this is better implemented in a separate system.

I remember that on iOS, there's a notification system that's completely separate from the rest; just a global object on which you can dispatch and register events (notifications). IMHO, that could be used for such sticky events, too. That could be implemented on application level or in a small extension library.

xleon commented 7 years ago

You can use Parsley: http://www.spicefactory.org/parsley/docs/2.2/manual/messaging.php or implement it yourself. An Event bus pattern has nothing to do with a gaming engine IMO and it´s considered as anti-pattern by many devs. Though it´s very useful in particular scenarios where the sender (dispatcher) and receiver are totally decoupled.

PrimaryFeather commented 6 years ago

I'll close this issue now — it seems to be the general consensus that such a feature is best implemented independently from the standard event system.