diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 7d9cd67ec..ad1df2b22 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -580,27 +580,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; } @@ -612,6 +644,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"); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index bc56e6688..0af7f2c36 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -106,6 +106,8 @@ static const char *const hudhook_opt[] = { "vote", NULL}; +static int patch_fields_ref = LUA_NOREF; + // alignment types for v.drawString enum align { align_left = 0, @@ -229,6 +231,8 @@ static const char *const hud_drawinfo_options[] = { "minimap", NULL}; +static int camera_fields_ref = LUA_NOREF; + static int lib_getHudInfo(lua_State *L) { UINT32 i; @@ -298,7 +302,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 CURRENTLY always valid, expected to be cached with PU_STATIC // this may change in the future, so patch.valid still exists @@ -333,7 +337,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); @@ -1439,11 +1443,15 @@ 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"); lua_pop(L,1); + camera_fields_ref = Lua_CreateFieldTable(L, camera_opt); + luaL_register(L, "hud", lib_hud); return 0; } diff --git a/src/lua_infolib.c b/src/lua_infolib.c index c94b42b5b..3ab044188 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -26,32 +26,6 @@ boolean LUA_CallAction(const char *action, mobj_t *actor); state_t *astate; -enum sfxinfo_read { - sfxinfor_name = 0, - sfxinfor_singular, - sfxinfor_priority, - sfxinfor_flags, // "pitch" - sfxinfor_skinsound -}; -const char *const sfxinfo_ropt[] = { - "name", - "singular", - "priority", - "flags", - "skinsound", - NULL}; - -enum sfxinfo_write { - sfxinfow_singular = 0, - sfxinfow_priority, - sfxinfow_flags // "pitch" -}; -const char *const sfxinfo_wopt[] = { - "singular", - "priority", - "flags", - NULL}; - // // Sprite Names // @@ -101,7 +75,7 @@ static void A_Lua(mobj_t *actor) { boolean found = false; I_Assert(actor != NULL); - + lua_settop(gL, 0); // Just in case... lua_pushcfunction(gL, LUA_GetErrorMessage); @@ -286,7 +260,7 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor) if (superstack && fasticmp(csaction, superactions[superstack-1])) // the action is calling itself, return false; // let it call the hardcoded function instead. - + lua_pushcfunction(gL, LUA_GetErrorMessage); // grab function by uppercase name. @@ -330,49 +304,93 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor) return true; // action successfully called. } +enum state_e { + state_sprite = 0, + state_frame, + state_tics, + state_action, + state_var1, + state_var2, + state_nextstate, +}; + +const char *const state_opt[] = { + "sprite", + "frame", + "tics", + "action", + "var1", + "var2", + "nextstate", + NULL +}; + +static int state_fields_ref = LUA_NOREF; + // state_t *, field -> number static int state_get(lua_State *L) { state_t *st = *((state_t **)luaL_checkudata(L, 1, META_STATE)); - const char *field = luaL_checkstring(L, 2); + enum state_e field = Lua_optoption(L, 2, -1, state_fields_ref); lua_Integer number; - if (fastcmp(field,"sprite")) - number = st->sprite; - else if (fastcmp(field,"frame")) - number = st->frame; - else if (fastcmp(field,"tics")) - number = st->tics; - else if (fastcmp(field,"action")) { - const char *name; - if (!st->action.acp1) // Action is NULL. - return 0; // return nil. - if (st->action.acp1 == (actionf_p1)A_Lua) { // This is a Lua function? - lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION); - I_Assert(lua_istable(L, -1)); - lua_pushlightuserdata(L, st); // Push the state pointer and - lua_rawget(L, -2); // use it to get the actual Lua function. - lua_remove(L, -2); // pop LREG_STATEACTION - return 1; // Return the Lua function. + switch (field) + { + case state_sprite: + number = st->sprite; + break; + + case state_frame: + number = st->frame; + break; + + case state_tics: + number = st->tics; + break; + + case state_action: + { + const char *name; + if (!st->action.acp1) // Action is NULL. + return 0; // return nil. + if (st->action.acp1 == (actionf_p1)A_Lua) { // This is a Lua function? + lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION); + I_Assert(lua_istable(L, -1)); + lua_pushlightuserdata(L, st); // Push the state pointer and + lua_rawget(L, -2); // use it to get the actual Lua function. + lua_remove(L, -2); // pop LREG_STATEACTION + return 1; // Return the Lua function. + } + name = LUA_GetActionName(&st->action); // find a hardcoded function name + if (!name) // If it's not a hardcoded function and it's not a Lua function... + return 0; // Just what is this?? + // get the function from the global + // because the metatable will trigger. + lua_getglobal(L, name); // actually gets from LREG_ACTIONS if applicable, and pushes a new C closure if not. + lua_pushstring(L, name); // push the name we found. + return 2; // return both the function and its name, in case somebody wanted to do a comparison by name or something? } - name = LUA_GetActionName(&st->action); // find a hardcoded function name - if (!name) // If it's not a hardcoded function and it's not a Lua function... - return 0; // Just what is this?? - // get the function from the global - // because the metatable will trigger. - lua_getglobal(L, name); // actually gets from LREG_ACTIONS if applicable, and pushes a new C closure if not. - lua_pushstring(L, name); // push the name we found. - return 2; // return both the function and its name, in case somebody wanted to do a comparison by name or something? - } else if (fastcmp(field,"var1")) - number = st->var1; - else if (fastcmp(field,"var2")) - number = st->var2; - else if (fastcmp(field,"nextstate")) - number = st->nextstate; - else if (devparm) - return luaL_error(L, LUA_QL("state_t") " has no field named " LUA_QS, field); - else - return 0; + break; + + case state_var1: + number = st->var1; + break; + + case state_var2: + number = st->var2; + break; + + case state_nextstate: + number = st->nextstate; + break; + + default: + { + if (devparm) + return luaL_error(L, LUA_QL("state_t") " has no field named " LUA_QS, field); + return 0; + } + } lua_pushinteger(L, number); return 1; @@ -382,7 +400,7 @@ static int state_get(lua_State *L) static int state_set(lua_State *L) { state_t *st = *((state_t **)luaL_checkudata(L, 1, META_STATE)); - const char *field = luaL_checkstring(L, 2); + enum state_e field = Lua_optoption(L, 2, -1, state_fields_ref); lua_Integer value; if (hud_running) @@ -390,16 +408,24 @@ static int state_set(lua_State *L) if (hook_cmd_running) return luaL_error(L, "Do not alter states in BuildCMD code!"); - if (fastcmp(field,"sprite")) { + switch (field) + { + case state_sprite: value = luaL_checknumber(L, 3); if (value < SPR_NULL || value >= NUMSPRITES) return luaL_error(L, "sprite number %d is invalid.", value); st->sprite = (spritenum_t)value; - } else if (fastcmp(field,"frame")) + break; + + case state_frame: st->frame = (UINT32)luaL_checknumber(L, 3); - else if (fastcmp(field,"tics")) + break; + + case state_tics: st->tics = (INT32)luaL_checknumber(L, 3); - else if (fastcmp(field,"action")) { + break; + + case state_action: switch(lua_type(L, 3)) { case LUA_TNIL: // Null? Set the action to nothing, then. @@ -420,17 +446,26 @@ static int state_set(lua_State *L) default: // ?! return luaL_typerror(L, 3, "function"); } - } else if (fastcmp(field,"var1")) + break; + + case state_var1: st->var1 = (INT32)luaL_checknumber(L, 3); - else if (fastcmp(field,"var2")) + break; + + case state_var2: st->var2 = (INT32)luaL_checknumber(L, 3); - else if (fastcmp(field,"nextstate")) { + break; + + case state_nextstate: value = luaL_checkinteger(L, 3); if (value < S_NULL || value >= NUMSTATES) return luaL_error(L, "nextstate number %d is invalid.", value); st->nextstate = (statenum_t)value; - } else + break; + + default: return luaL_error(L, LUA_QL("state_t") " has no field named " LUA_QS, field); + } return 0; } @@ -565,75 +600,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 = Lua_optoption(L, 2, -1, mobjinfo_fields_ref); 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; } @@ -642,7 +763,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!"); @@ -652,55 +773,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); @@ -708,18 +855,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; } @@ -752,6 +898,25 @@ static int lib_getSfxInfo(lua_State *L) return 1; } +enum sfxinfo_e { + sfxinfo_name = 0, + sfxinfo_singular, + sfxinfo_priority, + sfxinfo_flags, // "pitch" + sfxinfo_skinsound +}; + +const char *const sfxinfo_opt[] = { + "name", + "singular", + "priority", + "flags", + "skinsound", + NULL +}; + +static int sfxinfo_fields_ref = LUA_NOREF; + // stack: dummy, S_sfx[] table index, table of values to set. static int lib_setSfxInfo(lua_State *L) { @@ -775,22 +940,44 @@ static int lib_setSfxInfo(lua_State *L) lua_pushnil(L); while (lua_next(L, 1)) { - enum sfxinfo_write i; + enum sfxinfo_e i; if (lua_isnumber(L, 2)) - i = lua_tointeger(L, 2) - 1; // lua is one based, this enum is zero based. + { + int j = lua_tointeger(L, 2) - 1; + + // Read and Write enums were combined, need to do this switch now + switch (j) + { + case 1: + i = sfxinfo_singular; + break; + + case 2: + i = sfxinfo_priority; + break; + + case 3: + i = sfxinfo_flags; + break; + + default: + i = -1; + break; + } + } else - i = luaL_checkoption(L, 2, NULL, sfxinfo_wopt); + i = Lua_optoption(L, 2, -1, sfxinfo_fields_ref); switch(i) { - case sfxinfow_singular: + case sfxinfo_singular: info->singularity = luaL_checkboolean(L, 3); break; - case sfxinfow_priority: + case sfxinfo_priority: info->priority = (INT32)luaL_checkinteger(L, 3); break; - case sfxinfow_flags: + case sfxinfo_flags: info->pitch = (INT32)luaL_checkinteger(L, 3); break; default: @@ -812,29 +999,29 @@ static int lib_sfxlen(lua_State *L) static int sfxinfo_get(lua_State *L) { sfxinfo_t *sfx = *((sfxinfo_t **)luaL_checkudata(L, 1, META_SFXINFO)); - enum sfxinfo_read field = luaL_checkoption(L, 2, NULL, sfxinfo_ropt); + enum sfxinfo_e field = Lua_optoption(L, 2, -1, sfxinfo_fields_ref); I_Assert(sfx != NULL); switch (field) { - case sfxinfor_name: + case sfxinfo_name: lua_pushstring(L, sfx->name); return 1; - case sfxinfor_singular: + case sfxinfo_singular: lua_pushboolean(L, sfx->singularity); return 1; - case sfxinfor_priority: + case sfxinfo_priority: lua_pushinteger(L, sfx->priority); return 1; - case sfxinfor_flags: + case sfxinfo_flags: lua_pushinteger(L, sfx->pitch); return 1; - case sfxinfor_skinsound: + case sfxinfo_skinsound: lua_pushinteger(L, sfx->skinsound); return 1; default: - return luaL_error(L, "impossible error"); + return luaL_error(L, LUA_QL("sfxinfo_t") " has no field named " LUA_QS, lua_tostring(L, 2)); } return 0; } @@ -843,7 +1030,7 @@ static int sfxinfo_get(lua_State *L) static int sfxinfo_set(lua_State *L) { sfxinfo_t *sfx = *((sfxinfo_t **)luaL_checkudata(L, 1, META_SFXINFO)); - enum sfxinfo_write field = luaL_checkoption(L, 2, NULL, sfxinfo_wopt); + int field = Lua_optoption(L, 2, -1, sfxinfo_fields_ref); if (hud_running) return luaL_error(L, "Do not alter S_sfx in HUD rendering code!"); @@ -858,17 +1045,20 @@ static int sfxinfo_set(lua_State *L) switch (field) { - case sfxinfow_singular: + case sfxinfo_singular: sfx->singularity = luaL_checkboolean(L, 1); break; - case sfxinfow_priority: + case sfxinfo_priority: sfx->priority = luaL_checkinteger(L, 1); break; - case sfxinfow_flags: + case sfxinfo_flags: sfx->pitch = luaL_checkinteger(L, 1); break; default: - return luaL_error(L, "impossible error"); + if (field == -1) + return luaL_error(L, LUA_QL("sfxinfo_t") " has no field named " LUA_QS, lua_tostring(L, 2)); + else + return luaL_error(L, LUA_QL("sfxinfo_t") " field " LUA_QS " is read-only", lua_tostring(L, 2)); } return 0; } @@ -910,6 +1100,8 @@ int LUA_InfoLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + state_fields_ref = Lua_CreateFieldTable(L, state_opt); + luaL_newmetatable(L, META_MOBJINFO); lua_pushcfunction(L, mobjinfo_get); lua_setfield(L, -2, "__index"); @@ -921,6 +1113,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_SFXINFO); lua_pushcfunction(L, sfxinfo_get); lua_setfield(L, -2, "__index"); @@ -932,6 +1126,8 @@ int LUA_InfoLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + sfxinfo_fields_ref = Lua_CreateFieldTable(L, sfxinfo_opt); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getSprname); @@ -983,4 +1179,4 @@ int LUA_InfoLib(lua_State *L) lua_setglobal(L, "S_sfx"); lua_setglobal(L, "sfxinfo"); return 0; -} \ No newline at end of file +} diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 96222ba0a..d92cd1f8b 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -71,6 +71,8 @@ enum subsector_e { subsector_firstline, }; +static int sector_fields_ref = LUA_NOREF; + static const char *const subsector_opt[] = { "valid", "sector", @@ -78,6 +80,8 @@ static const char *const subsector_opt[] = { "firstline", NULL}; +static int subsector_fields_ref = LUA_NOREF; + enum line_e { line_valid = 0, line_v1, @@ -120,6 +124,8 @@ static const char *const line_opt[] = { "callcount", NULL}; +static int line_fields_ref = LUA_NOREF; + enum side_e { side_valid = 0, side_textureoffset, @@ -146,6 +152,8 @@ static const char *const side_opt[] = { "text", NULL}; +static int side_fields_ref = LUA_NOREF; + enum vertex_e { vertex_valid = 0, vertex_x, @@ -160,6 +168,8 @@ static const char *const vertex_opt[] = { "z", NULL}; +static int vertex_fields_ref = LUA_NOREF; + enum ffloor_e { ffloor_valid = 0, ffloor_topheight, @@ -196,6 +206,8 @@ static const char *const ffloor_opt[] = { "alpha", NULL}; +static int ffloor_fields_ref = LUA_NOREF; + enum slope_e { slope_valid = 0, slope_o, @@ -222,6 +234,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, @@ -387,7 +401,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) @@ -473,7 +487,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."); @@ -551,7 +565,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) { @@ -590,7 +604,7 @@ static int subsector_num(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) { @@ -715,7 +729,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) { @@ -765,7 +779,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) { @@ -816,7 +830,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) { @@ -1085,7 +1099,7 @@ static int lib_numvertexes(lua_State *L) 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) @@ -1161,7 +1175,7 @@ static int ffloor_get(lua_State *L) 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."); @@ -1239,7 +1253,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) { @@ -1289,7 +1303,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."); @@ -1446,93 +1460,207 @@ static int lib_nummapheaders(lua_State *L) return 1; } +enum mapheaderinfo_e +{ + mapheaderinfo_lvlttl, + mapheaderinfo_subttl, + mapheaderinfo_zonttl, + mapheaderinfo_actnum, + mapheaderinfo_typeoflevel, + mapheaderinfo_nextlevel, + mapheaderinfo_musname, + mapheaderinfo_mustrack, + mapheaderinfo_muspos, + mapheaderinfo_musinterfadeout, + mapheaderinfo_musintername, + 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_saveoverride, + mapheaderinfo_levelflags, + mapheaderinfo_menuflags, + //mapheaderinfo_automap, + mapheaderinfo_mobj_scale, +}; + +static const char *const mapheaderinfo_opt[] = { + "lvlttl", + "subttl", + "zonttl", + "actnum", + "typeoflevel", + "nextlevel", + "musname", + "mustrack", + "muspos", + "musinterfadeout", + "musintername", + "forcecharacter", + "weather", + "skynum", + "skybox_scalex", + "skybox_scaley", + "skybox_scalez", + "interscreen", + "runsoc", + "scriptname", + "precutscenenum", + "cutscenenum", + "countdown", + "palette", + "numlaps", + "unlockrequired", + "levelselect", + "bonustype", + "saveoverride", + "levelflags", + "menuflags", + //"automap", + "mobj_scale", + 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,"zonttl")) + break; + case mapheaderinfo_zonttl: lua_pushstring(L, header->zonttl); - else if (fastcmp(field,"actnum")) + break; + case mapheaderinfo_actnum: lua_pushstring(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,"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,"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,"saveoverride")) + break; + case mapheaderinfo_saveoverride: lua_pushinteger(L, header->saveoverride); - 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,"automap")) - lua_pushboolean(L, header->automap);*/ - else if (fastcmp(field,"mobj_scale")) + break; + /*case mapheaderinfo_automap: + lua_pushstring(L, header->selectheading); + break;*/ + case mapheaderinfo_mobj_scale: lua_pushfixed(L, header->mobj_scale); + 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); else lua_pushnil(L); } + } return 1; + } int LUA_MapLib(lua_State *L) @@ -1556,6 +1684,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"); @@ -1564,6 +1694,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"); @@ -1572,6 +1704,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_SIDENUM); lua_pushcfunction(L, sidenum_get); lua_setfield(L, -2, "__index"); @@ -1588,6 +1722,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"); @@ -1596,6 +1732,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"); @@ -1604,6 +1742,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); + ffloor_fields_ref = Lua_CreateFieldTable(L, ffloor_opt); + luaL_newmetatable(L, META_SLOPE); lua_pushcfunction(L, slope_get); lua_setfield(L, -2, "__index"); @@ -1612,6 +1752,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"); @@ -1630,6 +1772,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_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getSector); @@ -1690,4 +1834,4 @@ int LUA_MapLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "mapheaderinfo"); return 0; -} \ No newline at end of file +} diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 7b1db5327..f62e59486 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -769,14 +769,41 @@ static int mobj_set(lua_State *L) #undef NOSETPOS #undef NOFIELD +enum mapthing_e { + mapthing_valid = 0, + mapthing_x, + mapthing_y, + mapthing_angle, + mapthing_type, + mapthing_options, + mapthing_z, + mapthing_extrainfo, + mapthing_mobj, +}; + +const char *const mapthing_opt[] = { + "valid", + "x", + "y", + "angle", + "type", + "options", + "z", + "extrainfo", + "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; } @@ -785,39 +812,50 @@ 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,"type")) - number = mt->type; - else if(fastcmp(field,"options")) - number = mt->options; - else if(fastcmp(field,"z")) - number = mt->z; - else if(fastcmp(field,"extrainfo")) - number = mt->extrainfo; - 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; + switch (field) + { + 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_type: + lua_pushinteger(L, mt->type); + break; + case mapthing_options: + lua_pushinteger(L, mt->options); + break; + case mapthing_z: + lua_pushinteger(L, mt->z); + break; + case mapthing_extrainfo: + lua_pushinteger(L, mt->extrainfo); + 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; + } - 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."); @@ -827,24 +865,40 @@ static int mapthing_set(lua_State *L) if (hook_cmd_running) return luaL_error(L, "Do not alter mapthing_t in BuildCMD 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,"type")) - mt->type = (UINT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"options")) - mt->options = (UINT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"z")) - mt->z = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"extrainfo")) - mt->extrainfo = (UINT8)luaL_checkinteger(L, 3); - 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); + switch (field) + { + 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_type: + mt->type = (UINT16)luaL_checkinteger(L, 3); + break; + case mapthing_options: + mt->options = (UINT16)luaL_checkinteger(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_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); + } return 0; } @@ -915,6 +969,8 @@ int LUA_MobjLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + mapthing_fields_ref = Lua_CreateFieldTable(L, mapthing_opt); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getMapthing); @@ -925,4 +981,4 @@ int LUA_MobjLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "mapthings"); return 0; -} \ No newline at end of file +} diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 70324fa02..2d79d536d 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -694,30 +694,65 @@ static int kartstuff_len(lua_State *L) } #define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field) +#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " should not be set directly.", field) + +enum ticcmd_e +{ + ticcmd_forwardmove, + ticcmd_sidemove, + ticcmd_angleturn, + ticcmd_aiming, + ticcmd_buttons, + ticcmd_driftturn, + ticcmd_latency, +}; + +static const char *const ticcmd_opt[] = { + "forwardmove", + "sidemove", + "angleturn", + "aiming", + "buttons", + "driftturn", + "latency", + NULL, +}; + +static int ticcmd_fields_ref = LUA_NOREF; static int ticcmd_get(lua_State *L) { ticcmd_t *cmd = *((ticcmd_t **)luaL_checkudata(L, 1, META_TICCMD)); - const char *field = luaL_checkstring(L, 2); + enum ticcmd_e field = Lua_optoption(L, 2, -1, ticcmd_fields_ref); if (!cmd) return LUA_ErrInvalid(L, "player_t"); - if (fastcmp(field,"forwardmove")) + switch (field) + { + case ticcmd_forwardmove: lua_pushinteger(L, cmd->forwardmove); - else if (fastcmp(field,"sidemove")) + break; + case ticcmd_sidemove: lua_pushinteger(L, cmd->sidemove); - else if (fastcmp(field,"angleturn")) + break; + case ticcmd_angleturn: lua_pushinteger(L, cmd->angleturn); - else if (fastcmp(field,"aiming")) + break; + case ticcmd_aiming: lua_pushinteger(L, cmd->aiming); - else if (fastcmp(field,"buttons")) + break; + case ticcmd_buttons: lua_pushinteger(L, cmd->buttons); - else if (fastcmp(field,"driftturn")) + break; + case ticcmd_driftturn: lua_pushinteger(L, cmd->driftturn); - else if (fastcmp(field,"latency")) + break; + case ticcmd_latency: lua_pushinteger(L, cmd->latency); - else + break; + default: return NOFIELD; + } return 1; } @@ -725,32 +760,44 @@ static int ticcmd_get(lua_State *L) static int ticcmd_set(lua_State *L) { ticcmd_t *cmd = *((ticcmd_t **)luaL_checkudata(L, 1, META_TICCMD)); - const char *field = luaL_checkstring(L, 2); + enum ticcmd_e field = Lua_optoption(L, 2, -1, ticcmd_fields_ref); if (!cmd) return LUA_ErrInvalid(L, "ticcmd_t"); if (hud_running) return luaL_error(L, "Do not alter player_t in HUD rendering code!"); - if (fastcmp(field,"forwardmove")) + switch (field) + { + case ticcmd_forwardmove: cmd->forwardmove = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"sidemove")) + break; + case ticcmd_sidemove: cmd->sidemove = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"angleturn")) + break; + case ticcmd_angleturn: cmd->angleturn = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"aiming")) + break; + case ticcmd_aiming: cmd->aiming = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"buttons")) + break; + case ticcmd_buttons: cmd->buttons = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"driftturn")) + break; + case ticcmd_driftturn: cmd->driftturn = (INT16)luaL_checkinteger(L, 3); - else + break; + case ticcmd_latency: + return NOSET; + default: return NOFIELD; + } return 0; } #undef NOFIELD +#undef NOSET int LUA_PlayerLib(lua_State *L) { @@ -797,6 +844,8 @@ int LUA_PlayerLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + ticcmd_fields_ref = Lua_CreateFieldTable(L, ticcmd_opt); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getPlayer); diff --git a/src/lua_script.c b/src/lua_script.c index 3af655efe..13cdf7bdf 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1678,13 +1678,41 @@ void LUA_UnArchiveDemo(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) +{ + int result = -1; + + 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)) + result = lua_tointeger(L, -1); + + lua_pop(L, 2); // Pop result and fields table + + return result; +} + + +int Lua_CreateFieldTable(lua_State *L, const char *const lst[]) { - 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; - return -1; -} \ No newline at end of file + + 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); +} diff --git a/src/lua_script.h b/src/lua_script.h index a22e47c12..9903315c2 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -63,8 +63,8 @@ void LUA_UnArchiveDemo(void); void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(const char *name); // 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 LUAh_NetArchiveHook(lua_CFunction archFunc); // Console wrapper diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 286e983c1..403ac834e 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -38,6 +38,7 @@ enum skin { skin_highresscale, skin_soundsid }; + static const char *const skin_opt[] = { "valid", "name", @@ -61,10 +62,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); INT32 i; // skins are always valid, only added, never removed @@ -253,6 +256,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");