I’m experiencing a somewhat more nuanced problem right now, but I think this is general good modding information.
Specifically in my case, on initialization my view is calling a Lua call handler which requests a datastore from my service. If that datastore doesn’t exist yet, it creates it and gives it data based on saved variables. However, apparently one of the functions in my Lua service is nil at the time that this is initially called when I launch the game, resulting in an engine error! Other functions aren’t nil, and when I hop in the Lua console and check the function in question, it’s not nil.
That doesn’t sound Call handlers are require()d when you call a function, so they are guaranteed to be fully evaluated. If you’re using some other service that isn’t ready yet, you should listen to the appropriate events on the Lua side and resolve the response asynchronously.
Services are loaded in order, and stonehearth ones will load first. Each service has its own initialization logic, but most initialize synchronously. Can you show the specific issue?
function ObligationTrackerCallHandler:get_obligation_monitor(session, response)
local obligation_monitor = obligation_tracker.obligation_tracker:get_obligation_monitor(session.player_id)
response:resolve({ obligation_monitor = obligation_monitor })
end
When my Ember view is created, it calls that get_obligation_monitor function. These are some functions in my service:
function ObligationTrackerService:_get_player_sv(player_id)
if not self._sv.player_data[player_id] then
local data = {}
data.timers = {
consumables = {}, -- { buff_uri = { time_started, duration } }
trading_stalls = {} -- { specific_uri = { time_started, duration } }
}
data.auto_use = {}
self._sv.player_data[player_id] = data
end
return self._sv.player_data[player_id]
end
function ObligationTrackerService:get_obligation_monitor(player_id)
if not self.obligation_monitor[player_id] then
local data = radiant.create_datastore()
self.obligation_monitor[player_id] = data
self._set_obligation_monitor_data(player_id)
end
return self.obligation_monitor[player_id]
end
function ObligationTrackerService:_set_obligation_monitor_data(player_id, player_data)
if not self._get_player_sv then
radiant.log.write('obligationtracker', 0, 'Why is self._get_player_sv nil?!?')
end
if not player_data then
player_data = self:_get_player_sv(player_id)
end
-- first prune defunct timers from the table
self:_prune_defunct_timers(player_data)
self:get_obligation_monitor(player_id):set_data({timers = player_data.timers, auto_use = player_data.auto_use})
self.__saved_variables:mark_changed()
end
When the call handler is run, that radiant.log.write call is made, meaning (as far as I can tell) that at the time of the calling, the service is only partially initialized. Which is odd, because my server init script is normal, and obligation_tracker['obligation_tracker'] is not getting set until after it’s created and initialized, just like all other services.
I figured it out. >< Notice anything wrong with this call?
self._set_obligation_monitor_data(player_id)
Yeah, I used . instead of :, so self wasn’t defined (or was defined as the player_id string) within the scope of that call of _set_obligation_monitor_data. Sorry to bother you about something so silly.