Improve support for metatables in netgames
This adds two metatable-related functions to Lua:
-
registerMetatable(table metatable)
:Currently, tables passed through
NetVars
hooks or stored in custom player/mobj fields will not keep their metatable, because SRB2 does not keep track of them by default.This issue can be solved by calling this function during script loading to have SRB2 register the given metatable, in such a way that tables/userdata this metatable is attached to (via
setmetatable()
) will not lose their metatable when sent to a client connecting to the server.SRB2 accomplishes this by remembering the address of the metatable and associating a numeric ID to it (
UINT16
currently). During gamestate archiving, the server writes this ID next to every table archived; during unarchiving, the client reads that ID, retrieves the associated metatable from the list of registered metatables, and finally attaches the metatable back (compare this to using mobjtype to retrieve mobjinfo).Please note that this function must be called on the metatable, right after it is created (or at least before it is used), not on the tables that you call
setmetatable
on. It is perfectly fine to have many tables attached to the same metatable (that's the way metatables are normally used). -
table userdataMetatable(string userdataName)
:With this, you can easily access the metatable attached to each different type of userdata provided by SRB2.
The name given as argument is the one
userdataType
would return for that userdata. For instance, this code retrieves the metatable used by allplayer_t
objects:local mt = userdataMetatable("player_t")
I'm not going to delve into details, but basically all objects of the same type (player, mobj, state, sector, etc.) share a unique metatable, created by SRB2, that defines a number of metamethods. Of particular interest are
__index
and__newindex
, which define all the fields (player.lives
,mobj.x
, etc.) Lua scripts have access to.
Note that technically, both functions can be partially worked around by using certain hacks, but they are very unpractical and only work in very specific situations.