From 3f9d64717db75460a6e212371aadad3d245adc95 Mon Sep 17 00:00:00 2001 From: xyzzy Date: Thu, 31 Aug 2023 23:16:32 +0300 Subject: [PATCH 01/16] 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 02/16] 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 03/16] 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 04/16] 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 05/16] 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 06/16] 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 From d96389db546c5f79f66786650ab7b66de9062ad1 Mon Sep 17 00:00:00 2001 From: Indev Date: Mon, 30 Oct 2023 21:23:55 +0300 Subject: [PATCH 07/16] Fix looking up mobj type crashing game --- src/dehacked.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 16fd9f3da..2eb497817 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9400,7 +9400,7 @@ static int lua_enumlib_mobjtype_get(lua_State *L) static int lua_enumlib_sprite_get(lua_State *L) { const char *s = lua_tostring(L, 1); - for (int i = SPR_FIRSTFREESLOT; i < NUMSPRITES; i++) + for (int i = 0; i < NUMSPRITES; i++) { if (fastncmp(s+4, sprnames[i], 4)) { -- 2.54.0 From 034961c6ed2f8bee1c8dba8e8bb056cdc2a26da0 Mon Sep 17 00:00:00 2001 From: Indev Date: Mon, 30 Oct 2023 21:24:38 +0300 Subject: [PATCH 08/16] Fix hardcoded actions lookup not working --- src/dehacked.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 2eb497817..5777e582e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9536,7 +9536,8 @@ static int lua_enumlib_kartstuff_get(lua_State *L) static int lua_enumlib_action_get(lua_State *L) { - const char *action = lua_tostring(L, 1)+2; + const char *action = lua_tostring(L, 1); + for (int i = 0; actionpointers[i].name; i++) if (fasticmp(action, actionpointers[i].name)) { // push lib_action as a C closure with the actionf_t* as an upvalue. -- 2.54.0 From 74ee1fcdd8424dc1bd04420576d5162e65aeb812 Mon Sep 17 00:00:00 2001 From: Indev Date: Tue, 31 Oct 2023 20:40:43 +0300 Subject: [PATCH 09/16] Fix few warnings related to lua_glib. Get rid of f32 setters/getters since floats aren't used in lua --- src/dehacked.c | 11 +++++++---- src/lua_glib.c | 22 +++++++++------------- src/lua_glib.h | 6 +----- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 5777e582e..87ad821c6 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9272,8 +9272,7 @@ 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; + const char *word; boolean mathlib = lua_toboolean(L, UV_MATHLIB); if (lua_type(L,2) != LUA_TSTRING) return 0; @@ -9511,6 +9510,8 @@ static int lua_enumlib_power_get(lua_State *L) { return luaL_error(L, "power '%s' could not be found.\n", lua_tostring(L, 1)); } + + return 0; } static int lua_enumlib_kartstuff_get(lua_State *L) @@ -9532,6 +9533,8 @@ static int lua_enumlib_kartstuff_get(lua_State *L) { return luaL_error(L, "kartstuff '%s' could not be found.\n", lua_tostring(L, 1)); } + + return 0; } static int lua_enumlib_action_get(lua_State *L) @@ -9917,10 +9920,10 @@ int LUA_EnumLib(lua_State *L) PUSHGETTER(gametype, i16); PUSHGETTER(leveltime, u32); PUSHGETTER(curWeather, i32); - PUSHGETTER(globalweather, i8); + PUSHGETTER(globalweather, u8); PUSHGETTER(levelskynum, i32); PUSHGETTER(globallevelskynum, i32); - PUSHGETTER(mapmusname, str); + PUSHGETTER((*mapmusname), str); PUSHGETTER(mapmusflags, u16); PUSHGETTER(mapmusposition, u32); PUSHGETTER(gravity, fxp); diff --git a/src/lua_glib.c b/src/lua_glib.c index c213230ec..c8d39da79 100644 --- a/src/lua_glib.c +++ b/src/lua_glib.c @@ -281,7 +281,7 @@ int lua_glib_new_setter(lua_State *L) #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)); \ + const T* ptr = (const T*)lua_touserdata(L, lua_upvalueindex(1)); \ lua_pushinteger(L, (lua_Integer)*ptr); \ return 1; \ } @@ -289,21 +289,21 @@ int lua_glib_new_setter(lua_State *L) #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)); \ + T* ptr = (T*)lua_touserdata(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)); \ + const T* ptr = (const T*)lua_touserdata(L, lua_upvalueindex(1)); \ lua_pushboolean(L, *ptr != 0); \ 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)); \ + const T* ptr = (const T*)lua_touserdata(L, lua_upvalueindex(1)); \ lua_pushnumber(L, (lua_Number)*ptr); \ return 1; \ } @@ -311,14 +311,14 @@ int lua_glib_new_setter(lua_State *L) #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)); \ + T* ptr = (T*)lua_touserdata(L, lua_upvalueindex(1)); \ *ptr = (T)lua_tonumber(L, 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)); \ + T* ptr = (T*)lua_touserdata(L, lua_upvalueindex(1)); \ *ptr = (T)lua_toboolean(L, 1); \ return 0; \ } @@ -331,8 +331,6 @@ _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_BOOL_GETTER(uint8_t, b8); _GLIB_DECL_BOOL_GETTER(uint16_t, b16); _GLIB_DECL_BOOL_GETTER(uint32_t, b32); @@ -346,8 +344,6 @@ _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); _GLIB_DECL_BOOL_SETTER(uint8_t, b8); _GLIB_DECL_BOOL_SETTER(uint16_t, b16); _GLIB_DECL_BOOL_SETTER(uint32_t, b32); @@ -355,21 +351,21 @@ _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)); + fixed_t *fxp = (fixed_t*)lua_touserdata(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)); + const fixed_t *fxp = (const fixed_t*)lua_touserdata(L, lua_upvalueindex(1)); lua_pushfixed(L, *fxp); return 1; } int lua_glib_getter_str(lua_State *L) { - const char *str = (const char*)lua_topointer(L, lua_upvalueindex(1)); + const char *str = (const char*)lua_touserdata(L, lua_upvalueindex(1)); lua_pushstring(L, str); return 1; } diff --git a/src/lua_glib.h b/src/lua_glib.h index 1405f807a..5d4f35c9a 100644 --- a/src/lua_glib.h +++ b/src/lua_glib.h @@ -125,7 +125,7 @@ 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) { \ + static inline void lua_glib_push_##name##_getter(lua_State *L, T* ptr) { \ lua_pushlightuserdata(L, (void*)ptr); \ lua_pushcclosure(L, lua_glib_getter_##name, 1); \ } @@ -138,8 +138,6 @@ int lua_glib_setter_fxp(lua_State *L); _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); _LUA_GLIB_DECL_PGETTER(uint8_t, b8); @@ -163,8 +161,6 @@ int lua_glib_setter_fxp(lua_State *L); _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); _LUA_GLIB_DECL_PSETTER(uint8_t, b8); _LUA_GLIB_DECL_PSETTER(uint16_t, b16); _LUA_GLIB_DECL_PSETTER(uint32_t, b32); -- 2.54.0 From 6c7131ff8037083be7b1e8ddca195f1e12020e60 Mon Sep 17 00:00:00 2001 From: Indev Date: Thu, 2 Nov 2023 03:19:10 +0300 Subject: [PATCH 10/16] Fix overwriting mobj slots working differently from vanilla --- src/dehacked.c | 22 ++++++++++++++++++++-- src/lua_glib.c | 17 +++++++++++++++++ src/lua_glib.h | 5 +++++ src/lua_script.c | 35 ++++++++++++++++++++++++----------- src/lua_script.h | 4 ++++ 5 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 87ad821c6..fd66bf3ea 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -667,6 +667,9 @@ static void readfreeslots(MYFILE *f) for (i = 0; i < NUMMOBJFREESLOTS; i++) if (!FREE_MOBJS[i]) { CONS_Printf("MobjType MT_%s allocated.\n",word); + + LUA_InvalidateMathlibMobjCache(word); + FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); strcpy(FREE_MOBJS[i],word); freeslotusage[1][0]++; @@ -9225,6 +9228,11 @@ static inline int lib_freeslot(lua_State *L) for (i = 0; i < NUMMOBJFREESLOTS; i++) if (!FREE_MOBJS[i]) { CONS_Printf("MobjType MT_%s allocated.\n",word); + + lua_pushcfunction(L, lua_glib_invalidate_cache); + lua_pushfstring(L, "MT_%s", word); + lua_call(L, 1, 0); + FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); strcpy(FREE_MOBJS[i],word); freeslotusage[1][0]++; @@ -9383,9 +9391,10 @@ static int lua_enumlib_state_get(lua_State *L) static int lua_enumlib_mobjtype_get(lua_State *L) { const char *s = lua_tostring(L, 1); - for (int i = 0; i < NUMMOBJFREESLOTS; i++) + for (mobjtype_t i = 0; i < NUMMOBJFREESLOTS; i++) { - if (!FREE_MOBJS[i]) continue; + if (!FREE_MOBJS[i]) + break; if (fastcmp(s+3, FREE_MOBJS[i])) { lua_pushinteger(L, MT_FIRSTFREESLOT+i); @@ -9393,6 +9402,15 @@ static int lua_enumlib_mobjtype_get(lua_State *L) } } + for (mobjtype_t i = 0; i < MT_FIRSTFREESLOT; i++) + { + if (fastcmp(s, MOBJTYPE_LIST[i])) + { + lua_pushinteger(L, i); + return 1; + } + } + return luaL_error(L, "mobjtype '%s' does not exist.\n", s); } diff --git a/src/lua_glib.c b/src/lua_glib.c index c8d39da79..3a39cfc17 100644 --- a/src/lua_glib.c +++ b/src/lua_glib.c @@ -247,6 +247,23 @@ int lua_glib_new_enum(lua_State *L) return 0; } +int lua_glib_invalidate_cache(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TSTRING); + + lua_glib_push_db(L); + + lua_pushliteral(L, GLIB_DATABASE_CACHE); + lua_gettable(L, -2); + + lua_pushvalue(L, 1); + lua_pushnil(L); + + lua_settable(L, -3); + + return 0; +} + int lua_glib_new_getter(lua_State *L) { luaL_checktype(L, 1, LUA_TSTRING); diff --git a/src/lua_glib.h b/src/lua_glib.h index 5d4f35c9a..4d4b52f48 100644 --- a/src/lua_glib.h +++ b/src/lua_glib.h @@ -23,6 +23,11 @@ int lua_glib_append_cache(lua_State *L); */ int lua_glib_new_enum(lua_State *L); +/* Invalidate cache entry. + * @param L[1] Name of entry. ("MT_MYOBJECT" for example) + */ +int lua_glib_invalidate_cache(lua_State *L); + /** * Create a new getter. * @param L[1] The name of the getter. diff --git a/src/lua_script.c b/src/lua_script.c index d809de33d..30df39fbb 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -29,12 +29,16 @@ #include "lua_script.h" #include "lua_libs.h" +#include "lua_glib.h" #include "lua_hook.h" #include "doomstat.h" lua_State *gL = NULL; +// Mathlib global state +static lua_State *mL = NULL; + int hook_defrosting; // List of internal libraries to load from SRB2 @@ -358,22 +362,21 @@ void LUA_DumpFile(const char *filename) fixed_t LUA_EvalMath(const char *word) { - 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 - if (L == NULL) + if (mL == NULL) { - L = lua_newstate(LUA_Alloc, NULL); - lua_atpanic(L, LUA_Panic); + mL = lua_newstate(LUA_Alloc, NULL); + lua_atpanic(mL, LUA_Panic); // open only enum lib - lua_pushcfunction(L, LUA_EnumLib); - lua_pushboolean(L, true); - lua_call(L, 1, 0); + lua_pushcfunction(mL, LUA_EnumLib); + lua_pushboolean(mL, true); + lua_call(mL, 1, 0); } // change ^ into ^^ for Lua. @@ -388,20 +391,30 @@ fixed_t LUA_EvalMath(const char *word) *b = '\0'; // eval string. - lua_settop(L, 0); - if (luaL_dostring(L, buf)) + lua_settop(mL, 0); + if (luaL_dostring(mL, buf)) { - p = lua_tostring(L, -1); + p = lua_tostring(mL, -1); while (*p++ != ':' && *p) ; p += 3; // "1: " CONS_Alert(CONS_WARNING, "%s\n", p); } else - res = lua_tointeger(L, -1); + res = lua_tointeger(mL, -1); return res; } +void LUA_InvalidateMathlibMobjCache(const char *name) +{ + // No state => no cache => nothing to invalidate :3 + if (mL == NULL) return; + + lua_pushcfunction(mL, lua_glib_invalidate_cache); + lua_pushfstring(mL, "MT_%s", name); + lua_call(mL, 1, 0); +} + // Takes a pointer, any pointer, and a metatable name // Creates a userdata for that pointer with the given metatable // Pushes it to the stack and stores it in the registry. diff --git a/src/lua_script.h b/src/lua_script.h index dd21ae0d9..a84415ba6 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -47,6 +47,10 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump); void LUA_DumpFile(const char *filename); #endif fixed_t LUA_EvalMath(const char *word); + +// Need better name for this ;-; +void LUA_InvalidateMathlibMobjCache(const char *name); + void LUA_PushUserdata(lua_State *L, void *data, const char *meta); void LUA_InvalidateUserdata(void *data); void LUA_InvalidateLevel(void); -- 2.54.0 From 0c5a1e95b0ab0ef76a5dfbbb6857918756c6586f Mon Sep 17 00:00:00 2001 From: Indev Date: Thu, 2 Nov 2023 21:25:42 +0300 Subject: [PATCH 11/16] Fix overwriting states too --- src/dehacked.c | 8 ++++++++ src/lua_script.c | 10 ++++++++++ src/lua_script.h | 1 + 3 files changed, 19 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index fd66bf3ea..e283d80cf 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -653,6 +653,9 @@ static void readfreeslots(MYFILE *f) for (i = 0; i < NUMSTATEFREESLOTS; i++) if (!FREE_STATES[i]) { CONS_Printf("State S_%s allocated.\n",word); + + LUA_InvalidateMathlibStateCache(word); + FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); strcpy(FREE_STATES[i],word); freeslotusage[0][0]++; @@ -9212,6 +9215,11 @@ static inline int lib_freeslot(lua_State *L) for (i = 0; i < NUMSTATEFREESLOTS; i++) if (!FREE_STATES[i]) { CONS_Printf("State S_%s allocated.\n",word); + + lua_pushcfunction(L, lua_glib_invalidate_cache); + lua_pushfstring(L, "S_%s", word); + lua_call(L, 1, 0); + FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); strcpy(FREE_STATES[i],word); freeslotusage[0][0]++; diff --git a/src/lua_script.c b/src/lua_script.c index 30df39fbb..51c15062a 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -415,6 +415,16 @@ void LUA_InvalidateMathlibMobjCache(const char *name) lua_call(mL, 1, 0); } +void LUA_InvalidateMathlibStateCache(const char *name) +{ + // No state => no cache => nothing to invalidate :3 + if (mL == NULL) return; + + lua_pushcfunction(mL, lua_glib_invalidate_cache); + lua_pushfstring(mL, "S_%s", name); + lua_call(mL, 1, 0); +} + // Takes a pointer, any pointer, and a metatable name // Creates a userdata for that pointer with the given metatable // Pushes it to the stack and stores it in the registry. diff --git a/src/lua_script.h b/src/lua_script.h index a84415ba6..82768c1d5 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -50,6 +50,7 @@ fixed_t LUA_EvalMath(const char *word); // Need better name for this ;-; void LUA_InvalidateMathlibMobjCache(const char *name); +void LUA_InvalidateMathlibStateCache(const char *name); void LUA_PushUserdata(lua_State *L, void *data, const char *meta); void LUA_InvalidateUserdata(void *data); -- 2.54.0 From 4c5df81dac4072a346a69f7248a023ab33088ff9 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 2 Nov 2023 15:02:26 +0100 Subject: [PATCH 12/16] fixuer localskin stuff Fixes the Apply to all players and displaying player not working (thx haya c: ) Fixes the Vibrating? player animation speeding up when uncapped in localskinmenu Make so that the char spin speed respects the setting from saturn options (and add pain support ) --- src/m_menu.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index d47c78796..b95bb4806 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -12182,10 +12182,10 @@ static void M_LocalSkinChange(INT32 choice) switch (itemOn) { case 3: - COM_BufAddText(va("localskin -a %s", cv_fakelocalskin.string)); + COM_BufAddText(va("localskin %s -a", cv_fakelocalskin.string)); break; case 4: - COM_BufAddText(va("localskin -d 0 %s", cv_fakelocalskin.string)); + COM_BufAddText(va("localskin %s -d 0", cv_fakelocalskin.string)); break; case 5: COM_BufAddText(va("localskin %s", cv_fakelocalskin.string)); @@ -12216,16 +12216,19 @@ static void M_DrawLocalSkinMenu(void) #define charw 72 // anim the player in the box - if (--multi_tics <= 0) + multi_tics -= renderdeltatics; + while (multi_tics <= 0) { - st = multi_state->nextstate; + st = cv_skinselectspin.value == SKINSELECTSPIN_PAIN ? S_KART_PAIN : multi_state->nextstate; if (st != S_NULL) multi_state = &states[st]; - multi_tics = multi_state->tics; - if (multi_tics == -1) - multi_tics = 15; - } + if (multi_state->tics <= -1) + multi_tics += 15*FRACUNIT; + else + multi_tics += multi_state->tics * FRACUNIT; + } + // skin 0 is default player sprite if (R_AnySkinAvailable(cv_fakelocalskin.string) != -1) { @@ -12256,7 +12259,7 @@ static void M_DrawLocalSkinMenu(void) //minenice's speen css, it's a piece of shit but hey //patch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE); - speenframe = (I_GetTime()*4/TICRATE + 1)%8; + speenframe = (I_GetTime()*cv_skinselectspin.value/TICRATE + 1)%8; //this is a very shitty solution for checking if a sprite needs flipping //but it works -- 2.54.0 From e421c1345b93f3532eb97f2bc296b72a57449f90 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Mon, 6 Nov 2023 12:27:23 +0100 Subject: [PATCH 13/16] Cache and reuse removed mobjs when spawning mobjs from https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2200 --- src/d_think.h | 1 + src/p_local.h | 1 + src/p_mobj.c | 18 ++++++++++++++++-- src/p_setup.c | 2 ++ src/p_tick.c | 12 +++++++++++- 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/d_think.h b/src/d_think.h index b907c17fd..6b8ee113a 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -49,6 +49,7 @@ typedef struct thinker_s // killough 11/98: count of how many other objects reference // this one using pointers. Used for garbage collection. INT32 references; + boolean cachable; } thinker_t; #endif diff --git a/src/p_local.h b/src/p_local.h index bb7c62046..6b69da480 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -66,6 +66,7 @@ // both the head and tail of the thinker list extern thinker_t thinkercap; +extern mobj_t *mobjcache; void P_InitThinkers(void); void P_AddThinker(thinker_t *thinker); diff --git a/src/p_mobj.c b/src/p_mobj.c index 12653d39d..b7746a6ac 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -48,6 +48,7 @@ actioncache_t actioncachehead; static mobj_t *overlaycap = NULL; static mobj_t *shadowcap = NULL; mobj_t *waypointcap = NULL; +mobj_t *mobjcache = NULL; void P_InitCachedActions(void) { @@ -9510,7 +9511,18 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { const mobjinfo_t *info = &mobjinfo[type]; state_t *st; - mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + mobj_t *mobj; + + if (mobjcache != NULL) + { + mobj = mobjcache; + mobjcache = mobjcache->hnext; + memset(mobj, 0, sizeof(*mobj)); + } + else + { + mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + } // this is officially a mobj, declared as soon as possible. mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; @@ -10255,7 +10267,9 @@ void P_RemoveMobj(mobj_t *mobj) // Invalidate mobj_t data to cause crashes if accessed! memset(mobj, 0xff, sizeof(mobj_t)); #endif - Z_Free(mobj); // No refrences? Can be removed immediately! :D + // no references, dump it directly in the mobj cache + mobj->hnext = mobjcache; + mobjcache = mobj; } else { // Add thinker just to delay removing it until refrences are gone. diff --git a/src/p_setup.c b/src/p_setup.c index d8dcbb877..951c24933 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2995,6 +2995,8 @@ boolean P_SetupLevel(boolean skipprecip) R_FlushTranslationColormapCache(); Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); + + mobjcache = NULL; #if defined (WALLSPLATS) || defined (FLOORSPLATS) // clear the splats from previous level diff --git a/src/p_tick.c b/src/p_tick.c index 38900db9f..a70815b86 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -201,6 +201,7 @@ void P_AddThinker(thinker_t *thinker) thinkercap.prev = thinker; thinker->references = 0; // killough 11/98: init reference counter to 0 + thinker->cachable = thinker->function.acp1 == (actionf_p1)P_MobjThinker; } // @@ -236,7 +237,16 @@ void P_RemoveThinkerDelayed(void *pthinker) (next->prev = currentthinker = thinker->prev)->next = next; } R_DestroyLevelInterpolators(thinker); - Z_Free(thinker); + if (thinker->cachable) + { + // put cachable thinkers in the mobj cache, so we can avoid allocations + ((mobj_t *)thinker)->hnext = mobjcache; + mobjcache = (mobj_t *)thinker; + } + else + { + Z_Free(thinker); + } } } -- 2.54.0 From 44a42758062e8143e8e3288e21a554dadaa9f843 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 7 Nov 2023 00:40:17 +0100 Subject: [PATCH 14/16] Revert "Cache and reuse removed mobjs when spawning mobjs" This reverts commit e421c1345b93f3532eb97f2bc296b72a57449f90. accidentally merged this lol --- src/d_think.h | 1 - src/p_local.h | 1 - src/p_mobj.c | 18 ++---------------- src/p_setup.c | 2 -- src/p_tick.c | 12 +----------- 5 files changed, 3 insertions(+), 31 deletions(-) diff --git a/src/d_think.h b/src/d_think.h index 6b8ee113a..b907c17fd 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -49,7 +49,6 @@ typedef struct thinker_s // killough 11/98: count of how many other objects reference // this one using pointers. Used for garbage collection. INT32 references; - boolean cachable; } thinker_t; #endif diff --git a/src/p_local.h b/src/p_local.h index 6b69da480..bb7c62046 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -66,7 +66,6 @@ // both the head and tail of the thinker list extern thinker_t thinkercap; -extern mobj_t *mobjcache; void P_InitThinkers(void); void P_AddThinker(thinker_t *thinker); diff --git a/src/p_mobj.c b/src/p_mobj.c index b7746a6ac..12653d39d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -48,7 +48,6 @@ actioncache_t actioncachehead; static mobj_t *overlaycap = NULL; static mobj_t *shadowcap = NULL; mobj_t *waypointcap = NULL; -mobj_t *mobjcache = NULL; void P_InitCachedActions(void) { @@ -9511,18 +9510,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { const mobjinfo_t *info = &mobjinfo[type]; state_t *st; - mobj_t *mobj; - - if (mobjcache != NULL) - { - mobj = mobjcache; - mobjcache = mobjcache->hnext; - memset(mobj, 0, sizeof(*mobj)); - } - else - { - mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); - } + mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); // this is officially a mobj, declared as soon as possible. mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; @@ -10267,9 +10255,7 @@ void P_RemoveMobj(mobj_t *mobj) // Invalidate mobj_t data to cause crashes if accessed! memset(mobj, 0xff, sizeof(mobj_t)); #endif - // no references, dump it directly in the mobj cache - mobj->hnext = mobjcache; - mobjcache = mobj; + Z_Free(mobj); // No refrences? Can be removed immediately! :D } else { // Add thinker just to delay removing it until refrences are gone. diff --git a/src/p_setup.c b/src/p_setup.c index 951c24933..d8dcbb877 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2995,8 +2995,6 @@ boolean P_SetupLevel(boolean skipprecip) R_FlushTranslationColormapCache(); Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); - - mobjcache = NULL; #if defined (WALLSPLATS) || defined (FLOORSPLATS) // clear the splats from previous level diff --git a/src/p_tick.c b/src/p_tick.c index a70815b86..38900db9f 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -201,7 +201,6 @@ void P_AddThinker(thinker_t *thinker) thinkercap.prev = thinker; thinker->references = 0; // killough 11/98: init reference counter to 0 - thinker->cachable = thinker->function.acp1 == (actionf_p1)P_MobjThinker; } // @@ -237,16 +236,7 @@ void P_RemoveThinkerDelayed(void *pthinker) (next->prev = currentthinker = thinker->prev)->next = next; } R_DestroyLevelInterpolators(thinker); - if (thinker->cachable) - { - // put cachable thinkers in the mobj cache, so we can avoid allocations - ((mobj_t *)thinker)->hnext = mobjcache; - mobjcache = (mobj_t *)thinker; - } - else - { - Z_Free(thinker); - } + Z_Free(thinker); } } -- 2.54.0 From 7054b8658e45da7fdc23fe9b7e2366b64bf66620 Mon Sep 17 00:00:00 2001 From: Indev Date: Wed, 8 Nov 2023 02:01:06 +0300 Subject: [PATCH 15/16] Fix sprite freeslots behaving differently from vanilla (same as for MT_ and S_) --- src/dehacked.c | 14 +++++++++++--- src/lua_script.c | 14 ++------------ src/lua_script.h | 3 +-- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index e283d80cf..b34303c20 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -642,6 +642,9 @@ static void readfreeslots(MYFILE *f) strncpy(sprnames[i],word,4); //sprnames[i][4] = 0; CONS_Printf("Sprite SPR_%s allocated.\n",word); + + LUA_InvalidateMathlibCache(va("SPR_%s", word)); + used_spr[(i-SPR_FIRSTFREESLOT)/8] |= 1<<(i%8); // Okay, this sprite slot has been named now. break; } @@ -654,7 +657,7 @@ static void readfreeslots(MYFILE *f) if (!FREE_STATES[i]) { CONS_Printf("State S_%s allocated.\n",word); - LUA_InvalidateMathlibStateCache(word); + LUA_InvalidateMathlibCache(va("S_%s", word)); FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); strcpy(FREE_STATES[i],word); @@ -671,7 +674,7 @@ static void readfreeslots(MYFILE *f) if (!FREE_MOBJS[i]) { CONS_Printf("MobjType MT_%s allocated.\n",word); - LUA_InvalidateMathlibMobjCache(word); + LUA_InvalidateMathlibCache(va("MT_%s", word)); FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); strcpy(FREE_MOBJS[i],word); @@ -9199,6 +9202,11 @@ static inline int lib_freeslot(lua_State *L) } // Found a free slot! CONS_Printf("Sprite SPR_%s allocated.\n",word); + + lua_pushcfunction(L, lua_glib_invalidate_cache); + lua_pushfstring(L, "SPR_%s", word); + lua_call(L, 1, 0); + 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. @@ -9427,7 +9435,7 @@ static int lua_enumlib_sprite_get(lua_State *L) const char *s = lua_tostring(L, 1); for (int i = 0; i < NUMSPRITES; i++) { - if (fastncmp(s+4, sprnames[i], 4)) + if (!sprnames[i][4] && fastncmp(s+4, sprnames[i], 4)) { lua_pushinteger(L, i); return 1; diff --git a/src/lua_script.c b/src/lua_script.c index 51c15062a..29901bc3d 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -405,23 +405,13 @@ fixed_t LUA_EvalMath(const char *word) return res; } -void LUA_InvalidateMathlibMobjCache(const char *name) +void LUA_InvalidateMathlibCache(const char *name) { // No state => no cache => nothing to invalidate :3 if (mL == NULL) return; lua_pushcfunction(mL, lua_glib_invalidate_cache); - lua_pushfstring(mL, "MT_%s", name); - lua_call(mL, 1, 0); -} - -void LUA_InvalidateMathlibStateCache(const char *name) -{ - // No state => no cache => nothing to invalidate :3 - if (mL == NULL) return; - - lua_pushcfunction(mL, lua_glib_invalidate_cache); - lua_pushfstring(mL, "S_%s", name); + lua_pushstring(mL, name); lua_call(mL, 1, 0); } diff --git a/src/lua_script.h b/src/lua_script.h index 82768c1d5..8ea5f3a89 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -49,8 +49,7 @@ void LUA_DumpFile(const char *filename); fixed_t LUA_EvalMath(const char *word); // Need better name for this ;-; -void LUA_InvalidateMathlibMobjCache(const char *name); -void LUA_InvalidateMathlibStateCache(const char *name); +void LUA_InvalidateMathlibCache(const char *name); void LUA_PushUserdata(lua_State *L, void *data, const char *meta); void LUA_InvalidateUserdata(void *data); -- 2.54.0 From c6ba2ee0a7bc0c171accb2ea0cb47d7a5d209aea Mon Sep 17 00:00:00 2001 From: Indev Date: Wed, 3 Jan 2024 00:10:28 +0300 Subject: [PATCH 16/16] Fix warnings related to boolean glib getters/setters --- src/dehacked.c | 28 ++++++++++++++-------------- src/lua_glib.c | 4 +++- src/lua_glib.h | 4 ++++ 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index b34303c20..28e5095f3 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9941,15 +9941,15 @@ int LUA_EnumLib(lua_State *L) PUSHGETTER(gamemap, i16); PUSHGETTER(maptol, i16); PUSHGETTER(ultimatemode, b8); - PUSHGETTER(circuitmap, b32); - PUSHGETTER(netgame, b32); - PUSHGETTER(multiplayer, b32); + PUSHGETTER(circuitmap, bool); + PUSHGETTER(netgame, bool); + PUSHGETTER(multiplayer, bool); PUSHGETTER(modeattacking, b8); PUSHGETTER(splitscreen, u8); - PUSHGETTER(gamecomplete, b32); - PUSHGETTER(devparm, b32); - PUSHGETTER(majormods, b32); - PUSHGETTER(menuactive, b32); + PUSHGETTER(gamecomplete, bool); + PUSHGETTER(devparm, bool); + PUSHGETTER(majormods, bool); + PUSHGETTER(menuactive, bool); PUSHGETTER(paused, b8); PUSHGETTER(gametype, i16); PUSHGETTER(leveltime, u32); @@ -9962,13 +9962,13 @@ int LUA_EnumLib(lua_State *L) PUSHGETTER(mapmusposition, u32); PUSHGETTER(gravity, fxp); PUSHGETTER(gamespeed, u8); - PUSHGETTER(encoremode, b32); - PUSHGETTER(franticitems, b32); - PUSHGETTER(comeback, b32); + PUSHGETTER(encoremode, bool); + PUSHGETTER(franticitems, bool); + PUSHGETTER(comeback, bool); PUSHGETTER(wantedcalcdelay, u32); PUSHGETTER(indirectitemcooldown, u32); PUSHGETTER(hyubgone, u32); - PUSHGETTER(thwompsactive, b32); + PUSHGETTER(thwompsactive, bool); PUSHGETTER(spbplace, i8); PUSHGETTER(mapobjectscale, fxp); PUSHGETTER(racecountdown, u32); @@ -10006,12 +10006,12 @@ int LUA_EnumLib(lua_State *L) lua_pushcfunction(L, lua_glib_new_getter); lua_pushliteral(L, "isserver"); - lua_glib_push_b32_getter(L, &server); + lua_glib_push_bool_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_glib_push_bool_getter(L, &dedicated); lua_call(L, 2, 0); lua_pushcfunction(L, lua_glib_new_getter); @@ -10021,7 +10021,7 @@ int LUA_EnumLib(lua_State *L) lua_pushcfunction(L, lua_glib_new_getter); lua_pushliteral(L, "replayplayback"); - lua_glib_push_b32_getter(L, &demo.playback); + lua_glib_push_bool_getter(L, &demo.playback); lua_call(L, 2, 0); if (!mathlib) diff --git a/src/lua_glib.c b/src/lua_glib.c index 3a39cfc17..07b3a87b6 100644 --- a/src/lua_glib.c +++ b/src/lua_glib.c @@ -336,7 +336,7 @@ int lua_glib_new_setter(lua_State *L) #define _GLIB_DECL_BOOL_SETTER(T, name) \ int lua_glib_setter_##name(lua_State *L) { \ T* ptr = (T*)lua_touserdata(L, lua_upvalueindex(1)); \ - *ptr = (T)lua_toboolean(L, 1); \ + *ptr = lua_toboolean(L, 1) ? true : false; \ return 0; \ } @@ -352,6 +352,7 @@ _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_BOOL_GETTER(boolean, bool); _GLIB_DECL_INT_SETTER(int8_t, i8); _GLIB_DECL_INT_SETTER(int16_t, i16); @@ -365,6 +366,7 @@ _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); +_GLIB_DECL_BOOL_SETTER(boolean, bool); int lua_glib_setter_fxp(lua_State *L) { diff --git a/src/lua_glib.h b/src/lua_glib.h index 4d4b52f48..d21f9000c 100644 --- a/src/lua_glib.h +++ b/src/lua_glib.h @@ -108,6 +108,7 @@ 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_bool(lua_State *L); int lua_glib_getter_str(lua_State *L); int lua_glib_getter_ptr(lua_State *L); @@ -128,6 +129,7 @@ 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); +int lua_glib_setter_bool(lua_State *L); #define _LUA_GLIB_DECL_PGETTER(T, name) \ static inline void lua_glib_push_##name##_getter(lua_State *L, T* ptr) { \ @@ -150,6 +152,7 @@ int lua_glib_setter_fxp(lua_State *L); _LUA_GLIB_DECL_PGETTER(uint32_t, b32); _LUA_GLIB_DECL_PGETTER(uint64_t, b64); _LUA_GLIB_DECL_PGETTER(fixed_t, fxp); + _LUA_GLIB_DECL_PGETTER(boolean, bool); #undef _LUA_GLIB_DECL_PGETTER #define _LUA_GLIB_DECL_PSETTER(T, name) \ @@ -171,6 +174,7 @@ int lua_glib_setter_fxp(lua_State *L); _LUA_GLIB_DECL_PSETTER(uint32_t, b32); _LUA_GLIB_DECL_PSETTER(uint64_t, b64); _LUA_GLIB_DECL_PSETTER(fixed_t, fxp); + _LUA_GLIB_DECL_PSETTER(boolean, bool); #undef _LUA_GLIB_DECL_PSETTER #endif -- 2.54.0