Merge branch 'lua-lump-load-only' into 'master'

Lua lump load only

This branch prevents the following Lua functions from being used within hooks or coroutines, to prevent netgame desync problems or any other similar oddities when using these weirdly:

* `freeslot()`
* `addHook()`
* `hud.add()`
* `COM_AddCommand()`
* `CV_RegisterVar()`

All of the above should only be called when the Lua script is being loaded (i.e. it takes place the same instant a ".lua" file or a WAD file with a "LUA_" lump is being loaded)

To put it another way:
```
//This is valid usage:
freeslot("MT_TEST")

//This is NOT valid usage
addHook("MobjSpawn", function() freeslot("MT_TEST2") end, MT_PLAYER)

```

See *Monster Iestyn/Lua lump load only* on the FTP for an exe and test script.

See merge request !87
This commit is contained in:
Monster Iestyn 2017-08-05 16:36:05 -04:00
commit 0ac63c0949
6 changed files with 28 additions and 8 deletions

View File

@ -7861,11 +7861,14 @@ void FUNCMATH DEH_Check(void)
static inline int lib_freeslot(lua_State *L)
{
int n = lua_gettop(L);
int r = 0; // args returned
int r = 0; // args returned
char *s, *type,*word;
while (n-- > 0)
{
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
while (n-- > 0)
{
s = Z_StrDup(luaL_checkstring(L,1));
type = strtok(s, "_");
if (type)

View File

@ -22,8 +22,13 @@
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
// for functions not allowed in hud.add hooks
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
// for functions not allowed in hooks or coroutines (supercedes above)
#define NOHOOK if (!lua_lumploading)\
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
// for functions only allowed within a level
#define INLEVEL if (gamestate != GS_LEVEL)\
return luaL_error(L, "This function can only be used in a level!");
@ -184,7 +189,7 @@ static int lib_comAddCommand(lua_State *L)
strlwr(name);
luaL_checktype(L, 2, LUA_TFUNCTION);
NOHUD
NOHOOK
if (lua_gettop(L) >= 3)
{ // For the third argument, only take a boolean or a number.
lua_settop(L, 3);
@ -296,7 +301,7 @@ static int lib_cvRegisterVar(lua_State *L)
consvar_t *cvar;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one.
NOHUD
NOHOOK
cvar = lua_newuserdata(L, sizeof(consvar_t));
luaL_getmetatable(L, META_CVAR);
lua_setmetatable(L, -2);

View File

@ -109,8 +109,8 @@ static int lib_addHook(lua_State *L)
luaL_checktype(L, 1, LUA_TFUNCTION);
if (hud_running)
return luaL_error(L, "HUD rendering code should not call this function!");
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
switch(hook.type)
{

View File

@ -612,6 +612,9 @@ static int lib_hudadd(lua_State *L)
luaL_checktype(L, 1, LUA_TFUNCTION);
field = luaL_checkoption(L, 2, "game", hudhook_opt);
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
lua_getfield(L, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(L, -1));
lua_rawgeti(L, -1, field+2); // HUD[2+]

View File

@ -161,6 +161,11 @@ void LUA_ClearExtVars(void)
}
#endif
// Use this variable to prevent certain functions from running
// if they were not called on lump load
// (i.e. they were called in hooks or coroutines etc)
boolean lua_lumploading = false;
// Load a script from a MYFILE
static inline void LUA_LoadFile(MYFILE *f, char *name)
{
@ -198,7 +203,9 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump)
name[strlen(wadfiles[wad]->filename)+9] = '\0';
}
LUA_LoadFile(&f, name);
lua_lumploading = true; // turn on loading flag
LUA_LoadFile(&f, name); // actually load file!
lua_lumploading = false; // turn off again
free(name);
Z_Free(f.data);

View File

@ -38,6 +38,8 @@
void LUA_ClearExtVars(void);
#endif
extern boolean lua_lumploading; // is LUA_LoadLump being called?
void LUA_LoadLump(UINT16 wad, UINT16 lump);
#ifdef LUA_ALLOW_BYTECODE
void LUA_DumpFile(const char *filename);