-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Event Manager postEvent script callback error #325
Comments
I can't find it at the moment, but seems awfully similar to an issue Torque 3D ran into couple years back. |
So you're saying that if you set %this.currentState to false or 0 that it would prevent other callbacks from firing? Sounds like trouble... |
@greenfire27 No, the code above prevents further callbacks as it is (with "Restart" as a value), setting it to false or 0 has the same effect. i.e. T2D evaluates the last statement in these callback methods as the return value of the method, even when no return value is specified. Sounds like a nested issue in Con::executef. For the record, in my test project, I had to modify every callback function so that it ended with the statement :
and no further problems were had. - Testbed - I know the Event Manager sees very little use so here's a quick blurb to get started if that's the case.
Now just make sure Myobject and Myotherobject have the following methods :
In theory, Myotherobject shouldn't be triggered.
And everything should work. |
Ran into another instance of this. This subscriber(PlayerObject) has a behavior which handles the event (the object itself has no handler defined within its bare namespace). This second behavior then calls a method on a bunch of other behaviors (all also installed on PlayerObject). Let's call these the children behaviors. If I add an echo("Something random"); command in each of the children behaviors` methods, everything works fine. If I don't, all children behaviors will execute their method properly, one after the other, as expected. However, when the last of the children behaviors exits the function, all children methods except that last one are called again but without passing any parameters. Probably something no one ever encounters but....well, I did so it probably points to something deep-rooted in the namespace/behavior/component code. I`m writing this down to also help visualize the issue. |
For those following at home (lol) Behavior Connections are THE way to circumvent this self-referential namespace mess. |
I'm actually hanging on every word. Can you describe for the class Behavior Connections? |
Sure. I`ve made the modifications to my soon-to-be-shared-on-github project and it works perfectly. The start is still the same
This behavior now has an empty method called dispatch Each behavior which needs to be notified has its template created as such :
An Action method, where all the magic takes place, is defined on these behaviors. Then I connect the initial behavior's output to all the behaviors' inputs as such : Then, whenever my InputMatrix dispatches an event to %sourcebehavior, the method handling the event calls
And all behaviors connected to that output have their Action method executed. The wiki explains it very well https://github.com/GarageGames/Torque2D/wiki/Behavior-Connections but I had never used them before. Only drawback is that you cannot (as far as I know) pass arguments to/from the connected functions. |
Returning to the original problem, if you look at the notes for the function onMessageReceived in eventManager.cc, the code actually take the return values of the callbacks and uses them to decide if it should keep making the callbacks. Basically, a return value of true means that it will stop doing the callbacks (not sure if this is a useful feature or not). Most of the callbacks that the engine does, like onAdd() when you create an object, do not expect a return value. However, these particular callbacks expect a bool returned and are basically trying to make your last line in the callback into something it can use. In the event that it get's a string that doesn't equal "false" it uses it as true stops passing the callback to more listeners. To be honest, unless we decide to make it work differently, the best thing to do is simply always return false in your callbacks. Now, to keep things interesting, I found a better EventManager bug! It seems if you remove a listener from an event during that listener's callback the engine crashes.
My guess is that we're changing the length of the iterator in the middle of using it. |
Good find! I am not suggesting we change it, I simply tried to provide as much info as I could. The event manager will also crash if you do not specify a queue name upon creation as shown below.
|
Yes, the EventManager obviously has rough edges that need to be cleaned up or at the very least documented. Unfortunately, as far as I know, we don't have an Event Manager page yet in the wiki, which might explain why nobody really uses it and reports these issues with it. Is it possible to create multiple queues within the same EventManager? Is there really a point to naming a queue? It doesn't really seem like the name is used anywhere after creation. I would also love to see more useful script functions like a removeAll, or removeAllForSubscriber. Joining could be similar: subscribeToAll(%subscriber) or subscribeToQueue(%subscriber) if we had multiple queues which could be used to group events. |
Pull Request #376 is my attempt to fix all the problems around the event manager. I wrote a wiki page to describe how it works. Basically it allows any object to listen to any other object. Any object can now post events that will go out to all of its listeners. No need to set up a special object, no messaging queue, no registering events, and no returning false just to keep things running. I'll give the community time to play with this new event system, but at some point I hope to remove the old EventManager entirely. Its services are no longer required. |
Context
This occurs when an eventManager posts an event (via its postEvent ConsoleMethod) to its subscribers.
The code loops through all Simobject listeners (subscribers) and executes a script callback on each one.
/source/messaging/eventManager.cc
function EventManagerListener::onMessageReceived(...
If the callback function returns a value and this value is evaluated to "false", the loop stops and all remaining subscribers are completely ignored.
In my code, the callback function contained one line of code
This code assigns a string to a dynamically created variable (CurrentState) on a ScriptObject.
The ScriptObject named GameManager is a subscriber to the Event Manager.
Here is the problem :
The C++ code takes the string "Restart" as the return value of the callback function.
Why would this value be returned from Con::executef?
Using functions like echo(...) or complex physics manipulation never cause this problem, the only way I've managed to reproduce this is with simple dynamic variable assignations as illustrated here.
Hack city
Adding "return true;" at the end of the script function solves the issue.
I still think this points to a problem with the scripting engine.
The text was updated successfully, but these errors were encountered: