Set lua_compatmode for console commands and cvar functions

Thanks Indev for finding this oopsie and the patch for command code
This commit is contained in:
GenericHeroGuy 2025-12-16 23:22:29 +01:00
parent eb2cb338db
commit a9c66ec217
5 changed files with 44 additions and 9 deletions

View file

@ -328,7 +328,7 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
lua_pushstring(gL, luafiletransfers->filename);
// Call the callback
LUA_Call(gL, 2, 0, 1);
LUA_Call(gL, 2, 0, 1, lua_compatmode); // TODO...? (networked io.open is 2.2+)
lua_settop(gL, 0);
if (success)

View file

@ -34,6 +34,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
UINT8 i, argc, flags;
const char *argv[256];
char buf[256];
boolean compat;
argc = READUINT8(*cp);
argv[0] = (const char*)*cp;
@ -74,6 +75,10 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
if ((flags & 1) && playernum != serverplayer && !IsPlayerAdmin(playernum))
goto deny;
lua_rawgeti(gL, -1, 3); // push compatmode from command info table
compat = lua_toboolean(gL, -1);
lua_pop(gL, 1); // pop compatmode
lua_rawgeti(gL, -1, 1); // push function from command info table
// although honestly this should be true anyway
@ -88,7 +93,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
strlcpy(buf, argv[i], 255);
lua_pushstring(gL, buf);
}
LUA_Call(gL, (int)argc, 0, 1); // argc is 1-based, so this will cover the player we passed too.
LUA_Call(gL, (int)argc, 0, 1, compat); // argc is 1-based, so this will cover the player we passed too.
lua_pop(gL, 1); // Pop LUA_GetErrorMessage (lua_pcall doesn't pop it)
@ -113,6 +118,7 @@ void COM_Lua_f(void)
UINT16 flags;
UINT8 lpn = 0;
INT32 playernum = consoleplayer;
boolean compat;
I_Assert(gL != NULL);
@ -181,6 +187,10 @@ void COM_Lua_f(void)
return;
}
lua_rawgeti(gL, -1, 3); // push compatmode from command info table
compat = lua_toboolean(gL, -1);
lua_pop(gL, 1); // pop compatmode
// Do the command locally, NetXCmds don't go through outside of GS_LEVEL || GS_INTERMISSION || GS_VOTING
lua_rawgeti(gL, -1, 1); // push function from command info table
I_Assert(lua_isfunction(gL, -1));
@ -189,7 +199,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(), 0, 1); // COM_Argc is 1-based, so this will cover the player we passed too.
LUA_Call(gL, (int)COM_Argc(), 0, 1, compat); // COM_Argc is 1-based, so this will cover the player we passed too.
lua_pop(gL, 1); // Pop LUA_GetErrorMessage (lua_pcall doesn't pop it)
}
@ -235,6 +245,9 @@ static int lib_comAddCommand(lua_State *L)
lua_pushvalue(L, 3);
lua_rawseti(L, -2, 2);
lua_pushboolean(L, lua_compatmode);
lua_rawseti(L, -2, 3);
lua_setfield(L, -2, name);
// Try to add the Lua command
@ -296,11 +309,19 @@ void LUA_CVarChanged(void *cvar)
static void Lua_OnChange(void)
{
/// \todo Network this! XD_LUAVAR
boolean compat;
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_insert(gL, 1); // Because LUA_Call wants it at index 1.
// From CV_OnChangeCompat registry field, get the function's compatmode setting.
lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChangeCompat");
I_Assert(lua_istable(gL, -1));
lua_pushlightuserdata(gL, this_cvar);
lua_rawget(gL, -2);
compat = luaL_checkboolean(gL, -1);
lua_pop(gL, 2);
// 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));
@ -309,7 +330,7 @@ static void Lua_OnChange(void)
LUA_RawPushUserdata(gL, this_cvar);
LUA_Call(gL, 1, 0, 1); // call function(cvar)
LUA_Call(gL, 1, 0, 1, compat); // call function(cvar)
lua_pop(gL, 1); // pop CV_OnChange table
lua_remove(gL, 1); // remove LUA_GetErrorMessage
}
@ -408,6 +429,14 @@ static int lib_cvRegisterVar(lua_State *L)
lua_pushvalue(L, 4);
lua_rawset(L, 5);
lua_pop(L, 1);
lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChangeCompat");
I_Assert(lua_istable(L, 5));
lua_pushlightuserdata(L, cvar);
lua_pushboolean(L, lua_compatmode);
lua_rawset(L, 5);
lua_pop(L, 1);
cvar->func = Lua_OnChange;
}
lua_pop(L, 1);
@ -594,6 +623,8 @@ int LUA_ConsoleLib(lua_State *L)
lua_setfield(L, LUA_REGISTRYINDEX, "CV_PossibleValue");
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, "CV_OnChange");
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, "CV_OnChangeCompat");
// Push opaque CV_PossibleValue pointers
// Because I don't care enough to bother.

View file

@ -708,7 +708,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, 0, 1);
LUA_Call(gL, 3, 0, 1, lua_compatmode); // TODO
lua_pop(gL, 1); // pop error handler
@ -903,7 +903,7 @@ boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor)
superactions[superstack] = actionpointers[actionnum].name;
++superstack;
LUA_Call(gL, 3, 0, -(2 + 3));
LUA_Call(gL, 3, 0, -(2 + 3), lua_compatmode); // TODO
lua_pop(gL, -1); // Error handler
--superstack;

View file

@ -147,8 +147,11 @@ int LUA_GetErrorMessage(lua_State *L)
return 1;
}
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex)
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex, boolean compat)
{
boolean oldcompat = lua_compatmode;
lua_compatmode = compat;
int err = lua_pcall(L, nargs, nresults, errorhandlerindex);
if (err)
@ -157,6 +160,7 @@ int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex)
lua_pop(L, 1);
}
lua_compatmode = oldcompat;
return err;
}

View file

@ -54,7 +54,7 @@ extern INT32 lua_lumploading; // is LUA_LoadLump being called?
extern boolean lua_compatmode; // compatmode enabled for this lump/hook?
int LUA_GetErrorMessage(lua_State *L);
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex);
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex, boolean compat);
void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults);
#ifdef LUA_ALLOW_BYTECODE
void LUA_DumpFile(const char *filename);