Event System in STDLIB

Place to get help with not working mods / modding interface.
kiba
Filter Inserter
Filter Inserter
Posts: 344
Joined: Thu Jun 11, 2015 5:32 am
Contact:

Event System in STDLIB

Post by kiba »

I am trying to make use of the stdlib by Afforess, but I have no idea how to use its event system.

I discussed this on the stdlib's thread but nobody responded.

Code: Select all


function test()
  print("test")
end

Gui.Event.register (defines.events.on_player_armor_inventory_changed, "top", test)
Looking through the stdlib's source code, I am not clear on how the game check for events being pinged? Though Gui.Event.dispatch?

Supercheese
Filter Inserter
Filter Inserter
Posts: 841
Joined: Mon Sep 14, 2015 7:40 am
Contact:

Re: Event System in STDLIB

Post by Supercheese »

From what I can tell, the StdLib forms a list of all events, and assigns them each only a single function, initially just a null function that does nothing. When you call register() on that event, your code gets added to that event-function, and will run each time the event fires. In this fashion, you could have multiple functions that are independently registered and de-registered from an event -- so maybe sometimes you want this part of on_tick to run, so you register it, then later you want another part, so you register that, but later you de-register the first bit, so it stops running while the second bit still goes. It's a bit tricky at times, but can be helpful for performance under certain circumstances.

EDIT: Also, you call register() with only two arguments, not three. See: http://afforess.github.io/Factorio-Stdl ... Event.html

kiba
Filter Inserter
Filter Inserter
Posts: 344
Joined: Thu Jun 11, 2015 5:32 am
Contact:

Re: Event System in STDLIB

Post by kiba »

Supercheese wrote:From what I can tell, the StdLib forms a list of all events, and assigns them each only a single function, initially just a null function that does nothing. When you call register() on that event, your code gets added to that event-function, and will run each time the event fires. In this fashion, you could have multiple functions that are independently registered and de-registered from an event -- so maybe sometimes you want this part of on_tick to run, so you register it, then later you want another part, so you register that, but later you de-register the first bit, so it stops running while the second bit still goes. It's a bit tricky at times, but can be helpful for performance under certain circumstances.

EDIT: Also, you call register() with only two arguments, not three. See: http://afforess.github.io/Factorio-Stdl ... Event.html
So I can only have one event handler active at any given time?

Edit: I am looking at the GUI stuff, not the event stuff. That's why there's three.

Choumiko
Smart Inserter
Smart Inserter
Posts: 1352
Joined: Fri Mar 21, 2014 10:51 pm
Contact:

Re: Event System in STDLIB

Post by Choumiko »

kiba wrote: Gui.Event.register (defines.events.on_player_armor_inventory_changed, "top", test)
[/code]
This looks more like a mix between the gui events and the others.
For non gui events it is

Code: Select all

Event.register(defines.events.on_player_armor_inventory_changed, test)
Event.register lets you register mutliple functions for a single event and let's you remove them individually, as Supercheese described

Haven't used the GUI events from stdlib yet, but

Code: Select all

