From fd1efff338b716132a14535bf8c97708a2b2bb32 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 17 May 2017 20:36:40 +0100 Subject: [PATCH] Added the META_ACTION userdata type to Lua, created getActionName() to return string name SRB2's built-in action types will now all be pushed as META_ACTION, state_t.action can be assigned META_ACTION and return it getUserdataType returns "action" for META_ACTION variables --- src/dehacked.c | 35 +++++++++++++++++++++++++++-------- src/lua_baselib.c | 2 ++ src/lua_infolib.c | 27 ++++++++++++++++++++++++--- src/lua_libs.h | 2 ++ 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index aa6f4f7f9..071f1bcfe 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8263,11 +8263,11 @@ static inline int lib_freeslot(lua_State *L) } // Wrapper for ALL A_Action functions. -// Upvalue: actionf_t to represent // Arguments: mobj_t actor, int var1, int var2 -static inline int lib_action(lua_State *L) +static int action_call(lua_State *L) { - actionf_t *action = lua_touserdata(L,lua_upvalueindex(1)); + //actionf_t *action = lua_touserdata(L,lua_upvalueindex(1)); + actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L,1,META_MOBJ)); var1 = (INT32)luaL_optinteger(L,2,0); var2 = (INT32)luaL_optinteger(L,3,0); @@ -8547,9 +8547,8 @@ static inline int lib_getenum(lua_State *L) // Retrieving them from this metatable allows them to be case-insensitive! for (i = 0; actionpointers[i].name; i++) if (fasticmp(word, actionpointers[i].name)) { - // push lib_action as a C closure with the actionf_t* as an upvalue. - lua_pushlightuserdata(L, &actionpointers[i].action); - lua_pushcclosure(L, lib_action, 1); + // We push the actionf_t* itself as userdata! + LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION); return 1; } return 0; @@ -8563,8 +8562,7 @@ static inline int lib_getenum(lua_State *L) } for (i = 0; actionpointers[i].name; i++) if (fasticmp(superactions[superstack-1], actionpointers[i].name)) { - lua_pushlightuserdata(L, &actionpointers[i].action); - lua_pushcclosure(L, lib_action, 1); + LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION); return 1; } return 0; @@ -8688,9 +8686,30 @@ int LUA_EnumLib(lua_State *L) return 0; } +// getActionName(action) -> return action's string name +static int lib_getActionName(lua_State *L) +{ + actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION)); + const char *name = NULL; + if (!action) + return 0; // insert error here (or not?) + name = LUA_GetActionName(action); + if (!name) // that can't be right? + return 0; + lua_pushstring(L, name); + return 1; +} + int LUA_SOCLib(lua_State *L) { lua_register(L,"freeslot",lib_freeslot); + lua_register(L,"getActionName",lib_getActionName); + + luaL_newmetatable(L, META_ACTION); + lua_pushcfunction(L, action_call); + lua_setfield(L, -2, "__call"); + lua_pop(L, 1); + return 0; } diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 93f2979fa..2a129c88a 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -131,6 +131,8 @@ static const struct { {META_PATCH, "patch_t"}, {META_COLORMAP, "colormap"}, {META_CAMERA, "camera_t"}, + + {META_ACTION, "action"}, {NULL, NULL} }; diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 9361abe94..3edd6cc2f 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -244,6 +244,17 @@ static int lib_setState(lua_State *L) case LUA_TSTRING: // It's a string, expect the name of a built-in action LUA_SetActionByName(state, lua_tostring(L, 3)); break; + case LUA_TUSERDATA: // It's a userdata, expect META_ACTION of a built-in action + { + actionf_t *action = *((actionf_t **)luaL_checkudata(L, 3, META_ACTION)); + + if (!action) + return 0; //insert error here + + state->action = *action; + state->action.acv = action->acv; + state->action.acp1 = action->acp1; + } case LUA_TFUNCTION: // It's a function (a Lua function or a C function? either way!) lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION); I_Assert(lua_istable(L, -1)); @@ -393,9 +404,8 @@ static int state_get(lua_State *L) return 0; // Just what is this?? // get the function from the global // because the metatable will trigger. - lua_getglobal(L, name); // actually gets from LREG_ACTIONS if applicable, and pushes a new C closure if not. - lua_pushstring(L, name); // push the name we found. - return 2; // return both the function and its name, in case somebody wanted to do a comparison by name or something? + lua_getglobal(L, name); // actually gets from LREG_ACTIONS if applicable, and pushes a META_ACTION userdata if not. + return 1; // return just the function } else if (fastcmp(field,"var1")) number = st->var1; else if (fastcmp(field,"var2")) @@ -439,6 +449,17 @@ static int state_set(lua_State *L) case LUA_TSTRING: // It's a string, expect the name of a built-in action LUA_SetActionByName(st, lua_tostring(L, 3)); break; + case LUA_TUSERDATA: // It's a userdata, expect META_ACTION of a built-in action + { + actionf_t *action = *((actionf_t **)luaL_checkudata(L, 3, META_ACTION)); + + if (!action) + return 0; //insert error here + + st->action = *action; + st->action.acv = action->acv; + st->action.acp1 = action->acp1; + } case LUA_TFUNCTION: // It's a function (a Lua function or a C function? either way!) lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION); I_Assert(lua_istable(L, -1)); diff --git a/src/lua_libs.h b/src/lua_libs.h index fd4937b63..b63a3ceed 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -60,6 +60,8 @@ extern lua_State *gL; #define META_COLORMAP "COLORMAP" #define META_CAMERA "CAMERA_T*" +#define META_ACTION "ACTIONF_T*" + boolean luaL_checkboolean(lua_State *L, int narg); int LUA_EnumLib(lua_State *L);