I'm getting a very weird symptom: a scenario map's on_configuration_changed does not run if loaded when its mod is missing, and it's got something to do with remote interfaces. I've included a fairly minimal reproducer, I'm posting here on the theory that I must be doing something wrong. The o-c-c function is called properly for istm any change that doesn't involve removing that interface.
function configuration_changed(ccdata)
print(serpent.block(ccdata or 'o-c-c from on-init'))
do local _=remote.interfaces.testocc or {}
global.use_testocc_ti = _.t_i or false
print(_.t_i or false)
end
end
function conditionalhooks()
if global.use_testocc_ti then
for x=1,#player do
remote.call('testocc','t_i'
,{player_index=x})
end
else
on('player_left_game')
end
end
for k,v in next,_G do npg[k]=true end
use_testocc_ti = {} -- placeholder
player={}
on('configuration_changed',configuration_changed)
on('load',function()
for k,v in next,global do
print('Global "'..k..'" restored')
_G[k]=v end
conditionalhooks()
end)
on('init',function(...)
for k,v in next,_G do if not npg[k] then
print('Global "'..k..'" persisted')
global[k]=v end end
configuration_changed()
-- don't know c-c changing the lua globals is ok so just reload from map globals
for k,v in next,global do _G[k]=v end
conditionalhooks()
end)
is perfectly clear what it's doing and anyone new to Factorio modding will immediately know what it does because that's how the official documentation says to do it.
Re: Why is on_configuration_changed not running?
Posted: Fri Feb 02, 2018 5:19 am
by quyxkh
... yah, I thought that might be a distraction, so I made and have attached a really minimalized test-case.
digression
To address your question, yes, the code you're quoting has no apparent justification, but (a) considering only what you've quoted is is considering only the downsides of a judgement call, for which the upside is twofold, but elsewhere:
(1) e.g. on('player_joined_game',x) has a near-zeroperfect signal-to-noise ratio, and syntax highlighting for literal strings makes it pop in my editor. Compare that to `script.on_event(defines.events.on_player_joined_game,x) which is utterly lousy with lard, s/n ratio well below half, and doesn't highlight.The highest possible value of that lard is to be a waste of time and attention that one must either presume or verify doesn't contain typos. Old-school references for more background on my revulsion for boilerplate would include Strunk&White. Perhaps the "new-school" version would be DRY.
(2) some hooks might need or profit from scaffolding or multiplexing. on('tick') in the scenario file is bare-bones. The on('tick') in the mod carries an optional context, so functions that need to set a 10-second one-shotcan just have a `mytimercontext={interval=600}` in the mod-globals context and in their code do `on('tick',mytimerpopfunc,mytimercontext)`, and `on('tick',nil,mytimercontext)` in the timer pop to remove it.. Damn-near-zero lard, no boilerplate, if I want to rework how multiple timers are managed or see what's up or light traces or tinker with intervals for anything or everything, it's all in one place.
and (b) ... yah, can we not sidetrack? See below.
I've attached a scenario-only mod, and a service mod that provides a remote-call interface. To reproduce what I'm looking at,
1. Run with only the test-o-c-c-scenario mod (and any others except the other attached one), and play and save the map with the test-o-c-c-scenario/test-o-c-c scenario. It prints messages to the console, those might be helpful.
2. Bang on mod presence/version changes (*including* the attached test-o-c-c-service) you want, you can see the scenario's o-c-c- runs fine.
3. Save the map after loading it with the test-o-c-c-service mod present. Make any changes you want except removing the test-o-c-c-service mod, this save's o-c-c still runs fine, you can see the serpent.block printout of the args on the console.
4. Reload the save from step 3 without the test-o-c-c-service mod.
There's the part I don't understand: loading fails with an error in on_load, but it appears on_configuration_changed never ran.
local use_test = {} -- overwritten by on_init/on_load
local playerdata = {}
local ename={} for k,v in next,defines.events do ename[v]=k end
function ccchanged(ev)
print(serpent.line{ename[ev.name],ev})
end
function conditional_hooks() -- final setup
if global.use_test then
remote.call('testocc','test',playerdata)
else
script.on_event(defines.events.on_player_cursor_stack_changed,ccchanged)
end
end
function configuration_changed(ccdata) -- pre-on_load for map in new mod env
print(serpent.block(ccdata or 'o-c-c from on-init'))
do local _=remote.interfaces.testocc or {}
global.use_test = _.test or false
print(serpent.line{map_global_use_test=global.use_test})
end
end
script.on_configuration_changed(configuration_changed)
function reload() -- prep local lua env from on_init and on_load, then setup engine
use_test = global.use_test
playerdata = global.playerdata
conditional_hooks()
print(serpent.line{'reloaded globals:',playerdata=playerdata,use_test=use_test})
end
script.on_init(function()
configuration_changed()
global.playerdata = playerdata
return reload()
end)
script.on_load(reload)
script.on_event(defines.events.on_player_joined_game,function(ev)
if not playerdata[ev.player_index] then
playerdata[ev.player_index]={}
end
end)
-- vim: set sw=4 sts=4 lbr wrap tw=78 :
is perfectly clear what it's doing and anyone new to Factorio modding will immediately know what it does because that's how the official documentation says to do it.
What if I want to call "on_init" twice? Is it possible to register every "on_init" calling?
Re: Why is on_configuration_changed not running?
Posted: Sun Feb 04, 2018 10:42 pm
by quyxkh
Well, the problem was that I somehow got it in my head that on_configuration_changed runs before on_load, which doesn't match any version of docs or reality that I can find now. on_configuration_changed runs after on_load.
is perfectly clear what it's doing and anyone new to Factorio modding will immediately know what it does because that's how the official documentation says to do it.
What if I want to call "on_init" twice? Is it possible to register every "on_init" calling?
I've tried that before, the second call over-writes the first. There can only be one on_init.
is perfectly clear what it's doing and anyone new to Factorio modding will immediately know what it does because that's how the official documentation says to do it.
What if I want to call "on_init" twice? Is it possible to register every "on_init" calling?
The accepted method is to register a single on_init stub that calls every on_init function you want called.