Page 1 of 2

Event system discussion

Posted: Mon Jul 09, 2012 11:20 pm
by your-name-here
This thread will serve as a discussion on the event system.

I think we need to sit down and brainstorm out what the python coders need called from the C++ plugin.

Questions to answer are:
1) Should be have functionality similar to es.registerForEvent?
2) Should the core plugin also call a handleEvent function in the sp.py whenever an event is called?

There was a thread that Ayuto posted about simplifying IGameEvent access. There are a few things to consider with that proposal.
To implement what was suggested, we'd have to read the event descriptor and parse out variables every time an event is fired. We need to
do this because python has no way of knowing what variables exist within an event. Nor does it have a way of knowing what type those variables
are. We're going to sacrifice performance (especially on noisy events like weapon_fire) for usability. Is this a cost that is worth it?

We should hammer out the specs for the event system before we delve into writing tons of code :)

Posted: Tue Jul 10, 2012 12:18 am
by satoon101
As far as having es.addons.registerForEvent functionality, I would say almost definitely. If we went with a system like the decorators system, where the scripter would have to declare a function/method as an event explicitly, and it was built into the C++ side, then I would say no. Otherwise, I would have to say yes.

Having thought a little more about the decorator system, it is starting to grow on me. Using that system would eliminate the need completely of the plugin itself automatically searching through a script to register functions with names of events for the event.



While I would love if an Event Variable would return the proper type, I am not sure we can do this properly. As ynh mentioned, we would have to "know" what type is expected, especially since an "stringed" integer "could" be what is "supposed" to be returned, and not an integer.

Satoon

Posted: Tue Jul 10, 2012 12:19 am
by Absolute
I think you should have to register functions for events on plugin load, that way you could even change the hook type (like SM does it).

Btw: the .res files contain how many variables the event will have and their types, why not parse that one once? (if you really want to have it the native way)

Posted: Tue Jul 10, 2012 1:51 am
by satoon101
http://forums.eventscripts.com/viewtopic.php?p=317004#p317004

Look at SuperDave's reply in that thread.

Satoon

Posted: Tue Jul 10, 2012 10:06 am
by DanielB
satoon101 wrote:As far as having es.addons.registerForEvent functionality, I would say almost definitely. If we went with a system like the decorators system, where the scripter would have to declare a function/method as an event explicitly, and it was built into the C++ side, then I would say no. Otherwise, I would have to say yes.


I think it would be useful for certain libraries too - ES2's popuplib for example needs to listen for es_client_command. Obviously this is an ES specific example.

satoon101 wrote:Look at SuperDave's reply in that thread.


That is problematic - especially in custom defined events where we only know what the res file contains (and the script author may or may nor abide to that).
We could perhaps have this functionality explicitly invoked in the decorator which will give a parameter to the event that will type and memorize (and throw exception if needed) the value on request.

It would be nice to have values in their proper types - other things aside how many times have you seen a comparison between a string and integer userid?

It's something that would be nice, but if we can't be sure of the type it's usefulness drops a bit. (That said, it still would be useful in a large number of situations)

Posted: Tue Jul 10, 2012 6:54 pm
by Omega_K2
1) I think having a function to register events manually is an absolute must have. There are situations where you have to register events manually; for example on the fly due to config changes (or because you stored the events to register in a DB). In addition you need it libaries.
Same goes for unregistering obiviously.

2) Well, yes, that would be needed if we implement the calling for custom-registered events in python. Might aswell be done in c++ and made be available in py (for speed?)

I think going both ways would be a good idea. Because you can still have that speed when you need it, and if you don't, you can just rely on the conversion mechanisims. As for decorators or registering events this is easy to implement; it would just be a keyword argument that defaults to one of these options. So basically, default behaviour could be to convert vars to their type, and if you don't want it, you just disable it upon registering the event either though a function or a decorator.

Posted: Tue Jul 10, 2012 7:12 pm
by satoon101
Well, if we went with the decorators system, libraries (though we are going to use modules instead of libraries for this plugin) will easily be able to use that same functionality to register for an event. Currently, within ES2.1, only 3 events are registered in 2 total libraries. Only 1 of those (player_disconnect) is a non-ES event.

Config changes could work the same way, especially if an addon was designed properly, and unloaded certain modules when configurations were changed.

I still think calling GetString, GetInt, etc is more explicit and is much better than the plugin "guessing" what type of value the addon wishes to be returned. I don't believe reading a .res file is the proper answer to that issue either.

Satoon

Posted: Tue Jul 10, 2012 8:57 pm
by your-name-here
satoon101 wrote:Well, if we went with the decorators system, libraries (though we are going to use modules instead of libraries for this plugin) will easily be able to use that same functionality to register for an event. Currently, within ES2.1, only 3 events are registered in 2 total libraries. Only 1 of those (player_disconnect) is a non-ES event.

Config changes could work the same way, especially if an addon was designed properly, and unloaded certain modules when configurations were changed.

I still think calling GetString, GetInt, etc is more explicit and is much better than the plugin "guessing" what type of value the addon wishes to be returned. I don't believe reading a .res file is the proper answer to that issue either.

Satoon


Honestly, the more I think about this, the more I agree. Essentially we'd have to make major changes to the event system in order to hide types. We'd have to parse through the .res file in order to put all the event variables in one data struct. I am starting to lean against this. You can still call getInt and getFloat and such on string types. The engine will do the proper conversion at runtime (as far as I know at least).

