helix
helix copied to clipboard
Fix item instance's metatable object reference is not updated when gamemode refreshed.
Summary
table.Merge
function's merging is if element is table, replacing table's element.
function table.Merge( dest, source )
for k, v in pairs( source ) do
if ( istable( v ) && istable( dest[ k ] ) ) then
-- don't overwrite one table with another
-- instead merge them recurisvely
table.Merge( dest[ k ], v )
else
dest[ k ] = v
end
end
return dest
end
Unfortunately, table.Merge
function is not include metatable object case. (metatable is kind of table.) This means that the metatable reference of the table's metatable object does not change, only the value of the object changes.
Therefore, the following problem occurs when the gamemode is refreshed.
for _, v in pairs(ix.item.instances) do
if (v.uniqueID == uniqueID) then
table.Merge(v, ITEM);
-- It will be trigger assertion failure.
assert(getmetatable(v.somemetatableobject) == getmetatable(ITEM.somemetatableobject));
end
end
This code is part of sh_item.lua.
Changes
A new table merge function (ix.util.MetatableSafeTableMerge
) with exception handling for metatable objects has been added to the ix.util table and replaced the table.Merge function in sh_item.lua.
Alternative
New hooks for item table
Add an "OnGamemodeReloaded" hook (or similar) to give the items table responsibility for updating metatable objects. This make problem of having to implement code to update object refresh in item table code when using metatable objects.
Edit the document
Just write 'if metatable object in the field of the item table, the object's metatable reference will not change when gamemode refresh.' to the documentation. This is the easiest and fastest way.
i am in love
~~Could you not just make a local function instead of rewriting/overwriting table.Merge?~~
Nvm, you've changed it since.