I have implemented something like a generic version of your callback_manager. I use it to send references to tables and functions via message (msg.post
will always clone the table argument you give it, and it can’t contain functions).
What most Defold users do is store state (tables, functions, values) inside modules in order to share it between scripts. I try to avoid that as much as possible, since module state is global, and I prefer to tie state lifetime to the lifetime of scripts to ease clean-up and resetting the game.
I also use callbacks instead of the message system for most things so that I can run callback code without delay.
This is what I do in code:
-- registry.lua --
-- This is my generic callback_manager.
M.counter = 0
M.entries = {}
function M.add(entry)
local id = M.counter + 1
M.counter = id
M.entries[id] = entry
return id
end
function M.remove(id)
local entry = M.entries[id]
M.entries[id] = nil
return entry
end
function M.get(id)
return M.entries[id]
end
-- main.script --
-- Here I create state that I want to share with via the registry.
local appstate = {
event_system = event_system.create(),
game_world = game_world.create(),
}
-- Add appstate to the registry and send its id to another script.
local appstate_id = registry.add(appstate)
msg.post('/game_presenter', 'start', {appstate_id = appstate_id})
-- Later on when I'm done with appstate, maybe in the final function, I remove it from registry.
registry.remove(appstate_id)
-- game_presenter.script --
-- The other script receives the id and retrieves the appstate.
function on_message(self, message_id, message)
if message_id == hash('start') then
self.appstate = registry.get(message.appstate_id)
-- Through appstate, I can now share state and invoke callbacks added to appstate.
self.appstate.event_system:add_callback('my_event_type', function(event) print(event) end)
self.appstate.event_system:send_event('my_event_type', {'my data table'})
-- There's nothing preventing me from adding functions to the registry instead of tables.
-- I do this in one place to get a callback from another script when its final function runs.
local func_id = registry.get(function(...) print(...) end)
registry.remove(func_id)("remove and call the callback")
end
end