Merge branch 'optimize-field-lookup' into 'next'

Optimize field lookups in Lua metatables

See merge request STJr/SRB2!2024
This commit is contained in:
sphere 2023-06-19 22:41:36 +00:00
commit f68006dbd3
9 changed files with 1597 additions and 537 deletions

View file

@ -566,27 +566,59 @@ static luaL_Reg lib[] = {
{NULL, NULL}
};
enum cvar_e
{
cvar_name,
cvar_defaultvalue,
cvar_flags,
cvar_value,
cvar_string,
cvar_changed,
};
static const char *const cvar_opt[] = {
"name",
"defaultvalue",
"flags",
"value",
"string",
"changed",
NULL,
};
static int cvar_fields_ref = LUA_NOREF;
static int cvar_get(lua_State *L)
{
consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR);
const char *field = luaL_checkstring(L, 2);
enum cvar_e field = Lua_optoption(L, 2, -1, cvar_fields_ref);
if(fastcmp(field,"name"))
switch (field)
{
case cvar_name:
lua_pushstring(L, cvar->name);
else if(fastcmp(field,"defaultvalue"))
break;
case cvar_defaultvalue:
lua_pushstring(L, cvar->defaultvalue);
else if(fastcmp(field,"flags"))
break;
case cvar_flags:
lua_pushinteger(L, cvar->flags);
else if(fastcmp(field,"value"))
break;
case cvar_value:
lua_pushinteger(L, cvar->value);
else if(fastcmp(field,"string"))
break;
case cvar_string:
lua_pushstring(L, cvar->string);
else if(fastcmp(field,"changed"))
break;
case cvar_changed:
lua_pushboolean(L, cvar->changed);
else if (devparm)
return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS, field);
else
return 0;
break;
default:
if (devparm)
return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS, field);
else
return 0;
}
return 1;
}
@ -598,6 +630,8 @@ int LUA_ConsoleLib(lua_State *L)
lua_setfield(L, -2, "__index");
lua_pop(L,1);
cvar_fields_ref = Lua_CreateFieldTable(L, cvar_opt);
// Set empty registry tables
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, "COM_Command");

View file

