diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 3869fdc72..d5843ff37 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -36,6 +36,10 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) // like sending random junk lua commands to crash the server if (!gL) goto deny; + + lua_settop(gL, 0); // Just in case... + lua_pushcfunction(gL, LUA_GetErrorMessage); + lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command if (!lua_istable(gL, -1)) goto deny; @@ -72,7 +76,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) READSTRINGN(*cp, buf, 255); lua_pushstring(gL, buf); } - LUA_Call(gL, (int)argc); // argc is 1-based, so this will cover the player we passed too. + LUA_Call(gL, (int)argc, 0, 1); // argc is 1-based, so this will cover the player we passed too. return; deny: @@ -100,6 +104,10 @@ void COM_Lua_f(void) INT32 playernum = consoleplayer; I_Assert(gL != NULL); + + lua_settop(gL, 0); // Just in case... + lua_pushcfunction(gL, LUA_GetErrorMessage); + lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command I_Assert(lua_istable(gL, -1)); @@ -169,7 +177,7 @@ void COM_Lua_f(void) LUA_PushUserdata(gL, &players[playernum], META_PLAYER); for (i = 1; i < COM_Argc(); i++) lua_pushstring(gL, COM_Argv(i)); - LUA_Call(gL, (int)COM_Argc()); // COM_Argc is 1-based, so this will cover the player we passed too. + LUA_Call(gL, (int)COM_Argc(), 0, 1); // COM_Argc is 1-based, so this will cover the player we passed too. } // Wrapper for COM_AddCommand @@ -281,6 +289,10 @@ static void Lua_OnChange(void) /// \todo Network this! XD_LUAVAR + // Why?.. + //lua_settop(gL, 0); // Just in case... + lua_pushcfunction(gL, LUA_GetErrorMessage); + // From CV_OnChange registry field, get the function for this cvar by name. lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChange"); I_Assert(lua_istable(gL, -1)); @@ -292,8 +304,8 @@ static void Lua_OnChange(void) lua_getfield(gL, -1, cvname); // get consvar_t* userdata. lua_remove(gL, -2); // pop the CV_Vars table. - LUA_Call(gL, 1); // call function(cvar) - lua_pop(gL, 1); // pop CV_OnChange table + LUA_Call(gL, 1, 0, 1); // call function(cvar) + lua_pop(gL, 2); // pop CV_OnChange table and error handler } static int lib_cvRegisterVar(lua_State *L) @@ -382,19 +394,29 @@ static int lib_cvRegisterVar(lua_State *L) cvar->PossibleValue = cvpv; } else FIELDERROR("PossibleValue", va("%s or CV_PossibleValue_t expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) - } else if (cvar->flags & CV_CALL && (i == 5 || (k && fasticmp(k, "func")))) { - if (!lua_isfunction(L, 4)) - TYPEERROR("func", LUA_TFUNCTION) - lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange"); - I_Assert(lua_istable(L, 5)); - lua_pushvalue(L, 4); - lua_setfield(L, 5, cvar->name); - lua_pop(L, 1); - cvar->func = Lua_OnChange; } lua_pop(L, 1); } + if (cvar->flags & CV_CALL) { + lua_rawgeti(L, 1, 5); // Push function, if it stored at field 5 + + if (lua_isnil(L, -1)) { // If it is nil, try to get at field "func" + lua_pop(L, 1); + lua_getfield(L, 1, "func"); + } + + if (!lua_isfunction(L, -1)) + TYPEERROR("func", LUA_TFUNCTION) + + lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange"); // Push table + I_Assert(lua_istable(L, -1)); + lua_pushvalue(L, -2); // Push func + lua_setfield(L, -2, cvar->name); // Pop func, add it to table + lua_pop(L, 2); // Pop table and func + cvar->func = Lua_OnChange; + } + #undef FIELDERROR #undef TYPEERROR diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 9aab4920d..854721b2a 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1050,7 +1050,9 @@ void LUAh_GameHUD(player_t *stplayr, huddrawlist_h list) lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); hud_running = true; - lua_pop(gL, -1); + lua_settop(gL, 0); + + lua_pushcfunction(gL, LUA_GetErrorMessage); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); I_Assert(lua_istable(gL, -1)); @@ -1088,9 +1090,9 @@ void LUAh_GameHUD(player_t *stplayr, huddrawlist_h list) lua_pushvalue(gL, -5); // graphics library (HUD[1]) lua_pushvalue(gL, -5); // stplayr lua_pushvalue(gL, -5); // camera - LUA_Call(gL, 3); + LUA_Call(gL, 3, 0, 1); } - lua_pop(gL, -1); + lua_settop(gL, 0); hud_running = false; lua_pushlightuserdata(gL, NULL); @@ -1106,7 +1108,9 @@ void LUAh_ScoresHUD(huddrawlist_h list) lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); hud_running = true; - lua_pop(gL, -1); + lua_settop(gL, 0); + + lua_pushcfunction(gL, LUA_GetErrorMessage); lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); I_Assert(lua_istable(gL, -1)); @@ -1119,9 +1123,9 @@ void LUAh_ScoresHUD(huddrawlist_h list) lua_pushnil(gL); while (lua_next(gL, -3) != 0) { lua_pushvalue(gL, -3); // graphics library (HUD[1]) - LUA_Call(gL, 1); + LUA_Call(gL, 1, 0, 1); } - lua_pop(gL, -1); + lua_settop(gL, 0); hud_running = false; lua_pushlightuserdata(gL, NULL); diff --git a/src/lua_infolib.c b/src/lua_infolib.c index d8659a7e0..64a8b63d7 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -102,6 +102,9 @@ 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); // get the action for this state lua_getfield(gL, LUA_REGISTRYINDEX, LREG_STATEACTION); @@ -131,7 +134,7 @@ static void A_Lua(mobj_t *actor) LUA_PushUserdata(gL, actor, META_MOBJ); lua_pushinteger(gL, var1); lua_pushinteger(gL, var2); - LUA_Call(gL, 3); + LUA_Call(gL, 3, 0, 1); if (found) { @@ -284,6 +287,8 @@ 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. lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS); @@ -297,13 +302,14 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor) if (lua_isnil(gL, -1)) // no match { - lua_pop(gL, 1); // pop nil + lua_pop(gL, 2); // pop nil and error handler return false; // action not called. } if (superstack == MAXRECURSION) { CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n"); + lua_pop(gL, 2); // pop function and error handler return true; } @@ -317,7 +323,8 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor) superactions[superstack] = csaction; ++superstack; - LUA_Call(gL, 3); + LUA_Call(gL, 3, 0, -(2 + 3)); + lua_pop(gL, -1); // Error handler --superstack; superactions[superstack] = NULL; diff --git a/src/lua_script.c b/src/lua_script.c index d9359d3b2..8f4438732 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -131,6 +131,19 @@ int LUA_GetErrorMessage(lua_State *L) return 1; } +int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex) +{ + int err = lua_pcall(L, nargs, nresults, errorhandlerindex); + + if (err) + { + CONS_Alert(CONS_WARNING, "%s\n", lua_tostring(L, -1)); + lua_pop(L, 1); + } + + return err; +} + // This function decides which global variables you are allowed to set. static int noglobals(lua_State *L) { @@ -182,7 +195,7 @@ void LUA_ClearState(void) // open base libraries luaL_openlibs(L); - lua_pop(L, -1); + lua_settop(L, 0); // make LREG_VALID table for all pushed userdata cache. lua_newtable(L); @@ -372,7 +385,7 @@ fixed_t LUA_EvalMath(const char *word) *b = '\0'; // eval string. - lua_pop(L, -1); + lua_settop(L, 0); if (luaL_dostring(L, buf)) { p = lua_tostring(L, -1); diff --git a/src/lua_script.h b/src/lua_script.h index a21ce64d5..dd21ae0d9 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -41,6 +41,7 @@ void LUA_ClearExtVars(void); void LUA_ClearState(void); int LUA_GetErrorMessage(lua_State *L); +int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex); void LUA_LoadLump(UINT16 wad, UINT16 lump); #ifdef LUA_ALLOW_BYTECODE void LUA_DumpFile(const char *filename); @@ -67,14 +68,6 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc); // Console wrapper void COM_Lua_f(void); -#define LUA_Call(L,a)\ -{\ - if (lua_pcall(L, a, 0, 0)) {\ - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(L,-1));\ - lua_pop(L, 1);\ - }\ -} - #define LUA_ErrInvalid(L, type) luaL_error(L, "accessed " type " doesn't exist anymore, please check 'valid' before using " type "."); // Deprecation warnings