Improve support for metatables in netgames
- Nov 08, 2020
- Oct 30, 2020
-
-
LJ Sonic authored1155d875
-
f943f247
-
- Oct 03, 2020
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 all player_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.
This is done through the new "registermetatable" function, in a somewhat similar fashion to "freeslot" but for metatables: it must be called at script load to tell SRB2 your metatable can be automatically relinked during the unarchiving process.