Gui.on_click("button_name", test) --(Gui.on_click is short for Gui.Event.register(defines.events.on_gui_click, test)
should call the function if a gui element named button_name is clicked

Gui.Event.register() can have multiple patterns assigned per event, but only one handler/function per pattern. (I might be wrong about this, didn't write the Gui.Event)

kiba
Filter Inserter
Filter Inserter
Posts: 344
Joined: Thu Jun 11, 2015 5:32 am
Contact:

Re: Event System in STDLIB

Post by kiba »

Choumiko wrote:
kiba wrote: Gui.Event.register (defines.events.on_player_armor_inventory_changed, "top", test)
[/code]
This looks more like a mix between the gui events and the others.
For non gui events it is

Code: Select all

Event.register(defines.events.on_player_armor_inventory_changed, test)
Event.register lets you register mutliple functions for a single event and let's you remove them individually, as Supercheese described

Haven't used the GUI events from stdlib yet, but

Code: Select all

Gui.on_click("button_name", test) --(Gui.on_click is short for Gui.Event.register(defines.events.on_gui_click, test)
should call the function if a gui element named button_name is clicked

Gui.Event.register() can have multiple patterns assigned per event, but only one handler/function per pattern. (I might be wrong about this, didn't write the Gui.Event)
Ah, my problem is trying to register "gui.top" rather than creating an element for it, before I could register it toward a GUI element?

Choumiko
Smart Inserter
Smart Inserter
Posts: 1352
Joined: Fri Mar 21, 2014 10:51 pm
Contact:

Re: Event System in STDLIB

Post by Choumiko »

kiba wrote:Ah, my problem is trying to register "gui.top" rather than creating an element for it, before I could register it toward a GUI element?
I'm not sure what you want to achieve, but if by gui.top you mean e.g. game.players[1].gui.top then it should look like

Code: Select all

Gui.on_click("top", test)
This should call test() when you click the frame top (if that is even firing an event/can be clicked)

You can register any kind of string as a pattern, the element doesn't have to exist at time of registration.

User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: Event System in STDLIB

Post by aubergine18 »

If I understand correctly, the main GUI areas (top, left, center) are just flows and thus won't generate any gui click events. You'd have to have a button, checkbox or some other event-generating gui element in there and listen for that being clicked.
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

kiba
Filter Inserter
Filter Inserter
Posts: 344
Joined: Thu Jun 11, 2015 5:32 am
Contact:

Re: Event System in STDLIB

Post by kiba »

I simplified the code, but I still haven't figure out why it isn't working or triggering.

Code: Select all

function test()
  LOG.log("asdf_asdf")
  LOG.write()
  print("test")
end

Event.register (defines.events.on_player_armor_inventory_changed, test)

Nexela
Smart Inserter
Smart Inserter
Posts: 1828
Joined: Wed May 25, 2016 11:09 am
Contact:

Re: Event System in STDLIB

Post by Nexela »

I use the events system all over without a problem. not sure why your example isn't working.

Code: Select all

Event=require("stdlib.event.event")

local function do_once_tick(event)
  for _, player in pairs(game.players) do
    player.print("Once")
  end
  Event.remove(defines.events.on_tick, do_once_tick)
end
Event.register(defines.events.on_tick, do_once_tick)

Rseding91
Factorio Staff
Factorio Staff
Posts: 12282
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Event System in STDLIB

Post by Rseding91 »

Just wondering, what's the advantage to aliasing script.on_event(...)?

To me, it seems like it's just going to obscure the code so someone else doesn't understand what's happening compared to just registering the events directly. It will also be ever so slightly slower because it has to do more function calls.
If you want to get ahold of me I'm almost always on Discord.

Rseding91
Factorio Staff
Factorio Staff
Posts: 12282
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Event System in STDLIB

Post by Rseding91 »

Nexela wrote:I use the events system all over without a problem. not sure why your example isn't working.

Code: Select all

Event=require("stdlib.event.event")

local function do_once_tick(event)
  for _, player in pairs(game.players) do
    player.print("Once")
  end
  Event.remove(defines.events.on_tick, do_once_tick)
end
Event.register(defines.events.on_tick, do_once_tick)
Also there's no way this is MP safe since it would end up running every time someone connected/loaded a game.
If you want to get ahold of me I'm almost always on Discord.

Nexela
Smart Inserter
Smart Inserter
Posts: 1828
Joined: Wed May 25, 2016 11:09 am
Contact:

Re: Event System in STDLIB

Post by Nexela »

That was example code :p

Rseding91
Factorio Staff
Factorio Staff
Posts: 12282
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Event System in STDLIB

Post by Rseding91 »

Nexela wrote:That was example code :p
Sure, but any such "fire once" system isn't going to be save-load stable since you can't save/load closures and it isn't going to fire that event until the next tick.

If you tell it "fire on next tick" and then the game is saved and exited that same tick it won't happen.
If you want to get ahold of me I'm almost always on Discord.

kiba
Filter Inserter
Filter Inserter
Posts: 344
Joined: Thu Jun 11, 2015 5:32 am
Contact:

Re: Event System in STDLIB

Post by kiba »

Rseding91 wrote:Just wondering, what's the advantage to aliasing script.on_event(...)?

To me, it seems like it's just going to obscure the code so someone else doesn't understand what's happening compared to just registering the events directly. It will also be ever so slightly slower because it has to do more function calls.
I am not exactly sure myself. Supposedly, the advantage of using Afforess' stdlib is that I don't have to do so much gruntwork.

From what I peeked, it seems that there's a lot of code that do things but I don't know what exactly it do.

User avatar
Afforess
Filter Inserter
Filter Inserter
Posts: 422
Joined: Tue May 05, 2015 6:07 pm
Contact:

Re: Event System in STDLIB

Post by Afforess »

Rseding91 wrote:Just wondering, what's the advantage to aliasing script.on_event(...)?

To me, it seems like it's just going to obscure the code so someone else doesn't understand what's happening compared to just registering the events directly. It will also be ever so slightly slower because it has to do more function calls.
Main advantage is multiple handlers per event, and ability to deregister by handler, as well as built-in error handling.

Sorry about the slow response, hopefully you've figured things out by now Kiba.

Rseding91
Factorio Staff
Factorio Staff
Posts: 12282
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Event System in STDLIB

Post by Rseding91 »

Afforess wrote:
Rseding91 wrote:Just wondering, what's the advantage to aliasing script.on_event(...)?

To me, it seems like it's just going to obscure the code so someone else doesn't understand what's happening compared to just registering the events directly. It will also be ever so slightly slower because it has to do more function calls.
Main advantage is multiple handlers per event, and ability to deregister by handler, as well as built-in error handling.

Sorry about the slow response, hopefully you've figured things out by now Kiba.
How are the event handlers persisted through save-load? And if not, how are the order of the registered events maintained if mods have to re-register on_load?
If you want to get ahold of me I'm almost always on Discord.

User avatar
Afforess
Filter Inserter
Filter Inserter
Posts: 422
Joined: Tue May 05, 2015 6:07 pm
Contact:

Re: Event System in STDLIB

Post by Afforess »

Rseding91 wrote: How are the event handlers persisted through save-load? And if not, how are the order of the registered events maintained if mods have to re-register on_load?
They aren't, persisting closures is complex and generally not useful. The order is deterministic because event handlers are registered when the lua files are loaded, exactly how the script.on_event handlers are registered now. The Stdlib handlers just wrap those handlers with a table to allow multiple registration.

If it makes it more clear, stdlib event handlers *are* just wrappers. You can do a strict find-and-replace in a text editor, and replace script.on_event with Event.register, and your code will work exactly like before.

Rseding91
Factorio Staff
Factorio Staff
Posts: 12282
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Event System in STDLIB

Post by Rseding91 »

Afforess wrote:
Rseding91 wrote: How are the event handlers persisted through save-load? And if not, how are the order of the registered events maintained if mods have to re-register on_load?
They aren't, persisting closures is complex and generally not useful. The order is deterministic because event handlers are registered when the lua files are loaded, exactly how the script.on_event handlers are registered now. The Stdlib handlers just wrap those handlers with a table to allow multiple registration.

If it makes it more clear, stdlib event handlers *are* just wrappers. You can do a strict find-and-replace in a text editor, and replace script.on_event with Event.register, and your code will work exactly like before.
That's assuming people use it like that. Some register event handlers conditionally. For example: runtime the player builds something and that activates the on_tick handler for say 30 seconds and then it turns off again.

Not sure if anyone does that with this library system but it's just something to think about :)
If you want to get ahold of me I'm almost always on Discord.

User avatar
Afforess
Filter Inserter
Filter Inserter
Posts: 422
Joined: Tue May 05, 2015 6:07 pm
Contact:

Re: Event System in STDLIB

Post by Afforess »

Rseding91 wrote:
Afforess wrote:
Rseding91 wrote: How are the event handlers persisted through save-load? And if not, how are the order of the registered events maintained if mods have to re-register on_load?
They aren't, persisting closures is complex and generally not useful. The order is deterministic because event handlers are registered when the lua files are loaded, exactly how the script.on_event handlers are registered now. The Stdlib handlers just wrap those handlers with a table to allow multiple registration.

If it makes it more clear, stdlib event handlers *are* just wrappers. You can do a strict find-and-replace in a text editor, and replace script.on_event with Event.register, and your code will work exactly like before.
That's assuming people use it like that. Some register event handlers conditionally. For example: runtime the player builds something and that activates the on_tick handler for say 30 seconds and then it turns off again.

Not sure if anyone does that with this library system but it's just something to think about :)
As long as the events are registered in a deterministic fashion (register on_tick after an assembler is created for 30s), and it occurs on all hosts, there is no problem, right? I believe the problem would be when a mod registers handlers based on the state of local variables or something else not deterministic.

Rseding91
Factorio Staff
Factorio Staff
Posts: 12282
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Event System in STDLIB

Post by Rseding91 »

Afforess wrote:As long as the events are registered in a deterministic fashion (register on_tick after an assembler is created for 30s), and it occurs on all hosts, there is no problem, right? I believe the problem would be when a mod registers handlers based on the state of local variables or something else not deterministic.

Say they register on_tick and then you save and exit the game. On_load they re-register to keep the handler valid but now it's in a different order.
If you want to get ahold of me I'm almost always on Discord.

Post Reply

Return to “Modding help”