mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-29 12:40:58 +00:00
Merge branch 'register-metatables' into 'next'
Improve support for metatables in netgames See merge request STJr/SRB2!1224
This commit is contained in:
commit
097f204ceb
3 changed files with 95 additions and 1 deletions
|
@ -246,6 +246,56 @@ static int lib_userdataType(lua_State *L)
|
||||||
return luaL_typerror(L, 1, "userdata");
|
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 UINT16 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);
|
||||||
|
|
||||||
|
if (nextid == 0)
|
||||||
|
return luaL_error(L, "Too many metatables registered?! Please consider rewriting your script once you are sober again.\n");
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes a string as only argument and returns the metatable
|
||||||
|
// associated to the userdata type this string refers to
|
||||||
|
// Returns nil if the string does not refer to a valid userdata type
|
||||||
|
static int lib_userdataMetatable(lua_State *L)
|
||||||
|
{
|
||||||
|
UINT32 i;
|
||||||
|
const char *udname = luaL_checkstring(L, 1);
|
||||||
|
|
||||||
|
// Find internal metatable name
|
||||||
|
for (i = 0; meta2utype[i].meta; i++)
|
||||||
|
if (!strcmp(udname, meta2utype[i].utype))
|
||||||
|
{
|
||||||
|
luaL_getmetatable(L, meta2utype[i].meta);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int lib_isPlayerAdmin(lua_State *L)
|
static int lib_isPlayerAdmin(lua_State *L)
|
||||||
{
|
{
|
||||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||||
|
@ -3494,6 +3544,8 @@ static luaL_Reg lib[] = {
|
||||||
{"chatprint", lib_chatprint},
|
{"chatprint", lib_chatprint},
|
||||||
{"chatprintf", lib_chatprintf},
|
{"chatprintf", lib_chatprintf},
|
||||||
{"userdataType", lib_userdataType},
|
{"userdataType", lib_userdataType},
|
||||||
|
{"registerMetatable", lib_registerMetatable},
|
||||||
|
{"userdataMetatable", lib_userdataMetatable},
|
||||||
{"IsPlayerAdmin", lib_isPlayerAdmin},
|
{"IsPlayerAdmin", lib_isPlayerAdmin},
|
||||||
{"reserveLuabanks", lib_reserveLuabanks},
|
{"reserveLuabanks", lib_reserveLuabanks},
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ extern lua_State *gL;
|
||||||
#define LREG_EXTVARS "LUA_VARS"
|
#define LREG_EXTVARS "LUA_VARS"
|
||||||
#define LREG_STATEACTION "STATE_ACTION"
|
#define LREG_STATEACTION "STATE_ACTION"
|
||||||
#define LREG_ACTIONS "MOBJ_ACTION"
|
#define LREG_ACTIONS "MOBJ_ACTION"
|
||||||
|
#define LREG_METATABLES "METATABLES"
|
||||||
|
|
||||||
#define META_STATE "STATE_T*"
|
#define META_STATE "STATE_T*"
|
||||||
#define META_MOBJINFO "MOBJINFO_T*"
|
#define META_MOBJINFO "MOBJINFO_T*"
|
||||||
|
|
|
@ -443,6 +443,10 @@ static void LUA_ClearState(void)
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
lua_setfield(L, LUA_REGISTRYINDEX, LREG_VALID);
|
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
|
// open srb2 libraries
|
||||||
for(i = 0; liblist[i]; i++) {
|
for(i = 0; liblist[i]; i++) {
|
||||||
lua_pushcfunction(L, liblist[i]);
|
lua_pushcfunction(L, liblist[i]);
|
||||||
|
@ -980,8 +984,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
|
||||||
lua_pop(gL, 1);
|
lua_pop(gL, 1);
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
|
{
|
||||||
t++;
|
t++;
|
||||||
|
|
||||||
|
if (t == 0)
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_ERROR, "Too many tables to archive!\n");
|
||||||
|
WRITEUINT8(save_p, ARCH_NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WRITEUINT8(save_p, ARCH_TABLE);
|
WRITEUINT8(save_p, ARCH_TABLE);
|
||||||
WRITEUINT16(save_p, t);
|
WRITEUINT16(save_p, t);
|
||||||
|
|
||||||
|
@ -1294,8 +1307,22 @@ static void ArchiveTables(void)
|
||||||
|
|
||||||
lua_pop(gL, 1);
|
lua_pop(gL, 1);
|
||||||
}
|
}
|
||||||
lua_pop(gL, 1);
|
|
||||||
WRITEUINT8(save_p, ARCH_TEND);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1466,6 +1493,7 @@ static void UnArchiveTables(void)
|
||||||
{
|
{
|
||||||
int TABLESINDEX;
|
int TABLESINDEX;
|
||||||
UINT16 i, n;
|
UINT16 i, n;
|
||||||
|
UINT16 metatableid;
|
||||||
|
|
||||||
if (!gL)
|
if (!gL)
|
||||||
return;
|
return;
|
||||||
|
@ -1490,6 +1518,19 @@ static void UnArchiveTables(void)
|
||||||
else
|
else
|
||||||
lua_rawset(gL, -3);
|
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);
|
lua_pop(gL, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue