mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-30 05:00:46 +00:00
Let Lua scripts relink tables to their metatables when unarchiving
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.
This commit is contained in:
parent
304e4bb1f9
commit
121c7da809
3 changed files with 62 additions and 1 deletions
|
@ -238,6 +238,33 @@ static int lib_userdataType(lua_State *L)
|
|||
return luaL_typerror(L, 1, "userdata");
|
||||
}
|
||||
|
||||
// Takes a metatable as first and only argument
|
||||
// Only callable during script loading
|
||||
static int lib_registermetatable(lua_State *L)
|
||||
{
|
||||
static UINT32 nextid = 1;
|
||||
|
||||
if (!lua_lumploading)
|
||||
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_METATABLES); // 2
|
||||
// registry.metatables[metatable] = nextid
|
||||
lua_pushvalue(L, 1); // 3
|
||||
lua_pushnumber(L, nextid); // 4
|
||||
lua_settable(L, 2);
|
||||
|
||||
// registry.metatables[nextid] = metatable
|
||||
lua_pushnumber(L, nextid); // 3
|
||||
lua_pushvalue(L, 1); // 4
|
||||
lua_settable(L, 2);
|
||||
lua_pop(L, 1);
|
||||
|
||||
nextid++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_isPlayerAdmin(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
|
@ -3433,6 +3460,7 @@ static luaL_Reg lib[] = {
|
|||
{"chatprint", lib_chatprint},
|
||||
{"chatprintf", lib_chatprintf},
|
||||
{"userdataType", lib_userdataType},
|
||||
{"registermetatable", lib_registermetatable},
|
||||
{"IsPlayerAdmin", lib_isPlayerAdmin},
|
||||
{"reserveLuabanks", lib_reserveLuabanks},
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ extern lua_State *gL;
|
|||
#define LREG_EXTVARS "LUA_VARS"
|
||||
#define LREG_STATEACTION "STATE_ACTION"
|
||||
#define LREG_ACTIONS "MOBJ_ACTION"
|
||||
#define LREG_METATABLES "METATABLES"
|
||||
|
||||
#define META_STATE "STATE_T*"
|
||||
#define META_MOBJINFO "MOBJINFO_T*"
|
||||
|
|
|
@ -437,6 +437,10 @@ static void LUA_ClearState(void)
|
|||
lua_newtable(L);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, LREG_VALID);
|
||||
|
||||
// make LREG_METATABLES table for all registered metatables
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, LREG_METATABLES);
|
||||
|
||||
// open srb2 libraries
|
||||
for(i = 0; liblist[i]; i++) {
|
||||
lua_pushcfunction(L, liblist[i]);
|
||||
|
@ -1269,8 +1273,22 @@ static void ArchiveTables(void)
|
|||
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
lua_pop(gL, 1);
|
||||
WRITEUINT8(save_p, ARCH_TEND);
|
||||
|
||||
// Write metatable ID
|
||||
if (lua_getmetatable(gL, -1))
|
||||
{
|
||||
// registry.metatables[metatable]
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
|
||||
lua_pushvalue(gL, -2);
|
||||
lua_gettable(gL, -2);
|
||||
WRITEUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1));
|
||||
lua_pop(gL, 3);
|
||||
}
|
||||
else
|
||||
WRITEUINT16(save_p, 0);
|
||||
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1438,6 +1456,7 @@ static void UnArchiveTables(void)
|
|||
{
|
||||
int TABLESINDEX;
|
||||
UINT16 i, n;
|
||||
UINT16 metatableid;
|
||||
|
||||
if (!gL)
|
||||
return;
|
||||
|
@ -1462,6 +1481,19 @@ static void UnArchiveTables(void)
|
|||
else
|
||||
lua_rawset(gL, -3);
|
||||
}
|
||||
|
||||
metatableid = READUINT16(save_p);
|
||||
if (metatableid)
|
||||
{
|
||||
// setmetatable(table, registry.metatables[metatableid])
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
|
||||
lua_rawgeti(gL, -1, metatableid);
|
||||
if (lua_isnil(gL, -1))
|
||||
I_Error("Unknown metatable ID %d\n", metatableid);
|
||||
lua_setmetatable(gL, -3);
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue