Skip to content

Improve support for metatables in netgames

LJ Sonic requested to merge register-metatables into next

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.

Edited by LJ Sonic

Merge request reports