From 92a9dd88a39ae9705e98c55391f4194a9b5bc73e Mon Sep 17 00:00:00 2001 From: timfox Date: Sun, 15 Feb 2026 13:55:11 -0800 Subject: [PATCH 1/4] Add Lua scripting support - Introduced Lua scripting support, enabled by default, with options to disable via CMake. - Updated `CMakeLists.txt` to include Lua detection and linking. - Enhanced `scripts/compile_engine.sh` to accept a `lua` flag for enabling Lua during build. - Added Lua compatibility header and debug functions for script management. - Implemented commands for script reloading, listing, and dumping in the Lua environment. This addition allows for more flexible scripting capabilities within the engine, enhancing modding potential and runtime script management. --- BUILD.md | 22 ++++ CMakeLists.txt | 151 +++++++++++++++++++++++++++ scripts/compile_engine.sh | 9 +- src/qcommon/lua_compat.h | 78 ++++++++++++++ src/qcommon/lua_debug.c | 214 ++++++++++++++++++++++++++++++++++++++ src/qcommon/lua_debug.h | 8 ++ 6 files changed, 481 insertions(+), 1 deletion(-) create mode 100644 src/qcommon/lua_compat.h create mode 100644 src/qcommon/lua_debug.c create mode 100644 src/qcommon/lua_debug.h diff --git a/BUILD.md b/BUILD.md index 0be2a4fed..0f186bdad 100644 --- a/BUILD.md +++ b/BUILD.md @@ -229,3 +229,25 @@ Or let the helper script do it: ``` The flag targets the renderer code under `src/renderers/rendercommon/tr_font.c`, links with your platform’s FreeType library, and defines `BUILD_FREETYPE` for the build. Make sure the FreeType headers/libraries (`libfreetype6-dev`, `freetype-devel`, etc.) are installed before you configure the project. + +--- + +### Lua scripting support + +Lua support is enabled by default. + +To disable it explicitly: + +```bash +cmake -S . -B build -DUSE_LUA=OFF +``` + +`scripts/compile_engine.sh` also supports a `lua` flag, which passes `-DUSE_LUA=ON`. + +The engine looks for common Lua installs, including `lua5.5` / `lua-5.5` (plus `5.4`..`5.1` variants). Lua support requires Lua 5.1 or newer. + +When enabled, these commands are available: + +- `script_reload [file1.lua ...]` +- `script_list` +- `script_dump [maxEntries]` diff --git a/CMakeLists.txt b/CMakeLists.txt index a66b47aa3..54b32909f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,6 +181,144 @@ endif() if(NOT DEFINED USE_WEBM) option(USE_WEBM "Enable WebM audio support" ON) endif() +if(NOT DEFINED USE_LUA) + option(USE_LUA "Enable Lua scripting support" ON) +endif() + +set(LUA_FOUND FALSE) +set(LUA_LINK_LIBRARIES "") +set(LUA_VERSION_NUM 0) +set(LUA_VERSION_STRING "") +set(LUA_EXTRA_LIBRARIES "") + +if(USE_LUA) + set(_LUA_HINT_PATHS + $ENV{LUA_DIR} + $ENV{LUA_PATH} + ${CMAKE_PREFIX_PATH} + ${CMAKE_INSTALL_PREFIX} + /usr/local + /usr + /opt/local + /opt + /sw + ) + + find_path(LUA_INCLUDE_DIR + NAMES lua.h + PATH_SUFFIXES + include + include/lua + include/lua5.5 + include/lua-5.5 + include/lua5.4 + include/lua-5.4 + include/lua5.3 + include/lua-5.3 + include/lua5.2 + include/lua-5.2 + include/lua5.1 + include/lua-5.1 + PATHS ${_LUA_HINT_PATHS} + ) + + set(_LUA_HEADER_PATH "") + if(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h") + set(_LUA_HEADER_PATH "${LUA_INCLUDE_DIR}/lua.h") + endif() + + if(_LUA_HEADER_PATH) + file(STRINGS "${_LUA_HEADER_PATH}" LUA_VERSION_MAJOR_LINE REGEX "^#define[ \t]+LUA_VERSION_MAJOR_N[ \t]+[0-9]+" LIMIT_COUNT 1) + file(STRINGS "${_LUA_HEADER_PATH}" LUA_VERSION_MINOR_LINE REGEX "^#define[ \t]+LUA_VERSION_MINOR_N[ \t]+[0-9]+" LIMIT_COUNT 1) + if(LUA_VERSION_MAJOR_LINE AND LUA_VERSION_MINOR_LINE) + string(REGEX REPLACE ".*LUA_VERSION_MAJOR_N[ \t]+([0-9]+).*" "\\1" LUA_VERSION_MAJOR "${LUA_VERSION_MAJOR_LINE}") + string(REGEX REPLACE ".*LUA_VERSION_MINOR_N[ \t]+([0-9]+).*" "\\1" LUA_VERSION_MINOR "${LUA_VERSION_MINOR_LINE}") + math(EXPR LUA_VERSION_NUM "${LUA_VERSION_MAJOR} * 100 + ${LUA_VERSION_MINOR}") + set(LUA_VERSION_STRING "${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}") + else() + file(STRINGS "${_LUA_HEADER_PATH}" LUA_VERSION_NUM_LINE REGEX "^#define[ \t]+LUA_VERSION_NUM[ \t]+[0-9]+" LIMIT_COUNT 1) + if(LUA_VERSION_NUM_LINE) + string(REGEX REPLACE ".*LUA_VERSION_NUM[ \t]+([0-9]+).*" "\\1" LUA_VERSION_NUM "${LUA_VERSION_NUM_LINE}") + math(EXPR LUA_VERSION_MAJOR "${LUA_VERSION_NUM} / 100") + math(EXPR LUA_VERSION_MINOR "${LUA_VERSION_NUM} % 100") + set(LUA_VERSION_STRING "${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}") + endif() + endif() + endif() + + set(_LUA_LIB_NAMES lua5.5 lua-5.5 lua55 lua5.4 lua-5.4 lua54 lua5.3 lua-5.3 lua53 lua5.2 lua-5.2 lua52 lua5.1 lua-5.1 lua51 lua) + if(LUA_VERSION_STRING) + set(_LUA_LIB_NAMES lua${LUA_VERSION_STRING} lua-${LUA_VERSION_STRING} lua${LUA_VERSION_MAJOR}${LUA_VERSION_MINOR} ${_LUA_LIB_NAMES}) + list(REMOVE_DUPLICATES _LUA_LIB_NAMES) + endif() + + set(_LUA_LIB_HINTS "") + if(LUA_INCLUDE_DIR) + get_filename_component(_LUA_INCLUDE_PARENT "${LUA_INCLUDE_DIR}" DIRECTORY) + list(APPEND _LUA_LIB_HINTS + "${LUA_INCLUDE_DIR}/../lib" + "${LUA_INCLUDE_DIR}/../lib64" + "${_LUA_INCLUDE_PARENT}/lib" + "${_LUA_INCLUDE_PARENT}/lib64" + ) + list(REMOVE_DUPLICATES _LUA_LIB_HINTS) + endif() + + if(_LUA_LIB_HINTS) + find_library(LUA_LIBRARY + NAMES ${_LUA_LIB_NAMES} + HINTS ${_LUA_LIB_HINTS} + PATH_SUFFIXES "" lib lib64 + NO_DEFAULT_PATH + ) + endif() + + if(NOT LUA_LIBRARY) + find_library(LUA_LIBRARY + NAMES ${_LUA_LIB_NAMES} + PATH_SUFFIXES lib64 lib + PATHS ${_LUA_HINT_PATHS} + ) + endif() + + if((NOT LUA_INCLUDE_DIR OR NOT LUA_LIBRARY) AND NOT WIN32) + find_package(PkgConfig QUIET) + if(PKG_CONFIG_FOUND) + pkg_check_modules(LUA_PKG QUIET lua5.5 lua-5.5 lua55 lua5.4 lua-5.4 lua54 lua5.3 lua-5.3 lua53 lua5.2 lua-5.2 lua52 lua5.1 lua-5.1 lua51 lua) + if(LUA_PKG_FOUND) + if(NOT LUA_INCLUDE_DIR AND LUA_PKG_INCLUDE_DIRS) + list(GET LUA_PKG_INCLUDE_DIRS 0 LUA_INCLUDE_DIR) + endif() + if(NOT LUA_LIBRARY AND LUA_PKG_LINK_LIBRARIES) + list(GET LUA_PKG_LINK_LIBRARIES 0 LUA_LIBRARY) + list(REMOVE_AT LUA_PKG_LINK_LIBRARIES 0) + set(LUA_EXTRA_LIBRARIES ${LUA_PKG_LINK_LIBRARIES}) + endif() + endif() + endif() + endif() + + if(NOT LUA_INCLUDE_DIR OR NOT LUA_LIBRARY) + message(FATAL_ERROR "USE_LUA=ON but Lua headers/library were not found.") + endif() + + set(LUA_FOUND TRUE) + + if(LUA_VERSION_NUM GREATER 0 AND LUA_VERSION_NUM LESS 501) + message(FATAL_ERROR "Lua 5.1+ is required.") + endif() + + if(LUA_VERSION_STRING) + message(STATUS "Lua support enabled: ${LUA_VERSION_STRING} (${LUA_LIBRARY})") + else() + message(STATUS "Lua support enabled: ${LUA_LIBRARY}") + endif() + + list(APPEND LUA_LINK_LIBRARIES ${LUA_LIBRARY}) + if(LUA_EXTRA_LIBRARIES) + list(APPEND LUA_LINK_LIBRARIES ${LUA_EXTRA_LIBRARIES}) + endif() +endif() set(OPUS_FOUND FALSE) set(FLAC_FOUND FALSE) @@ -634,6 +772,10 @@ target_include_directories(qcommon PRIVATE ${CMAKE_SOURCE_DIR}/src/audio ) set_property(TARGET qcommon PROPERTY POSITION_INDEPENDENT_CODE ON) +if(USE_LUA AND LUA_FOUND) + target_compile_definitions(qcommon PRIVATE USE_LUA) + target_include_directories(qcommon PRIVATE ${LUA_INCLUDE_DIR}) +endif() # dedicated server ADD_LIBRARY(qcommon_ded OBJECT ${QCOMMON_SRCS} ${SERVER_SRCS}) @@ -649,6 +791,10 @@ target_include_directories(qcommon_ded PRIVATE ${CMAKE_SOURCE_DIR}/src/audio ) set_property(TARGET qcommon_ded PROPERTY POSITION_INDEPENDENT_CODE ON) +if(USE_LUA AND LUA_FOUND) + target_compile_definitions(qcommon_ded PRIVATE USE_LUA) + target_include_directories(qcommon_ded PRIVATE ${LUA_INCLUDE_DIR}) +endif() # Apply SKIP_IDPAK_CHECK to qcommon targets that compile files.c if(SKIP_IDPAK_CHECK) @@ -1145,6 +1291,11 @@ if(UNIX AND NOT MSVC AND NOT APPLE) target_link_options(${DNAME}${BINEXT} PRIVATE "-Wl,--export-dynamic") endif() +if(USE_LUA AND LUA_FOUND) + TARGET_LINK_LIBRARIES(${CNAME}${BINEXT} PRIVATE ${LUA_LINK_LIBRARIES}) + TARGET_LINK_LIBRARIES(${DNAME}${BINEXT} PRIVATE ${LUA_LINK_LIBRARIES}) +endif() + IF(WIN32) TARGET_LINK_LIBRARIES(${CNAME}${BINEXT} PRIVATE winmm comctl32 ws2_32) TARGET_LINK_LIBRARIES(${DNAME}${BINEXT} PRIVATE winmm comctl32 ws2_32) diff --git a/scripts/compile_engine.sh b/scripts/compile_engine.sh index 095fa1b10..b55cb3f17 100755 --- a/scripts/compile_engine.sh +++ b/scripts/compile_engine.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -# Usage: ./compile_engine.sh [game_name] [Debug|Release] [clean] [quiet] [coverage] [vulkan] [opengl] [freetype] +# Usage: ./compile_engine.sh [game_name] [Debug|Release] [clean] [quiet] [coverage] [vulkan] [opengl] [freetype] [lua] # Notes: # - build type defaults to Release # - vulkan and opengl are mutually exclusive @@ -12,6 +12,7 @@ VULKAN=0 OPENGL=0 SKIP_IDPAK=0 FREETYPE=0 +LUA=0 GAME_NAME="idtech3" BUILD_TYPE="Release" @@ -55,6 +56,7 @@ for arg in "$@"; do skip-idpak-check|skip_idpak_check|skip-pak|skip-paks) SKIP_IDPAK=1 ;; opengl) OPENGL=1 ;; freetype) FREETYPE=1 ;; + lua) LUA=1 ;; *) GAME_NAME="$arg" ;; esac done @@ -114,6 +116,11 @@ if [ "$FREETYPE" -eq 1 ]; then echo "CMake: BUILD_FREETYPE=ON" fi +if [ "$LUA" -eq 1 ]; then + CMAKE_FLAGS+=("-DUSE_LUA=ON") + echo "CMake: USE_LUA=ON" +fi + if [ "$VULKAN" -eq 1 ]; then CMAKE_FLAGS+=("-DRENDERER_DEFAULT=vulkan") else diff --git a/src/qcommon/lua_compat.h b/src/qcommon/lua_compat.h new file mode 100644 index 000000000..1e2d4a21b --- /dev/null +++ b/src/qcommon/lua_compat.h @@ -0,0 +1,78 @@ +#ifndef LUA_COMPAT_H +#define LUA_COMPAT_H + +#include +#include +#include + +#if !defined(LUA_VERSION_NUM) +#error "LUA_VERSION_NUM is required" +#endif + +#if LUA_VERSION_NUM < 501 +#error "Lua 5.1+ is required" +#endif + +#ifndef LUA_OK +#define LUA_OK 0 +#endif + +#if LUA_VERSION_NUM >= 502 +#define ID3_LUA_GETGLOBAL(L, N) lua_getglobal((L), (N)) +#else +#define ID3_LUA_GETGLOBAL(L, N) lua_getfield((L), LUA_GLOBALSINDEX, (N)) +#endif + +#if LUA_VERSION_NUM >= 502 +#define ID3_LUA_SETGLOBAL(L, N) lua_setglobal((L), (N)) +#else +#define ID3_LUA_SETGLOBAL(L, N) lua_setfield((L), LUA_GLOBALSINDEX, (N)) +#endif + +#if LUA_VERSION_NUM >= 502 +#define ID3_LUA_PUSH_GLOBAL_TABLE(L) lua_pushglobaltable((L)) +#else +#define ID3_LUA_PUSH_GLOBAL_TABLE(L) lua_pushvalue((L), LUA_GLOBALSINDEX) +#endif + +#if LUA_VERSION_NUM >= 502 +#define ID3_LUA_ABSINDEX(L, IDX) lua_absindex((L), (IDX)) +#else +#define ID3_LUA_ABSINDEX(L, IDX) ((IDX) > 0 || (IDX) <= LUA_REGISTRYINDEX ? (IDX) : lua_gettop((L)) + (IDX) + 1) +#endif + +#if LUA_VERSION_NUM >= 502 +#define ID3_LUA_RAWLEN(L, IDX) lua_rawlen((L), (IDX)) +#else +#define ID3_LUA_RAWLEN(L, IDX) lua_objlen((L), (IDX)) +#endif + +#if LUA_VERSION_NUM >= 502 +#define ID3_LUA_TONUMBERX(L, IDX, ISNUM) lua_tonumberx((L), (IDX), (ISNUM)) +#define ID3_LUA_TOINTEGERX(L, IDX, ISNUM) lua_tointegerx((L), (IDX), (ISNUM)) +#else +#define ID3_LUA_TONUMBERX(L, IDX, ISNUM) (((ISNUM) ? (*(ISNUM) = lua_isnumber((L), (IDX))) : 0), lua_tonumber((L), (IDX))) +#define ID3_LUA_TOINTEGERX(L, IDX, ISNUM) (((ISNUM) ? (*(ISNUM) = lua_isnumber((L), (IDX))) : 0), lua_tointeger((L), (IDX))) +#endif + +#if LUA_VERSION_NUM >= 503 +#define ID3_LUA_ISINTEGER(L, IDX) lua_isinteger((L), (IDX)) +#else +#define ID3_LUA_ISINTEGER(L, IDX) (0) +#endif + +#if LUA_VERSION_NUM >= 502 +#define ID3_LUA_NEWLIB(L, LREG) luaL_newlib((L), (LREG)) +#else +#define ID3_LUA_NEWLIB(L, LREG) (lua_newtable((L)), luaL_register((L), NULL, (LREG))) +#endif + +#if LUA_VERSION_NUM >= 504 +#define ID3_LUA_RESUME(L, FROM, NARGS, NRES_OUT) lua_resume((L), (FROM), (NARGS), (NRES_OUT)) +#elif LUA_VERSION_NUM >= 502 +#define ID3_LUA_RESUME(L, FROM, NARGS, NRES_OUT) ((void)(NRES_OUT), lua_resume((L), (FROM), (NARGS))) +#else +#define ID3_LUA_RESUME(L, FROM, NARGS, NRES_OUT) ((void)(NRES_OUT), lua_resume((L), (NARGS))) +#endif + +#endif diff --git a/src/qcommon/lua_debug.c b/src/qcommon/lua_debug.c new file mode 100644 index 000000000..cce5b5402 --- /dev/null +++ b/src/qcommon/lua_debug.c @@ -0,0 +1,214 @@ +#include "q_shared.h" +#include "qcommon.h" +#include "lua_debug.h" + +#ifdef USE_LUA +#include "lua_compat.h" + +#define MAX_LUA_TRACKED_SCRIPTS 64 + +static lua_State *s_luaState; +static int s_luaTrackedCount; +static char s_luaTrackedScripts[MAX_LUA_TRACKED_SCRIPTS][MAX_OSPATH]; + +static void LuaDebug_ClearTrackedScripts( void ) { + s_luaTrackedCount = 0; +} + +static void LuaDebug_CloseState( void ) { + if ( s_luaState ) { + lua_close( s_luaState ); + s_luaState = NULL; + } +} + +static qboolean LuaDebug_OpenState( void ) { + if ( s_luaState ) { + return qtrue; + } + + s_luaState = luaL_newstate(); + if ( !s_luaState ) { + Com_Printf( S_COLOR_RED "Lua: failed to initialize VM\n" ); + return qfalse; + } + + luaL_openlibs( s_luaState ); + return qtrue; +} + +static void LuaDebug_PrintLuaError( const char *prefix ) { + const char *msg = lua_tostring( s_luaState, -1 ); + Com_Printf( S_COLOR_RED "Lua: %s: %s\n", prefix, msg ? msg : "(unknown error)" ); + lua_pop( s_luaState, 1 ); +} + +static qboolean LuaDebug_LoadScript( const char *scriptPath ) { + if ( !LuaDebug_OpenState() ) { + return qfalse; + } + + if ( luaL_loadfile( s_luaState, scriptPath ) != LUA_OK ) { + LuaDebug_PrintLuaError( scriptPath ); + return qfalse; + } + + if ( lua_pcall( s_luaState, 0, LUA_MULTRET, 0 ) != LUA_OK ) { + LuaDebug_PrintLuaError( scriptPath ); + return qfalse; + } + + return qtrue; +} + +static void LuaDebug_TrackScript( const char *scriptPath ) { + int i; + + for ( i = 0; i < s_luaTrackedCount; i++ ) { + if ( !Q_stricmp( s_luaTrackedScripts[i], scriptPath ) ) { + return; + } + } + + if ( s_luaTrackedCount >= MAX_LUA_TRACKED_SCRIPTS ) { + Com_Printf( S_COLOR_YELLOW "Lua: tracked script limit reached (%d)\n", MAX_LUA_TRACKED_SCRIPTS ); + return; + } + + Q_strncpyz( s_luaTrackedScripts[s_luaTrackedCount], scriptPath, sizeof( s_luaTrackedScripts[0] ) ); + s_luaTrackedCount++; +} + +void Cmd_ScriptReload_f( void ) { + int argc = Cmd_Argc(); + int i; + int successCount = 0; + int failureCount = 0; + + if ( argc <= 1 ) { + if ( s_luaTrackedCount <= 0 ) { + LuaDebug_CloseState(); + if ( LuaDebug_OpenState() ) { + Com_Printf( "Lua: runtime initialized (%s, %d)\n", LUA_VERSION, LUA_VERSION_NUM ); + } + return; + } + + LuaDebug_CloseState(); + if ( !LuaDebug_OpenState() ) { + return; + } + + for ( i = 0; i < s_luaTrackedCount; i++ ) { + if ( LuaDebug_LoadScript( s_luaTrackedScripts[i] ) ) { + successCount++; + } else { + failureCount++; + } + } + + Com_Printf( "Lua: reloaded %d tracked script(s), %d failure(s)\n", successCount, failureCount ); + return; + } + + LuaDebug_CloseState(); + LuaDebug_ClearTrackedScripts(); + + if ( !LuaDebug_OpenState() ) { + return; + } + + for ( i = 1; i < argc; i++ ) { + const char *scriptPath = Cmd_Argv( i ); + + if ( !scriptPath || !scriptPath[0] ) { + continue; + } + + if ( LuaDebug_LoadScript( scriptPath ) ) { + LuaDebug_TrackScript( scriptPath ); + successCount++; + } else { + failureCount++; + } + } + + Com_Printf( "Lua: loaded %d script(s), %d failure(s)\n", successCount, failureCount ); +} + +void Cmd_ScriptList_f( void ) { + int i; + + Com_Printf( "Lua: compile-time API %s (LUA_VERSION_NUM=%d)\n", LUA_VERSION, LUA_VERSION_NUM ); + + if ( !s_luaState ) { + Com_Printf( "Lua: runtime not initialized. Run script_reload first.\n" ); + return; + } + + Com_Printf( "Lua: runtime initialized\n" ); + Com_Printf( "Lua: tracked scripts (%d)\n", s_luaTrackedCount ); + + for ( i = 0; i < s_luaTrackedCount; i++ ) { + Com_Printf( " %2d: %s\n", i + 1, s_luaTrackedScripts[i] ); + } +} + +void Cmd_ScriptDump_f( void ) { + int maxEntries = 128; + int printed = 0; + + if ( Cmd_Argc() > 1 ) { + const int requested = atoi( Cmd_Argv( 1 ) ); + if ( requested > 0 ) { + maxEntries = requested; + } + } + + if ( !s_luaState ) { + Com_Printf( "Lua: runtime not initialized. Run script_reload first.\n" ); + return; + } + + ID3_LUA_PUSH_GLOBAL_TABLE( s_luaState ); + lua_pushnil( s_luaState ); + + Com_Printf( "Lua: globals (limit %d)\n", maxEntries ); + while ( lua_next( s_luaState, -2 ) != 0 ) { + const char *keyName = lua_tostring( s_luaState, -2 ); + const char *valueType = lua_typename( s_luaState, lua_type( s_luaState, -1 ) ); + + if ( keyName ) { + Com_Printf( " %s : %s\n", keyName, valueType ); + } else { + const char *keyType = lua_typename( s_luaState, lua_type( s_luaState, -2 ) ); + Com_Printf( " [%s] : %s\n", keyType, valueType ); + } + + lua_pop( s_luaState, 1 ); + printed++; + if ( printed >= maxEntries ) { + Com_Printf( " ... output truncated ...\n" ); + break; + } + } + + lua_pop( s_luaState, 1 ); + Com_Printf( "Lua: dumped %d global entr%s\n", printed, printed == 1 ? "y" : "ies" ); +} + +#else + +void Cmd_ScriptReload_f( void ) { + Com_Printf( "Lua support is disabled in this build. Configure with -DUSE_LUA=ON.\n" ); +} + +void Cmd_ScriptList_f( void ) { + Com_Printf( "Lua support is disabled in this build. Configure with -DUSE_LUA=ON.\n" ); +} + +void Cmd_ScriptDump_f( void ) { + Com_Printf( "Lua support is disabled in this build. Configure with -DUSE_LUA=ON.\n" ); +} + +#endif diff --git a/src/qcommon/lua_debug.h b/src/qcommon/lua_debug.h new file mode 100644 index 000000000..6b7689aca --- /dev/null +++ b/src/qcommon/lua_debug.h @@ -0,0 +1,8 @@ +#ifndef LUA_DEBUG_H +#define LUA_DEBUG_H + +void Cmd_ScriptReload_f( void ); +void Cmd_ScriptList_f( void ); +void Cmd_ScriptDump_f( void ); + +#endif From 80273b89cd2e0096e041c2d2f2e263b23a3d8c86 Mon Sep 17 00:00:00 2001 From: timfox Date: Sun, 15 Feb 2026 14:08:41 -0800 Subject: [PATCH 2/4] Refactor Lua package detection in CMake and improve script dumping logic - Updated `CMakeLists.txt` to enhance Lua package detection by removing duplicates and improving the search logic for Lua libraries. - Modified `lua_debug.c` to introduce a truncation flag for the script dump command, allowing for more accurate handling of output when exceeding the maximum entry limit. These changes streamline the Lua integration process and enhance the debugging experience for Lua scripts. --- CMakeLists.txt | 35 ++++++++++++++++++++++++++--------- src/qcommon/lua_debug.c | 4 +++- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54b32909f..a25bb7091 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -284,15 +284,32 @@ if(USE_LUA) if((NOT LUA_INCLUDE_DIR OR NOT LUA_LIBRARY) AND NOT WIN32) find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) - pkg_check_modules(LUA_PKG QUIET lua5.5 lua-5.5 lua55 lua5.4 lua-5.4 lua54 lua5.3 lua-5.3 lua53 lua5.2 lua-5.2 lua52 lua5.1 lua-5.1 lua51 lua) - if(LUA_PKG_FOUND) - if(NOT LUA_INCLUDE_DIR AND LUA_PKG_INCLUDE_DIRS) - list(GET LUA_PKG_INCLUDE_DIRS 0 LUA_INCLUDE_DIR) - endif() - if(NOT LUA_LIBRARY AND LUA_PKG_LINK_LIBRARIES) - list(GET LUA_PKG_LINK_LIBRARIES 0 LUA_LIBRARY) - list(REMOVE_AT LUA_PKG_LINK_LIBRARIES 0) - set(LUA_EXTRA_LIBRARIES ${LUA_PKG_LINK_LIBRARIES}) + set(_LUA_PKG_NAMES ${_LUA_LIB_NAMES}) + list(REMOVE_DUPLICATES _LUA_PKG_NAMES) + if(_LUA_PKG_NAMES) + set(_LUA_PKG_DETECTED FALSE) + foreach(_LUA_PKG_NAME ${_LUA_PKG_NAMES}) + pkg_search_module(LUA_PKG QUIET ${_LUA_PKG_NAME}) + if(LUA_PKG_FOUND) + set(_LUA_PKG_DETECTED TRUE) + break() + endif() + endforeach() + if(_LUA_PKG_DETECTED) + if(NOT LUA_INCLUDE_DIR AND LUA_PKG_INCLUDE_DIRS) + list(GET LUA_PKG_INCLUDE_DIRS 0 LUA_INCLUDE_DIR) + endif() + if(NOT LUA_LIBRARY) + if(LUA_PKG_LIBRARIES) + list(GET LUA_PKG_LIBRARIES 0 LUA_LIBRARY) + list(REMOVE_AT LUA_PKG_LIBRARIES 0) + set(LUA_EXTRA_LIBRARIES ${LUA_PKG_LIBRARIES}) + elseif(LUA_PKG_LINK_LIBRARIES) + list(GET LUA_PKG_LINK_LIBRARIES 0 LUA_LIBRARY) + list(REMOVE_AT LUA_PKG_LINK_LIBRARIES 0) + set(LUA_EXTRA_LIBRARIES ${LUA_PKG_LINK_LIBRARIES}) + endif() + endif() endif() endif() endif() diff --git a/src/qcommon/lua_debug.c b/src/qcommon/lua_debug.c index cce5b5402..59afa8233 100644 --- a/src/qcommon/lua_debug.c +++ b/src/qcommon/lua_debug.c @@ -157,6 +157,7 @@ void Cmd_ScriptList_f( void ) { void Cmd_ScriptDump_f( void ) { int maxEntries = 128; int printed = 0; + qboolean truncated = qfalse; if ( Cmd_Argc() > 1 ) { const int requested = atoi( Cmd_Argv( 1 ) ); @@ -189,11 +190,12 @@ void Cmd_ScriptDump_f( void ) { printed++; if ( printed >= maxEntries ) { Com_Printf( " ... output truncated ...\n" ); + truncated = qtrue; break; } } - lua_pop( s_luaState, 1 ); + lua_pop( s_luaState, truncated ? 2 : 1 ); Com_Printf( "Lua: dumped %d global entr%s\n", printed, printed == 1 ? "y" : "ies" ); } From a759e4e0fe4f009290a744e6dcca6a18523e1b14 Mon Sep 17 00:00:00 2001 From: timfox Date: Sun, 15 Feb 2026 14:16:51 -0800 Subject: [PATCH 3/4] Enhance Lua support in CMake and CI configurations - Updated `CMakeLists.txt` to include additional Lua hint paths for Windows and improved error messaging for missing Lua headers/libraries. - Modified GitHub Actions workflow to install Lua 5.5 and its development libraries on Ubuntu and macOS environments, ensuring Lua support is available during builds. These changes improve the integration and detection of Lua scripting support across different platforms. --- .github/workflows/build.yml | 7 ++++--- CMakeLists.txt | 42 ++++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2b834de50..f1824e46f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -56,6 +56,7 @@ jobs: ${{ matrix.prefix }}-SDL2 ${{ matrix.prefix }}-openal ${{ matrix.prefix }}-freetype + ${{ matrix.prefix }}-lua msystem: ${{ matrix.msystem }} path-type: minimal release: false @@ -218,7 +219,7 @@ jobs: sudo rm -f /etc/apt/sources.list.d/azure-cli.list sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list sudo apt-get -qq update - sudo apt-get -y install cmake ninja-build libcurl4-openssl-dev mesa-common-dev libxxf86dga-dev libxrandr-dev libxxf86vm-dev libasound-dev libsdl2-dev libopenal-dev libfreetype6-dev + sudo apt-get -y install cmake ninja-build libcurl4-openssl-dev mesa-common-dev libxxf86dga-dev libxrandr-dev libxxf86vm-dev libasound-dev libsdl2-dev libopenal-dev libfreetype6-dev lua5.5 liblua5.5-dev - uses: actions/checkout@v4 @@ -315,7 +316,7 @@ jobs: apt-get -qq update apt-get install -y make gcc g++ cmake ninja-build - apt-get -y install libcurl4-openssl-dev mesa-common-dev libxxf86dga-dev libxrandr-dev libxxf86vm-dev libasound-dev libsdl2-dev libopenal-dev libfreetype6-dev + apt-get -y install libcurl4-openssl-dev mesa-common-dev libxxf86dga-dev libxrandr-dev libxxf86vm-dev libasound-dev libsdl2-dev libopenal-dev libfreetype6-dev lua5.5 liblua5.5-dev OUTDIR="${GITHUB_WORKSPACE}/bin" mkdir -p "$OUTDIR" @@ -378,7 +379,7 @@ jobs: steps: - name: Install tools - run: brew install coreutils sdl2 openal-soft cmake ninja freetype + run: brew install coreutils sdl2 openal-soft cmake ninja freetype lua@5.5 - uses: actions/checkout@v4 diff --git a/CMakeLists.txt b/CMakeLists.txt index a25bb7091..a686f8d62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -201,8 +201,20 @@ if(USE_LUA) /usr /opt/local /opt + /opt/homebrew /sw ) + if(WIN32) + list(APPEND _LUA_HINT_PATHS + "C:/msys64/mingw64" + "C:/msys64/ucrt64" + "C:/msys64/mingw32" + "C:/msys64/usr" + "C:/Lua" + "C:/Program Files/Lua" + "C:/Program Files (x86)/Lua" + ) + endif() find_path(LUA_INCLUDE_DIR NAMES lua.h @@ -316,24 +328,24 @@ if(USE_LUA) endif() if(NOT LUA_INCLUDE_DIR OR NOT LUA_LIBRARY) - message(FATAL_ERROR "USE_LUA=ON but Lua headers/library were not found.") - endif() - - set(LUA_FOUND TRUE) + message(WARNING "Lua headers/library not found; Lua scripting support will be disabled.") + else() + set(LUA_FOUND TRUE) - if(LUA_VERSION_NUM GREATER 0 AND LUA_VERSION_NUM LESS 501) - message(FATAL_ERROR "Lua 5.1+ is required.") - endif() + if(LUA_VERSION_NUM GREATER 0 AND LUA_VERSION_NUM LESS 501) + message(FATAL_ERROR "Lua 5.1+ is required.") + endif() - if(LUA_VERSION_STRING) - message(STATUS "Lua support enabled: ${LUA_VERSION_STRING} (${LUA_LIBRARY})") - else() - message(STATUS "Lua support enabled: ${LUA_LIBRARY}") - endif() + if(LUA_VERSION_STRING) + message(STATUS "Lua support enabled: ${LUA_VERSION_STRING} (${LUA_LIBRARY})") + else() + message(STATUS "Lua support enabled: ${LUA_LIBRARY}") + endif() - list(APPEND LUA_LINK_LIBRARIES ${LUA_LIBRARY}) - if(LUA_EXTRA_LIBRARIES) - list(APPEND LUA_LINK_LIBRARIES ${LUA_EXTRA_LIBRARIES}) + list(APPEND LUA_LINK_LIBRARIES ${LUA_LIBRARY}) + if(LUA_EXTRA_LIBRARIES) + list(APPEND LUA_LINK_LIBRARIES ${LUA_EXTRA_LIBRARIES}) + endif() endif() endif() From 7e2db25de01307bc45b0b733b9d2e3b913c6f6b7 Mon Sep 17 00:00:00 2001 From: timfox Date: Sun, 15 Feb 2026 14:19:22 -0800 Subject: [PATCH 4/4] Update Lua version in CI configurations - Changed the installation of Lua from version 5.5 to 5.4 in the GitHub Actions workflow for both Ubuntu and macOS environments. - Adjusted the installation command to reflect the updated Lua version and its development libraries. These modifications ensure compatibility with the latest Lua features and maintain consistency across build environments. --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f1824e46f..edef44cf1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -219,7 +219,7 @@ jobs: sudo rm -f /etc/apt/sources.list.d/azure-cli.list sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list sudo apt-get -qq update - sudo apt-get -y install cmake ninja-build libcurl4-openssl-dev mesa-common-dev libxxf86dga-dev libxrandr-dev libxxf86vm-dev libasound-dev libsdl2-dev libopenal-dev libfreetype6-dev lua5.5 liblua5.5-dev + sudo apt-get -y install cmake ninja-build libcurl4-openssl-dev mesa-common-dev libxxf86dga-dev libxrandr-dev libxxf86vm-dev libasound-dev libsdl2-dev libopenal-dev libfreetype6-dev lua5.4 liblua5.4-dev - uses: actions/checkout@v4 @@ -316,7 +316,7 @@ jobs: apt-get -qq update apt-get install -y make gcc g++ cmake ninja-build - apt-get -y install libcurl4-openssl-dev mesa-common-dev libxxf86dga-dev libxrandr-dev libxxf86vm-dev libasound-dev libsdl2-dev libopenal-dev libfreetype6-dev lua5.5 liblua5.5-dev + apt-get -y install libcurl4-openssl-dev mesa-common-dev libxxf86dga-dev libxrandr-dev libxxf86vm-dev libasound-dev libsdl2-dev libopenal-dev libfreetype6-dev lua5.4 liblua5.4-dev OUTDIR="${GITHUB_WORKSPACE}/bin" mkdir -p "$OUTDIR" @@ -379,7 +379,7 @@ jobs: steps: - name: Install tools - run: brew install coreutils sdl2 openal-soft cmake ninja freetype lua@5.5 + run: brew install coreutils sdl2 openal-soft cmake ninja freetype lua - uses: actions/checkout@v4