multi_events.lua bug with metatables
The multi_events script has a problem when registering an event to a metatable. When registering an event to an object, it embeds whatever event callbacks exist in its metatable at that time into the new callback. The problem is that any new callbacks registered with the metatable after that point are ignored.
Example
require"scripts/multi_events"
local sprite_meta = sol.main.get_metatable"sprite"
sprite_meta:register_event("on_direction_changed", function() print"meta1!" end)
local sprite = sol.sprite.create"hero/tunic1"
sprite:register_event("on_direction_changed", function() print"sprite1!" end)
sprite_meta:register_event("on_direction_changed", function() print"meta2!" end)
sprite:set_direction(2)
The expected behavior is to have "meta1", "meta2", and "sprite1" printed when the event is triggered.
The actual behavior is only "meta1" and "sprite1" are printed.
The way to fix the problem is to embed a function that gets the metatable callbacks (and calls them) at the time the event is called rather than to embed the metatable callbacks directly.
I modified the multi_events.lua script to fix the problem (here), but I'm having a problem getting the script to work on account of the safe_rawget()
function doesn't seem to work. I'm going to hold off on submitting the merge request on account of it not working properly.
The multi_events script has this safe_rawget()
function:
local function safe_rawget(object,key)
if type(object) == 'table' then
return rawget(object,key)
else
-- see if the object is a solarus userdata and perform the 'rawget'
local objtable = debug.getregistry()['sol.userdata_tables'][obj]
if objtable then
return objtable[key]
end
end
end
It has a typo where obj
should be object
, but even after making that change it still doesn't seem to work:
local sprite = sol.sprite.create"hero/tunic1"
function sprite:on_direction_changed() print"changed direction" end
print(safe_rawget(sprite,"on_direction_changed") or "not found")
--results in printing "not found"