From a 30,000ft view, it looks like I need to expose a registerForEvent function that would allow python-eventname bindings. Then, when someone does es_load, I call a function in our core sp.py library. This library will import the addon via the import keyword (since the addons directory is already in the search path). The core library will then parse for decorators and call registerForEvent as it needs to.

Posted: Tue Jul 10, 2012 9:07 pm
by Ayuto
What's about a simple try-except clause for getting a variable and an isinstance check for setting one? I guess that wouldn't cost much ressources. Also, I agree that a registerForEvent function could be usefull :)

Posted: Tue Jul 10, 2012 9:18 pm
by your-name-here
Ayuto wrote:What's about a simple try-except clause for getting a variable and an isinstance check for setting one? I guess that wouldn't cost much ressources. Also, I agree that a registerForEvent function could be usefull :)


Again, that would require me to write tons of code to parse through the .res file. You cannot know the type of the event variable unless you manually look at the .res file. Neither C++ nor Python can get at the types without parsing the event file. There are 5 event files. Keep in mind that I have no way of knowing which event belongs to what file. So that means I have to parse through 5 files in the worst case.

Not worth it honestly Ayuto. I think you'll be fine with .GetInt and .GetString. It forces scripters to be mindful of the types of vars they are dealing with.

Posted: Tue Jul 10, 2012 11:59 pm
by satoon101
Ayuto wrote:What's about a simple try-except clause for getting a variable and an isinstance check for setting one? I guess that wouldn't cost much ressources. Also, I agree that a registerForEvent function could be usefull :)
And again, what if the try/except works but the variable is "supposed" to be a string (like the Event Variable "text" for player_say) but casting it to an integer or float works?

Also, setting an Event Variable "should" only be used when creating a new event. If 2 scripts are loaded that both use the same event, it would depend on the load order whether the changed value of an Event Variable would affect the other script. And, changing the Event Variable's value does not actually change anything except for the value of that particular variable.

Satoon

Posted: Wed Jul 11, 2012 6:30 am
by Ayuto
satoon101 wrote:And again, what if the try/except works but the variable is "supposed" to be a string (like the Event Variable "text" for player_say) but casting it to an integer or float works?
Yeah, I haven't thought about this situation.

satoon101 wrote:And, changing the Event Variable's value does not actually change anything except for the value of that particular variable.
Alright, and in some cases the value is used by any functions e.g. reason in player_disconnect for printing a meassage.

Posted: Sat Jul 14, 2012 1:54 am
by your-name-here
Ayuto wrote:Yeah, I haven't thought about this situation.

Alright, and in some cases the value is used by any functions e.g. reason in player_disconnect for printing a meassage.


Yes because sometimes the event is fired before the actual thing it signifies occurs :)
player_disconnect being one such case.

Posted: Sat Jul 14, 2012 5:36 pm
by satoon101
Ayuto wrote:Alright, and in some cases the value is used by any functions e.g. reason in player_disconnect for printing a meassage.
Not sure if you have tested this fully or not, but it doesn't seem true by my testing. If I change the 'reason' in the script, it still shows the original disconnect message when the player disconnects.

Satoon

Posted: Sun Jul 15, 2012 2:33 pm
by Ayuto
I can just tell you that it worked for me, but I will test it again, when I will find some time. ;)

Posted: Sun Jul 15, 2012 3:31 pm
by satoon101
I did not have a second client when I tested, so that is why I did not think it worked. Now that my backup account received the Beta, I can test locally with 2 clients.

It still shows up in the server's console with the correct reason, but shows other clients the new one. However, this behavior is very rare. The vast majority of the time this sort of thing will not work.

Satoon

Posted: Sun Jul 15, 2012 10:57 pm
by BackRaw
your-name-here wrote:Not worth it honestly Ayuto. I think you'll be fine with .GetInt and .GetString. It forces scripters to be mindful of the types of vars they are dealing with.
Which is good!

Posted: Fri Jul 20, 2012 7:08 am
by Chrisber
BackRaw wrote:Which is good!

...and bad at the same time. This design speaks against the - more or less - strict typing of python. It is against its nature and that makes me think about to solve this.

@ynh: I know it's a lot of work, but where's the problem to parse the resource files? I've did the same in NativeTools and it worked like a charm. With parsing them and putting information about events using a std::multimap, I do not see any problems to resolve fast lookup. (Any how, C++ speed can be neglected, since Python itself is very slow compared to.)

Posted: Fri Jul 20, 2012 4:47 pm
by BackRaw
Chrisber wrote:...and bad at the same time. This design speaks against the - more or less - strict typing of python. It is against its nature and that makes me think about to solve this.


Well, I meant that it's better than having a dict with pre-defined (string) variables...

Posted: Fri Jul 20, 2012 5:39 pm
by your-name-here
Chrisber wrote:...and bad at the same time. This design speaks against the - more or less - strict typing of python. It is against its nature and that makes me think about to solve this.

@ynh: I know it's a lot of work, but where's the problem to parse the resource files? I've did the same in NativeTools and it worked like a charm. With parsing them and putting information about events using a std::multimap, I do not see any problems to resolve fast lookup. (Any how, C++ speed can be neglected, since Python itself is very slow compared to.)


Again, I don't see the reason to do any of that. You're asking me to write tons of extra code to save people from typing out GetInt or GetFloat just because it doesn't agree with the philosophy of python. Remember what you're dealing with here: A Python wrapper around a C++ game engine. You're going to hit these issues everywhere (just take a look at user messages), not just events. I believe it is better to stick with GetInt/GetFloat and the like because tons of the engine structures use WriteInt/WriteFloat style functions. We'll remain consistent that way.