@ -95,6 +95,8 @@ static const char *const patch_opt[] = {
"topoffset",
NULL};
static int patch_fields_ref = LUA_NOREF;
// alignment types for v.drawString
enum align {
align_left = 0,
@ -196,6 +198,8 @@ static const char *const camera_opt[] = {
"momz",
NULL};
static int camera_fields_ref = LUA_NOREF;
static int lib_getHudInfo(lua_State *L)
{
UINT32 i;
@ -276,7 +280,7 @@ static int colormap_get(lua_State *L)
static int patch_get(lua_State *L)
{
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
enum patch field = luaL_checkoption(L, 2, NULL, patch_opt);
enum patch field = Lua_optoption(L, 2, -1, patch_fields_ref);
// patches are invalidated when switching renderers
if (!patch) {
@ -316,7 +320,7 @@ static int patch_set(lua_State *L)
static int camera_get(lua_State *L)
{
camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA));
enum cameraf field = luaL_checkoption(L, 2, NULL, camera_opt);
enum cameraf field = Lua_optoption(L, 2, -1, camera_fields_ref);
// cameras should always be valid unless I'm a nutter
I_Assert(cam != NULL);
@ -372,7 +376,7 @@ static int camera_get(lua_State *L)
static int camera_set(lua_State *L)
{
camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA));
enum cameraf field = luaL_checkoption(L, 2, NULL, camera_opt);
enum cameraf field = Lua_optoption(L, 2, -1, camera_fields_ref);
I_Assert(cam != NULL);
@ -1444,6 +1448,8 @@ int LUA_HudLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
patch_fields_ref = Lua_CreateFieldTable(L, patch_opt);
luaL_newmetatable(L, META_CAMERA);
lua_pushcfunction(L, camera_get);
lua_setfield(L, -2, "__index");
@ -1452,6 +1458,8 @@ int LUA_HudLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
camera_fields_ref = Lua_CreateFieldTable(L, camera_opt);
luaL_register(L, "hud", lib_hud);
return 0;
}

View file

@ -1106,75 +1106,161 @@ static int lib_mobjinfolen(lua_State *L)
return 1;
}
enum mobjinfo_e
{
mobjinfo_doomednum,
mobjinfo_spawnstate,
mobjinfo_spawnhealth,
mobjinfo_seestate,
mobjinfo_seesound,
mobjinfo_reactiontime,
mobjinfo_attacksound,
mobjinfo_painstate,
mobjinfo_painchance,
mobjinfo_painsound,
mobjinfo_meleestate,
mobjinfo_missilestate,
mobjinfo_deathstate,
mobjinfo_xdeathstate,
mobjinfo_deathsound,
mobjinfo_speed,
mobjinfo_radius,
mobjinfo_height,
mobjinfo_dispoffset,
mobjinfo_mass,
mobjinfo_damage,
mobjinfo_activesound,
mobjinfo_flags,
mobjinfo_raisestate,
};
const char *const mobjinfo_opt[] = {
"doomednum",
"spawnstate",
"spawnhealth",
"seestate",
"seesound",
"reactiontime",
"attacksound",
"painstate",
"painchance",
"painsound",
"meleestate",
"missilestate",
"deathstate",
"xdeathstate",
"deathsound",
"speed",
"radius",
"height",
"dispoffset",
"mass",
"damage",
"activesound",
"flags",
"raisestate",
NULL,
};
static int mobjinfo_fields_ref = LUA_NOREF;
// mobjinfo_t *, field -> number
static int mobjinfo_get(lua_State *L)
{
mobjinfo_t *info = *((mobjinfo_t **)luaL_checkudata(L, 1, META_MOBJINFO));
const char *field = luaL_checkstring(L, 2);
enum mobjinfo_e field = luaL_checkoption(L, 2, mobjinfo_opt[0], mobjinfo_opt);
I_Assert(info != NULL);
I_Assert(info >= mobjinfo);
if (fastcmp(field,"doomednum"))
switch (field)
{
case mobjinfo_doomednum:
lua_pushinteger(L, info->doomednum);
else if (fastcmp(field,"spawnstate"))
break;
case mobjinfo_spawnstate:
lua_pushinteger(L, info->spawnstate);
else if (fastcmp(field,"spawnhealth"))
break;
case mobjinfo_spawnhealth:
lua_pushinteger(L, info->spawnhealth);
else if (fastcmp(field,"seestate"))
break;
case mobjinfo_seestate:
lua_pushinteger(L, info->seestate);
else if (fastcmp(field,"seesound"))
break;
case mobjinfo_seesound:
lua_pushinteger(L, info->seesound);
else if (fastcmp(field,"reactiontime"))
break;
case mobjinfo_reactiontime:
lua_pushinteger(L, info->reactiontime);
else if (fastcmp(field,"attacksound"))
break;
case mobjinfo_attacksound:
lua_pushinteger(L, info->attacksound);
else if (fastcmp(field,"painstate"))
break;
case mobjinfo_painstate:
lua_pushinteger(L, info->painstate);
else if (fastcmp(field,"painchance"))
break;
case mobjinfo_painchance:
lua_pushinteger(L, info->painchance);
else if (fastcmp(field,"painsound"))
break;
case mobjinfo_painsound:
lua_pushinteger(L, info->painsound);
else if (fastcmp(field,"meleestate"))
break;
case mobjinfo_meleestate:
lua_pushinteger(L, info->meleestate);
else if (fastcmp(field,"missilestate"))
break;
case mobjinfo_missilestate:
lua_pushinteger(L, info->missilestate);
else if (fastcmp(field,"deathstate"))
break;
case mobjinfo_deathstate:
lua_pushinteger(L, info->deathstate);
else if (fastcmp(field,"xdeathstate"))
break;
case mobjinfo_xdeathstate:
lua_pushinteger(L, info->xdeathstate);
else if (fastcmp(field,"deathsound"))
break;
case mobjinfo_deathsound:
lua_pushinteger(L, info->deathsound);
else if (fastcmp(field,"speed"))
break;
case mobjinfo_speed:
lua_pushinteger(L, info->speed); // sometimes it's fixed_t, sometimes it's not...
else if (fastcmp(field,"radius"))
break;
case mobjinfo_radius:
lua_pushfixed(L, info->radius);
else if (fastcmp(field,"height"))
break;
case mobjinfo_height:
lua_pushfixed(L, info->height);
else if (fastcmp(field,"dispoffset"))
break;
case mobjinfo_dispoffset:
lua_pushinteger(L, info->dispoffset);
else if (fastcmp(field,"mass"))
break;
case mobjinfo_mass:
lua_pushinteger(L, info->mass);
else if (fastcmp(field,"damage"))
break;
case mobjinfo_damage:
lua_pushinteger(L, info->damage);
else if (fastcmp(field,"activesound"))
break;
case mobjinfo_activesound:
lua_pushinteger(L, info->activesound);
else if (fastcmp(field,"flags"))
break;
case mobjinfo_flags:
lua_pushinteger(L, info->flags);
else if (fastcmp(field,"raisestate"))
break;
case mobjinfo_raisestate:
lua_pushinteger(L, info->raisestate);
else {
break;
default:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, info);
lua_rawget(L, -2);
if (!lua_istable(L, -1)) { // no extra values table
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", field);
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", lua_tostring(L, 2));
return 0;
}
lua_getfield(L, -1, field);
lua_pushvalue(L, 2); // field name
lua_gettable(L, -2);
if (lua_isnil(L, -1)) // no value for this field
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", field);
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", lua_tostring(L, 2));
break;
}
return 1;
}
@ -1183,7 +1269,7 @@ static int mobjinfo_get(lua_State *L)
static int mobjinfo_set(lua_State *L)
{
mobjinfo_t *info = *((mobjinfo_t **)luaL_checkudata(L, 1, META_MOBJINFO));
const char *field = luaL_checkstring(L, 2);
enum mobjinfo_e field = Lua_optoption(L, 2, -1, mobjinfo_fields_ref);
if (hud_running)
return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!");
@ -1193,55 +1279,81 @@ static int mobjinfo_set(lua_State *L)
I_Assert(info != NULL);
I_Assert(info >= mobjinfo);
if (fastcmp(field,"doomednum"))
switch (field)
{
case mobjinfo_doomednum:
info->doomednum = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"spawnstate"))
break;
case mobjinfo_spawnstate:
info->spawnstate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"spawnhealth"))
break;
case mobjinfo_spawnhealth:
info->spawnhealth = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"seestate"))
break;
case mobjinfo_seestate:
info->seestate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"seesound"))
break;
case mobjinfo_seesound:
info->seesound = luaL_checkinteger(L, 3);
else if (fastcmp(field,"reactiontime"))
break;
case mobjinfo_reactiontime:
info->reactiontime = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"attacksound"))
break;
case mobjinfo_attacksound:
info->attacksound = luaL_checkinteger(L, 3);
else if (fastcmp(field,"painstate"))
break;
case mobjinfo_painstate:
info->painstate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"painchance"))
break;
case mobjinfo_painchance:
info->painchance = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"painsound"))
break;
case mobjinfo_painsound:
info->painsound = luaL_checkinteger(L, 3);
else if (fastcmp(field,"meleestate"))
break;
case mobjinfo_meleestate:
info->meleestate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"missilestate"))
break;
case mobjinfo_missilestate:
info->missilestate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"deathstate"))
break;
case mobjinfo_deathstate:
info->deathstate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"xdeathstate"))
break;
case mobjinfo_xdeathstate:
info->xdeathstate = luaL_checkinteger(L, 3);
else if (fastcmp(field,"deathsound"))
break;
case mobjinfo_deathsound:
info->deathsound = luaL_checkinteger(L, 3);
else if (fastcmp(field,"speed"))
break;
case mobjinfo_speed:
info->speed = luaL_checkfixed(L, 3);
else if (fastcmp(field,"radius"))
break;
case mobjinfo_radius:
info->radius = luaL_checkfixed(L, 3);
else if (fastcmp(field,"height"))
break;
case mobjinfo_height:
info->height = luaL_checkfixed(L, 3);
else if (fastcmp(field,"dispoffset"))
break;
case mobjinfo_dispoffset:
info->dispoffset = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"mass"))
break;
case mobjinfo_mass:
info->mass = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"damage"))
break;
case mobjinfo_damage:
info->damage = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"activesound"))
break;
case mobjinfo_activesound:
info->activesound = luaL_checkinteger(L, 3);
else if (fastcmp(field,"flags"))
break;
case mobjinfo_flags:
info->flags = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"raisestate"))
break;
case mobjinfo_raisestate:
info->raisestate = luaL_checkinteger(L, 3);
else {
break;
default:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, info);
@ -1249,18 +1361,17 @@ static int mobjinfo_set(lua_State *L)
if (lua_isnil(L, -1)) {
// This index doesn't have a table for extra values yet, let's make one.
lua_pop(L, 1);
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "mobjinfo_t", field);
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "mobjinfo_t", lua_tostring(L, 2));
lua_newtable(L);
lua_pushlightuserdata(L, info);
lua_pushvalue(L, -2); // ext value table
lua_rawset(L, -4); // LREG_EXTVARS table
}
lua_pushvalue(L, 2); // key
lua_pushvalue(L, 3); // value to store
lua_setfield(L, -2, field);
lua_settable(L, -3);
lua_pop(L, 2);
}
//else
//return luaL_error(L, LUA_QL("mobjinfo_t") " has no field named " LUA_QS, field);
return 0;
}
@ -1788,6 +1899,8 @@ int LUA_InfoLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
mobjinfo_fields_ref = Lua_CreateFieldTable(L, mobjinfo_opt);
luaL_newmetatable(L, META_SKINCOLOR);
lua_pushcfunction(L, skincolor_get);
lua_setfield(L, -2, "__index");

