diff --git a/src/deh_lua.c b/src/deh_lua.c index a2ffca95b0622826dd69d350c60dba52e221b0f9..0bd906c1321f2126740494e34c450bc6887d8c6c 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -10,20 +10,7 @@ /// \file deh_lua.c /// \brief Lua SOC library -#include "g_game.h" -#include "s_sound.h" -#include "z_zone.h" -#include "m_menu.h" -#include "m_misc.h" -#include "p_local.h" -#include "st_stuff.h" -#include "fastcmp.h" -#include "lua_script.h" -#include "lua_libs.h" - -#include "dehacked.h" #include "deh_lua.h" -#include "deh_tables.h" // freeslot takes a name (string only!) // and allocates it to the appropriate free slot. @@ -89,6 +76,8 @@ static inline int lib_freeslot(lua_State *L) strncpy(sprnames[j],word,4); //sprnames[j][4] = 0; used_spr[(j-SPR_FIRSTFREESLOT)/8] |= 1<<(j%8); // Okay, this sprite slot has been named now. + // Lua needs to update the value in _G if it exists + LUA_UpdateSprName(word, j); lua_pushinteger(L, j); r++; break; @@ -216,18 +205,27 @@ static int lib_dummysuper(lua_State *L) return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions being called by state changes!"); // convoluted, I know. @_@;; } -static inline int lib_getenum(lua_State *L) +static void CacheAndPushConstant(lua_State *L, const char *name, lua_Integer value) +{ + // "cache" into _G + lua_pushstring(L, name); + lua_pushinteger(L, value); + lua_rawset(L, LUA_GLOBALSINDEX); + // push + lua_pushinteger(L, value); +} + +// Search for a matching constant variable. +// Result is stored into _G for faster subsequent use. (Except for SPR_ in the SOC parser) +static int ScanConstants(lua_State *L, boolean mathlib, const char *word) { - const char *word, *p; + const char *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); + if (strlen(word) == 1) { // Assume sprite frame if length 1. if (*word >= 'A' && *word <= '~') { - lua_pushinteger(L, *word-'A'); + CacheAndPushConstant(L, word, *word-'A'); return 1; } if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word); @@ -237,7 +235,7 @@ static inline int lib_getenum(lua_State *L) p = word+3; for (i = 0; MOBJFLAG_LIST[i]; i++) if (fastcmp(p, MOBJFLAG_LIST[i])) { - lua_pushinteger(L, ((lua_Integer)1<<i)); + CacheAndPushConstant(L, word, ((lua_Integer)1<<i)); return 1; } if (mathlib) return luaL_error(L, "mobjflag '%s' could not be found.\n", word); @@ -247,7 +245,7 @@ static inline int lib_getenum(lua_State *L) p = word+4; for (i = 0; MOBJFLAG2_LIST[i]; i++) if (fastcmp(p, MOBJFLAG2_LIST[i])) { - lua_pushinteger(L, ((lua_Integer)1<<i)); + CacheAndPushConstant(L, word, ((lua_Integer)1<<i)); return 1; } if (mathlib) return luaL_error(L, "mobjflag2 '%s' could not be found.\n", word); @@ -257,12 +255,12 @@ static inline int lib_getenum(lua_State *L) p = word+4; for (i = 0; MOBJEFLAG_LIST[i]; i++) if (fastcmp(p, MOBJEFLAG_LIST[i])) { - lua_pushinteger(L, ((lua_Integer)1<<i)); + CacheAndPushConstant(L, word, ((lua_Integer)1<<i)); return 1; } if (fastcmp(p, "REVERSESUPER")) { - lua_pushinteger(L, (lua_Integer)MFE_REVERSESUPER); + CacheAndPushConstant(L, word, (lua_Integer)MFE_REVERSESUPER); return 1; } if (mathlib) return luaL_error(L, "mobjeflag '%s' could not be found.\n", word); @@ -272,7 +270,7 @@ static inline int lib_getenum(lua_State *L) p = word+4; for (i = 0; i < 4; i++) if (MAPTHINGFLAG_LIST[i] && fastcmp(p, MAPTHINGFLAG_LIST[i])) { - lua_pushinteger(L, ((lua_Integer)1<<i)); + CacheAndPushConstant(L, word, ((lua_Integer)1<<i)); return 1; } if (mathlib) return luaL_error(L, "mapthingflag '%s' could not be found.\n", word); @@ -282,17 +280,17 @@ static inline int lib_getenum(lua_State *L) p = word+3; for (i = 0; PLAYERFLAG_LIST[i]; i++) if (fastcmp(p, PLAYERFLAG_LIST[i])) { - lua_pushinteger(L, ((lua_Integer)1<<i)); + CacheAndPushConstant(L, word, ((lua_Integer)1<<i)); return 1; } if (fastcmp(p, "FULLSTASIS")) { - lua_pushinteger(L, (lua_Integer)PF_FULLSTASIS); + CacheAndPushConstant(L, word, (lua_Integer)PF_FULLSTASIS); return 1; } else if (fastcmp(p, "USEDOWN")) // Remove case when 2.3 nears release... { - lua_pushinteger(L, (lua_Integer)PF_SPINDOWN); + CacheAndPushConstant(L, word, (lua_Integer)PF_SPINDOWN); return 1; } if (mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word); @@ -302,7 +300,7 @@ static inline int lib_getenum(lua_State *L) p = word; for (i = 0; Gametype_ConstantNames[i]; i++) if (fastcmp(p, Gametype_ConstantNames[i])) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } if (mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word); @@ -312,7 +310,7 @@ static inline int lib_getenum(lua_State *L) p = word+4; for (i = 0; GAMETYPERULE_LIST[i]; i++) if (fastcmp(p, GAMETYPERULE_LIST[i])) { - lua_pushinteger(L, ((lua_Integer)1<<i)); + CacheAndPushConstant(L, word, ((lua_Integer)1<<i)); return 1; } if (mathlib) return luaL_error(L, "game type rule '%s' could not be found.\n", word); @@ -322,7 +320,7 @@ static inline int lib_getenum(lua_State *L) p = word+4; for (i = 0; TYPEOFLEVEL[i].name; i++) if (fastcmp(p, TYPEOFLEVEL[i].name)) { - lua_pushinteger(L, TYPEOFLEVEL[i].flag); + CacheAndPushConstant(L, word, TYPEOFLEVEL[i].flag); return 1; } if (mathlib) return luaL_error(L, "typeoflevel '%s' could not be found.\n", word); @@ -332,7 +330,7 @@ static inline int lib_getenum(lua_State *L) p = word+3; for (i = 0; i < 16; i++) if (ML_LIST[i] && fastcmp(p, ML_LIST[i])) { - lua_pushinteger(L, ((lua_Integer)1<<i)); + CacheAndPushConstant(L, word, ((lua_Integer)1<<i)); return 1; } if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word); @@ -344,13 +342,13 @@ static inline int lib_getenum(lua_State *L) if (!FREE_STATES[i]) break; if (fastcmp(p, FREE_STATES[i])) { - lua_pushinteger(L, S_FIRSTFREESLOT+i); + CacheAndPushConstant(L, word, S_FIRSTFREESLOT+i); return 1; } } for (i = 0; i < S_FIRSTFREESLOT; i++) if (fastcmp(p, STATE_LIST[i]+2)) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } return luaL_error(L, "state '%s' does not exist.\n", word); @@ -361,13 +359,13 @@ static inline int lib_getenum(lua_State *L) if (!FREE_MOBJS[i]) break; if (fastcmp(p, FREE_MOBJS[i])) { - lua_pushinteger(L, MT_FIRSTFREESLOT+i); + CacheAndPushConstant(L, word, MT_FIRSTFREESLOT+i); return 1; } } for (i = 0; i < MT_FIRSTFREESLOT; i++) if (fastcmp(p, MOBJTYPE_LIST[i]+3)) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } return luaL_error(L, "mobjtype '%s' does not exist.\n", word); @@ -376,7 +374,12 @@ static inline int lib_getenum(lua_State *L) p = word+4; for (i = 0; i < NUMSPRITES; i++) if (!sprnames[i][4] && fastncmp(p,sprnames[i],4)) { - lua_pushinteger(L, i); + // updating overridden sprnames is not implemented for soc parser, + // so don't use cache + if (mathlib) + lua_pushinteger(L, i); + else + CacheAndPushConstant(L, word, i); return 1; } if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word); @@ -391,12 +394,12 @@ static inline int lib_getenum(lua_State *L) // the spr2names entry will have "_" on the end, as in "RUN_" if (spr2names[i][3] == '_' && !p[3]) { if (fastncmp(p,spr2names[i],3)) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } } else if (fastncmp(p,spr2names[i],4)) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } } @@ -407,7 +410,7 @@ static inline int lib_getenum(lua_State *L) p = word+4; for (i = 0; i < NUMSFX; i++) if (S_sfx[i].name && fastcmp(p, S_sfx[i].name)) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } return 0; @@ -416,7 +419,7 @@ static inline int lib_getenum(lua_State *L) p = word+4; for (i = 0; i < NUMSFX; i++) if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } return luaL_error(L, "sfx '%s' could not be found.\n", word); @@ -425,7 +428,7 @@ static inline int lib_getenum(lua_State *L) p = word+2; for (i = 0; i < NUMSFX; i++) if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } if (mathlib) return luaL_error(L, "sfx '%s' could not be found.\n", word); @@ -435,7 +438,7 @@ static inline int lib_getenum(lua_State *L) p = word+3; for (i = 0; i < NUMPOWERS; i++) if (fasticmp(p, POWERS_LIST[i])) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } return 0; @@ -444,7 +447,7 @@ static inline int lib_getenum(lua_State *L) p = word+3; for (i = 0; i < NUMPOWERS; i++) if (fastcmp(p, POWERS_LIST[i])) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } return luaL_error(L, "power '%s' could not be found.\n", word); @@ -453,7 +456,7 @@ static inline int lib_getenum(lua_State *L) p = word+4; for (i = 0; i < NUMHUDITEMS; i++) if (fastcmp(p, HUDITEMS_LIST[i])) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } if (mathlib) return luaL_error(L, "huditem '%s' could not be found.\n", word); @@ -465,13 +468,13 @@ static inline int lib_getenum(lua_State *L) if (!FREE_SKINCOLORS[i]) break; if (fastcmp(p, FREE_SKINCOLORS[i])) { - lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT+i); + CacheAndPushConstant(L, word, SKINCOLOR_FIRSTFREESLOT+i); return 1; } } for (i = 0; i < SKINCOLOR_FIRSTFREESLOT; i++) if (fastcmp(p, COLOR_ENUMS[i])) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } return luaL_error(L, "skincolor '%s' could not be found.\n", word); @@ -482,7 +485,7 @@ static inline int lib_getenum(lua_State *L) for (i = 0; NIGHTSGRADE_LIST[i]; i++) if (*p == NIGHTSGRADE_LIST[i]) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word); @@ -492,13 +495,41 @@ static inline int lib_getenum(lua_State *L) p = word+3; for (i = 0; i < NUMMENUTYPES; i++) if (fastcmp(p, MENUTYPES_LIST[i])) { - lua_pushinteger(L, i); + CacheAndPushConstant(L, word, i); return 1; } if (mathlib) return luaL_error(L, "menutype '%s' could not be found.\n", word); return 0; } - else if (!mathlib && fastncmp("A_",word,2)) { + + if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release... + { + CacheAndPushConstant(L, word, (lua_Integer)BT_SPIN); + return 1; + } + + for (i = 0; INT_CONST[i].n; i++) + if (fastcmp(word,INT_CONST[i].n)) { + CacheAndPushConstant(L, word, INT_CONST[i].v); + return 1; + } + + return 0; +} + +static inline int lib_getenum(lua_State *L) +{ + const char *word; + 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); + + // check actions, super and globals first, as they don't have _G caching implemented + // so they benefit from being checked first + + if (!mathlib && fastncmp("A_",word,2)) { char *caps; // Try to get a Lua action first. /// \todo Push a closure that sets superactions[] and superstack. @@ -537,25 +568,33 @@ static inline int lib_getenum(lua_State *L) } return 0; } - - if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release... - { - lua_pushinteger(L, (lua_Integer)BT_SPIN); + else if ((!mathlib && LUA_PushGlobals(L, word)) || ScanConstants(L, mathlib, word)) return 1; - } - - for (i = 0; INT_CONST[i].n; i++) - if (fastcmp(word,INT_CONST[i].n)) { - lua_pushinteger(L, INT_CONST[i].v); - return 1; - } if (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. - // You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime. - return LUA_PushGlobals(L, word); + return 0; +} + +// If a sprname has been "cached" to _G, update it to a new value. +void LUA_UpdateSprName(const char *name, lua_Integer value) +{ + char fullname[9] = "SPR_XXXX"; + + if (!gL) + return; + + strncpy(&fullname[4], name, 4); + lua_pushstring(gL, fullname); + lua_rawget(gL, LUA_GLOBALSINDEX); + + if (!lua_isnil(gL, -1)) + { + lua_pop(gL, 1); + lua_pushstring(gL, name); + lua_pushinteger(gL, value); + lua_rawset(gL, LUA_GLOBALSINDEX); + } } int LUA_EnumLib(lua_State *L) diff --git a/src/deh_lua.h b/src/deh_lua.h index 9df4028bdcf9619a14fe267d202aed2343125e2f..76c68860f3a1cb069d6f496c068881ec53aae673 100644 --- a/src/deh_lua.h +++ b/src/deh_lua.h @@ -13,6 +13,21 @@ #ifndef __DEH_LUA_H__ #define __DEH_LUA_H__ +#include "g_game.h" +#include "s_sound.h" +#include "z_zone.h" +#include "m_menu.h" +#include "m_misc.h" +#include "p_local.h" +#include "st_stuff.h" +#include "fastcmp.h" +#include "lua_script.h" +#include "lua_libs.h" + +#include "dehacked.h" +#include "deh_tables.h" + +void LUA_UpdateSprName(const char *name, lua_Integer value); boolean LUA_SetLuaAction(void *state, const char *actiontocompare); const char *LUA_GetActionName(void *action); void LUA_SetActionByName(void *state, const char *actiontocompare); diff --git a/src/deh_soc.c b/src/deh_soc.c index 3a611f3ba18daaacd3c9f5154505176f3a1ad4cd..e1979789e8774e41a7d3fd1a8d1ebfa3789f98cc 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -45,6 +45,7 @@ #include "dehacked.h" #include "deh_soc.h" #include "deh_lua.h" // included due to some LUA_SetLuaAction hack smh +// also used for LUA_UpdateSprName #include "deh_tables.h" // Loops through every constant and operation in word and performs its calculations, returning the final value. @@ -439,6 +440,8 @@ void readfreeslots(MYFILE *f) strncpy(sprnames[i],word,4); //sprnames[i][4] = 0; used_spr[(i-SPR_FIRSTFREESLOT)/8] |= 1<<(i%8); // Okay, this sprite slot has been named now. + // Lua needs to update the value in _G if it exists + LUA_UpdateSprName(word, i); break; } } diff --git a/src/lua_script.c b/src/lua_script.c index a1376ca2e37fbdad25f9c2db6fb34907e87c8cdd..d7670fe35144be538d2691654be44dbfedffd502 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -694,20 +694,23 @@ void LUA_DumpFile(const char *filename) fixed_t LUA_EvalMath(const char *word) { - lua_State *L = NULL; + static lua_State *L = NULL; 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); + if (!L) + { + // 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 "); @@ -732,8 +735,6 @@ fixed_t LUA_EvalMath(const char *word) else res = lua_tointeger(L, -1); - // clean up and return. - lua_close(L); return res; }