Page 1 of 1

Change registered function for event handler

Posted: Thu May 05, 2022 2:28 am
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.

Re: Change registered function for event handler

Posted: Thu May 05, 2022 3:21 am
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.

Re: Change registered function for event handler

Posted: Thu May 05, 2022 3:54 am
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.

Re: Change registered function for event handler

Posted: Thu May 05, 2022 4:18 am
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....

Re: Change registered function for event handler

Posted: Thu May 05, 2022 5:00 am
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

Re: Change registered function for event handler

Posted: Thu May 05, 2022 5:23 am
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.

Re: Change registered function for event handler

Posted: Thu May 05, 2022 12:01 pm
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.