View file

@ -88,6 +88,8 @@ static const char *const sector_opt[] = {
"gravity",
NULL};
static int sector_fields_ref = LUA_NOREF;
enum subsector_e {
subsector_valid = 0,
subsector_sector,
@ -104,6 +106,8 @@ static const char *const subsector_opt[] = {
"polyList",
NULL};
static int subsector_fields_ref = LUA_NOREF;
enum line_e {
line_valid = 0,
line_v1,
@ -156,6 +160,8 @@ static const char *const line_opt[] = {
"callcount",
NULL};
static int line_fields_ref = LUA_NOREF;
enum side_e {
side_valid = 0,
side_textureoffset,
@ -184,6 +190,8 @@ static const char *const side_opt[] = {
"text",
NULL};
static int side_fields_ref = LUA_NOREF;
enum vertex_e {
vertex_valid = 0,
vertex_x,
@ -204,6 +212,8 @@ static const char *const vertex_opt[] = {
"ceilingzset",
NULL};
static int vertex_fields_ref = LUA_NOREF;
enum ffloor_e {
ffloor_valid = 0,
ffloor_topheight,
@ -256,6 +266,8 @@ static const char *const ffloor_opt[] = {
"bouncestrength",
NULL};
static int ffloor_fields_ref = LUA_NOREF;
#ifdef HAVE_LUA_SEGS
enum seg_e {
seg_valid = 0,
@ -285,6 +297,8 @@ static const char *const seg_opt[] = {
"polyseg",
NULL};
static int seg_fields_ref = LUA_NOREF;
enum node_e {
node_valid = 0,
node_x,
@ -305,6 +319,8 @@ static const char *const node_opt[] = {
"children",
NULL};
static int node_fields_ref = LUA_NOREF;
enum nodechild_e {
nodechild_valid = 0,
nodechild_right,
@ -356,6 +372,8 @@ static const char *const slope_opt[] = {
"flags",
NULL};
static int slope_fields_ref = LUA_NOREF;
// shared by both vector2_t and vector3_t
enum vector_e {
vector_x = 0,
@ -575,7 +593,7 @@ static int sectorlines_num(lua_State *L)
static int sector_get(lua_State *L)
{
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
enum sector_e field = Lua_optoption(L, 2, sector_valid, sector_fields_ref);
INT16 i;
if (!sector)
@ -697,7 +715,7 @@ static int sector_get(lua_State *L)
static int sector_set(lua_State *L)
{
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
enum sector_e field = Lua_optoption(L, 2, sector_valid, sector_fields_ref);
if (!sector)
return luaL_error(L, "accessed sector_t doesn't exist anymore.");
@ -814,7 +832,7 @@ static int sector_num(lua_State *L)
static int subsector_get(lua_State *L)
{
subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR));
enum subsector_e field = luaL_checkoption(L, 2, subsector_opt[0], subsector_opt);
enum subsector_e field = Lua_optoption(L, 2, subsector_valid, subsector_fields_ref);
if (!subsector)
{
@ -898,7 +916,7 @@ static int linestringargs_len(lua_State *L)
static int line_get(lua_State *L)
{
line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE));
enum line_e field = luaL_checkoption(L, 2, line_opt[0], line_opt);
enum line_e field = Lua_optoption(L, 2, line_valid, line_fields_ref);
if (!line)
{
@ -1057,7 +1075,7 @@ static int sidenum_get(lua_State *L)
static int side_get(lua_State *L)
{
side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt);
enum side_e field = Lua_optoption(L, 2, side_valid, side_fields_ref);
if (!side)
{
@ -1110,7 +1128,7 @@ static int side_get(lua_State *L)
static int side_set(lua_State *L)
{
side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt);
enum side_e field = Lua_optoption(L, 2, side_valid, side_fields_ref);
if (!side)
{
@ -1166,7 +1184,7 @@ static int side_num(lua_State *L)
static int vertex_get(lua_State *L)
{
vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX));
enum vertex_e field = luaL_checkoption(L, 2, vertex_opt[0], vertex_opt);
enum vertex_e field = Lua_optoption(L, 2, vertex_valid, vertex_fields_ref);
if (!vertex)
{
@ -1220,7 +1238,7 @@ static int vertex_num(lua_State *L)
static int seg_get(lua_State *L)
{
seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
enum seg_e field = luaL_checkoption(L, 2, seg_opt[0], seg_opt);
enum seg_e field = Lua_optoption(L, 2, seg_valid, seg_fields_ref);
if (!seg)
{
@ -1284,7 +1302,7 @@ static int seg_num(lua_State *L)
static int node_get(lua_State *L)
{
node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE));
enum node_e field = luaL_checkoption(L, 2, node_opt[0], node_opt);
enum node_e field = Lua_optoption(L, 2, node_valid, node_fields_ref);
if (!node)
{
@ -1920,7 +1938,7 @@ static INT32 P_GetOldFOFFlags(ffloor_t *fflr)
static int ffloor_get(lua_State *L)
{
ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt);
enum ffloor_e field = Lua_optoption(L, 2, ffloor_valid, ffloor_fields_ref);
INT16 i;
if (!ffloor)
@ -2102,7 +2120,7 @@ static void P_SetOldFOFFlags(ffloor_t *fflr, oldffloortype_e oldflags)
static int ffloor_set(lua_State *L)
{
ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt);
enum ffloor_e field = Lua_optoption(L, 2, ffloor_valid, ffloor_fields_ref);
if (!ffloor)
return luaL_error(L, "accessed ffloor_t doesn't exist anymore.");
@ -2197,7 +2215,7 @@ static int ffloor_set(lua_State *L)
static int slope_get(lua_State *L)
{
pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt);
enum slope_e field = Lua_optoption(L, 2, slope_valid, slope_fields_ref);
if (!slope)
{
@ -2241,7 +2259,7 @@ static int slope_get(lua_State *L)
static int slope_set(lua_State *L)
{
pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE));
enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt);
enum slope_e field = Lua_optoption(L, 2, slope_valid, slope_fields_ref);
if (!slope)
return luaL_error(L, "accessed pslope_t doesn't exist anymore.");
@ -2405,110 +2423,258 @@ static int lib_nummapheaders(lua_State *L)
// mapheader_t //
/////////////////
enum mapheaderinfo_e
{
mapheaderinfo_lvlttl,
mapheaderinfo_subttl,
mapheaderinfo_actnum,
mapheaderinfo_typeoflevel,
mapheaderinfo_nextlevel,
mapheaderinfo_marathonnext,
mapheaderinfo_keywords,
mapheaderinfo_musname,
mapheaderinfo_mustrack,
mapheaderinfo_muspos,
mapheaderinfo_musinterfadeout,
mapheaderinfo_musintername,
mapheaderinfo_muspostbossname,
mapheaderinfo_muspostbosstrack,
mapheaderinfo_muspostbosspos,
mapheaderinfo_muspostbossfadein,
mapheaderinfo_musforcereset,
mapheaderinfo_forcecharacter,
mapheaderinfo_weather,
mapheaderinfo_skynum,
mapheaderinfo_skybox_scalex,
mapheaderinfo_skybox_scaley,
mapheaderinfo_skybox_scalez,
mapheaderinfo_interscreen,
mapheaderinfo_runsoc,
mapheaderinfo_scriptname,
mapheaderinfo_precutscenenum,
mapheaderinfo_cutscenenum,
mapheaderinfo_countdown,
mapheaderinfo_palette,
mapheaderinfo_numlaps,
mapheaderinfo_unlockrequired,
mapheaderinfo_levelselect,
mapheaderinfo_bonustype,
mapheaderinfo_ltzzpatch,
mapheaderinfo_ltzztext,
mapheaderinfo_ltactdiamond,
mapheaderinfo_maxbonuslives,
mapheaderinfo_levelflags,
mapheaderinfo_menuflags,
mapheaderinfo_selectheading,
mapheaderinfo_startrings,
mapheaderinfo_sstimer,
mapheaderinfo_ssspheres,
mapheaderinfo_gravity,
};
static const char *const mapheaderinfo_opt[] = {
"lvlttl",
"subttl",
"actnum",
"typeoflevel",
"nextlevel",
"marathonnext",
"keywords",
"musname",
"mustrack",
"muspos",
"musinterfadeout",
"musintername",
"muspostbossname",
"muspostbosstrack",
"muspostbosspos",
"muspostbossfadein",
"musforcereset",
"forcecharacter",
"weather",
"skynum",
"skybox_scalex",
"skybox_scaley",
"skybox_scalez",
"interscreen",
"runsoc",
"scriptname",
"precutscenenum",
"cutscenenum",
"countdown",
"palette",
"numlaps",
"unlockrequired",
"levelselect",
"bonustype",
"ltzzpatch",
"ltzztext",
"ltactdiamond",
"maxbonuslives",
"levelflags",
"menuflags",
"selectheading",
"startrings",
"sstimer",
"ssspheres",
"gravity",
NULL,
};
static int mapheaderinfo_fields_ref = LUA_NOREF;
static int mapheaderinfo_get(lua_State *L)
{
mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER));
const char *field = luaL_checkstring(L, 2);
enum mapheaderinfo_e field = Lua_optoption(L, 2, -1, mapheaderinfo_fields_ref);
INT16 i;
if (fastcmp(field,"lvlttl"))
switch (field)
{
case mapheaderinfo_lvlttl:
lua_pushstring(L, header->lvlttl);
else if (fastcmp(field,"subttl"))
break;
case mapheaderinfo_subttl:
lua_pushstring(L, header->subttl);
else if (fastcmp(field,"actnum"))
break;
case mapheaderinfo_actnum:
lua_pushinteger(L, header->actnum);
else if (fastcmp(field,"typeoflevel"))
break;
case mapheaderinfo_typeoflevel:
lua_pushinteger(L, header->typeoflevel);
else if (fastcmp(field,"nextlevel"))
break;
case mapheaderinfo_nextlevel:
lua_pushinteger(L, header->nextlevel);
else if (fastcmp(field,"marathonnext"))
break;
case mapheaderinfo_marathonnext:
lua_pushinteger(L, header->marathonnext);
else if (fastcmp(field,"keywords"))
break;
case mapheaderinfo_keywords:
lua_pushstring(L, header->keywords);
else if (fastcmp(field,"musname"))
break;
case mapheaderinfo_musname:
lua_pushstring(L, header->musname);
else if (fastcmp(field,"mustrack"))
break;
case mapheaderinfo_mustrack:
lua_pushinteger(L, header->mustrack);
else if (fastcmp(field,"muspos"))
break;
case mapheaderinfo_muspos:
lua_pushinteger(L, header->muspos);
else if (fastcmp(field,"musinterfadeout"))
break;
case mapheaderinfo_musinterfadeout:
lua_pushinteger(L, header->musinterfadeout);
else if (fastcmp(field,"musintername"))
break;
case mapheaderinfo_musintername:
lua_pushstring(L, header->musintername);
else if (fastcmp(field,"muspostbossname"))
break;
case mapheaderinfo_muspostbossname:
lua_pushstring(L, header->muspostbossname);
else if (fastcmp(field,"muspostbosstrack"))
break;
case mapheaderinfo_muspostbosstrack:
lua_pushinteger(L, header->muspostbosstrack);
else if (fastcmp(field,"muspostbosspos"))
break;
case mapheaderinfo_muspostbosspos:
lua_pushinteger(L, header->muspostbosspos);
else if (fastcmp(field,"muspostbossfadein"))
break;
case mapheaderinfo_muspostbossfadein:
lua_pushinteger(L, header->muspostbossfadein);
else if (fastcmp(field,"musforcereset"))
break;
case mapheaderinfo_musforcereset:
lua_pushinteger(L, header->musforcereset);
else if (fastcmp(field,"forcecharacter"))
break;
case mapheaderinfo_forcecharacter:
lua_pushstring(L, header->forcecharacter);
else if (fastcmp(field,"weather"))
break;
case mapheaderinfo_weather:
lua_pushinteger(L, header->weather);
else if (fastcmp(field,"skynum"))
break;
case mapheaderinfo_skynum:
lua_pushinteger(L, header->skynum);
else if (fastcmp(field,"skybox_scalex"))
break;
case mapheaderinfo_skybox_scalex:
lua_pushinteger(L, header->skybox_scalex);
else if (fastcmp(field,"skybox_scaley"))
break;
case mapheaderinfo_skybox_scaley:
lua_pushinteger(L, header->skybox_scaley);
else if (fastcmp(field,"skybox_scalez"))
break;
case mapheaderinfo_skybox_scalez:
lua_pushinteger(L, header->skybox_scalez);
else if (fastcmp(field,"interscreen")) {
break;
case mapheaderinfo_interscreen:
for (i = 0; i < 8; i++)
if (!header->interscreen[i])
break;
lua_pushlstring(L, header->interscreen, i);
} else if (fastcmp(field,"runsoc"))
break;
case mapheaderinfo_runsoc:
lua_pushstring(L, header->runsoc);
else if (fastcmp(field,"scriptname"))
break;
case mapheaderinfo_scriptname:
lua_pushstring(L, header->scriptname);
else if (fastcmp(field,"precutscenenum"))
break;
case mapheaderinfo_precutscenenum:
lua_pushinteger(L, header->precutscenenum);
else if (fastcmp(field,"cutscenenum"))
break;
case mapheaderinfo_cutscenenum:
lua_pushinteger(L, header->cutscenenum);
else if (fastcmp(field,"countdown"))
break;
case mapheaderinfo_countdown:
lua_pushinteger(L, header->countdown);
else if (fastcmp(field,"palette"))
break;
case mapheaderinfo_palette:
lua_pushinteger(L, header->palette);
else if (fastcmp(field,"numlaps"))
break;
case mapheaderinfo_numlaps:
lua_pushinteger(L, header->numlaps);
else if (fastcmp(field,"unlockrequired"))
break;
case mapheaderinfo_unlockrequired:
lua_pushinteger(L, header->unlockrequired);
else if (fastcmp(field,"levelselect"))
break;
case mapheaderinfo_levelselect:
lua_pushinteger(L, header->levelselect);
else if (fastcmp(field,"bonustype"))
break;
case mapheaderinfo_bonustype:
lua_pushinteger(L, header->bonustype);
else if (fastcmp(field,"ltzzpatch"))
break;
case mapheaderinfo_ltzzpatch:
lua_pushstring(L, header->ltzzpatch);
else if (fastcmp(field,"ltzztext"))
break;
case mapheaderinfo_ltzztext:
lua_pushstring(L, header->ltzztext);
else if (fastcmp(field,"ltactdiamond"))
break;
case mapheaderinfo_ltactdiamond:
lua_pushstring(L, header->ltactdiamond);
else if (fastcmp(field,"maxbonuslives"))
break;
case mapheaderinfo_maxbonuslives:
lua_pushinteger(L, header->maxbonuslives);
else if (fastcmp(field,"levelflags"))
break;
case mapheaderinfo_levelflags:
lua_pushinteger(L, header->levelflags);
else if (fastcmp(field,"menuflags"))
break;
case mapheaderinfo_menuflags:
lua_pushinteger(L, header->menuflags);
else if (fastcmp(field,"selectheading"))
break;
case mapheaderinfo_selectheading:
lua_pushstring(L, header->selectheading);
else if (fastcmp(field,"startrings"))
break;
case mapheaderinfo_startrings:
lua_pushinteger(L, header->startrings);
else if (fastcmp(field, "sstimer"))
break;
case mapheaderinfo_sstimer:
lua_pushinteger(L, header->sstimer);
else if (fastcmp(field, "ssspheres"))
break;
case mapheaderinfo_ssspheres:
lua_pushinteger(L, header->ssspheres);
else if (fastcmp(field, "gravity"))
break;
case mapheaderinfo_gravity:
lua_pushfixed(L, header->gravity);
break;
// TODO add support for reading numGradedMares and grades
else {
default:
// Read custom vars now
// (note: don't include the "LUA." in your lua scripts!)
UINT8 j = 0;
for (;j < header->numCustomOptions && !fastcmp(field, header->customopts[j].option); ++j);
for (;j < header->numCustomOptions && !fastcmp(lua_tostring(L, 2), header->customopts[j].option); ++j);
if(j < header->numCustomOptions)
lua_pushstring(L, header->customopts[j].value);
@ -2539,6 +2705,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
sector_fields_ref = Lua_CreateFieldTable(L, sector_opt);
luaL_newmetatable(L, META_SUBSECTOR);
lua_pushcfunction(L, subsector_get);
lua_setfield(L, -2, "__index");
@ -2547,6 +2715,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
subsector_fields_ref = Lua_CreateFieldTable(L, subsector_opt);
luaL_newmetatable(L, META_LINE);
lua_pushcfunction(L, line_get);
lua_setfield(L, -2, "__index");
@ -2555,6 +2725,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
line_fields_ref = Lua_CreateFieldTable(L, line_opt);
luaL_newmetatable(L, META_LINEARGS);
lua_pushcfunction(L, lineargs_get);
lua_setfield(L, -2, "__index");
@ -2587,6 +2759,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
side_fields_ref = Lua_CreateFieldTable(L, side_opt);
luaL_newmetatable(L, META_VERTEX);
lua_pushcfunction(L, vertex_get);
lua_setfield(L, -2, "__index");
@ -2595,6 +2769,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
vertex_fields_ref = Lua_CreateFieldTable(L, vertex_opt);
luaL_newmetatable(L, META_FFLOOR);
lua_pushcfunction(L, ffloor_get);
lua_setfield(L, -2, "__index");
@ -2603,6 +2779,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L, 1);
ffloor_fields_ref = Lua_CreateFieldTable(L, ffloor_opt);
#ifdef HAVE_LUA_SEGS
luaL_newmetatable(L, META_SEG);
lua_pushcfunction(L, seg_get);
@ -2612,6 +2790,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
seg_fields_ref = Lua_CreateFieldTable(L, seg_opt);
luaL_newmetatable(L, META_NODE);
lua_pushcfunction(L, node_get);
lua_setfield(L, -2, "__index");
@ -2620,6 +2800,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
node_fields_ref = Lua_CreateFieldTable(L, node_opt);
luaL_newmetatable(L, META_NODEBBOX);
//lua_pushcfunction(L, nodebbox_get);
//lua_setfield(L, -2, "__index");
@ -2646,6 +2828,8 @@ int LUA_MapLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L, 1);
slope_fields_ref = Lua_CreateFieldTable(L, slope_opt);
luaL_newmetatable(L, META_VECTOR2);
lua_pushcfunction(L, vector2_get);
lua_setfield(L, -2, "__index");
@ -2664,6 +2848,8 @@ int LUA_MapLib(lua_State *L)
//lua_setfield(L, -2, "__len");
lua_pop(L, 1);
mapheaderinfo_fields_ref = Lua_CreateFieldTable(L, mapheaderinfo_opt);
LUA_PushTaggableObjectArray(L, "sectors",
lib_iterateSectors,
lib_getSector,

View file

@ -179,10 +179,12 @@ static const char *const mobj_opt[] = {
#define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
static int mobj_fields_ref = LUA_NOREF;
static int mobj_get(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
enum mobj_e field = Lua_optoption(L, 2, NULL, mobj_opt);
enum mobj_e field = Lua_optoption(L, 2, -1, mobj_fields_ref);
lua_settop(L, 2);
if (!mo || !ISINLEVEL) {
@ -467,7 +469,7 @@ static int mobj_get(lua_State *L)
static int mobj_set(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
enum mobj_e field = Lua_optoption(L, 2, mobj_opt[0], mobj_opt);
enum mobj_e field = Lua_optoption(L, 2, mobj_valid, mobj_fields_ref);
lua_settop(L, 3);
INLEVEL
@ -876,14 +878,55 @@ static int thingstringargs_len(lua_State *L)
return 1;
}
enum mapthing_e {
mapthing_valid = 0,
mapthing_x,
mapthing_y,
mapthing_angle,
mapthing_pitch,
mapthing_roll,
mapthing_type,
mapthing_options,
mapthing_scale,
mapthing_z,
mapthing_extrainfo,
mapthing_tag,
mapthing_taglist,
mapthing_args,
mapthing_stringargs,
mapthing_mobj,
};
const char *const mapthing_opt[] = {
"valid",
"x",
"y",
"angle",
"pitch",
"roll",
"type",
"options",
"scale",
"z",
"extrainfo",
"tag",
"taglist",
"args",
"stringargs",
"mobj",
NULL,
};
static int mapthing_fields_ref = LUA_NOREF;
static int mapthing_get(lua_State *L)
{
mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING));
const char *field = luaL_checkstring(L, 2);
lua_Integer number;
enum mapthing_e field = Lua_optoption(L, 2, -1, mapthing_fields_ref);
lua_settop(L, 2);
if (!mt) {
if (fastcmp(field,"valid")) {
if (field == mapthing_valid) {
lua_pushboolean(L, false);
return 1;
}
@ -892,62 +935,71 @@ static int mapthing_get(lua_State *L)
return 0;
}
if (fastcmp(field,"valid")) {
lua_pushboolean(L, true);
return 1;
} else if(fastcmp(field,"x"))
number = mt->x;
else if(fastcmp(field,"y"))
number = mt->y;
else if(fastcmp(field,"angle"))
number = mt->angle;
else if(fastcmp(field,"pitch"))
number = mt->pitch;
else if(fastcmp(field,"roll"))
number = mt->roll;
else if(fastcmp(field,"type"))
number = mt->type;
else if(fastcmp(field,"options"))
number = mt->options;
else if(fastcmp(field,"scale"))
number = mt->scale;
else if(fastcmp(field,"z"))
number = mt->z;
else if(fastcmp(field,"extrainfo"))
number = mt->extrainfo;
else if(fastcmp(field,"tag"))
number = Tag_FGet(&mt->tags);
else if(fastcmp(field,"taglist"))
switch (field)
{
LUA_PushUserdata(L, &mt->tags, META_TAGLIST);
return 1;
case mapthing_valid:
lua_pushboolean(L, true);
break;
case mapthing_x:
lua_pushinteger(L, mt->x);
break;
case mapthing_y:
lua_pushinteger(L, mt->y);
break;
case mapthing_angle:
lua_pushinteger(L, mt->angle);
break;
case mapthing_pitch:
lua_pushinteger(L, mt->pitch);
break;
case mapthing_roll:
lua_pushinteger(L, mt->roll);
break;
case mapthing_type:
lua_pushinteger(L, mt->type);
break;
case mapthing_options:
lua_pushinteger(L, mt->options);
break;
case mapthing_scale:
lua_pushinteger(L, mt->scale);
break;
case mapthing_z:
lua_pushinteger(L, mt->z);
break;
case mapthing_extrainfo:
lua_pushinteger(L, mt->extrainfo);
break;
case mapthing_tag:
lua_pushinteger(L, Tag_FGet(&mt->tags));
break;
case mapthing_taglist:
LUA_PushUserdata(L, &mt->tags, META_TAGLIST);
break;
case mapthing_args:
LUA_PushUserdata(L, mt->args, META_THINGARGS);
break;
case mapthing_stringargs:
LUA_PushUserdata(L, mt->stringargs, META_THINGSTRINGARGS);
break;
case mapthing_mobj:
LUA_PushUserdata(L, mt->mobj, META_MOBJ);
break;
default:
if (devparm)
return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field);
else
return 0;
}
else if(fastcmp(field,"args"))
{
LUA_PushUserdata(L, mt->args, META_THINGARGS);
return 1;
}
else if(fastcmp(field,"stringargs"))
{
LUA_PushUserdata(L, mt->stringargs, META_THINGSTRINGARGS);
return 1;
}
else if(fastcmp(field,"mobj")) {
LUA_PushUserdata(L, mt->mobj, META_MOBJ);
return 1;
} else if (devparm)
return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field);
else
return 0;
lua_pushinteger(L, number);
return 1;
}
static int mapthing_set(lua_State *L)
{
mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING));
const char *field = luaL_checkstring(L, 2);
enum mapthing_e field = Lua_optoption(L, 2, -1, mapthing_fields_ref);
lua_settop(L, 3);
if (!mt)
return luaL_error(L, "accessed mapthing_t doesn't exist anymore.");
@ -957,39 +1009,52 @@ static int mapthing_set(lua_State *L)
if (hook_cmd_running)
return luaL_error(L, "Do not alter mapthing_t in CMD building code!");
if(fastcmp(field,"x"))
mt->x = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"y"))
mt->y = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"angle"))
mt->angle = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"pitch"))
mt->pitch = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"roll"))
mt->roll = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"type"))
mt->type = (UINT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"options"))
mt->options = (UINT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"scale"))
mt->scale = luaL_checkfixed(L, 3);
else if(fastcmp(field,"z"))
mt->z = (INT16)luaL_checkinteger(L, 3);
else if(fastcmp(field,"extrainfo"))
switch (field)
{
INT32 extrainfo = luaL_checkinteger(L, 3);
if (extrainfo & ~15)
return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15);
mt->extrainfo = (UINT8)extrainfo;
case mapthing_x:
mt->x = (INT16)luaL_checkinteger(L, 3);
break;
case mapthing_y:
mt->y = (INT16)luaL_checkinteger(L, 3);
break;
case mapthing_angle:
mt->angle = (INT16)luaL_checkinteger(L, 3);
break;
case mapthing_pitch:
mt->pitch = (INT16)luaL_checkinteger(L, 3);
break;
case mapthing_roll:
mt->roll = (INT16)luaL_checkinteger(L, 3);
break;
case mapthing_type:
mt->type = (UINT16)luaL_checkinteger(L, 3);
break;
case mapthing_options:
mt->options = (UINT16)luaL_checkinteger(L, 3);
break;
case mapthing_scale:
mt->scale = luaL_checkfixed(L, 3);
break;
case mapthing_z:
mt->z = (INT16)luaL_checkinteger(L, 3);
break;
case mapthing_extrainfo:
INT32 extrainfo = luaL_checkinteger(L, 3);
if (extrainfo & ~15)
return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15);
mt->extrainfo = (UINT8)extrainfo;
break;
case mapthing_tag:
Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3));
break;
case mapthing_taglist:
return LUA_ErrSetDirectly(L, "mapthing_t", "taglist");
case mapthing_mobj:
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
break;
default:
return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field);
}
else if (fastcmp(field,"tag"))
Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3));
else if (fastcmp(field,"taglist"))
return LUA_ErrSetDirectly(L, "mapthing_t", "taglist");
else if(fastcmp(field,"mobj"))
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
else
return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field);
return 0;
}
@ -1051,6 +1116,8 @@ int LUA_MobjLib(lua_State *L)
lua_setfield(L, -2, "__newindex");
lua_pop(L,1);
mobj_fields_ref = Lua_CreateFieldTable(L, mobj_opt);
luaL_newmetatable(L, META_THINGARGS);
lua_pushcfunction(L, thingargs_get);
lua_setfield(L, -2, "__index");
@ -1078,6 +1145,8 @@ int LUA_MobjLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L,1);
mapthing_fields_ref = Lua_CreateFieldTable(L, mapthing_opt);
LUA_PushTaggableObjectArray(L, "mapthings",
lib_iterateMapthings,
lib_getMapthing,

File diff suppressed because it is too large Load diff

View file

@ -1729,17 +1729,39 @@ void LUA_UnArchive(void)
}
// For mobj_t, player_t, etc. to take custom variables.
int Lua_optoption(lua_State *L, int narg,
const char *def, const char *const lst[])
int Lua_optoption(lua_State *L, int narg, int def, int list_ref)
{
const char *name = (def) ? luaL_optstring(L, narg, def) : luaL_checkstring(L, narg);
int i;
for (i=0; lst[i]; i++)
if (fastcmp(lst[i], name))
return i;
if (lua_isnoneornil(L, narg))
return def;
I_Assert(lua_checkstack(L, 2));
luaL_checkstring(L, narg);
lua_rawgeti(L, LUA_REGISTRYINDEX, list_ref);
I_Assert(lua_istable(L, -1));
lua_pushvalue(L, narg);
lua_rawget(L, -2);
if (lua_isnumber(L, -1))
return lua_tointeger(L, -1);
return -1;
}
int Lua_CreateFieldTable(lua_State *L, const char *const lst[])
{
int i;
lua_newtable(L);
for (i = 0; lst[i] != NULL; i++)
{
lua_pushstring(L, lst[i]);
lua_pushinteger(L, i);
lua_settable(L, -3);
}
return luaL_ref(L, LUA_REGISTRYINDEX);
}
void LUA_PushTaggableObjectArray
( lua_State *L,
const char *field,

View file

@ -57,8 +57,8 @@ int LUA_PushGlobals(lua_State *L, const char *word);
int LUA_CheckGlobals(lua_State *L, const char *word);
void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c
void LUA_CVarChanged(void *cvar); // lua_consolelib.c
int Lua_optoption(lua_State *L, int narg,
const char *def, const char *const lst[]);
int Lua_optoption(lua_State *L, int narg, int def, int list_ref);
int Lua_CreateFieldTable(lua_State *L, const char *const lst[]);
void LUA_HookNetArchive(lua_CFunction archFunc);
void LUA_PushTaggableObjectArray

View file

@ -55,6 +55,7 @@ enum skin {
skin_soundsid,
skin_sprites
};
static const char *const skin_opt[] = {
"valid",
"name",
@ -95,10 +96,12 @@ static const char *const skin_opt[] = {
#define UNIMPLEMENTED luaL_error(L, LUA_QL("skin_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", skin_opt[field])
static int skin_fields_ref = LUA_NOREF;
static int skin_get(lua_State *L)
{
skin_t *skin = *((skin_t **)luaL_checkudata(L, 1, META_SKIN));
enum skin field = luaL_checkoption(L, 2, NULL, skin_opt);
enum skin field = Lua_optoption(L, 2, -1, skin_fields_ref);
// skins are always valid, only added, never removed
I_Assert(skin != NULL);
@ -376,6 +379,8 @@ int LUA_SkinLib(lua_State *L)
lua_setfield(L, -2, "__len");
lua_pop(L,1);
skin_fields_ref = Lua_CreateFieldTable(L, skin_opt);
luaL_newmetatable(L, META_SOUNDSID);
lua_pushcfunction(L, soundsid_get);
lua_setfield(L, -2, "__index");