Change registered function for event handler

Place to get help with not working mods / modding interface.
Post Reply
FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 1207
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Change registered function for event handler

Post by FuryoftheStars »

Is it ok to change which function is registered for a particular event based on a setting? And to do it like below?

Code: Select all

if settings.startup["treesaplingsredux_upsfriendlyplanters"].value then
    script.on_event(defines.events.on_tick, onTick_NoLoopPlanters)
else
    script.on_event(defines.events.on_tick, onTick)
end
Basically, I want to avoid wrapping the loop I want to skip with an if clause that will then have to fire every tick. I realize the actual UPS cost would be near minimal, but I'd still rather not do it if there's another way.

robot256
Filter Inserter
Filter Inserter
Posts: 436
Joined: Sun Mar 17, 2019 1:52 am
Contact:

Re: Change registered function for event handler

Post by robot256 »

As long as your code goes in on_init and on_load, (and on_configuration_changed if you are paranoid), then it will work just fine. There are more nuances if you want to change event registrations based on runtime settings or global variables, but that can be done as well.

FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 1207
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Re: Change registered function for event handler

Post by FuryoftheStars »

So, putting it on the same level as where all the other events are registered won't work?

Code: Select all

script.on_init(Init)
script.on_configuration_changed(ConfigChanged)
script.on_event(defines.events.on_built_entity, BuiltEntity)
script.on_event(defines.events.on_player_mined_entity, MinedEntity)
script.on_event(defines.events.on_robot_built_entity, BuiltEntity)
script.on_event(defines.events.on_robot_mined_entity, MinedEntity)
script.on_event(defines.events.on_entity_died, MinedEntity)
script.on_event(defines.events.script_raised_built, ScriptBuiltEntity)
script.on_event(defines.events.script_raised_revive, ScriptBuiltEntity)
if settings.startup["treesaplingsredux_upsfriendlyplanters"].value then
    script.on_event(defines.events.on_tick, onTick_NoLoopPlanters)
else
    script.on_event(defines.events.on_tick, onTick)
end
It's a startup setting, so the game must be completely restarted to change it.

FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 1207
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Re: Change registered function for event handler

Post by FuryoftheStars »

Ok, sorry, I didn't expect to get to test this tonight, but I just did.

I put log statements into my two functions (onTick and onTick_NoLoopingPlanters) and from my very fast test, it does appear to work.

Started a new game with the setting as false, log has printouts for the onTick function. Saved, exited to main menu, changed the setting to true, restarted and loaded the save, log now has printouts for the onTick_NoLoopingPlanters function.

Hopefully there aren't other potential hidden issues in there....

robot256
Filter Inserter
Filter Inserter
Posts: 436
Joined: Sun Mar 17, 2019 1:52 am
Contact:

Re: Change registered function for event handler

Post by robot256 »

Yes, that will be fine because startup settings never change. They will run in box 1 of the diagram instead of boxes 2 and 4 (on_init and on_load). https://lua-api.factorio.com/latest/Data-Lifecycle.html

Pi-C
Smart Inserter
Smart Inserter
Posts: 1276
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Change registered function for event handler

Post by Pi-C »

FuryoftheStars wrote:
Thu May 05, 2022 2:28 am
Is it ok to change which function is registered for a particular event based on a setting?
Yes, you can assign another function (or nil to stop listening to an event). However, you must do this when the game is loading (this can be before on_load) or within an event. Also, something like this is possible:

Code: Select all

script.on_event(defines.events.on_entity_died, function(event)
  if event.entity.name == x  then
      script.on_event(defines.events.on_tick, function(event)
          game.print(event.tick)
      end)
  end
end)
while this is forbidden:

Code: Select all

script.on_event(defines.events.on_tick, function(event)
  if event.tick == 10000 then
      script.on_event(defines. events.on_tick, nil)
  end
end)
In other words: Don't disable an event handler while its running, but only from other events!

If you want to (un)register events conditionally, make sure to use a variable stored like global.x to determine the condition, not a local variable! While this would work in single player, you'll get desyncs in multiplayer mode if you try that.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

robot256
Filter Inserter
Filter Inserter
Posts: 436
Joined: Sun Mar 17, 2019 1:52 am
Contact:

Re: Change registered function for event handler

Post by robot256 »

Eh, I've had good results disabling on_tick from working on_tick, but like you said, the global table has to say exactly whether it is on or off and another event has to turn it back on.

Post Reply

Return to “Modding help”