From 3f9d64717db75460a6e212371aadad3d245adc95 Mon Sep 17 00:00:00 2001 From: xyzzy Date: Thu, 31 Aug 2023 23:16:32 +0300 Subject: [PATCH 1/6] Create a Lua globals library. --- src/CMakeLists.txt | 2 + src/blua/Makefile.cfg | 3 +- src/lua_glib.c | 304 ++++++++++++++++++++++++++++++++++++++++++ src/lua_glib.h | 141 ++++++++++++++++++++ 4 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 src/lua_glib.c create mode 100644 src/lua_glib.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 88231fc03..40e317031 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -270,6 +270,7 @@ if(${SRB2_CONFIG_HAVE_BLUA}) lua_skinlib.c lua_thinkerlib.c lua_udatalib.c + lua_glib.c ) set(SRB2_LUA_HEADERS lua_hook.h @@ -278,6 +279,7 @@ if(${SRB2_CONFIG_HAVE_BLUA}) lua_libs.h lua_script.h lua_udatalib.h + lua_glib.h ) prepend_sources(SRB2_LUA_SOURCES) diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg index fb3662592..a7146c79e 100644 --- a/src/blua/Makefile.cfg +++ b/src/blua/Makefile.cfg @@ -52,4 +52,5 @@ OBJS:=$(OBJS) \ $(OBJDIR)/lua_maplib.o \ $(OBJDIR)/lua_hudlib.o \ $(OBJDIR)/lua_hudlib_drawlist.o \ - $(OBJDIR)/lua_udatalib.o + $(OBJDIR)/lua_udatalib.o \ + $(OBJDIR)/lua_glib.o diff --git a/src/lua_glib.c b/src/lua_glib.c new file mode 100644 index 000000000..771ef4859 --- /dev/null +++ b/src/lua_glib.c @@ -0,0 +1,304 @@ +#include "lua_glib.h" + +#define GLIB_DATABASE_GUID "{cf75e032-00c8-4887-b15f-87b755784ad3}" + #define GLIB_DATABASE_GETTERS "getters" + #define GLIB_DATABASE_SETTERS "setters" + #define GLIB_DATABASE_ENUMS "enums" + #define GLIB_DATABASE_CACHE "cache" + #define GLIB_DATABASE_MTABLE "metatable" + +static inline void lua_glib_push_db(lua_State *L) +{ + lua_pushliteral(L, GLIB_DATABASE_GUID); + lua_gettable(L, LUA_REGISTRYINDEX); +} + +/** + * Copy table contents to another. + * @param L[1] Destination table. + * @param L[2] Source table. + */ +static int lua_glib_copy_table(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TTABLE); + + lua_pushnil(L); + while (lua_next(L, 2)) + { + lua_pushvalue(L, -2); /* Push key. */ + lua_pushvalue(L, -2); /* Push value. */ + lua_settable(L, 1); /* Store at dst. */ + + lua_pop(L, 1); /* Pop the value. */ + } + + return 0; +} + +static int lua_glib___index(lua_State *L) +{ + /* function mt:__index(key) */ + + const int CACHE = lua_upvalueindex(1); /* Enum cache. */ + const int GETTERS = lua_upvalueindex(2); /* Storage for getters. */ + const int ENUMS = lua_upvalueindex(3); /* Enum fallback cache. */ + + if (!lua_isstring(L, 1)) + { + /* A non string key should not happen. But somebody might really want it. */ + return 0; + } + + /* Attempt cache lookup. */ + + lua_pushvalue(L, 1); + lua_gettable(L, CACHE); + if (!lua_isnil(L, -1)) + { + return 1; + } + + lua_pop(L, 1); + + /* Attempt a get property. */ + + lua_pushvalue(L, 1); + lua_gettable(L, GETTERS); + if (lua_isfunction(L, -1)) + { + lua_call(L, 0, 1); + return 1; + } + + /* Try finding a the relevant enum fallback function. */ + const char *str = lua_tostring(L, 1); + int sz = lua_strlen(L, 1); + for (int i = 1; i < sz; i++) + { + lua_pushlstring(L, str, i); + lua_gettable(L, ENUMS); + + if (lua_isfunction(L, -1)) + { + lua_pushvalue(L, 1); + lua_call(L, 1, 1); + + /* Store value in cache. */ + lua_pushvalue(L, 1); + lua_pushvalue(L, -2); + lua_settable(L, CACHE); + + /* Return it. */ + return 1; + } + else + { + lua_pop(L, 1); + } + } + + /* This really does not exist. Returns nil. */ + return 0; +} + +static int lua_glib___newindex(lua_State *L) +{ + /* function mt:__newindex(key, value) */ + + const int SETTERS = lua_upvalueindex(1); + + lua_pushvalue(L, 1); + lua_gettable(L, SETTERS); + if (!lua_isfunction(L, -1)) + { + return luaL_error(L, "You cannot set the global table except known writeable properties. If this isn't a mistake use `rawset(_G, k, v)`."); + } + + /* Set the property. */ + lua_pushvalue(L, 2); + lua_call(L, 1, 0); + return 0; +} + +int lua_glib_require(lua_State *L) +{ + lua_pushliteral(L, GLIB_DATABASE_GUID); + lua_newtable(L); + /* Standard functions. */ + lua_pushliteral(L, GLIB_DATABASE_GETTERS); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushliteral(L, GLIB_DATABASE_SETTERS); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushliteral(L, GLIB_DATABASE_ENUMS); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushliteral(L, GLIB_DATABASE_CACHE); + lua_newtable(L); + lua_settable(L, -3); + + lua_pushliteral(L, GLIB_DATABASE_MTABLE); + lua_newtable(L); + lua_pushliteral(L, "__index"); + lua_pushliteral(L, GLIB_DATABASE_CACHE); + lua_gettable(L, -5); + + lua_pushliteral(L, GLIB_DATABASE_GETTERS); + lua_gettable(L, -6); + + lua_pushliteral(L, GLIB_DATABASE_ENUMS); + lua_gettable(L, -7); + + lua_pushcclosure(L, lua_glib___index, 3); + lua_settable(L, -3); /* __index */ + + lua_pushliteral(L, "__newindex"); + lua_pushliteral(L, GLIB_DATABASE_SETTERS); + lua_gettable(L, -5); + + lua_pushcclosure(L, lua_glib___newindex, 1); + lua_settable(L, -3); /* __newindex */ + + lua_settable(L, -3); /* GLIB_DATABASE_MTABLE. */ + + lua_settable(L, LUA_REGISTRYINDEX); /* GLIB_DATABASE_GUID. */ + + /* Set global metatable. */ + lua_glib_push_db(L); + lua_pushliteral(L, GLIB_DATABASE_MTABLE); + lua_gettable(L, -2); + lua_setmetatable(L, LUA_GLOBALSINDEX); + + return 0; +} + +int lua_glib_new_enum(lua_State *L) +{ + lua_glib_push_db(L); + + if (lua_istable(L, 1)) + { + /* copy_table(dst, src) */ + + lua_pushcfunction(L, lua_glib_copy_table); + + lua_pushliteral(L, GLIB_DATABASE_CACHE); + lua_gettable(L, -3); /* dst */ + + lua_pushvalue(L, 1); /* src */ + lua_call(L, 2, 0); + } + + if (lua_isstring(L, 2) && lua_isfunction(L, 3)) + { + lua_pushliteral(L, GLIB_DATABASE_ENUMS); + lua_gettable(L, -2); + + lua_pushvalue(L, 1); /* prefix */ + lua_pushvalue(L, 3); /* fallback */ + } + + return 0; +} + +int lua_glib_new_getter(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TSTRING); + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_glib_push_db(L); + lua_pushliteral(L, GLIB_DATABASE_GETTERS); + lua_gettable(L, -2); + + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + lua_settable(L, -3); + + return 0; +} + +int lua_glib_new_setter(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TSTRING); + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_glib_push_db(L); + lua_pushliteral(L, GLIB_DATABASE_SETTERS); + lua_gettable(L, -2); + + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + lua_settable(L, -3); + + return 0; +} + +#define _GLIB_DECL_INT_GETTER(T, name) \ + int lua_glib_getter_##name(lua_State *L) { \ + const T* ptr = (const T*)lua_topointer(L, lua_upvalueindex(1)); \ + lua_pushinteger(L, (lua_Integer)*ptr); \ + return 1; \ + } + +#define _GLIB_DECL_INT_SETTER(T, name) \ + int lua_glib_setter_##name(lua_State *L) { \ + luaL_checktype(L, 1, LUA_TNUMBER); \ + T* ptr = (T*)lua_topointer(L, lua_upvalueindex(1)); \ + *ptr = (T)lua_tointeger(L, 1); \ + return 1; \ + } + +#define _GLIB_DECL_FLOAT_GETTER(T, name) \ + int lua_glib_getter_##name(lua_State *L) { \ + const T* ptr = (const T*)lua_topointer(L, lua_upvalueindex(1)); \ + lua_pushnumber(L, (lua_Number)*ptr); \ + return 1; \ + } + +#define _GLIB_DECL_FLOAT_SETTER(T, name) \ + int lua_glib_setter_##name(lua_State *L) { \ + luaL_checktype(L, 1, LUA_TNUMBER); \ + T* ptr = (T*)lua_topointer(L, lua_upvalueindex(1)); \ + *ptr = (T)lua_tonumber(L, 1); \ + return 1; \ + } + +_GLIB_DECL_INT_GETTER(int8_t, i8); +_GLIB_DECL_INT_GETTER(int16_t, i16); +_GLIB_DECL_INT_GETTER(int32_t, i32); +_GLIB_DECL_INT_GETTER(int64_t, i64); +_GLIB_DECL_INT_GETTER(uint8_t, u8); +_GLIB_DECL_INT_GETTER(uint16_t, u16); +_GLIB_DECL_INT_GETTER(uint32_t, u32); +_GLIB_DECL_INT_GETTER(uint64_t, u64); +_GLIB_DECL_FLOAT_GETTER(float, f32); +_GLIB_DECL_FLOAT_GETTER(double, f64); + +_GLIB_DECL_INT_SETTER(int8_t, i8); +_GLIB_DECL_INT_SETTER(int16_t, i16); +_GLIB_DECL_INT_SETTER(int32_t, i32); +_GLIB_DECL_INT_SETTER(int64_t, i64); +_GLIB_DECL_INT_SETTER(uint8_t, u8); +_GLIB_DECL_INT_SETTER(uint16_t, u16); +_GLIB_DECL_INT_SETTER(uint32_t, u32); +_GLIB_DECL_INT_SETTER(uint64_t, u64); +_GLIB_DECL_FLOAT_SETTER(float, f32); +_GLIB_DECL_FLOAT_SETTER(double, f64); + +int lua_glib_getter_str(lua_State *L) +{ + const char *str = (const char*)lua_topointer(L, lua_upvalueindex(1)); + lua_pushstring(L, str); + return 1; +} + +int lua_glib_getter_ptr(lua_State *L) +{ + lua_pushvalue(L, lua_upvalueindex(1)); + return 1; +} diff --git a/src/lua_glib.h b/src/lua_glib.h new file mode 100644 index 000000000..bb23e543c --- /dev/null +++ b/src/lua_glib.h @@ -0,0 +1,141 @@ +/** + * @file lua_glib.h Lua global table field management library. + */ +#ifndef _LUA_GLIB_H_ +#define _LUA_GLIB_H_ + +#include "lua_script.h" + +/** + * Create a new enum. + * @param L[1] The cache table for the enum. + * @param L[2] The prefix for the enum. + * @param L[3] The fallback function for the enum. Can be nil. + * @returns Nothing. + */ +int lua_glib_new_enum(lua_State *L); + +/** + * Create a new getter. + * @param L[1] The name of the getter. + * @param L[2] The getter() function. + * @returns Nothing. + */ +int lua_glib_new_getter(lua_State *L); + +/** + * Create a new setter. + * @param L[1] The name of the setter. + * @param L[2] The setter(value) function. + */ +int lua_glib_new_setter(lua_State *L); + +/** + * Require the globals library. + * @remarks This is a standard Lua require function. + */ +int lua_glib_require(lua_State *L); + +/** + * Helper function to push a linear enum cache. + * @param L The Lua state. + * @param prefix enum prefix. + * @param list Enum list. + * @param count Number of elements in list. INT_MAX for NULL termination. + */ +inline static void lua_glib_push_linear_cache(lua_State *L, const char *prefix, const char * const *list, lua_Integer count) +{ + lua_newtable(L); + for (lua_Integer i = 0; i < count && list[i]; i++) + { + lua_pushfstring(L, "%s%s", prefix, list[i]); + lua_pushvalue(L, i); + lua_settable(L, -3); + } +} + +/** + * Helper function to push a bitfield enum cache. + * @param L The Lua state. + * @param prefix enum prefix. + * @param list Enum list. + * @param count Number of elements in list. INT_MAX for NULL termination. + */ +inline static void lua_glib_push_bitfield_cache(lua_State *L, const char *prefix, const char * const *list, lua_Integer count) +{ + lua_newtable(L); + for (lua_Integer i = 0; i < count && list[i]; i++) + { + lua_pushfstring(L, "%s%s", prefix, list[i]); + lua_pushvalue(L, (lua_Integer)1 << i); + lua_settable(L, -3); + } +} + +/* Base getters. */ + +int lua_glib_getter_i8(lua_State *L); +int lua_glib_getter_i16(lua_State *L); +int lua_glib_getter_i32(lua_State *L); +int lua_glib_getter_i64(lua_State *L); +int lua_glib_getter_u8(lua_State *L); +int lua_glib_getter_u16(lua_State *L); +int lua_glib_getter_u32(lua_State *L); +int lua_glib_getter_u64(lua_State *L); +int lua_glib_getter_f32(lua_State *L); +int lua_glib_getter_f64(lua_State *L); +int lua_glib_getter_str(lua_State *L); +int lua_glib_getter_ptr(lua_State *L); + +/* Base setters. */ + +int lua_glib_setter_i8(lua_State *L); +int lua_glib_setter_i16(lua_State *L); +int lua_glib_setter_i32(lua_State *L); +int lua_glib_setter_i64(lua_State *L); +int lua_glib_setter_u8(lua_State *L); +int lua_glib_setter_u16(lua_State *L); +int lua_glib_setter_u32(lua_State *L); +int lua_glib_setter_u64(lua_State *L); +int lua_glib_setter_f32(lua_State *L); +int lua_glib_setter_f64(lua_State *L); + +#define _LUA_GLIB_DECL_PGETTER(T, name) \ + static inline void lua_glib_push_##name##_getter(lua_State *L, const T* ptr) { \ + lua_pushlightuserdata(L, (void*)ptr); \ + lua_pushcclosure(L, lua_glib_getter_##name, 1); \ + } + + _LUA_GLIB_DECL_PGETTER(int8_t, i8); + _LUA_GLIB_DECL_PGETTER(int16_t, i16); + _LUA_GLIB_DECL_PGETTER(int32_t, i32); + _LUA_GLIB_DECL_PGETTER(int64_t, i64); + _LUA_GLIB_DECL_PGETTER(uint8_t, u8); + _LUA_GLIB_DECL_PGETTER(uint16_t, u16); + _LUA_GLIB_DECL_PGETTER(uint32_t, u32); + _LUA_GLIB_DECL_PGETTER(uint64_t, u64); + _LUA_GLIB_DECL_PGETTER(float, f32); + _LUA_GLIB_DECL_PGETTER(double, f64); + _LUA_GLIB_DECL_PGETTER(char, str); + _LUA_GLIB_DECL_PGETTER(void, ptr); +#undef _LUA_GLIB_DECL_PGETTER + +#define _LUA_GLIB_DECL_PSETTER(T, name) \ + static inline void lua_glib_push_##name##_setter(lua_State *L, T* ptr) { \ + lua_pushlightuserdata(L, ptr); \ + lua_pushcclosure(L, lua_glib_setter_##name, 1); \ + } + + _LUA_GLIB_DECL_PSETTER(int8_t, i8); + _LUA_GLIB_DECL_PSETTER(int16_t, i16); + _LUA_GLIB_DECL_PSETTER(int32_t, i32); + _LUA_GLIB_DECL_PSETTER(int64_t, i64); + _LUA_GLIB_DECL_PSETTER(uint8_t, u8); + _LUA_GLIB_DECL_PSETTER(uint16_t, u16); + _LUA_GLIB_DECL_PSETTER(uint32_t, u32); + _LUA_GLIB_DECL_PSETTER(uint64_t, u64); + _LUA_GLIB_DECL_PSETTER(float, f32); + _LUA_GLIB_DECL_PSETTER(double, f64); +#undef _LUA_GLIB_DECL_PSETTER + +#endif -- 2.54.0 From 49949309dfb3cd616c7d934b7e812985a0926ad2 Mon Sep 17 00:00:00 2001 From: xyzzy Date: Sat, 2 Sep 2023 19:30:53 +0300 Subject: [PATCH 2/6] Some fixes and feature additions to glib. --- src/lua_glib.c | 119 ++++++++++++++++++++++++++++++++++++++++--------- src/lua_glib.h | 37 ++++++++++++++- 2 files changed, 133 insertions(+), 23 deletions(-) diff --git a/src/lua_glib.c b/src/lua_glib.c index 771ef4859..c213230ec 100644 --- a/src/lua_glib.c +++ b/src/lua_glib.c @@ -1,11 +1,12 @@ #include "lua_glib.h" #define GLIB_DATABASE_GUID "{cf75e032-00c8-4887-b15f-87b755784ad3}" - #define GLIB_DATABASE_GETTERS "getters" - #define GLIB_DATABASE_SETTERS "setters" - #define GLIB_DATABASE_ENUMS "enums" - #define GLIB_DATABASE_CACHE "cache" - #define GLIB_DATABASE_MTABLE "metatable" + #define GLIB_DATABASE_GETTERS "getters" /* Table of getter functions. */ + #define GLIB_DATABASE_SETTERS "setters" /* Table of setter functions. */ + #define GLIB_DATABASE_ENUMS "enums" /* Table of enum fallback functions. */ + #define GLIB_DATABASE_CACHE "cache" /* Table of cached enum values. */ + #define GLIB_DATABASE_MTABLE "metatable" /* Metatable.*/ + #define GLIB_DATABASE_PROXY "proxy" /* Proxy table for the library that isn't the global table. */ static inline void lua_glib_push_db(lua_State *L) { @@ -13,6 +14,15 @@ static inline void lua_glib_push_db(lua_State *L) lua_gettable(L, LUA_REGISTRYINDEX); } +void lua_glib_get_proxy(lua_State *L) +{ + lua_pushliteral(L, GLIB_DATABASE_GUID); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushliteral(L, GLIB_DATABASE_PROXY); + lua_gettable(L, -2); + lua_remove(L, -2); +} + /** * Copy table contents to another. * @param L[1] Destination table. @@ -44,7 +54,7 @@ static int lua_glib___index(lua_State *L) const int GETTERS = lua_upvalueindex(2); /* Storage for getters. */ const int ENUMS = lua_upvalueindex(3); /* Enum fallback cache. */ - if (!lua_isstring(L, 1)) + if (!lua_isstring(L, 2)) { /* A non string key should not happen. But somebody might really want it. */ return 0; @@ -52,7 +62,7 @@ static int lua_glib___index(lua_State *L) /* Attempt cache lookup. */ - lua_pushvalue(L, 1); + lua_pushvalue(L, 2); lua_gettable(L, CACHE); if (!lua_isnil(L, -1)) { @@ -63,7 +73,7 @@ static int lua_glib___index(lua_State *L) /* Attempt a get property. */ - lua_pushvalue(L, 1); + lua_pushvalue(L, 2); lua_gettable(L, GETTERS); if (lua_isfunction(L, -1)) { @@ -72,8 +82,8 @@ static int lua_glib___index(lua_State *L) } /* Try finding a the relevant enum fallback function. */ - const char *str = lua_tostring(L, 1); - int sz = lua_strlen(L, 1); + const char *str = lua_tostring(L, 2); + int sz = lua_strlen(L, 2); for (int i = 1; i < sz; i++) { lua_pushlstring(L, str, i); @@ -81,11 +91,11 @@ static int lua_glib___index(lua_State *L) if (lua_isfunction(L, -1)) { - lua_pushvalue(L, 1); + lua_pushvalue(L, 2); lua_call(L, 1, 1); /* Store value in cache. */ - lua_pushvalue(L, 1); + lua_pushvalue(L, 2); lua_pushvalue(L, -2); lua_settable(L, CACHE); @@ -108,7 +118,7 @@ static int lua_glib___newindex(lua_State *L) const int SETTERS = lua_upvalueindex(1); - lua_pushvalue(L, 1); + lua_pushvalue(L, 2); lua_gettable(L, SETTERS); if (!lua_isfunction(L, -1)) { @@ -116,13 +126,34 @@ static int lua_glib___newindex(lua_State *L) } /* Set the property. */ - lua_pushvalue(L, 2); + lua_pushvalue(L, 3); lua_call(L, 1, 0); return 0; } +int lua_glib_append_cache(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_glib_push_db(L); + + lua_pushcfunction(L, lua_glib_copy_table); + lua_pushliteral(L, GLIB_DATABASE_CACHE); + lua_gettable(L, -3); + lua_pushvalue(L, 1); + lua_call(L, 2, 0); + + return 0; +} + int lua_glib_require(lua_State *L) { + if (!lua_isboolean(L, 1)) + { + /* Request loading the metatable by default. */ + lua_pushboolean(L, 1); + } + lua_pushliteral(L, GLIB_DATABASE_GUID); lua_newtable(L); /* Standard functions. */ @@ -163,16 +194,25 @@ int lua_glib_require(lua_State *L) lua_pushcclosure(L, lua_glib___newindex, 1); lua_settable(L, -3); /* __newindex */ - lua_settable(L, -3); /* GLIB_DATABASE_MTABLE. */ + lua_pushliteral(L, GLIB_DATABASE_PROXY); + lua_newtable(L); + lua_pushliteral(L, GLIB_DATABASE_MTABLE); + lua_gettable(L, -4); + lua_setmetatable(L, -2); /* get GLIB_DATABASE_MTABLE. */ + lua_settable(L, -3); /* GLIB_DATABASE_PROXY. */ + lua_settable(L, LUA_REGISTRYINDEX); /* GLIB_DATABASE_GUID. */ /* Set global metatable. */ - lua_glib_push_db(L); - lua_pushliteral(L, GLIB_DATABASE_MTABLE); - lua_gettable(L, -2); - lua_setmetatable(L, LUA_GLOBALSINDEX); + if (lua_toboolean(L, 1)) + { + lua_glib_push_db(L); + lua_pushliteral(L, GLIB_DATABASE_MTABLE); + lua_gettable(L, -2); + lua_setmetatable(L, LUA_GLOBALSINDEX); + } return 0; } @@ -199,8 +239,9 @@ int lua_glib_new_enum(lua_State *L) lua_pushliteral(L, GLIB_DATABASE_ENUMS); lua_gettable(L, -2); - lua_pushvalue(L, 1); /* prefix */ + lua_pushvalue(L, 2); /* prefix */ lua_pushvalue(L, 3); /* fallback */ + lua_settable(L, -3); } return 0; @@ -250,6 +291,13 @@ int lua_glib_new_setter(lua_State *L) luaL_checktype(L, 1, LUA_TNUMBER); \ T* ptr = (T*)lua_topointer(L, lua_upvalueindex(1)); \ *ptr = (T)lua_tointeger(L, 1); \ + return 0; \ + } + +#define _GLIB_DECL_BOOL_GETTER(T, name) \ + int lua_glib_getter_##name(lua_State *L) { \ + const T* ptr = (const T*)lua_topointer(L, lua_upvalueindex(1)); \ + lua_pushboolean(L, *ptr != 0); \ return 1; \ } @@ -265,7 +313,14 @@ int lua_glib_new_setter(lua_State *L) luaL_checktype(L, 1, LUA_TNUMBER); \ T* ptr = (T*)lua_topointer(L, lua_upvalueindex(1)); \ *ptr = (T)lua_tonumber(L, 1); \ - return 1; \ + return 0; \ + } + +#define _GLIB_DECL_BOOL_SETTER(T, name) \ + int lua_glib_setter_##name(lua_State *L) { \ + T* ptr = (T*)lua_topointer(L, lua_upvalueindex(1)); \ + *ptr = (T)lua_toboolean(L, 1); \ + return 0; \ } _GLIB_DECL_INT_GETTER(int8_t, i8); @@ -278,6 +333,10 @@ _GLIB_DECL_INT_GETTER(uint32_t, u32); _GLIB_DECL_INT_GETTER(uint64_t, u64); _GLIB_DECL_FLOAT_GETTER(float, f32); _GLIB_DECL_FLOAT_GETTER(double, f64); +_GLIB_DECL_BOOL_GETTER(uint8_t, b8); +_GLIB_DECL_BOOL_GETTER(uint16_t, b16); +_GLIB_DECL_BOOL_GETTER(uint32_t, b32); +_GLIB_DECL_BOOL_GETTER(uint64_t, b64); _GLIB_DECL_INT_SETTER(int8_t, i8); _GLIB_DECL_INT_SETTER(int16_t, i16); @@ -289,6 +348,24 @@ _GLIB_DECL_INT_SETTER(uint32_t, u32); _GLIB_DECL_INT_SETTER(uint64_t, u64); _GLIB_DECL_FLOAT_SETTER(float, f32); _GLIB_DECL_FLOAT_SETTER(double, f64); +_GLIB_DECL_BOOL_SETTER(uint8_t, b8); +_GLIB_DECL_BOOL_SETTER(uint16_t, b16); +_GLIB_DECL_BOOL_SETTER(uint32_t, b32); +_GLIB_DECL_BOOL_SETTER(uint64_t, b64); + +int lua_glib_setter_fxp(lua_State *L) +{ + fixed_t *fxp = (fixed_t*)lua_topointer(L, lua_upvalueindex(1)); + *fxp = lua_tointeger(L, 1); + return 0; +} + +int lua_glib_getter_fxp(lua_State *L) +{ + const fixed_t *fxp = (const fixed_t*)lua_topointer(L, lua_upvalueindex(1)); + lua_pushfixed(L, *fxp); + return 1; +} int lua_glib_getter_str(lua_State *L) { diff --git a/src/lua_glib.h b/src/lua_glib.h index bb23e543c..b38115bcf 100644 --- a/src/lua_glib.h +++ b/src/lua_glib.h @@ -6,6 +6,13 @@ #include "lua_script.h" +/** + * Feed a list of items to append to the enum cache. + * @param L[1] The table of tiems to add to the enum cache. + * @returns Nothing. + */ +int lua_glib_append_cache(lua_State *L); + /** * Create a new enum. * @param L[1] The cache table for the enum. @@ -32,10 +39,16 @@ int lua_glib_new_setter(lua_State *L); /** * Require the globals library. + * @param L[1] (optional) False to inhibit setting the global metatable. * @remarks This is a standard Lua require function. */ int lua_glib_require(lua_State *L); +/** + * Get the proxy table that can be used to get globals. + */ +void lua_glib_get_proxy(lua_State *L); + /** * Helper function to push a linear enum cache. * @param L The Lua state. @@ -49,7 +62,7 @@ inline static void lua_glib_push_linear_cache(lua_State *L, const char *prefix, for (lua_Integer i = 0; i < count && list[i]; i++) { lua_pushfstring(L, "%s%s", prefix, list[i]); - lua_pushvalue(L, i); + lua_pushinteger(L, i); lua_settable(L, -3); } } @@ -67,7 +80,7 @@ inline static void lua_glib_push_bitfield_cache(lua_State *L, const char *prefix for (lua_Integer i = 0; i < count && list[i]; i++) { lua_pushfstring(L, "%s%s", prefix, list[i]); - lua_pushvalue(L, (lua_Integer)1 << i); + lua_pushinteger(L, (lua_Integer)1 << i); lua_settable(L, -3); } } @@ -84,6 +97,11 @@ int lua_glib_getter_u32(lua_State *L); int lua_glib_getter_u64(lua_State *L); int lua_glib_getter_f32(lua_State *L); int lua_glib_getter_f64(lua_State *L); +int lua_glib_getter_b8(lua_State *L); +int lua_glib_getter_b16(lua_State *L); +int lua_glib_getter_b32(lua_State *L); +int lua_glib_getter_b64(lua_State *L); +int lua_glib_getter_fxp(lua_State *L); int lua_glib_getter_str(lua_State *L); int lua_glib_getter_ptr(lua_State *L); @@ -99,6 +117,11 @@ int lua_glib_setter_u32(lua_State *L); int lua_glib_setter_u64(lua_State *L); int lua_glib_setter_f32(lua_State *L); int lua_glib_setter_f64(lua_State *L); +int lua_glib_setter_b8(lua_State *L); +int lua_glib_setter_b16(lua_State *L); +int lua_glib_setter_b32(lua_State *L); +int lua_glib_setter_b64(lua_State *L); +int lua_glib_setter_fxp(lua_State *L); #define _LUA_GLIB_DECL_PGETTER(T, name) \ static inline void lua_glib_push_##name##_getter(lua_State *L, const T* ptr) { \ @@ -118,6 +141,11 @@ int lua_glib_setter_f64(lua_State *L); _LUA_GLIB_DECL_PGETTER(double, f64); _LUA_GLIB_DECL_PGETTER(char, str); _LUA_GLIB_DECL_PGETTER(void, ptr); + _LUA_GLIB_DECL_PGETTER(uint8_t, b8); + _LUA_GLIB_DECL_PGETTER(uint16_t, b16); + _LUA_GLIB_DECL_PGETTER(uint32_t, b32); + _LUA_GLIB_DECL_PGETTER(uint64_t, b64); + _LUA_GLIB_DECL_PGETTER(fixed_t, fxp); #undef _LUA_GLIB_DECL_PGETTER #define _LUA_GLIB_DECL_PSETTER(T, name) \ @@ -136,6 +164,11 @@ int lua_glib_setter_f64(lua_State *L); _LUA_GLIB_DECL_PSETTER(uint64_t, u64); _LUA_GLIB_DECL_PSETTER(float, f32); _LUA_GLIB_DECL_PSETTER(double, f64); + _LUA_GLIB_DECL_PSETTER(uint8_t, b8); + _LUA_GLIB_DECL_PSETTER(uint16_t, b16); + _LUA_GLIB_DECL_PSETTER(uint32_t, b32); + _LUA_GLIB_DECL_PSETTER(uint64_t, b64); + _LUA_GLIB_DECL_PSETTER(fixed_t, fxp); #undef _LUA_GLIB_DECL_PSETTER #endif -- 2.54.0 From 8420b2414c51ced00368adc437c41874641278a6 Mon Sep 17 00:00:00 2001 From: xyzzy Date: Sun, 3 Sep 2023 14:43:55 +0300 Subject: [PATCH 3/6] Change into a look up based system instead of whatever the fuck yanderedev suggested. --- src/dehacked.c | 1120 ++++++++++++++++++++++++++++++------------------ 1 file changed, 708 insertions(+), 412 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 925d69042..65922a4be 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -33,6 +33,7 @@ #include "r_sky.h" #include "fastcmp.h" #include "lua_script.h" +#include "lua_glib.h" #include "lua_hook.h" #include "d_clisrv.h" @@ -49,6 +50,8 @@ int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); #endif +#define REQUIRE_MATHLIB_GUID "{748fcbc8-6480-4013-ac4e-7afce6cab766}" + // Free slot names // The crazy word-reading stuff uses these. static char *FREE_STATES[NUMSTATEFREESLOTS]; @@ -9274,243 +9277,18 @@ static int lib_dummysuper(lua_State *L) static inline int lib_getenum(lua_State *L) { + const int UV_MATHLIB = lua_upvalueindex(1); + const int GLIB_PROXY = lua_upvalueindex(2); + const char *word, *p; fixed_t i; - boolean mathlib = lua_toboolean(L, lua_upvalueindex(1)); + boolean mathlib = lua_toboolean(L, UV_MATHLIB); 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'); - return 1; - } - if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word); - return 0; - } - else if (fastncmp("MF_", word, 3)) { - p = word+3; - for (i = 0; MOBJFLAG_LIST[i]; i++) - if (fastcmp(p, MOBJFLAG_LIST[i])) { - lua_pushinteger(L, ((lua_Integer)1< *size) + { + void *ptr = realloc(*buf, length+1); + if (!ptr) return NULL; + *buf = ptr; + *size = length+1; + + va_start(va, format); + vsnprintf(*buf, *size, format, va); + } + va_end(va); + + for (int i = 0; i < length; i++) + { + (*buf)[i] = toupper((*buf)[i]); + } + + return *buf; +} + +static int lua_enumlib_super_get(lua_State *L) +{ + /** + * TODO: I think there is still some improvement to be made here + * Not exactly sure how + */ + + if (!superstack) + { + lua_pushcfunction(L, lib_dummysuper); + return 1; + } + + for (int 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); + return 1; + } + + return 0; +} + +#define ARRAYLEN(arr) (sizeof(arr)/sizeof(*arr)) + 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_setfield(L, -2, "__index"); + int mathlib = lua_toboolean(L, 1); + + /* Store mathlib requirement to the registry. */ + lua_pushliteral(L, REQUIRE_MATHLIB_GUID); + lua_pushvalue(L, 1); + lua_settable(L, LUA_REGISTRYINDEX); + + lua_pushcfunction(L, lua_glib_require); + lua_pushboolean(L, 0); /* Inhibit setting the globals table. */ + lua_call(L, 1, 0); + + /* Although lua_glib_require already adds a metatable, make a new one here. */ + lua_newtable(L); + lua_pushliteral(L, "__index"); + lua_pushvalue(L ,1); + lua_glib_get_proxy(L); + lua_pushcclosure(L, lib_getenum, 2); + lua_settable(L, -3); lua_setmetatable(L, LUA_GLOBALSINDEX); + + lua_pushcfunction(L, lua_glib_append_cache); + lua_createtable(L, 0, ('~'-'A'+1) + ARRAYLEN(INT_CONST)); + + /* Push frame constants. */ + for (char chr = 'A'; chr <= '~'; chr++) + { + lua_pushfstring(L, "%c", chr); + lua_pushinteger(L, chr-'A'); + lua_settable(L, -3); + } + + /* Push other constants. */ + for (int i = 0; INT_CONST[i].n; i++) + { + lua_pushstring(L, INT_CONST[i].n); + lua_pushinteger(L, INT_CONST[i].v); + lua_settable(L, -3); + } + + lua_pushliteral(L, "VERSIONSTRING"); + lua_pushliteral(L, VERSIONSTRING); + lua_settable(L, -3); + + // TODO: ADD constant errors. + lua_call(L, 1, 0); + + /* MOBJFLAG (MF_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_glib_push_bitfield_cache(L, "MF_", MOBJFLAG_LIST, ARRAYLEN(MOBJFLAG_LIST)); + lua_pushliteral(L, "MF_"); + lua_pushliteral(L, "mobjflag"); + lua_pushcclosure(L, lua_enumlib_basic_fallback, 1); + lua_call(L, 3, 0); + + /* MOBJFLAG2 (MF2_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_glib_push_bitfield_cache(L, "MF2_", MOBJFLAG2_LIST, ARRAYLEN(MOBJFLAG2_LIST)); + lua_pushliteral(L, "MF2_"); + lua_pushliteral(L, "mobjflag2"); + lua_pushcclosure(L, lua_enumlib_basic_fallback, 1); + lua_call(L, 3, 0); + + /* MOBJEFLAG (MFE_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_glib_push_bitfield_cache(L, "MFE_", MOBJEFLAG_LIST, ARRAYLEN(MOBJEFLAG_LIST)); + lua_pushliteral(L, "MFE_"); + lua_pushliteral(L, "mobjeflag"); + lua_pushcclosure(L, lua_enumlib_basic_fallback, 1); + lua_call(L, 3, 0); + + /* mapthingflag (MTF_) */ + /* Because MTF_ flags array is stinky you have to do it manually :(*/ + lua_pushcfunction(L, lua_glib_new_enum); + lua_createtable(L, 0, 3); + for (int i = 1; i < 4; i++) + { + lua_pushfstring(L, "MTF_%s", MAPTHINGFLAG_LIST[i]); + lua_pushinteger(L, (lua_Integer)1 << i); + lua_settable(L, -3); + } + lua_pushliteral(L, "MTF_"); + lua_pushliteral(L, "mapthingflag"); + lua_pushcclosure(L, lua_enumlib_basic_fallback, 1); + lua_call(L, 3, 0); + + /* playerflag (PF_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_glib_push_bitfield_cache(L, "PF_", PLAYERFLAG_LIST, ARRAYLEN(PLAYERFLAG_LIST)); + lua_pushliteral(L, "PF_FULLSTASIS"); + lua_pushinteger(L, PF_FULLSTASIS); + lua_settable(L, -3); + lua_pushliteral(L, "PF_"); + lua_pushliteral(L, "playerflag"); + lua_pushcclosure(L, lua_enumlib_basic_fallback, 1); + lua_call(L, 3, 0); + + /* linedef flag (ML_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_glib_push_bitfield_cache(L, "ML_", ML_LIST, 16); + lua_pushliteral(L, "ML_NETONLY"); + lua_pushinteger(L, ML_NETONLY); + lua_settable(L, -3); + lua_pushliteral(L, "ML_"); + lua_pushliteral(L, "linedef flag"); + lua_pushcclosure(L, lua_enumlib_basic_fallback, 1); + lua_call(L, 3, 0); + + /* States (S_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_glib_push_linear_cache(L, "", STATE_LIST, S_FIRSTFREESLOT); + lua_pushliteral(L, "S_"); + lua_pushcfunction(L, lua_enumlib_state_get); + lua_call(L, 3, 0); + + /* Mobj Types (MT_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_glib_push_linear_cache(L, "", MOBJTYPE_LIST, MT_FIRSTFREESLOT); + lua_pushliteral(L, "MT_"); + lua_pushcfunction(L, lua_enumlib_mobjtype_get); + lua_call(L, 3, 0); + + /* Sprites (SPR_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_newtable(L); + for (int i = 0; i < SPR_FIRSTFREESLOT; i++) + { + lua_pushfstring(L,"SPR_%4s", &sprnames[i][0]); + lua_pushinteger(L, i); + lua_settable(L, -3); + } + lua_pushliteral(L, "SPR_"); + lua_pushcfunction(L, lua_enumlib_sprite_get); + lua_call(L, 3, 0); + + if (mathlib) + { + char *str = NULL; + int size = 0; + + /* SFX (SFX_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_createtable(L, 0, NUMSFX); + for (int i = 0; i < NUMSFX; i++) + { + if (!S_sfx[i].name) continue; + + if (lua_enumlib_sprintf_upper(&str, &size, "SFX_%s", S_sfx[i].name) == NULL) + return luaL_error(L, "Ran out of memory."); + + lua_pushstring(L, str); + lua_pushinteger(L, i); + lua_settable(L, -3); + } + lua_pushliteral(L, "SFX_"); + lua_pushcfunction(L, lua_enumlib_sfx_get_uppercase); + lua_call(L, 3, 0); + + /* SFX (DS) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_createtable(L, 0, NUMSFX); + for (int i = 0; i < NUMSFX; i++) + { + if (!S_sfx[i].name) continue; + + if (lua_enumlib_sprintf_upper(&str, &size, "DS%s", S_sfx[i].name) == NULL) + return luaL_error(L, "Ran out of memory."); + + lua_pushstring(L, str); + lua_pushinteger(L, i); + lua_settable(L, -3); + } + lua_pushliteral(L, "DS"); + lua_pushcfunction(L, lua_enumlib_sfx_get_ds); + lua_call(L, 3, 0); + + #ifdef MUSICSLOT_COMPATIBILITY + /* Music (MUS_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_pushnil(L); + lua_pushliteral(L, "MUS_"); + lua_pushcfunction(L, lua_enumlib_mus_get_mathlib); + lua_call(L, 3, 0); + + /* Music (O_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_pushnil(L); + lua_pushliteral(L, "O_"); + lua_pushcfunction(L, lua_enumlib_mus_get_mathlib); + lua_call(L, 3, 0); + #endif + + free(str); + } + else + { + /* SFX (sfx_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_createtable(L, 0, NUMSFX); + for (int i = 0; i < NUMSFX; i++) + { + if (!S_sfx[i].name) continue; + + lua_pushfstring(L, "sfx_%s", S_sfx[i].name); + lua_pushinteger(L, i); + lua_settable(L, -3); + } + lua_pushliteral(L, "sfx_"); + lua_pushcfunction(L, lua_enumlib_sfx_get); + lua_call(L, 3, 0); + + #ifdef MUSICSLOT_COMPATIBILITY + /* SFX (mus_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_pushnil(L); + lua_pushliteral(L, "mus_"); + lua_pushcfunction(L, lua_enumlib_mus_get); + lua_call(L, 3, 0); + #endif + } + + /* Powers (pw_/PW_)*/ + lua_pushcfunction(L, lua_glib_new_enum); + lua_createtable(L, 0, NUMPOWERS); + for (int i = 0; i < NUMPOWERS; i++) + { + lua_pushfstring(L, mathlib ? "PW_%s": "pw_%s", POWERS_LIST[i]); + lua_pushinteger(L, i); + lua_settable(L, -3); + } + lua_pushstring(L, mathlib ? "PW_" : "pw_"); + lua_pushcfunction(L, lua_enumlib_power_get); + lua_call(L, 3, 0); + + /* Kart Stuff (K_/k_)*/ + lua_pushcfunction(L, lua_glib_new_enum); + lua_createtable(L, 0, NUMKARTSTUFF); + for (int i = 0; i < NUMKARTSTUFF; i++) + { + lua_pushfstring(L, mathlib ? "K_%s": "k_%s", KARTSTUFF_LIST[i]); + lua_pushinteger(L, i); + lua_settable(L, -3); + } + lua_pushstring(L, mathlib ? "K_" : "k_"); + lua_pushcfunction(L, lua_enumlib_kartstuff_get); + lua_call(L, 3, 0); + + /* Head up display (HUD_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_glib_push_linear_cache(L, "HUD_", HUDITEMS_LIST, NUMHUDITEMS); + lua_pushliteral(L, "HUD_"); + lua_pushliteral(L, "huditem"); + lua_pushcclosure(L, lua_enumlib_basic_fallback, 1); + lua_call(L, 3, 0); + + /* Skin Color (SKINCOLOR_) */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_glib_push_linear_cache(L, "SKINCOLOR_", COLOR_ENUMS, MAXTRANSLATIONS); + lua_pushliteral(L, "SKINCOLOR_"); + lua_pushliteral(L, "skincolor"); + lua_pushcclosure(L, lua_enumlib_basic_fallback, 1); + lua_call(L, 3, 0); + + /* Actions (A_) + * These are only the hard coded actions are intended as a fast lookup path + * when possible. + */ + lua_pushcfunction(L, lua_glib_new_enum); + lua_createtable(L, 0, ARRAYLEN(actionpointers)); + for (int i = 0; actionpointers[i].name; i++) + { + lua_pushfstring(L, "A_%s", actionpointers[i].name); + lua_pushlightuserdata(L, &actionpointers[i].action); + lua_pushcclosure(L, lib_action, 1); + lua_settable(L, -3); + } + lua_pushliteral(L, "A_"); + lua_pushcfunction(L, lua_enumlib_action_get); + lua_call(L, 3, 0); + + /* Getters :) */ + +#define PUSHGETTER(what, t) do {\ + lua_pushcfunction(L, lua_glib_new_getter); \ + lua_pushliteral(L, #what); \ + lua_glib_push_##t##_getter(L, &what); \ + lua_call(L, 2, 0); \ +} while(0) + + PUSHGETTER(gamemap, i16); + PUSHGETTER(maptol, i16); + PUSHGETTER(ultimatemode, b8); + PUSHGETTER(circuitmap, b32); + PUSHGETTER(netgame, b32); + PUSHGETTER(multiplayer, b32); + PUSHGETTER(modeattacking, b8); + PUSHGETTER(splitscreen, u8); + PUSHGETTER(gamecomplete, b32); + PUSHGETTER(devparm, b32); + PUSHGETTER(majormods, b32); + PUSHGETTER(menuactive, b32); + PUSHGETTER(paused, b8); + PUSHGETTER(gametype, i16); + PUSHGETTER(leveltime, u32); + PUSHGETTER(curWeather, i32); + PUSHGETTER(globalweather, i8); + PUSHGETTER(levelskynum, i32); + PUSHGETTER(globallevelskynum, i32); + PUSHGETTER(mapmusname, str); + PUSHGETTER(mapmusflags, u16); + PUSHGETTER(mapmusposition, u32); + PUSHGETTER(gravity, fxp); + PUSHGETTER(gamespeed, u8); + PUSHGETTER(encoremode, b32); + PUSHGETTER(franticitems, b32); + PUSHGETTER(comeback, b32); + PUSHGETTER(wantedcalcdelay, u32); + PUSHGETTER(indirectitemcooldown, u32); + PUSHGETTER(hyubgone, u32); + PUSHGETTER(thwompsactive, b32); + PUSHGETTER(spbplace, i8); + PUSHGETTER(mapobjectscale, fxp); + PUSHGETTER(racecountdown, u32); + PUSHGETTER(exitcountdown, u32); + + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "mariomode"); + lua_pushcfunction(L, lua_enumlib_mariomode_get); + lua_call(L, 2, 0); + + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "twodlevel"); + lua_pushcfunction(L, lua_enumlib_twodlevel_get); + lua_call(L, 2, 0); + + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "modifiedgame"); + lua_pushcfunction(L, lua_enumlib_modifiedgame_get); + lua_call(L, 2, 0); + + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "defrosting"); + lua_glib_push_i32_getter(L, &hook_defrosting); + lua_call(L, 2, 0); + + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "server"); + lua_pushcfunction(L, lua_enumlib_server_get); + lua_call(L, 2, 0); + + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "consoleplayer"); + lua_pushcfunction(L, lua_enumlib_consoleplayer_get); + lua_call(L, 2, 0); + + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "isserver"); + lua_glib_push_b32_getter(L, &server); + lua_call(L, 2, 0); + + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "isdedicatedserver"); + lua_glib_push_b32_getter(L, &dedicated); + lua_call(L, 2, 0); + + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "numlaps"); + lua_glib_push_i32_getter(L, &cv_numlaps.value); + lua_call(L, 2, 0); + + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "replayplayback"); + lua_glib_push_b32_getter(L, &demo.playback); + lua_call(L, 2, 0); + + if (!mathlib) + { + lua_pushcfunction(L, lua_glib_new_getter); + lua_pushliteral(L, "super"); + lua_pushcfunction(L, lua_enumlib_super_get); + lua_call(L, 2, 0); + } + +#undef PUSHGETTER + + // lua_pushliteral(L, "{cf75e032-00c8-4887-b15f-87b755784ad3}"); + // lua_gettable(L, LUA_REGISTRYINDEX); + // lua_pushliteral(L, "cache"); + // lua_gettable(L, -2); + + // lua_pushnil(L); + // while (lua_next(L, -2)) + // { + // lua_pushvalue(L, -2); + // CONS_Printf("%s: %s\n", lua_tostring(L, -1), lua_tostring(L, -2)); + // lua_pop(L, 2); + // } return 0; } -- 2.54.0 From 96552765c24b36d395ff6d19c3371e932c66bff5 Mon Sep 17 00:00:00 2001 From: xyzzy Date: Sun, 3 Sep 2023 17:01:12 +0300 Subject: [PATCH 4/6] Include doomdef.h :') --- src/lua_glib.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lua_glib.h b/src/lua_glib.h index b38115bcf..1405f807a 100644 --- a/src/lua_glib.h +++ b/src/lua_glib.h @@ -4,6 +4,7 @@ #ifndef _LUA_GLIB_H_ #define _LUA_GLIB_H_ +#include "doomdef.h" #include "lua_script.h" /** -- 2.54.0 From 17629ad462cc15f8fe3ebf4672cc01238590aae1 Mon Sep 17 00:00:00 2001 From: Indev Date: Mon, 30 Oct 2023 14:23:03 +0300 Subject: [PATCH 5/6] Fix lua state for LUA_EvalMath being recreated multiple times (maybe not the best solution). Also fix segfault in lua_enumlib_mobjtype_get --- src/dehacked.c | 3 ++- src/lua_script.c | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 65922a4be..88003797e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -900,7 +900,7 @@ static void readlevelheader(MYFILE *f, INT32 num, INT32 wadnum) // This call automatically saves all previous information when DELFILE is defined. // We don't need to do it ourselves. P_AllocMapHeader((INT16)(num-1)); - + if (!strstr(wadfiles[wadnum]->filename, ".soc")) mapwads[num-1] = wadnum; @@ -9394,6 +9394,7 @@ static int lua_enumlib_mobjtype_get(lua_State *L) const char *s = lua_tostring(L, 1); for (int i = 0; i < NUMMOBJFREESLOTS; i++) { + if (!FREE_MOBJS[i]) continue; if (fastcmp(s+3, FREE_MOBJS[i])) { lua_pushinteger(L, MT_FIRSTFREESLOT+i); diff --git a/src/lua_script.c b/src/lua_script.c index 8f4438732..0b9383b41 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -358,20 +358,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); + if (L == NULL) + { + 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); + // 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 "); @@ -396,8 +399,6 @@ fixed_t LUA_EvalMath(const char *word) else res = lua_tointeger(L, -1); - // clean up and return. - lua_close(L); return res; } -- 2.54.0 From f59fbf94d3a8ff51d55bbdb4f44ecf1ac25eb0d2 Mon Sep 17 00:00:00 2001 From: Indev Date: Mon, 30 Oct 2023 14:52:10 +0300 Subject: [PATCH 6/6] Remove include for PC_DOS --- src/dehacked.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 203036b97..16fd9f3da 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -44,12 +44,6 @@ #include "r_draw.h" // translation colormap consts (for lua) #endif -#ifdef PC_DOS -#include // for snprintf -//int snprintf(char *str, size_t n, const char *fmt, ...); -int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); -#endif - #define REQUIRE_MATHLIB_GUID "{748fcbc8-6480-4013-ac4e-7afce6cab766}" // Free slot names -- 2.54.0