Use only one state for LUA_EvalMath and open enum lib once

This commit is contained in:
James R 2020-12-14 03:13:25 -08:00
parent e94bccc503
commit da1ef9376c
3 changed files with 72 additions and 58 deletions

View file

@ -29,6 +29,8 @@
#include "deh_soc.h" // for get_mus
#endif
boolean lua_mathlib;
// freeslot takes a name (string only!)
// and allocates it to the appropriate free slot.
// Returns the slot number allocated for it or nil if failed.
@ -224,7 +226,6 @@ static inline int lib_getenum(lua_State *L)
{
const char *word, *p;
fixed_t i;
boolean mathlib = lua_toboolean(L, lua_upvalueindex(1));
if (lua_type(L,2) != LUA_TSTRING)
return 0;
word = lua_tostring(L,2);
@ -234,7 +235,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, *word-'A');
return 1;
}
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
if (lua_mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
return 0;
}
else if (fastncmp("MF_", word, 3)) {
@ -244,7 +245,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjflag '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "mobjflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MF2_", word, 4)) {
@ -254,7 +255,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjflag2 '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "mobjflag2 '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MFE_", word, 4)) {
@ -264,7 +265,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjeflag '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "mobjeflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MTF_", word, 4)) {
@ -274,7 +275,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mapthingflag '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "mapthingflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("PF_", word, 3)) {
@ -294,7 +295,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, (lua_Integer)PF_SPINDOWN);
return 1;
}
if (mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GT_", word, 3)) {
@ -304,7 +305,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("GTR_", word, 4)) {
@ -314,7 +315,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "game type rule '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "game type rule '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("TOL_", word, 4)) {
@ -324,7 +325,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, TYPEOFLEVEL[i].flag);
return 1;
}
if (mathlib) return luaL_error(L, "typeoflevel '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "typeoflevel '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("ML_", word, 3)) {
@ -334,7 +335,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("S_",word,2)) {
@ -378,7 +379,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("SPR2_",word,5)) {
@ -399,10 +400,10 @@ static inline int lib_getenum(lua_State *L)
return 1;
}
}
if (mathlib) return luaL_error(L, "player sprite '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "player sprite '%s' could not be found.\n", word);
return 0;
}
else if (!mathlib && fastncmp("sfx_",word,4)) {
else if (!lua_mathlib && fastncmp("sfx_",word,4)) {
p = word+4;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fastcmp(p, S_sfx[i].name)) {
@ -411,7 +412,7 @@ static inline int lib_getenum(lua_State *L)
}
return 0;
}
else if (mathlib && fastncmp("SFX_",word,4)) { // SOCs are ALL CAPS!
else if (lua_mathlib && fastncmp("SFX_",word,4)) { // SOCs are ALL CAPS!
p = word+4;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) {
@ -420,32 +421,32 @@ static inline int lib_getenum(lua_State *L)
}
return luaL_error(L, "sfx '%s' could not be found.\n", word);
}
else if (mathlib && fastncmp("DS",word,2)) {
else if (lua_mathlib && fastncmp("DS",word,2)) {
p = word+2;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "sfx '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "sfx '%s' could not be found.\n", word);
return 0;
}
#ifdef MUSICSLOT_COMPATIBILITY
else if (!mathlib && fastncmp("mus_",word,4)) {
else if (!lua_mathlib && fastncmp("mus_",word,4)) {
p = word+4;
if ((i = get_mus(p, false)) == 0)
return 0;
lua_pushinteger(L, i);
return 1;
}
else if (mathlib && fastncmp("MUS_",word,4)) { // SOCs are ALL CAPS!
else if (lua_mathlib && fastncmp("MUS_",word,4)) { // SOCs are ALL CAPS!
p = word+4;
if ((i = get_mus(p, false)) == 0)
return luaL_error(L, "music '%s' could not be found.\n", word);
lua_pushinteger(L, i);
return 1;
}
else if (mathlib && (fastncmp("O_",word,2) || fastncmp("D_",word,2))) {
else if (lua_mathlib && (fastncmp("O_",word,2) || fastncmp("D_",word,2))) {
p = word+2;
if ((i = get_mus(p, false)) == 0)
return luaL_error(L, "music '%s' could not be found.\n", word);
@ -453,7 +454,7 @@ static inline int lib_getenum(lua_State *L)
return 1;
}
#endif
else if (!mathlib && fastncmp("pw_",word,3)) {
else if (!lua_mathlib && fastncmp("pw_",word,3)) {
p = word+3;
for (i = 0; i < NUMPOWERS; i++)
if (fasticmp(p, POWERS_LIST[i])) {
@ -462,7 +463,7 @@ static inline int lib_getenum(lua_State *L)
}
return 0;
}
else if (mathlib && fastncmp("PW_",word,3)) { // SOCs are ALL CAPS!
else if (lua_mathlib && fastncmp("PW_",word,3)) { // SOCs are ALL CAPS!
p = word+3;
for (i = 0; i < NUMPOWERS; i++)
if (fastcmp(p, POWERS_LIST[i])) {
@ -478,7 +479,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "huditem '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "huditem '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("SKINCOLOR_",word,10)) {
@ -507,7 +508,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word);
return 0;
}
else if (fastncmp("MN_",word,3)) {
@ -517,10 +518,10 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, i);
return 1;
}
if (mathlib) return luaL_error(L, "menutype '%s' could not be found.\n", word);
if (lua_mathlib) return luaL_error(L, "menutype '%s' could not be found.\n", word);
return 0;
}
else if (!mathlib && fastncmp("A_",word,2)) {
else if (!lua_mathlib && fastncmp("A_",word,2)) {
char *caps;
// Try to get a Lua action first.
/// \todo Push a closure that sets superactions[] and superstack.
@ -545,7 +546,7 @@ static inline int lib_getenum(lua_State *L)
}
return 0;
}
else if (!mathlib && fastcmp("super",word))
else if (!lua_mathlib && fastcmp("super",word))
{
if (!superstack)
{
@ -572,7 +573,7 @@ static inline int lib_getenum(lua_State *L)
return 1;
}
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
if (lua_mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
// DYNAMIC variables too!!
// Try not to add anything that would break netgames or timeattack replays here.
@ -582,13 +583,9 @@ static inline int lib_getenum(lua_State *L)
int LUA_EnumLib(lua_State *L)
{
if (lua_gettop(L) == 0)
lua_pushboolean(L, 0);
// Set the global metatable
lua_createtable(L, 0, 1);
lua_pushvalue(L, 1); // boolean passed to LUA_EnumLib as first argument.
lua_pushcclosure(L, lib_getenum, 1);
lua_pushcfunction(L, lib_getenum);
lua_setfield(L, -2, "__index");
lua_setmetatable(L, LUA_GLOBALSINDEX);
return 0;

View file

@ -13,6 +13,8 @@
#ifndef __DEH_LUA_H__
#define __DEH_LUA_H__
extern boolean lua_mathlib;
boolean LUA_SetLuaAction(void *state, const char *actiontocompare);
const char *LUA_GetActionName(void *action);
void LUA_SetActionByName(void *state, const char *actiontocompare);

View file

@ -39,9 +39,10 @@
lua_State *gL = NULL;
static lua_State *soc_lua_state;
// List of internal libraries to load from SRB2
static lua_CFunction liblist[] = {
LUA_EnumLib, // global metatable for enums
LUA_SOCLib, // A_Action functions, freeslot
LUA_BaseLib, // string concatination by +, CONS_Printf, p_local.h stuff (P_InstaThrust, P_Move), etc.
LUA_MathLib, // fixed_t and angle_t math functions
@ -474,24 +475,28 @@ static int setglobals(lua_State *L)
return luaL_error(L, "Implicit global " LUA_QS " prevented. Create a local variable instead.", csname);
}
static lua_State * LUA_EnumState (void)
{
lua_State *L = soc_lua_state;
if (!L)
{
L = lua_newstate(LUA_Alloc, NULL);
lua_atpanic(L, LUA_Panic);
LUA_EnumLib(L); // global metatable for enums
soc_lua_state = L;
}
return L;
}
// Clear and create a new Lua state, laddo!
// There's SCRIPTIN to be had!
static void LUA_ClearState(void)
{
lua_State *L;
lua_State *L = LUA_EnumState();
int i;
// close previous state
if (gL)
lua_close(gL);
gL = NULL;
CONS_Printf(M_GetText("Pardon me while I initialize the Lua scripting interface...\n"));
// allocate state
L = lua_newstate(LUA_Alloc, NULL);
lua_atpanic(L, LUA_Panic);
// open base libraries
luaL_openlibs(L);
lua_settop(L, 0);
@ -670,21 +675,13 @@ void LUA_DumpFile(const char *filename)
fixed_t LUA_EvalMath(const char *word)
{
lua_State *L = NULL;
static int fenv_ref = LUA_NOREF;
lua_State *L = LUA_EnumState();
char buf[1024], *b;
const char *p;
fixed_t res = 0;
// make a new state so SOC can't interefere with scripts
// allocate state
L = lua_newstate(LUA_Alloc, NULL);
lua_atpanic(L, LUA_Panic);
// open only enum lib
lua_pushcfunction(L, LUA_EnumLib);
lua_pushboolean(L, true);
lua_call(L, 1, 0);
// change ^ into ^^ for Lua.
strcpy(buf, "return ");
b = buf+strlen(buf);
@ -696,8 +693,23 @@ fixed_t LUA_EvalMath(const char *word)
}
*b = '\0';
// eval string.
if (fenv_ref == LUA_NOREF)
{
lua_createtable(L, 0, 1);
lua_getmetatable(L, LUA_GLOBALSINDEX);
lua_setmetatable(L, -2);
fenv_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
lua_settop(L, 0);
lua_pushthread(L);
lua_getref(L, fenv_ref);
lua_setfenv(L, 1);
lua_mathlib = true;
// eval string.
if (luaL_dostring(L, buf))
{
p = lua_tostring(L, -1);
@ -708,8 +720,11 @@ fixed_t LUA_EvalMath(const char *word)
else
res = lua_tointeger(L, -1);
// clean up and return.
lua_close(L);
lua_mathlib = false;
lua_pushvalue(L, LUA_GLOBALSINDEX);
lua_setfenv(L, 1);
return res;
}