From de2a9423fc4f703ec2692e4b0fb921f16ab6eb22 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 16 May 2025 18:29:00 +0100 Subject: [PATCH 01/76] Extend `CScriptStorage` with optional dialect specifier --- src/xrGame/vs2022/xrGame.vcxproj | 8 + src/xrGame/vs2022/xrGame.vcxproj.filters | 27 + src/xrServerEntities/script_dialect.cpp | 12 + src/xrServerEntities/script_dialect.h | 15 + .../script_dialect_fennel.cpp | 35 + src/xrServerEntities/script_dialect_fennel.h | 12 + src/xrServerEntities/script_dialect_lua.cpp | 24 + src/xrServerEntities/script_dialect_lua.h | 12 + src/xrServerEntities/script_dialects.cpp | 24 + src/xrServerEntities/script_dialects.h | 27 + src/xrServerEntities/script_storage.cpp | 1469 +++++++++-------- 11 files changed, 935 insertions(+), 730 deletions(-) create mode 100644 src/xrServerEntities/script_dialect.cpp create mode 100644 src/xrServerEntities/script_dialect.h create mode 100644 src/xrServerEntities/script_dialect_fennel.cpp create mode 100644 src/xrServerEntities/script_dialect_fennel.h create mode 100644 src/xrServerEntities/script_dialect_lua.cpp create mode 100644 src/xrServerEntities/script_dialect_lua.h create mode 100644 src/xrServerEntities/script_dialects.cpp create mode 100644 src/xrServerEntities/script_dialects.h diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index 5a2393d9c6..b8cbda3925 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -337,6 +337,7 @@ + @@ -349,6 +350,9 @@ + + + @@ -1962,6 +1966,7 @@ + pch_script.h $(IntDir)$(ProjectName)_script.pch @@ -1995,6 +2000,9 @@ pch_script.h $(IntDir)$(ProjectName)_script.pch + + + pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index 4d3352f16d..5c56b397f9 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -2497,6 +2497,9 @@ {c14ffa0c-947d-49b9-8e01-269569b48371} + + {53abd459-f211-4178-b3c6-2be2afe329ba} + @@ -7404,6 +7407,18 @@ UI\Common\ImGui + + AI\AScript\ScriptDialect + + + AI\AScript\ScriptDialect + + + AI\AScript\ScriptDialect + + + AI\AScript\ScriptDialect + @@ -11102,6 +11117,18 @@ UI\Common\ImGui + + AI\AScript\ScriptDialect + + + AI\AScript\ScriptDialect + + + AI\AScript\ScriptDialect + + + AI\AScript\ScriptDialect + diff --git a/src/xrServerEntities/script_dialect.cpp b/src/xrServerEntities/script_dialect.cpp new file mode 100644 index 0000000000..2d0234a1c3 --- /dev/null +++ b/src/xrServerEntities/script_dialect.cpp @@ -0,0 +1,12 @@ +#include "stdafx.h" +#include "script_dialect.h" + +size_t CScriptDialect::tag_length() const +{ + return xr_strlen(tag()); +} + +bool CScriptDialect::parse(LPCSTR src) const +{ + return strncmp(tag(), src, tag_length()) == 0; +} diff --git a/src/xrServerEntities/script_dialect.h b/src/xrServerEntities/script_dialect.h new file mode 100644 index 0000000000..e2792f2b9c --- /dev/null +++ b/src/xrServerEntities/script_dialect.h @@ -0,0 +1,15 @@ +#pragma once + +#include "script_storage_space.h" +#include "script_space_forward.h" + +class CScriptDialect +{ +private: + virtual const char* tag() const = 0; +public: + size_t tag_length() const; + bool parse(LPCSTR src) const; + virtual size_t wrap_ofs() const = 0; + virtual size_t wrap(LPSTR dest, LPCSTR src, size_t tSize) const = 0; +}; diff --git a/src/xrServerEntities/script_dialect_fennel.cpp b/src/xrServerEntities/script_dialect_fennel.cpp new file mode 100644 index 0000000000..a11accbdca --- /dev/null +++ b/src/xrServerEntities/script_dialect_fennel.cpp @@ -0,0 +1,35 @@ +#include "stdafx.h" +#include "script_dialect_fennel.h" + +LPCSTR FENNEL_TAG = ";dialect fennel"; + +LPCSTR FENNEL_WRAPPER = "\ +require(\"fennel\").eval(\n\ + [=[\n\ +%s\n\ + ]=],\n\ + {\n\ + allowedGlobals = false,\n\ + correlate = true,\n\ + env = this,\n\ + useBitLib = true,\n\ + }\n\ +)\n"; + +LPCSTR CFennelDialect::tag() const +{ + return FENNEL_TAG; +} + +size_t CFennelDialect::wrap_ofs() const +{ + return xr_strlen(FENNEL_WRAPPER) - 1; +} + +size_t CFennelDialect::wrap(LPSTR dest, LPCSTR src, size_t tSize) const +{ + size_t wrapper_size = wrap_ofs(); + size_t out_size = wrapper_size + tSize; + xr_sprintf(dest, out_size, FENNEL_WRAPPER, src); + return out_size - 1; +} diff --git a/src/xrServerEntities/script_dialect_fennel.h b/src/xrServerEntities/script_dialect_fennel.h new file mode 100644 index 0000000000..121b0a364b --- /dev/null +++ b/src/xrServerEntities/script_dialect_fennel.h @@ -0,0 +1,12 @@ +#pragma once + +#include "script_dialect.h" + +class CFennelDialect : public CScriptDialect +{ +private: + const char* tag() const; +public: + size_t wrap_ofs() const; + size_t wrap(LPSTR dest, LPCSTR src, size_t tSize) const; +}; diff --git a/src/xrServerEntities/script_dialect_lua.cpp b/src/xrServerEntities/script_dialect_lua.cpp new file mode 100644 index 0000000000..3062bbd14f --- /dev/null +++ b/src/xrServerEntities/script_dialect_lua.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" +#include "script_dialect_lua.h" + +LPCSTR LUA_TAG = "--dialect lua"; + +LPCSTR LUA_WRAPPER = "setfenv(1, this)\n%s"; + +LPCSTR CLuaDialect::tag() const +{ + return LUA_TAG; +} + +size_t CLuaDialect::wrap_ofs() const +{ + return xr_strlen(LUA_WRAPPER) - 1; +} + +size_t CLuaDialect::wrap(LPSTR dest, LPCSTR src, size_t tSize) const +{ + size_t wrapper_size = wrap_ofs(); + size_t out_size = wrapper_size + tSize; + xr_sprintf(dest, out_size, LUA_WRAPPER, src); + return out_size - 1; +} diff --git a/src/xrServerEntities/script_dialect_lua.h b/src/xrServerEntities/script_dialect_lua.h new file mode 100644 index 0000000000..0e56c3559e --- /dev/null +++ b/src/xrServerEntities/script_dialect_lua.h @@ -0,0 +1,12 @@ +#pragma once + +#include "script_dialect.h" + +class CLuaDialect : public CScriptDialect +{ +private: + const char* tag() const; +public: + size_t wrap_ofs() const; + size_t wrap(LPSTR dest, LPCSTR src, size_t tSize) const; +}; diff --git a/src/xrServerEntities/script_dialects.cpp b/src/xrServerEntities/script_dialects.cpp new file mode 100644 index 0000000000..3062bbd14f --- /dev/null +++ b/src/xrServerEntities/script_dialects.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" +#include "script_dialect_lua.h" + +LPCSTR LUA_TAG = "--dialect lua"; + +LPCSTR LUA_WRAPPER = "setfenv(1, this)\n%s"; + +LPCSTR CLuaDialect::tag() const +{ + return LUA_TAG; +} + +size_t CLuaDialect::wrap_ofs() const +{ + return xr_strlen(LUA_WRAPPER) - 1; +} + +size_t CLuaDialect::wrap(LPSTR dest, LPCSTR src, size_t tSize) const +{ + size_t wrapper_size = wrap_ofs(); + size_t out_size = wrapper_size + tSize; + xr_sprintf(dest, out_size, LUA_WRAPPER, src); + return out_size - 1; +} diff --git a/src/xrServerEntities/script_dialects.h b/src/xrServerEntities/script_dialects.h new file mode 100644 index 0000000000..d594424834 --- /dev/null +++ b/src/xrServerEntities/script_dialects.h @@ -0,0 +1,27 @@ +#pragma once + +#include "stdafx.h" +#include "script_dialect.h" +#include "script_dialect_lua.h" +#include "script_dialect_fennel.h" + +struct CScriptDialects { + CLuaDialect lua; + CFennelDialect fennel; + + const CScriptDialect* parse(LPCSTR src) const { + if (lua.parse(src)) { + return &lua; + } + else if (fennel.parse(src)) { + return &fennel; + } + return NULL; + } +}; + +static CScriptDialects dialects; +static const CScriptDialects& ScriptDialects() +{ + return dialects; +} \ No newline at end of file diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index 6f16bf430b..d5e83a9913 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -8,6 +8,7 @@ #include "pch_script.h" #include "script_storage.h" +#include "script_dialects.h" #include "script_thread.h" #include "../xrCore/mezz_stringbuffer.h" #include @@ -24,27 +25,21 @@ #include "lua.hpp" #endif -LPCSTR file_header_old = - "\ - local function script_name() \ - return \"%s\" \ - end \ - local this = {} \ - %s this %s \ - setmetatable(this, {__index = _G}) \ - setfenv(1, this) \ - "; - -LPCSTR file_header_new = - "\ - local function script_name() \ - return \"%s\" \ - end \ - local this = {} \ - this._G = _G \ - %s this %s \ - setfenv(1, this) \ - "; +LPCSTR file_header_old = "\ +local function script_name()\n\ + return \"%s\"\n\ +end\n\ +local this = {}\n\ +%s this %s\n\ +setmetatable(this, {__index = _G})\n"; + +LPCSTR file_header_new = "\ +local function script_name()\n\ + return \"%s\"\n\ +end\n\ +local this = {}\n\ +this._G = _G\n\ +%s this %s\n"; LPCSTR file_header = 0; @@ -76,24 +71,24 @@ LPCSTR file_header = 0; #ifndef USE_DL_ALLOCATOR static void* lua_alloc(void* ud, void* ptr, size_t osize, size_t nsize) { - (void)ud; - (void)osize; - if (nsize == 0) - { - xr_free(ptr); - return NULL; - } - else + (void)ud; + (void)osize; + if (nsize == 0) + { + xr_free(ptr); + return NULL; + } + else #ifdef DEBUG_MEMORY_NAME return Memory.mem_realloc (ptr, nsize, "LUA"); #else // DEBUG_MEMORY_MANAGER - return Memory.mem_realloc(ptr, nsize); + return Memory.mem_realloc(ptr, nsize); #endif // DEBUG_MEMORY_MANAGER } u32 game_lua_memory_usage() { - return (0); + return (0); } #else //USE_DL_ALLOCATOR @@ -146,39 +141,39 @@ u32 game_lua_memory_usage() #endif //!USE_DL_ALLOCATOR static LPVOID __cdecl luabind_allocator( - luabind::memory_allocation_function_parameter const, - void const* const pointer, - size_t const size + luabind::memory_allocation_function_parameter const, + void const* const pointer, + size_t const size ) { - if (!size) - { - LPVOID non_const_pointer = const_cast(pointer); - xr_free(non_const_pointer); - return (0); - } - - if (!pointer) - { + if (!size) + { + LPVOID non_const_pointer = const_cast(pointer); + xr_free(non_const_pointer); + return (0); + } + + if (!pointer) + { #ifdef DEBUG return ( Memory.mem_alloc(size, "luabind") ); #else //!DEBUG - return (Memory.mem_alloc(size)); + return (Memory.mem_alloc(size)); #endif //-DEBUG - } + } - LPVOID non_const_pointer = const_cast(pointer); + LPVOID non_const_pointer = const_cast(pointer); #ifdef DEBUG return ( Memory.mem_realloc(non_const_pointer, size, "luabind") ); #else //!DEBUG - return (Memory.mem_realloc(non_const_pointer, size)); + return (Memory.mem_realloc(non_const_pointer, size)); #endif //-DEBUG } void setup_luabind_allocator() { - luabind::allocator = &luabind_allocator; - luabind::allocator_parameter = 0; + luabind::allocator = &luabind_allocator; + luabind::allocator_parameter = 0; } @@ -280,16 +275,15 @@ static void put_function(lua_State* state, u8 const* buffer, u32 const buffer_si #endif //!DEBUG #endif //-USE_LUAJIT_ONE - CScriptStorage::CScriptStorage() { - m_current_thread = 0; + m_current_thread = 0; #ifdef DEBUG m_stack_is_ready = false; #endif //-DEBUG - m_virtual_machine = 0; + m_virtual_machine = 0; #ifdef USE_LUA_STUDIO # ifndef USE_DEBUGGER @@ -300,53 +294,53 @@ CScriptStorage::CScriptStorage() CScriptStorage::~CScriptStorage() { - if (m_virtual_machine) - lua_close(m_virtual_machine); + if (m_virtual_machine) + lua_close(m_virtual_machine); } extern int luaopen_lua_extensions(lua_State* L); void disable_os_funcs(lua_State* L) { - lua_getglobal(L, "os"); - lua_pushnil(L); - lua_setfield(L, -2, "execute"); - lua_pushnil(L); - lua_setfield(L, -2, "rename"); - lua_pushnil(L); - lua_setfield(L, -2, "remove"); - lua_pushnil(L); - lua_setfield(L, -2, "exit"); - lua_pop(L, 1); - - lua_getglobal(L, "io"); - lua_pushnil(L); - lua_setfield(L, -2, "popen"); - lua_pop(L, 1); + lua_getglobal(L, "os"); + lua_pushnil(L); + lua_setfield(L, -2, "execute"); + lua_pushnil(L); + lua_setfield(L, -2, "rename"); + lua_pushnil(L); + lua_setfield(L, -2, "remove"); + lua_pushnil(L); + lua_setfield(L, -2, "exit"); + lua_pop(L, 1); + + lua_getglobal(L, "io"); + lua_pushnil(L); + lua_setfield(L, -2, "popen"); + lua_pop(L, 1); } void CScriptStorage::reinit() { - if (m_virtual_machine) - lua_close(m_virtual_machine); + if (m_virtual_machine) + lua_close(m_virtual_machine); #ifdef USE_GSC_MEM_ALLOC m_virtual_machine = lua_newstate(lua_alloc, NULL); #else - m_virtual_machine = luaL_newstate(); + m_virtual_machine = luaL_newstate(); #endif //-USE_GSC_MEM_ALLOC - if (!m_virtual_machine) - { - Msg("! ERROR : Cannot initialize script virtual machine!"); - return; - } + if (!m_virtual_machine) + { + Msg("! ERROR : Cannot initialize script virtual machine!"); + return; + } #ifndef USE_LUAJIT_ONE - luaL_openlibs(lua()); - if (strstr(Core.Params, "-nojit")) - luaJIT_setmode(lua(), 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); + luaL_openlibs(lua()); + if (strstr(Core.Params, "-nojit")) + luaJIT_setmode(lua(), 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); #else // USE_LUAJIT_ONE // initialize lua standard library functions struct luajit @@ -387,13 +381,13 @@ void CScriptStorage::reinit() #endif //!USE_LUAJIT_ONE - luaopen_lua_extensions(lua()); - disable_os_funcs(lua()); + luaopen_lua_extensions(lua()); + disable_os_funcs(lua()); - if (strstr(Core.Params, "-_g")) - file_header = file_header_new; //AVO: I get fatal crash at the start if this is used - else - file_header = file_header_old; + if (strstr(Core.Params, "-_g")) + file_header = file_header_new; //AVO: I get fatal crash at the start if this is used + else + file_header = file_header_old; } int CScriptStorage::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker) @@ -405,15 +399,15 @@ int CScriptStorage::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, # endif //-DEBUG #endif //!NO_XRGAME_SCRIPT_ENGINE - //#ifndef PRINT_CALL_STACK - //return (0); - //#else //PRINT_CALL_STACK + //#ifndef PRINT_CALL_STACK + //return (0); + //#else //PRINT_CALL_STACK # ifndef NO_XRGAME_SCRIPT_ENGINE - //AVO: allow LUA debug prints (i.e.: ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!");) + //AVO: allow LUA debug prints (i.e.: ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!");) # ifndef DEBUG - if (!strstr(Core.Params, "-dbg")) - return (0); + if (!strstr(Core.Params, "-dbg")) + return (0); # endif //!DEBUG # ifndef LUA_DEBUG_PRINT # ifdef DEBUG @@ -426,71 +420,71 @@ int CScriptStorage::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, # endif //-LUA_DEBUG_PRINT #endif //-NO_XRGAME_SCRIPT_ENGINE - LPCSTR S = "", SS = ""; - LPSTR S1; - string4096 S2; - switch (tLuaMessageType) - { - case ScriptStorage::eLuaMessageTypeInfo: - { - S = "* [LUA] "; - SS = "[INFO] "; - break; - } - case ScriptStorage::eLuaMessageTypeError: - { - S = "! [LUA] "; - SS = "[ERROR] "; - break; - } - case ScriptStorage::eLuaMessageTypeMessage: - { - S = "~ [LUA] "; - SS = "[MESSAGE] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookCall: - { - S = "[LUA][HOOK_CALL] "; - SS = "[CALL] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookReturn: - { - S = "[LUA][HOOK_RETURN] "; - SS = "[RETURN] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookLine: - { - S = "[LUA][HOOK_LINE] "; - SS = "[LINE] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookCount: - { - S = "[LUA][HOOK_COUNT] "; - SS = "[COUNT] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookTailReturn: - { - S = "[LUA][HOOK_TAIL_RETURN] "; - SS = "[TAIL_RETURN] "; - break; - } - default: NODEFAULT; - } - - xr_strcpy(S2, S); - S1 = S2 + xr_strlen(S); - int l_iResult = vsprintf(S1, caFormat, marker); - Msg("%s", S2); - - xr_strcpy(S2, SS); - S1 = S2 + xr_strlen(SS); - vsprintf(S1, caFormat, marker); - xr_strcat(S2, "\r\n"); + LPCSTR S = "", SS = ""; + LPSTR S1; + string4096 S2; + switch (tLuaMessageType) + { + case ScriptStorage::eLuaMessageTypeInfo: + { + S = "* [LUA] "; + SS = "[INFO] "; + break; + } + case ScriptStorage::eLuaMessageTypeError: + { + S = "! [LUA] "; + SS = "[ERROR] "; + break; + } + case ScriptStorage::eLuaMessageTypeMessage: + { + S = "~ [LUA] "; + SS = "[MESSAGE] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookCall: + { + S = "[LUA][HOOK_CALL] "; + SS = "[CALL] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookReturn: + { + S = "[LUA][HOOK_RETURN] "; + SS = "[RETURN] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookLine: + { + S = "[LUA][HOOK_LINE] "; + SS = "[LINE] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookCount: + { + S = "[LUA][HOOK_COUNT] "; + SS = "[COUNT] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookTailReturn: + { + S = "[LUA][HOOK_TAIL_RETURN] "; + SS = "[TAIL_RETURN] "; + break; + } + default: NODEFAULT; + } + + xr_strcpy(S2, S); + S1 = S2 + xr_strlen(S); + int l_iResult = vsprintf(S1, caFormat, marker); + Msg("%s", S2); + + xr_strcpy(S2, SS); + S1 = S2 + xr_strlen(SS); + vsprintf(S1, caFormat, marker); + xr_strcat(S2, "\r\n"); #ifdef LUA_DEBUG_PRINT //DEBUG # ifndef ENGINE_BUILD @@ -498,8 +492,8 @@ int CScriptStorage::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, # endif //!ENGINE_BUILD #endif //-LUA_DEBUG_PRINT DEBUG - return (l_iResult); - //#endif //-PRINT_CALL_STACK + return (l_iResult); + //#endif //-PRINT_CALL_STACK } //#ifdef PRINT_CALL_STACK @@ -512,32 +506,32 @@ void CScriptStorage::print_stack() m_stack_is_ready = false; #endif //-DEBUG - lua_State* L = lua(); - lua_Debug l_tDebugInfo; - for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); ++i) - { - lua_getinfo(L, "nSlu", &l_tDebugInfo); - if (!l_tDebugInfo.name) - { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, - l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); - } - else - { - if (!xr_strcmp(l_tDebugInfo.what, "C")) - { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); - } - else - { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, - l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); - } - } - } + lua_State* L = lua(); + lua_Debug l_tDebugInfo; + for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); ++i) + { + lua_getinfo(L, "nSlu", &l_tDebugInfo); + if (!l_tDebugInfo.name) + { + script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, + l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); + //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); + } + else + { + if (!xr_strcmp(l_tDebugInfo.what, "C")) + { + script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); + //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); + } + else + { + script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, + l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); + //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); + } + } + } } //#endif //-PRINT_CALL_STACK @@ -545,402 +539,417 @@ void CScriptStorage::print_stack() //AVO: added to stop duplicate stack output prints in log int __cdecl CScriptStorage::script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) { - va_list marker; - va_start(marker, caFormat); - int result = vscript_log(tLuaMessageType, caFormat, marker); - va_end(marker); - return result; + va_list marker; + va_start(marker, caFormat); + int result = vscript_log(tLuaMessageType, caFormat, marker); + va_end(marker); + return result; } //-AVO int __cdecl CScriptStorage::script_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) { - va_list marker; - va_start(marker, caFormat); - int result = vscript_log(tLuaMessageType, caFormat, marker); - va_end(marker); - - static bool reenterability = false; - if (!reenterability) - { - reenterability = true; - if (tLuaMessageType == ScriptStorage::eLuaMessageTypeError) { - ai().script_engine().print_stack(); - } else { - reenterability = false; - } - } - - // #ifdef PRINT_CALL_STACK - // # ifndef ENGINE_BUILD - // static bool reenterability = false; - // if (!reenterability) - // { - // reenterability = true; - // if (eLuaMessageTypeError == tLuaMessageType) - // ai().script_engine().print_stack(); - // reenterability = false; - // } - // # endif //!ENGINE_BUILD - // #endif //-PRINT_CALL_STACK - - return (result); + va_list marker; + va_start(marker, caFormat); + int result = vscript_log(tLuaMessageType, caFormat, marker); + va_end(marker); + + static bool reenterability = false; + if (!reenterability) + { + reenterability = true; + if (tLuaMessageType == ScriptStorage::eLuaMessageTypeError) { + ai().script_engine().print_stack(); + } else { + reenterability = false; + } + } + + // #ifdef PRINT_CALL_STACK + // # ifndef ENGINE_BUILD + // static bool reenterability = false; + // if (!reenterability) + // { + // reenterability = true; + // if (eLuaMessageTypeError == tLuaMessageType) + // ai().script_engine().print_stack(); + // reenterability = false; + // } + // # endif //!ENGINE_BUILD + // #endif //-PRINT_CALL_STACK + + return (result); } bool CScriptStorage::parse_namespace(LPCSTR caNamespaceName, LPSTR b, u32 const b_size, LPSTR c, u32 const c_size) { - *b = 0; - *c = 0; - LPSTR S2; - STRCONCAT(S2, caNamespaceName); - LPSTR S = S2; - for (int i = 0;; ++i) - { - if (!xr_strlen(S)) - { - script_log(ScriptStorage::eLuaMessageTypeError, "the namespace name %s is incorrect!", caNamespaceName); - return (false); - } - LPSTR S1 = strchr(S, '.'); - if (S1) - *S1 = 0; - - if (i) - xr_strcat(b, b_size, "{"); - xr_strcat(b, b_size, S); - xr_strcat(b, b_size, "="); - if (i) - xr_strcat(c, c_size, "}"); - if (S1) - S = ++S1; - else - break; - } - - return (true); + *b = 0; + *c = 0; + LPSTR S2; + STRCONCAT(S2, caNamespaceName); + LPSTR S = S2; + for (int i = 0;; ++i) + { + if (!xr_strlen(S)) + { + script_log(ScriptStorage::eLuaMessageTypeError, "the namespace name %s is incorrect!", caNamespaceName); + return (false); + } + LPSTR S1 = strchr(S, '.'); + if (S1) + *S1 = 0; + + if (i) + xr_strcat(b, b_size, "{"); + xr_strcat(b, b_size, S); + xr_strcat(b, b_size, "="); + if (i) + xr_strcat(c, c_size, "}"); + if (S1) + S = ++S1; + else + break; + } + + return (true); } bool CScriptStorage::load_buffer(lua_State* L, LPCSTR caBuffer, size_t tSize, LPCSTR caScriptName, LPCSTR caNameSpaceName) { - int l_iErrorCode; - if (caNameSpaceName && xr_strcmp("_G", caNameSpaceName)) - { - string512 insert, a, b; - - LPCSTR header = file_header; - - if (!parse_namespace(caNameSpaceName, a, sizeof(a), b, sizeof(b))) - return (false); - - xr_sprintf(insert, header, caNameSpaceName, a, b); - u32 str_len = xr_strlen(insert); - u32 const total_size = str_len + tSize; - LPSTR script = 0; - bool dynamic_allocation = false; - - __try - { - if (total_size < 768 * 1024) - script = (LPSTR)_alloca(total_size); - else - { + const CScriptDialects& dialects = ScriptDialects(); + const CScriptDialect* script_dialect = dialects.parse(caBuffer); + + size_t lang_tag_len = 0; + if (script_dialect) + lang_tag_len = script_dialect->tag_length(); + else + { + script_dialect = &dialects.lua; + } + + caBuffer += lang_tag_len; + tSize -= lang_tag_len; + + int l_iErrorCode; + if (caNameSpaceName && xr_strcmp("_G", caNameSpaceName)) + { + string512 insert, a, b; + + LPCSTR header = file_header; + + if (!parse_namespace(caNameSpaceName, a, sizeof(a), b, sizeof(b))) + return (false); + + xr_sprintf(insert, header, caNameSpaceName, a, b); + u32 str_len = xr_strlen(insert); + u32 const total_size = str_len + script_dialect->wrap_ofs() + tSize; + LPSTR script = 0; + bool dynamic_allocation = false; + + __try + { + if (total_size < 768 * 1024) + script = (LPSTR)_alloca(total_size); + else + { #ifdef DEBUG script = (LPSTR)Memory.mem_alloc(total_size, "lua script file"); #else //!DEBUG - script = (LPSTR)Memory.mem_alloc(total_size); + script = (LPSTR)Memory.mem_alloc(total_size); #endif //-DEBUG - dynamic_allocation = true; - } - } - __except (GetExceptionCode() == STATUS_STACK_OVERFLOW) - { - int errcode = _resetstkoflw(); - R_ASSERT2(errcode, "Could not reset the stack after \"Stack overflow\" exception!"); + dynamic_allocation = true; + } + } + __except (GetExceptionCode() == STATUS_STACK_OVERFLOW) + { + int errcode = _resetstkoflw(); + R_ASSERT2(errcode, "Could not reset the stack after \"Stack overflow\" exception!"); #ifdef DEBUG script = (LPSTR)Memory.mem_alloc(total_size, "lua script file (after exception)"); #else //#ifdef DEBUG - script = (LPSTR)Memory.mem_alloc(total_size); + script = (LPSTR)Memory.mem_alloc(total_size); #endif //#ifdef DEBUG - dynamic_allocation = true; - }; - - xr_strcpy(script, total_size, insert); - CopyMemory(script + str_len, caBuffer, u32(tSize)); - - l_iErrorCode = luaL_loadbuffer(L, script, tSize + str_len, caScriptName); - - if (dynamic_allocation) - xr_free(script); - } - else - { - // try - { - l_iErrorCode = luaL_loadbuffer(L, caBuffer, tSize, caScriptName); - } - // catch(...) { - // l_iErrorCode= LUA_ERRSYNTAX; - // } - } - - if (l_iErrorCode) - { + dynamic_allocation = true; + }; + + xr_strcpy(script, total_size, insert); + + size_t out_size = script_dialect->wrap(script + str_len, caBuffer, tSize); + + l_iErrorCode = luaL_loadbuffer(L, script, out_size + str_len, caScriptName); + + if (dynamic_allocation) + xr_free(script); + } + else + { + // try + { + l_iErrorCode = luaL_loadbuffer(L, caBuffer, tSize, caScriptName); + } + // catch(...) { + // l_iErrorCode= LUA_ERRSYNTAX; + // } + } + + if (l_iErrorCode) + { //#ifdef DEBUG - if (strstr(Core.Params, "-dbg")) print_output(L,caScriptName,l_iErrorCode); + if (strstr(Core.Params, "-dbg")) print_output(L,caScriptName,l_iErrorCode); //#endif //-DEBUG - on_error(L); - return (false); - } - return (true); + on_error(L); + return (false); + } + return (true); } xr_unordered_map> unlocalizers; bool unlocalizerPassed = false; static std::string join_list(const std::vector& items_vec, std::string delim = "\n") { - std::string ret; - for (const auto& i : items_vec) { - if (!ret.empty()) { - ret += delim; - } - ret += i; - } - return ret; + std::string ret; + for (const auto& i : items_vec) { + if (!ret.empty()) { + ret += delim; + } + ret += i; + } + return ret; }; static bool unlocalRegex(std::set& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { - if (std::regex_match(s, pattern)) { - //Msg("matching local function pattern"); - std::smatch match; - std::regex_search(s, match, pattern); - std::string variable = match[group]; - if (unlocals.find(variable) != unlocals.end()) { - Msg("[unlocalRegex] found variable %s to unlocal", variable.c_str()); - s = std::regex_replace(s, pattern, replacement); - return true; - } - } else { - return false; - } - return false; + if (std::regex_match(s, pattern)) { + //Msg("matching local function pattern"); + std::smatch match; + std::regex_search(s, match, pattern); + std::string variable = match[group]; + if (unlocals.find(variable) != unlocals.end()) { + Msg("[unlocalRegex] found variable %s to unlocal", variable.c_str()); + s = std::regex_replace(s, pattern, replacement); + return true; + } + } else { + return false; + } + return false; }; bool CScriptStorage::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) { - if (!unlocalizerPassed) { - auto file_list = FS.file_list_open("$game_config$", "unlocalizers\\", FS_RootOnly | FS_ListFiles); - if (!file_list) { - unlocalizerPassed = true; - } else { - xr_string id; - auto i = file_list->begin(); - auto e = file_list->end(); - for (; i != e; ++i) - { - u32 length = xr_strlen(*i); - - if (!((length >= 4) && - ((*i)[length - 4] == '.') && - ((*i)[length - 3] == 'l') && - ((*i)[length - 2] == 't') && - ((*i)[length - 1] == 'x'))) - continue; - - id.assign(*i, length - 4); - - string_path file_name; - FS.update_path(file_name, "$game_config$", (xr_string("unlocalizers\\") + id).c_str()); - xr_strcat(file_name, ".ltx"); - - Msg("opening file %s", file_name); - auto config = xr_new(file_name); - - typedef CInifile::Root sections_type; - sections_type& sections = config->sections(); - - sections_type::const_iterator i = sections.begin(); - sections_type::const_iterator e = sections.end(); - for (; i != e; ++i) - { - auto sectionName = std::string((*i)->Name.c_str()); - toLowerCase(sectionName); - if (unlocalizers.find(sectionName) == unlocalizers.end()) { - - // construct set that contains top level variables to delocalize by section name - unlocalizers[sectionName].clear(); - Msg("creating unlocalizer for script %s", sectionName.c_str()); - } - auto& data = (*i)->Data; - for (auto& item : data) { - unlocalizers[sectionName].insert(std::string(item.first.c_str())); - Msg("adding variable %s for unlocalizer for script %s", item.first.c_str(), sectionName.c_str()); - } - } - xr_delete(config); - } - FS.file_list_close(file_list); - unlocalizerPassed = true; - } - } - int start = lua_gettop(lua()); - string_path l_caLuaFileName; - IReader* l_tpFileReader = FS.r_open(caScriptName); - - if (!l_tpFileReader) - { - script_log(eLuaMessageTypeError, "Cannot open file \"%s\"", caScriptName); - return (false); - } - - // Unlocalize variables in the script defined by unlocalizers map - auto scriptContents = static_cast(l_tpFileReader->pointer()); - auto scriptLength = (size_t)l_tpFileReader->length(); - bool unlocalPerformed = false; - std::string unlocalizerResult; - std::string loweredNameSpaceName = caNameSpaceName; - toLowerCase(loweredNameSpaceName); - if (unlocalizers.find(loweredNameSpaceName) != unlocalizers.end()) { - Msg("found script %s in unlocalizers data", caNameSpaceName); - - // Get contents of the script file and split by lines - std::vector tokens; - std::string temp; - while (!l_tpFileReader->eof()) - { - char c = l_tpFileReader->r_u8(); - temp += c; - } - - std::stringstream stringStream(temp); - std::string line; - tokens.clear(); - while (std::getline(stringStream, line)) { - tokens.push_back(line); - } - - // Iterate lines and unlocalize variables - auto& unlocals = unlocalizers[loweredNameSpaceName]; - - /*for (auto& u : unlocals) { - Msg("%s", u); - }*/ - - for (auto& s : tokens) { - - //Msg("%s", s.c_str()); - - trim(s, "\n\r"); - if (s.empty()) { - continue; - } - - std::regex pattern; - - //local function x(a,b,c) - pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); - if (unlocalRegex(unlocals, s, pattern, 5, "$3$4$5$6$7")) { - unlocalPerformed = true; - continue; - } - - //local a = ... - //local a - //local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) - //local x; local y; - unsupported yet - pattern = std::regex(R"((^local)([\t ]+)(.*))"); - if (std::regex_match(s, pattern)) { - std::smatch match; - std::regex_search(s, match, pattern); - std::string m = match[3]; - - // strip comments - std::regex r = std::regex(R"((.*)--.*)"); - if (std::regex_match(m, r)) { - //Msg("found comments\n"); - std::smatch noncomments; - std::regex_search(m, noncomments, r); - m = noncomments[1]; - } - - auto variablesAndValues = splitStringLimit(m, "=", 1); - bool hasValue = variablesAndValues.size() > 1; - auto variables = splitStringMulti(variablesAndValues[0], ","); - for (auto v : variables) { - trim(v); - //Msg("%s\n", v.c_str()); - if (unlocals.find(v) != unlocals.end()) { - unlocalPerformed = true; - Msg("found variable %s to unlocal", v.c_str()); - s = std::regex_replace(s, pattern, "$3"); - if (!hasValue) { - - // strip comments - std::regex r = std::regex(R"((.*)(--.*))"); - if (std::regex_match(s, r)) { - //Msg("found comments\n"); - std::smatch noncomments; - std::regex_search(s, noncomments, r); - s = std::string(noncomments[1]) + "= nil " + std::string(noncomments[2]); - } else { - s += " = nil"; - } - } - break; - } - } - } - } - - // Store result back - /*for (auto& s : tokens) { - Msg("%s", s.c_str()); - }*/ - - unlocalizerResult = join_list(tokens); - scriptContents = unlocalizerResult.c_str(); - scriptLength = strlen(scriptContents); - } - - strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); - - bool bufferLoaded = false; - if (unlocalPerformed) { - bufferLoaded = load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName); - } else { - l_tpFileReader->rewind(); - bufferLoaded = load_buffer(lua(), static_cast(l_tpFileReader->pointer()), (size_t)l_tpFileReader->length(), l_caLuaFileName, caNameSpaceName); - } - - if (!bufferLoaded) - { - // VERIFY (lua_gettop(lua()) >= 4); - // lua_pop (lua(),4); - // VERIFY (lua_gettop(lua()) == start - 3); - lua_settop(lua(), start); - FS.r_close(l_tpFileReader); - return (false); - } - FS.r_close(l_tpFileReader); - - int errFuncId = -1; + if (!unlocalizerPassed) { + auto file_list = FS.file_list_open("$game_config$", "unlocalizers\\", FS_RootOnly | FS_ListFiles); + if (!file_list) { + unlocalizerPassed = true; + } else { + xr_string id; + auto i = file_list->begin(); + auto e = file_list->end(); + for (; i != e; ++i) + { + u32 length = xr_strlen(*i); + + if (!((length >= 4) && + ((*i)[length - 4] == '.') && + ((*i)[length - 3] == 'l') && + ((*i)[length - 2] == 't') && + ((*i)[length - 1] == 'x'))) + continue; + + id.assign(*i, length - 4); + + string_path file_name; + FS.update_path(file_name, "$game_config$", (xr_string("unlocalizers\\") + id).c_str()); + xr_strcat(file_name, ".ltx"); + + Msg("opening file %s", file_name); + auto config = xr_new(file_name); + + typedef CInifile::Root sections_type; + sections_type& sections = config->sections(); + + sections_type::const_iterator i = sections.begin(); + sections_type::const_iterator e = sections.end(); + for (; i != e; ++i) + { + auto sectionName = std::string((*i)->Name.c_str()); + toLowerCase(sectionName); + if (unlocalizers.find(sectionName) == unlocalizers.end()) { + + // construct set that contains top level variables to delocalize by section name + unlocalizers[sectionName].clear(); + Msg("creating unlocalizer for script %s", sectionName.c_str()); + } + auto& data = (*i)->Data; + for (auto& item : data) { + unlocalizers[sectionName].insert(std::string(item.first.c_str())); + Msg("adding variable %s for unlocalizer for script %s", item.first.c_str(), sectionName.c_str()); + } + } + xr_delete(config); + } + FS.file_list_close(file_list); + unlocalizerPassed = true; + } + } + int start = lua_gettop(lua()); + string_path l_caLuaFileName; + IReader* l_tpFileReader = FS.r_open(caScriptName); + + if (!l_tpFileReader) + { + script_log(eLuaMessageTypeError, "Cannot open file \"%s\"", caScriptName); + return (false); + } + + // Unlocalize variables in the script defined by unlocalizers map + auto scriptContents = static_cast(l_tpFileReader->pointer()); + auto scriptLength = (size_t)l_tpFileReader->length(); + bool unlocalPerformed = false; + std::string unlocalizerResult; + std::string loweredNameSpaceName = caNameSpaceName; + toLowerCase(loweredNameSpaceName); + if (unlocalizers.find(loweredNameSpaceName) != unlocalizers.end()) { + Msg("found script %s in unlocalizers data", caNameSpaceName); + + // Get contents of the script file and split by lines + std::vector tokens; + std::string temp; + while (!l_tpFileReader->eof()) + { + char c = l_tpFileReader->r_u8(); + temp += c; + } + + std::stringstream stringStream(temp); + std::string line; + tokens.clear(); + while (std::getline(stringStream, line)) { + tokens.push_back(line); + } + + // Iterate lines and unlocalize variables + auto& unlocals = unlocalizers[loweredNameSpaceName]; + + /*for (auto& u : unlocals) { + Msg("%s", u); + }*/ + + for (auto& s : tokens) { + + //Msg("%s", s.c_str()); + + trim(s, "\n\r"); + if (s.empty()) { + continue; + } + + std::regex pattern; + + //local function x(a,b,c) + pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); + if (unlocalRegex(unlocals, s, pattern, 5, "$3$4$5$6$7")) { + unlocalPerformed = true; + continue; + } + + //local a = ... + //local a + //local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) + //local x; local y; - unsupported yet + pattern = std::regex(R"((^local)([\t ]+)(.*))"); + if (std::regex_match(s, pattern)) { + std::smatch match; + std::regex_search(s, match, pattern); + std::string m = match[3]; + + // strip comments + std::regex r = std::regex(R"((.*)--.*)"); + if (std::regex_match(m, r)) { + //Msg("found comments\n"); + std::smatch noncomments; + std::regex_search(m, noncomments, r); + m = noncomments[1]; + } + + auto variablesAndValues = splitStringLimit(m, "=", 1); + bool hasValue = variablesAndValues.size() > 1; + auto variables = splitStringMulti(variablesAndValues[0], ","); + for (auto v : variables) { + trim(v); + //Msg("%s\n", v.c_str()); + if (unlocals.find(v) != unlocals.end()) { + unlocalPerformed = true; + Msg("found variable %s to unlocal", v.c_str()); + s = std::regex_replace(s, pattern, "$3"); + if (!hasValue) { + + // strip comments + std::regex r = std::regex(R"((.*)(--.*))"); + if (std::regex_match(s, r)) { + //Msg("found comments\n"); + std::smatch noncomments; + std::regex_search(s, noncomments, r); + s = std::string(noncomments[1]) + "= nil " + std::string(noncomments[2]); + } else { + s += " = nil"; + } + } + break; + } + } + } + } + + // Store result back + /*for (auto& s : tokens) { + Msg("%s", s.c_str()); + }*/ + + unlocalizerResult = join_list(tokens); + scriptContents = unlocalizerResult.c_str(); + scriptLength = strlen(scriptContents); + } + + strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); + + bool bufferLoaded = false; + if (unlocalPerformed) { + bufferLoaded = load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName); + } else { + l_tpFileReader->rewind(); + bufferLoaded = load_buffer(lua(), static_cast(l_tpFileReader->pointer()), (size_t)l_tpFileReader->length(), l_caLuaFileName, caNameSpaceName); + } + + if (!bufferLoaded) + { + // VERIFY (lua_gettop(lua()) >= 4); + // lua_pop (lua(),4); + // VERIFY (lua_gettop(lua()) == start - 3); + lua_settop(lua(), start); + FS.r_close(l_tpFileReader); + return (false); + } + FS.r_close(l_tpFileReader); + + int errFuncId = -1; #ifdef USE_DEBUGGER # ifndef USE_LUA_STUDIO if( ai().script_engine().debugger() ) errFuncId = ai().script_engine().debugger()->PrepareLua(lua()); # endif // #ifndef USE_LUA_STUDIO #endif // #ifdef USE_DEBUGGER - if (0) //. - { - for (int i = 0; lua_type(lua(), -i - 1); i++) - Msg("%2d : %s", -i - 1, lua_typename(lua(), lua_type(lua(), -i - 1))); - } + if (0) //. + { + for (int i = 0; lua_type(lua(), -i - 1); i++) + Msg("%2d : %s", -i - 1, lua_typename(lua(), lua_type(lua(), -i - 1))); + } - // because that's the first and the only call of the main chunk - there is no point to compile it - // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_OFF); // Oles - int l_iErrorCode = lua_pcall(lua(), 0, 0, (-1 == errFuncId) ? 0 : errFuncId); // new_Andy - // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_ON); // Oles + // because that's the first and the only call of the main chunk - there is no point to compile it + // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_OFF); // Oles + int l_iErrorCode = lua_pcall(lua(), 0, 0, (-1 == errFuncId) ? 0 : errFuncId); // new_Andy + // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_ON); // Oles #ifdef USE_DEBUGGER # ifndef USE_LUA_STUDIO @@ -948,194 +957,194 @@ bool CScriptStorage::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) ai().script_engine().debugger()->UnPrepareLua(lua(),errFuncId); # endif // #ifndef USE_LUA_STUDIO #endif // #ifdef USE_DEBUGGER - if (l_iErrorCode) - { + if (l_iErrorCode) + { //#ifdef DEBUG - if (strstr(Core.Params, "-dbg")) print_output(lua(),caScriptName,l_iErrorCode); + if (strstr(Core.Params, "-dbg")) print_output(lua(),caScriptName,l_iErrorCode); //#endif - on_error(lua()); - lua_settop(lua(), start); - return (false); - } + on_error(lua()); + lua_settop(lua(), start); + return (false); + } - return (true); + return (true); } bool CScriptStorage::load_file_into_namespace(LPCSTR caScriptName, LPCSTR caNamespaceName) { - int start = lua_gettop(lua()); - if (!do_file(caScriptName, caNamespaceName)) - { - Msg("! [ERROR] --- Failed to load script %s", caNamespaceName); - lua_settop(lua(), start); - return (false); - } - VERIFY(lua_gettop(lua()) == start); - return (true); + int start = lua_gettop(lua()); + if (!do_file(caScriptName, caNamespaceName)) + { + Msg("! [ERROR] --- Failed to load script %s", caNamespaceName); + lua_settop(lua(), start); + return (false); + } + VERIFY(lua_gettop(lua()) == start); + return (true); } bool CScriptStorage::namespace_loaded(LPCSTR N, bool remove_from_stack) { - int start = lua_gettop(lua()); - lua_pushstring(lua(), "_G"); - lua_rawget(lua(), LUA_GLOBALSINDEX); - string256 S2; - xr_strcpy(S2, N); - LPSTR S = S2; - for (;;) - { - if (!xr_strlen(S)) - { - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(start == lua_gettop(lua())); - return (false); - } - LPSTR S1 = strchr(S, '.'); - if (S1) - *S1 = 0; - lua_pushstring(lua(), S); - lua_rawget(lua(), -2); - if (lua_isnil(lua(), -1)) - { - // lua_settop (lua(),0); - VERIFY(lua_gettop(lua()) >= 2); - lua_pop(lua(), 2); - VERIFY(start == lua_gettop(lua())); - return (false); // there is no namespace! - } - else if (!lua_istable(lua(), -1)) - { - // lua_settop (lua(),0); - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(start == lua_gettop(lua())); - FATAL(" Error : the namespace name is already being used by the non-table object!\n"); - return (false); - } - lua_remove(lua(), -2); - if (S1) - S = ++S1; - else - break; - } - if (!remove_from_stack) - { - VERIFY(lua_gettop(lua()) == start + 1); - } - else - { - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(lua_gettop(lua()) == start); - } - return (true); + int start = lua_gettop(lua()); + lua_pushstring(lua(), "_G"); + lua_rawget(lua(), LUA_GLOBALSINDEX); + string256 S2; + xr_strcpy(S2, N); + LPSTR S = S2; + for (;;) + { + if (!xr_strlen(S)) + { + VERIFY(lua_gettop(lua()) >= 1); + lua_pop(lua(), 1); + VERIFY(start == lua_gettop(lua())); + return (false); + } + LPSTR S1 = strchr(S, '.'); + if (S1) + *S1 = 0; + lua_pushstring(lua(), S); + lua_rawget(lua(), -2); + if (lua_isnil(lua(), -1)) + { + // lua_settop (lua(),0); + VERIFY(lua_gettop(lua()) >= 2); + lua_pop(lua(), 2); + VERIFY(start == lua_gettop(lua())); + return (false); // there is no namespace! + } + else if (!lua_istable(lua(), -1)) + { + // lua_settop (lua(),0); + VERIFY(lua_gettop(lua()) >= 1); + lua_pop(lua(), 1); + VERIFY(start == lua_gettop(lua())); + FATAL(" Error : the namespace name is already being used by the non-table object!\n"); + return (false); + } + lua_remove(lua(), -2); + if (S1) + S = ++S1; + else + break; + } + if (!remove_from_stack) + { + VERIFY(lua_gettop(lua()) == start + 1); + } + else + { + VERIFY(lua_gettop(lua()) >= 1); + lua_pop(lua(), 1); + VERIFY(lua_gettop(lua()) == start); + } + return (true); } bool CScriptStorage::object(LPCSTR identifier, int type) { - int start = lua_gettop(lua()); - lua_pushnil(lua()); - while (lua_next(lua(), -2)) - { - if ((lua_type(lua(), -1) == type) && !xr_strcmp(identifier, lua_tostring(lua(), -2))) - { - VERIFY(lua_gettop(lua()) >= 3); - lua_pop(lua(), 3); - VERIFY(lua_gettop(lua()) == start - 1); - return (true); - } - lua_pop(lua(), 1); - } - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(lua_gettop(lua()) == start - 1); - return (false); + int start = lua_gettop(lua()); + lua_pushnil(lua()); + while (lua_next(lua(), -2)) + { + if ((lua_type(lua(), -1) == type) && !xr_strcmp(identifier, lua_tostring(lua(), -2))) + { + VERIFY(lua_gettop(lua()) >= 3); + lua_pop(lua(), 3); + VERIFY(lua_gettop(lua()) == start - 1); + return (true); + } + lua_pop(lua(), 1); + } + VERIFY(lua_gettop(lua()) >= 1); + lua_pop(lua(), 1); + VERIFY(lua_gettop(lua()) == start - 1); + return (false); } bool CScriptStorage::object(LPCSTR namespace_name, LPCSTR identifier, int type) { - int start = lua_gettop(lua()); - if (xr_strlen(namespace_name) && !namespace_loaded(namespace_name, false)) - { - VERIFY(lua_gettop(lua()) == start); - return (false); - } - bool result = object(identifier, type); - VERIFY(lua_gettop(lua()) == start); - return (result); + int start = lua_gettop(lua()); + if (xr_strlen(namespace_name) && !namespace_loaded(namespace_name, false)) + { + VERIFY(lua_gettop(lua()) == start); + return (false); + } + bool result = object(identifier, type); + VERIFY(lua_gettop(lua()) == start); + return (result); } luabind::object CScriptStorage::name_space(LPCSTR namespace_name) { - string256 S1; - xr_strcpy(S1, namespace_name); - LPSTR S = S1; - luabind::object lua_namespace = luabind::get_globals(lua()); - for (;;) - { - if (!xr_strlen(S)) - return (lua_namespace); - LPSTR I = strchr(S, '.'); - if (!I) - return (lua_namespace[S]); - *I = 0; - lua_namespace = lua_namespace[S]; - S = I + 1; - } + string256 S1; + xr_strcpy(S1, namespace_name); + LPSTR S = S1; + luabind::object lua_namespace = luabind::get_globals(lua()); + for (;;) + { + if (!xr_strlen(S)) + return (lua_namespace); + LPSTR I = strchr(S, '.'); + if (!I) + return (lua_namespace[S]); + *I = 0; + lua_namespace = lua_namespace[S]; + S = I + 1; + } } #include struct raii_guard : private boost::noncopyable { - int m_error_code; - LPCSTR const& m_error_description; + int m_error_code; + LPCSTR const& m_error_description; - raii_guard(int error_code, LPCSTR const& m_description) : m_error_code(error_code), - m_error_description(m_description) - { - } + raii_guard(int error_code, LPCSTR const& m_description) : m_error_code(error_code), + m_error_description(m_description) + { + } - ~raii_guard() - { + ~raii_guard() + { #ifdef DEBUG bool lua_studio_connected = !!ai().script_engine().debugger(); if (!lua_studio_connected) #endif //-DEBUG - { + { #ifdef DEBUG static bool const break_on_assert = !!strstr(Core.Params,"-break_on_assert"); #else //!DEBUG - static bool const break_on_assert = false; //Alundaio: Can't get a proper stack trace with this enabled + static bool const break_on_assert = false; //Alundaio: Can't get a proper stack trace with this enabled #endif //-DEBUG - if (!m_error_code) - return; - - if (break_on_assert) - R_ASSERT2(!m_error_code, m_error_description); - else - Msg("! [SCRIPT ERROR]: %s", m_error_description); - } - } + if (!m_error_code) + return; + + if (break_on_assert) + R_ASSERT2(!m_error_code, m_error_description); + else + Msg("! [SCRIPT ERROR]: %s", m_error_description); + } + } }; //-struct raii_guard bool CScriptStorage::print_output(lua_State* L, LPCSTR caScriptFileName, int iErorCode) { - if (iErorCode) - print_error(L, iErorCode); + if (iErorCode) + print_error(L, iErorCode); - LPCSTR S = "see call_stack for details!"; + LPCSTR S = "see call_stack for details!"; - raii_guard guard(iErorCode, S); + raii_guard guard(iErorCode, S); - if (!lua_isstring(L, -1)) - return (false); + if (!lua_isstring(L, -1)) + return (false); - S = lua_tostring(L, -1); - if (!xr_strcmp(S, "cannot resume dead coroutine")) - { - VERIFY2("Please do not return any values from main!!!", caScriptFileName); + S = lua_tostring(L, -1); + if (!xr_strcmp(S, "cannot resume dead coroutine")) + { + VERIFY2("Please do not return any values from main!!!", caScriptFileName); #ifdef USE_DEBUGGER # ifndef USE_LUA_STUDIO if(ai().script_engine().debugger() && ai().script_engine().debugger()->Active() ){ @@ -1144,12 +1153,12 @@ bool CScriptStorage::print_output(lua_State* L, LPCSTR caScriptFileName, int iEr } # endif //!USE_LUA_STUDIO #endif //-USE_DEBUGGER - } - else - { - if (!iErorCode) - script_log(ScriptStorage::eLuaMessageTypeInfo, "Output from %s", caScriptFileName); - script_log(iErorCode ? ScriptStorage::eLuaMessageTypeError : ScriptStorage::eLuaMessageTypeMessage, "%s", S); + } + else + { + if (!iErorCode) + script_log(ScriptStorage::eLuaMessageTypeInfo, "Output from %s", caScriptFileName); + script_log(iErorCode ? ScriptStorage::eLuaMessageTypeError : ScriptStorage::eLuaMessageTypeMessage, "%s", S); #ifdef USE_DEBUGGER # ifndef USE_LUA_STUDIO if (ai().script_engine().debugger() && ai().script_engine().debugger()->Active()) { @@ -1158,46 +1167,46 @@ bool CScriptStorage::print_output(lua_State* L, LPCSTR caScriptFileName, int iEr } # endif //!USE_LUA_STUDIO #endif //-USE_DEBUGGER - } - return (true); + } + return (true); } void CScriptStorage::print_error(lua_State* L, int iErrorCode) { - switch (iErrorCode) - { - case LUA_ERRRUN: - { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT RUNTIME ERROR"); - break; - } - case LUA_ERRMEM: - { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (memory allocation)"); - break; - } - case LUA_ERRERR: - { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (while running the error handler function)"); - break; - } - case LUA_ERRFILE: - { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (while running file)"); - break; - } - case LUA_ERRSYNTAX: - { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT SYNTAX ERROR"); - break; - } - case LUA_YIELD: - { - script_log(ScriptStorage::eLuaMessageTypeInfo, "Thread is yielded"); - break; - } - default: NODEFAULT; - } + switch (iErrorCode) + { + case LUA_ERRRUN: + { + script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT RUNTIME ERROR"); + break; + } + case LUA_ERRMEM: + { + script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (memory allocation)"); + break; + } + case LUA_ERRERR: + { + script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (while running the error handler function)"); + break; + } + case LUA_ERRFILE: + { + script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (while running file)"); + break; + } + case LUA_ERRSYNTAX: + { + script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT SYNTAX ERROR"); + break; + } + case LUA_YIELD: + { + script_log(ScriptStorage::eLuaMessageTypeInfo, "Thread is yielded"); + break; + } + default: NODEFAULT; + } } #ifdef LUA_DEBUG_PRINT //DEBUG @@ -1212,19 +1221,19 @@ void CScriptStorage::flush_log() int CScriptStorage::error_log(LPCSTR format, ...) { - va_list marker; - va_start(marker, format); + va_list marker; + va_start(marker, format); - LPCSTR S = "! [LUA][ERROR] "; - LPSTR S1; - string4096 S2; - xr_strcpy(S2, S); - S1 = S2 + xr_strlen(S); + LPCSTR S = "! [LUA][ERROR] "; + LPSTR S1; + string4096 S2; + xr_strcpy(S2, S); + S1 = S2 + xr_strlen(S); - int result = vsprintf(S1, format, marker); - va_end(marker); + int result = vsprintf(S1, format, marker); + va_end(marker); - Msg("%s", S2); + Msg("%s", S2); - return (result); + return (result); } From d2b2e7fd09af845fc3ddacd27261a78a341df185 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sat, 17 May 2025 21:49:50 +0100 Subject: [PATCH 02/76] CScriptStorage / CScriptDialect refactor - Refactor Lua source composition around std::string - Now memory-safe - Fixes undefined behaviour that was hidden by Lua header padding - Improve structure of CScriptDialect family - Separated headers / implementation - Switch to by-value std::string patterns - Make CScriptDialect authoritative over wrapping and unlocalization - Implement lisp, lisp-macro dialects that compile to the corresponding Fennel constructs --- src/xrGame/vs2022/xrGame.vcxproj | 6 +- src/xrGame/vs2022/xrGame.vcxproj.filters | 10 +- src/xrServerEntities/script_dialect.h | 5 +- .../script_dialect_fennel.cpp | 35 -- src/xrServerEntities/script_dialect_fennel.h | 12 - src/xrServerEntities/script_dialect_lisp.cpp | 61 ++++ src/xrServerEntities/script_dialect_lisp.h | 12 + .../script_dialect_lisp_macro.cpp | 43 +++ .../script_dialect_lisp_macro.h | 12 + src/xrServerEntities/script_dialect_lua.cpp | 163 +++++++++- src/xrServerEntities/script_dialect_lua.h | 4 +- src/xrServerEntities/script_dialects.cpp | 37 +-- src/xrServerEntities/script_dialects.h | 16 +- src/xrServerEntities/script_storage.cpp | 305 ++---------------- src/xrServerEntities/script_storage.h | 83 ++++- src/xrServerEntities/script_thread.cpp | 2 +- 16 files changed, 435 insertions(+), 371 deletions(-) delete mode 100644 src/xrServerEntities/script_dialect_fennel.cpp delete mode 100644 src/xrServerEntities/script_dialect_fennel.h create mode 100644 src/xrServerEntities/script_dialect_lisp.cpp create mode 100644 src/xrServerEntities/script_dialect_lisp.h create mode 100644 src/xrServerEntities/script_dialect_lisp_macro.cpp create mode 100644 src/xrServerEntities/script_dialect_lisp_macro.h diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index b8cbda3925..af64fbcc7d 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -338,6 +338,7 @@ + @@ -351,7 +352,7 @@ - + @@ -1967,6 +1968,7 @@ + pch_script.h $(IntDir)$(ProjectName)_script.pch @@ -2001,7 +2003,7 @@ $(IntDir)$(ProjectName)_script.pch - + pch_script.h diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index 5c56b397f9..cf99197887 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -7410,7 +7410,7 @@ AI\AScript\ScriptDialect - + AI\AScript\ScriptDialect @@ -7419,6 +7419,9 @@ AI\AScript\ScriptDialect + + AI\AScript\ScriptDialect + @@ -11120,7 +11123,7 @@ AI\AScript\ScriptDialect - + AI\AScript\ScriptDialect @@ -11129,6 +11132,9 @@ AI\AScript\ScriptDialect + + AI\AScript\ScriptDialect + diff --git a/src/xrServerEntities/script_dialect.h b/src/xrServerEntities/script_dialect.h index e2792f2b9c..868b603f60 100644 --- a/src/xrServerEntities/script_dialect.h +++ b/src/xrServerEntities/script_dialect.h @@ -2,6 +2,7 @@ #include "script_storage_space.h" #include "script_space_forward.h" +#include "script_storage.h" class CScriptDialect { @@ -10,6 +11,6 @@ class CScriptDialect public: size_t tag_length() const; bool parse(LPCSTR src) const; - virtual size_t wrap_ofs() const = 0; - virtual size_t wrap(LPSTR dest, LPCSTR src, size_t tSize) const = 0; + virtual std::string wrap(const std::string& src, LPCSTR caNameSpaceName) const = 0; + virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const = 0; }; diff --git a/src/xrServerEntities/script_dialect_fennel.cpp b/src/xrServerEntities/script_dialect_fennel.cpp deleted file mode 100644 index a11accbdca..0000000000 --- a/src/xrServerEntities/script_dialect_fennel.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "stdafx.h" -#include "script_dialect_fennel.h" - -LPCSTR FENNEL_TAG = ";dialect fennel"; - -LPCSTR FENNEL_WRAPPER = "\ -require(\"fennel\").eval(\n\ - [=[\n\ -%s\n\ - ]=],\n\ - {\n\ - allowedGlobals = false,\n\ - correlate = true,\n\ - env = this,\n\ - useBitLib = true,\n\ - }\n\ -)\n"; - -LPCSTR CFennelDialect::tag() const -{ - return FENNEL_TAG; -} - -size_t CFennelDialect::wrap_ofs() const -{ - return xr_strlen(FENNEL_WRAPPER) - 1; -} - -size_t CFennelDialect::wrap(LPSTR dest, LPCSTR src, size_t tSize) const -{ - size_t wrapper_size = wrap_ofs(); - size_t out_size = wrapper_size + tSize; - xr_sprintf(dest, out_size, FENNEL_WRAPPER, src); - return out_size - 1; -} diff --git a/src/xrServerEntities/script_dialect_fennel.h b/src/xrServerEntities/script_dialect_fennel.h deleted file mode 100644 index 121b0a364b..0000000000 --- a/src/xrServerEntities/script_dialect_fennel.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "script_dialect.h" - -class CFennelDialect : public CScriptDialect -{ -private: - const char* tag() const; -public: - size_t wrap_ofs() const; - size_t wrap(LPSTR dest, LPCSTR src, size_t tSize) const; -}; diff --git a/src/xrServerEntities/script_dialect_lisp.cpp b/src/xrServerEntities/script_dialect_lisp.cpp new file mode 100644 index 0000000000..e2c9cda1e7 --- /dev/null +++ b/src/xrServerEntities/script_dialect_lisp.cpp @@ -0,0 +1,61 @@ +#include "stdafx.h" +#include "script_dialect_lisp.h" +#include + +LPCSTR LISP_TAG = ";dialect lisp"; + +LPCSTR LISP_WRAPPER = R"( +local function script_name() + return "%s" +end + +local this = {} +%s this %s +setmetatable(this, {__index = _G}) + +require("fennel").eval( + [=[ +%s + ]=], + { + allowedGlobals = false, + correlate = true, + env = this, + useBitLib = true, + ["error-pinpoint"] = false, + } +) +)"; + +LPCSTR LISP_UNLOCALIZE_WRAPPER = R"( +(import-macros {: unlocalize} :lisp_unlocalize) +(unlocalize + [%s] + %s) +)"; + +LPCSTR CLispDialect::tag() const +{ + return LISP_TAG; +} + +std::string CLispDialect::wrap(const std::string& src, LPCSTR caNameSpaceName) const +{ + string512 a, b; + if (!parse_namespace(caNameSpaceName, a, sizeof(a), b, sizeof(b))) + return (false); + + return string_format(LISP_WRAPPER, caNameSpaceName, a, b, src); +} + +std::string CLispDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const +{ + std::string unlocs; + for (auto unloc : unlocalizer) + { + if (unlocs.length() > 0) + unlocs += " "; + unlocs += unloc; + } + return string_format(LISP_UNLOCALIZE_WRAPPER, unlocs, src); +} diff --git a/src/xrServerEntities/script_dialect_lisp.h b/src/xrServerEntities/script_dialect_lisp.h new file mode 100644 index 0000000000..f273a8a826 --- /dev/null +++ b/src/xrServerEntities/script_dialect_lisp.h @@ -0,0 +1,12 @@ +#pragma once + +#include "script_dialect.h" + +class CLispDialect : public CScriptDialect +{ +private: + const char* tag() const; +public: + std::string wrap(const std::string& src, LPCSTR caNameSpaceName) const; + std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; +}; diff --git a/src/xrServerEntities/script_dialect_lisp_macro.cpp b/src/xrServerEntities/script_dialect_lisp_macro.cpp new file mode 100644 index 0000000000..5c7ee38e7c --- /dev/null +++ b/src/xrServerEntities/script_dialect_lisp_macro.cpp @@ -0,0 +1,43 @@ +#include "stdafx.h" +#include "script_dialect_lisp_macro.h" + +LPCSTR LISP_MACRO_TAG = ";dialect lisp-macro"; + +LPCSTR LISP_MACRO_WRAPPER = R"( +local fennel = require("fennel") +table.insert( + fennel["macro-searchers"], + function(module_name) + if module_name ~= "%s" then return end + return function() + return fennel.eval( + [=[ +%s + ]=], + { + correlate = true, + env = "_COMPILER", + useBitLib = true, + ["error-pinpoint"] = false, + } + ) + end, + module_name + end +) +)"; + +LPCSTR CLispMacroDialect::tag() const +{ + return LISP_MACRO_TAG; +} + +std::string CLispMacroDialect::wrap(const std::string& src, LPCSTR caNameSpaceName) const +{ + return string_format(LISP_MACRO_WRAPPER, caNameSpaceName, src); +} + +std::string CLispMacroDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const +{ + return src; +} diff --git a/src/xrServerEntities/script_dialect_lisp_macro.h b/src/xrServerEntities/script_dialect_lisp_macro.h new file mode 100644 index 0000000000..1e9a4fb9f4 --- /dev/null +++ b/src/xrServerEntities/script_dialect_lisp_macro.h @@ -0,0 +1,12 @@ +#pragma once + +#include "script_dialect.h" + +class CLispMacroDialect : public CScriptDialect +{ +private: + const char* tag() const; +public: + std::string wrap(const std::string& src, LPCSTR caNameSpaceName) const; + std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; +}; diff --git a/src/xrServerEntities/script_dialect_lua.cpp b/src/xrServerEntities/script_dialect_lua.cpp index 3062bbd14f..414b095951 100644 --- a/src/xrServerEntities/script_dialect_lua.cpp +++ b/src/xrServerEntities/script_dialect_lua.cpp @@ -1,24 +1,169 @@ #include "stdafx.h" #include "script_dialect_lua.h" +#include +#include +#include "../xrCore/mezz_stringbuffer.h" + LPCSTR LUA_TAG = "--dialect lua"; -LPCSTR LUA_WRAPPER = "setfenv(1, this)\n%s"; +LPCSTR LUA_WRAPPER = R"( +local function script_name() + return "%s" +end + +local this = {} +%s this %s +setmetatable(this, {__index = _G}) + +setfenv(1, this) +%s +)"; LPCSTR CLuaDialect::tag() const { return LUA_TAG; } -size_t CLuaDialect::wrap_ofs() const +std::string CLuaDialect::wrap(const std::string& src, LPCSTR caNameSpaceName) const { - return xr_strlen(LUA_WRAPPER) - 1; + string512 a, b; + if (!parse_namespace(caNameSpaceName, a, sizeof(a), b, sizeof(b))) + return (false); + + return string_format(LUA_WRAPPER, caNameSpaceName, a, b, src); } -size_t CLuaDialect::wrap(LPSTR dest, LPCSTR src, size_t tSize) const +static bool unlocalRegex(Unlocalizer& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { + if (std::regex_match(s, pattern)) { + //Msg("matching local function pattern"); + std::smatch match; + std::regex_search(s, match, pattern); + std::string variable = match[group]; + if (unlocals.find(variable) != unlocals.end()) { + Msg("[unlocalRegex] found variable %s to unlocal", variable.c_str()); + s = std::regex_replace(s, pattern, replacement); + return true; + } + } + else { + return false; + } + return false; +}; + +static std::string join_list(const std::vector& items_vec, std::string delim = "\n") { + std::string ret; + for (const auto& i : items_vec) { + if (!ret.empty()) { + ret += delim; + } + ret += i; + } + return ret; +}; + +std::string CLuaDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const { - size_t wrapper_size = wrap_ofs(); - size_t out_size = wrapper_size + tSize; - xr_sprintf(dest, out_size, LUA_WRAPPER, src); - return out_size - 1; -} + bool unlocalPerformed = false; + std::string unlocalizerResult; + + // Get contents of the script file and split by lines + std::vector tokens; + std::string temp; + temp += src; + + std::stringstream stringStream(temp); + std::string line; + tokens.clear(); + while (std::getline(stringStream, line)) { + tokens.push_back(line); + } + + /*for (auto& u : unlocalizer) { + Msg("Unlocalizer: %s", u); + }*/ + + for (std::string& s : tokens) { + + //Msg("Line: %s", s.c_str()); + + trim(s, "\n\r"); + if (s.empty()) { + //Msg("Empty, continuing"); + continue; + } + + std::regex pattern; + + //local function x(a,b,c) + pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); + if (unlocalRegex(unlocalizer, s, pattern, 5, "$3$4$5$6$7")) { + //Msg("Regex matched"); + unlocalPerformed = true; + continue; + } + + //Msg("Regex not matched"); + + //local a = ... + //local a + //local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) + //local x; local y; - unsupported yet + pattern = std::regex(R"((^local)([\t ]+)(.*))"); + if (std::regex_match(s, pattern)) { + std::smatch match; + std::regex_search(s, match, pattern); + std::string m = match[3]; + + // strip comments + std::regex r = std::regex(R"((.*)--.*)"); + if (std::regex_match(m, r)) { + //Msg("found comments\n"); + std::smatch noncomments; + std::regex_search(m, noncomments, r); + m = noncomments[1]; + } + + auto variablesAndValues = splitStringLimit(m, "=", 1); + bool hasValue = variablesAndValues.size() > 1; + auto variables = splitStringMulti(variablesAndValues[0], ","); + for (auto v : variables) { + trim(v); + //Msg("%s\n", v.c_str()); + if (unlocalizer.find(v) != unlocalizer.end()) { + unlocalPerformed = true; + Msg("found variable %s to unlocal", v.c_str()); + s = std::regex_replace(s, pattern, "$3"); + if (!hasValue) { + + // strip comments + std::regex r = std::regex(R"((.*)(--.*))"); + if (std::regex_match(s, r)) { + //Msg("found comments\n"); + std::smatch noncomments; + std::regex_search(s, noncomments, r); + s = std::string(noncomments[1]) + "= nil " + std::string(noncomments[2]); + } + else { + s += " = nil"; + } + } + break; + } + } + } + } + + // Store result back + /*for (auto& s : tokens) { + Msg("%s", s.c_str()); + }*/ + + if (unlocalPerformed) + { + return join_list(tokens); + } + + return src; +} \ No newline at end of file diff --git a/src/xrServerEntities/script_dialect_lua.h b/src/xrServerEntities/script_dialect_lua.h index 0e56c3559e..874650a584 100644 --- a/src/xrServerEntities/script_dialect_lua.h +++ b/src/xrServerEntities/script_dialect_lua.h @@ -7,6 +7,6 @@ class CLuaDialect : public CScriptDialect private: const char* tag() const; public: - size_t wrap_ofs() const; - size_t wrap(LPSTR dest, LPCSTR src, size_t tSize) const; + std::string wrap(const std::string& src, LPCSTR caNameSpaceName) const; + std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; }; diff --git a/src/xrServerEntities/script_dialects.cpp b/src/xrServerEntities/script_dialects.cpp index 3062bbd14f..734df9aafc 100644 --- a/src/xrServerEntities/script_dialects.cpp +++ b/src/xrServerEntities/script_dialects.cpp @@ -1,24 +1,15 @@ #include "stdafx.h" -#include "script_dialect_lua.h" - -LPCSTR LUA_TAG = "--dialect lua"; - -LPCSTR LUA_WRAPPER = "setfenv(1, this)\n%s"; - -LPCSTR CLuaDialect::tag() const -{ - return LUA_TAG; -} - -size_t CLuaDialect::wrap_ofs() const -{ - return xr_strlen(LUA_WRAPPER) - 1; -} - -size_t CLuaDialect::wrap(LPSTR dest, LPCSTR src, size_t tSize) const -{ - size_t wrapper_size = wrap_ofs(); - size_t out_size = wrapper_size + tSize; - xr_sprintf(dest, out_size, LUA_WRAPPER, src); - return out_size - 1; -} +#include "script_dialects.h" + +const CScriptDialect* CScriptDialects::parse(LPCSTR src) const { + if (lua.parse(src)) { + return &lua; + } + else if (lisp_macro.parse(src)) { + return &lisp_macro; + } + else if (lisp.parse(src)) { + return &lisp; + } + return NULL; +} \ No newline at end of file diff --git a/src/xrServerEntities/script_dialects.h b/src/xrServerEntities/script_dialects.h index d594424834..589ead1646 100644 --- a/src/xrServerEntities/script_dialects.h +++ b/src/xrServerEntities/script_dialects.h @@ -3,21 +3,15 @@ #include "stdafx.h" #include "script_dialect.h" #include "script_dialect_lua.h" -#include "script_dialect_fennel.h" +#include "script_dialect_lisp.h" +#include "script_dialect_lisp_macro.h" struct CScriptDialects { CLuaDialect lua; - CFennelDialect fennel; + CLispDialect lisp; + CLispMacroDialect lisp_macro; - const CScriptDialect* parse(LPCSTR src) const { - if (lua.parse(src)) { - return &lua; - } - else if (fennel.parse(src)) { - return &fennel; - } - return NULL; - } + const CScriptDialect* parse(LPCSTR src) const; }; static CScriptDialects dialects; diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index d5e83a9913..fb8bcfb6b6 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -12,10 +12,6 @@ #include "script_thread.h" #include "../xrCore/mezz_stringbuffer.h" #include -#include -#include -#include -#include #if !defined(DEBUG) && defined(USE_LUAJIT_ONE) # include "opt.lua.h" @@ -25,24 +21,6 @@ #include "lua.hpp" #endif -LPCSTR file_header_old = "\ -local function script_name()\n\ - return \"%s\"\n\ -end\n\ -local this = {}\n\ -%s this %s\n\ -setmetatable(this, {__index = _G})\n"; - -LPCSTR file_header_new = "\ -local function script_name()\n\ - return \"%s\"\n\ -end\n\ -local this = {}\n\ -this._G = _G\n\ -%s this %s\n"; - -LPCSTR file_header = 0; - #ifndef ENGINE_BUILD # include "script_engine.h" # include "ai_space.h" @@ -383,11 +361,6 @@ void CScriptStorage::reinit() luaopen_lua_extensions(lua()); disable_os_funcs(lua()); - - if (strstr(Core.Params, "-_g")) - file_header = file_header_new; //AVO: I get fatal crash at the start if this is used - else - file_header = file_header_old; } int CScriptStorage::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker) @@ -582,118 +555,53 @@ int __cdecl CScriptStorage::script_log(ScriptStorage::ELuaMessageType tLuaMessag return (result); } -bool CScriptStorage::parse_namespace(LPCSTR caNamespaceName, LPSTR b, u32 const b_size, LPSTR c, u32 const c_size) -{ - *b = 0; - *c = 0; - LPSTR S2; - STRCONCAT(S2, caNamespaceName); - LPSTR S = S2; - for (int i = 0;; ++i) - { - if (!xr_strlen(S)) - { - script_log(ScriptStorage::eLuaMessageTypeError, "the namespace name %s is incorrect!", caNamespaceName); - return (false); - } - LPSTR S1 = strchr(S, '.'); - if (S1) - *S1 = 0; - - if (i) - xr_strcat(b, b_size, "{"); - xr_strcat(b, b_size, S); - xr_strcat(b, b_size, "="); - if (i) - xr_strcat(c, c_size, "}"); - if (S1) - S = ++S1; - else - break; - } - - return (true); -} +Unlocalizers unlocalizers; +bool unlocalizerPassed = false; -bool CScriptStorage::load_buffer(lua_State* L, LPCSTR caBuffer, size_t tSize, LPCSTR caScriptName, - LPCSTR caNameSpaceName) +bool CScriptStorage::load_buffer( + lua_State* L, + Unlocalizers* unlocalizers, + LPCSTR caBuffer, + size_t tSize, + LPCSTR caScriptName, + LPCSTR caNameSpaceName +) { const CScriptDialects& dialects = ScriptDialects(); - const CScriptDialect* script_dialect = dialects.parse(caBuffer); + const CScriptDialect* dialect = dialects.parse(caBuffer); + + std::string caString(caBuffer, caBuffer + tSize); size_t lang_tag_len = 0; - if (script_dialect) - lang_tag_len = script_dialect->tag_length(); + if (dialect) + lang_tag_len = dialect->tag_length(); else - { - script_dialect = &dialects.lua; - } + dialect = &dialects.lua; - caBuffer += lang_tag_len; - tSize -= lang_tag_len; + if (lang_tag_len > 0) + caString.erase(0, lang_tag_len); - int l_iErrorCode; - if (caNameSpaceName && xr_strcmp("_G", caNameSpaceName)) + std::string loweredNameSpaceName; + if (caNameSpaceName) { - string512 insert, a, b; - - LPCSTR header = file_header; - - if (!parse_namespace(caNameSpaceName, a, sizeof(a), b, sizeof(b))) - return (false); - - xr_sprintf(insert, header, caNameSpaceName, a, b); - u32 str_len = xr_strlen(insert); - u32 const total_size = str_len + script_dialect->wrap_ofs() + tSize; - LPSTR script = 0; - bool dynamic_allocation = false; - - __try - { - if (total_size < 768 * 1024) - script = (LPSTR)_alloca(total_size); - else - { -#ifdef DEBUG - script = (LPSTR)Memory.mem_alloc(total_size, "lua script file"); -#else //!DEBUG - script = (LPSTR)Memory.mem_alloc(total_size); -#endif //-DEBUG - dynamic_allocation = true; - } - } - __except (GetExceptionCode() == STATUS_STACK_OVERFLOW) - { - int errcode = _resetstkoflw(); - R_ASSERT2(errcode, "Could not reset the stack after \"Stack overflow\" exception!"); -#ifdef DEBUG - script = (LPSTR)Memory.mem_alloc(total_size, "lua script file (after exception)"); -#else //#ifdef DEBUG - script = (LPSTR)Memory.mem_alloc(total_size); -#endif //#ifdef DEBUG - dynamic_allocation = true; - }; - - xr_strcpy(script, total_size, insert); - - size_t out_size = script_dialect->wrap(script + str_len, caBuffer, tSize); - - l_iErrorCode = luaL_loadbuffer(L, script, out_size + str_len, caScriptName); + loweredNameSpaceName += caNameSpaceName; + toLowerCase(loweredNameSpaceName); + } - if (dynamic_allocation) - xr_free(script); + if (unlocalizers && unlocalizers->find(loweredNameSpaceName) != unlocalizers->end()) + { + Msg("found script %s in unlocalizers data", caNameSpaceName); + // Iterate lines and unlocalize variables + Unlocalizer& unlocalizer = (*unlocalizers)[loweredNameSpaceName]; + caString = dialect->unlocalize(unlocalizer, caString, caNameSpaceName); } - else + + if (caNameSpaceName && xr_strcmp("_G", caNameSpaceName)) { - // try - { - l_iErrorCode = luaL_loadbuffer(L, caBuffer, tSize, caScriptName); - } - // catch(...) { - // l_iErrorCode= LUA_ERRSYNTAX; - // } + caString = dialect->wrap(caString, caNameSpaceName); } + int l_iErrorCode = luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); if (l_iErrorCode) { //#ifdef DEBUG @@ -705,37 +613,6 @@ bool CScriptStorage::load_buffer(lua_State* L, LPCSTR caBuffer, size_t tSize, LP return (true); } -xr_unordered_map> unlocalizers; -bool unlocalizerPassed = false; - -static std::string join_list(const std::vector& items_vec, std::string delim = "\n") { - std::string ret; - for (const auto& i : items_vec) { - if (!ret.empty()) { - ret += delim; - } - ret += i; - } - return ret; -}; - -static bool unlocalRegex(std::set& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { - if (std::regex_match(s, pattern)) { - //Msg("matching local function pattern"); - std::smatch match; - std::regex_search(s, match, pattern); - std::string variable = match[group]; - if (unlocals.find(variable) != unlocals.end()) { - Msg("[unlocalRegex] found variable %s to unlocal", variable.c_str()); - s = std::regex_replace(s, pattern, replacement); - return true; - } - } else { - return false; - } - return false; -}; - bool CScriptStorage::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) { if (!unlocalizerPassed) { @@ -803,124 +680,12 @@ bool CScriptStorage::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) return (false); } - // Unlocalize variables in the script defined by unlocalizers map auto scriptContents = static_cast(l_tpFileReader->pointer()); auto scriptLength = (size_t)l_tpFileReader->length(); - bool unlocalPerformed = false; - std::string unlocalizerResult; - std::string loweredNameSpaceName = caNameSpaceName; - toLowerCase(loweredNameSpaceName); - if (unlocalizers.find(loweredNameSpaceName) != unlocalizers.end()) { - Msg("found script %s in unlocalizers data", caNameSpaceName); - - // Get contents of the script file and split by lines - std::vector tokens; - std::string temp; - while (!l_tpFileReader->eof()) - { - char c = l_tpFileReader->r_u8(); - temp += c; - } - - std::stringstream stringStream(temp); - std::string line; - tokens.clear(); - while (std::getline(stringStream, line)) { - tokens.push_back(line); - } - - // Iterate lines and unlocalize variables - auto& unlocals = unlocalizers[loweredNameSpaceName]; - - /*for (auto& u : unlocals) { - Msg("%s", u); - }*/ - - for (auto& s : tokens) { - - //Msg("%s", s.c_str()); - - trim(s, "\n\r"); - if (s.empty()) { - continue; - } - - std::regex pattern; - - //local function x(a,b,c) - pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); - if (unlocalRegex(unlocals, s, pattern, 5, "$3$4$5$6$7")) { - unlocalPerformed = true; - continue; - } - - //local a = ... - //local a - //local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) - //local x; local y; - unsupported yet - pattern = std::regex(R"((^local)([\t ]+)(.*))"); - if (std::regex_match(s, pattern)) { - std::smatch match; - std::regex_search(s, match, pattern); - std::string m = match[3]; - - // strip comments - std::regex r = std::regex(R"((.*)--.*)"); - if (std::regex_match(m, r)) { - //Msg("found comments\n"); - std::smatch noncomments; - std::regex_search(m, noncomments, r); - m = noncomments[1]; - } - - auto variablesAndValues = splitStringLimit(m, "=", 1); - bool hasValue = variablesAndValues.size() > 1; - auto variables = splitStringMulti(variablesAndValues[0], ","); - for (auto v : variables) { - trim(v); - //Msg("%s\n", v.c_str()); - if (unlocals.find(v) != unlocals.end()) { - unlocalPerformed = true; - Msg("found variable %s to unlocal", v.c_str()); - s = std::regex_replace(s, pattern, "$3"); - if (!hasValue) { - - // strip comments - std::regex r = std::regex(R"((.*)(--.*))"); - if (std::regex_match(s, r)) { - //Msg("found comments\n"); - std::smatch noncomments; - std::regex_search(s, noncomments, r); - s = std::string(noncomments[1]) + "= nil " + std::string(noncomments[2]); - } else { - s += " = nil"; - } - } - break; - } - } - } - } - - // Store result back - /*for (auto& s : tokens) { - Msg("%s", s.c_str()); - }*/ - - unlocalizerResult = join_list(tokens); - scriptContents = unlocalizerResult.c_str(); - scriptLength = strlen(scriptContents); - } - - strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); bool bufferLoaded = false; - if (unlocalPerformed) { - bufferLoaded = load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName); - } else { - l_tpFileReader->rewind(); - bufferLoaded = load_buffer(lua(), static_cast(l_tpFileReader->pointer()), (size_t)l_tpFileReader->length(), l_caLuaFileName, caNameSpaceName); - } + strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); + bufferLoaded = load_buffer(lua(), &unlocalizers, scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName); if (!bufferLoaded) { diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h index 351ade5ed5..040afeca30 100644 --- a/src/xrServerEntities/script_storage.h +++ b/src/xrServerEntities/script_storage.h @@ -10,6 +10,9 @@ #include "script_storage_space.h" #include "script_space_forward.h" +#include +#include +#include struct lua_State; class CScriptThread; @@ -38,6 +41,76 @@ class CScriptThread; #endif //-!DEBUG //-AVO +class CScriptDialect; + +typedef std::set Unlocalizer; +typedef xr_unordered_map Unlocalizers; + +/** + * Convert all std::strings to const char* using constexpr if (C++17) + */ +template +auto convert(T&& t) { + if constexpr (std::is_same>, std::string>::value) { + return std::forward(t).c_str(); + } + else { + return std::forward(t); + } +} + +/** + * printf like formatting for C++ with std::string + * Original source: https://stackoverflow.com/a/26221725/11722 + */ +template +std::string string_format_internal(const std::string& format, Args&& ... args) +{ + const auto size = snprintf(nullptr, 0, format.c_str(), std::forward(args) ...) + 1; + if (size <= 0) { throw std::runtime_error("Error during formatting."); } + std::unique_ptr buf(new char[size]); + snprintf(buf.get(), size, format.c_str(), args ...); + return std::string(buf.get(), buf.get() + size - 1); +} + +template +std::string string_format(std::string fmt, Args&& ... args) { + return string_format_internal(fmt, convert(std::forward(args))...); +} + +static bool parse_namespace(LPCSTR caNamespaceName, LPSTR b, u32 const b_size, LPSTR c, u32 const c_size) +{ + *b = 0; + *c = 0; + LPSTR S2; + STRCONCAT(S2, caNamespaceName); + LPSTR S = S2; + for (int i = 0;; ++i) + { + if (!xr_strlen(S)) + { + Msg("the namespace name %s is incorrect!", caNamespaceName); + return (false); + } + LPSTR S1 = strchr(S, '.'); + if (S1) + *S1 = 0; + + if (i) + xr_strcat(b, b_size, "{"); + xr_strcat(b, b_size, S); + xr_strcat(b, b_size, "="); + if (i) + xr_strcat(c, c_size, "}"); + if (S1) + S = ++S1; + else + break; + } + + return (true); +} + using namespace ScriptStorage; class CScriptStorage @@ -64,7 +137,6 @@ class CScriptStorage protected: static int vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker); - bool parse_namespace(LPCSTR caNamespaceName, LPSTR b, u32 const b_size, LPSTR c, u32 const c_size); bool do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName); void reinit(); @@ -82,7 +154,14 @@ class CScriptStorage IC lua_State* lua(); IC void current_thread(CScriptThread* thread); IC CScriptThread* current_thread() const; - bool load_buffer(lua_State* L, LPCSTR caBuffer, size_t tSize, LPCSTR caScriptName, LPCSTR caNameSpaceName = 0); + bool load_buffer( + lua_State* L, + xr_unordered_map>* unlocalizers, + LPCSTR caBuffer, + size_t tSize, + LPCSTR caScriptName, + LPCSTR caNameSpaceName = 0 + ); bool load_file_into_namespace(LPCSTR caScriptName, LPCSTR caNamespaceName); bool namespace_loaded(LPCSTR caName, bool remove_from_stack = true); bool object(LPCSTR caIdentifier, int type); diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp index eee8178b92..efa06b3b42 100644 --- a/src/xrServerEntities/script_thread.cpp +++ b/src/xrServerEntities/script_thread.cpp @@ -110,7 +110,7 @@ CScriptThread::CScriptThread(LPCSTR caNamespaceName, bool do_string, bool reload else xr_sprintf(S, "%s()", main_function); - if (!ai().script_engine().load_buffer(lua(), S, xr_strlen(S), "@_thread_main")) + if (!ai().script_engine().load_buffer(lua(), NULL, S, xr_strlen(S), "@_thread_main")) return; m_active = true; From 52193c8735fd6bd4df6a40403b1f31187723622c Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 18 May 2025 00:02:45 +0100 Subject: [PATCH 03/76] Generalize script dialects to console commands --- src/xrGame/console_commands.cpp | 56 +++++++++++++++++-- src/xrServerEntities/script_dialect.cpp | 35 +++++++++++- src/xrServerEntities/script_dialect.h | 8 ++- src/xrServerEntities/script_dialect_lisp.cpp | 16 +----- src/xrServerEntities/script_dialect_lisp.h | 2 +- .../script_dialect_lisp_macro.cpp | 9 +-- .../script_dialect_lisp_macro.h | 3 +- src/xrServerEntities/script_dialect_lua.cpp | 22 -------- src/xrServerEntities/script_dialect_lua.h | 1 - src/xrServerEntities/script_dialects.cpp | 47 +++++++++++++++- src/xrServerEntities/script_dialects.h | 9 ++- src/xrServerEntities/script_storage.cpp | 33 +---------- src/xrServerEntities/script_storage.h | 2 +- src/xrServerEntities/script_thread.cpp | 22 +++++--- 14 files changed, 163 insertions(+), 102 deletions(-) diff --git a/src/xrGame/console_commands.cpp b/src/xrGame/console_commands.cpp index 65c717d585..f9bb215bad 100644 --- a/src/xrGame/console_commands.cpp +++ b/src/xrGame/console_commands.cpp @@ -1713,10 +1713,10 @@ class CCC_ScriptCommand : public IConsole_Command string4096 S; shared_str m_script_name = "console command"; xr_sprintf(S, "%s\n", args); - int l_iErrorCode = luaL_loadbuffer(ai().script_engine().lua(), S, xr_strlen(S), "@console_command"); - if (!l_iErrorCode) + bool loaded = ai().script_engine().load_buffer(ai().script_engine().lua(), NULL, S, xr_strlen(S), *m_script_name); + if (loaded) { - l_iErrorCode = lua_pcall(ai().script_engine().lua(), 0, 0, 0); + int l_iErrorCode = lua_pcall(ai().script_engine().lua(), 0, 0, 0); if (l_iErrorCode) { ai().script_engine().print_output(ai().script_engine().lua(), *m_script_name, l_iErrorCode); @@ -1725,7 +1725,7 @@ class CCC_ScriptCommand : public IConsole_Command } } - ai().script_engine().print_output(ai().script_engine().lua(), *m_script_name, l_iErrorCode); + ai().script_engine().print_output(ai().script_engine().lua(), *m_script_name, 0); } } //void Execute @@ -1749,6 +1749,47 @@ class CCC_ScriptCommand : public IConsole_Command IConsole_Command::fill_tips(tips, mode); } }; + +class CCC_LuaCommand : public CCC_ScriptCommand +{ +public: + CCC_LuaCommand(LPCSTR N) : CCC_ScriptCommand(N) {} + + virtual void Execute(LPCSTR args) + { + string4096 S; + xr_sprintf(S, "--dialect lua %s", args); + CCC_ScriptCommand::Execute(S); + } +}; + +class CCC_LispCommand : public CCC_ScriptCommand +{ +public: + CCC_LispCommand(LPCSTR N) : CCC_ScriptCommand(N) {} + + virtual void Execute(LPCSTR args) + { + string4096 S; + xr_sprintf(S, ";dialect lisp %s", args); + CCC_ScriptCommand::Execute(S); + } +}; + +// Unused for now, as console commands don't have a module-compatible script name +class CCC_LispMacroCommand : public CCC_ScriptCommand +{ +public: + CCC_LispMacroCommand(LPCSTR N) : CCC_ScriptCommand(N) {} + + virtual void Execute(LPCSTR args) + { + string4096 S; + xr_sprintf(S, ";dialect lisp-macro %s", args); + CCC_ScriptCommand::Execute(S); + } +}; + class CCC_FreezeTime : public IConsole_Command { public: @@ -2521,7 +2562,9 @@ void CCC_RegisterCommands() CMD3(CCC_Mask, "g_unlimitedammo", &psActorFlags, AF_UNLIMITEDAMMO); CMD1(CCC_Script, "run_script"); CMD1(CCC_ScriptCommand, "run_string"); - CMD1(CCC_TimeFactor, "time_factor"); + CMD1(CCC_LuaCommand, "eval_lua"); + CMD1(CCC_LispCommand, "eval_lisp"); + //CMD1(CCC_LispMacroCommand, "eval_lisp_macro"); #endif // DEBUG /* AVO: changing restriction to -dbg key instead of DEBUG */ @@ -2534,6 +2577,9 @@ void CCC_RegisterCommands() CMD3(CCC_Mask, "g_unlimitedammo", &psActorFlags, AF_UNLIMITEDAMMO); CMD1(CCC_Script, "run_script"); CMD1(CCC_ScriptCommand, "run_string"); + CMD1(CCC_LuaCommand, "eval_lua"); + CMD1(CCC_LispCommand, "eval_lisp"); + //CMD1(CCC_LispMacroCommand, "eval_lisp_macro"); //CMD3(CCC_Mask, "g_no_clip", &psActorFlags, AF_NO_CLIP); CMD1(CCC_PHGravity, "ph_gravity"); CMD3(CCC_Mask, "log_missing_ini", &FS.m_Flags, FS.flPrintLTX); diff --git a/src/xrServerEntities/script_dialect.cpp b/src/xrServerEntities/script_dialect.cpp index 2d0234a1c3..6551cae87b 100644 --- a/src/xrServerEntities/script_dialect.cpp +++ b/src/xrServerEntities/script_dialect.cpp @@ -1,12 +1,43 @@ #include "stdafx.h" #include "script_dialect.h" +LPCSTR NAMESPACE_WRAPPER = R"( +local function script_name() + return "%s" +end + +local this = {} +%s this %s +setmetatable(this, {__index = _G}) +setfenv(1, this) + +%s +)"; + size_t CScriptDialect::tag_length() const { return xr_strlen(tag()); } -bool CScriptDialect::parse(LPCSTR src) const +bool CScriptDialect::parse(const std::string& src) const +{ + return strncmp(tag(), src.c_str(), tag_length()) == 0; +} + +std::string CScriptDialect::wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const +{ + string512 a, b; + if (!parse_namespace(caNameSpaceName, a, sizeof(a), b, sizeof(b))) + return src; + return string_format(NAMESPACE_WRAPPER, caNameSpaceName, a, b, src); +} + +std::string CScriptDialect::wrap_body(const std::string& src, LPCSTR caNameSpaceName) const +{ + return src; +} + +std::string CScriptDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const { - return strncmp(tag(), src, tag_length()) == 0; + return src; } diff --git a/src/xrServerEntities/script_dialect.h b/src/xrServerEntities/script_dialect.h index 868b603f60..727e0b4505 100644 --- a/src/xrServerEntities/script_dialect.h +++ b/src/xrServerEntities/script_dialect.h @@ -10,7 +10,9 @@ class CScriptDialect virtual const char* tag() const = 0; public: size_t tag_length() const; - bool parse(LPCSTR src) const; - virtual std::string wrap(const std::string& src, LPCSTR caNameSpaceName) const = 0; - virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const = 0; + bool parse(const std::string& src) const; + + virtual std::string wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string wrap_body(const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; }; diff --git a/src/xrServerEntities/script_dialect_lisp.cpp b/src/xrServerEntities/script_dialect_lisp.cpp index e2c9cda1e7..48a3e9fbf0 100644 --- a/src/xrServerEntities/script_dialect_lisp.cpp +++ b/src/xrServerEntities/script_dialect_lisp.cpp @@ -5,14 +5,6 @@ LPCSTR LISP_TAG = ";dialect lisp"; LPCSTR LISP_WRAPPER = R"( -local function script_name() - return "%s" -end - -local this = {} -%s this %s -setmetatable(this, {__index = _G}) - require("fennel").eval( [=[ %s @@ -39,13 +31,9 @@ LPCSTR CLispDialect::tag() const return LISP_TAG; } -std::string CLispDialect::wrap(const std::string& src, LPCSTR caNameSpaceName) const +std::string CLispDialect::wrap_body(const std::string& src, LPCSTR caNameSpaceName) const { - string512 a, b; - if (!parse_namespace(caNameSpaceName, a, sizeof(a), b, sizeof(b))) - return (false); - - return string_format(LISP_WRAPPER, caNameSpaceName, a, b, src); + return string_format(LISP_WRAPPER, src); } std::string CLispDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const diff --git a/src/xrServerEntities/script_dialect_lisp.h b/src/xrServerEntities/script_dialect_lisp.h index f273a8a826..c1f505169c 100644 --- a/src/xrServerEntities/script_dialect_lisp.h +++ b/src/xrServerEntities/script_dialect_lisp.h @@ -7,6 +7,6 @@ class CLispDialect : public CScriptDialect private: const char* tag() const; public: - std::string wrap(const std::string& src, LPCSTR caNameSpaceName) const; + std::string wrap_body(const std::string& src, LPCSTR caNameSpaceName) const; std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; }; diff --git a/src/xrServerEntities/script_dialect_lisp_macro.cpp b/src/xrServerEntities/script_dialect_lisp_macro.cpp index 5c7ee38e7c..aa70de7e9b 100644 --- a/src/xrServerEntities/script_dialect_lisp_macro.cpp +++ b/src/xrServerEntities/script_dialect_lisp_macro.cpp @@ -32,12 +32,7 @@ LPCSTR CLispMacroDialect::tag() const return LISP_MACRO_TAG; } -std::string CLispMacroDialect::wrap(const std::string& src, LPCSTR caNameSpaceName) const +std::string CLispMacroDialect::wrap_body(const std::string& src, LPCSTR caNameSpaceName) const { return string_format(LISP_MACRO_WRAPPER, caNameSpaceName, src); -} - -std::string CLispMacroDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const -{ - return src; -} +} \ No newline at end of file diff --git a/src/xrServerEntities/script_dialect_lisp_macro.h b/src/xrServerEntities/script_dialect_lisp_macro.h index 1e9a4fb9f4..6b162bb724 100644 --- a/src/xrServerEntities/script_dialect_lisp_macro.h +++ b/src/xrServerEntities/script_dialect_lisp_macro.h @@ -7,6 +7,5 @@ class CLispMacroDialect : public CScriptDialect private: const char* tag() const; public: - std::string wrap(const std::string& src, LPCSTR caNameSpaceName) const; - std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; + std::string wrap_body(const std::string& src, LPCSTR caNameSpaceName) const; }; diff --git a/src/xrServerEntities/script_dialect_lua.cpp b/src/xrServerEntities/script_dialect_lua.cpp index 414b095951..ea8eaf067d 100644 --- a/src/xrServerEntities/script_dialect_lua.cpp +++ b/src/xrServerEntities/script_dialect_lua.cpp @@ -7,33 +7,11 @@ LPCSTR LUA_TAG = "--dialect lua"; -LPCSTR LUA_WRAPPER = R"( -local function script_name() - return "%s" -end - -local this = {} -%s this %s -setmetatable(this, {__index = _G}) - -setfenv(1, this) -%s -)"; - LPCSTR CLuaDialect::tag() const { return LUA_TAG; } -std::string CLuaDialect::wrap(const std::string& src, LPCSTR caNameSpaceName) const -{ - string512 a, b; - if (!parse_namespace(caNameSpaceName, a, sizeof(a), b, sizeof(b))) - return (false); - - return string_format(LUA_WRAPPER, caNameSpaceName, a, b, src); -} - static bool unlocalRegex(Unlocalizer& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { if (std::regex_match(s, pattern)) { //Msg("matching local function pattern"); diff --git a/src/xrServerEntities/script_dialect_lua.h b/src/xrServerEntities/script_dialect_lua.h index 874650a584..76942a519b 100644 --- a/src/xrServerEntities/script_dialect_lua.h +++ b/src/xrServerEntities/script_dialect_lua.h @@ -7,6 +7,5 @@ class CLuaDialect : public CScriptDialect private: const char* tag() const; public: - std::string wrap(const std::string& src, LPCSTR caNameSpaceName) const; std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; }; diff --git a/src/xrServerEntities/script_dialects.cpp b/src/xrServerEntities/script_dialects.cpp index 734df9aafc..5d1f6fbaf8 100644 --- a/src/xrServerEntities/script_dialects.cpp +++ b/src/xrServerEntities/script_dialects.cpp @@ -1,7 +1,8 @@ #include "stdafx.h" #include "script_dialects.h" +#include "../xrCore/mezz_stringbuffer.h" -const CScriptDialect* CScriptDialects::parse(LPCSTR src) const { +const CScriptDialect* CScriptDialects::parse(const std::string& src) const { if (lua.parse(src)) { return &lua; } @@ -12,4 +13,46 @@ const CScriptDialect* CScriptDialects::parse(LPCSTR src) const { return &lisp; } return NULL; -} \ No newline at end of file +} + +std::string CScriptDialects::wrap_buffer( + std::string caString, + LPCSTR caScriptName, + LPCSTR caNameSpaceName, + Unlocalizers* unlocalizers +) const +{ + const CScriptDialect* dialect = parse(caString); + size_t lang_tag_len = 0; + if (dialect) + lang_tag_len = dialect->tag_length(); + else + dialect = &dialects.lua; + + if (lang_tag_len > 0) + caString.erase(0, lang_tag_len); + + std::string loweredNameSpaceName; + if (caNameSpaceName) + { + loweredNameSpaceName += caNameSpaceName; + toLowerCase(loweredNameSpaceName); + } + + if (unlocalizers && unlocalizers->find(loweredNameSpaceName) != unlocalizers->end()) + { + Msg("found script %s in unlocalizers data", caNameSpaceName); + // Iterate lines and unlocalize variables + Unlocalizer& unlocalizer = (*unlocalizers)[loweredNameSpaceName]; + caString = dialect->unlocalize(unlocalizer, caString, caNameSpaceName); + } + + caString = dialect->wrap_body(caString, caNameSpaceName); + + if (caNameSpaceName && xr_strcmp("_G", caNameSpaceName)) + { + caString = dialect->wrap_namespace(caString, caNameSpaceName); + } + + return caString; +} diff --git a/src/xrServerEntities/script_dialects.h b/src/xrServerEntities/script_dialects.h index 589ead1646..bb5414bd88 100644 --- a/src/xrServerEntities/script_dialects.h +++ b/src/xrServerEntities/script_dialects.h @@ -1,6 +1,7 @@ #pragma once #include "stdafx.h" +#include "script_storage.h" #include "script_dialect.h" #include "script_dialect_lua.h" #include "script_dialect_lisp.h" @@ -11,7 +12,13 @@ struct CScriptDialects { CLispDialect lisp; CLispMacroDialect lisp_macro; - const CScriptDialect* parse(LPCSTR src) const; + const CScriptDialect* parse(const std::string& src) const; + std::string wrap_buffer( + std::string caString, + LPCSTR caScriptName, + LPCSTR caNameSpaceName = 0, + Unlocalizers* unlocalizers = 0 + ) const; }; static CScriptDialects dialects; diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index fb8bcfb6b6..5a6f7c4f17 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -567,39 +567,8 @@ bool CScriptStorage::load_buffer( LPCSTR caNameSpaceName ) { - const CScriptDialects& dialects = ScriptDialects(); - const CScriptDialect* dialect = dialects.parse(caBuffer); - std::string caString(caBuffer, caBuffer + tSize); - - size_t lang_tag_len = 0; - if (dialect) - lang_tag_len = dialect->tag_length(); - else - dialect = &dialects.lua; - - if (lang_tag_len > 0) - caString.erase(0, lang_tag_len); - - std::string loweredNameSpaceName; - if (caNameSpaceName) - { - loweredNameSpaceName += caNameSpaceName; - toLowerCase(loweredNameSpaceName); - } - - if (unlocalizers && unlocalizers->find(loweredNameSpaceName) != unlocalizers->end()) - { - Msg("found script %s in unlocalizers data", caNameSpaceName); - // Iterate lines and unlocalize variables - Unlocalizer& unlocalizer = (*unlocalizers)[loweredNameSpaceName]; - caString = dialect->unlocalize(unlocalizer, caString, caNameSpaceName); - } - - if (caNameSpaceName && xr_strcmp("_G", caNameSpaceName)) - { - caString = dialect->wrap(caString, caNameSpaceName); - } + caString = ScriptDialects().wrap_buffer(caString, caScriptName, caNameSpaceName, unlocalizers); int l_iErrorCode = luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); if (l_iErrorCode) diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h index 040afeca30..e4ec9fea55 100644 --- a/src/xrServerEntities/script_storage.h +++ b/src/xrServerEntities/script_storage.h @@ -156,7 +156,7 @@ class CScriptStorage IC CScriptThread* current_thread() const; bool load_buffer( lua_State* L, - xr_unordered_map>* unlocalizers, + Unlocalizers* unlocalizers, LPCSTR caBuffer, size_t tSize, LPCSTR caScriptName, diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp index efa06b3b42..4777a1df5c 100644 --- a/src/xrServerEntities/script_thread.cpp +++ b/src/xrServerEntities/script_thread.cpp @@ -14,6 +14,7 @@ };*/ //-AVO #include "script_engine.h" +#include "script_dialects.h" #include "script_thread.h" #include "ai_space.h" @@ -38,24 +39,27 @@ const LPCSTR main_function = "console_command_run_string_main_thread_function"; //extern "C" __declspec(dllimport) lua_State *lua_newcthread(lua_State *OL, int cstacksize); -CScriptThread::CScriptThread(LPCSTR caNamespaceName, bool do_string, bool reload) +CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string, bool reload) { m_virtual_machine = 0; m_active = false; try { - string256 S; + std::string S; + if (!do_string) { - m_script_name = caNamespaceName; - ai().script_engine().process_file(caNamespaceName, reload); + m_script_name = caBuffer; + ai().script_engine().process_file(caBuffer, reload); } else { m_script_name = "console command"; - xr_sprintf(S, "function %s()\n%s\nend\n", main_function, caNamespaceName); - int l_iErrorCode = luaL_loadbuffer(ai().script_engine().lua(), S, xr_strlen(S), "@console_command"); + S += caBuffer; + S = ScriptDialects().wrap_buffer(S, *m_script_name); + S = "function " + std::string(main_function) + "()\n" + S + "\nend"; + int l_iErrorCode = luaL_loadbuffer(ai().script_engine().lua(), S.c_str(), S.length(), "@console_command"); if (!l_iErrorCode) { l_iErrorCode = lua_pcall(ai().script_engine().lua(), 0, 0, 0); @@ -106,11 +110,11 @@ CScriptThread::CScriptThread(LPCSTR caNamespaceName, bool do_string, bool reload #endif // #ifndef USE_LUA_STUDIO if (!do_string) - xr_sprintf(S, "%s.main()", caNamespaceName); + S = std::string(caBuffer) + ".main()"; else - xr_sprintf(S, "%s()", main_function); + S = std::string(main_function) + "()"; - if (!ai().script_engine().load_buffer(lua(), NULL, S, xr_strlen(S), "@_thread_main")) + if (!ai().script_engine().load_buffer(lua(), NULL, S.c_str(), S.length(), "@_thread_main")) return; m_active = true; From f68ec6baffb1f7b90c139b8f2aa7aec4648628c1 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 18 May 2025 03:55:26 +0100 Subject: [PATCH 04/76] Refactor `parse_namespace` - Now lives in the `CScriptDialect` header - Rewritten using `std::string` - Fixed old broken `.` separator behaviour - Now creates tables if they don't exist, and updates otherwise - Allows `foo.bar.script` and `foo.baz.script` to coexist independently --- src/xrServerEntities/script_dialect.cpp | 12 ++++--- src/xrServerEntities/script_dialect.h | 21 +++++++++++++ src/xrServerEntities/script_dialect_lisp.cpp | 22 +++++++++++++ src/xrServerEntities/script_dialect_lisp.h | 5 +-- src/xrServerEntities/script_storage.h | 33 -------------------- 5 files changed, 53 insertions(+), 40 deletions(-) diff --git a/src/xrServerEntities/script_dialect.cpp b/src/xrServerEntities/script_dialect.cpp index 6551cae87b..b3a3cb4845 100644 --- a/src/xrServerEntities/script_dialect.cpp +++ b/src/xrServerEntities/script_dialect.cpp @@ -7,7 +7,7 @@ local function script_name() end local this = {} -%s this %s +%s this setmetatable(this, {__index = _G}) setfenv(1, this) @@ -26,10 +26,12 @@ bool CScriptDialect::parse(const std::string& src) const std::string CScriptDialect::wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const { - string512 a, b; - if (!parse_namespace(caNameSpaceName, a, sizeof(a), b, sizeof(b))) - return src; - return string_format(NAMESPACE_WRAPPER, caNameSpaceName, a, b, src); + return string_format( + NAMESPACE_WRAPPER, + caNameSpaceName, + parse_namespace(caNameSpaceName), + src + ); } std::string CScriptDialect::wrap_body(const std::string& src, LPCSTR caNameSpaceName) const diff --git a/src/xrServerEntities/script_dialect.h b/src/xrServerEntities/script_dialect.h index 727e0b4505..6ec3608de8 100644 --- a/src/xrServerEntities/script_dialect.h +++ b/src/xrServerEntities/script_dialect.h @@ -4,6 +4,27 @@ #include "script_space_forward.h" #include "script_storage.h" +static std::string parse_namespace(std::string src) +{ + std::string lsrc; + std::string dest; + while (true) + { + int sep = src.find("."); + if (sep > -1) + { + std::string cur = src.substr(0, sep); + dest += lsrc + cur + " = " + lsrc + cur + " or {}\n"; + lsrc += cur + "."; + src.erase(0, sep + 1); + continue; + } + + dest += lsrc + src + " = "; + return dest; + } +} + class CScriptDialect { private: diff --git a/src/xrServerEntities/script_dialect_lisp.cpp b/src/xrServerEntities/script_dialect_lisp.cpp index 48a3e9fbf0..53bf078126 100644 --- a/src/xrServerEntities/script_dialect_lisp.cpp +++ b/src/xrServerEntities/script_dialect_lisp.cpp @@ -26,11 +26,33 @@ LPCSTR LISP_UNLOCALIZE_WRAPPER = R"( %s) )"; +LPCSTR LISP_NAMESPACE_WRAPPER = R"( +local function script_name() + return "%s" +end + +local this = {} +%s this +setmetatable(this, {__index = _G}) + +%s +)"; + LPCSTR CLispDialect::tag() const { return LISP_TAG; } +std::string CLispDialect::wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const +{ + return string_format( + LISP_NAMESPACE_WRAPPER, + caNameSpaceName, + parse_namespace(caNameSpaceName), + src + ); +} + std::string CLispDialect::wrap_body(const std::string& src, LPCSTR caNameSpaceName) const { return string_format(LISP_WRAPPER, src); diff --git a/src/xrServerEntities/script_dialect_lisp.h b/src/xrServerEntities/script_dialect_lisp.h index c1f505169c..8a6e940a6a 100644 --- a/src/xrServerEntities/script_dialect_lisp.h +++ b/src/xrServerEntities/script_dialect_lisp.h @@ -7,6 +7,7 @@ class CLispDialect : public CScriptDialect private: const char* tag() const; public: - std::string wrap_body(const std::string& src, LPCSTR caNameSpaceName) const; - std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string wrap_body(const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; }; diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h index e4ec9fea55..df2afac4de 100644 --- a/src/xrServerEntities/script_storage.h +++ b/src/xrServerEntities/script_storage.h @@ -78,39 +78,6 @@ std::string string_format(std::string fmt, Args&& ... args) { return string_format_internal(fmt, convert(std::forward(args))...); } -static bool parse_namespace(LPCSTR caNamespaceName, LPSTR b, u32 const b_size, LPSTR c, u32 const c_size) -{ - *b = 0; - *c = 0; - LPSTR S2; - STRCONCAT(S2, caNamespaceName); - LPSTR S = S2; - for (int i = 0;; ++i) - { - if (!xr_strlen(S)) - { - Msg("the namespace name %s is incorrect!", caNamespaceName); - return (false); - } - LPSTR S1 = strchr(S, '.'); - if (S1) - *S1 = 0; - - if (i) - xr_strcat(b, b_size, "{"); - xr_strcat(b, b_size, S); - xr_strcat(b, b_size, "="); - if (i) - xr_strcat(c, c_size, "}"); - if (S1) - S = ++S1; - else - break; - } - - return (true); -} - using namespace ScriptStorage; class CScriptStorage From 2a15c75dbf8842d54680981f85d3038ef5486b3f Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 18 May 2025 06:55:35 +0100 Subject: [PATCH 05/76] Use return semantics instead of public bindings for lisp --- src/xrServerEntities/script_dialect_lisp.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/xrServerEntities/script_dialect_lisp.cpp b/src/xrServerEntities/script_dialect_lisp.cpp index 53bf078126..622b2bdb63 100644 --- a/src/xrServerEntities/script_dialect_lisp.cpp +++ b/src/xrServerEntities/script_dialect_lisp.cpp @@ -12,7 +12,6 @@ require("fennel").eval( { allowedGlobals = false, correlate = true, - env = this, useBitLib = true, ["error-pinpoint"] = false, } @@ -31,11 +30,7 @@ local function script_name() return "%s" end -local this = {} -%s this -setmetatable(this, {__index = _G}) - -%s +%s %s )"; LPCSTR CLispDialect::tag() const From 1941b72782b7aa944f273d484bf503f1c1ea251e Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 18 May 2025 18:59:48 +0100 Subject: [PATCH 06/76] Move dialect string manipulation machinery into `lua_macros.h` --- src/xrGame/vs2022/xrGame.vcxproj | 2 + src/xrGame/vs2022/xrGame.vcxproj.filters | 6 + src/xrServerEntities/lua_macros.cpp | 4 + src/xrServerEntities/lua_macros.h | 103 ++++++++++++++++++ src/xrServerEntities/script_dialect.cpp | 38 ++++--- src/xrServerEntities/script_dialect.h | 26 +---- src/xrServerEntities/script_dialect_lisp.cpp | 17 +-- .../script_dialect_lisp_macro.cpp | 34 +++--- src/xrServerEntities/script_storage.h | 38 +------ 9 files changed, 163 insertions(+), 105 deletions(-) create mode 100644 src/xrServerEntities/lua_macros.cpp create mode 100644 src/xrServerEntities/lua_macros.h diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index af64fbcc7d..e405e89223 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -307,6 +307,7 @@ + @@ -1941,6 +1942,7 @@ + pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index cf99197887..14d72fd1af 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -7422,6 +7422,9 @@ AI\AScript\ScriptDialect + + AI\AScript\ScriptDialect + @@ -11135,6 +11138,9 @@ AI\AScript\ScriptDialect + + AI\AScript\ScriptStorage + diff --git a/src/xrServerEntities/lua_macros.cpp b/src/xrServerEntities/lua_macros.cpp new file mode 100644 index 0000000000..9dc5ecf971 --- /dev/null +++ b/src/xrServerEntities/lua_macros.cpp @@ -0,0 +1,4 @@ +#pragma once + +#include "stdafx.h" +#include "lua_macros.h" diff --git a/src/xrServerEntities/lua_macros.h b/src/xrServerEntities/lua_macros.h new file mode 100644 index 0000000000..deeb39e2d9 --- /dev/null +++ b/src/xrServerEntities/lua_macros.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include + +/** + * Convert all std::strings to const char* using constexpr if (C++17) + */ +template +static auto convert(T&& t) { + if constexpr (std::is_same>, std::string>::value) { + return std::forward(t).c_str(); + } + else { + return std::forward(t); + } +} + +/** + * printf like formatting for C++ with std::string + * Original source: https://stackoverflow.com/a/26221725/11722 + */ +template +static std::string string_format_internal(const std::string& format, Args&& ... args) +{ + const auto size = snprintf(nullptr, 0, format.c_str(), std::forward(args) ...) + 1; + if (size <= 0) { throw std::runtime_error("Error during formatting."); } + std::unique_ptr buf(new char[size]); + snprintf(buf.get(), size, format.c_str(), args ...); + return std::string(buf.get(), buf.get() + size - 1); +} + +template +static std::string string_format(std::string fmt, Args&& ... args) { + return string_format_internal(fmt, convert(std::forward(args))...); +} + +template< typename ... Args > +std::string lines(Args const& ... args) +{ + std::ostringstream stream; + using List = int[]; + (void)List { + 0, ((void)(stream << "\n" << args), 0) ... + }; + + return stream.str(); +} + +static std::string assign_local(const std::string& key, const std::string& value) +{ + return string_format("local %s = %s", key, value); +} + +static std::string int_literal(int i) +{ + return std::to_string(i); +} + +static std::string scope_to(const std::string& sThis) +{ + return string_format("setfenv(%s, %s)", int_literal(1), sThis); +} + +static std::string script_name_getter(const std::string& name) +{ + return string_format( + R"( +local function script_name() + return "%s" +end + )", + name + ); +} + +// Given a namespace name with optional . delimiters, +// convert it into a series of assignments in the form: +// A = A or {} +// A.B = A.B or {} +// A.B.C = val +static std::string assign_path(std::string prefix, std::string namespaceName, std::string val) +{ + if (prefix.length() > 0) + prefix += "."; + + std::string dest; + while (true) + { + int sep = namespaceName.find("."); + if (sep > -1) + { + std::string cur = namespaceName.substr(0, sep); + dest += prefix + cur + " = " + prefix + cur + " or {}\n"; + prefix += cur + "."; + namespaceName.erase(0, sep + 1); + continue; + } + + dest += prefix + namespaceName + " = " + val; + return dest; + } +} diff --git a/src/xrServerEntities/script_dialect.cpp b/src/xrServerEntities/script_dialect.cpp index b3a3cb4845..3ec7d7be0c 100644 --- a/src/xrServerEntities/script_dialect.cpp +++ b/src/xrServerEntities/script_dialect.cpp @@ -1,18 +1,6 @@ #include "stdafx.h" #include "script_dialect.h" - -LPCSTR NAMESPACE_WRAPPER = R"( -local function script_name() - return "%s" -end - -local this = {} -%s this -setmetatable(this, {__index = _G}) -setfenv(1, this) - -%s -)"; +#include "lua_macros.h" size_t CScriptDialect::tag_length() const { @@ -26,10 +14,26 @@ bool CScriptDialect::parse(const std::string& src) const std::string CScriptDialect::wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const { - return string_format( - NAMESPACE_WRAPPER, - caNameSpaceName, - parse_namespace(caNameSpaceName), + return lines( + script_name_getter(caNameSpaceName), + assign_local("this", "{}"), + string_format( + R"( +setmetatable( + this, + { + __index = function(_, key) + local gv = _G[key] + if gv ~= nil then + return gv + end + end + } +) + )" + ), + assign_path("_G", caNameSpaceName, "this"), + scope_to("this"), src ); } diff --git a/src/xrServerEntities/script_dialect.h b/src/xrServerEntities/script_dialect.h index 6ec3608de8..2c7f8de367 100644 --- a/src/xrServerEntities/script_dialect.h +++ b/src/xrServerEntities/script_dialect.h @@ -1,29 +1,9 @@ #pragma once -#include "script_storage_space.h" -#include "script_space_forward.h" -#include "script_storage.h" +#include -static std::string parse_namespace(std::string src) -{ - std::string lsrc; - std::string dest; - while (true) - { - int sep = src.find("."); - if (sep > -1) - { - std::string cur = src.substr(0, sep); - dest += lsrc + cur + " = " + lsrc + cur + " or {}\n"; - lsrc += cur + "."; - src.erase(0, sep + 1); - continue; - } - - dest += lsrc + src + " = "; - return dest; - } -} +typedef std::set Unlocalizer; +typedef xr_unordered_map Unlocalizers; class CScriptDialect { diff --git a/src/xrServerEntities/script_dialect_lisp.cpp b/src/xrServerEntities/script_dialect_lisp.cpp index 622b2bdb63..4c0f78e3ef 100644 --- a/src/xrServerEntities/script_dialect_lisp.cpp +++ b/src/xrServerEntities/script_dialect_lisp.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "script_dialect_lisp.h" +#include "lua_macros.h" #include LPCSTR LISP_TAG = ";dialect lisp"; @@ -25,14 +26,6 @@ LPCSTR LISP_UNLOCALIZE_WRAPPER = R"( %s) )"; -LPCSTR LISP_NAMESPACE_WRAPPER = R"( -local function script_name() - return "%s" -end - -%s %s -)"; - LPCSTR CLispDialect::tag() const { return LISP_TAG; @@ -40,11 +33,9 @@ LPCSTR CLispDialect::tag() const std::string CLispDialect::wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const { - return string_format( - LISP_NAMESPACE_WRAPPER, - caNameSpaceName, - parse_namespace(caNameSpaceName), - src + return lines( + script_name_getter(caNameSpaceName), + assign_path("_G", caNameSpaceName, src) ); } diff --git a/src/xrServerEntities/script_dialect_lisp_macro.cpp b/src/xrServerEntities/script_dialect_lisp_macro.cpp index aa70de7e9b..67f8f2a41f 100644 --- a/src/xrServerEntities/script_dialect_lisp_macro.cpp +++ b/src/xrServerEntities/script_dialect_lisp_macro.cpp @@ -1,18 +1,29 @@ #include "stdafx.h" #include "script_dialect_lisp_macro.h" +#include "lua_macros.h" LPCSTR LISP_MACRO_TAG = ";dialect lisp-macro"; -LPCSTR LISP_MACRO_WRAPPER = R"( +LPCSTR CLispMacroDialect::tag() const +{ + return LISP_MACRO_TAG; +} + +std::string CLispMacroDialect::wrap_body(const std::string& src, LPCSTR caNameSpaceName) const +{ + return string_format( + R"( local fennel = require("fennel") table.insert( fennel["macro-searchers"], function(module_name) - if module_name ~= "%s" then return end + if module_name ~= "%s" then + return + end return function() return fennel.eval( [=[ -%s + %s ]=], { correlate = true, @@ -21,18 +32,11 @@ table.insert( ["error-pinpoint"] = false, } ) - end, - module_name + end end ) -)"; - -LPCSTR CLispMacroDialect::tag() const -{ - return LISP_MACRO_TAG; -} - -std::string CLispMacroDialect::wrap_body(const std::string& src, LPCSTR caNameSpaceName) const -{ - return string_format(LISP_MACRO_WRAPPER, caNameSpaceName, src); + )", + caNameSpaceName, + src + ); } \ No newline at end of file diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h index df2afac4de..3c041b9fa9 100644 --- a/src/xrServerEntities/script_storage.h +++ b/src/xrServerEntities/script_storage.h @@ -10,6 +10,7 @@ #include "script_storage_space.h" #include "script_space_forward.h" +#include "script_dialect.h" #include #include #include @@ -41,43 +42,6 @@ class CScriptThread; #endif //-!DEBUG //-AVO -class CScriptDialect; - -typedef std::set Unlocalizer; -typedef xr_unordered_map Unlocalizers; - -/** - * Convert all std::strings to const char* using constexpr if (C++17) - */ -template -auto convert(T&& t) { - if constexpr (std::is_same>, std::string>::value) { - return std::forward(t).c_str(); - } - else { - return std::forward(t); - } -} - -/** - * printf like formatting for C++ with std::string - * Original source: https://stackoverflow.com/a/26221725/11722 - */ -template -std::string string_format_internal(const std::string& format, Args&& ... args) -{ - const auto size = snprintf(nullptr, 0, format.c_str(), std::forward(args) ...) + 1; - if (size <= 0) { throw std::runtime_error("Error during formatting."); } - std::unique_ptr buf(new char[size]); - snprintf(buf.get(), size, format.c_str(), args ...); - return std::string(buf.get(), buf.get() + size - 1); -} - -template -std::string string_format(std::string fmt, Args&& ... args) { - return string_format_internal(fmt, convert(std::forward(args))...); -} - using namespace ScriptStorage; class CScriptStorage From 6acf97a040d17599dd9c6a870ad458524359a22b Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Mon, 19 May 2025 17:41:40 +0100 Subject: [PATCH 07/76] Script namespace sanitization pass - Scripts now load into package.loaded instead of _G - `require` is now the first-class autoload mechanism - Renamed existing `lua` dialect to `wua` - Recaptured vanilla semantics via `wua` metaprogramming - Reimplemented `lua` dialect as idiomatic clean-namespace Lua - Refactor lisp dialects around clean namespaces --- src/xrGame/console_commands.cpp | 15 ++ src/xrGame/vs2022/xrGame.vcxproj | 9 +- src/xrGame/vs2022/xrGame.vcxproj.filters | 17 +- src/xrServerEntities/lua_macros.cpp | 4 - src/xrServerEntities/lua_macros.h | 58 +++--- src/xrServerEntities/script_dialect.cpp | 38 +--- src/xrServerEntities/script_dialect.h | 9 +- src/xrServerEntities/script_dialect_lisp.cpp | 75 ++++---- src/xrServerEntities/script_dialect_lisp.h | 8 +- .../script_dialect_lisp_macro.cpp | 12 +- .../script_dialect_lisp_macro.h | 5 +- src/xrServerEntities/script_dialect_lua.cpp | 159 +++-------------- src/xrServerEntities/script_dialect_lua.h | 5 +- src/xrServerEntities/script_dialect_wua.cpp | 40 +++++ src/xrServerEntities/script_dialect_wua.h | 10 ++ src/xrServerEntities/script_dialect_wua_g.cpp | 167 ++++++++++++++++++ src/xrServerEntities/script_dialect_wua_g.h | 11 ++ src/xrServerEntities/script_dialects.cpp | 62 +++---- src/xrServerEntities/script_dialects.h | 10 +- src/xrServerEntities/script_engine.cpp | 54 ++++-- src/xrServerEntities/script_engine.h | 2 +- src/xrServerEntities/script_storage.cpp | 9 +- src/xrServerEntities/script_thread.cpp | 2 +- 23 files changed, 439 insertions(+), 342 deletions(-) delete mode 100644 src/xrServerEntities/lua_macros.cpp create mode 100644 src/xrServerEntities/script_dialect_wua.cpp create mode 100644 src/xrServerEntities/script_dialect_wua.h create mode 100644 src/xrServerEntities/script_dialect_wua_g.cpp create mode 100644 src/xrServerEntities/script_dialect_wua_g.h diff --git a/src/xrGame/console_commands.cpp b/src/xrGame/console_commands.cpp index f9bb215bad..82945979a3 100644 --- a/src/xrGame/console_commands.cpp +++ b/src/xrGame/console_commands.cpp @@ -1750,6 +1750,19 @@ class CCC_ScriptCommand : public IConsole_Command } }; +class CCC_WuaCommand : public CCC_ScriptCommand +{ +public: + CCC_WuaCommand(LPCSTR N) : CCC_ScriptCommand(N) {} + + virtual void Execute(LPCSTR args) + { + string4096 S; + xr_sprintf(S, "--dialect wua %s", args); + CCC_ScriptCommand::Execute(S); + } +}; + class CCC_LuaCommand : public CCC_ScriptCommand { public: @@ -2562,6 +2575,7 @@ void CCC_RegisterCommands() CMD3(CCC_Mask, "g_unlimitedammo", &psActorFlags, AF_UNLIMITEDAMMO); CMD1(CCC_Script, "run_script"); CMD1(CCC_ScriptCommand, "run_string"); + CMD1(CCC_WuaCommand, "eval_wua"); CMD1(CCC_LuaCommand, "eval_lua"); CMD1(CCC_LispCommand, "eval_lisp"); //CMD1(CCC_LispMacroCommand, "eval_lisp_macro"); @@ -2577,6 +2591,7 @@ void CCC_RegisterCommands() CMD3(CCC_Mask, "g_unlimitedammo", &psActorFlags, AF_UNLIMITEDAMMO); CMD1(CCC_Script, "run_script"); CMD1(CCC_ScriptCommand, "run_string"); + CMD1(CCC_WuaCommand, "eval_wua"); CMD1(CCC_LuaCommand, "eval_lua"); CMD1(CCC_LispCommand, "eval_lisp"); //CMD1(CCC_LispMacroCommand, "eval_lisp_macro"); diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index e405e89223..da8392266b 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -340,6 +340,8 @@ + + @@ -354,7 +356,7 @@ - + @@ -1942,7 +1944,6 @@ - pch_script.h $(IntDir)$(ProjectName)_script.pch @@ -1971,6 +1972,8 @@ + + pch_script.h $(IntDir)$(ProjectName)_script.pch @@ -2006,7 +2009,7 @@ - + pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index 14d72fd1af..70e4271bf9 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -7413,7 +7413,7 @@ AI\AScript\ScriptDialect - + AI\AScript\ScriptDialect @@ -7425,6 +7425,12 @@ AI\AScript\ScriptDialect + + AI\AScript\ScriptDialect + + + AI\AScript\ScriptDialect + @@ -11129,7 +11135,7 @@ AI\AScript\ScriptDialect - + AI\AScript\ScriptDialect @@ -11138,8 +11144,11 @@ AI\AScript\ScriptDialect - - AI\AScript\ScriptStorage + + AI\AScript\ScriptDialect + + + AI\AScript\ScriptDialect diff --git a/src/xrServerEntities/lua_macros.cpp b/src/xrServerEntities/lua_macros.cpp deleted file mode 100644 index 9dc5ecf971..0000000000 --- a/src/xrServerEntities/lua_macros.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "stdafx.h" -#include "lua_macros.h" diff --git a/src/xrServerEntities/lua_macros.h b/src/xrServerEntities/lua_macros.h index deeb39e2d9..0e359e1097 100644 --- a/src/xrServerEntities/lua_macros.h +++ b/src/xrServerEntities/lua_macros.h @@ -62,42 +62,30 @@ static std::string scope_to(const std::string& sThis) return string_format("setfenv(%s, %s)", int_literal(1), sThis); } -static std::string script_name_getter(const std::string& name) +static std::string wua_environment(const std::string& key) { return string_format( R"( -local function script_name() - return "%s" -end - )", - name - ); -} - -// Given a namespace name with optional . delimiters, -// convert it into a series of assignments in the form: -// A = A or {} -// A.B = A.B or {} -// A.B.C = val -static std::string assign_path(std::string prefix, std::string namespaceName, std::string val) -{ - if (prefix.length() > 0) - prefix += "."; + local %s = setmetatable( + {}, + { + __index = function(self, key) + local gv = _G[key] + if gv ~= nil then + return gv + end - std::string dest; - while (true) - { - int sep = namespaceName.find("."); - if (sep > -1) - { - std::string cur = namespaceName.substr(0, sep); - dest += prefix + cur + " = " + prefix + cur + " or {}\n"; - prefix += cur + "."; - namespaceName.erase(0, sep + 1); - continue; - } - - dest += prefix + namespaceName + " = " + val; - return dest; - } -} + local res, out = pcall(require, key) + if res then + return out + end + end, + __newindex = function(self, key, value) + _G[key] = value + end + } + ) + )", + key + ); +} \ No newline at end of file diff --git a/src/xrServerEntities/script_dialect.cpp b/src/xrServerEntities/script_dialect.cpp index 3ec7d7be0c..d5d7aac2cb 100644 --- a/src/xrServerEntities/script_dialect.cpp +++ b/src/xrServerEntities/script_dialect.cpp @@ -2,43 +2,7 @@ #include "script_dialect.h" #include "lua_macros.h" -size_t CScriptDialect::tag_length() const -{ - return xr_strlen(tag()); -} - -bool CScriptDialect::parse(const std::string& src) const -{ - return strncmp(tag(), src.c_str(), tag_length()) == 0; -} - -std::string CScriptDialect::wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const -{ - return lines( - script_name_getter(caNameSpaceName), - assign_local("this", "{}"), - string_format( - R"( -setmetatable( - this, - { - __index = function(_, key) - local gv = _G[key] - if gv ~= nil then - return gv - end - end - } -) - )" - ), - assign_path("_G", caNameSpaceName, "this"), - scope_to("this"), - src - ); -} - -std::string CScriptDialect::wrap_body(const std::string& src, LPCSTR caNameSpaceName) const +std::string CScriptDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const { return src; } diff --git a/src/xrServerEntities/script_dialect.h b/src/xrServerEntities/script_dialect.h index 2c7f8de367..f673eb5098 100644 --- a/src/xrServerEntities/script_dialect.h +++ b/src/xrServerEntities/script_dialect.h @@ -7,13 +7,8 @@ typedef xr_unordered_map Unlocalizers; class CScriptDialect { -private: - virtual const char* tag() const = 0; public: - size_t tag_length() const; - bool parse(const std::string& src) const; - - virtual std::string wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const; - virtual std::string wrap_body(const std::string& src, LPCSTR caNameSpaceName) const; + virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const = 0; virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const; }; diff --git a/src/xrServerEntities/script_dialect_lisp.cpp b/src/xrServerEntities/script_dialect_lisp.cpp index 4c0f78e3ef..236285e2ae 100644 --- a/src/xrServerEntities/script_dialect_lisp.cpp +++ b/src/xrServerEntities/script_dialect_lisp.cpp @@ -3,45 +3,11 @@ #include "lua_macros.h" #include -LPCSTR LISP_TAG = ";dialect lisp"; +const std::string TAG_LISP = ";dialect lisp"; -LPCSTR LISP_WRAPPER = R"( -require("fennel").eval( - [=[ -%s - ]=], - { - allowedGlobals = false, - correlate = true, - useBitLib = true, - ["error-pinpoint"] = false, - } -) -)"; - -LPCSTR LISP_UNLOCALIZE_WRAPPER = R"( -(import-macros {: unlocalize} :lisp_unlocalize) -(unlocalize - [%s] - %s) -)"; - -LPCSTR CLispDialect::tag() const -{ - return LISP_TAG; -} - -std::string CLispDialect::wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const -{ - return lines( - script_name_getter(caNameSpaceName), - assign_path("_G", caNameSpaceName, src) - ); -} - -std::string CLispDialect::wrap_body(const std::string& src, LPCSTR caNameSpaceName) const +bool CLispDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const { - return string_format(LISP_WRAPPER, src); + return src.compare(0, TAG_LISP.length(), TAG_LISP) == 0; } std::string CLispDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const @@ -53,5 +19,38 @@ std::string CLispDialect::unlocalize(Unlocalizer& unlocalizer, const std::string unlocs += " "; unlocs += unloc; } - return string_format(LISP_UNLOCALIZE_WRAPPER, unlocs, src); + return string_format( + R"( +(import-macros {: unlocalize} :lisp_unlocalize) +(unlocalize + [%s] + %s) + )", + unlocs, + src + ); +} + +std::string CLispDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const +{ + return string_format( + R"( +package.loaded["%s"] = require("fennel").eval( + [=[ +(fn script_name [] + "%s") +%s + ]=], + { + allowedGlobals = false, + correlate = true, + useBitLib = true, + ["error-pinpoint"] = false, + } +) + )", + caNameSpaceName, + caNameSpaceName, + src + ); } diff --git a/src/xrServerEntities/script_dialect_lisp.h b/src/xrServerEntities/script_dialect_lisp.h index 8a6e940a6a..337634c2bd 100644 --- a/src/xrServerEntities/script_dialect_lisp.h +++ b/src/xrServerEntities/script_dialect_lisp.h @@ -4,10 +4,8 @@ class CLispDialect : public CScriptDialect { -private: - const char* tag() const; public: - virtual std::string wrap_namespace(const std::string& src, LPCSTR caNameSpaceName) const; - virtual std::string wrap_body(const std::string& src, LPCSTR caNameSpaceName) const; - virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; + virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const override; + virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; }; diff --git a/src/xrServerEntities/script_dialect_lisp_macro.cpp b/src/xrServerEntities/script_dialect_lisp_macro.cpp index 67f8f2a41f..0cda54cd7d 100644 --- a/src/xrServerEntities/script_dialect_lisp_macro.cpp +++ b/src/xrServerEntities/script_dialect_lisp_macro.cpp @@ -2,14 +2,14 @@ #include "script_dialect_lisp_macro.h" #include "lua_macros.h" -LPCSTR LISP_MACRO_TAG = ";dialect lisp-macro"; +const std::string TAG_LISP_MACRO = ";dialect lisp macro"; -LPCSTR CLispMacroDialect::tag() const +bool CLispMacroDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const { - return LISP_MACRO_TAG; + return src.compare(0, TAG_LISP_MACRO.length(), TAG_LISP_MACRO) == 0; } -std::string CLispMacroDialect::wrap_body(const std::string& src, LPCSTR caNameSpaceName) const +std::string CLispMacroDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const { return string_format( R"( @@ -35,8 +35,10 @@ table.insert( end end ) +package.loaded["%s"] = {} )", caNameSpaceName, - src + src, + caNameSpaceName ); } \ No newline at end of file diff --git a/src/xrServerEntities/script_dialect_lisp_macro.h b/src/xrServerEntities/script_dialect_lisp_macro.h index 6b162bb724..ef95937b88 100644 --- a/src/xrServerEntities/script_dialect_lisp_macro.h +++ b/src/xrServerEntities/script_dialect_lisp_macro.h @@ -4,8 +4,7 @@ class CLispMacroDialect : public CScriptDialect { -private: - const char* tag() const; public: - std::string wrap_body(const std::string& src, LPCSTR caNameSpaceName) const; + virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; }; diff --git a/src/xrServerEntities/script_dialect_lua.cpp b/src/xrServerEntities/script_dialect_lua.cpp index ea8eaf067d..3c4acb9a2e 100644 --- a/src/xrServerEntities/script_dialect_lua.cpp +++ b/src/xrServerEntities/script_dialect_lua.cpp @@ -1,147 +1,36 @@ #include "stdafx.h" #include "script_dialect_lua.h" +#include "lua_macros.h" #include #include #include "../xrCore/mezz_stringbuffer.h" -LPCSTR LUA_TAG = "--dialect lua"; +const std::string TAG_LUA = "--dialect lua"; -LPCSTR CLuaDialect::tag() const +bool CLuaDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const { - return LUA_TAG; + return src.compare(0, TAG_LUA.length(), TAG_LUA) == 0; } -static bool unlocalRegex(Unlocalizer& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { - if (std::regex_match(s, pattern)) { - //Msg("matching local function pattern"); - std::smatch match; - std::regex_search(s, match, pattern); - std::string variable = match[group]; - if (unlocals.find(variable) != unlocals.end()) { - Msg("[unlocalRegex] found variable %s to unlocal", variable.c_str()); - s = std::regex_replace(s, pattern, replacement); - return true; - } - } - else { - return false; - } - return false; -}; - -static std::string join_list(const std::vector& items_vec, std::string delim = "\n") { - std::string ret; - for (const auto& i : items_vec) { - if (!ret.empty()) { - ret += delim; - } - ret += i; - } - return ret; -}; - -std::string CLuaDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const +std::string CLuaDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const { - bool unlocalPerformed = false; - std::string unlocalizerResult; - - // Get contents of the script file and split by lines - std::vector tokens; - std::string temp; - temp += src; - - std::stringstream stringStream(temp); - std::string line; - tokens.clear(); - while (std::getline(stringStream, line)) { - tokens.push_back(line); - } - - /*for (auto& u : unlocalizer) { - Msg("Unlocalizer: %s", u); - }*/ - - for (std::string& s : tokens) { - - //Msg("Line: %s", s.c_str()); - - trim(s, "\n\r"); - if (s.empty()) { - //Msg("Empty, continuing"); - continue; - } - - std::regex pattern; - - //local function x(a,b,c) - pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); - if (unlocalRegex(unlocalizer, s, pattern, 5, "$3$4$5$6$7")) { - //Msg("Regex matched"); - unlocalPerformed = true; - continue; - } - - //Msg("Regex not matched"); - - //local a = ... - //local a - //local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) - //local x; local y; - unsupported yet - pattern = std::regex(R"((^local)([\t ]+)(.*))"); - if (std::regex_match(s, pattern)) { - std::smatch match; - std::regex_search(s, match, pattern); - std::string m = match[3]; - - // strip comments - std::regex r = std::regex(R"((.*)--.*)"); - if (std::regex_match(m, r)) { - //Msg("found comments\n"); - std::smatch noncomments; - std::regex_search(m, noncomments, r); - m = noncomments[1]; - } - - auto variablesAndValues = splitStringLimit(m, "=", 1); - bool hasValue = variablesAndValues.size() > 1; - auto variables = splitStringMulti(variablesAndValues[0], ","); - for (auto v : variables) { - trim(v); - //Msg("%s\n", v.c_str()); - if (unlocalizer.find(v) != unlocalizer.end()) { - unlocalPerformed = true; - Msg("found variable %s to unlocal", v.c_str()); - s = std::regex_replace(s, pattern, "$3"); - if (!hasValue) { - - // strip comments - std::regex r = std::regex(R"((.*)(--.*))"); - if (std::regex_match(s, r)) { - //Msg("found comments\n"); - std::smatch noncomments; - std::regex_search(s, noncomments, r); - s = std::string(noncomments[1]) + "= nil " + std::string(noncomments[2]); - } - else { - s += " = nil"; - } - } - break; - } - } - } - } - - // Store result back - /*for (auto& s : tokens) { - Msg("%s", s.c_str()); - }*/ - - if (unlocalPerformed) - { - return join_list(tokens); - } - - return src; -} \ No newline at end of file + return lines( + string_format( + R"( +local function f() + local function script_name() + return "%s" + end + + %s +end + +package.loaded["%s"] = f() + )", + caNameSpaceName, + src, + caNameSpaceName + ) + ); +} diff --git a/src/xrServerEntities/script_dialect_lua.h b/src/xrServerEntities/script_dialect_lua.h index 76942a519b..6c7c30903f 100644 --- a/src/xrServerEntities/script_dialect_lua.h +++ b/src/xrServerEntities/script_dialect_lua.h @@ -4,8 +4,7 @@ class CLuaDialect : public CScriptDialect { -private: - const char* tag() const; public: - std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; + virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; }; diff --git a/src/xrServerEntities/script_dialect_wua.cpp b/src/xrServerEntities/script_dialect_wua.cpp new file mode 100644 index 0000000000..5dcae5c429 --- /dev/null +++ b/src/xrServerEntities/script_dialect_wua.cpp @@ -0,0 +1,40 @@ +#include "stdafx.h" +#include "script_dialect_wua.h" +#include "lua_macros.h" + +#include +#include +#include "../xrCore/mezz_stringbuffer.h" + +const std::string TAG_WUA = "--dialect wua"; + +bool CWuaDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const +{ + return src.compare(0, TAG_WUA.length(), TAG_WUA) == 0; +} + +std::string CWuaDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const +{ + return lines( + wua_environment("G"), + R"( +local this = setmetatable( + { _G = G }, + { __index = G } +) + )", + string_format( + R"( +package.loaded["%s"] = this +setfenv(1, this) + +local function script_name() + return "%s" +end + )", + caNameSpaceName, + caNameSpaceName + ), + src + ); +} diff --git a/src/xrServerEntities/script_dialect_wua.h b/src/xrServerEntities/script_dialect_wua.h new file mode 100644 index 0000000000..39bf1b2583 --- /dev/null +++ b/src/xrServerEntities/script_dialect_wua.h @@ -0,0 +1,10 @@ +#pragma once + +#include "script_dialect_wua_g.h" + +class CWuaDialect : public CWuaGDialect +{ +public: + virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const override; + virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; +}; diff --git a/src/xrServerEntities/script_dialect_wua_g.cpp b/src/xrServerEntities/script_dialect_wua_g.cpp new file mode 100644 index 0000000000..a1dab456af --- /dev/null +++ b/src/xrServerEntities/script_dialect_wua_g.cpp @@ -0,0 +1,167 @@ +#include "stdafx.h" +#include "script_dialect_wua.h" +#include "lua_macros.h" + +#include +#include +#include "../xrCore/mezz_stringbuffer.h" + +bool CWuaGDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const +{ + return xr_strcmp(caNameSpaceName, "_G") == 0; +} + +static bool unlocalRegex(Unlocalizer& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { + if (std::regex_match(s, pattern)) { + //Msg("matching local function pattern"); + std::smatch match; + std::regex_search(s, match, pattern); + std::string variable = match[group]; + if (unlocals.find(variable) != unlocals.end()) { + Msg("[unlocalRegex] found variable %s to unlocal", variable.c_str()); + s = std::regex_replace(s, pattern, replacement); + return true; + } + } + else { + return false; + } + return false; +}; + +static std::string join_list(const std::vector& items_vec, std::string delim = "\n") { + std::string ret; + for (const auto& i : items_vec) { + if (!ret.empty()) { + ret += delim; + } + ret += i; + } + return ret; +}; + +std::string CWuaGDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const +{ + bool unlocalPerformed = false; + std::string unlocalizerResult; + + // Get contents of the script file and split by lines + std::vector tokens; + std::string temp; + temp += src; + + std::stringstream stringStream(temp); + std::string line; + tokens.clear(); + while (std::getline(stringStream, line)) { + tokens.push_back(line); + } + + /*for (auto& u : unlocalizer) { + Msg("Unlocalizer: %s", u); + }*/ + + for (std::string& s : tokens) { + + //Msg("Line: %s", s.c_str()); + + trim(s, "\n\r"); + if (s.empty()) { + //Msg("Empty, continuing"); + continue; + } + + std::regex pattern; + + //local function x(a,b,c) + pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); + if (unlocalRegex(unlocalizer, s, pattern, 5, "$3$4$5$6$7")) { + //Msg("Regex matched"); + unlocalPerformed = true; + continue; + } + + //Msg("Regex not matched"); + + //local a = ... + //local a + //local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) + //local x; local y; - unsupported yet + pattern = std::regex(R"((^local)([\t ]+)(.*))"); + if (std::regex_match(s, pattern)) { + std::smatch match; + std::regex_search(s, match, pattern); + std::string m = match[3]; + + // strip comments + std::regex r = std::regex(R"((.*)--.*)"); + if (std::regex_match(m, r)) { + //Msg("found comments\n"); + std::smatch noncomments; + std::regex_search(m, noncomments, r); + m = noncomments[1]; + } + + auto variablesAndValues = splitStringLimit(m, "=", 1); + bool hasValue = variablesAndValues.size() > 1; + auto variables = splitStringMulti(variablesAndValues[0], ","); + for (auto v : variables) { + trim(v); + //Msg("%s\n", v.c_str()); + if (unlocalizer.find(v) != unlocalizer.end()) { + unlocalPerformed = true; + Msg("found variable %s to unlocal", v.c_str()); + s = std::regex_replace(s, pattern, "$3"); + if (!hasValue) { + + // strip comments + std::regex r = std::regex(R"((.*)(--.*))"); + if (std::regex_match(s, r)) { + //Msg("found comments\n"); + std::smatch noncomments; + std::regex_search(s, noncomments, r); + s = std::string(noncomments[1]) + "= nil " + std::string(noncomments[2]); + } + else { + s += " = nil"; + } + } + break; + } + } + } + } + + // Store result back + /*for (auto& s : tokens) { + Msg("%s", s.c_str()); + }*/ + + if (unlocalPerformed) + { + return join_list(tokens); + } + + return src; +} + +std::string CWuaGDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const +{ + return lines( + wua_environment("G"), + R"( +local env = setmetatable( + { _G = G }, + { + __index = G, + __newindex = function(self, key, value) + _G[key] = value + end + } +) + +setfenv(1, env) + )", + src + ); +} \ No newline at end of file diff --git a/src/xrServerEntities/script_dialect_wua_g.h b/src/xrServerEntities/script_dialect_wua_g.h new file mode 100644 index 0000000000..628210f77c --- /dev/null +++ b/src/xrServerEntities/script_dialect_wua_g.h @@ -0,0 +1,11 @@ +#pragma once + +#include "script_dialect.h" + +class CWuaGDialect : public CScriptDialect +{ +public: + virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const override; + virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; +}; diff --git a/src/xrServerEntities/script_dialects.cpp b/src/xrServerEntities/script_dialects.cpp index 5d1f6fbaf8..0c808706b6 100644 --- a/src/xrServerEntities/script_dialects.cpp +++ b/src/xrServerEntities/script_dialects.cpp @@ -1,58 +1,46 @@ #include "stdafx.h" #include "script_dialects.h" #include "../xrCore/mezz_stringbuffer.h" - -const CScriptDialect* CScriptDialects::parse(const std::string& src) const { - if (lua.parse(src)) { - return &lua; - } - else if (lisp_macro.parse(src)) { +#include "lua_macros.h" + +const CScriptDialect* CScriptDialects::recognize(const std::string& src, LPCSTR caNameSpaceName) const { + if (wua_g.recognize(src, caNameSpaceName)) + return &wua_g; + else if (wua.recognize(src, caNameSpaceName)) + return &wua; + else if (lua.recognize(src, caNameSpaceName)) + return &lua; + else if (lisp_macro.recognize(src, caNameSpaceName)) return &lisp_macro; - } - else if (lisp.parse(src)) { + else if (lisp.recognize(src, caNameSpaceName)) return &lisp; - } - return NULL; + return &wua; } -std::string CScriptDialects::wrap_buffer( +std::string CScriptDialects::lift( std::string caString, LPCSTR caScriptName, LPCSTR caNameSpaceName, Unlocalizers* unlocalizers ) const { - const CScriptDialect* dialect = parse(caString); - size_t lang_tag_len = 0; - if (dialect) - lang_tag_len = dialect->tag_length(); - else - dialect = &dialects.lua; - - if (lang_tag_len > 0) - caString.erase(0, lang_tag_len); + const CScriptDialect* dialect = recognize(caString, caNameSpaceName); + if (!dialect) + dialect = &dialects.wua; - std::string loweredNameSpaceName; if (caNameSpaceName) { + std::string loweredNameSpaceName; loweredNameSpaceName += caNameSpaceName; toLowerCase(loweredNameSpaceName); + if (unlocalizers && unlocalizers->find(loweredNameSpaceName) != unlocalizers->end()) + { + Msg("found script %s in unlocalizers data", caNameSpaceName); + // Iterate lines and unlocalize variables + Unlocalizer& unlocalizer = (*unlocalizers)[loweredNameSpaceName]; + caString = dialect->unlocalize(unlocalizer, caString, caNameSpaceName); + } } - if (unlocalizers && unlocalizers->find(loweredNameSpaceName) != unlocalizers->end()) - { - Msg("found script %s in unlocalizers data", caNameSpaceName); - // Iterate lines and unlocalize variables - Unlocalizer& unlocalizer = (*unlocalizers)[loweredNameSpaceName]; - caString = dialect->unlocalize(unlocalizer, caString, caNameSpaceName); - } - - caString = dialect->wrap_body(caString, caNameSpaceName); - - if (caNameSpaceName && xr_strcmp("_G", caNameSpaceName)) - { - caString = dialect->wrap_namespace(caString, caNameSpaceName); - } - - return caString; + return dialect->lift(caString, caNameSpaceName); } diff --git a/src/xrServerEntities/script_dialects.h b/src/xrServerEntities/script_dialects.h index bb5414bd88..7f2f570660 100644 --- a/src/xrServerEntities/script_dialects.h +++ b/src/xrServerEntities/script_dialects.h @@ -3,17 +3,23 @@ #include "stdafx.h" #include "script_storage.h" #include "script_dialect.h" +#include "script_dialect_wua.h" #include "script_dialect_lua.h" #include "script_dialect_lisp.h" #include "script_dialect_lisp_macro.h" struct CScriptDialects { + CWuaGDialect wua_g; + CWuaDialect wua; CLuaDialect lua; CLispDialect lisp; CLispMacroDialect lisp_macro; - const CScriptDialect* parse(const std::string& src) const; - std::string wrap_buffer( + const CScriptDialect* recognize( + const std::string& src, + LPCSTR caNameSpaceName = 0 + ) const; + std::string lift( std::string caString, LPCSTR caScriptName, LPCSTR caNameSpaceName = 0, diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index a5bb90ff1b..f5ce574856 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -312,31 +312,45 @@ void CScriptEngine::lua_hook_call (lua_State *L, lua_Debug *dbg) } #endif -int auto_load(lua_State* L) +int auto_load_closure(lua_State* L) { - if ((lua_gettop(L) < 2) || !lua_istable(L, 1) || !lua_isstring(L, 2)) + lua_pushvalue(L, lua_upvalueindex(1)); + return (1); +} + +int auto_load_searcher(lua_State* L) +{ + assert(lua_gettop(L) == 1); + assert(lua_isstring(L, 1)); + + LPCSTR name = lua_tostring(L, 1); + + if (ai().script_engine().process_file_if_exists(name, false)) { - lua_pushnil(L); + lua_getglobal(L, "package"); + lua_getfield(L, -1, "loaded"); + lua_pushstring(L, name); + lua_gettable(L, -2); + lua_remove(L, -2); + lua_pushcclosure(L, auto_load_closure, 1); return (1); } - ai().script_engine().process_file_if_exists(lua_tostring(L, 2), false); - lua_rawget(L, 1); + lua_pushstring(L, "\n\tFailure"); return (1); } void CScriptEngine::setup_auto_load() { - luaL_newmetatable(lua(), "XRAY_AutoLoadMetaTable"); - lua_pushstring(lua(), "__index"); - lua_pushcfunction(lua(), auto_load); - lua_settable(lua(), -3); - lua_pushstring(lua(), "_G"); - lua_gettable(lua(), LUA_GLOBALSINDEX); - luaL_getmetatable(lua(), "XRAY_AutoLoadMetaTable"); - lua_setmetatable(lua(), -2); - //. ?????????? - // lua_settop (lua(),-0); + lua_getglobal(lua(), "table"); + lua_getfield(lua(), -1, "insert"); + lua_remove(lua(), -2); + lua_getglobal(lua(), "package"); + lua_getfield(lua(), -1, "loaders"); + lua_remove(lua(), - 2); + lua_pushinteger(lua(), 2); + lua_pushcfunction(lua(), auto_load_searcher); + lua_call(lua(), 3, 0); } extern void export_classes(lua_State* L); @@ -451,11 +465,11 @@ void CScriptEngine::load_common_scripts() xr_delete(l_tpIniFile); } -void CScriptEngine::process_file_if_exists(LPCSTR file_name, bool warn_if_not_exist) +bool CScriptEngine::process_file_if_exists(LPCSTR file_name, bool warn_if_not_exist) { u32 string_length = xr_strlen(file_name); if (!warn_if_not_exist && no_file_exists(file_name, string_length)) - return; + return false; string_path S, S1; if (m_reload_modules || (*file_name && !namespace_loaded(file_name))) @@ -474,15 +488,17 @@ void CScriptEngine::process_file_if_exists(LPCSTR file_name, bool warn_if_not_ex } #endif add_no_file(file_name, string_length); - return; + return false; } //#ifndef MASTER_GOLD if (strstr(Core.Params, "-dbg")) Msg("* loading script %s", S1); //#endif // MASTER_GOLD m_reload_modules = false; - load_file_into_namespace(S, *file_name ? file_name : "_G"); + return load_file_into_namespace(S, *file_name ? file_name : "_G"); } + + return true; } void CScriptEngine::process_file(LPCSTR file_name) diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index beed1e9cb8..9b7101b393 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -94,7 +94,7 @@ class CScriptEngine : public CScriptStorage IC void add_script_process(const EScriptProcessors& process_id, CScriptProcess* script_process); void remove_script_process(const EScriptProcessors& process_id); void setup_auto_load(); - void process_file_if_exists(LPCSTR file_name, bool warn_if_not_exist); + bool process_file_if_exists(LPCSTR file_name, bool warn_if_not_exist); void process_file(LPCSTR file_name); void process_file(LPCSTR file_name, bool reload_modules); bool function_object(LPCSTR function_to_call, luabind::object& object, int type = LUA_TFUNCTION); diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index 5a6f7c4f17..552a236f54 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -568,7 +568,7 @@ bool CScriptStorage::load_buffer( ) { std::string caString(caBuffer, caBuffer + tSize); - caString = ScriptDialects().wrap_buffer(caString, caScriptName, caNameSpaceName, unlocalizers); + caString = ScriptDialects().lift(caString, caScriptName, caNameSpaceName, unlocalizers); int l_iErrorCode = luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); if (l_iErrorCode) @@ -720,8 +720,9 @@ bool CScriptStorage::load_file_into_namespace(LPCSTR caScriptName, LPCSTR caName bool CScriptStorage::namespace_loaded(LPCSTR N, bool remove_from_stack) { int start = lua_gettop(lua()); - lua_pushstring(lua(), "_G"); - lua_rawget(lua(), LUA_GLOBALSINDEX); + lua_getglobal(lua(), "package"); + lua_getfield(lua(), -1, "loaded"); + lua_remove(lua(), -2); string256 S2; xr_strcpy(S2, N); LPSTR S = S2; @@ -815,6 +816,8 @@ luabind::object CScriptStorage::name_space(LPCSTR namespace_name) xr_strcpy(S1, namespace_name); LPSTR S = S1; luabind::object lua_namespace = luabind::get_globals(lua()); + lua_namespace = lua_namespace["package"]; + lua_namespace = lua_namespace["loaded"]; for (;;) { if (!xr_strlen(S)) diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp index 4777a1df5c..353a149ccf 100644 --- a/src/xrServerEntities/script_thread.cpp +++ b/src/xrServerEntities/script_thread.cpp @@ -57,7 +57,7 @@ CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string, bool reload) { m_script_name = "console command"; S += caBuffer; - S = ScriptDialects().wrap_buffer(S, *m_script_name); + S = ScriptDialects().lift(S, *m_script_name); S = "function " + std::string(main_function) + "()\n" + S + "\nend"; int l_iErrorCode = luaL_loadbuffer(ai().script_engine().lua(), S.c_str(), S.length(), "@console_command"); if (!l_iErrorCode) From 2cdacb9ac9e66546d599e28532f0a873a306ac6c Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Mon, 19 May 2025 19:57:18 +0100 Subject: [PATCH 08/76] Account for null namespace name in `CWuaGDialect` --- src/xrServerEntities/script_dialect_wua_g.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xrServerEntities/script_dialect_wua_g.cpp b/src/xrServerEntities/script_dialect_wua_g.cpp index a1dab456af..83e49dc614 100644 --- a/src/xrServerEntities/script_dialect_wua_g.cpp +++ b/src/xrServerEntities/script_dialect_wua_g.cpp @@ -8,7 +8,7 @@ bool CWuaGDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const { - return xr_strcmp(caNameSpaceName, "_G") == 0; + return caNameSpaceName && xr_strcmp(caNameSpaceName, "_G") == 0; } static bool unlocalRegex(Unlocalizer& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { From 83da17abd8c7a7b76ef689111a8653b0b0e254c1 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Mon, 19 May 2025 19:57:47 +0100 Subject: [PATCH 09/76] Expose `CScriptDialect` to luabind --- src/xrGame/vs2022/xrGame.vcxproj | 1 + src/xrGame/vs2022/xrGame.vcxproj.filters | 3 +++ src/xrServerEntities/script_dialect.cpp | 5 +++++ src/xrServerEntities/script_dialect.h | 11 +++++++++-- src/xrServerEntities/script_dialect_script.cpp | 17 +++++++++++++++++ 5 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/xrServerEntities/script_dialect_script.cpp diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index da8392266b..d894721dc2 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -1973,6 +1973,7 @@ + pch_script.h diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index 70e4271bf9..5f3b510cb6 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -11150,6 +11150,9 @@ AI\AScript\ScriptDialect + + AI\AScript\ScriptDialect + diff --git a/src/xrServerEntities/script_dialect.cpp b/src/xrServerEntities/script_dialect.cpp index d5d7aac2cb..b25efa1f25 100644 --- a/src/xrServerEntities/script_dialect.cpp +++ b/src/xrServerEntities/script_dialect.cpp @@ -2,6 +2,11 @@ #include "script_dialect.h" #include "lua_macros.h" +bool CScriptDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const +{ + return false; +} + std::string CScriptDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const { return src; diff --git a/src/xrServerEntities/script_dialect.h b/src/xrServerEntities/script_dialect.h index f673eb5098..ada2b7f789 100644 --- a/src/xrServerEntities/script_dialect.h +++ b/src/xrServerEntities/script_dialect.h @@ -1,14 +1,21 @@ #pragma once +#include "script_export_space.h" #include typedef std::set Unlocalizer; typedef xr_unordered_map Unlocalizers; -class CScriptDialect +class CScriptDialect : public DLL_Pure { public: - virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const = 0; + virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const; + +DECLARE_SCRIPT_REGISTER_FUNCTION }; + +add_to_type_list(CScriptDialect) +#undef script_type_list +#define script_type_list save_type_list(CScriptDialect) \ No newline at end of file diff --git a/src/xrServerEntities/script_dialect_script.cpp b/src/xrServerEntities/script_dialect_script.cpp new file mode 100644 index 0000000000..e507266932 --- /dev/null +++ b/src/xrServerEntities/script_dialect_script.cpp @@ -0,0 +1,17 @@ +#include "stdafx.h" +#include "pch_script.h" +#include "script_dialect.h" + +using namespace luabind; + +#pragma optimize("s",on) +void CScriptDialect::script_register(lua_State* L) +{ + module(L) + [ + class_("CScriptDialect") + .def("recognize", &CScriptDialect::recognize) + .def("unlocalize", &CScriptDialect::unlocalize) + .def("lift", &CScriptDialect::lift) + ]; +} From 678c2a9653088022873bbf5a8c23c0323ca2aa55 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Mon, 19 May 2025 20:25:01 +0100 Subject: [PATCH 10/76] Factor out `CWuaGDialect` in favor of `CWuaDialect` --- src/xrGame/vs2022/xrGame.vcxproj | 6 +- src/xrGame/vs2022/xrGame.vcxproj.filters | 10 +- src/xrServerEntities/script_dialect_wua.cpp | 192 ++++++++++++++++-- src/xrServerEntities/script_dialect_wua.h | 7 +- src/xrServerEntities/script_dialect_wua_g.cpp | 167 --------------- src/xrServerEntities/script_dialect_wua_g.h | 11 - src/xrServerEntities/script_dialects.cpp | 8 +- src/xrServerEntities/script_dialects.h | 1 - 8 files changed, 183 insertions(+), 219 deletions(-) delete mode 100644 src/xrServerEntities/script_dialect_wua_g.cpp delete mode 100644 src/xrServerEntities/script_dialect_wua_g.h diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index d894721dc2..f369c98f0a 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -341,7 +341,7 @@ - + @@ -356,7 +356,6 @@ - @@ -1974,7 +1973,7 @@ - + pch_script.h $(IntDir)$(ProjectName)_script.pch @@ -2010,7 +2009,6 @@ - pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index 5f3b510cb6..13a0357fe7 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -7413,9 +7413,6 @@ AI\AScript\ScriptDialect - - AI\AScript\ScriptDialect - AI\AScript\ScriptDialect @@ -7425,7 +7422,7 @@ AI\AScript\ScriptDialect - + AI\AScript\ScriptDialect @@ -11135,16 +11132,13 @@ AI\AScript\ScriptDialect - - AI\AScript\ScriptDialect - AI\AScript\ScriptDialect AI\AScript\ScriptDialect - + AI\AScript\ScriptDialect diff --git a/src/xrServerEntities/script_dialect_wua.cpp b/src/xrServerEntities/script_dialect_wua.cpp index 5dcae5c429..2378bd0b6b 100644 --- a/src/xrServerEntities/script_dialect_wua.cpp +++ b/src/xrServerEntities/script_dialect_wua.cpp @@ -6,35 +6,191 @@ #include #include "../xrCore/mezz_stringbuffer.h" -const std::string TAG_WUA = "--dialect wua"; - bool CWuaDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const { - return src.compare(0, TAG_WUA.length(), TAG_WUA) == 0; + return true; +} + +static bool unlocalRegex(Unlocalizer& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { + if (std::regex_match(s, pattern)) { + //Msg("matching local function pattern"); + std::smatch match; + std::regex_search(s, match, pattern); + std::string variable = match[group]; + if (unlocals.find(variable) != unlocals.end()) { + Msg("[unlocalRegex] found variable %s to unlocal", variable.c_str()); + s = std::regex_replace(s, pattern, replacement); + return true; + } + } + else { + return false; + } + return false; +}; + +static std::string join_list(const std::vector& items_vec, std::string delim = "\n") { + std::string ret; + for (const auto& i : items_vec) { + if (!ret.empty()) { + ret += delim; + } + ret += i; + } + return ret; +}; + +std::string CWuaDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const +{ + bool unlocalPerformed = false; + std::string unlocalizerResult; + + // Get contents of the script file and split by lines + std::vector tokens; + std::string temp; + temp += src; + + std::stringstream stringStream(temp); + std::string line; + tokens.clear(); + while (std::getline(stringStream, line)) { + tokens.push_back(line); + } + + /*for (auto& u : unlocalizer) { + Msg("Unlocalizer: %s", u); + }*/ + + for (std::string& s : tokens) { + + //Msg("Line: %s", s.c_str()); + + trim(s, "\n\r"); + if (s.empty()) { + //Msg("Empty, continuing"); + continue; + } + + std::regex pattern; + + //local function x(a,b,c) + pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); + if (unlocalRegex(unlocalizer, s, pattern, 5, "$3$4$5$6$7")) { + //Msg("Regex matched"); + unlocalPerformed = true; + continue; + } + + //Msg("Regex not matched"); + + //local a = ... + //local a + //local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) + //local x; local y; - unsupported yet + pattern = std::regex(R"((^local)([\t ]+)(.*))"); + if (std::regex_match(s, pattern)) { + std::smatch match; + std::regex_search(s, match, pattern); + std::string m = match[3]; + + // strip comments + std::regex r = std::regex(R"((.*)--.*)"); + if (std::regex_match(m, r)) { + //Msg("found comments\n"); + std::smatch noncomments; + std::regex_search(m, noncomments, r); + m = noncomments[1]; + } + + auto variablesAndValues = splitStringLimit(m, "=", 1); + bool hasValue = variablesAndValues.size() > 1; + auto variables = splitStringMulti(variablesAndValues[0], ","); + for (auto v : variables) { + trim(v); + //Msg("%s\n", v.c_str()); + if (unlocalizer.find(v) != unlocalizer.end()) { + unlocalPerformed = true; + Msg("found variable %s to unlocal", v.c_str()); + s = std::regex_replace(s, pattern, "$3"); + if (!hasValue) { + + // strip comments + std::regex r = std::regex(R"((.*)(--.*))"); + if (std::regex_match(s, r)) { + //Msg("found comments\n"); + std::smatch noncomments; + std::regex_search(s, noncomments, r); + s = std::string(noncomments[1]) + "= nil " + std::string(noncomments[2]); + } + else { + s += " = nil"; + } + } + break; + } + } + } + } + + // Store result back + /*for (auto& s : tokens) { + Msg("%s", s.c_str()); + }*/ + + if (unlocalPerformed) + { + return join_list(tokens); + } + + return src; } std::string CWuaDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const { - return lines( - wua_environment("G"), - R"( -local this = setmetatable( - { _G = G }, - { __index = G } -) - )", - string_format( + bool is_g = caNameSpaceName && xr_strcmp(caNameSpaceName, "_G") == 0; + std::string out; + out += wua_environment("G"); + out += R"( +local mt = {} +mt.__index = G + )"; + if (is_g) + out += R"( +mt.__newindex = function(self, key, value) + _G[key] = value +end + )"; + + out += R"( +local this = {} +this._G = G + )"; + + if (!is_g) + { + out += string_format( R"( package.loaded["%s"] = this + )", + caNameSpaceName + ); + } + + out += R"( +setmetatable(this, mt) setfenv(1, this) + )"; + out += string_format( + R"( local function script_name() - return "%s" +return "%s" end - )", - caNameSpaceName, - caNameSpaceName - ), - src + )", + caNameSpaceName ); + + out += "\n" + src; + + return out; } diff --git a/src/xrServerEntities/script_dialect_wua.h b/src/xrServerEntities/script_dialect_wua.h index 39bf1b2583..9fc225a4ac 100644 --- a/src/xrServerEntities/script_dialect_wua.h +++ b/src/xrServerEntities/script_dialect_wua.h @@ -1,10 +1,11 @@ #pragma once -#include "script_dialect_wua_g.h" +#include "script_dialect.h" -class CWuaDialect : public CWuaGDialect +class CWuaDialect : public CScriptDialect { public: - virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const override; + virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const override; virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; }; diff --git a/src/xrServerEntities/script_dialect_wua_g.cpp b/src/xrServerEntities/script_dialect_wua_g.cpp deleted file mode 100644 index 83e49dc614..0000000000 --- a/src/xrServerEntities/script_dialect_wua_g.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include "stdafx.h" -#include "script_dialect_wua.h" -#include "lua_macros.h" - -#include -#include -#include "../xrCore/mezz_stringbuffer.h" - -bool CWuaGDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const -{ - return caNameSpaceName && xr_strcmp(caNameSpaceName, "_G") == 0; -} - -static bool unlocalRegex(Unlocalizer& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { - if (std::regex_match(s, pattern)) { - //Msg("matching local function pattern"); - std::smatch match; - std::regex_search(s, match, pattern); - std::string variable = match[group]; - if (unlocals.find(variable) != unlocals.end()) { - Msg("[unlocalRegex] found variable %s to unlocal", variable.c_str()); - s = std::regex_replace(s, pattern, replacement); - return true; - } - } - else { - return false; - } - return false; -}; - -static std::string join_list(const std::vector& items_vec, std::string delim = "\n") { - std::string ret; - for (const auto& i : items_vec) { - if (!ret.empty()) { - ret += delim; - } - ret += i; - } - return ret; -}; - -std::string CWuaGDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const -{ - bool unlocalPerformed = false; - std::string unlocalizerResult; - - // Get contents of the script file and split by lines - std::vector tokens; - std::string temp; - temp += src; - - std::stringstream stringStream(temp); - std::string line; - tokens.clear(); - while (std::getline(stringStream, line)) { - tokens.push_back(line); - } - - /*for (auto& u : unlocalizer) { - Msg("Unlocalizer: %s", u); - }*/ - - for (std::string& s : tokens) { - - //Msg("Line: %s", s.c_str()); - - trim(s, "\n\r"); - if (s.empty()) { - //Msg("Empty, continuing"); - continue; - } - - std::regex pattern; - - //local function x(a,b,c) - pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); - if (unlocalRegex(unlocalizer, s, pattern, 5, "$3$4$5$6$7")) { - //Msg("Regex matched"); - unlocalPerformed = true; - continue; - } - - //Msg("Regex not matched"); - - //local a = ... - //local a - //local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) - //local x; local y; - unsupported yet - pattern = std::regex(R"((^local)([\t ]+)(.*))"); - if (std::regex_match(s, pattern)) { - std::smatch match; - std::regex_search(s, match, pattern); - std::string m = match[3]; - - // strip comments - std::regex r = std::regex(R"((.*)--.*)"); - if (std::regex_match(m, r)) { - //Msg("found comments\n"); - std::smatch noncomments; - std::regex_search(m, noncomments, r); - m = noncomments[1]; - } - - auto variablesAndValues = splitStringLimit(m, "=", 1); - bool hasValue = variablesAndValues.size() > 1; - auto variables = splitStringMulti(variablesAndValues[0], ","); - for (auto v : variables) { - trim(v); - //Msg("%s\n", v.c_str()); - if (unlocalizer.find(v) != unlocalizer.end()) { - unlocalPerformed = true; - Msg("found variable %s to unlocal", v.c_str()); - s = std::regex_replace(s, pattern, "$3"); - if (!hasValue) { - - // strip comments - std::regex r = std::regex(R"((.*)(--.*))"); - if (std::regex_match(s, r)) { - //Msg("found comments\n"); - std::smatch noncomments; - std::regex_search(s, noncomments, r); - s = std::string(noncomments[1]) + "= nil " + std::string(noncomments[2]); - } - else { - s += " = nil"; - } - } - break; - } - } - } - } - - // Store result back - /*for (auto& s : tokens) { - Msg("%s", s.c_str()); - }*/ - - if (unlocalPerformed) - { - return join_list(tokens); - } - - return src; -} - -std::string CWuaGDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const -{ - return lines( - wua_environment("G"), - R"( -local env = setmetatable( - { _G = G }, - { - __index = G, - __newindex = function(self, key, value) - _G[key] = value - end - } -) - -setfenv(1, env) - )", - src - ); -} \ No newline at end of file diff --git a/src/xrServerEntities/script_dialect_wua_g.h b/src/xrServerEntities/script_dialect_wua_g.h deleted file mode 100644 index 628210f77c..0000000000 --- a/src/xrServerEntities/script_dialect_wua_g.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "script_dialect.h" - -class CWuaGDialect : public CScriptDialect -{ -public: - virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; - virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const override; - virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; -}; diff --git a/src/xrServerEntities/script_dialects.cpp b/src/xrServerEntities/script_dialects.cpp index 0c808706b6..f62966f03a 100644 --- a/src/xrServerEntities/script_dialects.cpp +++ b/src/xrServerEntities/script_dialects.cpp @@ -4,11 +4,7 @@ #include "lua_macros.h" const CScriptDialect* CScriptDialects::recognize(const std::string& src, LPCSTR caNameSpaceName) const { - if (wua_g.recognize(src, caNameSpaceName)) - return &wua_g; - else if (wua.recognize(src, caNameSpaceName)) - return &wua; - else if (lua.recognize(src, caNameSpaceName)) + if (lua.recognize(src, caNameSpaceName)) return &lua; else if (lisp_macro.recognize(src, caNameSpaceName)) return &lisp_macro; @@ -25,8 +21,6 @@ std::string CScriptDialects::lift( ) const { const CScriptDialect* dialect = recognize(caString, caNameSpaceName); - if (!dialect) - dialect = &dialects.wua; if (caNameSpaceName) { diff --git a/src/xrServerEntities/script_dialects.h b/src/xrServerEntities/script_dialects.h index 7f2f570660..280318d31f 100644 --- a/src/xrServerEntities/script_dialects.h +++ b/src/xrServerEntities/script_dialects.h @@ -9,7 +9,6 @@ #include "script_dialect_lisp_macro.h" struct CScriptDialects { - CWuaGDialect wua_g; CWuaDialect wua; CLuaDialect lua; CLispDialect lisp; From d73467b509f3fb095f63570ad343c835eb4a8d89 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Mon, 19 May 2025 23:06:50 +0100 Subject: [PATCH 11/76] Refactor around macro semantic - Replaced dialect semantic with macro semantic - Offloaded non-wua macros to scripts --- gamedata/scripts/macro_lisp.script | 37 ++++++++++ .../scripts/macro_lisp_macro.script | 30 +++----- gamedata/scripts/macro_lua.script | 18 +++++ src/xrGame/vs2022/xrGame.vcxproj | 20 ++---- src/xrGame/vs2022/xrGame.vcxproj.filters | 21 ++---- src/xrServerEntities/script_dialect.cpp | 18 ----- src/xrServerEntities/script_dialect_lisp.cpp | 56 --------------- src/xrServerEntities/script_dialect_lisp.h | 11 --- .../script_dialect_lisp_macro.h | 10 --- src/xrServerEntities/script_dialect_lua.cpp | 36 ---------- src/xrServerEntities/script_dialect_lua.h | 10 --- .../script_dialect_script.cpp | 17 ----- src/xrServerEntities/script_dialect_wua.h | 11 --- src/xrServerEntities/script_dialects.cpp | 40 ----------- src/xrServerEntities/script_dialects.h | 33 --------- src/xrServerEntities/script_macro.cpp | 13 ++++ .../{script_dialect.h => script_macro.h} | 9 ++- src/xrServerEntities/script_macro_script.cpp | 16 +++++ ...t_dialect_wua.cpp => script_macro_wua.cpp} | 11 +-- src/xrServerEntities/script_macro_wua.h | 10 +++ src/xrServerEntities/script_macros.cpp | 69 +++++++++++++++++++ src/xrServerEntities/script_macros.h | 31 +++++++++ src/xrServerEntities/script_storage.cpp | 4 +- src/xrServerEntities/script_storage.h | 2 +- src/xrServerEntities/script_thread.cpp | 4 +- 25 files changed, 229 insertions(+), 308 deletions(-) create mode 100644 gamedata/scripts/macro_lisp.script rename src/xrServerEntities/script_dialect_lisp_macro.cpp => gamedata/scripts/macro_lisp_macro.script (51%) create mode 100644 gamedata/scripts/macro_lua.script delete mode 100644 src/xrServerEntities/script_dialect.cpp delete mode 100644 src/xrServerEntities/script_dialect_lisp.cpp delete mode 100644 src/xrServerEntities/script_dialect_lisp.h delete mode 100644 src/xrServerEntities/script_dialect_lisp_macro.h delete mode 100644 src/xrServerEntities/script_dialect_lua.cpp delete mode 100644 src/xrServerEntities/script_dialect_lua.h delete mode 100644 src/xrServerEntities/script_dialect_script.cpp delete mode 100644 src/xrServerEntities/script_dialect_wua.h delete mode 100644 src/xrServerEntities/script_dialects.cpp delete mode 100644 src/xrServerEntities/script_dialects.h create mode 100644 src/xrServerEntities/script_macro.cpp rename src/xrServerEntities/{script_dialect.h => script_macro.h} (50%) create mode 100644 src/xrServerEntities/script_macro_script.cpp rename src/xrServerEntities/{script_dialect_wua.cpp => script_macro_wua.cpp} (94%) create mode 100644 src/xrServerEntities/script_macro_wua.h create mode 100644 src/xrServerEntities/script_macros.cpp create mode 100644 src/xrServerEntities/script_macros.h diff --git a/gamedata/scripts/macro_lisp.script b/gamedata/scripts/macro_lisp.script new file mode 100644 index 0000000000..42499e839b --- /dev/null +++ b/gamedata/scripts/macro_lisp.script @@ -0,0 +1,37 @@ +function lisp(src, namespace_name, unlocs) + -- Unlocalize + if #unlocs then + src = string.format( + [[ +(import-macros {: unlocalize} :lisp_unlocalize) +(unlocalize + [%s] + %s) + ]], + table.concat(unlocs, " "), + src + ) + end + + -- Wrap into lisp compiler + return string.format( + [==[ +package.loaded["%s"] = require("fennel").eval( + [=[ +(fn script_name [] + "%s") +%s + ]=], + { + allowedGlobals = false, + correlate = true, + useBitLib = true, + ["error-pinpoint"] = false, + } +) + ]==], + namespace_name, + namespace_name, + src + ); +end diff --git a/src/xrServerEntities/script_dialect_lisp_macro.cpp b/gamedata/scripts/macro_lisp_macro.script similarity index 51% rename from src/xrServerEntities/script_dialect_lisp_macro.cpp rename to gamedata/scripts/macro_lisp_macro.script index 0cda54cd7d..21ea0edd0d 100644 --- a/src/xrServerEntities/script_dialect_lisp_macro.cpp +++ b/gamedata/scripts/macro_lisp_macro.script @@ -1,18 +1,6 @@ -#include "stdafx.h" -#include "script_dialect_lisp_macro.h" -#include "lua_macros.h" - -const std::string TAG_LISP_MACRO = ";dialect lisp macro"; - -bool CLispMacroDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const -{ - return src.compare(0, TAG_LISP_MACRO.length(), TAG_LISP_MACRO) == 0; -} - -std::string CLispMacroDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const -{ - return string_format( - R"( +function lisp_macro(src, namespace_name) + return string.format( + [==[ local fennel = require("fennel") table.insert( fennel["macro-searchers"], @@ -36,9 +24,9 @@ table.insert( end ) package.loaded["%s"] = {} - )", - caNameSpaceName, - src, - caNameSpaceName - ); -} \ No newline at end of file + ]==], + namespace_name, + src, + namespace_name + ) +end diff --git a/gamedata/scripts/macro_lua.script b/gamedata/scripts/macro_lua.script new file mode 100644 index 0000000000..713cf06c07 --- /dev/null +++ b/gamedata/scripts/macro_lua.script @@ -0,0 +1,18 @@ +function lua(src, namespace_name, unlocalizer) + return string.format( + [[ +local function f() + local function script_name() + return "%s" + end + + %s +end + +package.loaded["%s"] = f() + ]], + namespace_name, + src, + namespace_name + ) +end diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index f369c98f0a..b59ddb07e0 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -338,10 +338,8 @@ - - - - + + @@ -354,8 +352,7 @@ - - + @@ -1969,11 +1966,9 @@ - - - - - + + + pch_script.h $(IntDir)$(ProjectName)_script.pch @@ -2007,8 +2002,7 @@ pch_script.h $(IntDir)$(ProjectName)_script.pch - - + pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index 13a0357fe7..a64b31da7e 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -7408,24 +7408,16 @@ UI\Common\ImGui + AI\AScript\ScriptDialect - - AI\AScript\ScriptDialect - - - AI\AScript\ScriptDialect - - + AI\AScript\ScriptDialect AI\AScript\ScriptDialect - - AI\AScript\ScriptDialect - - + AI\AScript\ScriptDialect @@ -11136,15 +11128,16 @@ AI\AScript\ScriptDialect + AI\AScript\ScriptDialect - + AI\AScript\ScriptDialect - + AI\AScript\ScriptDialect - + AI\AScript\ScriptDialect diff --git a/src/xrServerEntities/script_dialect.cpp b/src/xrServerEntities/script_dialect.cpp deleted file mode 100644 index b25efa1f25..0000000000 --- a/src/xrServerEntities/script_dialect.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "stdafx.h" -#include "script_dialect.h" -#include "lua_macros.h" - -bool CScriptDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const -{ - return false; -} - -std::string CScriptDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const -{ - return src; -} - -std::string CScriptDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const -{ - return src; -} diff --git a/src/xrServerEntities/script_dialect_lisp.cpp b/src/xrServerEntities/script_dialect_lisp.cpp deleted file mode 100644 index 236285e2ae..0000000000 --- a/src/xrServerEntities/script_dialect_lisp.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "stdafx.h" -#include "script_dialect_lisp.h" -#include "lua_macros.h" -#include - -const std::string TAG_LISP = ";dialect lisp"; - -bool CLispDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const -{ - return src.compare(0, TAG_LISP.length(), TAG_LISP) == 0; -} - -std::string CLispDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const -{ - std::string unlocs; - for (auto unloc : unlocalizer) - { - if (unlocs.length() > 0) - unlocs += " "; - unlocs += unloc; - } - return string_format( - R"( -(import-macros {: unlocalize} :lisp_unlocalize) -(unlocalize - [%s] - %s) - )", - unlocs, - src - ); -} - -std::string CLispDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const -{ - return string_format( - R"( -package.loaded["%s"] = require("fennel").eval( - [=[ -(fn script_name [] - "%s") -%s - ]=], - { - allowedGlobals = false, - correlate = true, - useBitLib = true, - ["error-pinpoint"] = false, - } -) - )", - caNameSpaceName, - caNameSpaceName, - src - ); -} diff --git a/src/xrServerEntities/script_dialect_lisp.h b/src/xrServerEntities/script_dialect_lisp.h deleted file mode 100644 index 337634c2bd..0000000000 --- a/src/xrServerEntities/script_dialect_lisp.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "script_dialect.h" - -class CLispDialect : public CScriptDialect -{ -public: - virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; - virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const override; - virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; -}; diff --git a/src/xrServerEntities/script_dialect_lisp_macro.h b/src/xrServerEntities/script_dialect_lisp_macro.h deleted file mode 100644 index ef95937b88..0000000000 --- a/src/xrServerEntities/script_dialect_lisp_macro.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "script_dialect.h" - -class CLispMacroDialect : public CScriptDialect -{ -public: - virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; - virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; -}; diff --git a/src/xrServerEntities/script_dialect_lua.cpp b/src/xrServerEntities/script_dialect_lua.cpp deleted file mode 100644 index 3c4acb9a2e..0000000000 --- a/src/xrServerEntities/script_dialect_lua.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "stdafx.h" -#include "script_dialect_lua.h" -#include "lua_macros.h" - -#include -#include -#include "../xrCore/mezz_stringbuffer.h" - -const std::string TAG_LUA = "--dialect lua"; - -bool CLuaDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const -{ - return src.compare(0, TAG_LUA.length(), TAG_LUA) == 0; -} - -std::string CLuaDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const -{ - return lines( - string_format( - R"( -local function f() - local function script_name() - return "%s" - end - - %s -end - -package.loaded["%s"] = f() - )", - caNameSpaceName, - src, - caNameSpaceName - ) - ); -} diff --git a/src/xrServerEntities/script_dialect_lua.h b/src/xrServerEntities/script_dialect_lua.h deleted file mode 100644 index 6c7c30903f..0000000000 --- a/src/xrServerEntities/script_dialect_lua.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "script_dialect.h" - -class CLuaDialect : public CScriptDialect -{ -public: - virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; - virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; -}; diff --git a/src/xrServerEntities/script_dialect_script.cpp b/src/xrServerEntities/script_dialect_script.cpp deleted file mode 100644 index e507266932..0000000000 --- a/src/xrServerEntities/script_dialect_script.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "stdafx.h" -#include "pch_script.h" -#include "script_dialect.h" - -using namespace luabind; - -#pragma optimize("s",on) -void CScriptDialect::script_register(lua_State* L) -{ - module(L) - [ - class_("CScriptDialect") - .def("recognize", &CScriptDialect::recognize) - .def("unlocalize", &CScriptDialect::unlocalize) - .def("lift", &CScriptDialect::lift) - ]; -} diff --git a/src/xrServerEntities/script_dialect_wua.h b/src/xrServerEntities/script_dialect_wua.h deleted file mode 100644 index 9fc225a4ac..0000000000 --- a/src/xrServerEntities/script_dialect_wua.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "script_dialect.h" - -class CWuaDialect : public CScriptDialect -{ -public: - virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; - virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const override; - virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; -}; diff --git a/src/xrServerEntities/script_dialects.cpp b/src/xrServerEntities/script_dialects.cpp deleted file mode 100644 index f62966f03a..0000000000 --- a/src/xrServerEntities/script_dialects.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "stdafx.h" -#include "script_dialects.h" -#include "../xrCore/mezz_stringbuffer.h" -#include "lua_macros.h" - -const CScriptDialect* CScriptDialects::recognize(const std::string& src, LPCSTR caNameSpaceName) const { - if (lua.recognize(src, caNameSpaceName)) - return &lua; - else if (lisp_macro.recognize(src, caNameSpaceName)) - return &lisp_macro; - else if (lisp.recognize(src, caNameSpaceName)) - return &lisp; - return &wua; -} - -std::string CScriptDialects::lift( - std::string caString, - LPCSTR caScriptName, - LPCSTR caNameSpaceName, - Unlocalizers* unlocalizers -) const -{ - const CScriptDialect* dialect = recognize(caString, caNameSpaceName); - - if (caNameSpaceName) - { - std::string loweredNameSpaceName; - loweredNameSpaceName += caNameSpaceName; - toLowerCase(loweredNameSpaceName); - if (unlocalizers && unlocalizers->find(loweredNameSpaceName) != unlocalizers->end()) - { - Msg("found script %s in unlocalizers data", caNameSpaceName); - // Iterate lines and unlocalize variables - Unlocalizer& unlocalizer = (*unlocalizers)[loweredNameSpaceName]; - caString = dialect->unlocalize(unlocalizer, caString, caNameSpaceName); - } - } - - return dialect->lift(caString, caNameSpaceName); -} diff --git a/src/xrServerEntities/script_dialects.h b/src/xrServerEntities/script_dialects.h deleted file mode 100644 index 280318d31f..0000000000 --- a/src/xrServerEntities/script_dialects.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "stdafx.h" -#include "script_storage.h" -#include "script_dialect.h" -#include "script_dialect_wua.h" -#include "script_dialect_lua.h" -#include "script_dialect_lisp.h" -#include "script_dialect_lisp_macro.h" - -struct CScriptDialects { - CWuaDialect wua; - CLuaDialect lua; - CLispDialect lisp; - CLispMacroDialect lisp_macro; - - const CScriptDialect* recognize( - const std::string& src, - LPCSTR caNameSpaceName = 0 - ) const; - std::string lift( - std::string caString, - LPCSTR caScriptName, - LPCSTR caNameSpaceName = 0, - Unlocalizers* unlocalizers = 0 - ) const; -}; - -static CScriptDialects dialects; -static const CScriptDialects& ScriptDialects() -{ - return dialects; -} \ No newline at end of file diff --git a/src/xrServerEntities/script_macro.cpp b/src/xrServerEntities/script_macro.cpp new file mode 100644 index 0000000000..18ab5bec6c --- /dev/null +++ b/src/xrServerEntities/script_macro.cpp @@ -0,0 +1,13 @@ +#include "stdafx.h" +#include "script_macro.h" +#include "lua_macros.h" + +std::string CScriptMacro::lift(const std::string& src, LPCSTR caNameSpaceName) const +{ + return src; +} + +std::string CScriptMacro::unlocalize(const std::string& src, LPCSTR caNameSpaceName, Unlocalizer& unlocalizer) const +{ + return src; +} diff --git a/src/xrServerEntities/script_dialect.h b/src/xrServerEntities/script_macro.h similarity index 50% rename from src/xrServerEntities/script_dialect.h rename to src/xrServerEntities/script_macro.h index ada2b7f789..3af9283a2d 100644 --- a/src/xrServerEntities/script_dialect.h +++ b/src/xrServerEntities/script_macro.h @@ -6,16 +6,15 @@ typedef std::set Unlocalizer; typedef xr_unordered_map Unlocalizers; -class CScriptDialect : public DLL_Pure +class CScriptMacro : public DLL_Pure { public: - virtual bool recognize(const std::string& src, LPCSTR caNameSpaceName) const; - virtual std::string unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName, Unlocalizer& unlocalizer) const; virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const; DECLARE_SCRIPT_REGISTER_FUNCTION }; -add_to_type_list(CScriptDialect) +add_to_type_list(CScriptMacro) #undef script_type_list -#define script_type_list save_type_list(CScriptDialect) \ No newline at end of file +#define script_type_list save_type_list(CScriptMacro) \ No newline at end of file diff --git a/src/xrServerEntities/script_macro_script.cpp b/src/xrServerEntities/script_macro_script.cpp new file mode 100644 index 0000000000..16b4678854 --- /dev/null +++ b/src/xrServerEntities/script_macro_script.cpp @@ -0,0 +1,16 @@ +#include "stdafx.h" +#include "pch_script.h" +#include "script_macro.h" + +using namespace luabind; + +#pragma optimize("s",on) +void CScriptMacro::script_register(lua_State* L) +{ + module(L) + [ + class_("CScriptMacro") + .def("unlocalize", &CScriptMacro::unlocalize) + .def("lift", &CScriptMacro::lift) + ]; +} diff --git a/src/xrServerEntities/script_dialect_wua.cpp b/src/xrServerEntities/script_macro_wua.cpp similarity index 94% rename from src/xrServerEntities/script_dialect_wua.cpp rename to src/xrServerEntities/script_macro_wua.cpp index 2378bd0b6b..d2ee3cfb33 100644 --- a/src/xrServerEntities/script_dialect_wua.cpp +++ b/src/xrServerEntities/script_macro_wua.cpp @@ -1,16 +1,11 @@ #include "stdafx.h" -#include "script_dialect_wua.h" +#include "script_macro_wua.h" #include "lua_macros.h" #include #include #include "../xrCore/mezz_stringbuffer.h" -bool CWuaDialect::recognize(const std::string& src, LPCSTR caNameSpaceName) const -{ - return true; -} - static bool unlocalRegex(Unlocalizer& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { if (std::regex_match(s, pattern)) { //Msg("matching local function pattern"); @@ -40,7 +35,7 @@ static std::string join_list(const std::vector& items_vec, std::str return ret; }; -std::string CWuaDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& src, LPCSTR caNameSpaceName) const +std::string CWuaMacro::unlocalize(const std::string& src, LPCSTR caNameSpaceName, Unlocalizer& unlocalizer) const { bool unlocalPerformed = false; std::string unlocalizerResult; @@ -145,7 +140,7 @@ std::string CWuaDialect::unlocalize(Unlocalizer& unlocalizer, const std::string& return src; } -std::string CWuaDialect::lift(const std::string& src, LPCSTR caNameSpaceName) const +std::string CWuaMacro::lift(const std::string& src, LPCSTR caNameSpaceName) const { bool is_g = caNameSpaceName && xr_strcmp(caNameSpaceName, "_G") == 0; std::string out; diff --git a/src/xrServerEntities/script_macro_wua.h b/src/xrServerEntities/script_macro_wua.h new file mode 100644 index 0000000000..2ad99a5917 --- /dev/null +++ b/src/xrServerEntities/script_macro_wua.h @@ -0,0 +1,10 @@ +#pragma once + +#include "script_macro.h" + +class CWuaMacro : public CScriptMacro +{ +public: + virtual std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName, Unlocalizer& unlocalizer) const override; + virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; +}; diff --git a/src/xrServerEntities/script_macros.cpp b/src/xrServerEntities/script_macros.cpp new file mode 100644 index 0000000000..b822084e56 --- /dev/null +++ b/src/xrServerEntities/script_macros.cpp @@ -0,0 +1,69 @@ +#include "stdafx.h" +#include "script_macros.h" +#include "ai_space.h" +#include "script_engine.h" +#include "../xrCore/mezz_stringbuffer.h" +#include "lua_macros.h" +#include "luabind/luabind.hpp" +#include +#include + +std::string CScriptMacros::lift( + std::string caString, + LPCSTR caScriptName, + LPCSTR caNameSpaceName, + Unlocalizers* unlocalizers +) const +{ + Unlocalizer* unlocalizer = NULL; + if (caNameSpaceName) + { + std::string loweredNameSpaceName; + loweredNameSpaceName += caNameSpaceName; + toLowerCase(loweredNameSpaceName); + if (unlocalizers && unlocalizers->find(loweredNameSpaceName) != unlocalizers->end()) + { + Msg("found script %s in unlocalizers data", caNameSpaceName); + // Iterate lines and unlocalize variables + unlocalizer = &(*unlocalizers)[loweredNameSpaceName]; + } + } + + std::regex pattern(R"(#macro (.*)(\s+))"); + std::smatch match; + if (std::regex_search(caString, match, pattern)) + { + std::string macro_name = match[1]; + caString = std::string(match[2]) + std::string(match.suffix()); + if (macro_name != "wua") + { + luabind::functor macro; + if (ai().script_engine().functor(string_format("macro_%s.%s", macro_name, macro_name).c_str(), macro)) + { + + luabind::object unlocs = luabind::newtable(ai().script_engine().lua()); + if (unlocalizer) + { + int i = 1; + for (auto unloc : *unlocalizer) + { + unlocs[i] = unloc.c_str(); + i++; + } + } + + return std::string(macro(caString.c_str(), caNameSpaceName, unlocs)); + } + else + { + Msg("No such macro: %s", macro_name); + FATAL("Failed to load macro"); + } + } + } + + if (unlocalizer) + caString = wua.unlocalize(caString, caNameSpaceName, *unlocalizer); + + return wua.lift(caString, caNameSpaceName); +} diff --git a/src/xrServerEntities/script_macros.h b/src/xrServerEntities/script_macros.h new file mode 100644 index 0000000000..8639ae2208 --- /dev/null +++ b/src/xrServerEntities/script_macros.h @@ -0,0 +1,31 @@ +#pragma once + +#include "stdafx.h" +#include "script_storage.h" +#include "script_macro.h" +#include "script_macro_wua.h" + +namespace luabind +{ + template + class functor; + + class object; +} // namespace luabind + +struct CScriptMacros { + CWuaMacro wua; + + std::string lift( + std::string caString, + LPCSTR caScriptName, + LPCSTR caNameSpaceName = 0, + Unlocalizers* unlocalizers = 0 + ) const; +}; + +static CScriptMacros macros; +static const CScriptMacros& ScriptMacros() +{ + return macros; +} \ No newline at end of file diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index 552a236f54..225a35f077 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -8,7 +8,7 @@ #include "pch_script.h" #include "script_storage.h" -#include "script_dialects.h" +#include "script_macros.h" #include "script_thread.h" #include "../xrCore/mezz_stringbuffer.h" #include @@ -568,7 +568,7 @@ bool CScriptStorage::load_buffer( ) { std::string caString(caBuffer, caBuffer + tSize); - caString = ScriptDialects().lift(caString, caScriptName, caNameSpaceName, unlocalizers); + caString = ScriptMacros().lift(caString, caScriptName, caNameSpaceName, unlocalizers); int l_iErrorCode = luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); if (l_iErrorCode) diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h index 3c041b9fa9..7e0a1c0087 100644 --- a/src/xrServerEntities/script_storage.h +++ b/src/xrServerEntities/script_storage.h @@ -10,7 +10,7 @@ #include "script_storage_space.h" #include "script_space_forward.h" -#include "script_dialect.h" +#include "script_macro.h" #include #include #include diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp index 353a149ccf..493c8aa3ad 100644 --- a/src/xrServerEntities/script_thread.cpp +++ b/src/xrServerEntities/script_thread.cpp @@ -14,7 +14,7 @@ };*/ //-AVO #include "script_engine.h" -#include "script_dialects.h" +#include "script_macros.h" #include "script_thread.h" #include "ai_space.h" @@ -57,7 +57,7 @@ CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string, bool reload) { m_script_name = "console command"; S += caBuffer; - S = ScriptDialects().lift(S, *m_script_name); + S = ScriptMacros().lift(S, *m_script_name); S = "function " + std::string(main_function) + "()\n" + S + "\nend"; int l_iErrorCode = luaL_loadbuffer(ai().script_engine().lua(), S.c_str(), S.length(), "@console_command"); if (!l_iErrorCode) From 6911324d6ce4ff2723229f633aad8846856e8b7a Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 20 May 2025 02:33:06 +0100 Subject: [PATCH 12/76] Compiler semantic pass - Rename `CScriptMacros` to `CScriptCompiler` - Make authoritative over unlocalization data - Simplify `CScriptMacro` implementation --- gamedata/scripts/macro_lisp.script | 2 +- gamedata/scripts/macro_lisp_macro.script | 2 +- gamedata/scripts/macro_lua.script | 6 +- src/xrGame/console_commands.cpp | 2 +- src/xrGame/vs2022/xrGame.vcxproj | 4 +- src/xrGame/vs2022/xrGame.vcxproj.filters | 21 ++-- src/xrServerEntities/script_compiler.cpp | 124 +++++++++++++++++++ src/xrServerEntities/script_compiler.h | 35 ++++++ src/xrServerEntities/script_engine.cpp | 6 +- src/xrServerEntities/script_macro.cpp | 7 +- src/xrServerEntities/script_macro.h | 6 +- src/xrServerEntities/script_macro_script.cpp | 1 - src/xrServerEntities/script_macro_wua.cpp | 14 ++- src/xrServerEntities/script_macro_wua.h | 3 +- src/xrServerEntities/script_macros.cpp | 69 ----------- src/xrServerEntities/script_macros.h | 31 ----- src/xrServerEntities/script_storage.cpp | 65 +--------- src/xrServerEntities/script_storage.h | 1 - src/xrServerEntities/script_thread.cpp | 6 +- 19 files changed, 199 insertions(+), 206 deletions(-) create mode 100644 src/xrServerEntities/script_compiler.cpp create mode 100644 src/xrServerEntities/script_compiler.h delete mode 100644 src/xrServerEntities/script_macros.cpp delete mode 100644 src/xrServerEntities/script_macros.h diff --git a/gamedata/scripts/macro_lisp.script b/gamedata/scripts/macro_lisp.script index 42499e839b..ced4878811 100644 --- a/gamedata/scripts/macro_lisp.script +++ b/gamedata/scripts/macro_lisp.script @@ -1,4 +1,4 @@ -function lisp(src, namespace_name, unlocs) +function expand(src, namespace_name, unlocs) -- Unlocalize if #unlocs then src = string.format( diff --git a/gamedata/scripts/macro_lisp_macro.script b/gamedata/scripts/macro_lisp_macro.script index 21ea0edd0d..86ef4381d8 100644 --- a/gamedata/scripts/macro_lisp_macro.script +++ b/gamedata/scripts/macro_lisp_macro.script @@ -1,4 +1,4 @@ -function lisp_macro(src, namespace_name) +function expand(src, namespace_name) return string.format( [==[ local fennel = require("fennel") diff --git a/gamedata/scripts/macro_lua.script b/gamedata/scripts/macro_lua.script index 713cf06c07..43b65f4ebf 100644 --- a/gamedata/scripts/macro_lua.script +++ b/gamedata/scripts/macro_lua.script @@ -1,6 +1,6 @@ -function lua(src, namespace_name, unlocalizer) +function expand(src, namespace_name, unlocalizer) return string.format( - [[ + [=[ local function f() local function script_name() return "%s" @@ -10,7 +10,7 @@ local function f() end package.loaded["%s"] = f() - ]], + ]=], namespace_name, src, namespace_name diff --git a/src/xrGame/console_commands.cpp b/src/xrGame/console_commands.cpp index 82945979a3..3d8e379c65 100644 --- a/src/xrGame/console_commands.cpp +++ b/src/xrGame/console_commands.cpp @@ -1713,7 +1713,7 @@ class CCC_ScriptCommand : public IConsole_Command string4096 S; shared_str m_script_name = "console command"; xr_sprintf(S, "%s\n", args); - bool loaded = ai().script_engine().load_buffer(ai().script_engine().lua(), NULL, S, xr_strlen(S), *m_script_name); + bool loaded = ai().script_engine().load_buffer(ai().script_engine().lua(), S, xr_strlen(S), *m_script_name); if (loaded) { int l_iErrorCode = lua_pcall(ai().script_engine().lua(), 0, 0, 0); diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index b59ddb07e0..6cf971e200 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -338,7 +338,7 @@ - + @@ -1966,7 +1966,7 @@ - + diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index a64b31da7e..b270dcdcd4 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -2498,6 +2498,7 @@ {c14ffa0c-947d-49b9-8e01-269569b48371} + {53abd459-f211-4178-b3c6-2be2afe329ba} @@ -7409,16 +7410,16 @@ - AI\AScript\ScriptDialect + AI\AScript\ScriptCompiler - - AI\AScript\ScriptDialect + + AI\AScript\ScriptCompiler - AI\AScript\ScriptDialect + AI\AScript\ScriptCompiler - AI\AScript\ScriptDialect + AI\AScript\ScriptCompiler @@ -11129,16 +11130,16 @@ - AI\AScript\ScriptDialect + AI\AScript\ScriptCompiler - - AI\AScript\ScriptDialect + + AI\AScript\ScriptCompiler - AI\AScript\ScriptDialect + AI\AScript\ScriptCompiler - AI\AScript\ScriptDialect + AI\AScript\ScriptCompiler diff --git a/src/xrServerEntities/script_compiler.cpp b/src/xrServerEntities/script_compiler.cpp new file mode 100644 index 0000000000..c15e13c865 --- /dev/null +++ b/src/xrServerEntities/script_compiler.cpp @@ -0,0 +1,124 @@ +#include "stdafx.h" +#include "script_compiler.h" +#include "ai_space.h" +#include "script_engine.h" +#include "../xrCore/mezz_stringbuffer.h" +#include "lua_macros.h" +#include "luabind/luabind.hpp" +#include +#include + +Unlocalizers unlocalizers; +CWuaMacro wua; + +void CScriptCompiler::load_unlocalizers() +{ + auto file_list = FS.file_list_open("$game_config$", "unlocalizers\\", FS_RootOnly | FS_ListFiles); + if (!file_list) { + return; + } + else { + xr_string id; + auto i = file_list->begin(); + auto e = file_list->end(); + for (; i != e; ++i) + { + u32 length = xr_strlen(*i); + + if (!((length >= 4) && + ((*i)[length - 4] == '.') && + ((*i)[length - 3] == 'l') && + ((*i)[length - 2] == 't') && + ((*i)[length - 1] == 'x'))) + continue; + + id.assign(*i, length - 4); + + string_path file_name; + FS.update_path(file_name, "$game_config$", (xr_string("unlocalizers\\") + id).c_str()); + xr_strcat(file_name, ".ltx"); + + Msg("opening file %s", file_name); + auto config = xr_new(file_name); + + typedef CInifile::Root sections_type; + sections_type& sections = config->sections(); + + sections_type::const_iterator i = sections.begin(); + sections_type::const_iterator e = sections.end(); + for (; i != e; ++i) + { + auto sectionName = std::string((*i)->Name.c_str()); + toLowerCase(sectionName); + if (unlocalizers.find(sectionName) == unlocalizers.end()) { + + // construct set that contains top level variables to delocalize by section name + unlocalizers[sectionName].clear(); + Msg("creating unlocalizer for script %s", sectionName.c_str()); + } + auto& data = (*i)->Data; + for (auto& item : data) { + unlocalizers[sectionName].insert(std::string(item.first.c_str())); + Msg("adding variable %s for unlocalizer for script %s", item.first.c_str(), sectionName.c_str()); + } + } + xr_delete(config); + } + FS.file_list_close(file_list); + } +} + +Unlocalizer* CScriptCompiler::get_unlocalizer(std::string name) +{ + toLowerCase(name); + if (unlocalizers.find(name) != unlocalizers.end()) + { + Msg("Found key %s in unlocalizers data", name); + return &unlocalizers[name]; + } + + return NULL; +} + +std::string CScriptCompiler::lift( + std::string caString, + LPCSTR caScriptName, + LPCSTR caNameSpaceName +) +{ + std::regex pattern(R"(#macro (.*)(\s+))"); + std::smatch match; + if (std::regex_search(caString, match, pattern)) + { + std::string macro_name = match[1]; + caString = std::string(match[2]) + std::string(match.suffix()); + if (macro_name != "wua") + { + luabind::functor macro; + if (ai().script_engine().functor((std::string("macro_") + macro_name).c_str(), macro)) + { + + luabind::object unlocs = luabind::newtable(ai().script_engine().lua()); + Unlocalizer* unlocalizer = get_unlocalizer(caNameSpaceName); + if (unlocalizer) + { + int i = 1; + for (auto unloc : *unlocalizer) + { + unlocs[i] = unloc.c_str(); + i++; + } + } + + return std::string(macro(caString.c_str(), caNameSpaceName, unlocs)); + } + else + { + Msg("No such macro: %s", macro_name); + FATAL("Failed to load macro"); + } + } + } + + return wua.lift(caString, caNameSpaceName); +} diff --git a/src/xrServerEntities/script_compiler.h b/src/xrServerEntities/script_compiler.h new file mode 100644 index 0000000000..de5c0ca230 --- /dev/null +++ b/src/xrServerEntities/script_compiler.h @@ -0,0 +1,35 @@ +#pragma once + +#include "stdafx.h" +#include "script_storage.h" +#include "script_macro.h" +#include "script_macro_wua.h" + +typedef std::set Unlocalizer; +typedef xr_unordered_map Unlocalizers; + +namespace luabind +{ + template + class functor; + + class object; +} // namespace luabind + +struct CScriptCompiler { +public: + void load_unlocalizers(); + Unlocalizer* CScriptCompiler::get_unlocalizer(std::string name); + + std::string lift( + std::string caString, + LPCSTR caScriptName, + LPCSTR caNameSpaceName = 0 + ); +}; + +static CScriptCompiler compiler; +static CScriptCompiler& ScriptCompiler() +{ + return compiler; +} \ No newline at end of file diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index f5ce574856..1ae8cd4fee 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -13,6 +13,7 @@ #include "script_process.h" #include "../build_config_defines.h" #include "script_storage.h" +#include "script_compiler.h" #include #include @@ -354,8 +355,6 @@ void CScriptEngine::setup_auto_load() } extern void export_classes(lua_State* L); -extern xr_unordered_map> unlocalizers; -extern bool unlocalizerPassed; void CScriptEngine::init() { @@ -402,8 +401,7 @@ void CScriptEngine::init() #endif // #ifndef USE_LUA_STUDIO // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); - unlocalizers.clear(); - unlocalizerPassed = false; + ScriptCompiler().load_unlocalizers(); bool save = m_reload_modules; m_reload_modules = true; process_file_if_exists("_G", false); diff --git a/src/xrServerEntities/script_macro.cpp b/src/xrServerEntities/script_macro.cpp index 18ab5bec6c..8871b45fc5 100644 --- a/src/xrServerEntities/script_macro.cpp +++ b/src/xrServerEntities/script_macro.cpp @@ -2,12 +2,7 @@ #include "script_macro.h" #include "lua_macros.h" -std::string CScriptMacro::lift(const std::string& src, LPCSTR caNameSpaceName) const -{ - return src; -} - -std::string CScriptMacro::unlocalize(const std::string& src, LPCSTR caNameSpaceName, Unlocalizer& unlocalizer) const +std::string CScriptMacro::lift(std::string src, LPCSTR caNameSpaceName) const { return src; } diff --git a/src/xrServerEntities/script_macro.h b/src/xrServerEntities/script_macro.h index 3af9283a2d..9cda3c8681 100644 --- a/src/xrServerEntities/script_macro.h +++ b/src/xrServerEntities/script_macro.h @@ -3,14 +3,10 @@ #include "script_export_space.h" #include -typedef std::set Unlocalizer; -typedef xr_unordered_map Unlocalizers; - class CScriptMacro : public DLL_Pure { public: - virtual std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName, Unlocalizer& unlocalizer) const; - virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const; + virtual std::string lift(std::string src, LPCSTR caNameSpaceName) const; DECLARE_SCRIPT_REGISTER_FUNCTION }; diff --git a/src/xrServerEntities/script_macro_script.cpp b/src/xrServerEntities/script_macro_script.cpp index 16b4678854..e2291ab835 100644 --- a/src/xrServerEntities/script_macro_script.cpp +++ b/src/xrServerEntities/script_macro_script.cpp @@ -10,7 +10,6 @@ void CScriptMacro::script_register(lua_State* L) module(L) [ class_("CScriptMacro") - .def("unlocalize", &CScriptMacro::unlocalize) .def("lift", &CScriptMacro::lift) ]; } diff --git a/src/xrServerEntities/script_macro_wua.cpp b/src/xrServerEntities/script_macro_wua.cpp index d2ee3cfb33..10fb2199dd 100644 --- a/src/xrServerEntities/script_macro_wua.cpp +++ b/src/xrServerEntities/script_macro_wua.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "script_macro_wua.h" +#include "script_compiler.h" #include "lua_macros.h" #include @@ -35,8 +36,12 @@ static std::string join_list(const std::vector& items_vec, std::str return ret; }; -std::string CWuaMacro::unlocalize(const std::string& src, LPCSTR caNameSpaceName, Unlocalizer& unlocalizer) const +std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName) { + Unlocalizer* unlocalizer = ScriptCompiler().get_unlocalizer(caNameSpaceName); + if (!unlocalizer) + return src; + bool unlocalPerformed = false; std::string unlocalizerResult; @@ -70,7 +75,7 @@ std::string CWuaMacro::unlocalize(const std::string& src, LPCSTR caNameSpaceName //local function x(a,b,c) pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); - if (unlocalRegex(unlocalizer, s, pattern, 5, "$3$4$5$6$7")) { + if (unlocalRegex(*unlocalizer, s, pattern, 5, "$3$4$5$6$7")) { //Msg("Regex matched"); unlocalPerformed = true; continue; @@ -103,7 +108,7 @@ std::string CWuaMacro::unlocalize(const std::string& src, LPCSTR caNameSpaceName for (auto v : variables) { trim(v); //Msg("%s\n", v.c_str()); - if (unlocalizer.find(v) != unlocalizer.end()) { + if (unlocalizer->find(v) != unlocalizer->end()) { unlocalPerformed = true; Msg("found variable %s to unlocal", v.c_str()); s = std::regex_replace(s, pattern, "$3"); @@ -140,8 +145,9 @@ std::string CWuaMacro::unlocalize(const std::string& src, LPCSTR caNameSpaceName return src; } -std::string CWuaMacro::lift(const std::string& src, LPCSTR caNameSpaceName) const +std::string CWuaMacro::lift(std::string src, LPCSTR caNameSpaceName) const { + src = unlocalize(src, caNameSpaceName); bool is_g = caNameSpaceName && xr_strcmp(caNameSpaceName, "_G") == 0; std::string out; out += wua_environment("G"); diff --git a/src/xrServerEntities/script_macro_wua.h b/src/xrServerEntities/script_macro_wua.h index 2ad99a5917..d0853a4911 100644 --- a/src/xrServerEntities/script_macro_wua.h +++ b/src/xrServerEntities/script_macro_wua.h @@ -5,6 +5,5 @@ class CWuaMacro : public CScriptMacro { public: - virtual std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName, Unlocalizer& unlocalizer) const override; - virtual std::string lift(const std::string& src, LPCSTR caNameSpaceName) const override; + virtual std::string lift(std::string src, LPCSTR caNameSpaceName) const override; }; diff --git a/src/xrServerEntities/script_macros.cpp b/src/xrServerEntities/script_macros.cpp deleted file mode 100644 index b822084e56..0000000000 --- a/src/xrServerEntities/script_macros.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "stdafx.h" -#include "script_macros.h" -#include "ai_space.h" -#include "script_engine.h" -#include "../xrCore/mezz_stringbuffer.h" -#include "lua_macros.h" -#include "luabind/luabind.hpp" -#include -#include - -std::string CScriptMacros::lift( - std::string caString, - LPCSTR caScriptName, - LPCSTR caNameSpaceName, - Unlocalizers* unlocalizers -) const -{ - Unlocalizer* unlocalizer = NULL; - if (caNameSpaceName) - { - std::string loweredNameSpaceName; - loweredNameSpaceName += caNameSpaceName; - toLowerCase(loweredNameSpaceName); - if (unlocalizers && unlocalizers->find(loweredNameSpaceName) != unlocalizers->end()) - { - Msg("found script %s in unlocalizers data", caNameSpaceName); - // Iterate lines and unlocalize variables - unlocalizer = &(*unlocalizers)[loweredNameSpaceName]; - } - } - - std::regex pattern(R"(#macro (.*)(\s+))"); - std::smatch match; - if (std::regex_search(caString, match, pattern)) - { - std::string macro_name = match[1]; - caString = std::string(match[2]) + std::string(match.suffix()); - if (macro_name != "wua") - { - luabind::functor macro; - if (ai().script_engine().functor(string_format("macro_%s.%s", macro_name, macro_name).c_str(), macro)) - { - - luabind::object unlocs = luabind::newtable(ai().script_engine().lua()); - if (unlocalizer) - { - int i = 1; - for (auto unloc : *unlocalizer) - { - unlocs[i] = unloc.c_str(); - i++; - } - } - - return std::string(macro(caString.c_str(), caNameSpaceName, unlocs)); - } - else - { - Msg("No such macro: %s", macro_name); - FATAL("Failed to load macro"); - } - } - } - - if (unlocalizer) - caString = wua.unlocalize(caString, caNameSpaceName, *unlocalizer); - - return wua.lift(caString, caNameSpaceName); -} diff --git a/src/xrServerEntities/script_macros.h b/src/xrServerEntities/script_macros.h deleted file mode 100644 index 8639ae2208..0000000000 --- a/src/xrServerEntities/script_macros.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "stdafx.h" -#include "script_storage.h" -#include "script_macro.h" -#include "script_macro_wua.h" - -namespace luabind -{ - template - class functor; - - class object; -} // namespace luabind - -struct CScriptMacros { - CWuaMacro wua; - - std::string lift( - std::string caString, - LPCSTR caScriptName, - LPCSTR caNameSpaceName = 0, - Unlocalizers* unlocalizers = 0 - ) const; -}; - -static CScriptMacros macros; -static const CScriptMacros& ScriptMacros() -{ - return macros; -} \ No newline at end of file diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index 225a35f077..2a5cb6293f 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -8,7 +8,7 @@ #include "pch_script.h" #include "script_storage.h" -#include "script_macros.h" +#include "script_compiler.h" #include "script_thread.h" #include "../xrCore/mezz_stringbuffer.h" #include @@ -555,12 +555,8 @@ int __cdecl CScriptStorage::script_log(ScriptStorage::ELuaMessageType tLuaMessag return (result); } -Unlocalizers unlocalizers; -bool unlocalizerPassed = false; - bool CScriptStorage::load_buffer( lua_State* L, - Unlocalizers* unlocalizers, LPCSTR caBuffer, size_t tSize, LPCSTR caScriptName, @@ -568,7 +564,7 @@ bool CScriptStorage::load_buffer( ) { std::string caString(caBuffer, caBuffer + tSize); - caString = ScriptMacros().lift(caString, caScriptName, caNameSpaceName, unlocalizers); + caString = ScriptCompiler().lift(caString, caScriptName, caNameSpaceName); int l_iErrorCode = luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); if (l_iErrorCode) @@ -584,61 +580,6 @@ bool CScriptStorage::load_buffer( bool CScriptStorage::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) { - if (!unlocalizerPassed) { - auto file_list = FS.file_list_open("$game_config$", "unlocalizers\\", FS_RootOnly | FS_ListFiles); - if (!file_list) { - unlocalizerPassed = true; - } else { - xr_string id; - auto i = file_list->begin(); - auto e = file_list->end(); - for (; i != e; ++i) - { - u32 length = xr_strlen(*i); - - if (!((length >= 4) && - ((*i)[length - 4] == '.') && - ((*i)[length - 3] == 'l') && - ((*i)[length - 2] == 't') && - ((*i)[length - 1] == 'x'))) - continue; - - id.assign(*i, length - 4); - - string_path file_name; - FS.update_path(file_name, "$game_config$", (xr_string("unlocalizers\\") + id).c_str()); - xr_strcat(file_name, ".ltx"); - - Msg("opening file %s", file_name); - auto config = xr_new(file_name); - - typedef CInifile::Root sections_type; - sections_type& sections = config->sections(); - - sections_type::const_iterator i = sections.begin(); - sections_type::const_iterator e = sections.end(); - for (; i != e; ++i) - { - auto sectionName = std::string((*i)->Name.c_str()); - toLowerCase(sectionName); - if (unlocalizers.find(sectionName) == unlocalizers.end()) { - - // construct set that contains top level variables to delocalize by section name - unlocalizers[sectionName].clear(); - Msg("creating unlocalizer for script %s", sectionName.c_str()); - } - auto& data = (*i)->Data; - for (auto& item : data) { - unlocalizers[sectionName].insert(std::string(item.first.c_str())); - Msg("adding variable %s for unlocalizer for script %s", item.first.c_str(), sectionName.c_str()); - } - } - xr_delete(config); - } - FS.file_list_close(file_list); - unlocalizerPassed = true; - } - } int start = lua_gettop(lua()); string_path l_caLuaFileName; IReader* l_tpFileReader = FS.r_open(caScriptName); @@ -654,7 +595,7 @@ bool CScriptStorage::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) bool bufferLoaded = false; strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); - bufferLoaded = load_buffer(lua(), &unlocalizers, scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName); + bufferLoaded = load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName); if (!bufferLoaded) { diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h index 7e0a1c0087..788dd89160 100644 --- a/src/xrServerEntities/script_storage.h +++ b/src/xrServerEntities/script_storage.h @@ -87,7 +87,6 @@ class CScriptStorage IC CScriptThread* current_thread() const; bool load_buffer( lua_State* L, - Unlocalizers* unlocalizers, LPCSTR caBuffer, size_t tSize, LPCSTR caScriptName, diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp index 493c8aa3ad..ba31046ab4 100644 --- a/src/xrServerEntities/script_thread.cpp +++ b/src/xrServerEntities/script_thread.cpp @@ -14,7 +14,7 @@ };*/ //-AVO #include "script_engine.h" -#include "script_macros.h" +#include "script_compiler.h" #include "script_thread.h" #include "ai_space.h" @@ -57,7 +57,7 @@ CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string, bool reload) { m_script_name = "console command"; S += caBuffer; - S = ScriptMacros().lift(S, *m_script_name); + S = ScriptCompiler().lift(S, *m_script_name); S = "function " + std::string(main_function) + "()\n" + S + "\nend"; int l_iErrorCode = luaL_loadbuffer(ai().script_engine().lua(), S.c_str(), S.length(), "@console_command"); if (!l_iErrorCode) @@ -114,7 +114,7 @@ CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string, bool reload) else S = std::string(main_function) + "()"; - if (!ai().script_engine().load_buffer(lua(), NULL, S.c_str(), S.length(), "@_thread_main")) + if (!ai().script_engine().load_buffer(lua(), S.c_str(), S.length(), "@_thread_main")) return; m_active = true; From e1ca36b80a18893f9bc847fab50c560916cce2c3 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 20 May 2025 06:57:00 +0100 Subject: [PATCH 13/76] Macro hygeine pass - Switch macro output from string to Lua function - Rewrite existing macros with Lua metaprogramming - Refactor lisp_macro loading to compile eagerly, populate `package.loaded` as well as fennel macro storage - Rewrite lisp macro to manipulate AST --- gamedata/scripts/macro.script | 10 +++ gamedata/scripts/macro_lisp.script | 102 ++++++++++++++-------- gamedata/scripts/macro_lisp_macro.script | 48 ++++------ gamedata/scripts/macro_lua.script | 24 ++--- src/xrServerEntities/script_compiler.cpp | 12 ++- src/xrServerEntities/script_compiler.h | 3 +- src/xrServerEntities/script_macro_wua.cpp | 3 + src/xrServerEntities/script_storage.cpp | 10 ++- src/xrServerEntities/script_thread.cpp | 12 +-- 9 files changed, 125 insertions(+), 99 deletions(-) create mode 100644 gamedata/scripts/macro.script diff --git a/gamedata/scripts/macro.script b/gamedata/scripts/macro.script new file mode 100644 index 0000000000..0b4b52013b --- /dev/null +++ b/gamedata/scripts/macro.script @@ -0,0 +1,10 @@ +function load_src(src) + return assert(loadstring(src)) +end + +function extend_env(dest) + for k,v in pairs(getfenv(0)) do + dest[k] = v + end + return dest +end \ No newline at end of file diff --git a/gamedata/scripts/macro_lisp.script b/gamedata/scripts/macro_lisp.script index ced4878811..e25e7c4d5a 100644 --- a/gamedata/scripts/macro_lisp.script +++ b/gamedata/scripts/macro_lisp.script @@ -1,37 +1,71 @@ -function expand(src, namespace_name, unlocs) - -- Unlocalize - if #unlocs then - src = string.format( - [[ -(import-macros {: unlocalize} :lisp_unlocalize) -(unlocalize - [%s] - %s) - ]], - table.concat(unlocs, " "), - src - ) +COMPILER_OPTS = { + allowedGlobals = false, + correlate = true, + useBitLib = true, + ["error-pinpoint"] = false, +} + +function make_compiler_opts(env) + local opts = { env = env } + for k,v in pairs(COMPILER_OPTS) do + opts[k] = v end + return opts +end + +function fennel_form(src) + local _, form = assert( + fennel.parser(src)() + ) + return form +end - -- Wrap into lisp compiler - return string.format( - [==[ -package.loaded["%s"] = require("fennel").eval( - [=[ -(fn script_name [] - "%s") -%s - ]=], - { - allowedGlobals = false, - correlate = true, - useBitLib = true, - ["error-pinpoint"] = false, - } -) - ]==], - namespace_name, - namespace_name, - src - ); +function fennel_forms(src) + local forms = {} + for ok, form in fennel.parser(src) do + assert(ok, "Invalid form") + table.insert(forms, form) + end + return forms +end + +function fennel_list(lst) + return fennel_form("[" .. table.concat(lst, " ") .. "]") +end + +function fennel_eval_ast(ast, opts) + local env = opts.env + opts.env = nil + + return fennel.loadCode( + fennel.compile( + ast, + opts + ), + env + )() +end + +function compile(src, namespace_name, unlocs) + return function() + local ast = fennel_forms(src) + + if #unlocs then + ast = lisp_unlocalize.unlocalize( + fennel_list(unlocs), + unpack(ast) + ) + end + + package.loaded[namespace_name] = fennel_eval_ast( + ast, + make_compiler_opts( + macro.extend_env { + script_name = function() + return namespace_name + end + } + ) + ) + end end diff --git a/gamedata/scripts/macro_lisp_macro.script b/gamedata/scripts/macro_lisp_macro.script index 86ef4381d8..0c5667897d 100644 --- a/gamedata/scripts/macro_lisp_macro.script +++ b/gamedata/scripts/macro_lisp_macro.script @@ -1,32 +1,18 @@ -function expand(src, namespace_name) - return string.format( - [==[ -local fennel = require("fennel") -table.insert( - fennel["macro-searchers"], - function(module_name) - if module_name ~= "%s" then - return - end - return function() - return fennel.eval( - [=[ - %s - ]=], - { - correlate = true, - env = "_COMPILER", - useBitLib = true, - ["error-pinpoint"] = false, - } - ) - end - end -) -package.loaded["%s"] = {} - ]==], - namespace_name, - src, - namespace_name - ) +COMPILER_OPTS = { + correlate = true, + env = "_COMPILER", + useBitLib = true, + ["error-pinpoint"] = false, +} + +function compile(src, namespace_name) + return function() + local macros = fennel.eval( + src, + COMPILER_OPTS + ) + + package.loaded[namespace_name] = macros + fennel["macro-loaded"][namespace_name] = macros + end end diff --git a/gamedata/scripts/macro_lua.script b/gamedata/scripts/macro_lua.script index 43b65f4ebf..248c9ce450 100644 --- a/gamedata/scripts/macro_lua.script +++ b/gamedata/scripts/macro_lua.script @@ -1,18 +1,12 @@ function expand(src, namespace_name, unlocalizer) - return string.format( - [=[ -local function f() - local function script_name() - return "%s" + return function() + package.loaded[namespace_name] = setfenv( + macro.load_src(src), + macro.extend_env { + script_name = function() + return namespace_name + end + } + )() end - - %s -end - -package.loaded["%s"] = f() - ]=], - namespace_name, - src, - namespace_name - ) end diff --git a/src/xrServerEntities/script_compiler.cpp b/src/xrServerEntities/script_compiler.cpp index c15e13c865..7da4816dc9 100644 --- a/src/xrServerEntities/script_compiler.cpp +++ b/src/xrServerEntities/script_compiler.cpp @@ -80,7 +80,8 @@ Unlocalizer* CScriptCompiler::get_unlocalizer(std::string name) return NULL; } -std::string CScriptCompiler::lift( +int CScriptCompiler::compile( + lua_State* L, std::string caString, LPCSTR caScriptName, LPCSTR caNameSpaceName @@ -94,7 +95,7 @@ std::string CScriptCompiler::lift( caString = std::string(match[2]) + std::string(match.suffix()); if (macro_name != "wua") { - luabind::functor macro; + luabind::functor macro; if (ai().script_engine().functor((std::string("macro_") + macro_name).c_str(), macro)) { @@ -110,7 +111,9 @@ std::string CScriptCompiler::lift( } } - return std::string(macro(caString.c_str(), caNameSpaceName, unlocs)); + luabind::object result = macro(caString.c_str(), caNameSpaceName, unlocs); + result.pushvalue(); + return 0; } else { @@ -120,5 +123,6 @@ std::string CScriptCompiler::lift( } } - return wua.lift(caString, caNameSpaceName); + caString = wua.lift(caString, caNameSpaceName); + return luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); } diff --git a/src/xrServerEntities/script_compiler.h b/src/xrServerEntities/script_compiler.h index de5c0ca230..bda8c928c0 100644 --- a/src/xrServerEntities/script_compiler.h +++ b/src/xrServerEntities/script_compiler.h @@ -21,7 +21,8 @@ struct CScriptCompiler { void load_unlocalizers(); Unlocalizer* CScriptCompiler::get_unlocalizer(std::string name); - std::string lift( + int compile( + lua_State* L, std::string caString, LPCSTR caScriptName, LPCSTR caNameSpaceName = 0 diff --git a/src/xrServerEntities/script_macro_wua.cpp b/src/xrServerEntities/script_macro_wua.cpp index 10fb2199dd..5dd931de14 100644 --- a/src/xrServerEntities/script_macro_wua.cpp +++ b/src/xrServerEntities/script_macro_wua.cpp @@ -38,6 +38,9 @@ static std::string join_list(const std::vector& items_vec, std::str std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName) { + if (!caNameSpaceName) + return src; + Unlocalizer* unlocalizer = ScriptCompiler().get_unlocalizer(caNameSpaceName); if (!unlocalizer) return src; diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index 2a5cb6293f..5c72ece43a 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -563,10 +563,12 @@ bool CScriptStorage::load_buffer( LPCSTR caNameSpaceName ) { - std::string caString(caBuffer, caBuffer + tSize); - caString = ScriptCompiler().lift(caString, caScriptName, caNameSpaceName); - - int l_iErrorCode = luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); + int l_iErrorCode = ScriptCompiler().compile( + L, + std::string(caBuffer, caBuffer + tSize), + caScriptName, + caNameSpaceName + ); if (l_iErrorCode) { //#ifdef DEBUG diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp index ba31046ab4..10647e3511 100644 --- a/src/xrServerEntities/script_thread.cpp +++ b/src/xrServerEntities/script_thread.cpp @@ -57,18 +57,10 @@ CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string, bool reload) { m_script_name = "console command"; S += caBuffer; - S = ScriptCompiler().lift(S, *m_script_name); - S = "function " + std::string(main_function) + "()\n" + S + "\nend"; - int l_iErrorCode = luaL_loadbuffer(ai().script_engine().lua(), S.c_str(), S.length(), "@console_command"); + int l_iErrorCode = ScriptCompiler().compile(ai().script_engine().lua(), S, "@console_command"); if (!l_iErrorCode) { - l_iErrorCode = lua_pcall(ai().script_engine().lua(), 0, 0, 0); - if (l_iErrorCode) - { - ai().script_engine().print_output(ai().script_engine().lua(), *m_script_name, l_iErrorCode); - ai().script_engine().on_error(ai().script_engine().lua()); - return; - } + lua_setglobal(ai().script_engine().lua(), main_function); } else { From f26f936e246c938479d290d9f00eac144006e1e2 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 21 May 2025 20:23:30 +0100 Subject: [PATCH 14/76] Move `CScriptStorage::object` into `CScriptEngine` --- src/xrServerEntities/script_engine.cpp | 34 +++++++++++++++++++++++++ src/xrServerEntities/script_engine.h | 4 +++ src/xrServerEntities/script_storage.cpp | 34 ------------------------- src/xrServerEntities/script_storage.h | 2 -- 4 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 1ae8cd4fee..211ecc6420 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -545,6 +545,40 @@ void CScriptEngine::register_script_classes() } } +bool CScriptEngine::object(LPCSTR identifier, int type) +{ + int start = lua_gettop(lua()); + lua_pushnil(lua()); + while (lua_next(lua(), -2)) + { + if ((lua_type(lua(), -1) == type) && !xr_strcmp(identifier, lua_tostring(lua(), -2))) + { + VERIFY(lua_gettop(lua()) >= 3); + lua_pop(lua(), 3); + VERIFY(lua_gettop(lua()) == start - 1); + return (true); + } + lua_pop(lua(), 1); + } + VERIFY(lua_gettop(lua()) >= 1); + lua_pop(lua(), 1); + VERIFY(lua_gettop(lua()) == start - 1); + return (false); +} + +bool CScriptEngine::object(LPCSTR namespace_name, LPCSTR identifier, int type) +{ + int start = lua_gettop(lua()); + if (xr_strlen(namespace_name) && !namespace_loaded(namespace_name, false)) + { + VERIFY(lua_gettop(lua()) == start); + return (false); + } + bool result = object(identifier, type); + VERIFY(lua_gettop(lua()) == start); + return (result); +} + bool CScriptEngine::function_object(LPCSTR function_to_call, luabind::object& object, int type) { if (!xr_strlen(function_to_call)) diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index 9b7101b393..3b47619442 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -97,6 +97,10 @@ class CScriptEngine : public CScriptStorage bool process_file_if_exists(LPCSTR file_name, bool warn_if_not_exist); void process_file(LPCSTR file_name); void process_file(LPCSTR file_name, bool reload_modules); +protected: + bool object(LPCSTR caIdentifier, int type); + bool object(LPCSTR caNamespaceName, LPCSTR caIdentifier, int type); +public: bool function_object(LPCSTR function_to_call, luabind::object& object, int type = LUA_TFUNCTION); void register_script_classes(); IC void parse_script_namespace(LPCSTR function_to_call, LPSTR name_space, u32 const namespace_size, LPSTR function, diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index 5c72ece43a..1ae786182c 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -717,41 +717,7 @@ bool CScriptStorage::namespace_loaded(LPCSTR N, bool remove_from_stack) VERIFY(lua_gettop(lua()) == start); } return (true); -} - -bool CScriptStorage::object(LPCSTR identifier, int type) -{ - int start = lua_gettop(lua()); - lua_pushnil(lua()); - while (lua_next(lua(), -2)) - { - if ((lua_type(lua(), -1) == type) && !xr_strcmp(identifier, lua_tostring(lua(), -2))) - { - VERIFY(lua_gettop(lua()) >= 3); - lua_pop(lua(), 3); - VERIFY(lua_gettop(lua()) == start - 1); - return (true); } - lua_pop(lua(), 1); - } - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(lua_gettop(lua()) == start - 1); - return (false); -} - -bool CScriptStorage::object(LPCSTR namespace_name, LPCSTR identifier, int type) -{ - int start = lua_gettop(lua()); - if (xr_strlen(namespace_name) && !namespace_loaded(namespace_name, false)) - { - VERIFY(lua_gettop(lua()) == start); - return (false); - } - bool result = object(identifier, type); - VERIFY(lua_gettop(lua()) == start); - return (result); -} luabind::object CScriptStorage::name_space(LPCSTR namespace_name) { diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h index 788dd89160..2fa4806668 100644 --- a/src/xrServerEntities/script_storage.h +++ b/src/xrServerEntities/script_storage.h @@ -94,8 +94,6 @@ class CScriptStorage ); bool load_file_into_namespace(LPCSTR caScriptName, LPCSTR caNamespaceName); bool namespace_loaded(LPCSTR caName, bool remove_from_stack = true); - bool object(LPCSTR caIdentifier, int type); - bool object(LPCSTR caNamespaceName, LPCSTR caIdentifier, int type); luabind::object name_space(LPCSTR namespace_name); int error_log(LPCSTR caFormat, ...); static int __cdecl script_log(ELuaMessageType message, LPCSTR caFormat, ...); From 9c2bdb41f6ceb32b559ecd4e71deb9435c06b74a Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 21 May 2025 20:37:38 +0100 Subject: [PATCH 15/76] Implement direct package unloading --- src/xrServerEntities/script_engine.cpp | 24 +++++++++++------------- src/xrServerEntities/script_engine.h | 5 +---- src/xrServerEntities/script_process.cpp | 5 ++++- src/xrServerEntities/script_thread.cpp | 4 ++-- src/xrServerEntities/script_thread.h | 2 +- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 211ecc6420..65deeaca75 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -138,7 +138,6 @@ void CScriptEngine::disconnect_from_debugger () CScriptEngine::CScriptEngine() { m_stack_level = 0; - m_reload_modules = false; m_last_no_file_length = 0; *m_last_no_file = 0; @@ -402,10 +401,7 @@ void CScriptEngine::init() // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); ScriptCompiler().load_unlocalizers(); - bool save = m_reload_modules; - m_reload_modules = true; process_file_if_exists("_G", false); - m_reload_modules = save; register_script_classes(); object_factory().register_script(); @@ -426,6 +422,16 @@ void CScriptEngine::remove_script_process(const EScriptProcessors& process_id) } } +void CScriptEngine::unload_package(LPCSTR name) +{ + lua_getglobal(lua(), "package"); + lua_getfield(lua(), -1, "loaded"); + lua_remove(lua(), -2); + lua_pushnil(lua()); + lua_setfield(lua(), -2, name); + lua_remove(lua(), -1); +} + void CScriptEngine::load_common_scripts() { #ifdef DBG_DISABLE_SCRIPTS @@ -470,7 +476,7 @@ bool CScriptEngine::process_file_if_exists(LPCSTR file_name, bool warn_if_not_ex return false; string_path S, S1; - if (m_reload_modules || (*file_name && !namespace_loaded(file_name))) + if (0 == xr_strcmp(file_name, "_G") || * file_name && !namespace_loaded(file_name)) { FS.update_path(S, "$game_scripts$", strconcat(sizeof(S1), S1, file_name, ".script")); if (!warn_if_not_exist && !FS.exist(S)) @@ -492,7 +498,6 @@ bool CScriptEngine::process_file_if_exists(LPCSTR file_name, bool warn_if_not_ex if (strstr(Core.Params, "-dbg")) Msg("* loading script %s", S1); //#endif // MASTER_GOLD - m_reload_modules = false; return load_file_into_namespace(S, *file_name ? file_name : "_G"); } @@ -504,13 +509,6 @@ void CScriptEngine::process_file(LPCSTR file_name) process_file_if_exists(file_name, true); } -void CScriptEngine::process_file(LPCSTR file_name, bool reload_modules) -{ - m_reload_modules = reload_modules; - process_file_if_exists(file_name, true); - m_reload_modules = false; -} - void CScriptEngine::register_script_classes() { #ifdef DBG_DISABLE_SCRIPTS diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index 3b47619442..162ec8524a 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -51,9 +51,6 @@ class CScriptEngine : public CScriptStorage typedef ScriptEngine::EScriptProcessors EScriptProcessors; typedef associative_vector CScriptProcessStorage; -private: - bool m_reload_modules; - protected: CScriptProcessStorage m_script_processes; int m_stack_level; @@ -94,9 +91,9 @@ class CScriptEngine : public CScriptStorage IC void add_script_process(const EScriptProcessors& process_id, CScriptProcess* script_process); void remove_script_process(const EScriptProcessors& process_id); void setup_auto_load(); + void unload_package(LPCSTR package); bool process_file_if_exists(LPCSTR file_name, bool warn_if_not_exist); void process_file(LPCSTR file_name); - void process_file(LPCSTR file_name, bool reload_modules); protected: bool object(LPCSTR caIdentifier, int type); bool object(LPCSTR caNamespaceName, LPCSTR caIdentifier, int type); diff --git a/src/xrServerEntities/script_process.cpp b/src/xrServerEntities/script_process.cpp index 7daf32c5ca..f38dbfd294 100644 --- a/src/xrServerEntities/script_process.cpp +++ b/src/xrServerEntities/script_process.cpp @@ -45,7 +45,10 @@ void CScriptProcess::run_scripts() S = xr_strdup(I); m_scripts_to_run.pop_back(); - CScriptThread* script = xr_new(S, do_string, reload); + if (reload) + ai().script_engine().unload_package(S); + + CScriptThread* script = xr_new(S, do_string); xr_free(S); if (script->active()) diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp index 10647e3511..cd5f285b93 100644 --- a/src/xrServerEntities/script_thread.cpp +++ b/src/xrServerEntities/script_thread.cpp @@ -39,7 +39,7 @@ const LPCSTR main_function = "console_command_run_string_main_thread_function"; //extern "C" __declspec(dllimport) lua_State *lua_newcthread(lua_State *OL, int cstacksize); -CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string, bool reload) +CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string) { m_virtual_machine = 0; m_active = false; @@ -51,7 +51,7 @@ CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string, bool reload) if (!do_string) { m_script_name = caBuffer; - ai().script_engine().process_file(caBuffer, reload); + ai().script_engine().process_file(caBuffer); } else { diff --git a/src/xrServerEntities/script_thread.h b/src/xrServerEntities/script_thread.h index 67012ed778..67d290071f 100644 --- a/src/xrServerEntities/script_thread.h +++ b/src/xrServerEntities/script_thread.h @@ -32,7 +32,7 @@ class CScriptThread #endif public: - CScriptThread(LPCSTR caNamespaceName, bool do_string = false, bool reload = false); + CScriptThread(LPCSTR caNamespaceName, bool do_string = false); virtual ~CScriptThread(); bool update(); IC bool active() const; From 318992ed31e3a7ba6b3506e9ce05b7d9bbd21ce7 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 21 May 2025 21:06:57 +0100 Subject: [PATCH 16/76] Return error code instead of bool from `load_buffer` --- src/xrGame/console_commands.cpp | 3 +-- src/xrServerEntities/script_storage.cpp | 10 +++------- src/xrServerEntities/script_storage.h | 2 +- src/xrServerEntities/script_thread.cpp | 2 +- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/xrGame/console_commands.cpp b/src/xrGame/console_commands.cpp index 3d8e379c65..0a6a2ee572 100644 --- a/src/xrGame/console_commands.cpp +++ b/src/xrGame/console_commands.cpp @@ -1713,8 +1713,7 @@ class CCC_ScriptCommand : public IConsole_Command string4096 S; shared_str m_script_name = "console command"; xr_sprintf(S, "%s\n", args); - bool loaded = ai().script_engine().load_buffer(ai().script_engine().lua(), S, xr_strlen(S), *m_script_name); - if (loaded) + if (0 == ai().script_engine().load_buffer(ai().script_engine().lua(), S, xr_strlen(S), *m_script_name)) { int l_iErrorCode = lua_pcall(ai().script_engine().lua(), 0, 0, 0); if (l_iErrorCode) diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index 1ae786182c..81930dce52 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -555,7 +555,7 @@ int __cdecl CScriptStorage::script_log(ScriptStorage::ELuaMessageType tLuaMessag return (result); } -bool CScriptStorage::load_buffer( +int CScriptStorage::load_buffer( lua_State* L, LPCSTR caBuffer, size_t tSize, @@ -575,9 +575,8 @@ bool CScriptStorage::load_buffer( if (strstr(Core.Params, "-dbg")) print_output(L,caScriptName,l_iErrorCode); //#endif //-DEBUG on_error(L); - return (false); } - return (true); + return l_iErrorCode; } bool CScriptStorage::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) @@ -595,11 +594,8 @@ bool CScriptStorage::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) auto scriptContents = static_cast(l_tpFileReader->pointer()); auto scriptLength = (size_t)l_tpFileReader->length(); - bool bufferLoaded = false; strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); - bufferLoaded = load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName); - - if (!bufferLoaded) + if (load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName)) { // VERIFY (lua_gettop(lua()) >= 4); // lua_pop (lua(),4); diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h index 2fa4806668..0155755399 100644 --- a/src/xrServerEntities/script_storage.h +++ b/src/xrServerEntities/script_storage.h @@ -85,7 +85,7 @@ class CScriptStorage IC lua_State* lua(); IC void current_thread(CScriptThread* thread); IC CScriptThread* current_thread() const; - bool load_buffer( + int load_buffer( lua_State* L, LPCSTR caBuffer, size_t tSize, diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp index cd5f285b93..397140fa13 100644 --- a/src/xrServerEntities/script_thread.cpp +++ b/src/xrServerEntities/script_thread.cpp @@ -106,7 +106,7 @@ CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string) else S = std::string(main_function) + "()"; - if (!ai().script_engine().load_buffer(lua(), S.c_str(), S.length(), "@_thread_main")) + if (ai().script_engine().load_buffer(lua(), S.c_str(), S.length(), "@_thread_main")) return; m_active = true; From 86e4e069d8e47c9f853eae659a93c123691a69c6 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 21 May 2025 21:09:49 +0100 Subject: [PATCH 17/76] Improve error checking / reporting for `namespace_loaded` --- src/xrServerEntities/script_storage.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index 81930dce52..51900e8d55 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -660,7 +660,9 @@ bool CScriptStorage::namespace_loaded(LPCSTR N, bool remove_from_stack) { int start = lua_gettop(lua()); lua_getglobal(lua(), "package"); + VERIFY(lua_istable(lua(), -1)); lua_getfield(lua(), -1, "loaded"); + VERIFY(lua_istable(lua(), -1)); lua_remove(lua(), -2); string256 S2; xr_strcpy(S2, N); @@ -689,11 +691,12 @@ bool CScriptStorage::namespace_loaded(LPCSTR N, bool remove_from_stack) } else if (!lua_istable(lua(), -1)) { + std::string tn(lua_typename(lua(), -1)); // lua_settop (lua(),0); VERIFY(lua_gettop(lua()) >= 1); lua_pop(lua(), 1); VERIFY(start == lua_gettop(lua())); - FATAL(" Error : the namespace name is already being used by the non-table object!\n"); + FATAL((std::string("Error : the namespace name ") + N + " is already being used by non-table object of type " + tn + "\n").c_str()); return (false); } lua_remove(lua(), -2); From c56f05df1f98f764a785b51b8a6b43e24ba5dc46 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 21 May 2025 21:28:26 +0100 Subject: [PATCH 18/76] Run `init` before `_G`, use to implement Lua `print` --- gamedata/scripts/_init.script | 26 ++++++++++++++++++++++++++ src/xrServerEntities/script_engine.cpp | 1 + 2 files changed, 27 insertions(+) create mode 100644 gamedata/scripts/_init.script diff --git a/gamedata/scripts/_init.script b/gamedata/scripts/_init.script new file mode 100644 index 0000000000..6cd6ac8330 --- /dev/null +++ b/gamedata/scripts/_init.script @@ -0,0 +1,26 @@ +function print(...) + local str = "" + for _,v in ipairs({...}) do + if #str > 0 then + str = str .. " " + end + + local s = nil + if (type(v) == 'userdata') then + s = 'userdata' + else + s = tostring(v) + end + + str = str .. s + end + + if (log) then + log(str) + else + get_console():execute("load ~#debug msg:" .. str) + end +end + +print("Lua initializing...") +print("package.loaded._G:", package.loaded._G) diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 65deeaca75..13abb408c6 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -401,6 +401,7 @@ void CScriptEngine::init() // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); ScriptCompiler().load_unlocalizers(); + process_file_if_exists("_init", false); process_file_if_exists("_G", false); register_script_classes(); From c714adfe7a9871a0fa6df559fcad2b46a3962a23 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 21 May 2025 22:30:06 +0100 Subject: [PATCH 19/76] Move script compiler internals to Lua --- gamedata/scripts/_init.script | 2 + gamedata/scripts/script_compiler.script | 42 +++++++ src/xrGame/vs2022/xrGame.vcxproj | 2 - src/xrGame/vs2022/xrGame.vcxproj.filters | 6 - .../{script_macro_wua.cpp => macro_wua.h} | 38 ++++-- src/xrServerEntities/script_compiler.cpp | 111 ++---------------- src/xrServerEntities/script_compiler.h | 7 -- src/xrServerEntities/script_engine.cpp | 1 - src/xrServerEntities/script_macro_script.cpp | 4 +- src/xrServerEntities/script_macro_wua.h | 9 -- 10 files changed, 82 insertions(+), 140 deletions(-) create mode 100644 gamedata/scripts/script_compiler.script rename src/xrServerEntities/{script_macro_wua.cpp => macro_wua.h} (83%) delete mode 100644 src/xrServerEntities/script_macro_wua.h diff --git a/gamedata/scripts/_init.script b/gamedata/scripts/_init.script index 6cd6ac8330..7e9df81b73 100644 --- a/gamedata/scripts/_init.script +++ b/gamedata/scripts/_init.script @@ -24,3 +24,5 @@ end print("Lua initializing...") print("package.loaded._G:", package.loaded._G) + +require("script_compiler").set_default_macro(compile_wua) \ No newline at end of file diff --git a/gamedata/scripts/script_compiler.script b/gamedata/scripts/script_compiler.script new file mode 100644 index 0000000000..336fa8a285 --- /dev/null +++ b/gamedata/scripts/script_compiler.script @@ -0,0 +1,42 @@ +TAG_MACRO = "#macro " + +local state = { + default_macro = nil +} + +function compile(src, script_name, namespace_name) + print("compile", script_name, namespace_name) + + if string.sub(src, 1, #TAG_MACRO) == TAG_MACRO then + src = string.sub(src, #TAG_MACRO + 1) + local tag, rest = string.match(src, "([^%s]+)(%s+.*)") + local path = {} + for v in string.gmatch(tag, "[^%.]+") do + table.insert(path, v) + end + + local mod_name = table.remove(path, 1) + local out = require("macro_" .. mod_name) + for _, v in ipairs(path) do + out = out[v] + end + return out(rest, namespace_name) + end + + if state.default_macro then + print("loading via default macro") + return loadstring(state.default_macro(src, namespace_name), script_name) + end + + print("loading raw lua") + return loadstring(src, script_name) +end + +function set_default_macro(mac) + state.default_macro = mac +end + +package.loaded["script_compiler"] = { + compile = compile, + set_default_macro = set_default_macro +} diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index 6cf971e200..3bc2037719 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -339,7 +339,6 @@ - @@ -1968,7 +1967,6 @@ - pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index b270dcdcd4..0b19afe3ed 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -7418,9 +7418,6 @@ AI\AScript\ScriptCompiler - - AI\AScript\ScriptCompiler - @@ -11135,9 +11132,6 @@ AI\AScript\ScriptCompiler - - AI\AScript\ScriptCompiler - AI\AScript\ScriptCompiler diff --git a/src/xrServerEntities/script_macro_wua.cpp b/src/xrServerEntities/macro_wua.h similarity index 83% rename from src/xrServerEntities/script_macro_wua.cpp rename to src/xrServerEntities/macro_wua.h index 5dd931de14..8ffcd90772 100644 --- a/src/xrServerEntities/script_macro_wua.cpp +++ b/src/xrServerEntities/macro_wua.h @@ -1,12 +1,17 @@ #include "stdafx.h" -#include "script_macro_wua.h" -#include "script_compiler.h" #include "lua_macros.h" +#include "ai_space.h" +#include "script_engine.h" +#include #include #include +#include #include "../xrCore/mezz_stringbuffer.h" +typedef std::set Unlocalizer; +typedef xr_unordered_map Unlocalizers; + static bool unlocalRegex(Unlocalizer& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { if (std::regex_match(s, pattern)) { //Msg("matching local function pattern"); @@ -36,15 +41,29 @@ static std::string join_list(const std::vector& items_vec, std::str return ret; }; -std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName) +static std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName) { if (!caNameSpaceName) return src; - Unlocalizer* unlocalizer = ScriptCompiler().get_unlocalizer(caNameSpaceName); - if (!unlocalizer) + Unlocalizer unlocalizer; + + luabind::functor f; + if (xr_strcmp(caNameSpaceName, "unlocalizers") == 0) return src; + VERIFY(!ai().script_engine().functor("unlocalizers.get", f)); + + luabind::object table = f(caNameSpaceName); + + if (table.type() != LUA_TTABLE) + return src; + + for (luabind::object o : table) + { + unlocalizer.insert(luabind::object_cast(o)); + } + bool unlocalPerformed = false; std::string unlocalizerResult; @@ -78,7 +97,7 @@ std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName) //local function x(a,b,c) pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); - if (unlocalRegex(*unlocalizer, s, pattern, 5, "$3$4$5$6$7")) { + if (unlocalRegex(unlocalizer, s, pattern, 5, "$3$4$5$6$7")) { //Msg("Regex matched"); unlocalPerformed = true; continue; @@ -111,7 +130,7 @@ std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName) for (auto v : variables) { trim(v); //Msg("%s\n", v.c_str()); - if (unlocalizer->find(v) != unlocalizer->end()) { + if (unlocalizer.find(v) != unlocalizer.end()) { unlocalPerformed = true; Msg("found variable %s to unlocal", v.c_str()); s = std::regex_replace(s, pattern, "$3"); @@ -148,8 +167,9 @@ std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName) return src; } -std::string CWuaMacro::lift(std::string src, LPCSTR caNameSpaceName) const +static LPCSTR compile_wua(LPCSTR buffer, LPCSTR caNameSpaceName) { + std::string src(buffer); src = unlocalize(src, caNameSpaceName); bool is_g = caNameSpaceName && xr_strcmp(caNameSpaceName, "_G") == 0; std::string out; @@ -196,5 +216,5 @@ end out += "\n" + src; - return out; + return out.c_str(); } diff --git a/src/xrServerEntities/script_compiler.cpp b/src/xrServerEntities/script_compiler.cpp index 7da4816dc9..62e3118d45 100644 --- a/src/xrServerEntities/script_compiler.cpp +++ b/src/xrServerEntities/script_compiler.cpp @@ -8,78 +8,6 @@ #include #include -Unlocalizers unlocalizers; -CWuaMacro wua; - -void CScriptCompiler::load_unlocalizers() -{ - auto file_list = FS.file_list_open("$game_config$", "unlocalizers\\", FS_RootOnly | FS_ListFiles); - if (!file_list) { - return; - } - else { - xr_string id; - auto i = file_list->begin(); - auto e = file_list->end(); - for (; i != e; ++i) - { - u32 length = xr_strlen(*i); - - if (!((length >= 4) && - ((*i)[length - 4] == '.') && - ((*i)[length - 3] == 'l') && - ((*i)[length - 2] == 't') && - ((*i)[length - 1] == 'x'))) - continue; - - id.assign(*i, length - 4); - - string_path file_name; - FS.update_path(file_name, "$game_config$", (xr_string("unlocalizers\\") + id).c_str()); - xr_strcat(file_name, ".ltx"); - - Msg("opening file %s", file_name); - auto config = xr_new(file_name); - - typedef CInifile::Root sections_type; - sections_type& sections = config->sections(); - - sections_type::const_iterator i = sections.begin(); - sections_type::const_iterator e = sections.end(); - for (; i != e; ++i) - { - auto sectionName = std::string((*i)->Name.c_str()); - toLowerCase(sectionName); - if (unlocalizers.find(sectionName) == unlocalizers.end()) { - - // construct set that contains top level variables to delocalize by section name - unlocalizers[sectionName].clear(); - Msg("creating unlocalizer for script %s", sectionName.c_str()); - } - auto& data = (*i)->Data; - for (auto& item : data) { - unlocalizers[sectionName].insert(std::string(item.first.c_str())); - Msg("adding variable %s for unlocalizer for script %s", item.first.c_str(), sectionName.c_str()); - } - } - xr_delete(config); - } - FS.file_list_close(file_list); - } -} - -Unlocalizer* CScriptCompiler::get_unlocalizer(std::string name) -{ - toLowerCase(name); - if (unlocalizers.find(name) != unlocalizers.end()) - { - Msg("Found key %s in unlocalizers data", name); - return &unlocalizers[name]; - } - - return NULL; -} - int CScriptCompiler::compile( lua_State* L, std::string caString, @@ -87,42 +15,17 @@ int CScriptCompiler::compile( LPCSTR caNameSpaceName ) { - std::regex pattern(R"(#macro (.*)(\s+))"); - std::smatch match; - if (std::regex_search(caString, match, pattern)) + luabind::functor compile; + if (ai().script_engine().namespace_loaded("script_compiler", true)) { - std::string macro_name = match[1]; - caString = std::string(match[2]) + std::string(match.suffix()); - if (macro_name != "wua") + if (ai().script_engine().functor("script_compiler.compile", compile)) { - luabind::functor macro; - if (ai().script_engine().functor((std::string("macro_") + macro_name).c_str(), macro)) - { - - luabind::object unlocs = luabind::newtable(ai().script_engine().lua()); - Unlocalizer* unlocalizer = get_unlocalizer(caNameSpaceName); - if (unlocalizer) - { - int i = 1; - for (auto unloc : *unlocalizer) - { - unlocs[i] = unloc.c_str(); - i++; - } - } - - luabind::object result = macro(caString.c_str(), caNameSpaceName, unlocs); - result.pushvalue(); - return 0; - } - else - { - Msg("No such macro: %s", macro_name); - FATAL("Failed to load macro"); - } + luabind::object result = compile(caString.c_str(), caScriptName, caNameSpaceName); + result.pushvalue(); + return 0; } } - caString = wua.lift(caString, caNameSpaceName); + Msg("script_compiler not available, loading as raw Lua..."); return luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); } diff --git a/src/xrServerEntities/script_compiler.h b/src/xrServerEntities/script_compiler.h index bda8c928c0..cb0b3a7d7e 100644 --- a/src/xrServerEntities/script_compiler.h +++ b/src/xrServerEntities/script_compiler.h @@ -3,10 +3,6 @@ #include "stdafx.h" #include "script_storage.h" #include "script_macro.h" -#include "script_macro_wua.h" - -typedef std::set Unlocalizer; -typedef xr_unordered_map Unlocalizers; namespace luabind { @@ -18,9 +14,6 @@ namespace luabind struct CScriptCompiler { public: - void load_unlocalizers(); - Unlocalizer* CScriptCompiler::get_unlocalizer(std::string name); - int compile( lua_State* L, std::string caString, diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 13abb408c6..0c0b69e96c 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -400,7 +400,6 @@ void CScriptEngine::init() #endif // #ifndef USE_LUA_STUDIO // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); - ScriptCompiler().load_unlocalizers(); process_file_if_exists("_init", false); process_file_if_exists("_G", false); diff --git a/src/xrServerEntities/script_macro_script.cpp b/src/xrServerEntities/script_macro_script.cpp index e2291ab835..4169d2093e 100644 --- a/src/xrServerEntities/script_macro_script.cpp +++ b/src/xrServerEntities/script_macro_script.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "pch_script.h" #include "script_macro.h" +#include "macro_wua.h" using namespace luabind; @@ -9,7 +10,6 @@ void CScriptMacro::script_register(lua_State* L) { module(L) [ - class_("CScriptMacro") - .def("lift", &CScriptMacro::lift) + def("compile_wua", &compile_wua) ]; } diff --git a/src/xrServerEntities/script_macro_wua.h b/src/xrServerEntities/script_macro_wua.h deleted file mode 100644 index d0853a4911..0000000000 --- a/src/xrServerEntities/script_macro_wua.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "script_macro.h" - -class CWuaMacro : public CScriptMacro -{ -public: - virtual std::string lift(std::string src, LPCSTR caNameSpaceName) const override; -}; From 61a33dc4d733047e089f83e1694a5c1880bc5a22 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 21 May 2025 23:14:09 +0100 Subject: [PATCH 20/76] Factor out `CScriptCompiler` and `CScriptMacro` --- src/xrGame/vs2022/xrGame.vcxproj | 6 -- src/xrGame/vs2022/xrGame.vcxproj.filters | 45 ---------- src/xrServerEntities/lua_macros.h | 91 -------------------- src/xrServerEntities/script_compiler.cpp | 31 ------- src/xrServerEntities/script_compiler.h | 29 ------- src/xrServerEntities/script_engine.cpp | 14 ++- src/xrServerEntities/script_macro.cpp | 8 -- src/xrServerEntities/script_macro.h | 16 ---- src/xrServerEntities/script_macro_script.cpp | 15 ---- src/xrServerEntities/script_storage.cpp | 22 ++++- src/xrServerEntities/script_storage.h | 7 +- src/xrServerEntities/script_thread.cpp | 3 +- 12 files changed, 39 insertions(+), 248 deletions(-) delete mode 100644 src/xrServerEntities/lua_macros.h delete mode 100644 src/xrServerEntities/script_compiler.cpp delete mode 100644 src/xrServerEntities/script_compiler.h delete mode 100644 src/xrServerEntities/script_macro.cpp delete mode 100644 src/xrServerEntities/script_macro.h delete mode 100644 src/xrServerEntities/script_macro_script.cpp diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index 3bc2037719..5a2393d9c6 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -307,7 +307,6 @@ - @@ -338,7 +337,6 @@ - @@ -351,7 +349,6 @@ - @@ -1965,8 +1962,6 @@ - - pch_script.h $(IntDir)$(ProjectName)_script.pch @@ -2000,7 +1995,6 @@ pch_script.h $(IntDir)$(ProjectName)_script.pch - pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index 0b19afe3ed..0cb8cb86a6 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -2494,13 +2494,6 @@ {8d6475ec-c185-4ebb-9ba6-e7dc1644c4c1} - - {c14ffa0c-947d-49b9-8e01-269569b48371} - - - - {53abd459-f211-4178-b3c6-2be2afe329ba} - @@ -7402,22 +7395,6 @@ UI\Cursor - - UI\Common\ImGui - - - UI\Common\ImGui - - - - AI\AScript\ScriptCompiler - - - AI\AScript\ScriptCompiler - - - AI\AScript\ScriptCompiler - @@ -11113,28 +11090,6 @@ UI\Cursor - - UI\Common\ImGui - - - AI\AScript\ScriptDialect - - - AI\AScript\ScriptDialect - - - AI\AScript\ScriptDialect - - - - AI\AScript\ScriptCompiler - - - AI\AScript\ScriptCompiler - - - AI\AScript\ScriptCompiler - diff --git a/src/xrServerEntities/lua_macros.h b/src/xrServerEntities/lua_macros.h deleted file mode 100644 index 0e359e1097..0000000000 --- a/src/xrServerEntities/lua_macros.h +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include -#include - -/** - * Convert all std::strings to const char* using constexpr if (C++17) - */ -template -static auto convert(T&& t) { - if constexpr (std::is_same>, std::string>::value) { - return std::forward(t).c_str(); - } - else { - return std::forward(t); - } -} - -/** - * printf like formatting for C++ with std::string - * Original source: https://stackoverflow.com/a/26221725/11722 - */ -template -static std::string string_format_internal(const std::string& format, Args&& ... args) -{ - const auto size = snprintf(nullptr, 0, format.c_str(), std::forward(args) ...) + 1; - if (size <= 0) { throw std::runtime_error("Error during formatting."); } - std::unique_ptr buf(new char[size]); - snprintf(buf.get(), size, format.c_str(), args ...); - return std::string(buf.get(), buf.get() + size - 1); -} - -template -static std::string string_format(std::string fmt, Args&& ... args) { - return string_format_internal(fmt, convert(std::forward(args))...); -} - -template< typename ... Args > -std::string lines(Args const& ... args) -{ - std::ostringstream stream; - using List = int[]; - (void)List { - 0, ((void)(stream << "\n" << args), 0) ... - }; - - return stream.str(); -} - -static std::string assign_local(const std::string& key, const std::string& value) -{ - return string_format("local %s = %s", key, value); -} - -static std::string int_literal(int i) -{ - return std::to_string(i); -} - -static std::string scope_to(const std::string& sThis) -{ - return string_format("setfenv(%s, %s)", int_literal(1), sThis); -} - -static std::string wua_environment(const std::string& key) -{ - return string_format( - R"( - local %s = setmetatable( - {}, - { - __index = function(self, key) - local gv = _G[key] - if gv ~= nil then - return gv - end - - local res, out = pcall(require, key) - if res then - return out - end - end, - __newindex = function(self, key, value) - _G[key] = value - end - } - ) - )", - key - ); -} \ No newline at end of file diff --git a/src/xrServerEntities/script_compiler.cpp b/src/xrServerEntities/script_compiler.cpp deleted file mode 100644 index 62e3118d45..0000000000 --- a/src/xrServerEntities/script_compiler.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "stdafx.h" -#include "script_compiler.h" -#include "ai_space.h" -#include "script_engine.h" -#include "../xrCore/mezz_stringbuffer.h" -#include "lua_macros.h" -#include "luabind/luabind.hpp" -#include -#include - -int CScriptCompiler::compile( - lua_State* L, - std::string caString, - LPCSTR caScriptName, - LPCSTR caNameSpaceName -) -{ - luabind::functor compile; - if (ai().script_engine().namespace_loaded("script_compiler", true)) - { - if (ai().script_engine().functor("script_compiler.compile", compile)) - { - luabind::object result = compile(caString.c_str(), caScriptName, caNameSpaceName); - result.pushvalue(); - return 0; - } - } - - Msg("script_compiler not available, loading as raw Lua..."); - return luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); -} diff --git a/src/xrServerEntities/script_compiler.h b/src/xrServerEntities/script_compiler.h deleted file mode 100644 index cb0b3a7d7e..0000000000 --- a/src/xrServerEntities/script_compiler.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "stdafx.h" -#include "script_storage.h" -#include "script_macro.h" - -namespace luabind -{ - template - class functor; - - class object; -} // namespace luabind - -struct CScriptCompiler { -public: - int compile( - lua_State* L, - std::string caString, - LPCSTR caScriptName, - LPCSTR caNameSpaceName = 0 - ); -}; - -static CScriptCompiler compiler; -static CScriptCompiler& ScriptCompiler() -{ - return compiler; -} \ No newline at end of file diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 0c0b69e96c..be14cb85ff 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -13,7 +13,7 @@ #include "script_process.h" #include "../build_config_defines.h" #include "script_storage.h" -#include "script_compiler.h" +#include "macro_wua.h" #include #include @@ -355,6 +355,15 @@ void CScriptEngine::setup_auto_load() extern void export_classes(lua_State* L); +int do_compile_wua(lua_State* L) +{ + VERIFY(lua_gettop(L) == 2); + VERIFY(lua_type(L, 1) == LUA_TSTRING); + VERIFY(lua_type(L, 2) == LUA_TSTRING); + lua_pushstring(L, compile_wua(lua_tostring(L, 1), lua_tostring(L, 2))); + return (1); +} + void CScriptEngine::init() { #ifdef USE_LUA_STUDIO @@ -400,6 +409,9 @@ void CScriptEngine::init() #endif // #ifndef USE_LUA_STUDIO // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); + lua_pushcfunction(lua(), do_compile_wua); + lua_setglobal(lua(), "compile_wua"); + process_file_if_exists("_init", false); process_file_if_exists("_G", false); diff --git a/src/xrServerEntities/script_macro.cpp b/src/xrServerEntities/script_macro.cpp deleted file mode 100644 index 8871b45fc5..0000000000 --- a/src/xrServerEntities/script_macro.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "stdafx.h" -#include "script_macro.h" -#include "lua_macros.h" - -std::string CScriptMacro::lift(std::string src, LPCSTR caNameSpaceName) const -{ - return src; -} diff --git a/src/xrServerEntities/script_macro.h b/src/xrServerEntities/script_macro.h deleted file mode 100644 index 9cda3c8681..0000000000 --- a/src/xrServerEntities/script_macro.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "script_export_space.h" -#include - -class CScriptMacro : public DLL_Pure -{ -public: - virtual std::string lift(std::string src, LPCSTR caNameSpaceName) const; - -DECLARE_SCRIPT_REGISTER_FUNCTION -}; - -add_to_type_list(CScriptMacro) -#undef script_type_list -#define script_type_list save_type_list(CScriptMacro) \ No newline at end of file diff --git a/src/xrServerEntities/script_macro_script.cpp b/src/xrServerEntities/script_macro_script.cpp deleted file mode 100644 index 4169d2093e..0000000000 --- a/src/xrServerEntities/script_macro_script.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "stdafx.h" -#include "pch_script.h" -#include "script_macro.h" -#include "macro_wua.h" - -using namespace luabind; - -#pragma optimize("s",on) -void CScriptMacro::script_register(lua_State* L) -{ - module(L) - [ - def("compile_wua", &compile_wua) - ]; -} diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp index 51900e8d55..acc1dfd4d2 100644 --- a/src/xrServerEntities/script_storage.cpp +++ b/src/xrServerEntities/script_storage.cpp @@ -8,7 +8,6 @@ #include "pch_script.h" #include "script_storage.h" -#include "script_compiler.h" #include "script_thread.h" #include "../xrCore/mezz_stringbuffer.h" #include @@ -555,6 +554,23 @@ int __cdecl CScriptStorage::script_log(ScriptStorage::ELuaMessageType tLuaMessag return (result); } +int CScriptStorage::compile_buffer(lua_State* L, std::string caString, LPCSTR caScriptName, LPCSTR caNameSpaceName) +{ + luabind::functor compile; + if (ai().script_engine().namespace_loaded("script_compiler", true)) + { + if (ai().script_engine().functor("script_compiler.compile", compile)) + { + luabind::object result = compile(caString.c_str(), caScriptName, caNameSpaceName); + result.pushvalue(); + return 0; + } + } + + Msg("script_compiler not available, loading as raw Lua..."); + return luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); +} + int CScriptStorage::load_buffer( lua_State* L, LPCSTR caBuffer, @@ -563,7 +579,7 @@ int CScriptStorage::load_buffer( LPCSTR caNameSpaceName ) { - int l_iErrorCode = ScriptCompiler().compile( + int l_iErrorCode = compile_buffer( L, std::string(caBuffer, caBuffer + tSize), caScriptName, @@ -716,7 +732,7 @@ bool CScriptStorage::namespace_loaded(LPCSTR N, bool remove_from_stack) VERIFY(lua_gettop(lua()) == start); } return (true); - } +} luabind::object CScriptStorage::name_space(LPCSTR namespace_name) { diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h index 0155755399..87c88f8655 100644 --- a/src/xrServerEntities/script_storage.h +++ b/src/xrServerEntities/script_storage.h @@ -10,7 +10,6 @@ #include "script_storage_space.h" #include "script_space_forward.h" -#include "script_macro.h" #include #include #include @@ -85,6 +84,12 @@ class CScriptStorage IC lua_State* lua(); IC void current_thread(CScriptThread* thread); IC CScriptThread* current_thread() const; + int compile_buffer( + lua_State* L, + std::string caString, + LPCSTR caScriptName, + LPCSTR caNameSpaceName = 0 + ); int load_buffer( lua_State* L, LPCSTR caBuffer, diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp index 397140fa13..2c762ef912 100644 --- a/src/xrServerEntities/script_thread.cpp +++ b/src/xrServerEntities/script_thread.cpp @@ -14,7 +14,6 @@ };*/ //-AVO #include "script_engine.h" -#include "script_compiler.h" #include "script_thread.h" #include "ai_space.h" @@ -57,7 +56,7 @@ CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string) { m_script_name = "console command"; S += caBuffer; - int l_iErrorCode = ScriptCompiler().compile(ai().script_engine().lua(), S, "@console_command"); + int l_iErrorCode = ai().script_engine().compile_buffer(ai().script_engine().lua(), S, "@console_command"); if (!l_iErrorCode) { lua_setglobal(ai().script_engine().lua(), main_function); From d27c17459f710b60e499acbcb3115cce62b453b3 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 22 May 2025 01:41:17 +0100 Subject: [PATCH 21/76] Replace C-side `macro_wua` with Lua implementation - Macro system is now entirely hosted in Lua --- gamedata/scripts/_init.script | 2 +- gamedata/scripts/macro.script | 7 +- gamedata/scripts/macro_wua.script | 203 +++++++++++++++++++++++ src/xrServerEntities/macro_wua.h | 220 ------------------------- src/xrServerEntities/script_engine.cpp | 14 +- 5 files changed, 211 insertions(+), 235 deletions(-) create mode 100644 gamedata/scripts/macro_wua.script delete mode 100644 src/xrServerEntities/macro_wua.h diff --git a/gamedata/scripts/_init.script b/gamedata/scripts/_init.script index 7e9df81b73..b7a5b86892 100644 --- a/gamedata/scripts/_init.script +++ b/gamedata/scripts/_init.script @@ -25,4 +25,4 @@ end print("Lua initializing...") print("package.loaded._G:", package.loaded._G) -require("script_compiler").set_default_macro(compile_wua) \ No newline at end of file +require("script_compiler").set_default_macro(require("macro_wua").expand) \ No newline at end of file diff --git a/gamedata/scripts/macro.script b/gamedata/scripts/macro.script index 0b4b52013b..bb8d580285 100644 --- a/gamedata/scripts/macro.script +++ b/gamedata/scripts/macro.script @@ -7,4 +7,9 @@ function extend_env(dest) dest[k] = v end return dest -end \ No newline at end of file +end + +package.loaded["macro"] = { + load_src = load_src, + extend_env = extend_env, +} \ No newline at end of file diff --git a/gamedata/scripts/macro_wua.script b/gamedata/scripts/macro_wua.script new file mode 100644 index 0000000000..d167aa73f9 --- /dev/null +++ b/gamedata/scripts/macro_wua.script @@ -0,0 +1,203 @@ +local unlocalizers = require("unlocalizers") +local macro = require("macro") + +local function string_trim(s, v) + if v == nil then + v = " \t\n\r\f\v" + end + local pattern = string.format("^[%s]*([^%s]*)[%s]*$", v, v, v) + print("pattern:", pattern) + return string.match(s, pattern) +end + +local function contains(lst, a) + for _,b in ipairs(lst) do + if a == b then + return true + end + end + + return false +end + +local function unlocal_regex(unlocals, s) + local pattern = [[^(local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(%(.*)$]] + local _, _, c, d, e, f, g = string.match(s, pattern) + + if e and contains(unlocals, e) then + print("[unlocal_regex] found variable " .. e .. " to unlocal") + print("s", s) + s = c .. d .. e .. f .. g + print("s'", s) + return s + end + + return nil +end + +local function unlocalize(src, namespace_name) + if not namespace_name then + return src + end + + local unlocalizer = unlocalizers.get(namespace_name) + if not unlocalizer then + return src + end + + local unlocal_performed = false + + local temp = src + local tokens = {} + for line in string.gmatch(temp, "[^\n]+") do + table.insert(tokens, line) + end + + for i,s in ipairs(tokens) do + print("s", s) + s = string_trim(s, "\n\r") + print("trimmed", s) + tokens[i] = s + + if s == "" then + goto next_token + end + + -- local function x(a,b,c) + local ur = unlocal_regex(unlocalizer, s) + if ur then + tokens[i] = ur + unlocal_performed = true + tokens[i] = s + goto next_token + end + + -- local a = ... + -- local a + -- local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) + -- local x; local y; - unsupported yet + local pattern = [[^local%s+(.*)]] + local c = string.match(s, pattern) or "" + if #c > 0 then + local r = [[(.*)--.*]] + local nc = string.match(c, r) + if nc then + c = nc + end + end + + local pattern = [[([^=]+)=(.*)]] + local variables, values = string.match(c, pattern) + if variables then + for v in string.gmatch(variables, "[^,]+") do + v = string_trim(v) + if contains(unlocalizer, v) then + unlocal_performed = true + print("found variable", v, "to unlocal") + s = c + if not values then + local r = [[(.*)(--.*)]] + local lhs, rhs = string.match(s, r) + if lhs and rhs then + s = lhs .. "= nil " .. rhs + else + s = s .. " = nil" + end + end + tokens[i] = s + break + end + end + end + + ::next_token:: + end + + if unlocal_performed then + return table.concat(tokens, "\n") + end + + return src +end + +local function compile(src, namespace_name) + local is_g = namespace_name == "_G" + + local G = setmetatable( + {}, + { + __index = function(_, key) + local gv = _G[key] + if gv ~= nil then + return gv + end + + local res, out = pcall(require, key) + if res then + return out + end + end, + __newindex = function(_, k, v) + _G[k] = v + end + } + ) + + local mt = { + __index = G + } + + if is_g then + mt.__newindex = function(_, k, v) + _G[k] = v + end + end + + local env = setmetatable({ _G = G }, mt) + + setmetatable(env, mt) + + if is_g then + print("expanding _g") + else + print("expanding module", namespace_name) + env._M = env + if namespace_name then + env._PACKAGE = namespace_name + package.loaded[namespace_name] = env + end + end + + + if namespace_name then + src = [[ +local script_name = function() + return _PACKAGE +end + ]] .. src + end + + src = [[ +local this = _M + ]] .. src + + return setfenv( + macro.load_src(src), + env + ) +end + +local function expand(src, namespace_name) + print("macro_wua.expand", namespace_name) + + return macro.load_src( + compile( + unlocalize(src, namespace_name), + namespace_name + ) + ) +end + +package.loaded["macro_wua"] = { + expand = expand +} diff --git a/src/xrServerEntities/macro_wua.h b/src/xrServerEntities/macro_wua.h deleted file mode 100644 index 8ffcd90772..0000000000 --- a/src/xrServerEntities/macro_wua.h +++ /dev/null @@ -1,220 +0,0 @@ -#include "stdafx.h" -#include "lua_macros.h" -#include "ai_space.h" -#include "script_engine.h" - -#include -#include -#include -#include -#include "../xrCore/mezz_stringbuffer.h" - -typedef std::set Unlocalizer; -typedef xr_unordered_map Unlocalizers; - -static bool unlocalRegex(Unlocalizer& unlocals, std::string& s, const std::regex& pattern, const int group, const std::string& replacement) { - if (std::regex_match(s, pattern)) { - //Msg("matching local function pattern"); - std::smatch match; - std::regex_search(s, match, pattern); - std::string variable = match[group]; - if (unlocals.find(variable) != unlocals.end()) { - Msg("[unlocalRegex] found variable %s to unlocal", variable.c_str()); - s = std::regex_replace(s, pattern, replacement); - return true; - } - } - else { - return false; - } - return false; -}; - -static std::string join_list(const std::vector& items_vec, std::string delim = "\n") { - std::string ret; - for (const auto& i : items_vec) { - if (!ret.empty()) { - ret += delim; - } - ret += i; - } - return ret; -}; - -static std::string unlocalize(const std::string& src, LPCSTR caNameSpaceName) -{ - if (!caNameSpaceName) - return src; - - Unlocalizer unlocalizer; - - luabind::functor f; - if (xr_strcmp(caNameSpaceName, "unlocalizers") == 0) - return src; - - VERIFY(!ai().script_engine().functor("unlocalizers.get", f)); - - luabind::object table = f(caNameSpaceName); - - if (table.type() != LUA_TTABLE) - return src; - - for (luabind::object o : table) - { - unlocalizer.insert(luabind::object_cast(o)); - } - - bool unlocalPerformed = false; - std::string unlocalizerResult; - - // Get contents of the script file and split by lines - std::vector tokens; - std::string temp; - temp += src; - - std::stringstream stringStream(temp); - std::string line; - tokens.clear(); - while (std::getline(stringStream, line)) { - tokens.push_back(line); - } - - /*for (auto& u : unlocalizer) { - Msg("Unlocalizer: %s", u); - }*/ - - for (std::string& s : tokens) { - - //Msg("Line: %s", s.c_str()); - - trim(s, "\n\r"); - if (s.empty()) { - //Msg("Empty, continuing"); - continue; - } - - std::regex pattern; - - //local function x(a,b,c) - pattern = std::regex(R"((^local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(\(.*$))"); - if (unlocalRegex(unlocalizer, s, pattern, 5, "$3$4$5$6$7")) { - //Msg("Regex matched"); - unlocalPerformed = true; - continue; - } - - //Msg("Regex not matched"); - - //local a = ... - //local a - //local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) - //local x; local y; - unsupported yet - pattern = std::regex(R"((^local)([\t ]+)(.*))"); - if (std::regex_match(s, pattern)) { - std::smatch match; - std::regex_search(s, match, pattern); - std::string m = match[3]; - - // strip comments - std::regex r = std::regex(R"((.*)--.*)"); - if (std::regex_match(m, r)) { - //Msg("found comments\n"); - std::smatch noncomments; - std::regex_search(m, noncomments, r); - m = noncomments[1]; - } - - auto variablesAndValues = splitStringLimit(m, "=", 1); - bool hasValue = variablesAndValues.size() > 1; - auto variables = splitStringMulti(variablesAndValues[0], ","); - for (auto v : variables) { - trim(v); - //Msg("%s\n", v.c_str()); - if (unlocalizer.find(v) != unlocalizer.end()) { - unlocalPerformed = true; - Msg("found variable %s to unlocal", v.c_str()); - s = std::regex_replace(s, pattern, "$3"); - if (!hasValue) { - - // strip comments - std::regex r = std::regex(R"((.*)(--.*))"); - if (std::regex_match(s, r)) { - //Msg("found comments\n"); - std::smatch noncomments; - std::regex_search(s, noncomments, r); - s = std::string(noncomments[1]) + "= nil " + std::string(noncomments[2]); - } - else { - s += " = nil"; - } - } - break; - } - } - } - } - - // Store result back - /*for (auto& s : tokens) { - Msg("%s", s.c_str()); - }*/ - - if (unlocalPerformed) - { - return join_list(tokens); - } - - return src; -} - -static LPCSTR compile_wua(LPCSTR buffer, LPCSTR caNameSpaceName) -{ - std::string src(buffer); - src = unlocalize(src, caNameSpaceName); - bool is_g = caNameSpaceName && xr_strcmp(caNameSpaceName, "_G") == 0; - std::string out; - out += wua_environment("G"); - out += R"( -local mt = {} -mt.__index = G - )"; - if (is_g) - out += R"( -mt.__newindex = function(self, key, value) - _G[key] = value -end - )"; - - out += R"( -local this = {} -this._G = G - )"; - - if (!is_g) - { - out += string_format( - R"( -package.loaded["%s"] = this - )", - caNameSpaceName - ); - } - - out += R"( -setmetatable(this, mt) -setfenv(1, this) - )"; - - out += string_format( - R"( -local function script_name() -return "%s" -end - )", - caNameSpaceName - ); - - out += "\n" + src; - - return out.c_str(); -} diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index be14cb85ff..4edc7714fe 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -13,7 +13,6 @@ #include "script_process.h" #include "../build_config_defines.h" #include "script_storage.h" -#include "macro_wua.h" #include #include @@ -355,14 +354,6 @@ void CScriptEngine::setup_auto_load() extern void export_classes(lua_State* L); -int do_compile_wua(lua_State* L) -{ - VERIFY(lua_gettop(L) == 2); - VERIFY(lua_type(L, 1) == LUA_TSTRING); - VERIFY(lua_type(L, 2) == LUA_TSTRING); - lua_pushstring(L, compile_wua(lua_tostring(L, 1), lua_tostring(L, 2))); - return (1); -} void CScriptEngine::init() { @@ -408,10 +399,7 @@ void CScriptEngine::init() # endif // #ifdef DEBUG #endif // #ifndef USE_LUA_STUDIO // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); - - lua_pushcfunction(lua(), do_compile_wua); - lua_setglobal(lua(), "compile_wua"); - + process_file_if_exists("_init", false); process_file_if_exists("_G", false); From d0cf8f1504d66e29c2615690fc3794bf7c2705f7 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 22 May 2025 04:30:54 +0100 Subject: [PATCH 22/76] Factor out `CScriptStorage`, `CScriptEngine::process_file` --- src/xrGame/vs2022/xrGame.vcxproj | 6 - src/xrGame/vs2022/xrGame.vcxproj.filters | 9 - src/xrServerEntities/script_engine.cpp | 920 +++++++++++++++++- src/xrServerEntities/script_engine.h | 107 +- src/xrServerEntities/script_engine_inline.h | 16 + src/xrServerEntities/script_engine_script.cpp | 2 +- src/xrServerEntities/script_storage.cpp | 900 ----------------- src/xrServerEntities/script_storage.h | 115 --- src/xrServerEntities/script_storage_inline.h | 25 - src/xrServerEntities/script_thread.cpp | 2 +- 10 files changed, 1010 insertions(+), 1092 deletions(-) delete mode 100644 src/xrServerEntities/script_storage.cpp delete mode 100644 src/xrServerEntities/script_storage.h delete mode 100644 src/xrServerEntities/script_storage_inline.h diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index 5a2393d9c6..c53587fd05 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -360,8 +360,6 @@ - - @@ -2023,10 +2021,6 @@ pch_script.h $(IntDir)$(ProjectName)_script.pch - - pch_script.h - $(IntDir)$(ProjectName)_script.pch - pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index 0cb8cb86a6..672e4983ac 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -5229,12 +5229,6 @@ AI\AScript\ScriptProcess - - AI\AScript\ScriptStorage - - - AI\AScript\ScriptStorage - AI\AScript\ScriptStorage @@ -8816,9 +8810,6 @@ AI\AScript\ScriptProcess - - AI\AScript\ScriptStorage - AI\AScript\ScriptThread diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 4edc7714fe..f81ee2b02d 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -12,10 +12,877 @@ #include "object_factory.h" #include "script_process.h" #include "../build_config_defines.h" -#include "script_storage.h" +#include "script_thread.h" +#include "../xrCore/mezz_stringbuffer.h" +#include #include #include +#if !defined(DEBUG) && defined(USE_LUAJIT_ONE) +# include "opt.lua.h" +# include "opt_inline.lua.h" +#endif //!DEBUG && USE_LUAJIT_ONE +#ifndef USE_LUAJIT_ONE +#include "lua.hpp" +#endif + +#ifndef ENGINE_BUILD +# include "script_engine.h" +# include "ai_space.h" +#else //ENGINE_BUILD +# define NO_XRGAME_SCRIPT_ENGINE +#endif //!ENGINE_BUILD + +#ifndef XRGAME_EXPORTS +# define NO_XRGAME_SCRIPT_ENGINE +#endif //!XRGAME_EXPORTS + +#ifndef NO_XRGAME_SCRIPT_ENGINE +# include "ai_debug.h" +#endif //!NO_XRGAME_SCRIPT_ENGINE + +#ifdef USE_DEBUGGER +# include "script_debugger.h" +#endif + +#ifndef PURE_ALLOC +//# ifndef USE_MEMORY_MONITOR +//# define USE_DL_ALLOCATOR +//# endif //!USE_MEMORY_MONITOR +#endif //!PURE_ALLOC + +#ifndef USE_DL_ALLOCATOR +static void* lua_alloc(void* ud, void* ptr, size_t osize, size_t nsize) +{ + (void)ud; + (void)osize; + if (nsize == 0) + { + xr_free(ptr); + return NULL; + } + else +#ifdef DEBUG_MEMORY_NAME + return Memory.mem_realloc(ptr, nsize, "LUA"); +#else // DEBUG_MEMORY_MANAGER + return Memory.mem_realloc(ptr, nsize); +#endif // DEBUG_MEMORY_MANAGER +} + +u32 game_lua_memory_usage() +{ + return (0); +} +#else //USE_DL_ALLOCATOR + +# ifdef USE_ARENA_ALLOCATOR +static const u32 s_arena_size = 96 * 1024 * 1024; +static char s_fake_array[s_arena_size]; +// static doug_lea_allocator s_allocator( s_fake_array, s_arena_size, "lua" ); +# else //-USE_ARENA_ALLOCATOR +// static doug_lea_allocator s_allocator(0, 0, "lua"); +# endif //-USE_ARENA_ALLOCATOR + +static void* lua_alloc(void* ud, void* ptr, size_t osize, size_t nsize) +{ +#ifndef USE_MEMORY_MONITOR + (void)ud; + (void)osize; + if (!nsize) + { + s_allocator.free_impl(ptr); + return 0; + } + if (!ptr) + return s_allocator.malloc_impl((u32)nsize); + + return s_allocator.realloc_impl(ptr, (u32)nsize); +#else //USE_MEMORY_MONITOR + if (!nsize) { + memory_monitor::monitor_free(ptr); + s_allocator.free_impl(ptr); + return NULL; + } + + if (!ptr) { + void* const result = s_allocator.malloc_impl((u32)nsize); + memory_monitor::monitor_alloc(result, nsize, "LUA"); + return result; + } + + memory_monitor::monitor_free(ptr); + void* const result = s_allocator.realloc_impl(ptr, (u32)nsize); + memory_monitor::monitor_alloc(result, nsize, "LUA"); + return result; +#endif //!USE_MEMORY_MONITOR +} + +u32 game_lua_memory_usage() +{ + return (s_allocator.get_allocated_size()); +} +#endif //!USE_DL_ALLOCATOR + +static LPVOID __cdecl luabind_allocator( + luabind::memory_allocation_function_parameter const, + void const* const pointer, + size_t const size +) +{ + if (!size) + { + LPVOID non_const_pointer = const_cast(pointer); + xr_free(non_const_pointer); + return (0); + } + + if (!pointer) + { +#ifdef DEBUG + return (Memory.mem_alloc(size, "luabind")); +#else //!DEBUG + return (Memory.mem_alloc(size)); +#endif //-DEBUG + } + + LPVOID non_const_pointer = const_cast(pointer); +#ifdef DEBUG + return (Memory.mem_realloc(non_const_pointer, size, "luabind")); +#else //!DEBUG + return (Memory.mem_realloc(non_const_pointer, size)); +#endif //-DEBUG +} + +void setup_luabind_allocator() +{ + luabind::allocator = &luabind_allocator; + luabind::allocator_parameter = 0; +} + + +#ifdef USE_LUAJIT_ONE // [1/14/2015 Andrey] + +/* ---- start of LuaJIT extensions */ +static void l_message(lua_State* state, const char* msg) +{ + Msg("! [LUA_JIT] %s", msg); +} + + +static int report(lua_State* L, int status) +{ + if (status && !lua_isnil(L, -1)) + { + const char* msg = lua_tostring(L, -1); + if (msg == NULL) msg = "(error object is not a string)"; + l_message(L, msg); + lua_pop(L, 1); + } + return status; +} + +static int loadjitmodule(lua_State* L, const char* notfound) +{ + lua_getglobal(L, "require"); + lua_pushliteral(L, "jit."); + lua_pushvalue(L, -3); + lua_concat(L, 2); + if (lua_pcall(L, 1, 1, 0)) + { + const char* msg = lua_tostring(L, -1); + if (msg && !strncmp(msg, "module ", 7)) + { + l_message(L, notfound); + return 1; + } + else + return report(L, 1); + } + lua_getfield(L, -1, "start"); + lua_remove(L, -2); /* drop module table */ + return 0; +} + +/* JIT engine control command: try jit library first or load add-on module */ +static int dojitcmd(lua_State* L, const char* cmd) +{ + const char* val = strchr(cmd, '='); + lua_pushlstring(L, cmd, val ? val - cmd : xr_strlen(cmd)); + lua_getglobal(L, "jit"); /* get jit.* table */ + lua_pushvalue(L, -2); + lua_gettable(L, -2); /* lookup library function */ + if (!lua_isfunction(L, -1)) + { + lua_pop(L, 2); /* drop non-function and jit.* table, keep module name */ + if (loadjitmodule(L, "unknown luaJIT command")) + return 1; + } + else + { + lua_remove(L, -2); /* drop jit.* table */ + } + lua_remove(L, -2); /* drop module name */ + if (val) lua_pushstring(L, val + 1); + return report(L, lua_pcall(L, val ? 1 : 0, 0, 0)); +} + +void jit_command(lua_State* state, LPCSTR command) +{ + dojitcmd(state, command); +} + +#ifndef DEBUG +/* start optimizer */ +static int dojitopt(lua_State* L, const char* opt) +{ + lua_pushliteral(L, "opt"); + if (loadjitmodule(L, "LuaJIT optimizer module not installed")) + return 1; + lua_remove(L, -2); /* drop module name */ + if (*opt) lua_pushstring(L, opt); + return report(L, lua_pcall(L, *opt ? 1 : 0, 0, 0)); +} + +static void put_function(lua_State* state, u8 const* buffer, u32 const buffer_size, LPCSTR package_id) +{ + lua_getglobal(state, "package"); + lua_pushstring(state, "preload"); + lua_gettable(state, -2); + + lua_pushstring(state, package_id); + luaL_loadbuffer(state, (char*)buffer, buffer_size, package_id); + lua_settable(state, -3); +} + +/* ---- end of LuaJIT extensions */ +#endif //!DEBUG +#endif //-USE_LUAJIT_ONE + +extern int luaopen_lua_extensions(lua_State* L); + +void disable_os_funcs(lua_State* L) +{ + lua_getglobal(L, "os"); + lua_pushnil(L); + lua_setfield(L, -2, "execute"); + lua_pushnil(L); + lua_setfield(L, -2, "rename"); + lua_pushnil(L); + lua_setfield(L, -2, "remove"); + lua_pushnil(L); + lua_setfield(L, -2, "exit"); + lua_pop(L, 1); + + lua_getglobal(L, "io"); + lua_pushnil(L); + lua_setfield(L, -2, "popen"); + lua_pop(L, 1); +} + +void CScriptEngine::reinit() +{ + if (m_virtual_machine) + lua_close(m_virtual_machine); + +#ifdef USE_GSC_MEM_ALLOC + m_virtual_machine = lua_newstate(lua_alloc, NULL); +#else + m_virtual_machine = luaL_newstate(); +#endif //-USE_GSC_MEM_ALLOC + + if (!m_virtual_machine) + { + Msg("! ERROR : Cannot initialize script virtual machine!"); + return; + } + + +#ifndef USE_LUAJIT_ONE + luaL_openlibs(lua()); + if (strstr(Core.Params, "-nojit")) + luaJIT_setmode(lua(), 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); +#else // USE_LUAJIT_ONE + // initialize lua standard library functions + struct luajit + { + static void open_lib(lua_State* L, pcstr module_name, lua_CFunction function) + { + lua_pushcfunction(L, function); + lua_pushstring(L, module_name); + lua_call(L, 1, 0); + } + }; // struct lua; + + luajit::open_lib(lua(), "", luaopen_base); + luajit::open_lib(lua(), LUA_LOADLIBNAME, luaopen_package); + luajit::open_lib(lua(), LUA_TABLIBNAME, luaopen_table); + luajit::open_lib(lua(), LUA_IOLIBNAME, luaopen_io); + luajit::open_lib(lua(), LUA_OSLIBNAME, luaopen_os); + luajit::open_lib(lua(), LUA_MATHLIBNAME, luaopen_math); + luajit::open_lib(lua(), LUA_STRLIBNAME, luaopen_string); + +#ifdef DEBUG + luajit::open_lib(lua(), LUA_DBLIBNAME, luaopen_debug); +#else //!DEBUG + + if (strstr(Core.Params, "-dbg")) + luajit::open_lib(lua(), LUA_DBLIBNAME, luaopen_debug); +#endif //-DEBUG + + if (!strstr(Core.Params, "-nojit")) + { + luajit::open_lib(lua(), LUA_JITLIBNAME, luaopen_jit); +#ifndef DEBUG + put_function(lua(), opt_lua_binary, sizeof(opt_lua_binary), "jit.opt"); + put_function(lua(), opt_inline_lua_binary, sizeof(opt_lua_binary), "jit.opt_inline"); + dojitopt(lua(), "2"); +#endif //!DEBUG + } + +#endif //!USE_LUAJIT_ONE + + luaopen_lua_extensions(lua()); + disable_os_funcs(lua()); +} + +int CScriptEngine::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker) +{ +#ifndef NO_XRGAME_SCRIPT_ENGINE +# ifdef DEBUG + if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) + return(0); +# endif //-DEBUG +#endif //!NO_XRGAME_SCRIPT_ENGINE + + //#ifndef PRINT_CALL_STACK + //return (0); + //#else //PRINT_CALL_STACK +# ifndef NO_XRGAME_SCRIPT_ENGINE + //AVO: allow LUA debug prints (i.e.: ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!");) +# ifndef DEBUG + + if (!strstr(Core.Params, "-dbg")) + return (0); +# endif //!DEBUG +# ifndef LUA_DEBUG_PRINT +# ifdef DEBUG + if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) + return(0); +# endif //-DEBUG +# else //!LUA_DEBUG_PRINT + if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) + return(0); +# endif //-LUA_DEBUG_PRINT +#endif //-NO_XRGAME_SCRIPT_ENGINE + + LPCSTR S = "", SS = ""; + LPSTR S1; + string4096 S2; + switch (tLuaMessageType) + { + case ScriptStorage::eLuaMessageTypeInfo: + { + S = "* [LUA] "; + SS = "[INFO] "; + break; + } + case ScriptStorage::eLuaMessageTypeError: + { + S = "! [LUA] "; + SS = "[ERROR] "; + break; + } + case ScriptStorage::eLuaMessageTypeMessage: + { + S = "~ [LUA] "; + SS = "[MESSAGE] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookCall: + { + S = "[LUA][HOOK_CALL] "; + SS = "[CALL] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookReturn: + { + S = "[LUA][HOOK_RETURN] "; + SS = "[RETURN] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookLine: + { + S = "[LUA][HOOK_LINE] "; + SS = "[LINE] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookCount: + { + S = "[LUA][HOOK_COUNT] "; + SS = "[COUNT] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookTailReturn: + { + S = "[LUA][HOOK_TAIL_RETURN] "; + SS = "[TAIL_RETURN] "; + break; + } + default: NODEFAULT; + } + + xr_strcpy(S2, S); + S1 = S2 + xr_strlen(S); + int l_iResult = vsprintf(S1, caFormat, marker); + Msg("%s", S2); + + xr_strcpy(S2, SS); + S1 = S2 + xr_strlen(SS); + vsprintf(S1, caFormat, marker); + xr_strcat(S2, "\r\n"); + +#ifdef LUA_DEBUG_PRINT //DEBUG +# ifndef ENGINE_BUILD + ai().script_engine().m_output.w(S2, xr_strlen(S2) * sizeof(char)); +# endif //!ENGINE_BUILD +#endif //-LUA_DEBUG_PRINT DEBUG + + return (l_iResult); + //#endif //-PRINT_CALL_STACK +} + +//#ifdef PRINT_CALL_STACK +void CScriptEngine::print_stack() +{ +#ifdef DEBUG + if (!m_stack_is_ready) + return; + + m_stack_is_ready = false; +#endif //-DEBUG + + lua_State* L = lua(); + lua_Debug l_tDebugInfo; + for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); ++i) + { + lua_getinfo(L, "nSlu", &l_tDebugInfo); + if (!l_tDebugInfo.name) + { + script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, + l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); + //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); + } + else + { + if (!xr_strcmp(l_tDebugInfo.what, "C")) + { + script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); + //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); + } + else + { + script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, + l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); + //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); + } + } + } +} + +//#endif //-PRINT_CALL_STACK + +//AVO: added to stop duplicate stack output prints in log +int __cdecl CScriptEngine::script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) +{ + va_list marker; + va_start(marker, caFormat); + int result = vscript_log(tLuaMessageType, caFormat, marker); + va_end(marker); + return result; +} + +//-AVO + +int __cdecl CScriptEngine::script_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) +{ + va_list marker; + va_start(marker, caFormat); + int result = vscript_log(tLuaMessageType, caFormat, marker); + va_end(marker); + + static bool reenterability = false; + if (!reenterability) + { + reenterability = true; + if (tLuaMessageType == ScriptStorage::eLuaMessageTypeError) { + ai().script_engine().print_stack(); + } + else { + reenterability = false; + } + } + + // #ifdef PRINT_CALL_STACK + // # ifndef ENGINE_BUILD + // static bool reenterability = false; + // if (!reenterability) + // { + // reenterability = true; + // if (eLuaMessageTypeError == tLuaMessageType) + // ai().script_engine().print_stack(); + // reenterability = false; + // } + // # endif //!ENGINE_BUILD + // #endif //-PRINT_CALL_STACK + + return (result); +} + +int CScriptEngine::compile_buffer(lua_State* L, std::string caString, LPCSTR caScriptName, LPCSTR caNameSpaceName) +{ + luabind::functor compile; + if (ai().script_engine().namespace_loaded("script_compiler", true)) + { + if (ai().script_engine().functor("script_compiler.compile", compile)) + { + luabind::object result = compile(caString.c_str(), caScriptName, caNameSpaceName); + result.pushvalue(); + return 0; + } + } + + Msg("script_compiler not available, loading as raw Lua..."); + return luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); +} + +int CScriptEngine::load_buffer( + lua_State* L, + LPCSTR caBuffer, + size_t tSize, + LPCSTR caScriptName, + LPCSTR caNameSpaceName +) +{ + int l_iErrorCode = compile_buffer( + L, + std::string(caBuffer, caBuffer + tSize), + caScriptName, + caNameSpaceName + ); + if (l_iErrorCode) + { + //#ifdef DEBUG + if (strstr(Core.Params, "-dbg")) print_output(L, caScriptName, l_iErrorCode); + //#endif //-DEBUG + on_error(L); + } + return l_iErrorCode; +} + +bool CScriptEngine::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) +{ + int start = lua_gettop(lua()); + string_path l_caLuaFileName; + IReader* l_tpFileReader = FS.r_open(caScriptName); + + if (!l_tpFileReader) + { + script_log(eLuaMessageTypeError, "Cannot open file \"%s\"", caScriptName); + return (false); + } + + auto scriptContents = static_cast(l_tpFileReader->pointer()); + auto scriptLength = (size_t)l_tpFileReader->length(); + + strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); + if (load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName)) + { + // VERIFY (lua_gettop(lua()) >= 4); + // lua_pop (lua(),4); + // VERIFY (lua_gettop(lua()) == start - 3); + lua_settop(lua(), start); + FS.r_close(l_tpFileReader); + return (false); + } + FS.r_close(l_tpFileReader); + + int errFuncId = -1; +#ifdef USE_DEBUGGER +# ifndef USE_LUA_STUDIO + if (ai().script_engine().debugger()) + errFuncId = ai().script_engine().debugger()->PrepareLua(lua()); +# endif // #ifndef USE_LUA_STUDIO +#endif // #ifdef USE_DEBUGGER + if (0) //. + { + for (int i = 0; lua_type(lua(), -i - 1); i++) + Msg("%2d : %s", -i - 1, lua_typename(lua(), lua_type(lua(), -i - 1))); + } + + // because that's the first and the only call of the main chunk - there is no point to compile it + // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_OFF); // Oles + int l_iErrorCode = lua_pcall(lua(), 0, 0, (-1 == errFuncId) ? 0 : errFuncId); // new_Andy + // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_ON); // Oles + +#ifdef USE_DEBUGGER +# ifndef USE_LUA_STUDIO + if (ai().script_engine().debugger()) + ai().script_engine().debugger()->UnPrepareLua(lua(), errFuncId); +# endif // #ifndef USE_LUA_STUDIO +#endif // #ifdef USE_DEBUGGER + if (l_iErrorCode) + { + //#ifdef DEBUG + if (strstr(Core.Params, "-dbg")) print_output(lua(), caScriptName, l_iErrorCode); + //#endif + on_error(lua()); + lua_settop(lua(), start); + return (false); + } + + return (true); +} + +bool CScriptEngine::load_file_into_namespace(LPCSTR caScriptName, LPCSTR caNamespaceName) +{ + int start = lua_gettop(lua()); + if (!do_file(caScriptName, caNamespaceName)) + { + Msg("! [ERROR] --- Failed to load script %s", caNamespaceName); + lua_settop(lua(), start); + return (false); + } + VERIFY(lua_gettop(lua()) == start); + return (true); +} + +bool CScriptEngine::namespace_loaded(LPCSTR N, bool remove_from_stack) +{ + int start = lua_gettop(lua()); + lua_getglobal(lua(), "package"); + VERIFY(lua_istable(lua(), -1)); + lua_getfield(lua(), -1, "loaded"); + VERIFY(lua_istable(lua(), -1)); + lua_remove(lua(), -2); + string256 S2; + xr_strcpy(S2, N); + LPSTR S = S2; + for (;;) + { + if (!xr_strlen(S)) + { + VERIFY(lua_gettop(lua()) >= 1); + lua_pop(lua(), 1); + VERIFY(start == lua_gettop(lua())); + return (false); + } + LPSTR S1 = strchr(S, '.'); + if (S1) + *S1 = 0; + lua_pushstring(lua(), S); + lua_rawget(lua(), -2); + if (lua_isnil(lua(), -1)) + { + // lua_settop (lua(),0); + VERIFY(lua_gettop(lua()) >= 2); + lua_pop(lua(), 2); + VERIFY(start == lua_gettop(lua())); + return (false); // there is no namespace! + } + else if (!lua_istable(lua(), -1)) + { + std::string tn(lua_typename(lua(), -1)); + // lua_settop (lua(),0); + VERIFY(lua_gettop(lua()) >= 1); + lua_pop(lua(), 1); + VERIFY(start == lua_gettop(lua())); + FATAL((std::string("Error : the namespace name ") + N + " is already being used by non-table object of type " + tn + "\n").c_str()); + return (false); + } + lua_remove(lua(), -2); + if (S1) + S = ++S1; + else + break; + } + if (!remove_from_stack) + { + VERIFY(lua_gettop(lua()) == start + 1); + } + else + { + VERIFY(lua_gettop(lua()) >= 1); + lua_pop(lua(), 1); + VERIFY(lua_gettop(lua()) == start); + } + return (true); +} + +luabind::object CScriptEngine::name_space(LPCSTR namespace_name) +{ + string256 S1; + xr_strcpy(S1, namespace_name); + LPSTR S = S1; + luabind::object lua_namespace = luabind::get_globals(lua()); + lua_namespace = lua_namespace["package"]; + lua_namespace = lua_namespace["loaded"]; + for (;;) + { + if (!xr_strlen(S)) + return (lua_namespace); + LPSTR I = strchr(S, '.'); + if (!I) + return (lua_namespace[S]); + *I = 0; + lua_namespace = lua_namespace[S]; + S = I + 1; + } +} + +#include + +struct raii_guard : private boost::noncopyable +{ + int m_error_code; + LPCSTR const& m_error_description; + + raii_guard(int error_code, LPCSTR const& m_description) : m_error_code(error_code), + m_error_description(m_description) + { + } + + ~raii_guard() + { +#ifdef DEBUG + bool lua_studio_connected = !!ai().script_engine().debugger(); + if (!lua_studio_connected) +#endif //-DEBUG + { +#ifdef DEBUG + static bool const break_on_assert = !!strstr(Core.Params, "-break_on_assert"); +#else //!DEBUG + static bool const break_on_assert = false; //Alundaio: Can't get a proper stack trace with this enabled +#endif //-DEBUG + if (!m_error_code) + return; + + if (break_on_assert) + R_ASSERT2(!m_error_code, m_error_description); + else + Msg("! [SCRIPT ERROR]: %s", m_error_description); + } + } +}; //-struct raii_guard + +bool CScriptEngine::print_output(lua_State* L, LPCSTR caScriptFileName, int iErorCode) +{ + if (iErorCode) + print_error(L, iErorCode); + + LPCSTR S = "see call_stack for details!"; + + raii_guard guard(iErorCode, S); + + if (!lua_isstring(L, -1)) + return (false); + + S = lua_tostring(L, -1); + if (!xr_strcmp(S, "cannot resume dead coroutine")) + { + VERIFY2("Please do not return any values from main!!!", caScriptFileName); +#ifdef USE_DEBUGGER +# ifndef USE_LUA_STUDIO + if (ai().script_engine().debugger() && ai().script_engine().debugger()->Active()) { + ai().script_engine().debugger()->Write(S); + ai().script_engine().debugger()->ErrorBreak(); + } +# endif //!USE_LUA_STUDIO +#endif //-USE_DEBUGGER + } + else + { + if (!iErorCode) + script_log(ScriptStorage::eLuaMessageTypeInfo, "Output from %s", caScriptFileName); + script_log(iErorCode ? ScriptStorage::eLuaMessageTypeError : ScriptStorage::eLuaMessageTypeMessage, "%s", S); +#ifdef USE_DEBUGGER +# ifndef USE_LUA_STUDIO + if (ai().script_engine().debugger() && ai().script_engine().debugger()->Active()) { + ai().script_engine().debugger()->Write(S); + ai().script_engine().debugger()->ErrorBreak(); + } +# endif //!USE_LUA_STUDIO +#endif //-USE_DEBUGGER + } + return (true); +} + +void CScriptEngine::print_error(lua_State* L, int iErrorCode) +{ + switch (iErrorCode) + { + case LUA_ERRRUN: + { + script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT RUNTIME ERROR"); + break; + } + case LUA_ERRMEM: + { + script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (memory allocation)"); + break; + } + case LUA_ERRERR: + { + script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (while running the error handler function)"); + break; + } + case LUA_ERRFILE: + { + script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (while running file)"); + break; + } + case LUA_ERRSYNTAX: + { + script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT SYNTAX ERROR"); + break; + } + case LUA_YIELD: + { + script_log(ScriptStorage::eLuaMessageTypeInfo, "Thread is yielded"); + break; + } + default: NODEFAULT; + } +} + +#ifdef LUA_DEBUG_PRINT //DEBUG +void CScriptEngine::flush_log() +{ + string_path log_file_name; + strconcat(sizeof(log_file_name), log_file_name, Core.ApplicationName, "_", Core.UserName, "_lua.log"); + FS.update_path(log_file_name, "$logs$", log_file_name); + m_output.save_to(log_file_name); +} +#endif //-LUA_DEBUG_PRINT DEBUG + +int CScriptEngine::error_log(LPCSTR format, ...) +{ + va_list marker; + va_start(marker, format); + + LPCSTR S = "! [LUA][ERROR] "; + LPSTR S1; + string4096 S2; + xr_strcpy(S2, S); + S1 = S2 + xr_strlen(S); + + int result = vsprintf(S1, format, marker); + va_end(marker); + + Msg("%s", S2); + + return (result); +} + #ifdef USE_DEBUGGER # ifndef USE_LUA_STUDIO # include "script_debugger.h" @@ -136,36 +1003,46 @@ void CScriptEngine::disconnect_from_debugger () CScriptEngine::CScriptEngine() { - m_stack_level = 0; - m_last_no_file_length = 0; - *m_last_no_file = 0; + m_current_thread = 0; + +#ifdef DEBUG + m_stack_is_ready = false; +#endif //-DEBUG + + m_virtual_machine = 0; + m_stack_level = 0; + m_last_no_file_length = 0; + *m_last_no_file = 0; #ifdef USE_DEBUGGER # ifndef USE_LUA_STUDIO - m_scriptDebugger = NULL; - restartDebugger (); + m_scriptDebugger = NULL; + restartDebugger(); # else //USE_LUA_STUDIO - m_lua_studio_world = 0; + m_lua_studio_world = 0; # endif //!USE_LUA_STUDIO #endif } CScriptEngine::~CScriptEngine() { - while (!m_script_processes.empty()) - remove_script_process(m_script_processes.begin()->first); - #ifdef LUA_DEBUG_PRINT flush_log(); #endif //-LUA_DEBUG_PRINT #ifdef USE_DEBUGGER # ifndef USE_LUA_STUDIO - xr_delete (m_scriptDebugger); + xr_delete(m_scriptDebugger); # else // #ifndef USE_LUA_STUDIO disconnect_from_debugger(); # endif // #ifndef USE_LUA_STUDIO #endif + + if (m_virtual_machine) + lua_close(m_virtual_machine); + + while (!m_script_processes.empty()) + remove_script_process(m_script_processes.begin()->first); } void CScriptEngine::unload() @@ -324,7 +1201,7 @@ int auto_load_searcher(lua_State* L) LPCSTR name = lua_tostring(L, 1); - if (ai().script_engine().process_file_if_exists(name, false)) + if (ai().script_engine().load_package(name, false)) { lua_getglobal(L, "package"); lua_getfield(L, -1, "loaded"); @@ -363,7 +1240,7 @@ void CScriptEngine::init() m_lua_studio_world->remove (lua()); #endif // #ifdef USE_LUA_STUDIO - CScriptStorage::reinit(); + CScriptEngine::reinit(); #ifdef USE_LUA_STUDIO if (m_lua_studio_world || strstr(Core.Params, "-lua_studio")) { @@ -400,8 +1277,8 @@ void CScriptEngine::init() #endif // #ifndef USE_LUA_STUDIO // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); - process_file_if_exists("_init", false); - process_file_if_exists("_G", false); + load_package("_init", false); + load_package("_G", false); register_script_classes(); object_factory().register_script(); @@ -454,7 +1331,7 @@ void CScriptEngine::load_common_scripts() string256 I; for (u32 i = 0; i < n; ++i) { - process_file(_GetItem(caScriptString, i, I)); + load_package(_GetItem(caScriptString, i, I)); xr_strcat(I, "_initialize"); if (object("_G", I, LUA_TFUNCTION)) { @@ -469,7 +1346,7 @@ void CScriptEngine::load_common_scripts() xr_delete(l_tpIniFile); } -bool CScriptEngine::process_file_if_exists(LPCSTR file_name, bool warn_if_not_exist) +bool CScriptEngine::load_package(LPCSTR file_name, bool warn_if_not_exist) { u32 string_length = xr_strlen(file_name); if (!warn_if_not_exist && no_file_exists(file_name, string_length)) @@ -504,11 +1381,6 @@ bool CScriptEngine::process_file_if_exists(LPCSTR file_name, bool warn_if_not_ex return true; } -void CScriptEngine::process_file(LPCSTR file_name) -{ - process_file_if_exists(file_name, true); -} - void CScriptEngine::register_script_classes() { #ifdef DBG_DISABLE_SCRIPTS @@ -589,11 +1461,11 @@ bool CScriptEngine::function_object(LPCSTR function_to_call, luabind::object& ob { LPSTR file_name = strchr(name_space, '.'); if (!file_name) - process_file(name_space); + load_package(name_space); else { *file_name = 0; - process_file(name_space); + load_package(name_space); *file_name = '.'; } } diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index 162ec8524a..9e4bb249b9 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -8,11 +8,10 @@ #pragma once -#include "script_storage.h" +#include "script_storage_space.h" #include "script_export_space.h" #include "script_space_forward.h" #include "associative_vector.h" -#include "script_storage.h" //AVO: lua re-org #include "lua.hpp" @@ -25,6 +24,32 @@ #include "script_engine_space.h" +#ifndef MASTER_GOLD +# define USE_DEBUGGER +# define USE_LUA_STUDIO +#endif //-!MASTER_GOLD + +#ifdef XRGAME_EXPORTS +# ifndef MASTER_GOLD +# define PRINT_CALL_STACK +# endif //-!MASTER_GOLD +#else //!XRGAME_EXPORTS +# ifndef NDEBUG +# define PRINT_CALL_STACK +# endif // #ifndef NDEBUG +#endif //-XRGAME_EXPORTS + +//AVO: allow LUA debug prints (i.e.: ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!");) +#include "..\build_config_defines.h" +#ifndef DEBUG +# ifdef LUA_DEBUG_PRINT +# define PRINT_CALL_STACK +# endif +#endif //-!DEBUG +//-AVO + +using namespace ScriptStorage; + class CScriptProcess; class CScriptThread; struct lua_State; @@ -44,10 +69,75 @@ struct lua_Debug; # endif // #ifndef USE_LUA_STUDIO #endif -class CScriptEngine : public CScriptStorage +class CScriptEngine { +private: + lua_State* m_virtual_machine; + CScriptThread* m_current_thread; + BOOL m_jit; + +#ifdef DEBUG +public: + bool m_stack_is_ready; +#endif //-DEBUG + +#ifdef LUA_DEBUG_PRINT//PRINT_CALL_STACK +protected: + CMemoryWriter m_output; +#else +# ifdef DEBUG +protected: + CMemoryWriter m_output; +# endif //-DEBUG +#endif //-LUA_DEBUG_PRINT PRINT_CALL_STACK + +protected: + static int vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker); + bool do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName); + void reinit(); + +public: + //#ifdef PRINT_CALL_STACK + void print_stack(); + //AVO: added to stop duplicate stack output prints in log + static int __cdecl script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...); + //-AVO + //#endif //-PRINT_CALL_STACK + +public: + CScriptEngine(); + ~CScriptEngine(); + IC lua_State* lua(); + IC void current_thread(CScriptThread* thread); + IC CScriptThread* current_thread() const; + int compile_buffer( + lua_State* L, + std::string caString, + LPCSTR caScriptName, + LPCSTR caNameSpaceName = 0 + ); + int load_buffer( + lua_State* L, + LPCSTR caBuffer, + size_t tSize, + LPCSTR caScriptName, + LPCSTR caNameSpaceName = 0 + ); + bool load_file_into_namespace(LPCSTR caScriptName, LPCSTR caNamespaceName); + bool namespace_loaded(LPCSTR caName, bool remove_from_stack = true); + luabind::object name_space(LPCSTR namespace_name); + int error_log(LPCSTR caFormat, ...); + static int __cdecl script_log(ELuaMessageType message, LPCSTR caFormat, ...); + static bool print_output(lua_State* L, LPCSTR caScriptName, int iErorCode = 0); + static void print_error(lua_State* L, int iErrorCode); + void on_error(lua_State* L); + +#ifdef LUA_DEBUG_PRINT //DEBUG +public: + void flush_log(); +#endif //-LUA_DEBUG_PRINT DEBUG + public: - typedef CScriptStorage inherited; typedef ScriptEngine::EScriptProcessors EScriptProcessors; typedef associative_vector CScriptProcessStorage; @@ -74,10 +164,8 @@ class CScriptEngine : public CScriptStorage void add_no_file(LPCSTR file_name, u32 string_length); public: - CScriptEngine(); - virtual ~CScriptEngine(); void init(); - virtual void unload(); + void unload(); static int lua_panic(lua_State* L); static void lua_error(lua_State* L); static int lua_pcall_failed(lua_State* L); @@ -86,14 +174,12 @@ class CScriptEngine : public CScriptStorage #endif // #ifdef DEBUG void setup_callbacks(); void load_common_scripts(); - bool load_file(LPCSTR caScriptName, LPCSTR namespace_name); IC CScriptProcess* script_process(const EScriptProcessors& process_id) const; IC void add_script_process(const EScriptProcessors& process_id, CScriptProcess* script_process); void remove_script_process(const EScriptProcessors& process_id); void setup_auto_load(); + bool load_package(LPCSTR file_name, bool warn_if_not_exist = true); void unload_package(LPCSTR package); - bool process_file_if_exists(LPCSTR file_name, bool warn_if_not_exist); - void process_file(LPCSTR file_name); protected: bool object(LPCSTR caIdentifier, int type); bool object(LPCSTR caNamespaceName, LPCSTR caIdentifier, int type); @@ -117,7 +203,6 @@ class CScriptEngine : public CScriptStorage inline cs::lua_studio::world* debugger () const { return m_lua_studio_world; } # endif // ifndef USE_LUA_STUDIO #endif - virtual void on_error(lua_State* state); void collect_all_garbage(); DECLARE_SCRIPT_REGISTER_FUNCTION diff --git a/src/xrServerEntities/script_engine_inline.h b/src/xrServerEntities/script_engine_inline.h index 1770f0d6bd..558bed3213 100644 --- a/src/xrServerEntities/script_engine_inline.h +++ b/src/xrServerEntities/script_engine_inline.h @@ -8,6 +8,22 @@ #pragma once +IC lua_State* CScriptEngine::lua() +{ + return (m_virtual_machine); +} + +IC void CScriptEngine::current_thread(CScriptThread* thread) +{ + VERIFY((thread && !m_current_thread) || !thread); + m_current_thread = thread; +} + +IC CScriptThread* CScriptEngine::current_thread() const +{ + return (m_current_thread); +} + IC void CScriptEngine::add_script_process(const EScriptProcessors& process_id, CScriptProcess* script_process) { // CScriptProcessStorage::const_iterator I = m_script_processes.find(process_id); diff --git a/src/xrServerEntities/script_engine_script.cpp b/src/xrServerEntities/script_engine_script.cpp index 2d23b21318..56c1d9a555 100644 --- a/src/xrServerEntities/script_engine_script.cpp +++ b/src/xrServerEntities/script_engine_script.cpp @@ -121,7 +121,7 @@ LPCSTR user_name() void prefetch_module(LPCSTR file_name) { - ai().script_engine().process_file(file_name); + ai().script_engine().load_package(file_name); } struct profile_timer_script diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp deleted file mode 100644 index acc1dfd4d2..0000000000 --- a/src/xrServerEntities/script_storage.cpp +++ /dev/null @@ -1,900 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_storage.cpp -// Created : 01.04.2004 -// Modified : [1/14/2015 Andrey] -// Author : Dmitriy Iassenev -// Description : XRay Script Storage -//////////////////////////////////////////////////////////////////////////// - -#include "pch_script.h" -#include "script_storage.h" -#include "script_thread.h" -#include "../xrCore/mezz_stringbuffer.h" -#include - -#if !defined(DEBUG) && defined(USE_LUAJIT_ONE) -# include "opt.lua.h" -# include "opt_inline.lua.h" -#endif //!DEBUG && USE_LUAJIT_ONE -#ifndef USE_LUAJIT_ONE -#include "lua.hpp" -#endif - -#ifndef ENGINE_BUILD -# include "script_engine.h" -# include "ai_space.h" -#else //ENGINE_BUILD -# define NO_XRGAME_SCRIPT_ENGINE -#endif //!ENGINE_BUILD - -#ifndef XRGAME_EXPORTS -# define NO_XRGAME_SCRIPT_ENGINE -#endif //!XRGAME_EXPORTS - -#ifndef NO_XRGAME_SCRIPT_ENGINE -# include "ai_debug.h" -#endif //!NO_XRGAME_SCRIPT_ENGINE - -#ifdef USE_DEBUGGER -# include "script_debugger.h" -#endif - -#ifndef PURE_ALLOC -//# ifndef USE_MEMORY_MONITOR -//# define USE_DL_ALLOCATOR -//# endif //!USE_MEMORY_MONITOR -#endif //!PURE_ALLOC - -#ifndef USE_DL_ALLOCATOR -static void* lua_alloc(void* ud, void* ptr, size_t osize, size_t nsize) -{ - (void)ud; - (void)osize; - if (nsize == 0) - { - xr_free(ptr); - return NULL; - } - else -#ifdef DEBUG_MEMORY_NAME - return Memory.mem_realloc (ptr, nsize, "LUA"); -#else // DEBUG_MEMORY_MANAGER - return Memory.mem_realloc(ptr, nsize); -#endif // DEBUG_MEMORY_MANAGER -} - -u32 game_lua_memory_usage() -{ - return (0); -} -#else //USE_DL_ALLOCATOR - -# ifdef USE_ARENA_ALLOCATOR - static const u32 s_arena_size = 96*1024*1024; - static char s_fake_array[s_arena_size]; -// static doug_lea_allocator s_allocator( s_fake_array, s_arena_size, "lua" ); -# else //-USE_ARENA_ALLOCATOR -// static doug_lea_allocator s_allocator(0, 0, "lua"); -# endif //-USE_ARENA_ALLOCATOR - -static void *lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) -{ -#ifndef USE_MEMORY_MONITOR - (void)ud; - (void) osize; - if (!nsize) - { - s_allocator.free_impl(ptr); - return 0; - } - if (!ptr) - return s_allocator.malloc_impl((u32) nsize); - - return s_allocator.realloc_impl(ptr, (u32) nsize); -#else //USE_MEMORY_MONITOR - if ( !nsize ) { - memory_monitor::monitor_free(ptr); - s_allocator.free_impl (ptr); - return NULL; - } - - if ( !ptr ) { - void* const result = s_allocator.malloc_impl((u32)nsize); - memory_monitor::monitor_alloc (result,nsize,"LUA"); - return result; - } - - memory_monitor::monitor_free (ptr); - void* const result = s_allocator.realloc_impl(ptr, (u32)nsize); - memory_monitor::monitor_alloc (result,nsize,"LUA"); - return result; -#endif //!USE_MEMORY_MONITOR -} - -u32 game_lua_memory_usage() -{ - return (s_allocator.get_allocated_size()); -} -#endif //!USE_DL_ALLOCATOR - -static LPVOID __cdecl luabind_allocator( - luabind::memory_allocation_function_parameter const, - void const* const pointer, - size_t const size -) -{ - if (!size) - { - LPVOID non_const_pointer = const_cast(pointer); - xr_free(non_const_pointer); - return (0); - } - - if (!pointer) - { -#ifdef DEBUG - return ( Memory.mem_alloc(size, "luabind") ); -#else //!DEBUG - return (Memory.mem_alloc(size)); -#endif //-DEBUG - } - - LPVOID non_const_pointer = const_cast(pointer); -#ifdef DEBUG - return ( Memory.mem_realloc(non_const_pointer, size, "luabind") ); -#else //!DEBUG - return (Memory.mem_realloc(non_const_pointer, size)); -#endif //-DEBUG -} - -void setup_luabind_allocator() -{ - luabind::allocator = &luabind_allocator; - luabind::allocator_parameter = 0; -} - - -#ifdef USE_LUAJIT_ONE // [1/14/2015 Andrey] - -/* ---- start of LuaJIT extensions */ -static void l_message(lua_State* state, const char *msg) -{ - Msg("! [LUA_JIT] %s", msg); -} - - -static int report(lua_State *L, int status) -{ - if (status && !lua_isnil(L, -1)) - { - const char *msg = lua_tostring(L, -1); - if (msg == NULL) msg = "(error object is not a string)"; - l_message(L, msg); - lua_pop(L, 1); - } - return status; -} - -static int loadjitmodule(lua_State *L, const char *notfound) -{ - lua_getglobal(L, "require"); - lua_pushliteral(L, "jit."); - lua_pushvalue(L, -3); - lua_concat(L, 2); - if (lua_pcall(L, 1, 1, 0)) - { - const char *msg = lua_tostring(L, -1); - if (msg && !strncmp(msg, "module ", 7)) - { - l_message(L, notfound); - return 1; - } - else - return report(L, 1); - } - lua_getfield(L, -1, "start"); - lua_remove(L, -2); /* drop module table */ - return 0; -} - -/* JIT engine control command: try jit library first or load add-on module */ -static int dojitcmd(lua_State *L, const char *cmd) -{ - const char *val = strchr(cmd, '='); - lua_pushlstring(L, cmd, val ? val - cmd : xr_strlen(cmd)); - lua_getglobal(L, "jit"); /* get jit.* table */ - lua_pushvalue(L, -2); - lua_gettable(L, -2); /* lookup library function */ - if (!lua_isfunction(L, -1)) - { - lua_pop(L, 2); /* drop non-function and jit.* table, keep module name */ - if (loadjitmodule(L, "unknown luaJIT command")) - return 1; - } - else - { - lua_remove(L, -2); /* drop jit.* table */ - } - lua_remove(L, -2); /* drop module name */ - if (val) lua_pushstring(L, val + 1); - return report(L, lua_pcall(L, val ? 1 : 0, 0, 0)); -} - -void jit_command(lua_State* state, LPCSTR command) -{ - dojitcmd(state, command); -} - -#ifndef DEBUG -/* start optimizer */ -static int dojitopt(lua_State *L, const char *opt) -{ - lua_pushliteral(L, "opt"); - if (loadjitmodule(L, "LuaJIT optimizer module not installed")) - return 1; - lua_remove(L, -2); /* drop module name */ - if (*opt) lua_pushstring(L, opt); - return report(L, lua_pcall(L, *opt ? 1 : 0, 0, 0)); -} - -static void put_function(lua_State* state, u8 const* buffer, u32 const buffer_size, LPCSTR package_id) -{ - lua_getglobal(state, "package"); - lua_pushstring(state, "preload"); - lua_gettable(state, -2); - - lua_pushstring(state, package_id); - luaL_loadbuffer(state, (char*) buffer, buffer_size, package_id); - lua_settable(state, -3); -} - -/* ---- end of LuaJIT extensions */ -#endif //!DEBUG -#endif //-USE_LUAJIT_ONE - -CScriptStorage::CScriptStorage() -{ - m_current_thread = 0; - -#ifdef DEBUG - m_stack_is_ready = false; -#endif //-DEBUG - - m_virtual_machine = 0; - -#ifdef USE_LUA_STUDIO -# ifndef USE_DEBUGGER - STATIC_CHECK( false, Do_Not_Define_USE_LUA_STUDIO_macro_without_USE_DEBUGGER_macro ); -# endif //!USE_DEBUGGER -#endif //-USE_LUA_STUDIO -} - -CScriptStorage::~CScriptStorage() -{ - if (m_virtual_machine) - lua_close(m_virtual_machine); -} - -extern int luaopen_lua_extensions(lua_State* L); - -void disable_os_funcs(lua_State* L) -{ - lua_getglobal(L, "os"); - lua_pushnil(L); - lua_setfield(L, -2, "execute"); - lua_pushnil(L); - lua_setfield(L, -2, "rename"); - lua_pushnil(L); - lua_setfield(L, -2, "remove"); - lua_pushnil(L); - lua_setfield(L, -2, "exit"); - lua_pop(L, 1); - - lua_getglobal(L, "io"); - lua_pushnil(L); - lua_setfield(L, -2, "popen"); - lua_pop(L, 1); -} - -void CScriptStorage::reinit() -{ - if (m_virtual_machine) - lua_close(m_virtual_machine); - -#ifdef USE_GSC_MEM_ALLOC - m_virtual_machine = lua_newstate(lua_alloc, NULL); -#else - m_virtual_machine = luaL_newstate(); -#endif //-USE_GSC_MEM_ALLOC - - if (!m_virtual_machine) - { - Msg("! ERROR : Cannot initialize script virtual machine!"); - return; - } - - -#ifndef USE_LUAJIT_ONE - luaL_openlibs(lua()); - if (strstr(Core.Params, "-nojit")) - luaJIT_setmode(lua(), 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); -#else // USE_LUAJIT_ONE - // initialize lua standard library functions - struct luajit - { - static void open_lib(lua_State *L, pcstr module_name, lua_CFunction function) - { - lua_pushcfunction(L, function); - lua_pushstring(L, module_name); - lua_call(L, 1, 0); - } - }; // struct lua; - - luajit::open_lib(lua(), "", luaopen_base); - luajit::open_lib(lua(), LUA_LOADLIBNAME, luaopen_package); - luajit::open_lib(lua(), LUA_TABLIBNAME, luaopen_table); - luajit::open_lib(lua(), LUA_IOLIBNAME, luaopen_io); - luajit::open_lib(lua(), LUA_OSLIBNAME, luaopen_os); - luajit::open_lib(lua(), LUA_MATHLIBNAME, luaopen_math); - luajit::open_lib(lua(), LUA_STRLIBNAME, luaopen_string); - -#ifdef DEBUG - luajit::open_lib(lua(), LUA_DBLIBNAME, luaopen_debug); -#else //!DEBUG - - if (strstr(Core.Params, "-dbg")) - luajit::open_lib(lua(), LUA_DBLIBNAME, luaopen_debug); -#endif //-DEBUG - - if (!strstr(Core.Params, "-nojit")) - { - luajit::open_lib(lua(), LUA_JITLIBNAME, luaopen_jit); -#ifndef DEBUG - put_function(lua(), opt_lua_binary, sizeof(opt_lua_binary), "jit.opt"); - put_function(lua(), opt_inline_lua_binary, sizeof(opt_lua_binary), "jit.opt_inline"); - dojitopt(lua(), "2"); -#endif //!DEBUG - } - -#endif //!USE_LUAJIT_ONE - - luaopen_lua_extensions(lua()); - disable_os_funcs(lua()); -} - -int CScriptStorage::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker) -{ -#ifndef NO_XRGAME_SCRIPT_ENGINE -# ifdef DEBUG - if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) - return(0); -# endif //-DEBUG -#endif //!NO_XRGAME_SCRIPT_ENGINE - - //#ifndef PRINT_CALL_STACK - //return (0); - //#else //PRINT_CALL_STACK -# ifndef NO_XRGAME_SCRIPT_ENGINE - //AVO: allow LUA debug prints (i.e.: ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!");) -# ifndef DEBUG - - if (!strstr(Core.Params, "-dbg")) - return (0); -# endif //!DEBUG -# ifndef LUA_DEBUG_PRINT -# ifdef DEBUG - if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) - return(0); -# endif //-DEBUG -# else //!LUA_DEBUG_PRINT - if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) - return(0); -# endif //-LUA_DEBUG_PRINT -#endif //-NO_XRGAME_SCRIPT_ENGINE - - LPCSTR S = "", SS = ""; - LPSTR S1; - string4096 S2; - switch (tLuaMessageType) - { - case ScriptStorage::eLuaMessageTypeInfo: - { - S = "* [LUA] "; - SS = "[INFO] "; - break; - } - case ScriptStorage::eLuaMessageTypeError: - { - S = "! [LUA] "; - SS = "[ERROR] "; - break; - } - case ScriptStorage::eLuaMessageTypeMessage: - { - S = "~ [LUA] "; - SS = "[MESSAGE] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookCall: - { - S = "[LUA][HOOK_CALL] "; - SS = "[CALL] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookReturn: - { - S = "[LUA][HOOK_RETURN] "; - SS = "[RETURN] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookLine: - { - S = "[LUA][HOOK_LINE] "; - SS = "[LINE] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookCount: - { - S = "[LUA][HOOK_COUNT] "; - SS = "[COUNT] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookTailReturn: - { - S = "[LUA][HOOK_TAIL_RETURN] "; - SS = "[TAIL_RETURN] "; - break; - } - default: NODEFAULT; - } - - xr_strcpy(S2, S); - S1 = S2 + xr_strlen(S); - int l_iResult = vsprintf(S1, caFormat, marker); - Msg("%s", S2); - - xr_strcpy(S2, SS); - S1 = S2 + xr_strlen(SS); - vsprintf(S1, caFormat, marker); - xr_strcat(S2, "\r\n"); - -#ifdef LUA_DEBUG_PRINT //DEBUG -# ifndef ENGINE_BUILD - ai().script_engine().m_output.w(S2,xr_strlen(S2)*sizeof(char)); -# endif //!ENGINE_BUILD -#endif //-LUA_DEBUG_PRINT DEBUG - - return (l_iResult); - //#endif //-PRINT_CALL_STACK -} - -//#ifdef PRINT_CALL_STACK -void CScriptStorage::print_stack() -{ -#ifdef DEBUG - if (!m_stack_is_ready) - return; - - m_stack_is_ready = false; -#endif //-DEBUG - - lua_State* L = lua(); - lua_Debug l_tDebugInfo; - for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); ++i) - { - lua_getinfo(L, "nSlu", &l_tDebugInfo); - if (!l_tDebugInfo.name) - { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, - l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); - } - else - { - if (!xr_strcmp(l_tDebugInfo.what, "C")) - { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); - } - else - { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, - l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); - } - } - } -} - -//#endif //-PRINT_CALL_STACK - -//AVO: added to stop duplicate stack output prints in log -int __cdecl CScriptStorage::script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) -{ - va_list marker; - va_start(marker, caFormat); - int result = vscript_log(tLuaMessageType, caFormat, marker); - va_end(marker); - return result; -} - -//-AVO - -int __cdecl CScriptStorage::script_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) -{ - va_list marker; - va_start(marker, caFormat); - int result = vscript_log(tLuaMessageType, caFormat, marker); - va_end(marker); - - static bool reenterability = false; - if (!reenterability) - { - reenterability = true; - if (tLuaMessageType == ScriptStorage::eLuaMessageTypeError) { - ai().script_engine().print_stack(); - } else { - reenterability = false; - } - } - - // #ifdef PRINT_CALL_STACK - // # ifndef ENGINE_BUILD - // static bool reenterability = false; - // if (!reenterability) - // { - // reenterability = true; - // if (eLuaMessageTypeError == tLuaMessageType) - // ai().script_engine().print_stack(); - // reenterability = false; - // } - // # endif //!ENGINE_BUILD - // #endif //-PRINT_CALL_STACK - - return (result); -} - -int CScriptStorage::compile_buffer(lua_State* L, std::string caString, LPCSTR caScriptName, LPCSTR caNameSpaceName) -{ - luabind::functor compile; - if (ai().script_engine().namespace_loaded("script_compiler", true)) - { - if (ai().script_engine().functor("script_compiler.compile", compile)) - { - luabind::object result = compile(caString.c_str(), caScriptName, caNameSpaceName); - result.pushvalue(); - return 0; - } - } - - Msg("script_compiler not available, loading as raw Lua..."); - return luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); -} - -int CScriptStorage::load_buffer( - lua_State* L, - LPCSTR caBuffer, - size_t tSize, - LPCSTR caScriptName, - LPCSTR caNameSpaceName -) -{ - int l_iErrorCode = compile_buffer( - L, - std::string(caBuffer, caBuffer + tSize), - caScriptName, - caNameSpaceName - ); - if (l_iErrorCode) - { -//#ifdef DEBUG - if (strstr(Core.Params, "-dbg")) print_output(L,caScriptName,l_iErrorCode); -//#endif //-DEBUG - on_error(L); - } - return l_iErrorCode; -} - -bool CScriptStorage::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) -{ - int start = lua_gettop(lua()); - string_path l_caLuaFileName; - IReader* l_tpFileReader = FS.r_open(caScriptName); - - if (!l_tpFileReader) - { - script_log(eLuaMessageTypeError, "Cannot open file \"%s\"", caScriptName); - return (false); - } - - auto scriptContents = static_cast(l_tpFileReader->pointer()); - auto scriptLength = (size_t)l_tpFileReader->length(); - - strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); - if (load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName)) - { - // VERIFY (lua_gettop(lua()) >= 4); - // lua_pop (lua(),4); - // VERIFY (lua_gettop(lua()) == start - 3); - lua_settop(lua(), start); - FS.r_close(l_tpFileReader); - return (false); - } - FS.r_close(l_tpFileReader); - - int errFuncId = -1; -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if( ai().script_engine().debugger() ) - errFuncId = ai().script_engine().debugger()->PrepareLua(lua()); -# endif // #ifndef USE_LUA_STUDIO -#endif // #ifdef USE_DEBUGGER - if (0) //. - { - for (int i = 0; lua_type(lua(), -i - 1); i++) - Msg("%2d : %s", -i - 1, lua_typename(lua(), lua_type(lua(), -i - 1))); - } - - // because that's the first and the only call of the main chunk - there is no point to compile it - // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_OFF); // Oles - int l_iErrorCode = lua_pcall(lua(), 0, 0, (-1 == errFuncId) ? 0 : errFuncId); // new_Andy - // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_ON); // Oles - -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if( ai().script_engine().debugger() ) - ai().script_engine().debugger()->UnPrepareLua(lua(),errFuncId); -# endif // #ifndef USE_LUA_STUDIO -#endif // #ifdef USE_DEBUGGER - if (l_iErrorCode) - { -//#ifdef DEBUG - if (strstr(Core.Params, "-dbg")) print_output(lua(),caScriptName,l_iErrorCode); -//#endif - on_error(lua()); - lua_settop(lua(), start); - return (false); - } - - return (true); -} - -bool CScriptStorage::load_file_into_namespace(LPCSTR caScriptName, LPCSTR caNamespaceName) -{ - int start = lua_gettop(lua()); - if (!do_file(caScriptName, caNamespaceName)) - { - Msg("! [ERROR] --- Failed to load script %s", caNamespaceName); - lua_settop(lua(), start); - return (false); - } - VERIFY(lua_gettop(lua()) == start); - return (true); -} - -bool CScriptStorage::namespace_loaded(LPCSTR N, bool remove_from_stack) -{ - int start = lua_gettop(lua()); - lua_getglobal(lua(), "package"); - VERIFY(lua_istable(lua(), -1)); - lua_getfield(lua(), -1, "loaded"); - VERIFY(lua_istable(lua(), -1)); - lua_remove(lua(), -2); - string256 S2; - xr_strcpy(S2, N); - LPSTR S = S2; - for (;;) - { - if (!xr_strlen(S)) - { - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(start == lua_gettop(lua())); - return (false); - } - LPSTR S1 = strchr(S, '.'); - if (S1) - *S1 = 0; - lua_pushstring(lua(), S); - lua_rawget(lua(), -2); - if (lua_isnil(lua(), -1)) - { - // lua_settop (lua(),0); - VERIFY(lua_gettop(lua()) >= 2); - lua_pop(lua(), 2); - VERIFY(start == lua_gettop(lua())); - return (false); // there is no namespace! - } - else if (!lua_istable(lua(), -1)) - { - std::string tn(lua_typename(lua(), -1)); - // lua_settop (lua(),0); - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(start == lua_gettop(lua())); - FATAL((std::string("Error : the namespace name ") + N + " is already being used by non-table object of type " + tn + "\n").c_str()); - return (false); - } - lua_remove(lua(), -2); - if (S1) - S = ++S1; - else - break; - } - if (!remove_from_stack) - { - VERIFY(lua_gettop(lua()) == start + 1); - } - else - { - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(lua_gettop(lua()) == start); - } - return (true); -} - -luabind::object CScriptStorage::name_space(LPCSTR namespace_name) -{ - string256 S1; - xr_strcpy(S1, namespace_name); - LPSTR S = S1; - luabind::object lua_namespace = luabind::get_globals(lua()); - lua_namespace = lua_namespace["package"]; - lua_namespace = lua_namespace["loaded"]; - for (;;) - { - if (!xr_strlen(S)) - return (lua_namespace); - LPSTR I = strchr(S, '.'); - if (!I) - return (lua_namespace[S]); - *I = 0; - lua_namespace = lua_namespace[S]; - S = I + 1; - } -} - -#include - -struct raii_guard : private boost::noncopyable -{ - int m_error_code; - LPCSTR const& m_error_description; - - raii_guard(int error_code, LPCSTR const& m_description) : m_error_code(error_code), - m_error_description(m_description) - { - } - - ~raii_guard() - { -#ifdef DEBUG - bool lua_studio_connected = !!ai().script_engine().debugger(); - if (!lua_studio_connected) -#endif //-DEBUG - { -#ifdef DEBUG - static bool const break_on_assert = !!strstr(Core.Params,"-break_on_assert"); -#else //!DEBUG - static bool const break_on_assert = false; //Alundaio: Can't get a proper stack trace with this enabled -#endif //-DEBUG - if (!m_error_code) - return; - - if (break_on_assert) - R_ASSERT2(!m_error_code, m_error_description); - else - Msg("! [SCRIPT ERROR]: %s", m_error_description); - } - } -}; //-struct raii_guard - -bool CScriptStorage::print_output(lua_State* L, LPCSTR caScriptFileName, int iErorCode) -{ - if (iErorCode) - print_error(L, iErorCode); - - LPCSTR S = "see call_stack for details!"; - - raii_guard guard(iErorCode, S); - - if (!lua_isstring(L, -1)) - return (false); - - S = lua_tostring(L, -1); - if (!xr_strcmp(S, "cannot resume dead coroutine")) - { - VERIFY2("Please do not return any values from main!!!", caScriptFileName); -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if(ai().script_engine().debugger() && ai().script_engine().debugger()->Active() ){ - ai().script_engine().debugger()->Write(S); - ai().script_engine().debugger()->ErrorBreak(); - } -# endif //!USE_LUA_STUDIO -#endif //-USE_DEBUGGER - } - else - { - if (!iErorCode) - script_log(ScriptStorage::eLuaMessageTypeInfo, "Output from %s", caScriptFileName); - script_log(iErorCode ? ScriptStorage::eLuaMessageTypeError : ScriptStorage::eLuaMessageTypeMessage, "%s", S); -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if (ai().script_engine().debugger() && ai().script_engine().debugger()->Active()) { - ai().script_engine().debugger()->Write (S); - ai().script_engine().debugger()->ErrorBreak (); - } -# endif //!USE_LUA_STUDIO -#endif //-USE_DEBUGGER - } - return (true); -} - -void CScriptStorage::print_error(lua_State* L, int iErrorCode) -{ - switch (iErrorCode) - { - case LUA_ERRRUN: - { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT RUNTIME ERROR"); - break; - } - case LUA_ERRMEM: - { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (memory allocation)"); - break; - } - case LUA_ERRERR: - { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (while running the error handler function)"); - break; - } - case LUA_ERRFILE: - { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (while running file)"); - break; - } - case LUA_ERRSYNTAX: - { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT SYNTAX ERROR"); - break; - } - case LUA_YIELD: - { - script_log(ScriptStorage::eLuaMessageTypeInfo, "Thread is yielded"); - break; - } - default: NODEFAULT; - } -} - -#ifdef LUA_DEBUG_PRINT //DEBUG -void CScriptStorage::flush_log() -{ - string_path log_file_name; - strconcat (sizeof(log_file_name),log_file_name,Core.ApplicationName,"_",Core.UserName,"_lua.log"); - FS.update_path (log_file_name,"$logs$",log_file_name); - m_output.save_to (log_file_name); -} -#endif //-LUA_DEBUG_PRINT DEBUG - -int CScriptStorage::error_log(LPCSTR format, ...) -{ - va_list marker; - va_start(marker, format); - - LPCSTR S = "! [LUA][ERROR] "; - LPSTR S1; - string4096 S2; - xr_strcpy(S2, S); - S1 = S2 + xr_strlen(S); - - int result = vsprintf(S1, format, marker); - va_end(marker); - - Msg("%s", S2); - - return (result); -} diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h deleted file mode 100644 index 87c88f8655..0000000000 --- a/src/xrServerEntities/script_storage.h +++ /dev/null @@ -1,115 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_storage.h -// Created : 01.04.2004 -// Modified : [1/14/2015 Andrey] -// Author : Dmitriy Iassenev -// Description : XRay Script Storage -//////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include "script_storage_space.h" -#include "script_space_forward.h" -#include -#include -#include - -struct lua_State; -class CScriptThread; - -#ifndef MASTER_GOLD -# define USE_DEBUGGER -# define USE_LUA_STUDIO -#endif //-!MASTER_GOLD - -#ifdef XRGAME_EXPORTS -# ifndef MASTER_GOLD -# define PRINT_CALL_STACK -# endif //-!MASTER_GOLD -#else //!XRGAME_EXPORTS -# ifndef NDEBUG -# define PRINT_CALL_STACK -# endif // #ifndef NDEBUG -#endif //-XRGAME_EXPORTS - -//AVO: allow LUA debug prints (i.e.: ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!");) -#include "..\build_config_defines.h" -#ifndef DEBUG -# ifdef LUA_DEBUG_PRINT -# define PRINT_CALL_STACK -# endif -#endif //-!DEBUG -//-AVO - -using namespace ScriptStorage; - -class CScriptStorage -{ -private: - lua_State* m_virtual_machine; - CScriptThread* m_current_thread; - BOOL m_jit; - -#ifdef DEBUG -public: - bool m_stack_is_ready ; -#endif //-DEBUG - -#ifdef LUA_DEBUG_PRINT//PRINT_CALL_STACK -protected: - CMemoryWriter m_output; -#else -# ifdef DEBUG -protected: - CMemoryWriter m_output; -# endif //-DEBUG -#endif //-LUA_DEBUG_PRINT PRINT_CALL_STACK - -protected: - static int vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker); - bool do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName); - void reinit(); - -public: - //#ifdef PRINT_CALL_STACK - void print_stack(); - //AVO: added to stop duplicate stack output prints in log - static int __cdecl script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...); - //-AVO - //#endif //-PRINT_CALL_STACK - -public: - CScriptStorage(); - virtual ~CScriptStorage(); - IC lua_State* lua(); - IC void current_thread(CScriptThread* thread); - IC CScriptThread* current_thread() const; - int compile_buffer( - lua_State* L, - std::string caString, - LPCSTR caScriptName, - LPCSTR caNameSpaceName = 0 - ); - int load_buffer( - lua_State* L, - LPCSTR caBuffer, - size_t tSize, - LPCSTR caScriptName, - LPCSTR caNameSpaceName = 0 - ); - bool load_file_into_namespace(LPCSTR caScriptName, LPCSTR caNamespaceName); - bool namespace_loaded(LPCSTR caName, bool remove_from_stack = true); - luabind::object name_space(LPCSTR namespace_name); - int error_log(LPCSTR caFormat, ...); - static int __cdecl script_log(ELuaMessageType message, LPCSTR caFormat, ...); - static bool print_output(lua_State* L, LPCSTR caScriptName, int iErorCode = 0); - static void print_error(lua_State* L, int iErrorCode); - virtual void on_error(lua_State* L) = 0; - -#ifdef LUA_DEBUG_PRINT //DEBUG -public: - void flush_log(); -#endif //-LUA_DEBUG_PRINT DEBUG -}; - -#include "script_storage_inline.h" diff --git a/src/xrServerEntities/script_storage_inline.h b/src/xrServerEntities/script_storage_inline.h deleted file mode 100644 index 8cd7788466..0000000000 --- a/src/xrServerEntities/script_storage_inline.h +++ /dev/null @@ -1,25 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_storage_inline.h -// Created : 01.04.2004 -// Modified : 01.04.2004 -// Author : Dmitriy Iassenev -// Description : XRay Script Storage inline functions -//////////////////////////////////////////////////////////////////////////// - -#pragma once - -IC lua_State* CScriptStorage::lua() -{ - return (m_virtual_machine); -} - -IC void CScriptStorage::current_thread(CScriptThread* thread) -{ - VERIFY((thread && !m_current_thread) || !thread); - m_current_thread = thread; -} - -IC CScriptThread* CScriptStorage::current_thread() const -{ - return (m_current_thread); -} diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp index 2c762ef912..67d424bed9 100644 --- a/src/xrServerEntities/script_thread.cpp +++ b/src/xrServerEntities/script_thread.cpp @@ -50,7 +50,7 @@ CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string) if (!do_string) { m_script_name = caBuffer; - ai().script_engine().process_file(caBuffer); + ai().script_engine().load_package(caBuffer); } else { From 6806d78f080d5e17af5a92f6a4df3e2bf73447a8 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 22 May 2025 07:28:00 +0100 Subject: [PATCH 23/76] Move sandboxing and `package.loader` setup into Lua --- gamedata/scripts/_init.script | 31 +- ...t_compiler.script => scam_compiler.script} | 7 +- gamedata/scripts/scam_loader.script | 28 + gamedata/scripts/scam_print.script | 24 + gamedata/scripts/scam_sandbox.script | 18 + src/xrServerEntities/script_engine.cpp | 1267 ++++++++--------- src/xrServerEntities/script_engine.h | 143 +- 7 files changed, 747 insertions(+), 771 deletions(-) rename gamedata/scripts/{script_compiler.script => scam_compiler.script} (86%) create mode 100644 gamedata/scripts/scam_loader.script create mode 100644 gamedata/scripts/scam_print.script create mode 100644 gamedata/scripts/scam_sandbox.script diff --git a/gamedata/scripts/_init.script b/gamedata/scripts/_init.script index b7a5b86892..6c599fa9d6 100644 --- a/gamedata/scripts/_init.script +++ b/gamedata/scripts/_init.script @@ -1,28 +1,13 @@ -function print(...) - local str = "" - for _,v in ipairs({...}) do - if #str > 0 then - str = str .. " " - end +load_package("scam_print") - local s = nil - if (type(v) == 'userdata') then - s = 'userdata' - else - s = tostring(v) - end +print("Instigating S.C.A.M.") - str = str .. s - end +load_package("scam_sandbox") - if (log) then - log(str) - else - get_console():execute("load ~#debug msg:" .. str) - end -end +load_package("scam_loader") -print("Lua initializing...") -print("package.loaded._G:", package.loaded._G) +require("scam_compiler").set_default_macro( + require("macro_wua").expand +) -require("script_compiler").set_default_macro(require("macro_wua").expand) \ No newline at end of file +load_package("_G") diff --git a/gamedata/scripts/script_compiler.script b/gamedata/scripts/scam_compiler.script similarity index 86% rename from gamedata/scripts/script_compiler.script rename to gamedata/scripts/scam_compiler.script index 336fa8a285..487604d699 100644 --- a/gamedata/scripts/script_compiler.script +++ b/gamedata/scripts/scam_compiler.script @@ -25,10 +25,11 @@ function compile(src, script_name, namespace_name) if state.default_macro then print("loading via default macro") - return loadstring(state.default_macro(src, namespace_name), script_name) + src = state.default_macro(src, namespace_name) + else + print("loading raw lua") end - print("loading raw lua") return loadstring(src, script_name) end @@ -36,7 +37,7 @@ function set_default_macro(mac) state.default_macro = mac end -package.loaded["script_compiler"] = { +package.loaded["scam_compiler"] = { compile = compile, set_default_macro = set_default_macro } diff --git a/gamedata/scripts/scam_loader.script b/gamedata/scripts/scam_loader.script new file mode 100644 index 0000000000..1aa55f6ab0 --- /dev/null +++ b/gamedata/scripts/scam_loader.script @@ -0,0 +1,28 @@ +-- Setup script load paths +local scripts_path = getFS():update_path("$game_scripts$", "") +local paths = { + "?.script", + "?.lua", + "?.fnl", +} + +for i=#paths,1,-1 do + local path = paths[i] + package.path = scripts_path .. path .. ";" .. package.path +end + +-- Inject our custom X-Ray FS implementation next +table.insert( + package.loaders, + 2, + function(name) + if load_package(name, false) then + local res = package.loaded[name] + return function() + return res + end + end + + return "\n\t" .. name .. " not present in X-Ray filesystem" + end +) diff --git a/gamedata/scripts/scam_print.script b/gamedata/scripts/scam_print.script new file mode 100644 index 0000000000..9c0e80da9c --- /dev/null +++ b/gamedata/scripts/scam_print.script @@ -0,0 +1,24 @@ +-- Emplace working print function +function print(...) + local str = "" + for _,v in ipairs({...}) do + if #str > 0 then + str = str .. " " + end + + local s = nil + if (type(v) == 'userdata') then + s = 'userdata' + else + s = tostring(v) + end + + str = str .. s + end + + if (log) then + log(str) + else + get_console():execute("load ~#debug msg:" .. str) + end +end \ No newline at end of file diff --git a/gamedata/scripts/scam_sandbox.script b/gamedata/scripts/scam_sandbox.script new file mode 100644 index 0000000000..46ebf49736 --- /dev/null +++ b/gamedata/scripts/scam_sandbox.script @@ -0,0 +1,18 @@ +-- Disable OS functions +local disabled = { + os = { + "execute", + "rename", + "remove", + "exit", + }, + io = { + "popen" + } +} + +for k,v in pairs(disabled) do + for i=1,#v do + _G[k][v[i]] = nil + end +end diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index f81ee2b02d..1c13b38378 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #if !defined(DEBUG) && defined(USE_LUAJIT_ONE) # include "opt.lua.h" @@ -51,6 +52,42 @@ //# endif //!USE_MEMORY_MONITOR #endif //!PURE_ALLOC +struct raii_guard : private boost::noncopyable +{ + int m_error_code; + LPCSTR const& m_error_description; + + raii_guard(int error_code, LPCSTR const& m_description) : m_error_code(error_code), + m_error_description(m_description) + { + } + + ~raii_guard() + { +#ifdef DEBUG + bool lua_studio_connected = !!ai().script_engine().debugger(); + if (!lua_studio_connected) +#endif //-DEBUG + { +#ifdef DEBUG + static bool const break_on_assert = !!strstr(Core.Params, "-break_on_assert"); +#else //!DEBUG + static bool const break_on_assert = false; //Alundaio: Can't get a proper stack trace with this enabled +#endif //-DEBUG + if (!m_error_code) + return; + + if (break_on_assert) + R_ASSERT2(!m_error_code, m_error_description); + else + Msg("! [SCRIPT ERROR]: %s", m_error_description); + } + } +}; //-struct raii_guard + +extern void export_classes(lua_State* L); +extern int luaopen_lua_extensions(lua_State* L); + #ifndef USE_DL_ALLOCATOR static void* lua_alloc(void* ud, void* ptr, size_t osize, size_t nsize) { @@ -258,25 +295,120 @@ static void put_function(lua_State* state, u8 const* buffer, u32 const buffer_si #endif //!DEBUG #endif //-USE_LUAJIT_ONE -extern int luaopen_lua_extensions(lua_State* L); +CScriptEngine::CScriptEngine() +{ + m_current_thread = 0; + +#ifdef DEBUG + m_stack_is_ready = false; +#endif //-DEBUG + + m_virtual_machine = 0; + m_stack_level = 0; + +#ifdef USE_DEBUGGER +# ifndef USE_LUA_STUDIO + m_scriptDebugger = NULL; + restartDebugger(); +# else //USE_LUA_STUDIO + m_lua_studio_world = 0; +# endif //!USE_LUA_STUDIO +#endif +} + +CScriptEngine::~CScriptEngine() +{ +#ifdef LUA_DEBUG_PRINT + flush_log(); +#endif //-LUA_DEBUG_PRINT -void disable_os_funcs(lua_State* L) +#ifdef USE_DEBUGGER +# ifndef USE_LUA_STUDIO + xr_delete(m_scriptDebugger); +# else // #ifndef USE_LUA_STUDIO + disconnect_from_debugger(); +# endif // #ifndef USE_LUA_STUDIO +#endif + + if (m_virtual_machine) + lua_close(m_virtual_machine); + + while (!m_script_processes.empty()) + remove_script_process(m_script_processes.begin()->first); +} + +int do_load_package(lua_State* L) +{ + assert(lua_gettop(L) == 1); + assert(lua_isstring(L, 1)); + + lua_pushboolean( + L, + ai().script_engine().load_package( + lua_tostring(L, 1), + false + ) + ); + + return (1); +} + +void CScriptEngine::init() { - lua_getglobal(L, "os"); - lua_pushnil(L); - lua_setfield(L, -2, "execute"); - lua_pushnil(L); - lua_setfield(L, -2, "rename"); - lua_pushnil(L); - lua_setfield(L, -2, "remove"); - lua_pushnil(L); - lua_setfield(L, -2, "exit"); - lua_pop(L, 1); - - lua_getglobal(L, "io"); - lua_pushnil(L); - lua_setfield(L, -2, "popen"); - lua_pop(L, 1); +#ifdef USE_LUA_STUDIO + bool lua_studio_connected = !!m_lua_studio_world; + if (lua_studio_connected) + m_lua_studio_world->remove(lua()); +#endif // #ifdef USE_LUA_STUDIO + + CScriptEngine::reinit(); + +#ifdef USE_LUA_STUDIO + if (m_lua_studio_world || strstr(Core.Params, "-lua_studio")) { + if (!lua_studio_connected) + try_connect_to_debugger(); + else { +#ifdef USE_LUAJIT_ONE + jit_command(lua(), "debug=2"); + jit_command(lua(), "off"); +#else + luaJIT_setmode(lua(), 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); +#endif + m_lua_studio_world->add(lua()); + } + } +#endif // #ifdef USE_LUA_STUDIO + + luabind::open(lua()); + setup_callbacks(); + export_classes(lua()); + +#ifdef DEBUG + m_stack_is_ready = true; +#endif + +#ifndef USE_LUA_STUDIO +# ifdef DEBUG +# if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO) + if (!debugger() || !debugger()->Active()) +# endif // #if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO) + lua_sethook(lua(), lua_hook_call, LUA_MASKLINE | LUA_MASKCALL | LUA_MASKRET, 0); +# endif // #ifdef DEBUG +#endif // #ifndef USE_LUA_STUDIO + // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); + + lua_pushcfunction(lua(), do_load_package); + lua_setglobal(lua(), "load_package"); + + load_package("_init", false); + + register_script_classes(); + object_factory().register_script(); + +#ifdef XRGAME_EXPORTS + load_common_scripts(); +#endif + m_stack_level = lua_gettop(lua()); } void CScriptEngine::reinit() @@ -342,208 +474,118 @@ void CScriptEngine::reinit() #endif //!USE_LUAJIT_ONE luaopen_lua_extensions(lua()); - disable_os_funcs(lua()); } -int CScriptEngine::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker) +void CScriptEngine::unload() { -#ifndef NO_XRGAME_SCRIPT_ENGINE -# ifdef DEBUG - if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) - return(0); -# endif //-DEBUG -#endif //!NO_XRGAME_SCRIPT_ENGINE - - //#ifndef PRINT_CALL_STACK - //return (0); - //#else //PRINT_CALL_STACK -# ifndef NO_XRGAME_SCRIPT_ENGINE - //AVO: allow LUA debug prints (i.e.: ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!");) -# ifndef DEBUG - - if (!strstr(Core.Params, "-dbg")) - return (0); -# endif //!DEBUG -# ifndef LUA_DEBUG_PRINT -# ifdef DEBUG - if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) - return(0); -# endif //-DEBUG -# else //!LUA_DEBUG_PRINT - if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) - return(0); -# endif //-LUA_DEBUG_PRINT -#endif //-NO_XRGAME_SCRIPT_ENGINE - - LPCSTR S = "", SS = ""; - LPSTR S1; - string4096 S2; - switch (tLuaMessageType) - { - case ScriptStorage::eLuaMessageTypeInfo: - { - S = "* [LUA] "; - SS = "[INFO] "; - break; - } - case ScriptStorage::eLuaMessageTypeError: - { - S = "! [LUA] "; - SS = "[ERROR] "; - break; - } - case ScriptStorage::eLuaMessageTypeMessage: - { - S = "~ [LUA] "; - SS = "[MESSAGE] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookCall: - { - S = "[LUA][HOOK_CALL] "; - SS = "[CALL] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookReturn: - { - S = "[LUA][HOOK_RETURN] "; - SS = "[RETURN] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookLine: - { - S = "[LUA][HOOK_LINE] "; - SS = "[LINE] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookCount: - { - S = "[LUA][HOOK_COUNT] "; - SS = "[COUNT] "; - break; - } - case ScriptStorage::eLuaMessageTypeHookTailReturn: - { - S = "[LUA][HOOK_TAIL_RETURN] "; - SS = "[TAIL_RETURN] "; - break; - } - default: NODEFAULT; - } - - xr_strcpy(S2, S); - S1 = S2 + xr_strlen(S); - int l_iResult = vsprintf(S1, caFormat, marker); - Msg("%s", S2); - - xr_strcpy(S2, SS); - S1 = S2 + xr_strlen(SS); - vsprintf(S1, caFormat, marker); - xr_strcat(S2, "\r\n"); - -#ifdef LUA_DEBUG_PRINT //DEBUG -# ifndef ENGINE_BUILD - ai().script_engine().m_output.w(S2, xr_strlen(S2) * sizeof(char)); -# endif //!ENGINE_BUILD -#endif //-LUA_DEBUG_PRINT DEBUG - - return (l_iResult); - //#endif //-PRINT_CALL_STACK + lua_settop(lua(), m_stack_level); } -//#ifdef PRINT_CALL_STACK -void CScriptEngine::print_stack() +int CScriptEngine::lua_panic(lua_State* L) { -#ifdef DEBUG - if (!m_stack_is_ready) - return; - - m_stack_is_ready = false; -#endif //-DEBUG + ai().script_engine().print_stack(); + print_output(L, "PANIC", LUA_ERRRUN); + return (0); +} - lua_State* L = lua(); +// demonized: get lua stack in array +static std::vector get_lua_stack(lua_State* L) +{ + std::vector res; lua_Debug l_tDebugInfo; for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); ++i) { lua_getinfo(L, "nSlu", &l_tDebugInfo); if (!l_tDebugInfo.name) { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, - l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); + res.push_back(make_string("%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, "")); } else { if (!xr_strcmp(l_tDebugInfo.what, "C")) { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); + res.push_back(make_string("%2d : [C ] %s", i, l_tDebugInfo.name)); } else { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, - l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); + res.push_back(make_string("%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name)); } } } + return res; } -//#endif //-PRINT_CALL_STACK - -//AVO: added to stop duplicate stack output prints in log -int __cdecl CScriptEngine::script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) +void CScriptEngine::lua_error(lua_State* L) { - va_list marker; - va_start(marker, caFormat); - int result = vscript_log(tLuaMessageType, caFormat, marker); - va_end(marker); - return result; + ai().script_engine().print_stack(); + print_output(L, "", LUA_ERRRUN); + ai().script_engine().on_error(L); + + // demonized: print first line with lua error + auto stack = get_lua_stack(L); + std::string lua_error_line = ""; + for (auto const& s : stack) { + if (s.find("[Lua]") != std::string::npos) { + lua_error_line = s; + break; + } + } + + auto error_str = make_string("\n%s\n\nLUA error: %s\n\nCheck log for details", lua_error_line.c_str(), lua_tostring(L, -1)); + LPCSTR error_msg = error_str.c_str(); + +#if !XRAY_EXCEPTIONS + Debug.fatal(DEBUG_INFO, error_msg); +#else + throw lua_tostring(L, -1); +#endif } -//-AVO +void printLuaStack() +{ + ai().script_engine().print_stack(); +} -int __cdecl CScriptEngine::script_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) +int CScriptEngine::lua_pcall_failed(lua_State* L) { - va_list marker; - va_start(marker, caFormat); - int result = vscript_log(tLuaMessageType, caFormat, marker); - va_end(marker); + ai().script_engine().print_stack(); + print_output(L, "", LUA_ERRRUN); + ai().script_engine().on_error(L); - static bool reenterability = false; - if (!reenterability) - { - reenterability = true; - if (tLuaMessageType == ScriptStorage::eLuaMessageTypeError) { - ai().script_engine().print_stack(); - } - else { - reenterability = false; + // demonized: print first line with lua error + auto stack = get_lua_stack(L); + std::string lua_error_line = ""; + for (auto const& s : stack) { + if (s.find("[Lua]") != std::string::npos) { + lua_error_line = s; + break; } } - // #ifdef PRINT_CALL_STACK - // # ifndef ENGINE_BUILD - // static bool reenterability = false; - // if (!reenterability) - // { - // reenterability = true; - // if (eLuaMessageTypeError == tLuaMessageType) - // ai().script_engine().print_stack(); - // reenterability = false; - // } - // # endif //!ENGINE_BUILD - // #endif //-PRINT_CALL_STACK + auto error_str = make_string("\n%s\n\nLUA error: %s\n\nCheck log for details", lua_error_line.c_str(), lua_isstring(L, -1) ? lua_tostring(L, -1) : ""); + LPCSTR error_msg = error_str.c_str(); - return (result); +#if !XRAY_EXCEPTIONS + Debug.fatal(DEBUG_INFO, error_msg); +#endif + if (lua_isstring(L, -1)) + lua_pop(L, 1); + return (LUA_ERRRUN); +} + +void lua_cast_failed(lua_State* L, LUABIND_TYPE_INFO info) +{ + CScriptEngine::print_output(L, "", LUA_ERRRUN); + + Debug.fatal(DEBUG_INFO, "LUA error: cannot cast lua value to %s", info->name()); } int CScriptEngine::compile_buffer(lua_State* L, std::string caString, LPCSTR caScriptName, LPCSTR caNameSpaceName) { luabind::functor compile; - if (ai().script_engine().namespace_loaded("script_compiler", true)) + if (ai().script_engine().namespace_loaded("scam_compiler", true)) { - if (ai().script_engine().functor("script_compiler.compile", compile)) + if (ai().script_engine().functor("scam_compiler.compile", compile)) { luabind::object result = compile(caString.c_str(), caScriptName, caNameSpaceName); result.pushvalue(); @@ -551,7 +593,7 @@ int CScriptEngine::compile_buffer(lua_State* L, std::string caString, LPCSTR caS } } - Msg("script_compiler not available, loading as raw Lua..."); + Msg("scam_compiler not available, loading as raw Lua..."); return luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); } @@ -579,83 +621,6 @@ int CScriptEngine::load_buffer( return l_iErrorCode; } -bool CScriptEngine::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName) -{ - int start = lua_gettop(lua()); - string_path l_caLuaFileName; - IReader* l_tpFileReader = FS.r_open(caScriptName); - - if (!l_tpFileReader) - { - script_log(eLuaMessageTypeError, "Cannot open file \"%s\"", caScriptName); - return (false); - } - - auto scriptContents = static_cast(l_tpFileReader->pointer()); - auto scriptLength = (size_t)l_tpFileReader->length(); - - strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); - if (load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNameSpaceName)) - { - // VERIFY (lua_gettop(lua()) >= 4); - // lua_pop (lua(),4); - // VERIFY (lua_gettop(lua()) == start - 3); - lua_settop(lua(), start); - FS.r_close(l_tpFileReader); - return (false); - } - FS.r_close(l_tpFileReader); - - int errFuncId = -1; -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if (ai().script_engine().debugger()) - errFuncId = ai().script_engine().debugger()->PrepareLua(lua()); -# endif // #ifndef USE_LUA_STUDIO -#endif // #ifdef USE_DEBUGGER - if (0) //. - { - for (int i = 0; lua_type(lua(), -i - 1); i++) - Msg("%2d : %s", -i - 1, lua_typename(lua(), lua_type(lua(), -i - 1))); - } - - // because that's the first and the only call of the main chunk - there is no point to compile it - // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_OFF); // Oles - int l_iErrorCode = lua_pcall(lua(), 0, 0, (-1 == errFuncId) ? 0 : errFuncId); // new_Andy - // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_ON); // Oles - -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if (ai().script_engine().debugger()) - ai().script_engine().debugger()->UnPrepareLua(lua(), errFuncId); -# endif // #ifndef USE_LUA_STUDIO -#endif // #ifdef USE_DEBUGGER - if (l_iErrorCode) - { - //#ifdef DEBUG - if (strstr(Core.Params, "-dbg")) print_output(lua(), caScriptName, l_iErrorCode); - //#endif - on_error(lua()); - lua_settop(lua(), start); - return (false); - } - - return (true); -} - -bool CScriptEngine::load_file_into_namespace(LPCSTR caScriptName, LPCSTR caNamespaceName) -{ - int start = lua_gettop(lua()); - if (!do_file(caScriptName, caNamespaceName)) - { - Msg("! [ERROR] --- Failed to load script %s", caNamespaceName); - lua_settop(lua(), start); - return (false); - } - VERIFY(lua_gettop(lua()) == start); - return (true); -} - bool CScriptEngine::namespace_loaded(LPCSTR N, bool remove_from_stack) { int start = lua_gettop(lua()); @@ -696,8 +661,9 @@ bool CScriptEngine::namespace_loaded(LPCSTR N, bool remove_from_stack) VERIFY(lua_gettop(lua()) >= 1); lua_pop(lua(), 1); VERIFY(start == lua_gettop(lua())); - FATAL((std::string("Error : the namespace name ") + N + " is already being used by non-table object of type " + tn + "\n").c_str()); - return (false); + if (S1) + FATAL((std::string("Error : the namespace name ") + N + " is already being used by non-table object of type " + tn + "\n").c_str()); + return (true); } lua_remove(lua(), -2); if (S1) @@ -739,40 +705,199 @@ luabind::object CScriptEngine::name_space(LPCSTR namespace_name) } } -#include - -struct raii_guard : private boost::noncopyable +int CScriptEngine::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker) { - int m_error_code; - LPCSTR const& m_error_description; +#ifndef NO_XRGAME_SCRIPT_ENGINE +# ifdef DEBUG + if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) + return(0); +# endif //-DEBUG +#endif //!NO_XRGAME_SCRIPT_ENGINE - raii_guard(int error_code, LPCSTR const& m_description) : m_error_code(error_code), - m_error_description(m_description) + //#ifndef PRINT_CALL_STACK + //return (0); + //#else //PRINT_CALL_STACK +# ifndef NO_XRGAME_SCRIPT_ENGINE + //AVO: allow LUA debug prints (i.e.: ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!");) +# ifndef DEBUG + + if (!strstr(Core.Params, "-dbg")) + return (0); +# endif //!DEBUG +# ifndef LUA_DEBUG_PRINT +# ifdef DEBUG + if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) + return(0); +# endif //-DEBUG +# else //!LUA_DEBUG_PRINT + if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) + return(0); +# endif //-LUA_DEBUG_PRINT +#endif //-NO_XRGAME_SCRIPT_ENGINE + + LPCSTR S = "", SS = ""; + LPSTR S1; + string4096 S2; + switch (tLuaMessageType) + { + case ScriptStorage::eLuaMessageTypeInfo: { + S = "* [LUA] "; + SS = "[INFO] "; + break; } - - ~raii_guard() + case ScriptStorage::eLuaMessageTypeError: { + S = "! [LUA] "; + SS = "[ERROR] "; + break; + } + case ScriptStorage::eLuaMessageTypeMessage: + { + S = "~ [LUA] "; + SS = "[MESSAGE] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookCall: + { + S = "[LUA][HOOK_CALL] "; + SS = "[CALL] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookReturn: + { + S = "[LUA][HOOK_RETURN] "; + SS = "[RETURN] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookLine: + { + S = "[LUA][HOOK_LINE] "; + SS = "[LINE] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookCount: + { + S = "[LUA][HOOK_COUNT] "; + SS = "[COUNT] "; + break; + } + case ScriptStorage::eLuaMessageTypeHookTailReturn: + { + S = "[LUA][HOOK_TAIL_RETURN] "; + SS = "[TAIL_RETURN] "; + break; + } + default: NODEFAULT; + } + + xr_strcpy(S2, S); + S1 = S2 + xr_strlen(S); + int l_iResult = vsprintf(S1, caFormat, marker); + Msg("%s", S2); + + xr_strcpy(S2, SS); + S1 = S2 + xr_strlen(SS); + vsprintf(S1, caFormat, marker); + xr_strcat(S2, "\r\n"); + +#ifdef LUA_DEBUG_PRINT //DEBUG +# ifndef ENGINE_BUILD + ai().script_engine().m_output.w(S2, xr_strlen(S2) * sizeof(char)); +# endif //!ENGINE_BUILD +#endif //-LUA_DEBUG_PRINT DEBUG + + return (l_iResult); + //#endif //-PRINT_CALL_STACK +} + +//#ifdef PRINT_CALL_STACK +void CScriptEngine::print_stack() +{ #ifdef DEBUG - bool lua_studio_connected = !!ai().script_engine().debugger(); - if (!lua_studio_connected) -#endif //-DEBUG - { -#ifdef DEBUG - static bool const break_on_assert = !!strstr(Core.Params, "-break_on_assert"); -#else //!DEBUG - static bool const break_on_assert = false; //Alundaio: Can't get a proper stack trace with this enabled + if (!m_stack_is_ready) + return; + + m_stack_is_ready = false; #endif //-DEBUG - if (!m_error_code) - return; - if (break_on_assert) - R_ASSERT2(!m_error_code, m_error_description); + lua_State* L = lua(); + lua_Debug l_tDebugInfo; + for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); ++i) + { + lua_getinfo(L, "nSlu", &l_tDebugInfo); + if (!l_tDebugInfo.name) + { + script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, + l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); + //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); + } + else + { + if (!xr_strcmp(l_tDebugInfo.what, "C")) + { + script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); + //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); + } else - Msg("! [SCRIPT ERROR]: %s", m_error_description); + { + script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, + l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); + //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); + } } } -}; //-struct raii_guard +} + +//#endif //-PRINT_CALL_STACK + +//AVO: added to stop duplicate stack output prints in log +int __cdecl CScriptEngine::script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) +{ + va_list marker; + va_start(marker, caFormat); + int result = vscript_log(tLuaMessageType, caFormat, marker); + va_end(marker); + return result; +} + +//-AVO + +int __cdecl CScriptEngine::script_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) +{ + va_list marker; + va_start(marker, caFormat); + int result = vscript_log(tLuaMessageType, caFormat, marker); + va_end(marker); + + static bool reenterability = false; + if (!reenterability) + { + reenterability = true; + if (tLuaMessageType == ScriptStorage::eLuaMessageTypeError) { + ai().script_engine().print_stack(); + } + else { + reenterability = false; + } + } + + // #ifdef PRINT_CALL_STACK + // # ifndef ENGINE_BUILD + // static bool reenterability = false; + // if (!reenterability) + // { + // reenterability = true; + // if (eLuaMessageTypeError == tLuaMessageType) + // ai().script_engine().print_stack(); + // reenterability = false; + // } + // # endif //!ENGINE_BUILD + // #endif //-PRINT_CALL_STACK + + return (result); +} + bool CScriptEngine::print_output(lua_State* L, LPCSTR caScriptFileName, int iErorCode) { @@ -949,205 +1074,57 @@ static void initialize_lua_studio ( lua_State* state, cs::lua_studio::world*& wo s_script_debugger_handle, "_cs_lua_studio_backend_destroy_world@4" ); - R_ASSERT2 (s_destroy_world, "can't find function \"cs_lua_studio_backend_destroy_world\" in the library"); - - engine = xr_new(); - world = s_create_world( *engine, false, false ); - VERIFY (world); - - s_old_log_callback = SetLogCB(&log_callback); - -#ifdef USE_LUAJIT_ONE - jit_command (state, "debug=2"); - jit_command (state, "off"); -#else - luaJIT_setmode(state, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); -#endif - - world->add (state); -} - -static void finalize_lua_studio ( lua_State* state, cs::lua_studio::world*& world, lua_studio_engine*& engine) -{ - world->remove (state); - - VERIFY (world); - s_destroy_world (world); - world = 0; - - VERIFY (engine); - xr_delete (engine); - - FreeLibrary (s_script_debugger_handle); - s_script_debugger_handle = 0; - - SetLogCB (s_old_log_callback); -} - -void CScriptEngine::try_connect_to_debugger () -{ - if (m_lua_studio_world) - return; - - initialize_lua_studio ( lua(), m_lua_studio_world, m_lua_studio_engine ); -} - -void CScriptEngine::disconnect_from_debugger () -{ - if (!m_lua_studio_world) - return; - - finalize_lua_studio ( lua(), m_lua_studio_world, m_lua_studio_engine ); -} -#endif //-(USE_DEBUGGER) && defined(USE_LUA_STUDIO) - -CScriptEngine::CScriptEngine() -{ - m_current_thread = 0; - -#ifdef DEBUG - m_stack_is_ready = false; -#endif //-DEBUG - - m_virtual_machine = 0; - m_stack_level = 0; - m_last_no_file_length = 0; - *m_last_no_file = 0; - -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - m_scriptDebugger = NULL; - restartDebugger(); -# else //USE_LUA_STUDIO - m_lua_studio_world = 0; -# endif //!USE_LUA_STUDIO -#endif -} - -CScriptEngine::~CScriptEngine() -{ -#ifdef LUA_DEBUG_PRINT - flush_log(); -#endif //-LUA_DEBUG_PRINT - -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - xr_delete(m_scriptDebugger); -# else // #ifndef USE_LUA_STUDIO - disconnect_from_debugger(); -# endif // #ifndef USE_LUA_STUDIO -#endif + R_ASSERT2 (s_destroy_world, "can't find function \"cs_lua_studio_backend_destroy_world\" in the library"); - if (m_virtual_machine) - lua_close(m_virtual_machine); + engine = xr_new(); + world = s_create_world( *engine, false, false ); + VERIFY (world); - while (!m_script_processes.empty()) - remove_script_process(m_script_processes.begin()->first); -} + s_old_log_callback = SetLogCB(&log_callback); -void CScriptEngine::unload() -{ - lua_settop(lua(), m_stack_level); - m_last_no_file_length = 0; - *m_last_no_file = 0; -} +#ifdef USE_LUAJIT_ONE + jit_command (state, "debug=2"); + jit_command (state, "off"); +#else + luaJIT_setmode(state, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); +#endif -int CScriptEngine::lua_panic(lua_State* L) -{ - ai().script_engine().print_stack(); - print_output(L, "PANIC", LUA_ERRRUN); - return (0); + world->add (state); } -// demonized: get lua stack in array -static std::vector get_lua_stack(lua_State* L) +static void finalize_lua_studio ( lua_State* state, cs::lua_studio::world*& world, lua_studio_engine*& engine) { - std::vector res; - lua_Debug l_tDebugInfo; - for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); ++i) - { - lua_getinfo(L, "nSlu", &l_tDebugInfo); - if (!l_tDebugInfo.name) - { - res.push_back(make_string("%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, "")); - } else - { - if (!xr_strcmp(l_tDebugInfo.what, "C")) - { - res.push_back(make_string("%2d : [C ] %s", i, l_tDebugInfo.name)); - } else - { - res.push_back(make_string("%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name)); - } - } - } - return res; -} + world->remove (state); -void CScriptEngine::lua_error(lua_State* L) -{ - ai().script_engine().print_stack(); - print_output(L, "", LUA_ERRRUN); - ai().script_engine().on_error(L); - - // demonized: print first line with lua error - auto stack = get_lua_stack(L); - std::string lua_error_line = ""; - for (auto const& s : stack) { - if (s.find("[Lua]") != std::string::npos) { - lua_error_line = s; - break; - } - } + VERIFY (world); + s_destroy_world (world); + world = 0; - auto error_str = make_string("\n%s\n\nLUA error: %s\n\nCheck log for details", lua_error_line.c_str(), lua_tostring(L, -1)); - LPCSTR error_msg = error_str.c_str(); + VERIFY (engine); + xr_delete (engine); -#if !XRAY_EXCEPTIONS - Debug.fatal(DEBUG_INFO, error_msg); -#else - throw lua_tostring(L,-1); -#endif -} + FreeLibrary (s_script_debugger_handle); + s_script_debugger_handle = 0; -void printLuaStack() -{ - ai().script_engine().print_stack(); + SetLogCB (s_old_log_callback); } -int CScriptEngine::lua_pcall_failed(lua_State* L) +void CScriptEngine::try_connect_to_debugger () { - ai().script_engine().print_stack(); - print_output(L, "", LUA_ERRRUN); - ai().script_engine().on_error(L); - - // demonized: print first line with lua error - auto stack = get_lua_stack(L); - std::string lua_error_line = ""; - for (auto const& s : stack) { - if (s.find("[Lua]") != std::string::npos) { - lua_error_line = s; - break; - } - } - - auto error_str = make_string("\n%s\n\nLUA error: %s\n\nCheck log for details", lua_error_line.c_str(), lua_isstring(L, -1) ? lua_tostring(L, -1) : ""); - LPCSTR error_msg = error_str.c_str(); + if (m_lua_studio_world) + return; -#if !XRAY_EXCEPTIONS - Debug.fatal(DEBUG_INFO, error_msg); -#endif - if (lua_isstring(L, -1)) - lua_pop(L, 1); - return (LUA_ERRRUN); + initialize_lua_studio ( lua(), m_lua_studio_world, m_lua_studio_engine ); } -void lua_cast_failed(lua_State* L, LUABIND_TYPE_INFO info) +void CScriptEngine::disconnect_from_debugger () { - CScriptEngine::print_output(L, "", LUA_ERRRUN); + if (!m_lua_studio_world) + return; - Debug.fatal(DEBUG_INFO, "LUA error: cannot cast lua value to %s", info->name()); + finalize_lua_studio ( lua(), m_lua_studio_world, m_lua_studio_engine ); } +#endif //-(USE_DEBUGGER) && defined(USE_LUA_STUDIO) void CScriptEngine::setup_callbacks() { @@ -1188,125 +1165,120 @@ void CScriptEngine::lua_hook_call (lua_State *L, lua_Debug *dbg) } #endif -int auto_load_closure(lua_State* L) -{ - lua_pushvalue(L, lua_upvalueindex(1)); - return (1); -} - -int auto_load_searcher(lua_State* L) +void CScriptEngine::remove_script_process(const EScriptProcessors& process_id) { - assert(lua_gettop(L) == 1); - assert(lua_isstring(L, 1)); - - LPCSTR name = lua_tostring(L, 1); - - if (ai().script_engine().load_package(name, false)) + CScriptProcessStorage::iterator I = m_script_processes.find(process_id); + if (I != m_script_processes.end()) { - lua_getglobal(L, "package"); - lua_getfield(L, -1, "loaded"); - lua_pushstring(L, name); - lua_gettable(L, -2); - lua_remove(L, -2); - lua_pushcclosure(L, auto_load_closure, 1); - return (1); + xr_delete((*I).second); + m_script_processes.erase(I); } - - lua_pushstring(L, "\n\tFailure"); - return (1); } -void CScriptEngine::setup_auto_load() +bool CScriptEngine::load_package(LPCSTR caNamespaceName, bool warn_if_not_exist) { - lua_getglobal(lua(), "table"); - lua_getfield(lua(), -1, "insert"); - lua_remove(lua(), -2); - lua_getglobal(lua(), "package"); - lua_getfield(lua(), -1, "loaders"); - lua_remove(lua(), - 2); - lua_pushinteger(lua(), 2); - lua_pushcfunction(lua(), auto_load_searcher); - lua_call(lua(), 3, 0); -} - -extern void export_classes(lua_State* L); + if (*caNamespaceName && xr_strcmp(caNamespaceName, "_G") && namespace_loaded(caNamespaceName)) + { + return true; + } + string_path caScriptName, S1; + FS.update_path(caScriptName, "$game_scripts$", strconcat(sizeof(S1), S1, caNamespaceName, ".script")); + if (!warn_if_not_exist && !FS.exist(caScriptName)) + { +#ifdef DEBUG +# ifndef XRSE_FACTORY_EXPORTS + if (psAI_Flags.test(aiNilObjectAccess)) +# endif + { + print_stack(); + Msg("* trying to access variable %s, which doesn't exist, or to load script %s, which doesn't exist too", file_name, S); + m_stack_is_ready = true; + } +#endif + return false; + } -void CScriptEngine::init() -{ -#ifdef USE_LUA_STUDIO - bool lua_studio_connected = !!m_lua_studio_world; - if (lua_studio_connected) - m_lua_studio_world->remove (lua()); -#endif // #ifdef USE_LUA_STUDIO + //#ifndef MASTER_GOLD + if (strstr(Core.Params, "-dbg")) + Msg("* loading script %s", S1); + //#endif // MASTER_GOLD - CScriptEngine::reinit(); + if (!caNamespaceName) + caNamespaceName = "_G"; + + int start = lua_gettop(lua()); + string_path l_caLuaFileName; + IReader* l_tpFileReader = FS.r_open(caScriptName); -#ifdef USE_LUA_STUDIO - if (m_lua_studio_world || strstr(Core.Params, "-lua_studio")) { - if (!lua_studio_connected) - try_connect_to_debugger (); - else { -#ifdef USE_LUAJIT_ONE - jit_command (lua(), "debug=2"); - jit_command (lua(), "off"); -#else - luaJIT_setmode(lua(), 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); -#endif - m_lua_studio_world->add (lua()); - } + if (!l_tpFileReader) + { + script_log(eLuaMessageTypeError, "Cannot open file \"%s\"", caScriptName); + return (false); } -#endif // #ifdef USE_LUA_STUDIO - luabind::open(lua()); - setup_callbacks(); - export_classes(lua()); - setup_auto_load(); + auto scriptContents = static_cast(l_tpFileReader->pointer()); + auto scriptLength = (size_t)l_tpFileReader->length(); -#ifdef DEBUG - m_stack_is_ready = true; -#endif + strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); + if (load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNamespaceName)) + { + // VERIFY (lua_gettop(lua()) >= 4); + // lua_pop (lua(),4); + // VERIFY (lua_gettop(lua()) == start - 3); + lua_settop(lua(), start); + FS.r_close(l_tpFileReader); + return (false); + } + FS.r_close(l_tpFileReader); -#ifndef USE_LUA_STUDIO -# ifdef DEBUG -# if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO) - if( !debugger() || !debugger()->Active() ) -# endif // #if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO) - lua_sethook (lua(),lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); -# endif // #ifdef DEBUG -#endif // #ifndef USE_LUA_STUDIO - // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); - - load_package("_init", false); - load_package("_G", false); + int errFuncId = -1; +#ifdef USE_DEBUGGER +# ifndef USE_LUA_STUDIO + if (ai().script_engine().debugger()) + errFuncId = ai().script_engine().debugger()->PrepareLua(lua()); +# endif // #ifndef USE_LUA_STUDIO +#endif // #ifdef USE_DEBUGGER + if (0) //. + { + for (int i = 0; lua_type(lua(), -i - 1); i++) + Msg("%2d : %s", -i - 1, lua_typename(lua(), lua_type(lua(), -i - 1))); + } - register_script_classes(); - object_factory().register_script(); + // because that's the first and the only call of the main chunk - there is no point to compile it + // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_OFF); // Oles + int l_iErrorCode = lua_pcall(lua(), 0, 0, (-1 == errFuncId) ? 0 : errFuncId); // new_Andy + // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_ON); // Oles -#ifdef XRGAME_EXPORTS - load_common_scripts(); -#endif - m_stack_level = lua_gettop(lua()); -} +#ifdef USE_DEBUGGER +# ifndef USE_LUA_STUDIO + if (ai().script_engine().debugger()) + ai().script_engine().debugger()->UnPrepareLua(lua(), errFuncId); +# endif // #ifndef USE_LUA_STUDIO +#endif // #ifdef USE_DEBUGGER + if (l_iErrorCode) + { + //#ifdef DEBUG + if (strstr(Core.Params, "-dbg")) print_output(lua(), caScriptName, l_iErrorCode); + //#endif + on_error(lua()); + Msg("! [ERROR] --- Failed to load script %s", caNamespaceName); + lua_settop(lua(), start); + return (false); + } -void CScriptEngine::remove_script_process(const EScriptProcessors& process_id) -{ - CScriptProcessStorage::iterator I = m_script_processes.find(process_id); - if (I != m_script_processes.end()) - { - xr_delete((*I).second); - m_script_processes.erase(I); - } + VERIFY(lua_gettop(lua()) == start); + return (true); } void CScriptEngine::unload_package(LPCSTR name) { - lua_getglobal(lua(), "package"); - lua_getfield(lua(), -1, "loaded"); - lua_remove(lua(), -2); - lua_pushnil(lua()); - lua_setfield(lua(), -2, name); - lua_remove(lua(), -1); + lua_getglobal(lua(), "package"); + lua_getfield(lua(), -1, "loaded"); + lua_remove(lua(), -2); + lua_pushnil(lua()); + lua_setfield(lua(), -2, name); + lua_remove(lua(), -1); } void CScriptEngine::load_common_scripts() @@ -1314,71 +1286,36 @@ void CScriptEngine::load_common_scripts() #ifdef DBG_DISABLE_SCRIPTS return; #endif - string_path S; - FS.update_path(S, "$game_config$", "script.ltx"); - CInifile* l_tpIniFile = xr_new(S); - R_ASSERT(l_tpIniFile); - if (!l_tpIniFile->section_exist("common")) - { - xr_delete(l_tpIniFile); - return; - } - - if (l_tpIniFile->line_exist("common", "script")) - { - LPCSTR caScriptString = l_tpIniFile->r_string("common", "script"); - u32 n = _GetItemCount(caScriptString); - string256 I; - for (u32 i = 0; i < n; ++i) - { - load_package(_GetItem(caScriptString, i, I)); - xr_strcat(I, "_initialize"); - if (object("_G", I, LUA_TFUNCTION)) - { - // lua_dostring (lua(),xr_strcat(I,"()")); - luabind::functor f; - R_ASSERT(functor(I, f)); - f(); - } - } - } - - xr_delete(l_tpIniFile); -} - -bool CScriptEngine::load_package(LPCSTR file_name, bool warn_if_not_exist) -{ - u32 string_length = xr_strlen(file_name); - if (!warn_if_not_exist && no_file_exists(file_name, string_length)) - return false; + string_path S; + FS.update_path(S, "$game_config$", "script.ltx"); + CInifile* l_tpIniFile = xr_new(S); + R_ASSERT(l_tpIniFile); + if (!l_tpIniFile->section_exist("common")) + { + xr_delete(l_tpIniFile); + return; + } - string_path S, S1; - if (0 == xr_strcmp(file_name, "_G") || * file_name && !namespace_loaded(file_name)) - { - FS.update_path(S, "$game_scripts$", strconcat(sizeof(S1), S1, file_name, ".script")); - if (!warn_if_not_exist && !FS.exist(S)) - { -#ifdef DEBUG -# ifndef XRSE_FACTORY_EXPORTS - if (psAI_Flags.test(aiNilObjectAccess)) -# endif + if (l_tpIniFile->line_exist("common", "script")) + { + LPCSTR caScriptString = l_tpIniFile->r_string("common", "script"); + u32 n = _GetItemCount(caScriptString); + string256 I; + for (u32 i = 0; i < n; ++i) + { + load_package(_GetItem(caScriptString, i, I)); + xr_strcat(I, "_initialize"); + if (object("_G", I, LUA_TFUNCTION)) { - print_stack (); - Msg ("* trying to access variable %s, which doesn't exist, or to load script %s, which doesn't exist too",file_name,S); - m_stack_is_ready = true; + // lua_dostring (lua(),xr_strcat(I,"()")); + luabind::functor f; + R_ASSERT(functor(I, f)); + f(); } -#endif - add_no_file(file_name, string_length); - return false; - } - //#ifndef MASTER_GOLD - if (strstr(Core.Params, "-dbg")) - Msg("* loading script %s", S1); - //#endif // MASTER_GOLD - return load_file_into_namespace(S, *file_name ? file_name : "_G"); - } + } + } - return true; + xr_delete(l_tpIniFile); } void CScriptEngine::register_script_classes() @@ -1386,33 +1323,33 @@ void CScriptEngine::register_script_classes() #ifdef DBG_DISABLE_SCRIPTS return; #endif - string_path S; - FS.update_path(S, "$game_config$", "script.ltx"); - CInifile* l_tpIniFile = xr_new(S); - R_ASSERT(l_tpIniFile); + string_path S; + FS.update_path(S, "$game_config$", "script.ltx"); + CInifile* l_tpIniFile = xr_new(S); + R_ASSERT(l_tpIniFile); - if (!l_tpIniFile->section_exist("common")) - { - xr_delete(l_tpIniFile); - return; - } + if (!l_tpIniFile->section_exist("common")) + { + xr_delete(l_tpIniFile); + return; + } - m_class_registrators = READ_IF_EXISTS(l_tpIniFile, r_string, "common", "class_registrators", ""); - xr_delete(l_tpIniFile); + shared_str m_class_registrators = READ_IF_EXISTS(l_tpIniFile, r_string, "common", "class_registrators", ""); + xr_delete(l_tpIniFile); - u32 n = _GetItemCount(*m_class_registrators); - string256 I; - for (u32 i = 0; i < n; ++i) - { - _GetItem(*m_class_registrators, i, I); - luabind::functor result; - if (!functor(I, result)) - { - script_log(eLuaMessageTypeError, "Cannot load class registrator %s!", I); - continue; - } - result(const_cast(&object_factory())); - } + u32 n = _GetItemCount(*m_class_registrators); + string256 I; + for (u32 i = 0; i < n; ++i) + { + _GetItem(*m_class_registrators, i, I); + luabind::functor result; + if (!functor(I, result)) + { + script_log(eLuaMessageTypeError, "Cannot load class registrator %s!", I); + continue; + } + result(const_cast(&object_factory())); + } } bool CScriptEngine::object(LPCSTR identifier, int type) @@ -1478,6 +1415,22 @@ bool CScriptEngine::function_object(LPCSTR function_to_call, luabind::object& ob return (true); } +void CScriptEngine::collect_all_garbage() +{ + lua_gc(lua(), LUA_GCCOLLECT, 0); + lua_gc(lua(), LUA_GCCOLLECT, 0); +} + +void CScriptEngine::on_error(lua_State* state) +{ +#if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) + if (!debugger()) + return; + + debugger()->on_error(state); +#endif // #if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) +} + #if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO) void CScriptEngine::stopDebugger () { @@ -1499,33 +1452,3 @@ void CScriptEngine::restartDebugger () Msg ("Script debugger succesfully restarted."); } #endif // #if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO) - -bool CScriptEngine::no_file_exists(LPCSTR file_name, u32 string_length) -{ - if (m_last_no_file_length != string_length) - return (false); - - return (!memcmp(m_last_no_file, file_name, string_length * sizeof(char))); -} - -void CScriptEngine::add_no_file(LPCSTR file_name, u32 string_length) -{ - m_last_no_file_length = string_length; - CopyMemory(m_last_no_file, file_name, (string_length + 1)*sizeof(char)); -} - -void CScriptEngine::collect_all_garbage() -{ - lua_gc(lua(), LUA_GCCOLLECT, 0); - lua_gc(lua(), LUA_GCCOLLECT, 0); -} - -void CScriptEngine::on_error(lua_State* state) -{ -#if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) - if (!debugger()) - return; - - debugger()->on_error ( state ); -#endif // #if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) -} diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index 9e4bb249b9..10b8ff0049 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -55,6 +55,9 @@ class CScriptThread; struct lua_State; struct lua_Debug; +typedef ScriptEngine::EScriptProcessors EScriptProcessors; +typedef associative_vector CScriptProcessStorage; + #ifdef USE_DEBUGGER # ifndef USE_LUA_STUDIO class CScriptDebugger; @@ -74,7 +77,19 @@ class CScriptEngine private: lua_State* m_virtual_machine; CScriptThread* m_current_thread; - BOOL m_jit; + +protected: + CScriptProcessStorage m_script_processes; + int m_stack_level; + +#ifdef USE_DEBUGGER +# ifndef USE_LUA_STUDIO + CScriptDebugger* m_scriptDebugger; +# else // #ifndef USE_LUA_STUDIO + cs::lua_studio::world* m_lua_studio_world; + lua_studio_engine* m_lua_studio_engine; +# endif // #ifndef USE_LUA_STUDIO +#endif // #ifdef USE_DEBUGGER #ifdef DEBUG public: @@ -91,25 +106,33 @@ class CScriptEngine # endif //-DEBUG #endif //-LUA_DEBUG_PRINT PRINT_CALL_STACK -protected: - static int vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker); - bool do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName); - void reinit(); - -public: - //#ifdef PRINT_CALL_STACK - void print_stack(); - //AVO: added to stop duplicate stack output prints in log - static int __cdecl script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...); - //-AVO - //#endif //-PRINT_CALL_STACK - public: CScriptEngine(); ~CScriptEngine(); - IC lua_State* lua(); + + void init(); + void unload(); + IC void current_thread(CScriptThread* thread); IC CScriptThread* current_thread() const; + + IC CScriptProcess* script_process(const EScriptProcessors& process_id) const; + IC void add_script_process(const EScriptProcessors& process_id, CScriptProcess* script_process); + void remove_script_process(const EScriptProcessors& process_id); + + IC lua_State* lua(); + static int lua_panic(lua_State* L); + static void lua_error(lua_State* L); + static int lua_pcall_failed(lua_State* L); + +#ifdef DEBUG + static void lua_hook_call(lua_State* L, lua_Debug* dbg); +#endif // #ifdef DEBUG + + void setup_callbacks(); + void load_common_scripts(); + void register_script_classes(); + int compile_buffer( lua_State* L, std::string caString, @@ -123,9 +146,12 @@ class CScriptEngine LPCSTR caScriptName, LPCSTR caNameSpaceName = 0 ); - bool load_file_into_namespace(LPCSTR caScriptName, LPCSTR caNamespaceName); + bool namespace_loaded(LPCSTR caName, bool remove_from_stack = true); luabind::object name_space(LPCSTR namespace_name); + bool load_package(LPCSTR file_name, bool warn_if_not_exist = true); + void unload_package(LPCSTR package); + int error_log(LPCSTR caFormat, ...); static int __cdecl script_log(ELuaMessageType message, LPCSTR caFormat, ...); static bool print_output(lua_State* L, LPCSTR caScriptName, int iErorCode = 0); @@ -133,77 +159,48 @@ class CScriptEngine void on_error(lua_State* L); #ifdef LUA_DEBUG_PRINT //DEBUG -public: void flush_log(); #endif //-LUA_DEBUG_PRINT DEBUG -public: - typedef ScriptEngine::EScriptProcessors EScriptProcessors; - typedef associative_vector CScriptProcessStorage; - -protected: - CScriptProcessStorage m_script_processes; - int m_stack_level; - shared_str m_class_registrators; - -protected: -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - CScriptDebugger *m_scriptDebugger; -# else // #ifndef USE_LUA_STUDIO - cs::lua_studio::world* m_lua_studio_world; - lua_studio_engine* m_lua_studio_engine; -# endif // #ifndef USE_LUA_STUDIO -#endif // #ifdef USE_DEBUGGER - -private: - string128 m_last_no_file; - u32 m_last_no_file_length; - - bool no_file_exists(LPCSTR file_name, u32 string_length); - void add_no_file(LPCSTR file_name, u32 string_length); + IC void parse_script_namespace( + LPCSTR function_to_call, + LPSTR name_space, + u32 const namespace_size, + LPSTR function, + u32 const function_size + ); -public: - void init(); - void unload(); - static int lua_panic(lua_State* L); - static void lua_error(lua_State* L); - static int lua_pcall_failed(lua_State* L); -#ifdef DEBUG - static void lua_hook_call (lua_State *L, lua_Debug *dbg); -#endif // #ifdef DEBUG - void setup_callbacks(); - void load_common_scripts(); - IC CScriptProcess* script_process(const EScriptProcessors& process_id) const; - IC void add_script_process(const EScriptProcessors& process_id, CScriptProcess* script_process); - void remove_script_process(const EScriptProcessors& process_id); - void setup_auto_load(); - bool load_package(LPCSTR file_name, bool warn_if_not_exist = true); - void unload_package(LPCSTR package); -protected: - bool object(LPCSTR caIdentifier, int type); - bool object(LPCSTR caNamespaceName, LPCSTR caIdentifier, int type); -public: bool function_object(LPCSTR function_to_call, luabind::object& object, int type = LUA_TFUNCTION); - void register_script_classes(); - IC void parse_script_namespace(LPCSTR function_to_call, LPSTR name_space, u32 const namespace_size, LPSTR function, - u32 const function_size); template IC bool functor(LPCSTR function_to_call, luabind::functor<_result_type>& lua_function); + //#ifdef PRINT_CALL_STACK + void print_stack(); + //AVO: added to stop duplicate stack output prints in log + static int __cdecl script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...); + //-AVO + //#endif //-PRINT_CALL_STACK + + void collect_all_garbage(); + #ifdef USE_DEBUGGER # ifndef USE_LUA_STUDIO - void stopDebugger (); - void restartDebugger (); - CScriptDebugger *debugger (); + void stopDebugger(); + void restartDebugger(); + CScriptDebugger* debugger(); # else // ifndef USE_LUA_STUDIO - void try_connect_to_debugger (); - void disconnect_from_debugger (); - inline cs::lua_studio::world* debugger () const { return m_lua_studio_world; } + void try_connect_to_debugger(); + void disconnect_from_debugger(); + inline cs::lua_studio::world* debugger() const { return m_lua_studio_world; } # endif // ifndef USE_LUA_STUDIO #endif - void collect_all_garbage(); + +protected: + void reinit(); + static int vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker); + bool object(LPCSTR caIdentifier, int type); + bool object(LPCSTR caNamespaceName, LPCSTR caIdentifier, int type); DECLARE_SCRIPT_REGISTER_FUNCTION }; From 20efcc31485b9787d5f2c8eb695ce5b7dbea388b Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 22 May 2025 18:41:51 +0100 Subject: [PATCH 24/76] Move `register_script_classes` into Lua --- gamedata/scripts/_init.script | 26 +++++++++++++++ gamedata/scripts/scam_classes.script | 25 ++++++++++++++ gamedata/scripts/scam_compiler.script | 19 +++++------ src/xrServerEntities/script_engine.cpp | 46 ++++++-------------------- src/xrServerEntities/script_engine.h | 1 - 5 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 gamedata/scripts/scam_classes.script diff --git a/gamedata/scripts/_init.script b/gamedata/scripts/_init.script index 6c599fa9d6..e9e5693b08 100644 --- a/gamedata/scripts/_init.script +++ b/gamedata/scripts/_init.script @@ -1,3 +1,26 @@ +function require_path(str) + print("require_path:", str) + local path = {} + for v in string.gmatch(str, "[^%.]+") do + table.insert(path, v) + end + + local mod_name = table.remove(path, 1) + print("mod_name:", mod_name) + + local mod = require(mod_name) + print("mod:", mod) + + local val = mod + for _, seg in ipairs(path) do + print("seg:", seg) + val = val[seg] + print("val:", val) + end + + return val +end + load_package("scam_print") print("Instigating S.C.A.M.") @@ -11,3 +34,6 @@ require("scam_compiler").set_default_macro( ) load_package("_G") + +load_package("scam_classes") +--load_package("scam_scripts") diff --git a/gamedata/scripts/scam_classes.script b/gamedata/scripts/scam_classes.script new file mode 100644 index 0000000000..b15195f248 --- /dev/null +++ b/gamedata/scripts/scam_classes.script @@ -0,0 +1,25 @@ +local ini = ini_file("script.ltx") +if not ini then + return +end + +if not ini:section_exist("common") then + error("Missing common section") +end + +if not ini:line_exist("common", "class_registrators") then + error("Missing class_registrators line") +end + +local regs = ini:r_string("common", "class_registrators", "") +print("class registrators:", regs) + +local fac = get_object_factory() +print("object_factory:", fac) + +for reg_path in regs:gmatch("[^,]+") do + print("reg_path:", reg_path) + local reg = require_path(reg_path) + print("reg:", reg) + reg(fac) +end diff --git a/gamedata/scripts/scam_compiler.script b/gamedata/scripts/scam_compiler.script index 487604d699..b92c98c338 100644 --- a/gamedata/scripts/scam_compiler.script +++ b/gamedata/scripts/scam_compiler.script @@ -10,17 +10,14 @@ function compile(src, script_name, namespace_name) if string.sub(src, 1, #TAG_MACRO) == TAG_MACRO then src = string.sub(src, #TAG_MACRO + 1) local tag, rest = string.match(src, "([^%s]+)(%s+.*)") - local path = {} - for v in string.gmatch(tag, "[^%.]+") do - table.insert(path, v) - end - - local mod_name = table.remove(path, 1) - local out = require("macro_" .. mod_name) - for _, v in ipairs(path) do - out = out[v] - end - return out(rest, namespace_name) + + local mac = require_path("macro_" .. tag) + print("mac:", mac) + + local out = mac(rest, namespace_name) + print("out:", out) + + return out end if state.default_macro then diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 1c13b38378..a9a8e80bc9 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -337,7 +337,7 @@ CScriptEngine::~CScriptEngine() remove_script_process(m_script_processes.begin()->first); } -int do_load_package(lua_State* L) +static int do_load_package(lua_State* L) { assert(lua_gettop(L) == 1); assert(lua_isstring(L, 1)); @@ -353,6 +353,12 @@ int do_load_package(lua_State* L) return (1); } +static int get_object_factory(lua_State* L) +{ + luabind::object(L, const_cast(&object_factory())).pushvalue(); + return (1); +} + void CScriptEngine::init() { #ifdef USE_LUA_STUDIO @@ -400,9 +406,11 @@ void CScriptEngine::init() lua_pushcfunction(lua(), do_load_package); lua_setglobal(lua(), "load_package"); + lua_pushcfunction(lua(), get_object_factory); + lua_setglobal(lua(), "get_object_factory"); + load_package("_init", false); - register_script_classes(); object_factory().register_script(); #ifdef XRGAME_EXPORTS @@ -1318,40 +1326,6 @@ void CScriptEngine::load_common_scripts() xr_delete(l_tpIniFile); } -void CScriptEngine::register_script_classes() -{ -#ifdef DBG_DISABLE_SCRIPTS - return; -#endif - string_path S; - FS.update_path(S, "$game_config$", "script.ltx"); - CInifile* l_tpIniFile = xr_new(S); - R_ASSERT(l_tpIniFile); - - if (!l_tpIniFile->section_exist("common")) - { - xr_delete(l_tpIniFile); - return; - } - - shared_str m_class_registrators = READ_IF_EXISTS(l_tpIniFile, r_string, "common", "class_registrators", ""); - xr_delete(l_tpIniFile); - - u32 n = _GetItemCount(*m_class_registrators); - string256 I; - for (u32 i = 0; i < n; ++i) - { - _GetItem(*m_class_registrators, i, I); - luabind::functor result; - if (!functor(I, result)) - { - script_log(eLuaMessageTypeError, "Cannot load class registrator %s!", I); - continue; - } - result(const_cast(&object_factory())); - } -} - bool CScriptEngine::object(LPCSTR identifier, int type) { int start = lua_gettop(lua()); diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index 10b8ff0049..f869ec39c3 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -131,7 +131,6 @@ class CScriptEngine void setup_callbacks(); void load_common_scripts(); - void register_script_classes(); int compile_buffer( lua_State* L, From 6f6aa8a0c1c323e93ec29953a73c2285121fcaf4 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 22 May 2025 19:13:41 +0100 Subject: [PATCH 25/76] Move `object_factory.register_script` call into Lua --- gamedata/scripts/scam_classes.script | 8 +++----- src/xrServerEntities/object_factory_script.cpp | 1 + src/xrServerEntities/script_engine.cpp | 2 -- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/gamedata/scripts/scam_classes.script b/gamedata/scripts/scam_classes.script index b15195f248..afa9366e02 100644 --- a/gamedata/scripts/scam_classes.script +++ b/gamedata/scripts/scam_classes.script @@ -11,15 +11,13 @@ if not ini:line_exist("common", "class_registrators") then error("Missing class_registrators line") end -local regs = ini:r_string("common", "class_registrators", "") -print("class registrators:", regs) local fac = get_object_factory() -print("object_factory:", fac) +local regs = ini:r_string("common", "class_registrators", "") for reg_path in regs:gmatch("[^,]+") do - print("reg_path:", reg_path) local reg = require_path(reg_path) - print("reg:", reg) reg(fac) end + +fac:register_script() diff --git a/src/xrServerEntities/object_factory_script.cpp b/src/xrServerEntities/object_factory_script.cpp index d727d13a65..0c885080ae 100644 --- a/src/xrServerEntities/object_factory_script.cpp +++ b/src/xrServerEntities/object_factory_script.cpp @@ -105,6 +105,7 @@ void CObjectFactory::script_register(lua_State* L) .def("register", (void (CObjectFactory::*)(LPCSTR, LPCSTR, LPCSTR, LPCSTR))(&CObjectFactory::register_script_class)) .def("register", (void (CObjectFactory::*)(LPCSTR, LPCSTR, LPCSTR))(&CObjectFactory::register_script_class)) + .def("register_script", &CObjectFactory::register_script) ]; } diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index a9a8e80bc9..4d3ef325e1 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -411,8 +411,6 @@ void CScriptEngine::init() load_package("_init", false); - object_factory().register_script(); - #ifdef XRGAME_EXPORTS load_common_scripts(); #endif From a89cdaea8916ced57a0c1729325124d53729d960 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 22 May 2025 19:14:56 +0100 Subject: [PATCH 26/76] Move `load_common_scripts` into Lua --- gamedata/scripts/_init.script | 2 +- gamedata/scripts/scam_scripts.script | 28 ++++++++++++++++++ src/xrServerEntities/script_engine.cpp | 41 -------------------------- src/xrServerEntities/script_engine.h | 1 - 4 files changed, 29 insertions(+), 43 deletions(-) create mode 100644 gamedata/scripts/scam_scripts.script diff --git a/gamedata/scripts/_init.script b/gamedata/scripts/_init.script index e9e5693b08..1feb0c5b0b 100644 --- a/gamedata/scripts/_init.script +++ b/gamedata/scripts/_init.script @@ -36,4 +36,4 @@ require("scam_compiler").set_default_macro( load_package("_G") load_package("scam_classes") ---load_package("scam_scripts") +load_package("scam_scripts") diff --git a/gamedata/scripts/scam_scripts.script b/gamedata/scripts/scam_scripts.script new file mode 100644 index 0000000000..13fb2ca9b1 --- /dev/null +++ b/gamedata/scripts/scam_scripts.script @@ -0,0 +1,28 @@ +local DISABLE_SCRIPTS = false + +if DISABLE_SCRIPTS then + return +end + +local ini = ini_file("script.ltx") +if not ini then + return +end + +if not ini:section_exist("common") then + error("Missing common section") +end + +if not ini:line_exist("common", "script") then + error("Missing script line") +end + +local scripts = ini:r_string("common", "script", "") + +for script in scripts:gmatch("[^,]+") do + local init_name = script .. "_initialize" + local init = _G[init_name] + if init then + init() + end +end diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 4d3ef325e1..5cee0210b2 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -410,10 +410,6 @@ void CScriptEngine::init() lua_setglobal(lua(), "get_object_factory"); load_package("_init", false); - -#ifdef XRGAME_EXPORTS - load_common_scripts(); -#endif m_stack_level = lua_gettop(lua()); } @@ -1287,43 +1283,6 @@ void CScriptEngine::unload_package(LPCSTR name) lua_remove(lua(), -1); } -void CScriptEngine::load_common_scripts() -{ -#ifdef DBG_DISABLE_SCRIPTS - return; -#endif - string_path S; - FS.update_path(S, "$game_config$", "script.ltx"); - CInifile* l_tpIniFile = xr_new(S); - R_ASSERT(l_tpIniFile); - if (!l_tpIniFile->section_exist("common")) - { - xr_delete(l_tpIniFile); - return; - } - - if (l_tpIniFile->line_exist("common", "script")) - { - LPCSTR caScriptString = l_tpIniFile->r_string("common", "script"); - u32 n = _GetItemCount(caScriptString); - string256 I; - for (u32 i = 0; i < n; ++i) - { - load_package(_GetItem(caScriptString, i, I)); - xr_strcat(I, "_initialize"); - if (object("_G", I, LUA_TFUNCTION)) - { - // lua_dostring (lua(),xr_strcat(I,"()")); - luabind::functor f; - R_ASSERT(functor(I, f)); - f(); - } - } - } - - xr_delete(l_tpIniFile); -} - bool CScriptEngine::object(LPCSTR identifier, int type) { int start = lua_gettop(lua()); diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index f869ec39c3..5067e1b70f 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -130,7 +130,6 @@ class CScriptEngine #endif // #ifdef DEBUG void setup_callbacks(); - void load_common_scripts(); int compile_buffer( lua_State* L, From eec5af85dcb3edd682e6f25dbcc99fe006af9cd7 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 22 May 2025 19:15:06 +0100 Subject: [PATCH 27/76] Factor out `parse_script_namespace` --- src/xrServerEntities/script_engine.cpp | 20 +++++++++++++++++++- src/xrServerEntities/script_engine.h | 8 -------- src/xrServerEntities/script_engine_inline.h | 21 --------------------- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 5cee0210b2..a7427ccdab 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -1324,7 +1324,25 @@ bool CScriptEngine::function_object(LPCSTR function_to_call, luabind::object& ob string256 name_space, function; - parse_script_namespace(function_to_call, name_space, sizeof(name_space), function, sizeof(function)); + // Parse namespace + LPCSTR I = function_to_call, J = 0; + for (; ; J = I, ++I) + { + I = strchr(I, '.'); + if (!I) + break; + } + xr_strcpy(name_space, sizeof(name_space), "_G"); + if (!J) + xr_strcpy(function, sizeof(function), function_to_call); + else + { + CopyMemory(name_space, function_to_call, u32(J - function_to_call) * sizeof(char)); + name_space[u32(J - function_to_call)] = 0; + xr_strcpy(function, sizeof(function), J + 1); + } + + // If not _G, load corresponding package if (xr_strcmp(name_space, "_G")) { LPSTR file_name = strchr(name_space, '.'); diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index 5067e1b70f..910b9ac4a8 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -160,14 +160,6 @@ class CScriptEngine void flush_log(); #endif //-LUA_DEBUG_PRINT DEBUG - IC void parse_script_namespace( - LPCSTR function_to_call, - LPSTR name_space, - u32 const namespace_size, - LPSTR function, - u32 const function_size - ); - bool function_object(LPCSTR function_to_call, luabind::object& object, int type = LUA_TFUNCTION); template diff --git a/src/xrServerEntities/script_engine_inline.h b/src/xrServerEntities/script_engine_inline.h index 558bed3213..8124cfd6df 100644 --- a/src/xrServerEntities/script_engine_inline.h +++ b/src/xrServerEntities/script_engine_inline.h @@ -39,27 +39,6 @@ CScriptProcess* CScriptEngine::script_process(const EScriptProcessors& process_i return (0); } -IC void CScriptEngine::parse_script_namespace(LPCSTR function_to_call, LPSTR name_space, u32 const namespace_size, - LPSTR function, u32 const function_size) -{ - LPCSTR I = function_to_call, J = 0; - for (; ; J = I, ++I) - { - I = strchr(I, '.'); - if (!I) - break; - } - xr_strcpy(name_space, namespace_size, "_G"); - if (!J) - xr_strcpy(function, function_size, function_to_call); - else - { - CopyMemory(name_space, function_to_call, u32(J - function_to_call)*sizeof(char)); - name_space[u32(J - function_to_call)] = 0; - xr_strcpy(function, function_size, J + 1); - } -} - template IC bool CScriptEngine::functor(LPCSTR function_to_call, luabind::functor<_result_type>& lua_function) { From 3ab5d16099740f094a6236708e8dc46159d25b05 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 22 May 2025 19:22:06 +0100 Subject: [PATCH 28/76] Rename `_init.script` to `init.script` --- gamedata/scripts/{_init.script => init.script} | 0 src/xrServerEntities/script_engine.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename gamedata/scripts/{_init.script => init.script} (100%) diff --git a/gamedata/scripts/_init.script b/gamedata/scripts/init.script similarity index 100% rename from gamedata/scripts/_init.script rename to gamedata/scripts/init.script diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index a7427ccdab..0258a87dc4 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -409,7 +409,7 @@ void CScriptEngine::init() lua_pushcfunction(lua(), get_object_factory); lua_setglobal(lua(), "get_object_factory"); - load_package("_init", false); + load_package("init", false); m_stack_level = lua_gettop(lua()); } From 5c7b73b9007440248a238b861c0692c1255aecab Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 23 May 2025 06:29:53 +0100 Subject: [PATCH 29/76] First-pass Lua-side loading - Moved `function_object` into Lua - Removed C-side `object` methods - Scripts are loaded from the filesystem by Lua - Engine FS is used as a fallback to account for `*.db` data - Memoization is used to minimize runtime overhead for `wua` metatable environment - Comparable runtime overhead to previous impl - However, load times are much worse due to cache wipe on level load - Need to reimplement `CScriptStorage` as a basic persistent data store --- gamedata/scripts/init.lua | 196 ++++++++++++++++++ gamedata/scripts/init.script | 39 ---- .../scripts/{macro.script => macro/init.lua} | 6 +- .../lisp/init.lua} | 9 +- .../lisp/macro.lua} | 8 +- gamedata/scripts/macro/lua/init.lua | 11 + .../{macro_wua.script => macro/wua/init.lua} | 108 +++++----- gamedata/scripts/macro_lua.script | 12 -- .../{scam_classes.script => scam/classes.lua} | 2 +- gamedata/scripts/scam/compiler.lua | 28 +++ gamedata/scripts/scam/init.lua | 16 ++ .../{scam_sandbox.script => scam/sandbox.lua} | 0 .../{scam_scripts.script => scam/scripts.lua} | 18 +- gamedata/scripts/scam/unlocalize.lua | 69 ++++++ gamedata/scripts/scam_compiler.script | 40 ---- gamedata/scripts/scam_loader.script | 28 --- gamedata/scripts/scam_print.script | 24 --- src/xrServerEntities/script_engine.cpp | 128 +++--------- src/xrServerEntities/script_engine.h | 2 - 19 files changed, 431 insertions(+), 313 deletions(-) create mode 100644 gamedata/scripts/init.lua delete mode 100644 gamedata/scripts/init.script rename gamedata/scripts/{macro.script => macro/init.lua} (69%) rename gamedata/scripts/{macro_lisp.script => macro/lisp/init.lua} (83%) rename gamedata/scripts/{macro_lisp_macro.script => macro/lisp/macro.lua} (57%) create mode 100644 gamedata/scripts/macro/lua/init.lua rename gamedata/scripts/{macro_wua.script => macro/wua/init.lua} (72%) delete mode 100644 gamedata/scripts/macro_lua.script rename gamedata/scripts/{scam_classes.script => scam/classes.lua} (91%) create mode 100644 gamedata/scripts/scam/compiler.lua create mode 100644 gamedata/scripts/scam/init.lua rename gamedata/scripts/{scam_sandbox.script => scam/sandbox.lua} (100%) rename gamedata/scripts/{scam_scripts.script => scam/scripts.lua} (58%) create mode 100644 gamedata/scripts/scam/unlocalize.lua delete mode 100644 gamedata/scripts/scam_compiler.script delete mode 100644 gamedata/scripts/scam_loader.script delete mode 100644 gamedata/scripts/scam_print.script diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua new file mode 100644 index 0000000000..c236604d17 --- /dev/null +++ b/gamedata/scripts/init.lua @@ -0,0 +1,196 @@ +package.loaded._G = nil + +-- Emplace working print function +function print(...) + local str = "" + for _,v in ipairs({...}) do + if #str > 0 then + str = str .. " " + end + + local s = nil + if (type(v) == 'userdata') then + s = 'userdata' + else + s = tostring(v) + end + + str = str .. s + end + + if (log) then + log(str) + else + get_console():execute("load ~#debug msg:" .. str) + end +end + +-- Setup script load paths +local scripts_path = getFS():update_path("$game_scripts$", ""):gsub("\\", "/") +local paths = { + "?.script", + "?/init.script", + "?.lua", + "?/init.lua", + "?.fnl", + "?/init.fnl", +} + +for i=#paths,1,-1 do + local path = paths[i] + package.path = scripts_path .. path .. ";" .. package.path +end + +-- Define *.db reader +function read_db(name) + local fs = getFS() + local fname = name:gsub("/", "\\") .. ".script" + local path = fs:update_path("$game_scripts$", fname) + local file = fs:r_open(path) + + if not file then + return nil, nil, "No db entry: gamedata/scripts/" .. fname + end + + local src = "" + while not file:r_eof() do + src = src .. string.char(file:r_u8()) + end + + return src, path +end + +-- Define IO reader +function read_io(name) + local errs = "" + for seg in package.path:gmatch("[^;]+") do + local path = seg:gsub("?", name) + + local file, err = io.open(path) + if file == nil then + if #errs > 0 then + errs = errs .. "\n" + end + errs = errs .. err + goto next_seg + end + + local src = file:read("*a") + file:close() + + if src then + return src, path + end + + ::next_seg:: + end + + return nil, nil, errs +end + +function _COMPILER(src, script_name, namespace_name) + print("lua: loading " .. namespace_name) + return loadstring(src, namespace_name) +end + +-- Define reader -> loader transformer +function loader(with) + return function(name) + local src, path, err = with(name) + if not src then + return "\n\t" .. err + end + + local mod = _COMPILER(src, path, name) + + if mod then + return mod + end + + return "\n\tFailed to compile " .. name + end +end + +-- Define the set of readers to register as loaders +local readers = { + read_io, + read_db +} + +-- Pop the preloader off the loader list +local preload_loader = table.remove(package.loaders, 1) + +-- Pop the default textual script loader +table.remove(package.loaders, 1) + +-- Emplace new loaders for filesystem and db +for i=#readers,1,-1 do + table.insert(package.loaders, 1, loader(readers[i])) +end + + +-- Lift into a memoized higher-order loader +local loaders = package.loaders +local io_miss = {} +local function io_loader(name) + if io_miss[name] then + return io_miss[name] + end + + local err = "" + for i=1,#loaders do + local res = loaders[i](name) + + local ty = type(res) + if ty == "function" then + return res + else + if #err > 0 then + err = err .. "\n" + end + if ty == "string" then + err = err .. res + else + err = err .. "Loader returned invalid type: " .. ty + end + end + end + + io_miss[name] = err + return io_miss[name] +end + +-- Replace the loader list with the preloader plus our memoized IO loader +package.loaders = { preload_loader, io_loader } + +-- Extend require with path support +function function_object(str) + local path = {} + for v in string.gmatch(str, "[^%.]+") do + table.insert(path, v) + end + + local mod_name = table.remove(path, 1) + + local mod = nil + if mod_name == "_G" then + mod = _G + elseif _G[mod_name] then + mod = _G[mod_name] + else + mod = require(mod_name) + end + + local val = mod + for _, seg in ipairs(path) do + val = val[seg] + end + + return val +end + +-- Pass control to scam init +local res, err = pcall(require, "scam") +if not res then + error("Failed to load scam:\n" .. err) +end diff --git a/gamedata/scripts/init.script b/gamedata/scripts/init.script deleted file mode 100644 index 1feb0c5b0b..0000000000 --- a/gamedata/scripts/init.script +++ /dev/null @@ -1,39 +0,0 @@ -function require_path(str) - print("require_path:", str) - local path = {} - for v in string.gmatch(str, "[^%.]+") do - table.insert(path, v) - end - - local mod_name = table.remove(path, 1) - print("mod_name:", mod_name) - - local mod = require(mod_name) - print("mod:", mod) - - local val = mod - for _, seg in ipairs(path) do - print("seg:", seg) - val = val[seg] - print("val:", val) - end - - return val -end - -load_package("scam_print") - -print("Instigating S.C.A.M.") - -load_package("scam_sandbox") - -load_package("scam_loader") - -require("scam_compiler").set_default_macro( - require("macro_wua").expand -) - -load_package("_G") - -load_package("scam_classes") -load_package("scam_scripts") diff --git a/gamedata/scripts/macro.script b/gamedata/scripts/macro/init.lua similarity index 69% rename from gamedata/scripts/macro.script rename to gamedata/scripts/macro/init.lua index bb8d580285..d03e30ee21 100644 --- a/gamedata/scripts/macro.script +++ b/gamedata/scripts/macro/init.lua @@ -1,5 +1,5 @@ -function load_src(src) - return assert(loadstring(src)) +function load_src(src, script_name) + return assert(loadstring(src, script_name)) end function extend_env(dest) @@ -12,4 +12,4 @@ end package.loaded["macro"] = { load_src = load_src, extend_env = extend_env, -} \ No newline at end of file +} diff --git a/gamedata/scripts/macro_lisp.script b/gamedata/scripts/macro/lisp/init.lua similarity index 83% rename from gamedata/scripts/macro_lisp.script rename to gamedata/scripts/macro/lisp/init.lua index e25e7c4d5a..ce70ad0c70 100644 --- a/gamedata/scripts/macro_lisp.script +++ b/gamedata/scripts/macro/lisp/init.lua @@ -1,3 +1,6 @@ +local scam_unlocalize = require("scam/unlocalize") +local lisp_unlocalize = require("macro/lisp/unlocalize") + COMPILER_OPTS = { allowedGlobals = false, correlate = true, @@ -46,7 +49,11 @@ function fennel_eval_ast(ast, opts) )() end -function compile(src, namespace_name, unlocs) +function compile(src, namespace_name) + print("lisp: compiling " .. namespace_name) + + local unlocs = scam_unlocalize.get(namespace_name) + return function() local ast = fennel_forms(src) diff --git a/gamedata/scripts/macro_lisp_macro.script b/gamedata/scripts/macro/lisp/macro.lua similarity index 57% rename from gamedata/scripts/macro_lisp_macro.script rename to gamedata/scripts/macro/lisp/macro.lua index 0c5667897d..3f3b704487 100644 --- a/gamedata/scripts/macro_lisp_macro.script +++ b/gamedata/scripts/macro/lisp/macro.lua @@ -6,13 +6,17 @@ COMPILER_OPTS = { } function compile(src, namespace_name) + print("lisp_macro: compiling " .. namespace_name) + return function() local macros = fennel.eval( src, COMPILER_OPTS ) - package.loaded[namespace_name] = macros - fennel["macro-loaded"][namespace_name] = macros + if namespace_name then + fennel["macro-loaded"][namespace_name] = macros + package.loaded[namespace_name] = macros + end end end diff --git a/gamedata/scripts/macro/lua/init.lua b/gamedata/scripts/macro/lua/init.lua new file mode 100644 index 0000000000..d829eae97a --- /dev/null +++ b/gamedata/scripts/macro/lua/init.lua @@ -0,0 +1,11 @@ +function expand(src, namespace_name) + print("lua: expanding " .. namespace_name) + return setfenv( + macro.load_src(src), + macro.extend_env { + script_name = function() + return namespace_name + end + } + ) +end diff --git a/gamedata/scripts/macro_wua.script b/gamedata/scripts/macro/wua/init.lua similarity index 72% rename from gamedata/scripts/macro_wua.script rename to gamedata/scripts/macro/wua/init.lua index d167aa73f9..912ffc499b 100644 --- a/gamedata/scripts/macro_wua.script +++ b/gamedata/scripts/macro/wua/init.lua @@ -121,83 +121,79 @@ local function unlocalize(src, namespace_name) end local function compile(src, namespace_name) - local is_g = namespace_name == "_G" - - local G = setmetatable( - {}, - { - __index = function(_, key) - local gv = _G[key] - if gv ~= nil then - return gv - end + return function() + local is_g = namespace_name == "_G" + + local G = setmetatable( + {}, + { + __index = function(_, key) + local gv = _G[key] + if gv ~= nil then + return gv + end - local res, out = pcall(require, key) - if res then - return out + local res, out = pcall(require, key) + if res then + return out + end + end, + __newindex = function(_, k, v) + _G[k] = v end - end, - __newindex = function(_, k, v) - _G[k] = v - end - } - ) + } + ) - local mt = { - __index = G - } + local mt = { + __index = G + } - if is_g then - mt.__newindex = function(_, k, v) - _G[k] = v + if is_g then + mt.__newindex = function(_, k, v) + _G[k] = v + end end - end - - local env = setmetatable({ _G = G }, mt) - setmetatable(env, mt) + local env = setmetatable({ _G = G }, mt) - if is_g then - print("expanding _g") - else - print("expanding module", namespace_name) - env._M = env - if namespace_name then - env._PACKAGE = namespace_name - package.loaded[namespace_name] = env + if not is_g then + env._M = env + if namespace_name then + env._PACKAGE = namespace_name + -- Prepopulate the environment in case of indirection + package.loaded[namespace_name] = env + end end - end - if namespace_name then - src = [[ + if namespace_name then + src = [[ local script_name = function() return _PACKAGE end - ]] .. src - end + ]] .. src + end - src = [[ + src = [[ local this = _M - ]] .. src + ]] .. src - return setfenv( - macro.load_src(src), - env - ) + local mod = require("macro").load_src(src, namespace_name) + setfenv(mod, env)() + + -- Emplace in package.loaded so require returns env + package.loaded[namespace_name] = env + end end local function expand(src, namespace_name) - print("macro_wua.expand", namespace_name) - - return macro.load_src( - compile( - unlocalize(src, namespace_name), - namespace_name - ) + print("wua: expanding " .. namespace_name) + return compile( + unlocalize(src, namespace_name), + namespace_name ) end -package.loaded["macro_wua"] = { +package.loaded["macro/wua"] = { expand = expand } diff --git a/gamedata/scripts/macro_lua.script b/gamedata/scripts/macro_lua.script deleted file mode 100644 index 248c9ce450..0000000000 --- a/gamedata/scripts/macro_lua.script +++ /dev/null @@ -1,12 +0,0 @@ -function expand(src, namespace_name, unlocalizer) - return function() - package.loaded[namespace_name] = setfenv( - macro.load_src(src), - macro.extend_env { - script_name = function() - return namespace_name - end - } - )() - end -end diff --git a/gamedata/scripts/scam_classes.script b/gamedata/scripts/scam/classes.lua similarity index 91% rename from gamedata/scripts/scam_classes.script rename to gamedata/scripts/scam/classes.lua index afa9366e02..032a463473 100644 --- a/gamedata/scripts/scam_classes.script +++ b/gamedata/scripts/scam/classes.lua @@ -16,7 +16,7 @@ local fac = get_object_factory() local regs = ini:r_string("common", "class_registrators", "") for reg_path in regs:gmatch("[^,]+") do - local reg = require_path(reg_path) + local reg = function_object(reg_path) reg(fac) end diff --git a/gamedata/scripts/scam/compiler.lua b/gamedata/scripts/scam/compiler.lua new file mode 100644 index 0000000000..de6ae48d21 --- /dev/null +++ b/gamedata/scripts/scam/compiler.lua @@ -0,0 +1,28 @@ +TAG_MACRO = "#macro " + +local state = { + default_macro = nil +} + +function set_default_macro(mac) + state.default_macro = mac +end + +local old_compiler = _COMPILER +function _COMPILER(src, script_name, namespace_name) + if string.sub(src, 1, #TAG_MACRO) == TAG_MACRO then + src = string.sub(src, #TAG_MACRO + 1) + local tag, rest = string.match(src, "([^%s]+)(%s+.*)") + local path = "macro/" .. tag + return function_object(path)(rest, namespace_name) + elseif state.default_macro then + return function_object(state.default_macro)(src, namespace_name) + end + + return old_compiler(src, script_name, namespace_name) +end + +package.loaded["scam/compiler"] = { + compile = _COMPILER, + set_default_macro = set_default_macro +} diff --git a/gamedata/scripts/scam/init.lua b/gamedata/scripts/scam/init.lua new file mode 100644 index 0000000000..f658e9fb99 --- /dev/null +++ b/gamedata/scripts/scam/init.lua @@ -0,0 +1,16 @@ +print("Instigating S.C.A.M.") + +require("scam/sandbox") + +local compiler = require("scam/compiler") + +require("macro") +require("scam/unlocalize") +require("macro/wua") + +compiler.set_default_macro("macro/wua.expand") + +require("_G") + +require("scam/classes") +require("scam/scripts") diff --git a/gamedata/scripts/scam_sandbox.script b/gamedata/scripts/scam/sandbox.lua similarity index 100% rename from gamedata/scripts/scam_sandbox.script rename to gamedata/scripts/scam/sandbox.lua diff --git a/gamedata/scripts/scam_scripts.script b/gamedata/scripts/scam/scripts.lua similarity index 58% rename from gamedata/scripts/scam_scripts.script rename to gamedata/scripts/scam/scripts.lua index 13fb2ca9b1..f7e275253c 100644 --- a/gamedata/scripts/scam_scripts.script +++ b/gamedata/scripts/scam/scripts.lua @@ -20,9 +20,19 @@ end local scripts = ini:r_string("common", "script", "") for script in scripts:gmatch("[^,]+") do - local init_name = script .. "_initialize" - local init = _G[init_name] - if init then - init() + print("script:", script) + local mod = require(script) + if type(mod) ~= "table" then + print("Error: " .. script .. " module is not a table") + return end + + local init = mod[script .. "_initialize"] + if not init then + goto next_script + end + + init() + + ::next_script:: end diff --git a/gamedata/scripts/scam/unlocalize.lua b/gamedata/scripts/scam/unlocalize.lua new file mode 100644 index 0000000000..13c64dd2b7 --- /dev/null +++ b/gamedata/scripts/scam/unlocalize.lua @@ -0,0 +1,69 @@ +local unlocalizers = {} +local updated = false + +function update() + local fs = getFS() + local list = fs:file_list_open( + "$game_config$", + "unlocalizers\\", + bit_or( + FS.FS_ListFiles, + FS.FS_RootOnly + ) + ) + + if not list then + return + end + + local count = list:Size() or 0 + if count == 0 then + return + end + + for i=1,count do + local id = list:GetAt(i - 1) + + if #id < 4 then + goto next_filename + end + + if string.sub(id, #id - 3, #id) ~= ".ltx" then + goto next_filename + end + + print("opening file:", id) + + local config = ini_file("unlocalizers\\" .. id) + config:section_for_each(function(section) + local name = string.lower(section) + local count = config:line_count(name) + for j=0,count-1 do + local res, sec = config:r_line(name, j) + if not res then + goto next_line + end + unlocalizers[name] = unlocalizers[name] or {} + table.insert(unlocalizers[name], sec) + + ::next_line:: + end + end) + + ::next_filename:: + end +end + +function get(k) + if not updated then + updated = true + update() + end + return unlocalizers[k] +end + + +package.loaded["scam/unlocalize"] = { + update = update, + get = get +} diff --git a/gamedata/scripts/scam_compiler.script b/gamedata/scripts/scam_compiler.script deleted file mode 100644 index b92c98c338..0000000000 --- a/gamedata/scripts/scam_compiler.script +++ /dev/null @@ -1,40 +0,0 @@ -TAG_MACRO = "#macro " - -local state = { - default_macro = nil -} - -function compile(src, script_name, namespace_name) - print("compile", script_name, namespace_name) - - if string.sub(src, 1, #TAG_MACRO) == TAG_MACRO then - src = string.sub(src, #TAG_MACRO + 1) - local tag, rest = string.match(src, "([^%s]+)(%s+.*)") - - local mac = require_path("macro_" .. tag) - print("mac:", mac) - - local out = mac(rest, namespace_name) - print("out:", out) - - return out - end - - if state.default_macro then - print("loading via default macro") - src = state.default_macro(src, namespace_name) - else - print("loading raw lua") - end - - return loadstring(src, script_name) -end - -function set_default_macro(mac) - state.default_macro = mac -end - -package.loaded["scam_compiler"] = { - compile = compile, - set_default_macro = set_default_macro -} diff --git a/gamedata/scripts/scam_loader.script b/gamedata/scripts/scam_loader.script deleted file mode 100644 index 1aa55f6ab0..0000000000 --- a/gamedata/scripts/scam_loader.script +++ /dev/null @@ -1,28 +0,0 @@ --- Setup script load paths -local scripts_path = getFS():update_path("$game_scripts$", "") -local paths = { - "?.script", - "?.lua", - "?.fnl", -} - -for i=#paths,1,-1 do - local path = paths[i] - package.path = scripts_path .. path .. ";" .. package.path -end - --- Inject our custom X-Ray FS implementation next -table.insert( - package.loaders, - 2, - function(name) - if load_package(name, false) then - local res = package.loaded[name] - return function() - return res - end - end - - return "\n\t" .. name .. " not present in X-Ray filesystem" - end -) diff --git a/gamedata/scripts/scam_print.script b/gamedata/scripts/scam_print.script deleted file mode 100644 index 9c0e80da9c..0000000000 --- a/gamedata/scripts/scam_print.script +++ /dev/null @@ -1,24 +0,0 @@ --- Emplace working print function -function print(...) - local str = "" - for _,v in ipairs({...}) do - if #str > 0 then - str = str .. " " - end - - local s = nil - if (type(v) == 'userdata') then - s = 'userdata' - else - s = tostring(v) - end - - str = str .. s - end - - if (log) then - log(str) - else - get_console():execute("load ~#debug msg:" .. str) - end -end \ No newline at end of file diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 0258a87dc4..14aa411af0 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -337,22 +337,6 @@ CScriptEngine::~CScriptEngine() remove_script_process(m_script_processes.begin()->first); } -static int do_load_package(lua_State* L) -{ - assert(lua_gettop(L) == 1); - assert(lua_isstring(L, 1)); - - lua_pushboolean( - L, - ai().script_engine().load_package( - lua_tostring(L, 1), - false - ) - ); - - return (1); -} - static int get_object_factory(lua_State* L) { luabind::object(L, const_cast(&object_factory())).pushvalue(); @@ -403,13 +387,17 @@ void CScriptEngine::init() #endif // #ifndef USE_LUA_STUDIO // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); - lua_pushcfunction(lua(), do_load_package); - lua_setglobal(lua(), "load_package"); - lua_pushcfunction(lua(), get_object_factory); lua_setglobal(lua(), "get_object_factory"); - load_package("init", false); + string_path path; + if (luaL_dofile(lua(), FS.update_path(path, "$game_scripts$", "init.lua"))) + { + LPCSTR e = lua_tostring(lua(), -1); + lua_pop(lua(), 1); + FATAL((std::string("Failed to load init.lua:\n") + e).c_str()); + } + m_stack_level = lua_gettop(lua()); } @@ -584,15 +572,12 @@ void lua_cast_failed(lua_State* L, LUABIND_TYPE_INFO info) int CScriptEngine::compile_buffer(lua_State* L, std::string caString, LPCSTR caScriptName, LPCSTR caNameSpaceName) { - luabind::functor compile; - if (ai().script_engine().namespace_loaded("scam_compiler", true)) + luabind::functor compiler; + if (functor("_COMPILER", compiler)) { - if (ai().script_engine().functor("scam_compiler.compile", compile)) - { - luabind::object result = compile(caString.c_str(), caScriptName, caNameSpaceName); - result.pushvalue(); - return 0; - } + luabind::object result = compiler(caString.c_str(), caScriptName, caNameSpaceName); + result.pushvalue(); + return 0; } Msg("scam_compiler not available, loading as raw Lua..."); @@ -1283,85 +1268,26 @@ void CScriptEngine::unload_package(LPCSTR name) lua_remove(lua(), -1); } -bool CScriptEngine::object(LPCSTR identifier, int type) -{ - int start = lua_gettop(lua()); - lua_pushnil(lua()); - while (lua_next(lua(), -2)) - { - if ((lua_type(lua(), -1) == type) && !xr_strcmp(identifier, lua_tostring(lua(), -2))) - { - VERIFY(lua_gettop(lua()) >= 3); - lua_pop(lua(), 3); - VERIFY(lua_gettop(lua()) == start - 1); - return (true); - } - lua_pop(lua(), 1); - } - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(lua_gettop(lua()) == start - 1); - return (false); -} - -bool CScriptEngine::object(LPCSTR namespace_name, LPCSTR identifier, int type) -{ - int start = lua_gettop(lua()); - if (xr_strlen(namespace_name) && !namespace_loaded(namespace_name, false)) - { - VERIFY(lua_gettop(lua()) == start); - return (false); - } - bool result = object(identifier, type); - VERIFY(lua_gettop(lua()) == start); - return (result); -} - -bool CScriptEngine::function_object(LPCSTR function_to_call, luabind::object& object, int type) +bool CScriptEngine::function_object(LPCSTR function_to_call, luabind::object& out, int type) { - if (!xr_strlen(function_to_call)) - return (false); - - string256 name_space, function; + int start = lua_gettop(lua()); + lua_getglobal(lua(), "function_object"); + lua_pushstring(lua(), function_to_call); - // Parse namespace - LPCSTR I = function_to_call, J = 0; - for (; ; J = I, ++I) - { - I = strchr(I, '.'); - if (!I) - break; - } - xr_strcpy(name_space, sizeof(name_space), "_G"); - if (!J) - xr_strcpy(function, sizeof(function), function_to_call); - else + int l_iErrorCode = lua_pcall(lua(), 1, 1, 0); + VERIFY(lua_gettop(lua()) == start + 1); + if (l_iErrorCode) { - CopyMemory(name_space, function_to_call, u32(J - function_to_call) * sizeof(char)); - name_space[u32(J - function_to_call)] = 0; - xr_strcpy(function, sizeof(function), J + 1); + lua_pop(lua(), 1); + VERIFY(lua_gettop(lua()) == start); + return false; } - // If not _G, load corresponding package - if (xr_strcmp(name_space, "_G")) - { - LPSTR file_name = strchr(name_space, '.'); - if (!file_name) - load_package(name_space); - else - { - *file_name = 0; - load_package(name_space); - *file_name = '.'; - } - } - - if (!this->object(name_space, function, type)) - return (false); + bool is_type = lua_type(lua(), -1) == type; + out = luabind::object(lua()); + out.set(); - luabind::object lua_namespace = this->name_space(name_space); - object = lua_namespace[function]; - return (true); + return is_type; } void CScriptEngine::collect_all_garbage() diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index 910b9ac4a8..05a26df7b6 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -189,8 +189,6 @@ class CScriptEngine protected: void reinit(); static int vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker); - bool object(LPCSTR caIdentifier, int type); - bool object(LPCSTR caNamespaceName, LPCSTR caIdentifier, int type); DECLARE_SCRIPT_REGISTER_FUNCTION }; From 4a6f2509296efd4e1ed2b13140c0baf226f6c803 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 23 May 2025 18:33:04 +0100 Subject: [PATCH 30/76] Factor out `ScriptStorage` namespace in favor of `ScriptEngine` - Replace fully-qualified names with `using` prefix to reduce footprint --- src/xrGame/Inventory.cpp | 2 +- .../ai/stalker/ai_stalker_script_entity.cpp | 6 +- src/xrGame/level_script.cpp | 2 +- src/xrGame/relation_registry.cpp | 2 +- src/xrGame/script_bind_macroses.h | 2 +- src/xrGame/script_binder.cpp | 2 +- src/xrGame/script_game_object.cpp | 76 ++-- src/xrGame/script_game_object2.cpp | 88 ++--- src/xrGame/script_game_object3.cpp | 194 +++++----- src/xrGame/script_game_object4.cpp | 40 +- .../script_game_object_inventory_owner.cpp | 346 +++++++++--------- .../script_game_object_smart_covers.cpp | 82 +++-- src/xrGame/script_game_object_trader.cpp | 12 +- src/xrGame/script_game_object_use.cpp | 33 +- src/xrGame/script_game_object_use2.cpp | 50 +-- .../script_property_evaluator_wrapper.cpp | 2 +- src/xrGame/script_sound.cpp | 4 +- src/xrGame/script_sound_action.cpp | 2 +- src/xrGame/vs2022/xrGame.vcxproj | 2 + src/xrGame/vs2022/xrGame.vcxproj.filters | 6 + src/xrServerEntities/script_engine.cpp | 62 ++-- src/xrServerEntities/script_engine.h | 9 +- src/xrServerEntities/script_engine_space.h | 12 + src/xrServerEntities/script_process.cpp | 2 +- src/xrServerEntities/script_stack_tracker.cpp | 7 +- src/xrServerEntities/script_storage_space.h | 24 -- 26 files changed, 541 insertions(+), 528 deletions(-) delete mode 100644 src/xrServerEntities/script_storage_space.h diff --git a/src/xrGame/Inventory.cpp b/src/xrGame/Inventory.cpp index c83accaa77..59aa5cddec 100644 --- a/src/xrGame/Inventory.cpp +++ b/src/xrGame/Inventory.cpp @@ -1265,7 +1265,7 @@ CInventoryItem* CInventory::tpfGetObjectByIndex(int iIndex) } else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "invalid inventory index!"); + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "invalid inventory index!"); return (0); } R_ASSERT(false); diff --git a/src/xrGame/ai/stalker/ai_stalker_script_entity.cpp b/src/xrGame/ai/stalker/ai_stalker_script_entity.cpp index 796eeff0c8..852fa657e2 100644 --- a/src/xrGame/ai/stalker/ai_stalker_script_entity.cpp +++ b/src/xrGame/ai/stalker/ai_stalker_script_entity.cpp @@ -251,7 +251,7 @@ bool CAI_Stalker::bfAssignObject(CScriptEntityAction* tpEntityAction) l_tObjectAction.m_bCompleted = true; } else - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "cannot reload active item because it is not selected!"); // if (inventory().ActiveItem()) { @@ -306,7 +306,7 @@ bool CAI_Stalker::bfAssignObject(CScriptEntityAction* tpEntityAction) { if (inventory().GetItemFromInventory(*l_tObjectAction.m_tpObject->cName())) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "item is already in the inventory!"); return ((l_tObjectAction.m_bCompleted = true) == false); } @@ -318,7 +318,7 @@ bool CAI_Stalker::bfAssignObject(CScriptEntityAction* tpEntityAction) { if (!inventory().GetItemFromInventory(*l_tObjectAction.m_tpObject->cName())) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "item is not in the inventory!"); + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "item is not in the inventory!"); return ((l_tObjectAction.m_bCompleted = true) == false); } DropItemSendMessage(l_tObjectAction.m_tpObject); diff --git a/src/xrGame/level_script.cpp b/src/xrGame/level_script.cpp index ac115b0ce6..09ab83df2f 100644 --- a/src/xrGame/level_script.cpp +++ b/src/xrGame/level_script.cpp @@ -991,7 +991,7 @@ int g_get_general_goodwill_between(u16 from, u16 to) if (!from_obj || !to_obj) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "RELATION_REGISTRY::get_general_goodwill_between : cannot convert obj to CSE_ALifeTraderAbstract!"); return (0); } diff --git a/src/xrGame/relation_registry.cpp b/src/xrGame/relation_registry.cpp index 5703aa719a..4ee23d7cf3 100644 --- a/src/xrGame/relation_registry.cpp +++ b/src/xrGame/relation_registry.cpp @@ -167,7 +167,7 @@ void RELATION_REGISTRY::ForceSetGoodwill(u16 from, u16 to, CHARACTER_GOODWILL go if (!from_obj || !to_obj) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "RELATION_REGISTRY::ForceSetGoodwill : cannot convert obj to CSE_ALifeTraderAbstract!"); return; } diff --git a/src/xrGame/script_bind_macroses.h b/src/xrGame/script_bind_macroses.h index 10175dfc86..5206312213 100644 --- a/src/xrGame/script_bind_macroses.h +++ b/src/xrGame/script_bind_macroses.h @@ -22,7 +22,7 @@ #define CAST_OBJECT(Z,A,B)\ B *l_tpEntity = smart_cast(Z);\ if (!l_tpEntity) {\ - ai().script_engine().script_log (ScriptStorage::eLuaMessageTypeError,"%s : cannot access class member %s!",#B,#A); + ai().script_engine().script_log (ScriptEngine::eLuaMessageTypeError,"%s : cannot access class member %s!",#B,#A); #define CAST_OBJECT0(Z,A,B)\ CAST_OBJECT(Z,A,B)\ diff --git a/src/xrGame/script_binder.cpp b/src/xrGame/script_binder.cpp index 2680690891..b6654e70b5 100644 --- a/src/xrGame/script_binder.cpp +++ b/src/xrGame/script_binder.cpp @@ -93,7 +93,7 @@ void CScriptBinder::reload(LPCSTR section) luabind::functor lua_function; if (!ai().script_engine().functor(pSettings->r_string(section, "script_binding"), lua_function)) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "function %s is not loaded!", + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "function %s is not loaded!", pSettings->r_string(section, "script_binding")); return; } diff --git a/src/xrGame/script_game_object.cpp b/src/xrGame/script_game_object.cpp index 9fb3447b59..029a710527 100644 --- a/src/xrGame/script_game_object.cpp +++ b/src/xrGame/script_game_object.cpp @@ -49,6 +49,8 @@ #include "player_hud.h" #include "script_attachment_manager.h" +using namespace ScriptEngine; + class CScriptBinderObject; ////////////////////////////////////////////////////////////////////////// @@ -182,7 +184,7 @@ void CScriptGameObject::ResetActionQueue() { CScriptEntity* l_tpScriptMonster = smart_cast(&object()); if (!l_tpScriptMonster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member ResetActionQueue!"); else l_tpScriptMonster->ClearActionQueue(); @@ -192,7 +194,7 @@ CScriptEntityAction* CScriptGameObject::GetCurrentAction() const { CScriptEntity* l_tpScriptMonster = smart_cast(&object()); if (!l_tpScriptMonster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member GetCurrentAction!"); else if (l_tpScriptMonster->GetCurrentAction()) return (xr_new(l_tpScriptMonster->GetCurrentAction())); @@ -203,7 +205,7 @@ void CScriptGameObject::AddAction(const CScriptEntityAction* tpEntityAction, boo { CScriptEntity* l_tpScriptMonster = smart_cast(&object()); if (!l_tpScriptMonster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member AddAction!"); else l_tpScriptMonster->AddAction(tpEntityAction, bHighPriority); @@ -214,7 +216,7 @@ const CScriptEntityAction* CScriptGameObject::GetActionByIndex(u32 action_index) CScriptEntity* l_tpScriptMonster = smart_cast(&object()); if (!l_tpScriptMonster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptEntity : cannot access class member GetActionByIndex!"); return (0); } @@ -245,7 +247,7 @@ CHelicopter* CScriptGameObject::get_helicopter() CHelicopter* helicopter = smart_cast(&object()); if (!helicopter) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member get_helicopter!"); NODEFAULT; } @@ -257,7 +259,7 @@ CHangingLamp* CScriptGameObject::get_hanging_lamp() CHangingLamp* lamp = smart_cast(&object()); if (!lamp) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CGameObject : it is not a lamp!"); + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : it is not a lamp!"); NODEFAULT; } return lamp; @@ -268,7 +270,7 @@ CHolderCustom* CScriptGameObject::get_custom_holder() CHolderCustom* holder = smart_cast(&object()); if (!holder) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CGameObject : it is not a holder!"); + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : it is not a holder!"); } return holder; } @@ -286,7 +288,7 @@ LPCSTR CScriptGameObject::WhoHitName() : NULL; else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member WhoHitName()"); return NULL; } @@ -301,7 +303,7 @@ LPCSTR CScriptGameObject::WhoHitSectionName() : NULL; else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member WhoHitName()"); return NULL; } @@ -312,7 +314,7 @@ bool CScriptGameObject::CheckObjectVisibility(const CScriptGameObject* tpLuaGame CEntityAlive* entity_alive = smart_cast(&object()); if (entity_alive && !entity_alive->g_Alive()) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot check visibility of dead object!"); return (false); } @@ -323,7 +325,7 @@ bool CScriptGameObject::CheckObjectVisibility(const CScriptGameObject* tpLuaGame CActor* actor = smart_cast(&object()); if (!actor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member CheckObjectVisibility!"); return (false); } @@ -351,7 +353,7 @@ void CScriptGameObject::set_previous_point(int point_index) { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member set_previous_point!"); else monster->movement().patrol().set_previous_point(point_index); @@ -361,7 +363,7 @@ void CScriptGameObject::set_start_point(int point_index) { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member set_start_point!"); else monster->movement().patrol().set_start_point(point_index); @@ -372,7 +374,7 @@ u32 CScriptGameObject::get_current_patrol_point_index() CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot call [get_current_patrol_point_index()]!"); return (u32(-1)); } @@ -697,7 +699,7 @@ void CScriptGameObject::SetQueueSize(u32 queue_size) CWeaponMagazined* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeaponMagazined : cannot access class member SetQueueSize!"); return; } @@ -713,7 +715,7 @@ u32 CScriptGameObject::Cost() const CInventoryItem* inventory_item = smart_cast(&object()); if (!inventory_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member Cost!"); return (false); } @@ -725,7 +727,7 @@ float CScriptGameObject::GetCondition() const CInventoryItem* inventory_item = smart_cast(&object()); if (!inventory_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member GetCondition!"); return (false); } @@ -737,7 +739,7 @@ void CScriptGameObject::SetCondition(float val) CInventoryItem* inventory_item = smart_cast(&object()); if (!inventory_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member SetCondition!"); return; } @@ -750,7 +752,7 @@ float CScriptGameObject::GetPowerCritical() const CInventoryItem* inventory_item = smart_cast(&object()); if (!inventory_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member GetPowerCritical!"); return 0.f; } @@ -762,7 +764,7 @@ float CScriptGameObject::GetPsyFactor() const CPda* pda = smart_cast(&object()); if (!pda) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member GetPsyFactor!"); return 0.f; } @@ -774,7 +776,7 @@ void CScriptGameObject::SetPsyFactor(float val) CPda* pda = smart_cast(&object()); if (!pda) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member SetPsyFactor!"); return; } @@ -785,7 +787,7 @@ void CScriptGameObject::eat(CScriptGameObject* item) { if (!item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member eat!"); return; } @@ -793,7 +795,7 @@ void CScriptGameObject::eat(CScriptGameObject* item) CInventoryItem* inventory_item = smart_cast(&item->object()); if (!inventory_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member eat!"); return; } @@ -801,7 +803,7 @@ void CScriptGameObject::eat(CScriptGameObject* item) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member eat!"); return; } @@ -814,7 +816,7 @@ bool CScriptGameObject::inside(const Fvector& position, float epsilon) const CSpaceRestrictor* space_restrictor = smart_cast(&object()); if (!space_restrictor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSpaceRestrictor : cannot access class member inside!"); return (false); } @@ -834,7 +836,7 @@ void CScriptGameObject::set_patrol_extrapolate_callback(const luabind::functor(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member set_patrol_extrapolate_callback!"); return; } @@ -847,7 +849,7 @@ void CScriptGameObject::set_patrol_extrapolate_callback(const luabind::functor(&this->object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member set_patrol_extrapolate_callback!"); return; } @@ -859,7 +861,7 @@ void CScriptGameObject::set_patrol_extrapolate_callback() CCustomMonster* monster = smart_cast(&this->object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member set_patrol_extrapolate_callback!"); return; } @@ -871,7 +873,7 @@ void CScriptGameObject::extrapolate_length(float extrapolate_length) CCustomMonster* monster = smart_cast(&this->object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member extrapolate_length!"); return; } @@ -883,7 +885,7 @@ float CScriptGameObject::extrapolate_length() const CCustomMonster* monster = smart_cast(&this->object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member extrapolate_length!"); return (0.f); } @@ -895,7 +897,7 @@ void CScriptGameObject::set_fov(float new_fov) CCustomMonster* monster = smart_cast(&this->object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member set_fov!"); return; } @@ -907,7 +909,7 @@ void CScriptGameObject::set_range(float new_range) CCustomMonster* monster = smart_cast(&this->object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member set_range!"); return; } @@ -919,14 +921,14 @@ u32 CScriptGameObject::vertex_in_direction(u32 level_vertex_id, Fvector directio CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member vertex_in_direction!"); return (u32(-1)); } if (!monster->movement().restrictions().accessible(level_vertex_id)) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster::vertex_in_direction - start vertex id is not accessible!"); return (u32(-1)); } @@ -947,7 +949,7 @@ bool CScriptGameObject::invulnerable() const CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member invulnerable!"); return (false); } @@ -960,7 +962,7 @@ void CScriptGameObject::invulnerable(bool invulnerable) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member invulnerable!"); return; } @@ -973,7 +975,7 @@ LPCSTR CScriptGameObject::get_smart_cover_description() const smart_cover::object* smart_cover_object = smart_cast(&object()); if (!smart_cover_object) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "smart_cover::object : cannot access class member get_smart_cover_description!"); return (0); } diff --git a/src/xrGame/script_game_object2.cpp b/src/xrGame/script_game_object2.cpp index 4a95ae02c5..b488d43edc 100644 --- a/src/xrGame/script_game_object2.cpp +++ b/src/xrGame/script_game_object2.cpp @@ -41,18 +41,20 @@ #include "InventoryOwner.h" #include "CharacterPhysicsSupport.h" +using namespace ScriptEngine; + void CScriptGameObject::explode(u32 level_time) { CExplosive* explosive = smart_cast(&object()); if (object().H_Parent()) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CExplosive : cannot explode object wiht parent!"); return; } if (!explosive) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CExplosive : cannot access class member explode!"); else { @@ -68,7 +70,7 @@ bool CScriptGameObject::active_zone_contact(u16 id) CScriptZone* script_zone = smart_cast(&object()); if (!script_zone) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptZone : cannot access class member active_zone_contact!"); return (false); } @@ -80,7 +82,7 @@ CScriptGameObject* CScriptGameObject::best_weapon() CObjectHandler* object_handler = smart_cast(&object()); if (!object_handler) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptEntity : cannot access class member best_weapon!"); return (0); } @@ -102,7 +104,7 @@ void CScriptGameObject::set_item(MonsterSpace::EObjectAction object_action) { CObjectHandler* object_handler = smart_cast(&object()); if (!object_handler) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CObjectHandler : cannot access class member set_item!"); else object_handler->set_goal(object_action); @@ -112,7 +114,7 @@ void CScriptGameObject::set_item(MonsterSpace::EObjectAction object_action, CScr { CObjectHandler* object_handler = smart_cast(&object()); if (!object_handler) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CObjectHandler : cannot access class member set_item!"); else object_handler->set_goal(object_action, lua_game_object ? &lua_game_object->object() : 0); @@ -123,7 +125,7 @@ void CScriptGameObject::set_item(MonsterSpace::EObjectAction object_action, CScr { CObjectHandler* object_handler = smart_cast(&object()); if (!object_handler) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CObjectHandler : cannot access class member set_item!"); else object_handler->set_goal(object_action, lua_game_object ? &lua_game_object->object() : 0, queue_size, @@ -135,7 +137,7 @@ void CScriptGameObject::set_item(MonsterSpace::EObjectAction object_action, CScr { CObjectHandler* object_handler = smart_cast(&object()); if (!object_handler) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CObjectHandler : cannot access class member set_item!"); else object_handler->set_goal(object_action, lua_game_object ? &lua_game_object->object() : 0, queue_size, @@ -151,13 +153,13 @@ void CScriptGameObject::play_cycle(LPCSTR anim, bool mix_in) if (m) sa->PlayCycle(m, (BOOL)mix_in); else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CGameObject : has not cycle %s", + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : has not cycle %s", anim); } } else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CGameObject : is not animated object"); + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : is not animated object"); } } @@ -232,7 +234,7 @@ u32 CScriptGameObject::memory_time(const CScriptGameObject& lua_game_object) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptEntity : cannot access class member memory!"); return (0); } @@ -245,7 +247,7 @@ Fvector CScriptGameObject::memory_position(const CScriptGameObject& lua_game_obj CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptEntity : cannot access class member memory!"); return (Fvector().set(0.f, 0.f, 0.f)); } @@ -257,7 +259,7 @@ void CScriptGameObject::enable_memory_object(CScriptGameObject* game_object, boo { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member enable_memory_object!"); else monster->memory().enable(&game_object->object(), enable); @@ -268,7 +270,7 @@ const xr_vector& CScriptGameObject::not_yet_visible_object CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member not_yet_visible_objects!"); NODEFAULT; } @@ -280,7 +282,7 @@ float CScriptGameObject::visibility_threshold() const CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member visibility_threshold!"); NODEFAULT; } @@ -292,7 +294,7 @@ void CScriptGameObject::enable_vision(bool value) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CVisualMemoryManager : cannot access class member enable_vision!"); return; } @@ -304,7 +306,7 @@ bool CScriptGameObject::vision_enabled() const CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CVisualMemoryManager : cannot access class member vision_enabled!"); return (false); } @@ -316,7 +318,7 @@ void CScriptGameObject::set_sound_threshold(float value) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundMemoryManager : cannot access class member set_sound_threshold!"); return; } @@ -328,7 +330,7 @@ void CScriptGameObject::restore_sound_threshold() CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundMemoryManager : cannot access class member restore_sound_threshold!"); return; } @@ -381,7 +383,7 @@ void CScriptGameObject::SetActorPosition(Fvector pos, bool bskip_collision_corre } } else - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ScriptGameObject : attempt to call SetActorPosition method for non-actor object"); } @@ -399,7 +401,7 @@ void CScriptGameObject::SetNpcPosition(Fvector pos) // actor->XFORM().c = pos; } else - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ScriptGameObject : attempt to call SetActorPosition method for non-CCustomMonster object"); } @@ -412,7 +414,7 @@ void CScriptGameObject::SetActorDirection(float dir, float pitch, float roll) actor->cam_Active()->Set(dir, pitch, roll); // actor->XFORM().setXYZ(0,dir,0); } else - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ScriptGameObject : attempt to call SetActorDirection method for non-actor object"); } @@ -438,7 +440,7 @@ void CScriptGameObject::DisableHitMarks(bool disable) if (actor) actor->DisableHitMarks(disable); else - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ScriptGameObject : attempt to call DisableHitMarks method for non-actor object"); } @@ -449,7 +451,7 @@ bool CScriptGameObject::DisableHitMarks() const return actor->DisableHitMarks(); else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ScriptGameObject : attempt to call DisableHitMarks method for non-actor object"); return false; } @@ -460,7 +462,7 @@ Fvector CScriptGameObject::GetMovementSpeed() const CActor* actor = smart_cast(&object()); if (!actor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ScriptGameObject : attempt to call GetMovementSpeed method for non-actor object"); NODEFAULT; } @@ -474,7 +476,7 @@ void CScriptGameObject::SetMovementSpeed(Fvector vel) CActor* actor = smart_cast(&object()); if (!actor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ScriptGameObject : attempt to call SetMovementSpeed method for non-actor object"); return; } @@ -496,7 +498,7 @@ void CScriptGameObject::set_ignore_monster_threshold(float ignore_monster_thresh CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_ignore_monster_threshold!"); return; } @@ -509,7 +511,7 @@ void CScriptGameObject::restore_ignore_monster_threshold() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member restore_ignore_monster_threshold!"); return; } @@ -521,7 +523,7 @@ float CScriptGameObject::ignore_monster_threshold() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member ignore_monster_threshold!"); return (0.f); } @@ -533,7 +535,7 @@ void CScriptGameObject::set_max_ignore_monster_distance(const float& max_ignore_ CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_max_ignore_monster_distance!"); return; } @@ -545,7 +547,7 @@ void CScriptGameObject::restore_max_ignore_monster_distance() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member restore_max_ignore_monster_distance!"); return; } @@ -557,7 +559,7 @@ float CScriptGameObject::max_ignore_monster_distance() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member max_ignore_monster_distance!"); return (0.f); } @@ -569,7 +571,7 @@ CCar* CScriptGameObject::get_car() CCar* car = smart_cast(&object()); if (!car) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member get_car!"); NODEFAULT; } @@ -581,7 +583,7 @@ void CScriptGameObject::debug_planner (const script_planner *planner) { CAI_Stalker *stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log (ScriptStorage::eLuaMessageTypeError,"CAI_Stalker : cannot access class member debug_planner!"); + ai().script_engine().script_log (eLuaMessageTypeError,"CAI_Stalker : cannot access class member debug_planner!"); return; } @@ -593,7 +595,7 @@ u32 CScriptGameObject::location_on_path(float distance, Fvector* location) { if (!location) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : location_on_path -> specify destination location!"); return (u32(-1)); } @@ -601,7 +603,7 @@ u32 CScriptGameObject::location_on_path(float distance, Fvector* location) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member location_on_path!"); return (u32(-1)); } @@ -615,7 +617,7 @@ bool CScriptGameObject::is_there_items_to_pickup() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member is_there_items_to_pickup!"); return false; } @@ -713,7 +715,7 @@ CScriptGameObject* CScriptGameObject::get_talking_npc() { CInventoryOwner* pInvOwner = smart_cast(&object()); if (!pInvOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : get_talking_npc works only with CInventoryOwner!"); return nullptr; } @@ -733,14 +735,14 @@ luabind::object CScriptGameObject::get_scope_ui() { luabind::object table = luabind::newtable(ai().script_engine().lua()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : get_scope_ui works only with CWeapon object!"); return table; } auto& zoomTextureWndList = weapon->ZoomTexture()->GetChildWndList(); if (zoomTextureWndList.empty()) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : get_scope_ui, no scope texture found for %s!", weapon->cNameSect().c_str()); return table; } @@ -750,7 +752,7 @@ luabind::object CScriptGameObject::get_scope_ui() { for (int i = 0; i < zoomTextureWndList.size(); i++) { CUIStatic* staticWnd = smart_cast(zoomTextureWndList[i]); if (!staticWnd) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : get_scope_ui, can't cast scope texture %d to CUIStatic for %s!", i, weapon->cNameSect().c_str()); } else { staticChildren[i + 1] = staticWnd; @@ -768,14 +770,14 @@ void CScriptGameObject::set_scope_ui(LPCSTR scope_texture) { CWeapon* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : set_scope_ui works only with CWeapon object!"); return; } auto wnd = weapon->ZoomTexture(); if (!wnd) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : set_scope_ui no scope found for %s!", weapon->cNameSect().c_str()); return; } diff --git a/src/xrGame/script_game_object3.cpp b/src/xrGame/script_game_object3.cpp index 5ae097ab08..498ec87eb7 100644 --- a/src/xrGame/script_game_object3.cpp +++ b/src/xrGame/script_game_object3.cpp @@ -56,6 +56,8 @@ #include "Torch.h" #include "Flashlight.h" +using namespace ScriptEngine; + namespace MemorySpace { struct CVisibleObject; @@ -69,7 +71,7 @@ const CCoverPoint* CScriptGameObject::best_cover(const Fvector& position, const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member best_cover!"); return (0); } @@ -83,7 +85,7 @@ const CCoverPoint* CScriptGameObject::safe_cover(const Fvector& position, float CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member best_cover!"); return (0); } @@ -97,7 +99,7 @@ const xr_vector& CScriptGameObject::memory_visible_ CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member memory_visible_objects!"); NODEFAULT; } @@ -109,7 +111,7 @@ const xr_vector& CScriptGameObject::memory_sound_obje CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member memory_sound_objects!"); NODEFAULT; } @@ -121,7 +123,7 @@ const xr_vector& CScriptGameObject::memory_hit_objects( CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member memory_hit_objects!"); NODEFAULT; } @@ -132,7 +134,7 @@ void CScriptGameObject::ChangeTeam(u8 team, u8 squad, u8 group) { CCustomMonster* custom_monster = smart_cast(&object()); if (!custom_monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster: cannot access class member ChangeTeam!"); else custom_monster->ChangeTeam(team, squad, group); @@ -142,7 +144,7 @@ void CScriptGameObject::SetVisualMemoryEnabled(bool enabled) { CCustomMonster* custom_monster = smart_cast(&object()); if (!custom_monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster: cannot access class member ChangeTeam!"); else custom_monster->memory().visual().enable(enabled); @@ -160,7 +162,7 @@ CScriptGameObject* CScriptGameObject::GetEnemy() const } else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member GetEnemy!"); return (0); } @@ -176,7 +178,7 @@ CScriptGameObject* CScriptGameObject::GetCorpse() const else return (0); else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member GetCorpse!"); return (0); } @@ -189,7 +191,7 @@ bool CScriptGameObject::CheckTypeVisibility(const char* section_name) return (l_tpCustomMonster->CheckTypeVisibility(section_name)); else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member CheckTypeVisibility!"); return (false); } @@ -200,7 +202,7 @@ CScriptGameObject* CScriptGameObject::GetCurrentWeapon() const CAI_Stalker* l_tpStalker = smart_cast(&object()); if (!l_tpStalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member GetCurrentWeapon!"); return (0); } @@ -213,7 +215,7 @@ void CScriptGameObject::deadbody_closed(bool status) CInventoryOwner* inventoryOwner = smart_cast(&object()); if (!inventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member deadbody_closed!"); return; } @@ -225,7 +227,7 @@ bool CScriptGameObject::deadbody_closed_status() CInventoryOwner* inventoryOwner = smart_cast(&object()); if (!inventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member deadbody_closed_status!"); return (0); } @@ -237,7 +239,7 @@ void CScriptGameObject::can_select_weapon(bool status) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member can_select_weapon!"); return; } @@ -249,7 +251,7 @@ bool CScriptGameObject::can_select_weapon() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member can_select_weapon!"); return (0); } @@ -261,7 +263,7 @@ void CScriptGameObject::deadbody_can_take(bool status) CInventoryOwner* inventoryOwner = smart_cast(&object()); if (!inventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member deadbody_can_take!"); return; } @@ -273,7 +275,7 @@ bool CScriptGameObject::deadbody_can_take_status() CInventoryOwner* inventoryOwner = smart_cast(&object()); if (!inventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member deadbody_can_take_status!"); return (0); } @@ -287,7 +289,7 @@ CScriptGameObject* CScriptGameObject::GetCurrentOutfit() const CInventoryOwner* inventoryOwner = smart_cast(&object()); if (!inventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member GetCurrentOutfit!"); return (0); } @@ -301,7 +303,7 @@ float CScriptGameObject::GetCurrentOutfitProtection(int hit_type) CInventoryOwner* inventoryOwner = smart_cast(&object()); if (!inventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member GetCurrentOutfitProtection!"); return (0); } @@ -317,7 +319,7 @@ CScriptGameObject* CScriptGameObject::GetFood() const CAI_Stalker* l_tpStalker = smart_cast(&object()); if (!l_tpStalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member GetFood!"); return (0); } @@ -330,7 +332,7 @@ CScriptGameObject* CScriptGameObject::GetMedikit() const CAI_Stalker* l_tpStalker = smart_cast(&object()); if (!l_tpStalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member GetCurrentWeapon!"); return (0); } @@ -346,7 +348,7 @@ LPCSTR CScriptGameObject::GetPatrolPathName() CScriptEntity* script_monster = smart_cast(&object()); if (!script_monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member GetPatrolPathName!"); return (""); } @@ -362,7 +364,7 @@ void CScriptGameObject::add_animation(LPCSTR animation, bool hand_usage, bool us CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member add_animation!"); return; } @@ -395,7 +397,7 @@ void CScriptGameObject::add_animation(LPCSTR animation, bool hand_usage, Fvector CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member add_animation!"); return; } @@ -427,7 +429,7 @@ void CScriptGameObject::clear_animations() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member clear_animations!"); return; } @@ -439,7 +441,7 @@ int CScriptGameObject::animation_count() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member clear_animations!"); return (-1); } @@ -466,7 +468,7 @@ void CScriptGameObject::set_patrol_path(LPCSTR path_name, const PatrolPathManage { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else stalker->movement().patrol().set_path(path_name, patrol_start_type, patrol_route_type, random); @@ -476,7 +478,7 @@ void CScriptGameObject::inactualize_patrol_path() { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else stalker->movement().patrol().make_inactual(); @@ -486,21 +488,21 @@ void CScriptGameObject::set_dest_level_vertex_id(u32 level_vertex_id) { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_dest_level_vertex_id!"); else { if (!ai().level_graph().valid_vertex_id(level_vertex_id)) { #ifdef DEBUG - ai().script_engine().script_log (ScriptStorage::eLuaMessageTypeError,"CAI_Stalker : invalid vertex id being setup by action %s!",stalker->brain().CStalkerPlanner::current_action().m_action_name); + ai().script_engine().script_log (eLuaMessageTypeError,"CAI_Stalker : invalid vertex id being setup by action %s!",stalker->brain().CStalkerPlanner::current_action().m_action_name); #endif return; } if (!stalker->movement().restrictions().accessible(level_vertex_id)) { ai().script_engine().script_log( - ScriptStorage::eLuaMessageTypeError, + eLuaMessageTypeError, "! you are trying to setup destination for the stalker %s, which is not accessible by its restrictors in[%s] out[%s]", stalker->cName().c_str(), Level().space_restriction_manager().in_restrictions(stalker->ID()).c_str(), @@ -516,14 +518,14 @@ void CScriptGameObject::set_dest_game_vertex_id(GameGraph::_GRAPH_ID game_vertex { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_dest_game_vertex_id!"); else { if (!ai().game_graph().valid_vertex_id(game_vertex_id)) { #ifdef DEBUG - ai().script_engine().script_log (ScriptStorage::eLuaMessageTypeError,"CAI_Stalker : invalid vertex id being setup by action %s!",stalker->brain().CStalkerPlanner::current_action().m_action_name); + ai().script_engine().script_log (eLuaMessageTypeError,"CAI_Stalker : invalid vertex id being setup by action %s!",stalker->brain().CStalkerPlanner::current_action().m_action_name); #endif return; } @@ -535,7 +537,7 @@ void CScriptGameObject::set_movement_selection_type(ESelectionType selection_typ { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_movement_selection_type!"); stalker->movement().game_selector().set_selection_type(selection_type); } @@ -545,7 +547,7 @@ CHARACTER_RANK_VALUE CScriptGameObject::GetRank() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member GetRank!"); return (CHARACTER_RANK_VALUE(0)); } @@ -557,7 +559,7 @@ void CScriptGameObject::set_desired_position() { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else stalker->movement().set_desired_position(0); @@ -567,7 +569,7 @@ void CScriptGameObject::set_desired_position(const Fvector* desired_position) { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else { @@ -580,7 +582,7 @@ void CScriptGameObject::set_desired_direction() { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else stalker->movement().set_desired_direction(0); @@ -590,18 +592,18 @@ void CScriptGameObject::set_desired_direction(const Fvector* desired_direction) { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else { if (fsimilar(desired_direction->magnitude(), 0.f)) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : [%s] set_desired_direction - you passed zero direction!", stalker->cName().c_str()); else { if (!fsimilar(desired_direction->magnitude(), 1.f)) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : [%s] set_desired_direction - you passed non-normalized direction!", stalker->cName().c_str()); } @@ -617,7 +619,7 @@ void CScriptGameObject::set_body_state(EBodyState body_state) THROW((body_state == eBodyStateStand) || (body_state == eBodyStateCrouch)); CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else stalker->movement().set_body_state(body_state); @@ -627,7 +629,7 @@ void CScriptGameObject::set_movement_type(EMovementType movement_type) { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else stalker->movement().set_movement_type(movement_type); @@ -637,7 +639,7 @@ void CScriptGameObject::set_mental_state(EMentalState mental_state) { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else { @@ -645,7 +647,7 @@ void CScriptGameObject::set_mental_state(EMentalState mental_state) if (mental_state != eMentalStateDanger) { if (stalker->brain().initialized()) { if (stalker->brain().current_action_id() == StalkerDecisionSpace::eWorldOperatorCombatPlanner) { - ai().script_engine().script_log (ScriptStorage::eLuaMessageTypeError,"CAI_Stalker : set_mental_state is used during universal combat!, object[%s]", stalker->cName().c_str()); + ai().script_engine().script_log (eLuaMessageTypeError,"CAI_Stalker : set_mental_state is used during universal combat!, object[%s]", stalker->cName().c_str()); // return; } } @@ -659,7 +661,7 @@ void CScriptGameObject::set_path_type(MovementManager::EPathType path_type) { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else stalker->movement().set_path_type(path_type); @@ -669,7 +671,7 @@ void CScriptGameObject::set_detail_path_type(DetailPathManager::EDetailPathType { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement!"); else stalker->movement().set_detail_path_type(detail_path_type); @@ -680,7 +682,7 @@ MonsterSpace::EBodyState CScriptGameObject::body_state() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member body_state!"); return (MonsterSpace::eBodyStateStand); } @@ -692,7 +694,7 @@ MonsterSpace::EBodyState CScriptGameObject::target_body_state() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member body_state!"); return (MonsterSpace::eBodyStateStand); } @@ -704,7 +706,7 @@ MonsterSpace::EMovementType CScriptGameObject::movement_type() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement_type!"); return (MonsterSpace::eMovementTypeStand); } @@ -716,7 +718,7 @@ MonsterSpace::EMovementType CScriptGameObject::target_movement_type() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member target_movement_type!"); return (MonsterSpace::eMovementTypeStand); } @@ -728,7 +730,7 @@ MonsterSpace::EMentalState CScriptGameObject::mental_state() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member mental_state!"); return (MonsterSpace::eMentalStateDanger); } @@ -740,7 +742,7 @@ MonsterSpace::EMentalState CScriptGameObject::target_mental_state() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member mental_state!"); return (MonsterSpace::eMentalStateDanger); } @@ -752,7 +754,7 @@ MovementManager::EPathType CScriptGameObject::path_type() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member path_type!"); return (MovementManager::ePathTypeNoPath); } @@ -764,7 +766,7 @@ DetailPathManager::EDetailPathType CScriptGameObject::detail_path_type() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member detail_path_type!"); return (DetailPathManager::eDetailPathTypeSmooth); } @@ -775,7 +777,7 @@ void CScriptGameObject::set_sight(SightManager::ESightType sight_type, Fvector* { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSightManager : cannot access class member set_sight!"); else { @@ -793,7 +795,7 @@ void CScriptGameObject::set_sight(SightManager::ESightType sight_type, bool tors { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSightManager : cannot access class member set_sight!"); else stalker->sight().setup(sight_type, torso_look, path); @@ -803,7 +805,7 @@ void CScriptGameObject::set_sight(SightManager::ESightType sight_type, Fvector& { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSightManager : cannot access class member set_sight!"); else { @@ -821,7 +823,7 @@ void CScriptGameObject::set_sight(SightManager::ESightType sight_type, Fvector* { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSightManager : cannot access class member set_sight!"); else { @@ -839,7 +841,7 @@ void CScriptGameObject::set_sight(CScriptGameObject* object_to_look) { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSightManager : cannot access class member set_sight!"); else stalker->sight().setup(&object_to_look->object()); @@ -849,7 +851,7 @@ void CScriptGameObject::set_sight(CScriptGameObject* object_to_look, bool torso_ { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSightManager : cannot access class member set_sight!"); else stalker->sight().setup(&object_to_look->object(), torso_look); @@ -859,7 +861,7 @@ void CScriptGameObject::set_sight(CScriptGameObject* object_to_look, bool torso_ { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSightManager : cannot access class member set_sight!"); else stalker->sight().setup(&object_to_look->object(), torso_look, fire_object); @@ -869,7 +871,7 @@ void CScriptGameObject::set_sight(CScriptGameObject* object_to_look, bool torso_ { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSightManager : cannot access class member set_sight!"); else stalker->sight().setup(CSightAction(&object_to_look->object(), torso_look, fire_object, no_pitch)); @@ -879,7 +881,7 @@ void CScriptGameObject::set_sight(const CMemoryInfo* memory_object, bool torso_l { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSightManager : cannot access class member set_sight!"); else stalker->sight().setup(memory_object, torso_look); @@ -897,7 +899,7 @@ u32 CScriptGameObject::GetInventoryObjectCount() const return (l_tpInventoryOwner->inventory().dwfGetObjectCount()); else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member obj_count!"); return (0); } @@ -913,7 +915,7 @@ CScriptGameObject* CScriptGameObject::GetActiveItem() return (0); else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member activge_item!"); return (0); } @@ -947,7 +949,7 @@ CScriptGameObject* CScriptGameObject::GetObjectByName(LPCSTR caObjectName) const } else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member object!"); return (0); } @@ -967,7 +969,7 @@ CScriptGameObject* CScriptGameObject::GetObjectByIndex(int iIndex) const } else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member object!"); return (0); } @@ -1003,7 +1005,7 @@ CScriptGameObject* CScriptGameObject::GetObjectById(u16 id) const } else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member object_id!"); return (0); } @@ -1099,7 +1101,7 @@ bool CScriptGameObject::weapon_strapped() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member weapon_strapped!"); return (false); } @@ -1114,7 +1116,7 @@ bool CScriptGameObject::weapon_unstrapped() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member weapon_unstrapped!"); return (false); } @@ -1128,7 +1130,7 @@ bool CScriptGameObject::path_completed() const CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member path_completed!"); return (false); } @@ -1140,7 +1142,7 @@ void CScriptGameObject::patrol_path_make_inactual() CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member patrol_path_make_inactual!"); return; } @@ -1153,7 +1155,7 @@ Fvector CScriptGameObject::head_orientation() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member head_orientation!"); return (Fvector().set(flt_max,flt_max,flt_max)); } @@ -1180,7 +1182,7 @@ void CScriptGameObject::jump(const Fvector& position, float factor) CBaseMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot process jump for not a monster!"); return; } @@ -1194,7 +1196,7 @@ void CScriptGameObject::make_object_visible_somewhen(CScriptGameObject* object) CAI_Stalker* stalker = smart_cast(&this->object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member make_object_visible_somewhen!"); return; } @@ -1202,7 +1204,7 @@ void CScriptGameObject::make_object_visible_somewhen(CScriptGameObject* object) CEntityAlive* entity_alive = smart_cast(&object->object()); if (!entity_alive) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CEntityAlive : cannot access class member make_object_visible_somewhen!"); return; } @@ -1215,7 +1217,7 @@ void CScriptGameObject::sell_condition(CScriptIniFile* ini_file, LPCSTR section) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member sell_condition!"); return; } @@ -1228,7 +1230,7 @@ void CScriptGameObject::sell_condition(float friend_factor, float enemy_factor) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member sell_condition!"); return; } @@ -1247,7 +1249,7 @@ void CScriptGameObject::buy_condition(CScriptIniFile* ini_file, LPCSTR section) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member buy_condition!"); return; } @@ -1260,7 +1262,7 @@ void CScriptGameObject::buy_condition(float friend_factor, float enemy_factor) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member buy_condition!"); return; } @@ -1279,7 +1281,7 @@ void CScriptGameObject::show_condition(CScriptIniFile* ini_file, LPCSTR section) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member show_condition!"); return; } @@ -1296,7 +1298,7 @@ void CScriptGameObject::buy_supplies(CScriptIniFile* ini_file, LPCSTR section) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member buy_condition!"); return; } @@ -1312,7 +1314,7 @@ void CScriptGameObject::buy_item_condition_factor(float factor) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member buy_item_condition_factor!"); return; } @@ -1325,7 +1327,7 @@ void CScriptGameObject::buy_item_exponent(float factor) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member buy_item_exponent!"); return; } @@ -1338,7 +1340,7 @@ void CScriptGameObject::sell_item_exponent(float factor) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member sell_item_exponent!"); return; } @@ -1388,7 +1390,7 @@ LPCSTR CScriptGameObject::sound_prefix() const CCustomMonster* custom_monster = smart_cast(&object()); if (!custom_monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member sound_prefix!"); return (0); } @@ -1401,7 +1403,7 @@ void CScriptGameObject::sound_prefix(LPCSTR sound_prefix) CCustomMonster* custom_monster = smart_cast(&object()); if (!custom_monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member sound_prefix!"); return; } @@ -1413,7 +1415,7 @@ bool CScriptGameObject::is_weapon_going_to_be_strapped(CScriptGameObject const* { if (!object) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member is_weapon_going_to_be_strapped (object passed is null)!"); return false; } @@ -1421,7 +1423,7 @@ bool CScriptGameObject::is_weapon_going_to_be_strapped(CScriptGameObject const* CAI_Stalker const* stalker = smart_cast(&this->object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member is_weapon_going_to_be_strapped!"); return false; } @@ -1579,7 +1581,7 @@ void CScriptGameObject::AttachVehicle(CScriptGameObject* veh, bool bForce) if (vehicle) actor->use_HolderEx(vehicle, bForce); else - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CGameObject : cannot be cast to CHolderCustom!"); + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot be cast to CHolderCustom!"); } } @@ -1811,7 +1813,7 @@ void CScriptGameObject::ForceSetAngle(Fvector ang, bool bActivate) else { LPCSTR text = "force_set_angleHPB: object %s has no physics shell!"; - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, text, object().Name()); + ai().script_engine().script_log(eLuaMessageTypeError, text, object().Name()); } } @@ -1918,7 +1920,7 @@ bool CScriptGameObject::get_enable_anomalies_pathfinding() auto stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member m_enable_anomalies_pathfinding!"); return false; } @@ -1929,7 +1931,7 @@ void CScriptGameObject::set_enable_anomalies_pathfinding(bool v) auto stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member m_enable_anomalies_pathfinding!"); return; } @@ -1940,7 +1942,7 @@ bool CScriptGameObject::get_enable_anomalies_damage() auto stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member m_enable_anomalies_damage!"); return false; } @@ -1951,7 +1953,7 @@ void CScriptGameObject::set_enable_anomalies_damage(bool v) auto stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member m_enable_anomalies_damage!"); return; } diff --git a/src/xrGame/script_game_object4.cpp b/src/xrGame/script_game_object4.cpp index bbf5407388..7caba56a76 100644 --- a/src/xrGame/script_game_object4.cpp +++ b/src/xrGame/script_game_object4.cpp @@ -51,6 +51,8 @@ #include "antirad.h" #include "BottleItem.h" +using namespace ScriptEngine; + class CWeapon; ////////////////////////////////////////////////////////////////////////// @@ -62,7 +64,7 @@ bool CScriptGameObject::is_body_turning() const CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member is_turning!"); return (false); } @@ -88,7 +90,7 @@ u32 CScriptGameObject::add_sound(LPCSTR prefix, u32 max_count, ESoundTypes type, CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundPlayer : cannot access class member add!"); return (0); } @@ -102,7 +104,7 @@ u32 CScriptGameObject::add_combat_sound(LPCSTR prefix, u32 max_count, ESoundType CAI_Stalker* const stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundPlayer : cannot access class member add!"); return (0); } @@ -121,7 +123,7 @@ void CScriptGameObject::remove_sound(u32 internal_type) { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundPlayer : cannot access class member add!"); else monster->sound().remove(internal_type); @@ -131,7 +133,7 @@ void CScriptGameObject::set_sound_mask(u32 sound_mask) { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundPlayer : cannot access class member set_sound_mask!"); else { @@ -148,7 +150,7 @@ void CScriptGameObject::play_sound(u32 internal_type) { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundPlayer : cannot access class member play!"); else monster->sound().play(internal_type); @@ -158,7 +160,7 @@ void CScriptGameObject::play_sound(u32 internal_type, u32 max_start_time) { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundPlayer : cannot access class member play!"); else monster->sound().play(internal_type, max_start_time); @@ -168,7 +170,7 @@ void CScriptGameObject::play_sound(u32 internal_type, u32 max_start_time, u32 mi { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundPlayer : cannot access class member play!"); else monster->sound().play(internal_type, max_start_time, min_start_time); @@ -178,7 +180,7 @@ void CScriptGameObject::play_sound(u32 internal_type, u32 max_start_time, u32 mi { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundPlayer : cannot access class member play!"); else monster->sound().play(internal_type, max_start_time, min_start_time, max_stop_time); @@ -189,7 +191,7 @@ void CScriptGameObject::play_sound(u32 internal_type, u32 max_start_time, u32 mi { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundPlayer : cannot access class member play!"); else monster->sound().play(internal_type, max_start_time, min_start_time, max_stop_time, min_stop_time); @@ -200,7 +202,7 @@ void CScriptGameObject::play_sound(u32 internal_type, u32 max_start_time, u32 mi { CCustomMonster* monster = smart_cast(&object()); if (!monster) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSoundPlayer : cannot access class member play!"); else monster->sound().play(internal_type, max_start_time, min_start_time, max_stop_time, min_stop_time, id); @@ -211,7 +213,7 @@ int CScriptGameObject::active_sound_count(bool only_playing) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CGameObject : cannot access class member active_sound_count!"); return (-1); } @@ -229,7 +231,7 @@ bool CScriptGameObject::wounded() const const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member wounded!"); return (false); } @@ -242,7 +244,7 @@ void CScriptGameObject::wounded(bool value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member wounded!"); return; } @@ -256,7 +258,7 @@ void CScriptGameObject::set_enable_movement_collision(bool value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot set_enable_movement_collision for non CAI_Stalker objects"); return; } @@ -269,7 +271,7 @@ CSightParams CScriptGameObject::sight_params() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member sight_params!"); CSightParams result; @@ -292,7 +294,7 @@ bool CScriptGameObject::critically_wounded() CCustomMonster* custom_monster = smart_cast(&object()); if (!custom_monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member critically_wounded!"); return (false); } @@ -418,7 +420,7 @@ void CScriptGameObject::start_particles(LPCSTR pname, LPCSTR bone) if (K->LL_GetBoneVisible(play_bone)) PP->StartParticles(pname, play_bone, Fvector().set(0, 1, 0), 9999); else - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "Cant start particles, bone [%s] is not visible now", bone); } @@ -439,7 +441,7 @@ void CScriptGameObject::stop_particles(LPCSTR pname, LPCSTR bone) if (K->LL_GetBoneVisible(play_bone)) PP->StopParticles(9999, play_bone, true); else - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "Cant stop particles, bone [%s] is not visible now", bone); } diff --git a/src/xrGame/script_game_object_inventory_owner.cpp b/src/xrGame/script_game_object_inventory_owner.cpp index 26ea93fe96..f6532b5cd0 100644 --- a/src/xrGame/script_game_object_inventory_owner.cpp +++ b/src/xrGame/script_game_object_inventory_owner.cpp @@ -66,6 +66,8 @@ #include "Flashlight.h" #include "CharacterPhysicsSupport.h" +using namespace ScriptEngine; + bool CScriptGameObject::GiveInfoPortion(LPCSTR info_id) { CInventoryOwner* pInventoryOwner = smart_cast(&object()); @@ -231,7 +233,7 @@ void CScriptGameObject::ForEachInventoryItems(const luabind::functor& func CInventoryOwner* owner = smart_cast(&object()); if (!owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::ForEachInventoryItems non-CInventoryOwner object !!!"); return; } @@ -258,7 +260,7 @@ void CScriptGameObject::IterateInventory(luabind::functor functor, luabind CInventoryOwner* inventory_owner = smart_cast(&this->object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::IterateInventory non-CInventoryOwner object !!!"); return; } @@ -275,7 +277,7 @@ void CScriptGameObject::IterateRuck(luabind::functor functor, luabind::obj CInventoryOwner* inventory_owner = smart_cast(&this->object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::IterateRuck non-CInventoryOwner object !!!"); return; } @@ -292,7 +294,7 @@ void CScriptGameObject::IterateBelt(luabind::functor functor, luabind::obj CInventoryOwner* inventory_owner = smart_cast(&this->object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::IterateBelt non-CInventoryOwner object !!!"); return; } @@ -309,7 +311,7 @@ void CScriptGameObject::IterateInventoryBox(luabind::functor functor, luab CInventoryBox* inventory_box = smart_cast(&this->object()); if (!inventory_box) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::IterateInventoryBox non-CInventoryBox object !!!"); return; } @@ -330,7 +332,7 @@ void CScriptGameObject::MarkItemDropped(CScriptGameObject* item, bool flag) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::MarkItemDropped non-CInventoryOwner object !!!"); return; } @@ -338,7 +340,7 @@ void CScriptGameObject::MarkItemDropped(CScriptGameObject* item, bool flag) CInventoryItem* inventory_item = smart_cast(&item->object()); if (!inventory_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::MarkItemDropped non-CInventoryItem object !!!"); return; } @@ -351,7 +353,7 @@ bool CScriptGameObject::MarkedDropped(CScriptGameObject* item) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::MarkedDropped non-CInventoryOwner object !!!"); return (false); } @@ -359,7 +361,7 @@ bool CScriptGameObject::MarkedDropped(CScriptGameObject* item) CInventoryItem* inventory_item = smart_cast(&item->object()); if (!inventory_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::MarkedDropped non-CInventoryItem object !!!"); return (false); } @@ -372,7 +374,7 @@ void CScriptGameObject::UnloadMagazine(bool bKeepAmmo) CWeaponMagazined* weapon_magazined = smart_cast(&object()); if (!weapon_magazined) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::UnloadMagazine non-CWeaponMagazined object !!!"); return; } @@ -389,7 +391,7 @@ void CScriptGameObject::ForceUnloadMagazine(bool bKeepAmmo) CWeaponMagazined* weapon_magazined = smart_cast(&object()); if (!weapon_magazined) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::UnloadMagazine non-CWeaponMagazined object !!!"); return; } @@ -404,7 +406,7 @@ void CScriptGameObject::SetCanBeHarmed(bool state) CEntityAlive* ent = smart_cast(&object()); if (!ent) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CEntityAlive : cannot access class member set_can_be_harmed!"); return; } @@ -417,7 +419,7 @@ bool CScriptGameObject::CanBeHarmed() CEntityAlive* ent = smart_cast(&object()); if (!ent) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CEntityAlive : cannot access class member can_be_harmed!"); return false; } @@ -431,7 +433,7 @@ void CScriptGameObject::DropItem(CScriptGameObject* pItem) CInventoryItem* item = smart_cast(&pItem->object()); if (!owner || !item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::DropItem non-CInventoryOwner object !!!"); return; } @@ -483,7 +485,7 @@ void CScriptGameObject::MoveItemToRuck(CScriptGameObject* pItem) CInventoryItem* item = smart_cast(&pItem->object()); if (!owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::MoveItemToRuck non-CInventoryOwner object !!!"); return; } @@ -503,7 +505,7 @@ void CScriptGameObject::MoveItemToSlot(CScriptGameObject* pItem, u16 slot_id) CInventoryItem* item = smart_cast(&pItem->object()); if (!owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::MoveItemToSlot non-CInventoryOwner object !!!"); return; } @@ -512,7 +514,7 @@ void CScriptGameObject::MoveItemToSlot(CScriptGameObject* pItem, u16 slot_id) /* if (!owner->inventory().CanPutInSlot(item, slot_id)) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::MoveItemToSlot can't put in slot !!!"); return; } @@ -540,7 +542,7 @@ void CScriptGameObject::MoveItemToBelt(CScriptGameObject* pItem) CInventoryItem* item = smart_cast(&pItem->object()); if (!owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::MoveItemToBelt non-CInventoryOwner object !!!"); return; } @@ -560,7 +562,7 @@ void CScriptGameObject::ItemAllowTrade(CScriptGameObject* pItem) CInventoryItem* item = smart_cast(&pItem->object()); if (!owner || !item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::ItemAllowTrade non-CInventoryOwner object !!!"); return; } @@ -573,7 +575,7 @@ void CScriptGameObject::ItemDenyTrade(CScriptGameObject* pItem) CInventoryItem* item = smart_cast(&pItem->object()); if (!owner || !item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::ItemAllowTrade non-CInventoryOwner object !!!"); return; } @@ -585,7 +587,7 @@ void CScriptGameObject::TransferItem(CScriptGameObject* pItem, CScriptGameObject { if (!pItem || !pForWho) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "cannot transfer NULL item"); + ai().script_engine().script_log(eLuaMessageTypeError, "cannot transfer NULL item"); return; } @@ -593,7 +595,7 @@ void CScriptGameObject::TransferItem(CScriptGameObject* pItem, CScriptGameObject if (!pIItem) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "Cannot transfer not CInventoryItem item"); + ai().script_engine().script_log(eLuaMessageTypeError, "Cannot transfer not CInventoryItem item"); return; } @@ -613,14 +615,14 @@ void CScriptGameObject::TakeItem(CScriptGameObject* pItem) { if (!pItem) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "!CScriptGameObject::TakeItem | cannot take NULL item"); + ai().script_engine().script_log(eLuaMessageTypeError, "!CScriptGameObject::TakeItem | cannot take NULL item"); return; } CInventoryItem* pIItem = smart_cast(&pItem->object()); if (!pIItem) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "!CScriptGameObject::TakeItem | Cannot take not CInventoryItem item"); + ai().script_engine().script_log(eLuaMessageTypeError, "!CScriptGameObject::TakeItem | Cannot take not CInventoryItem item"); return; } @@ -644,7 +646,7 @@ void CScriptGameObject::TakeItem(CScriptGameObject* pItem) } else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "!CScriptGameObject::TakeItem | Unknown parent type found?"); + ai().script_engine().script_log(eLuaMessageTypeError, "!CScriptGameObject::TakeItem | Unknown parent type found?"); } return; // added return here just in case parent isn't identified as inventory owner or a box @@ -665,7 +667,7 @@ void CScriptGameObject::TransferMoney(int money, CScriptGameObject* pForWho) { if (!pForWho) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "cannot transfer money for NULL object"); + ai().script_engine().script_log(eLuaMessageTypeError, "cannot transfer money for NULL object"); return; } CInventoryOwner* pOurOwner = smart_cast(&object()); @@ -675,7 +677,7 @@ void CScriptGameObject::TransferMoney(int money, CScriptGameObject* pForWho) if (pOurOwner->get_money() - money < 0) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "Character does not have enought money"); + ai().script_engine().script_log(eLuaMessageTypeError, "Character does not have enought money"); return; } @@ -700,7 +702,7 @@ int CScriptGameObject::GetGoodwill(CScriptGameObject* pToWho) if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "GetGoodwill available only for InventoryOwner"); return 0; } @@ -713,7 +715,7 @@ void CScriptGameObject::SetGoodwill(int goodwill, CScriptGameObject* pWhoToSet) if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetGoodwill available only for InventoryOwner"); return; } @@ -726,7 +728,7 @@ void CScriptGameObject::ForceSetGoodwill(int goodwill, CScriptGameObject* pWhoTo if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ForceSetGoodwill available only for InventoryOwner"); return; } @@ -739,7 +741,7 @@ void CScriptGameObject::ChangeGoodwill(int delta_goodwill, CScriptGameObject* pW if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ChangeGoodwill available only for InventoryOwner"); return; } @@ -754,7 +756,7 @@ void CScriptGameObject::SetRelation(ALife::ERelationType relation, CScriptGameOb if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetRelation available only for InventoryOwner"); return; } @@ -763,7 +765,7 @@ void CScriptGameObject::SetRelation(ALife::ERelationType relation, CScriptGameOb VERIFY(pOthersInventoryOwner); if (!pOthersInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetRelation available only for InventoryOwner"); return; } @@ -776,7 +778,7 @@ float CScriptGameObject::GetSympathy() if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "GetSympathy available only for InventoryOwner"); return 0.0f; } @@ -789,7 +791,7 @@ void CScriptGameObject::SetSympathy(float sympathy) if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetSympathy available only for InventoryOwner"); return; } @@ -802,7 +804,7 @@ int CScriptGameObject::GetCommunityGoodwill_obj(LPCSTR community) if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "GetCommunityGoodwill available only for InventoryOwner"); return 0; } @@ -818,7 +820,7 @@ void CScriptGameObject::SetCommunityGoodwill_obj(LPCSTR community, int goodwill) if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetCommunityGoodwill available only for InventoryOwner"); return; } @@ -846,7 +848,7 @@ LPCSTR CScriptGameObject::ProfileName() CInventoryOwner* pInventoryOwner = smart_cast(&object()); if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ProfileName available only for InventoryOwner"); return NULL; } @@ -864,7 +866,7 @@ LPCSTR CScriptGameObject::CharacterName() if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CharacterName available only for InventoryOwner"); return NULL; } @@ -877,7 +879,7 @@ LPCSTR CScriptGameObject::CharacterIcon() if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CharacterIconName available only for InventoryOwner"); return NULL; } @@ -893,7 +895,7 @@ int CScriptGameObject::CharacterRank() CInventoryOwner* pInventoryOwner = smart_cast(&object()); if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CharacterRank available only for InventoryOwner and BaseMonster"); return 0; } @@ -910,7 +912,7 @@ luabind::object CScriptGameObject::CharacterDialogs() if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CharacterDialogs available only for InventoryOwner"); return table; } @@ -930,7 +932,7 @@ void CScriptGameObject::SetCharacterRank(int char_rank) if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetCharacterRank available only for InventoryOwner"); return; } @@ -943,7 +945,7 @@ void CScriptGameObject::ChangeCharacterRank(int char_rank) if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ChangeCharacterRank available only for InventoryOwner"); return; } @@ -956,7 +958,7 @@ int CScriptGameObject::CharacterReputation() if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CharacterReputation available only for InventoryOwner"); return 0; } @@ -969,7 +971,7 @@ void CScriptGameObject::ChangeCharacterReputation(int char_rep) if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "ChangeCharacterReputation available only for InventoryOwner"); return; } @@ -982,7 +984,7 @@ void CScriptGameObject::SetCharacterReputation(int char_rep) if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetCharacterReputation available only for InventoryOwner"); return; } @@ -995,7 +997,7 @@ LPCSTR CScriptGameObject::CharacterCommunity() if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CharacterCommunity available only for InventoryOwner"); return NULL; } @@ -1009,7 +1011,7 @@ void CScriptGameObject::SetCharacterCommunity(LPCSTR comm, int squad, int group) if (!pInventoryOwner || !entity) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetCharacterCommunity available only for InventoryOwner"); return; } @@ -1017,7 +1019,7 @@ void CScriptGameObject::SetCharacterCommunity(LPCSTR comm, int squad, int group) community.set(comm); if (community.index() < 0) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "SetCharacterCommunity failed for '%'", + ai().script_engine().script_log(eLuaMessageTypeError, "SetCharacterCommunity failed for '%'", comm); return; } @@ -1030,7 +1032,7 @@ LPCSTR CScriptGameObject::sound_voice_prefix() const CInventoryOwner* pInventoryOwner = smart_cast(&object()); if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "sound_voice_prefix available only for InventoryOwner"); return NULL; } @@ -1108,7 +1110,7 @@ void CScriptGameObject::RunTalkDialog(CScriptGameObject* pToWho, bool disable_br if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "RunTalkDialog applicable only for actor"); + ai().script_engine().script_log(eLuaMessageTypeError, "RunTalkDialog applicable only for actor"); return; } @@ -1152,7 +1154,7 @@ void CScriptGameObject::add_restrictions(LPCSTR out, LPCSTR in) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : cannot access class member add_restrictions!"); return; } @@ -1166,7 +1168,7 @@ void CScriptGameObject::remove_restrictions(LPCSTR out, LPCSTR in) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : cannot access class member remove_restrictions!"); return; } @@ -1180,7 +1182,7 @@ void CScriptGameObject::remove_all_restrictions() CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : cannot access class member remove_all_restrictions!"); return; } @@ -1194,7 +1196,7 @@ LPCSTR CScriptGameObject::in_restrictions() CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : cannot access class member in_restrictions!"); return (""); } @@ -1206,7 +1208,7 @@ LPCSTR CScriptGameObject::out_restrictions() CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : cannot access class member out_restrictions!"); return (""); } @@ -1218,7 +1220,7 @@ LPCSTR CScriptGameObject::base_in_restrictions() CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : cannot access class member base_in_restrictions!"); return (""); } @@ -1230,7 +1232,7 @@ LPCSTR CScriptGameObject::base_out_restrictions() CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : cannot access class member base_out_restrictions!"); return (""); } @@ -1242,7 +1244,7 @@ bool CScriptGameObject::accessible_position(const Fvector& position) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : cannot access class member accessible!"); return (false); } @@ -1254,7 +1256,7 @@ bool CScriptGameObject::accessible_vertex_id(u32 level_vertex_id) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : cannot access class member accessible!"); return (false); } @@ -1270,13 +1272,13 @@ u32 CScriptGameObject::accessible_nearest(const Fvector& position, Fvector& resu CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : cannot access class member accessible!"); return (u32(-1)); } if (monster->movement().restrictions().accessible(position)) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CRestrictedObject : you use accessible_nearest when position is already accessible!"); return (u32(-1)); } @@ -1288,7 +1290,7 @@ void CScriptGameObject::enable_attachable_item(bool value) CAttachableItem* attachable_item = smart_cast(&object()); if (!attachable_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAttachableItem : cannot access class member enable_attachable_item!"); return; } @@ -1300,7 +1302,7 @@ bool CScriptGameObject::attachable_item_enabled() const CAttachableItem* attachable_item = smart_cast(&object()); if (!attachable_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAttachableItem : cannot access class member attachable_item_enabled!"); return (false); } @@ -1312,7 +1314,7 @@ void CScriptGameObject::night_vision_allowed(bool value) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member enable_night_vision!"); return; } @@ -1324,7 +1326,7 @@ void CScriptGameObject::enable_night_vision(bool value) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member enable_night_vision!"); return; } @@ -1336,7 +1338,7 @@ bool CScriptGameObject::night_vision_enabled() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member enable_night_vision!"); return (false); } @@ -1348,7 +1350,7 @@ void CScriptGameObject::enable_torch(bool value) CTorch* torch = smart_cast(&object()); if (!torch) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CTorch : cannot access class member enable_torch!"); return; } @@ -1360,7 +1362,7 @@ bool CScriptGameObject::torch_enabled() const CTorch* torch = smart_cast(&object()); if (!torch) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CTorch : cannot access class member torch_enabled!"); return (false); } @@ -1373,7 +1375,7 @@ void CScriptGameObject::update_torch() CTorch* torch = smart_cast(&object()); if (!torch) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CTorch : cannot access class member enable_torch!"); return; } @@ -1385,7 +1387,7 @@ void CScriptGameObject::attachable_item_load_attach(LPCSTR section) CAttachableItem* attachable_item = smart_cast(&object()); if (!attachable_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAttachableItem : cannot access class member attachable_item_load_attach!"); return; } @@ -1423,7 +1425,7 @@ int CScriptGameObject::Weapon_GrenadeLauncher_Status() CWeapon* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_GrenadeLauncher_Status!"); return (false); } @@ -1435,7 +1437,7 @@ int CScriptGameObject::Weapon_Scope_Status() CWeapon* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_Scope_Status!"); return (false); } @@ -1447,7 +1449,7 @@ int CScriptGameObject::Weapon_Silencer_Status() CWeapon* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_Silencer_Status!"); return (false); } @@ -1459,7 +1461,7 @@ bool CScriptGameObject::Weapon_IsGrenadeLauncherAttached() CWeapon* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsGrenadeLauncherAttached!"); return (false); } @@ -1471,7 +1473,7 @@ bool CScriptGameObject::Weapon_IsScopeAttached() CWeapon* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!"); return (false); } @@ -1483,7 +1485,7 @@ bool CScriptGameObject::Weapon_IsSilencerAttached() CWeapon* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsSilencerAttached!"); return (false); } @@ -1500,7 +1502,7 @@ int CScriptGameObject::animation_slot() const CHudItem* hud_item = smart_cast(&object()); if (!hud_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CHudItem : cannot access class member animation_slot!"); return (u32(-1)); } @@ -1512,7 +1514,7 @@ CScriptGameObject* CScriptGameObject::active_device() const CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member active_detector!"); return (0); } @@ -1533,7 +1535,7 @@ void CScriptGameObject::show_device(bool bFast) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member show_device!"); return; } @@ -1552,7 +1554,7 @@ void CScriptGameObject::hide_device(bool bFast) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member hide_device!"); return; } @@ -1571,7 +1573,7 @@ void CScriptGameObject::force_hide_device() CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member force_hide_device!"); return; } @@ -1590,7 +1592,7 @@ CScriptGameObject* CScriptGameObject::item_in_slot(u32 slot_id) const CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member item_in_slot!"); return (0); } @@ -1626,7 +1628,7 @@ u32 CScriptGameObject::active_slot() CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member active_slot!"); return (0); } @@ -1638,7 +1640,7 @@ void CScriptGameObject::activate_slot(u32 slot_id) CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member activate_slot!"); return; } @@ -1650,7 +1652,7 @@ void CScriptGameObject::enable_movement(bool enable) CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member movement_enabled!"); return; } @@ -1663,7 +1665,7 @@ bool CScriptGameObject::movement_enabled() CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member movement_enabled!"); return (false); } @@ -1676,7 +1678,7 @@ bool CScriptGameObject::can_throw_grenades() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member can_throw_grenades!"); return (false); } @@ -1689,7 +1691,7 @@ void CScriptGameObject::can_throw_grenades(bool can_throw_grenades) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member can_throw_grenades!"); return; } @@ -1702,7 +1704,7 @@ u32 CScriptGameObject::throw_time_interval() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member throw_time_interval!"); return (0); } @@ -1715,7 +1717,7 @@ void CScriptGameObject::throw_time_interval(u32 throw_time_interval) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member throw_time_interval!"); return; } @@ -1728,7 +1730,7 @@ u32 CScriptGameObject::group_throw_time_interval() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member group_throw_time_interval!"); return (0); } @@ -1741,7 +1743,7 @@ void CScriptGameObject::group_throw_time_interval(u32 throw_time_interval) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member group_throw_time_interval!"); return; } @@ -1754,7 +1756,7 @@ void CScriptGameObject::aim_time(CScriptGameObject* weapon, u32 aim_time) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member aim_time!"); return; } @@ -1762,7 +1764,7 @@ void CScriptGameObject::aim_time(CScriptGameObject* weapon, u32 aim_time) CWeapon* weapon_ = smart_cast(&weapon->object()); if (!weapon_) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member aim_time (not a weapon passed)!"); return; } @@ -1775,7 +1777,7 @@ u32 CScriptGameObject::aim_time(CScriptGameObject* weapon) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member aim_time!"); return (u32(-1)); } @@ -1783,7 +1785,7 @@ u32 CScriptGameObject::aim_time(CScriptGameObject* weapon) CWeapon* weapon_ = smart_cast(&weapon->object()); if (!weapon_) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member aim_time (not a weapon passed)!"); return (u32(-1)); } @@ -1796,7 +1798,7 @@ void CScriptGameObject::special_danger_move(bool value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member special_danger_move!"); return; } @@ -1809,7 +1811,7 @@ bool CScriptGameObject::special_danger_move() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member special_danger_move!"); return (false); } @@ -1822,7 +1824,7 @@ void CScriptGameObject::sniper_update_rate(bool value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member sniper_update_rate!"); return; } @@ -1835,7 +1837,7 @@ bool CScriptGameObject::sniper_update_rate() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member sniper_update_rate!"); return (false); } @@ -1848,7 +1850,7 @@ void CScriptGameObject::sniper_fire_mode(bool value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member sniper_fire_mode!"); return; } @@ -1861,7 +1863,7 @@ bool CScriptGameObject::sniper_fire_mode() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member sniper_fire_mode!"); return (false); } @@ -1874,7 +1876,7 @@ void CScriptGameObject::aim_bone_id(LPCSTR bone_id) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member aim_bone_id!"); return; } @@ -1887,7 +1889,7 @@ LPCSTR CScriptGameObject::aim_bone_id() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member aim_bone_id!"); return (false); } @@ -1900,7 +1902,7 @@ void CScriptGameObject::register_in_combat() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member register_in_combat!"); return; } @@ -1913,7 +1915,7 @@ void CScriptGameObject::unregister_in_combat() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member unregister_in_combat!"); return; } @@ -1926,7 +1928,7 @@ CCoverPoint const* CScriptGameObject::find_best_cover(Fvector position_to_cover_ CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member find_best_cover!"); return (0); } @@ -1938,7 +1940,7 @@ bool CScriptGameObject::suitable_smart_cover(CScriptGameObject* object) { if (!object) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker::suitable_smart_cover null smart cover specified!"); return (false); } @@ -1946,7 +1948,7 @@ bool CScriptGameObject::suitable_smart_cover(CScriptGameObject* object) CAI_Stalker* stalker = smart_cast(&this->object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member suitable_smart_cover!"); return (false); } @@ -1954,7 +1956,7 @@ bool CScriptGameObject::suitable_smart_cover(CScriptGameObject* object) smart_cover::object const* const smart_object = smart_cast(&object->object()); if (!smart_object) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : suitable_smart_cover: passed non-smart_cover object!"); return (false); } @@ -1979,7 +1981,7 @@ void CScriptGameObject::take_items_enabled(bool const value) CAI_Stalker* const stalker = smart_cast(&this->object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member take_items_enabled!"); return; } @@ -1992,7 +1994,7 @@ bool CScriptGameObject::take_items_enabled() const CAI_Stalker* stalker = smart_cast(&this->object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member take_items_enabled!"); return (false); } @@ -2005,7 +2007,7 @@ void CScriptGameObject::SetPlayShHdRldSounds(bool val) CInventoryOwner* owner = smart_cast(&object()); if (!owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member SetPlayShHdRldSounds!"); return; } @@ -2017,7 +2019,7 @@ void CScriptGameObject::death_sound_enabled(bool const value) CAI_Stalker* const stalker = smart_cast(&this->object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member death_sound_enabled!"); return; } @@ -2030,7 +2032,7 @@ bool CScriptGameObject::death_sound_enabled() const CAI_Stalker* stalker = smart_cast(&this->object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member death_sound_enabled!"); return (false); } @@ -2108,14 +2110,14 @@ void CScriptGameObject::Weapon_AddonAttach(CScriptGameObject* item) CWeaponMagazined* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeaponMagazined : cannot access class member Weapon_AddonAttach!"); return; } CInventoryItem* pItm = item->object().cast_inventory_item(); if (!pItm) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeaponMagazined : trying to attach non-CInventoryItem!"); return; } @@ -2130,7 +2132,7 @@ void CScriptGameObject::Weapon_AddonDetach(LPCSTR item_section, bool b_spawn_ite CWeaponMagazined* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeaponMagazined : cannot access class member Weapon_AddonDetach!"); return; } @@ -2146,7 +2148,7 @@ void CScriptGameObject::Weapon_SetCurrentScope(u8 type) CWeaponMagazined* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeaponMagazined : cannot access class member Weapon_SetCurrentScope!"); return; } @@ -2159,7 +2161,7 @@ u8 CScriptGameObject::Weapon_GetCurrentScope() CWeaponMagazined* weapon = smart_cast(&object()); if (!weapon) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CWeaponMagazined : cannot access class member Weapon_GetCurrentScope!"); return 255; } @@ -2171,7 +2173,7 @@ bool CScriptGameObject::InstallUpgrade(LPCSTR upgrade) CInventoryItem* item = smart_cast(&object()); if (!item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryItem : cannot access class member InstallUpgrade!"); return false; } @@ -2187,7 +2189,7 @@ bool CScriptGameObject::HasUpgrade(LPCSTR upgrade) CInventoryItem* item = smart_cast(&object()); if (!item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryItem : cannot access class member HasUpgrade!"); return false; } @@ -2220,7 +2222,7 @@ CScriptGameObject* CScriptGameObject::ItemOnBelt(u32 item_id) const CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member item_on_belt!"); return (0); } @@ -2228,7 +2230,7 @@ CScriptGameObject* CScriptGameObject::ItemOnBelt(u32 item_id) const TIItemContainer* belt = &(inventory_owner->inventory().m_belt); if (belt->size() < item_id) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "item_on_belt: item id outside belt!"); + ai().script_engine().script_log(eLuaMessageTypeError, "item_on_belt: item id outside belt!"); return (0); } @@ -2242,7 +2244,7 @@ bool CScriptGameObject::IsOnBelt(CScriptGameObject* obj) const CInventoryItem* inventory_item = smart_cast(&(obj->object())); if (!inventory_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryItem : cannot access class member is_on_belt!"); return (0); } @@ -2250,7 +2252,7 @@ bool CScriptGameObject::IsOnBelt(CScriptGameObject* obj) const CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member is_on_belt!"); return (0); } @@ -2263,7 +2265,7 @@ u32 CScriptGameObject::BeltSize() const CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member move_to_belt!"); return (0); } @@ -2276,7 +2278,7 @@ float CScriptGameObject::GetActorMaxWeight() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorMaxWeight!"); return (false); } @@ -2288,7 +2290,7 @@ void CScriptGameObject::SetActorMaxWeight(float max_weight) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorMaxWeight!"); return; } @@ -2301,7 +2303,7 @@ float CScriptGameObject::GetActorMaxWalkWeight() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorMaxWalkWeight!"); return (false); } @@ -2313,7 +2315,7 @@ void CScriptGameObject::SetActorMaxWalkWeight(float max_walk_weight) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorMaxWalkWeight!"); return; } @@ -2328,7 +2330,7 @@ float CScriptGameObject::GetAdditionalMaxWeight() const CBackpack* pBackpack = smart_cast(&object()); if (!outfit && !pBackpack) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomOutfit : cannot access class member GetAdditionalMaxWeight!"); return (false); } @@ -2345,7 +2347,7 @@ float CScriptGameObject::GetAdditionalMaxWalkWeight() const CBackpack* pBackpack = smart_cast(&object()); if (!outfit && !pBackpack) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomOutfit : cannot access class member GetAdditionalMaxWalkWeight!"); return (false); } @@ -2361,7 +2363,7 @@ void CScriptGameObject::SetAdditionalMaxWeight(float add_max_weight) CBackpack* pBackpack = smart_cast(&object()); if (!outfit && !pBackpack) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomOutfit : cannot access class member SetAdditionalMaxWeight!"); return; } @@ -2378,7 +2380,7 @@ void CScriptGameObject::SetAdditionalMaxWalkWeight(float add_max_walk_weight) CBackpack* pBackpack = smart_cast(&object()); if (!outfit && !pBackpack) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomOutfit : cannot access class member SetAdditionalMaxWalkWeight!"); return; } @@ -2397,7 +2399,7 @@ float CScriptGameObject::GetTotalWeight() const CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member GetTotalWeight!"); return (false); } @@ -2410,7 +2412,7 @@ void CScriptGameObject::UpdateWeight() const CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member GetTotalWeightForceUpdate!"); return; } @@ -2422,7 +2424,7 @@ float CScriptGameObject::GetTotalWeightForceUpdate() const CInventoryOwner* inventory_owner = smart_cast(&object()); if (!inventory_owner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CInventoryOwner : cannot access class member GetTotalWeightForceUpdate!"); return (false); } @@ -2436,7 +2438,7 @@ float CScriptGameObject::Weight() const CInventoryItem* inventory_item = smart_cast(&object()); if (!inventory_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member Weight!"); return (false); } @@ -2448,7 +2450,7 @@ void CScriptGameObject::SetWeight(float w) CInventoryItem* inventory_item = smart_cast(&object()); if (!inventory_item) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member SetWeight!"); return; } @@ -2461,7 +2463,7 @@ float CScriptGameObject::GetActorUILuminosity() CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject::GetActorLuminosity, object is not actor"); return 0.f; } @@ -2473,7 +2475,7 @@ float CScriptGameObject::GetActorJumpSpeed() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorJumpSpeed!"); return (false); } @@ -2485,7 +2487,7 @@ void CScriptGameObject::SetActorJumpSpeed(float jump_speed) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorJumpSpeed!"); return; } @@ -2498,7 +2500,7 @@ float CScriptGameObject::GetActorSprintKoef() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorJumpSpeed!"); return (false); } @@ -2510,7 +2512,7 @@ void CScriptGameObject::SetActorSprintKoef(float sprint_koef) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorJumpSpeed!"); return; } @@ -2522,7 +2524,7 @@ float CScriptGameObject::GetActorRunCoef() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorJumpSpeed!"); return (false); } @@ -2534,7 +2536,7 @@ void CScriptGameObject::SetActorRunCoef(float run_coef) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorJumpSpeed!"); return; } @@ -2546,7 +2548,7 @@ float CScriptGameObject::GetActorRunBackCoef() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorJumpSpeed!"); return (false); } @@ -2558,7 +2560,7 @@ void CScriptGameObject::SetActorRunBackCoef(float run_back_coef) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorJumpSpeed!"); return; } @@ -2570,7 +2572,7 @@ void CScriptGameObject::SetActorCamBoxYOffset(u32 box_num, float offset) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorCamBoxYOffset!"); return; } @@ -2583,7 +2585,7 @@ float CScriptGameObject::GetActorWalkAccel() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorWalkAccel!"); return (false); } @@ -2594,7 +2596,7 @@ void CScriptGameObject::SetActorWalkAccel(float val) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorWalkAccel!"); return; } @@ -2607,7 +2609,7 @@ float CScriptGameObject::GetActorWalkBackCoef() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorWalkBackCoef!"); return (false); } @@ -2618,7 +2620,7 @@ void CScriptGameObject::SetActorWalkBackCoef(float val) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorWalkBackCoef!"); return; } @@ -2632,7 +2634,7 @@ void CScriptGameObject::SetCharacterIcon(LPCSTR iconName) if (!pInventoryOwner) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetCharacterIcon available only for InventoryOwner"); return; } @@ -2645,7 +2647,7 @@ float CScriptGameObject::GetActorLookoutCoef() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorLookoutCoef!"); return (false); } @@ -2656,7 +2658,7 @@ void CScriptGameObject::SetActorLookoutCoef(float val) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorLookoutCoef!"); return; } @@ -2669,7 +2671,7 @@ float CScriptGameObject::GetActorCrouchCoef() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorCrouchCoef!"); return (false); } @@ -2680,7 +2682,7 @@ void CScriptGameObject::SetActorCrouchCoef(float val) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorCrouchCoef!"); return; } @@ -2691,7 +2693,7 @@ float CScriptGameObject::GetActorClimbCoef() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorClimbCoef!"); return (false); } @@ -2702,7 +2704,7 @@ void CScriptGameObject::SetActorClimbCoef(float val) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorClimbCoef!"); return; } @@ -2713,7 +2715,7 @@ float CScriptGameObject::GetActorWalkStrafeCoef() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorWalkStrafeCoef!"); return (false); } @@ -2724,7 +2726,7 @@ void CScriptGameObject::SetActorWalkStrafeCoef(float val) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorWalkStrafeCoef!"); return; } @@ -2735,7 +2737,7 @@ float CScriptGameObject::GetActorRunStrafeCoef() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorRunStrafeCoef!"); return (false); } @@ -2746,7 +2748,7 @@ void CScriptGameObject::SetActorRunStrafeCoef(float val) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorRunStrafeCoef!"); return; } @@ -2757,7 +2759,7 @@ float CScriptGameObject::GetActorSprintStrafeCoef() const CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorSprintStrafeCoef!"); return (false); } @@ -2768,7 +2770,7 @@ void CScriptGameObject::SetActorSprintStrafeCoef(float val) CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member SetActorSprintStrafeCoef!"); return; } @@ -2780,7 +2782,7 @@ CScriptGameObject* CScriptGameObject::GetActorObjectLookingAt() CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorObjectLookingAt!"); return nullptr; } @@ -2796,7 +2798,7 @@ CScriptGameObject* CScriptGameObject::GetActorPersonLookingAt() CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetActorPersonLookingAt!"); return nullptr; } @@ -2816,7 +2818,7 @@ LPCSTR CScriptGameObject::GetActorDefaultActionForObject() CActor* pActor = smart_cast(&object()); if (!pActor) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CActor : cannot access class member GetDefaultActionForObject!"); return nullptr; } diff --git a/src/xrGame/script_game_object_smart_covers.cpp b/src/xrGame/script_game_object_smart_covers.cpp index b55d63482a..2d6a07672b 100644 --- a/src/xrGame/script_game_object_smart_covers.cpp +++ b/src/xrGame/script_game_object_smart_covers.cpp @@ -14,12 +14,14 @@ #include "script_callback_ex.h" #include "smart_cover.h" +using namespace ScriptEngine; + bool CScriptGameObject::use_smart_covers_only() const { CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member use_smart_covers_only!"); return (false); } @@ -32,7 +34,7 @@ void CScriptGameObject::use_smart_covers_only(bool value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member use_smart_covers_only!"); return; } @@ -45,7 +47,7 @@ void CScriptGameObject::set_smart_cover_target_selector() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_smart_cover_target_selector!"); return; } @@ -58,7 +60,7 @@ void CScriptGameObject::set_smart_cover_target_selector(luabind::functor f CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_smart_cover_target_selector!"); return; } @@ -73,7 +75,7 @@ void CScriptGameObject::set_smart_cover_target_selector(luabind::functor f CAI_Stalker* stalker = smart_cast(&this->object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_smart_cover_target_selector!"); return; } @@ -88,14 +90,14 @@ void CScriptGameObject::set_smart_cover_target_idle() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member smart_cover_setup_idle_target!"); return; } if (!stalker->g_Alive()) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : do not call smart_cover_setup_idle_target when stalker is dead!"); return; } @@ -108,14 +110,14 @@ void CScriptGameObject::set_smart_cover_target_lookout() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member smart_cover_setup_lookout_target!"); return; } if (!stalker->g_Alive()) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : do not call smart_cover_setup_lookout_target when stalker is dead!"); return; } @@ -128,14 +130,14 @@ void CScriptGameObject::set_smart_cover_target_fire() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member smart_cover_setup_fire_target!"); return; } if (!stalker->g_Alive()) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : do not call smart_cover_setup_fire_target when stalker is dead!"); return; } @@ -148,14 +150,14 @@ void CScriptGameObject::set_smart_cover_target_fire_no_lookout() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member smart_cover_setup_fire_no_lookout_target!"); return; } if (!stalker->g_Alive()) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : do not call set_smart_cover_target_fire_no_lookout when stalker is dead!"); return; } @@ -168,14 +170,14 @@ void CScriptGameObject::set_smart_cover_target_default(bool value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_smart_cover_target_default!"); return; } if (!stalker->g_Alive()) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : do not call set_smart_cover_target_default when stalker is dead!"); return; } @@ -188,7 +190,7 @@ bool CScriptGameObject::in_smart_cover() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member in_smart_cover_mode!"); return (""); } @@ -201,7 +203,7 @@ void CScriptGameObject::set_dest_smart_cover(LPCSTR cover_id) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_dest_smart_cover!"); return; } @@ -214,7 +216,7 @@ void CScriptGameObject::set_dest_smart_cover() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_dest_smart_cover!"); return; } @@ -227,7 +229,7 @@ CCoverPoint const* CScriptGameObject::get_dest_smart_cover() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member get_dest_smart_cover!"); return (0); } @@ -240,7 +242,7 @@ LPCSTR CScriptGameObject::get_dest_smart_cover_name() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member get_dest_smart_cover!"); return (0); } @@ -253,7 +255,7 @@ void CScriptGameObject::set_dest_loophole(LPCSTR loophole_id) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_dest_loophole!"); return; } @@ -266,7 +268,7 @@ void CScriptGameObject::set_dest_loophole() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_dest_loophole!"); return; } @@ -279,7 +281,7 @@ void CScriptGameObject::set_smart_cover_target(Fvector value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_smart_cover_target!"); return; } @@ -292,7 +294,7 @@ void CScriptGameObject::set_smart_cover_target() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_smart_cover_target!"); return; } @@ -305,7 +307,7 @@ void CScriptGameObject::set_smart_cover_target(CScriptGameObject* enemy_object) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member set_smart_cover_target!"); return; } @@ -318,7 +320,7 @@ bool CScriptGameObject::in_loophole_fov(LPCSTR cover_id, LPCSTR loophole_id, Fve CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member object_in_loophole_fov!"); return (false); } @@ -331,7 +333,7 @@ bool CScriptGameObject::in_current_loophole_fov(Fvector object_position) const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member object_in_loophole_fov!"); return (false); } @@ -344,7 +346,7 @@ bool CScriptGameObject::in_loophole_range(LPCSTR cover_id, LPCSTR loophole_id, F CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member object_in_loophole_range!"); return (false); } @@ -357,7 +359,7 @@ bool CScriptGameObject::in_current_loophole_range(Fvector object_position) const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member object_in_loophole_range!"); return (false); } @@ -370,7 +372,7 @@ float const CScriptGameObject::idle_min_time() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member idle_min_time!"); return (flt_max); } @@ -383,7 +385,7 @@ void CScriptGameObject::idle_min_time(float value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member idle_min_time!"); return; } @@ -396,7 +398,7 @@ float const CScriptGameObject::idle_max_time() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member idle_max_time!"); return (flt_max); } @@ -409,7 +411,7 @@ void CScriptGameObject::idle_max_time(float value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member idle_max_time!"); return; } @@ -422,7 +424,7 @@ float const CScriptGameObject::lookout_min_time() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member lookout_min_time!"); return (flt_max); } @@ -435,7 +437,7 @@ void CScriptGameObject::lookout_min_time(float value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member lookout_min_time!"); return; } @@ -448,7 +450,7 @@ float const CScriptGameObject::lookout_max_time() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member lookout_max_time!"); return (flt_max); } @@ -461,7 +463,7 @@ void CScriptGameObject::lookout_max_time(float value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member lookout_max_time!"); return; } @@ -474,7 +476,7 @@ float CScriptGameObject::apply_loophole_direction_distance() const CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member smart_cover_enter_distance!"); return (flt_max); } @@ -487,7 +489,7 @@ void CScriptGameObject::apply_loophole_direction_distance(float value) CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member smart_cover_enter_distance!"); return; } @@ -500,7 +502,7 @@ bool CScriptGameObject::movement_target_reached() CAI_Stalker* stalker = smart_cast(&object()); if (!stalker) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member movement_target_reached!"); return (false); } diff --git a/src/xrGame/script_game_object_trader.cpp b/src/xrGame/script_game_object_trader.cpp index 9d86f6895a..006a414e19 100644 --- a/src/xrGame/script_game_object_trader.cpp +++ b/src/xrGame/script_game_object_trader.cpp @@ -8,12 +8,14 @@ #include "ai/trader/ai_trader.h" #include "ai/trader/trader_animation.h" +using namespace ScriptEngine; + void CScriptGameObject::set_trader_global_anim(LPCSTR anim) { CAI_Trader* trader = smart_cast(&object()); if (!trader) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "Cannot cast sctipt game object to trader!"); return; } @@ -25,7 +27,7 @@ void CScriptGameObject::set_trader_head_anim(LPCSTR anim) CAI_Trader* trader = smart_cast(&object()); if (!trader) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "Cannot cast sctipt game object to trader!"); return; } @@ -37,7 +39,7 @@ void CScriptGameObject::set_trader_sound(LPCSTR sound, LPCSTR anim) CAI_Trader* trader = smart_cast(&object()); if (!trader) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "Cannot cast sctipt game object to trader!"); return; } @@ -49,7 +51,7 @@ void CScriptGameObject::external_sound_start(LPCSTR sound) CAI_Trader* trader = smart_cast(&object()); if (!trader) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "Cannot cast sctipt game object to trader!"); return; } @@ -61,7 +63,7 @@ void CScriptGameObject::external_sound_stop() CAI_Trader* trader = smart_cast(&object()); if (!trader) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "Cannot cast sctipt game object to trader!"); return; } diff --git a/src/xrGame/script_game_object_use.cpp b/src/xrGame/script_game_object_use.cpp index 419cf871d3..fda263718a 100644 --- a/src/xrGame/script_game_object_use.cpp +++ b/src/xrGame/script_game_object_use.cpp @@ -3,7 +3,6 @@ #include "script_game_object_impl.h" #include "UsableScriptObject.h" #include "GameObject.h" -#include "script_storage_space.h" #include "script_engine.h" #include "stalker_planner.h" #include "ai/stalker/ai_stalker.h" @@ -20,11 +19,13 @@ #include "../xrphysics/iphworld.h" #include "doors_manager.h" +using namespace ScriptEngine; + void CScriptGameObject::SetTipText(LPCSTR tip_text) { CUsableScriptObject* l_tpUseableScriptObject = smart_cast(&object()); if (!l_tpUseableScriptObject) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetTipText. Reason: the object is not usable"); else l_tpUseableScriptObject->set_tip_text(tip_text); } @@ -33,7 +34,7 @@ void CScriptGameObject::SetTipTextDefault() { CUsableScriptObject* l_tpUseableScriptObject = smart_cast(&object()); if (!l_tpUseableScriptObject) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetTipTextDefault . Reason: the object is not usable"); else l_tpUseableScriptObject->set_tip_text_default(); } @@ -42,7 +43,7 @@ void CScriptGameObject::SetNonscriptUsable(bool nonscript_usable) { CUsableScriptObject* l_tpUseableScriptObject = smart_cast(&object()); if (!l_tpUseableScriptObject) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "SetNonscriptUsable . Reason: the object is not usable"); else l_tpUseableScriptObject->set_nonscript_usable(nonscript_usable); } @@ -53,7 +54,7 @@ Fvector CScriptGameObject::GetCurrentDirection() CProjector* obj = smart_cast(&object()); if (!obj) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "Script Object : cannot access class member GetCurrentDirection!"); return Fvector().set(0.f, 0.f, 0.f); } @@ -111,14 +112,14 @@ void CScriptGameObject::Kill(CScriptGameObject* who, CEntity* l_tpEntity = smart_cast(&object()); if (!l_tpEntity) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "%s cannot access class member Kill!", + ai().script_engine().script_log(eLuaMessageTypeError, "%s cannot access class member Kill!", *object().cName()); return; } if (!l_tpEntity->AlreadyDie()) l_tpEntity->KillEntity(who ? who->object().ID() : object().ID(), bypass_actor_check ? 1 : 0); else - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "attempt to kill dead object %s", + ai().script_engine().script_log(eLuaMessageTypeError, "attempt to kill dead object %s", *object().cName()); } @@ -127,7 +128,7 @@ bool CScriptGameObject::Alive() const CEntity* entity = smart_cast(&object()); if (!entity) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CSciptEntity : cannot access class member Alive!"); return (false); } @@ -139,7 +140,7 @@ ALife::ERelationType CScriptGameObject::GetRelationType(CScriptGameObject* who) CEntityAlive* l_tpEntityAlive1 = smart_cast(&object()); if (!l_tpEntityAlive1) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "%s cannot access class member GetRelationType!", *object().cName()); return ALife::eRelationTypeDummy; } @@ -147,7 +148,7 @@ ALife::ERelationType CScriptGameObject::GetRelationType(CScriptGameObject* who) CEntityAlive* l_tpEntityAlive2 = smart_cast(&who->object()); if (!l_tpEntityAlive2) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "%s cannot apply GetRelationType method for non-alive object!", *who->object().cName()); return ALife::eRelationTypeDummy; @@ -162,7 +163,7 @@ IC T* CScriptGameObject::action_planner() CAI_Stalker* manager = smart_cast(&object()); if (!manager) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Stalker : cannot access class member action_planner!"); return (0); } @@ -179,7 +180,7 @@ void CScriptGameObject::set_enemy_callback(const luabind::functor& functor CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member set_enemy_callback!"); return; } @@ -191,7 +192,7 @@ void CScriptGameObject::set_enemy_callback(const luabind::functor& functor CCustomMonster* monster = smart_cast(&this->object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member set_enemy_callback!"); return; } @@ -203,7 +204,7 @@ void CScriptGameObject::set_enemy_callback() CCustomMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CCustomMonster : cannot access class member set_enemy_callback!"); return; } @@ -242,13 +243,13 @@ void CScriptGameObject::set_const_force(const Fvector& dir, float value, u32 tim // shell->set_LinearVel( Fvector().set(0,0,0) ); if (!physics_world()) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "set_const_force : ph_world do not exist!"); return; } if (!shell) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "set_const_force : object %s has no physics shell!", *object().cName()); return; } diff --git a/src/xrGame/script_game_object_use2.cpp b/src/xrGame/script_game_object_use2.cpp index db35433fac..53ddd6ae36 100644 --- a/src/xrGame/script_game_object_use2.cpp +++ b/src/xrGame/script_game_object_use2.cpp @@ -10,6 +10,8 @@ #include "ai/monsters/monster_home.h" #include "ai/monsters/control_animation_base.h" +using namespace ScriptEngine; + ////////////////////////////////////////////////////////////////////////// // Burer @@ -18,7 +20,7 @@ void CScriptGameObject::set_force_anti_aim(bool force) CBaseMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "object is not CBaseMonster to call set_force_anti_aim"); return; } @@ -31,7 +33,7 @@ bool CScriptGameObject::get_force_anti_aim() CBaseMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "object is not CBaseMonster to call get_force_anti_aim"); return false; } @@ -44,7 +46,7 @@ void CScriptGameObject::burer_set_force_gravi_attack(bool force) CBurer* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "object is not CBurer to call burer_set_force_gravi_attack"); return; } @@ -57,7 +59,7 @@ bool CScriptGameObject::burer_get_force_gravi_attack() CBurer* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "object is not CBurer to call burer_set_force_gravi_attack"); return false; } @@ -73,7 +75,7 @@ void CScriptGameObject::poltergeist_set_actor_ignore(bool ignore) CPoltergeist* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "object is not Poltergeist to call poltergeist_set_actor_ignore"); return; } @@ -86,7 +88,7 @@ bool CScriptGameObject::poltergeist_get_actor_ignore() CPoltergeist* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "object is not Poltergeist to call poltergeist_get_actor_ignore"); return false; } @@ -102,7 +104,7 @@ void CScriptGameObject::force_visibility_state(int state) CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Bloodsucker : cannot access class member force_visibility_state!"); return; } @@ -115,7 +117,7 @@ int CScriptGameObject::get_visibility_state() CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Bloodsucker : cannot access class member get_visibility_state!"); return CAI_Bloodsucker::full_visibility; } @@ -128,7 +130,7 @@ void CScriptGameObject::set_override_animation(pcstr anim_name) CBaseMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "object is not of CBaseMonster class!"); + ai().script_engine().script_log(eLuaMessageTypeError, "object is not of CBaseMonster class!"); return; } @@ -140,7 +142,7 @@ void CScriptGameObject::set_override_animation(u32 AnimType, u32 AnimIndex) CBaseMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "object is not of CBaseMonster class!"); + ai().script_engine().script_log(eLuaMessageTypeError, "object is not of CBaseMonster class!"); return; } @@ -152,7 +154,7 @@ void CScriptGameObject::clear_override_animation() CBaseMonster* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "object is not of CBaseMonster class!"); + ai().script_engine().script_log(eLuaMessageTypeError, "object is not of CBaseMonster class!"); return; } @@ -164,7 +166,7 @@ void CScriptGameObject::force_stand_sleep_animation(u32 index) CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Bloodsucker : cannot access class member force_stand_sleep_animation!"); return; } @@ -177,7 +179,7 @@ void CScriptGameObject::release_stand_sleep_animation() CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Bloodsucker : cannot access class member release_stand_sleep_animation!"); return; } @@ -190,7 +192,7 @@ void CScriptGameObject::set_invisible(bool val) CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Bloodsucker : cannot access class member set_invisible!"); return; } @@ -203,7 +205,7 @@ void CScriptGameObject::set_manual_invisibility(bool val) CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Bloodsucker : cannot access class member set_manual_invisible!"); return; } @@ -215,7 +217,7 @@ void CScriptGameObject::bloodsucker_drag_jump(CScriptGameObject* e, LPCSTR e_str CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot process drag, anim, jump for CAI_Bloodsucker!"); return; } @@ -233,7 +235,7 @@ void CScriptGameObject::set_enemy(CScriptGameObject* e) CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Bloodsucker : cannot access class member set_enemy!"); return; } @@ -247,7 +249,7 @@ void CScriptGameObject::set_vis_state(float val) CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Bloodsucker : cannot access class member set_vis_state!"); return; } @@ -266,7 +268,7 @@ void CScriptGameObject::off_collision(bool val) CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Bloodsucker : cannot access class member set_vis_state!"); return; } @@ -278,7 +280,7 @@ void CScriptGameObject::set_alien_control(bool val) CAI_Bloodsucker* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CAI_Bloodsucker : cannot access class member alien_control_activate!"); return; } @@ -306,7 +308,7 @@ CScriptSoundInfo CScriptGameObject::GetSoundInfo() } else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member GetSoundInfo!"); } return (ret_val); @@ -328,7 +330,7 @@ CScriptMonsterHitInfo CScriptGameObject::GetMonsterHitInfo() } else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CScriptGameObject : cannot access class member GetMonsterHitInfo!"); } return (ret_val); @@ -365,7 +367,7 @@ bool CScriptGameObject::fake_death_fall_down() CZombie* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CZombie : cannot access class member fake_death_fall_down!"); return false; } @@ -378,7 +380,7 @@ void CScriptGameObject::fake_death_stand_up() CZombie* monster = smart_cast(&object()); if (!monster) { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(eLuaMessageTypeError, "CZombie : cannot access class member fake_death_fall_down!"); return; } diff --git a/src/xrGame/script_property_evaluator_wrapper.cpp b/src/xrGame/script_property_evaluator_wrapper.cpp index ca2a032690..30cacafd04 100644 --- a/src/xrGame/script_property_evaluator_wrapper.cpp +++ b/src/xrGame/script_property_evaluator_wrapper.cpp @@ -41,7 +41,7 @@ bool CScriptPropertyEvaluatorWrapper::evaluate() catch (...) { //Alundaio: m_evaluator_name - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "SCRIPT RUNTIME ERROR : evaluator [%s] returns value with not a bool type!", m_evaluator_name); } diff --git a/src/xrGame/script_sound.cpp b/src/xrGame/script_sound.cpp index c44ad35ad1..2083369249 100644 --- a/src/xrGame/script_sound.cpp +++ b/src/xrGame/script_sound.cpp @@ -22,7 +22,7 @@ CScriptSound::CScriptSound(LPCSTR caSoundName, ESoundTypes sound_type) m_sound.create(caSoundName, st_Effect, sound_type); else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "File not found \"%s\"!", l_caFileName); + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "File not found \"%s\"!", l_caFileName); m_sound.create("$no_sound.ogg", st_Effect, sound_type); } } @@ -44,7 +44,7 @@ Fvector CScriptSound::GetPosition() const return (l_tpSoundParams->position); else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "Sound was not launched, can't get position!"); return (Fvector().set(0, 0, 0)); } diff --git a/src/xrGame/script_sound_action.cpp b/src/xrGame/script_sound_action.cpp index 901e55634d..d8cde2d3ba 100644 --- a/src/xrGame/script_sound_action.cpp +++ b/src/xrGame/script_sound_action.cpp @@ -28,7 +28,7 @@ void CScriptSoundAction::SetSound(LPCSTR caSoundToPlay) } else { - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "File not found \"%s\"!", l_caFileName); + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "File not found \"%s\"!", l_caFileName); m_bStartedToPlay = true; m_bCompleted = true; } diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index c53587fd05..969cea88d3 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -360,6 +360,7 @@ + @@ -2021,6 +2022,7 @@ pch_script.h $(IntDir)$(ProjectName)_script.pch + pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index 672e4983ac..e921f26bb3 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -7389,6 +7389,9 @@ UI\Cursor + + AI\AScript\ScriptStorage + @@ -11081,6 +11084,9 @@ UI\Cursor + + AI\AScript\ScriptStorage + diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 14aa411af0..20e98997b0 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -19,6 +19,8 @@ #include #include +using namespace ScriptEngine; + #if !defined(DEBUG) && defined(USE_LUAJIT_ONE) # include "opt.lua.h" # include "opt_inline.lua.h" @@ -692,11 +694,11 @@ luabind::object CScriptEngine::name_space(LPCSTR namespace_name) } } -int CScriptEngine::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker) +int CScriptEngine::vscript_log(ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker) { #ifndef NO_XRGAME_SCRIPT_ENGINE # ifdef DEBUG - if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) + if (!psAI_Flags.test(aiLua) && (tLuaMessageType != eLuaMessageTypeError)) return(0); # endif //-DEBUG #endif //!NO_XRGAME_SCRIPT_ENGINE @@ -705,7 +707,7 @@ int CScriptEngine::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, L //return (0); //#else //PRINT_CALL_STACK # ifndef NO_XRGAME_SCRIPT_ENGINE - //AVO: allow LUA debug prints (i.e.: ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!");) + //AVO: allow LUA debug prints (i.e.: ai().script_engine().script_log(eLuaMessageTypeError, "CWeapon : cannot access class member Weapon_IsScopeAttached!");) # ifndef DEBUG if (!strstr(Core.Params, "-dbg")) @@ -713,11 +715,11 @@ int CScriptEngine::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, L # endif //!DEBUG # ifndef LUA_DEBUG_PRINT # ifdef DEBUG - if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) + if (!psAI_Flags.test(aiLua) && (tLuaMessageType != eLuaMessageTypeError)) return(0); # endif //-DEBUG # else //!LUA_DEBUG_PRINT - if (!psAI_Flags.test(aiLua) && (tLuaMessageType != ScriptStorage::eLuaMessageTypeError)) + if (!psAI_Flags.test(aiLua) && (tLuaMessageType != eLuaMessageTypeError)) return(0); # endif //-LUA_DEBUG_PRINT #endif //-NO_XRGAME_SCRIPT_ENGINE @@ -727,49 +729,49 @@ int CScriptEngine::vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, L string4096 S2; switch (tLuaMessageType) { - case ScriptStorage::eLuaMessageTypeInfo: + case eLuaMessageTypeInfo: { S = "* [LUA] "; SS = "[INFO] "; break; } - case ScriptStorage::eLuaMessageTypeError: + case eLuaMessageTypeError: { S = "! [LUA] "; SS = "[ERROR] "; break; } - case ScriptStorage::eLuaMessageTypeMessage: + case eLuaMessageTypeMessage: { S = "~ [LUA] "; SS = "[MESSAGE] "; break; } - case ScriptStorage::eLuaMessageTypeHookCall: + case eLuaMessageTypeHookCall: { S = "[LUA][HOOK_CALL] "; SS = "[CALL] "; break; } - case ScriptStorage::eLuaMessageTypeHookReturn: + case eLuaMessageTypeHookReturn: { S = "[LUA][HOOK_RETURN] "; SS = "[RETURN] "; break; } - case ScriptStorage::eLuaMessageTypeHookLine: + case eLuaMessageTypeHookLine: { S = "[LUA][HOOK_LINE] "; SS = "[LINE] "; break; } - case ScriptStorage::eLuaMessageTypeHookCount: + case eLuaMessageTypeHookCount: { S = "[LUA][HOOK_COUNT] "; SS = "[COUNT] "; break; } - case ScriptStorage::eLuaMessageTypeHookTailReturn: + case eLuaMessageTypeHookTailReturn: { S = "[LUA][HOOK_TAIL_RETURN] "; SS = "[TAIL_RETURN] "; @@ -815,22 +817,22 @@ void CScriptEngine::print_stack() lua_getinfo(L, "nSlu", &l_tDebugInfo); if (!l_tDebugInfo.name) { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, + script_log_no_stack(eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); + //script_log(eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); } else { if (!xr_strcmp(l_tDebugInfo.what, "C")) { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); + script_log_no_stack(eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); + //script_log(eLuaMessageTypeError, "%2d : [C ] %s", i, l_tDebugInfo.name); } else { - script_log_no_stack(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, + script_log_no_stack(eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); - //script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); + //script_log(eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); } } } @@ -839,7 +841,7 @@ void CScriptEngine::print_stack() //#endif //-PRINT_CALL_STACK //AVO: added to stop duplicate stack output prints in log -int __cdecl CScriptEngine::script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) +int __cdecl CScriptEngine::script_log_no_stack(ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) { va_list marker; va_start(marker, caFormat); @@ -850,7 +852,7 @@ int __cdecl CScriptEngine::script_log_no_stack(ScriptStorage::ELuaMessageType tL //-AVO -int __cdecl CScriptEngine::script_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) +int __cdecl CScriptEngine::script_log(ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...) { va_list marker; va_start(marker, caFormat); @@ -861,7 +863,7 @@ int __cdecl CScriptEngine::script_log(ScriptStorage::ELuaMessageType tLuaMessage if (!reenterability) { reenterability = true; - if (tLuaMessageType == ScriptStorage::eLuaMessageTypeError) { + if (tLuaMessageType == eLuaMessageTypeError) { ai().script_engine().print_stack(); } else { @@ -914,8 +916,8 @@ bool CScriptEngine::print_output(lua_State* L, LPCSTR caScriptFileName, int iEro else { if (!iErorCode) - script_log(ScriptStorage::eLuaMessageTypeInfo, "Output from %s", caScriptFileName); - script_log(iErorCode ? ScriptStorage::eLuaMessageTypeError : ScriptStorage::eLuaMessageTypeMessage, "%s", S); + script_log(eLuaMessageTypeInfo, "Output from %s", caScriptFileName); + script_log(iErorCode ? eLuaMessageTypeError : eLuaMessageTypeMessage, "%s", S); #ifdef USE_DEBUGGER # ifndef USE_LUA_STUDIO if (ai().script_engine().debugger() && ai().script_engine().debugger()->Active()) { @@ -934,32 +936,32 @@ void CScriptEngine::print_error(lua_State* L, int iErrorCode) { case LUA_ERRRUN: { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT RUNTIME ERROR"); + script_log(eLuaMessageTypeError, "SCRIPT RUNTIME ERROR"); break; } case LUA_ERRMEM: { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (memory allocation)"); + script_log(eLuaMessageTypeError, "SCRIPT ERROR (memory allocation)"); break; } case LUA_ERRERR: { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (while running the error handler function)"); + script_log(eLuaMessageTypeError, "SCRIPT ERROR (while running the error handler function)"); break; } case LUA_ERRFILE: { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT ERROR (while running file)"); + script_log(eLuaMessageTypeError, "SCRIPT ERROR (while running file)"); break; } case LUA_ERRSYNTAX: { - script_log(ScriptStorage::eLuaMessageTypeError, "SCRIPT SYNTAX ERROR"); + script_log(eLuaMessageTypeError, "SCRIPT SYNTAX ERROR"); break; } case LUA_YIELD: { - script_log(ScriptStorage::eLuaMessageTypeInfo, "Thread is yielded"); + script_log(eLuaMessageTypeInfo, "Thread is yielded"); break; } default: NODEFAULT; diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index 05a26df7b6..a859c18650 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -8,7 +8,7 @@ #pragma once -#include "script_storage_space.h" +#include "script_engine_space.h" #include "script_export_space.h" #include "script_space_forward.h" #include "associative_vector.h" @@ -48,14 +48,13 @@ #endif //-!DEBUG //-AVO -using namespace ScriptStorage; +using namespace ScriptEngine; class CScriptProcess; class CScriptThread; struct lua_State; struct lua_Debug; -typedef ScriptEngine::EScriptProcessors EScriptProcessors; typedef associative_vector CScriptProcessStorage; #ifdef USE_DEBUGGER @@ -168,7 +167,7 @@ class CScriptEngine //#ifdef PRINT_CALL_STACK void print_stack(); //AVO: added to stop duplicate stack output prints in log - static int __cdecl script_log_no_stack(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...); + static int __cdecl script_log_no_stack(ELuaMessageType tLuaMessageType, LPCSTR caFormat, ...); //-AVO //#endif //-PRINT_CALL_STACK @@ -188,7 +187,7 @@ class CScriptEngine protected: void reinit(); - static int vscript_log(ScriptStorage::ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker); + static int vscript_log(ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker); DECLARE_SCRIPT_REGISTER_FUNCTION }; diff --git a/src/xrServerEntities/script_engine_space.h b/src/xrServerEntities/script_engine_space.h index 78f55bd9ab..15c4617c97 100644 --- a/src/xrServerEntities/script_engine_space.h +++ b/src/xrServerEntities/script_engine_space.h @@ -10,6 +10,18 @@ namespace ScriptEngine { + enum ELuaMessageType + { + eLuaMessageTypeInfo = u32(0), + eLuaMessageTypeError, + eLuaMessageTypeMessage, + eLuaMessageTypeHookCall, + eLuaMessageTypeHookReturn, + eLuaMessageTypeHookLine, + eLuaMessageTypeHookCount, + eLuaMessageTypeHookTailReturn = u32(-1), + }; + enum EScriptProcessors { eScriptProcessorLevel = u32(0), diff --git a/src/xrServerEntities/script_process.cpp b/src/xrServerEntities/script_process.cpp index f38dbfd294..3459e66e27 100644 --- a/src/xrServerEntities/script_process.cpp +++ b/src/xrServerEntities/script_process.cpp @@ -86,7 +86,7 @@ void CScriptProcess::update() if (g_ca_stdout[0]) { fputc(0,stderr); - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeInfo, "%s", g_ca_stdout); + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeInfo, "%s", g_ca_stdout); fflush(stderr); } diff --git a/src/xrServerEntities/script_stack_tracker.cpp b/src/xrServerEntities/script_stack_tracker.cpp index b7b1eaf7c9..46da3cb340 100644 --- a/src/xrServerEntities/script_stack_tracker.cpp +++ b/src/xrServerEntities/script_stack_tracker.cpp @@ -8,7 +8,6 @@ #include "pch_script.h" #include "script_stack_tracker.h" -#include "script_storage_space.h" #include "ai_space.h" #include "script_engine.h" @@ -79,13 +78,13 @@ void CScriptStackTracker::print_stack(lua_State* L) { lua_Debug l_tDebugInfo = *m_stack[j]; if (!l_tDebugInfo.name) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", k, + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", k, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); else if (!xr_strcmp(l_tDebugInfo.what, "C")) - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [C ] %s", k, + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "%2d : [C ] %s", k, l_tDebugInfo.name); else - ai().script_engine().script_log(ScriptStorage::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", k, + ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", k, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name); } diff --git a/src/xrServerEntities/script_storage_space.h b/src/xrServerEntities/script_storage_space.h deleted file mode 100644 index 9b0fcf7023..0000000000 --- a/src/xrServerEntities/script_storage_space.h +++ /dev/null @@ -1,24 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_storage_space.h -// Created : 01.04.2004 -// Modified : 01.04.2004 -// Author : Dmitriy Iassenev -// Description : XRay Script Storage space -//////////////////////////////////////////////////////////////////////////// - -#pragma once - -namespace ScriptStorage -{ - enum ELuaMessageType - { - eLuaMessageTypeInfo = u32(0), - eLuaMessageTypeError, - eLuaMessageTypeMessage, - eLuaMessageTypeHookCall, - eLuaMessageTypeHookReturn, - eLuaMessageTypeHookLine, - eLuaMessageTypeHookCount, - eLuaMessageTypeHookTailReturn = u32(-1), - }; -} From 826daa7ac2cb4ae59ac488639b3db5b143839539 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 23 May 2025 20:10:16 +0100 Subject: [PATCH 31/76] Reimplement `CScriptStorage` as basic persistent Lua storage --- gamedata/scripts/init.lua | 9 +++---- gamedata/scripts/scam/classes.lua | 6 ++--- src/xrGame/vs2022/xrGame.vcxproj | 1 + src/xrGame/vs2022/xrGame.vcxproj.filters | 3 +++ src/xrServerEntities/script_engine.cpp | 13 ++++++---- src/xrServerEntities/script_storage.cpp | 24 +++++++++++++++++++ src/xrServerEntities/script_storage.h | 23 ++++++++++++++++++ .../script_storage_script.cpp | 20 ++++++++++++++++ 8 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 src/xrServerEntities/script_storage.cpp create mode 100644 src/xrServerEntities/script_storage.h create mode 100644 src/xrServerEntities/script_storage_script.cpp diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index c236604d17..4046117b6c 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -133,8 +133,9 @@ end local loaders = package.loaders local io_miss = {} local function io_loader(name) - if io_miss[name] then - return io_miss[name] + local io_miss = _SCRIPT_STORAGE:get("io_loader", name) + if io_miss then + return io_miss end local err = "" @@ -156,8 +157,8 @@ local function io_loader(name) end end - io_miss[name] = err - return io_miss[name] + _SCRIPT_STORAGE:set("io_loader", name, err) + return err end -- Replace the loader list with the preloader plus our memoized IO loader diff --git a/gamedata/scripts/scam/classes.lua b/gamedata/scripts/scam/classes.lua index 032a463473..6427fcae7c 100644 --- a/gamedata/scripts/scam/classes.lua +++ b/gamedata/scripts/scam/classes.lua @@ -12,12 +12,10 @@ if not ini:line_exist("common", "class_registrators") then end -local fac = get_object_factory() - local regs = ini:r_string("common", "class_registrators", "") for reg_path in regs:gmatch("[^,]+") do local reg = function_object(reg_path) - reg(fac) + reg(_OBJECT_FACTORY) end -fac:register_script() +_OBJECT_FACTORY:register_script() diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index 969cea88d3..d9830106f2 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -2023,6 +2023,7 @@ $(IntDir)$(ProjectName)_script.pch + pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index e921f26bb3..a3203bac36 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -11087,6 +11087,9 @@ AI\AScript\ScriptStorage + + AI\AScript\ScriptEngine + diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 20e98997b0..ef5f491390 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -8,6 +8,7 @@ #include "pch_script.h" #include "script_engine.h" +#include "script_storage.h" #include "ai_space.h" #include "object_factory.h" #include "script_process.h" @@ -339,9 +340,9 @@ CScriptEngine::~CScriptEngine() remove_script_process(m_script_processes.begin()->first); } -static int get_object_factory(lua_State* L) +static int get_script_storage(lua_State* L) { - luabind::object(L, const_cast(&object_factory())).pushvalue(); + luabind::object(L, const_cast(&ScriptStorage())).pushvalue(); return (1); } @@ -389,8 +390,12 @@ void CScriptEngine::init() #endif // #ifndef USE_LUA_STUDIO // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); - lua_pushcfunction(lua(), get_object_factory); - lua_setglobal(lua(), "get_object_factory"); + luabind::object(lua(), const_cast(&object_factory())).pushvalue(); + lua_setglobal(lua(), "_OBJECT_FACTORY"); + + CScriptStorage::script_register(lua()); + luabind::object(lua(), const_cast(&ScriptStorage())).pushvalue(); + lua_setglobal(lua(), "_SCRIPT_STORAGE"); string_path path; if (luaL_dofile(lua(), FS.update_path(path, "$game_scripts$", "init.lua"))) diff --git a/src/xrServerEntities/script_storage.cpp b/src/xrServerEntities/script_storage.cpp new file mode 100644 index 0000000000..89addee1ff --- /dev/null +++ b/src/xrServerEntities/script_storage.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" +#include "script_storage.h" + +LPCSTR CScriptStorage::get(LPCSTR name_space, LPCSTR key) +{ + auto cache = &m_cache[name_space]; + if (cache->find(key) == cache->end()) + return NULL; + + return cache->at(std::string(key)).c_str(); +} + +void CScriptStorage::set(LPCSTR name_space, LPCSTR key, LPCSTR val) +{ + auto cache = &m_cache[name_space]; + if (key && val) + cache->insert(std::pair(std::string(key), std::string(val))); +} + +CScriptStorage g_script_storage; +CScriptStorage& ScriptStorage() +{ + return g_script_storage; +} \ No newline at end of file diff --git a/src/xrServerEntities/script_storage.h b/src/xrServerEntities/script_storage.h new file mode 100644 index 0000000000..6fd93f8be6 --- /dev/null +++ b/src/xrServerEntities/script_storage.h @@ -0,0 +1,23 @@ +#pragma once + +#include "script_export_space.h" +#include +#include + +// Persistent storage for the Lua environment +class CScriptStorage +{ +private: + std::map> m_cache; +public: + LPCSTR get(LPCSTR name_space, LPCSTR key); + void set(LPCSTR name_space, LPCSTR key, LPCSTR value); + +DECLARE_SCRIPT_REGISTER_FUNCTION +}; + +CScriptStorage& ScriptStorage(); + +add_to_type_list(CScriptStorage) +#undef script_type_list +#define script_type_list save_type_list(CScriptStorage) diff --git a/src/xrServerEntities/script_storage_script.cpp b/src/xrServerEntities/script_storage_script.cpp new file mode 100644 index 0000000000..b30ead0423 --- /dev/null +++ b/src/xrServerEntities/script_storage_script.cpp @@ -0,0 +1,20 @@ +#include "stdafx.h" + +#include "luabind/luabind.hpp" +#include "script_storage.h" +#include "ai_space.h" +#include "script_engine.h" +#include "object_item_script.h" + +using namespace luabind; + +#pragma optimize("s",on) +void CScriptStorage::script_register(lua_State* L) +{ + module(L) + [ + class_("CScriptStorage") + .def("get", &CScriptStorage::get) + .def("set", &CScriptStorage::set) + ]; +} \ No newline at end of file From 9c7cd2bd8cc87400c53915f84c52db8e6c935a19 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sat, 24 May 2025 18:36:13 +0100 Subject: [PATCH 32/76] Rescan `$game_scripts$` recursively before booting script engine --- src/xrServerEntities/script_engine.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index ef5f491390..7ea46a2ce1 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -390,6 +390,10 @@ void CScriptEngine::init() #endif // #ifndef USE_LUA_STUDIO // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); + // Force the FS to recursively enumerate the scripts folder + FS_Path* P = FS.get_path("$game_scripts$"); + P->m_Flags.set(FS_Path::flNeedRescan, TRUE); + FS.rescan_pathes(); luabind::object(lua(), const_cast(&object_factory())).pushvalue(); lua_setglobal(lua(), "_OBJECT_FACTORY"); From 1bb831420bd2e6808b41762ee133021d73f2199e Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sat, 24 May 2025 18:36:46 +0100 Subject: [PATCH 33/76] Print engine-level load message for `init.lua`, document globals --- src/xrServerEntities/script_engine.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 7ea46a2ce1..b1d80426d2 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -394,13 +394,18 @@ void CScriptEngine::init() FS_Path* P = FS.get_path("$game_scripts$"); P->m_Flags.set(FS_Path::flNeedRescan, TRUE); FS.rescan_pathes(); + + // Emplace the object factory luabind::object(lua(), const_cast(&object_factory())).pushvalue(); lua_setglobal(lua(), "_OBJECT_FACTORY"); + // Emplace script storage CScriptStorage::script_register(lua()); luabind::object(lua(), const_cast(&ScriptStorage())).pushvalue(); lua_setglobal(lua(), "_SCRIPT_STORAGE"); + // Hand control to Lua + Msg("* engine: loading init.lua"); string_path path; if (luaL_dofile(lua(), FS.update_path(path, "$game_scripts$", "init.lua"))) { From 00b9af3be7ee38cb41979d16a2bd71efed156b6c Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 25 May 2025 06:57:51 +0100 Subject: [PATCH 34/76] Consistent logging style for `init.lua` load --- src/xrServerEntities/script_engine.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index b1d80426d2..4c1c59d87f 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -411,7 +411,7 @@ void CScriptEngine::init() { LPCSTR e = lua_tostring(lua(), -1); lua_pop(lua(), 1); - FATAL((std::string("Failed to load init.lua:\n") + e).c_str()); + FATAL((std::string("! engine: error loading init.lua:\n") + e).c_str()); } m_stack_level = lua_gettop(lua()); @@ -591,12 +591,12 @@ int CScriptEngine::compile_buffer(lua_State* L, std::string caString, LPCSTR caS luabind::functor compiler; if (functor("_COMPILER", compiler)) { - luabind::object result = compiler(caString.c_str(), caScriptName, caNameSpaceName); + luabind::object result = compiler(caString.c_str(), caNameSpaceName, caScriptName); result.pushvalue(); return 0; } - Msg("scam_compiler not available, loading as raw Lua..."); + Msg("* engine: loading %s", caNameSpaceName); return luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); } From e93110d876265b0e0ff4dda8294828590a24a4a4 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sat, 31 May 2025 20:19:21 +0100 Subject: [PATCH 35/76] Use X-Ray FS to load `init.lua` --- src/xrServerEntities/script_engine.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 4c1c59d87f..48946d1aee 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -404,10 +404,23 @@ void CScriptEngine::init() luabind::object(lua(), const_cast(&ScriptStorage())).pushvalue(); lua_setglobal(lua(), "_SCRIPT_STORAGE"); - // Hand control to Lua Msg("* engine: loading init.lua"); + + // Fetch init.lua's path from the FS string_path path; - if (luaL_dofile(lua(), FS.update_path(path, "$game_scripts$", "init.lua"))) + FS.update_path(path, "$game_scripts$", "init.lua"); + if (!path) + FATAL("* engine: invalid init.lua path"); + + // Open a file handle and read it into a string + auto file = FS.r_open(path); + if (!file) + FATAL("* engine: failed to load init.lua"); + std::string src((char*)file->pointer(), file->length()); + FS.r_close(file); + + // Run the resulting source + if (luaL_dostring(lua(), src.c_str())) { LPCSTR e = lua_tostring(lua(), -1); lua_pop(lua(), 1); From 27bb3ffb9f493184fe8d00728eef002154821e28 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 1 Jun 2025 04:00:32 +0100 Subject: [PATCH 36/76] Implement `load_file` to work around broken Lua `IReader` string behaviour --- src/xrServerEntities/script_engine.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 48946d1aee..d0d2a4ac0a 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -340,9 +340,22 @@ CScriptEngine::~CScriptEngine() remove_script_process(m_script_processes.begin()->first); } -static int get_script_storage(lua_State* L) +// Low level path -> string content loader to work around intractable Lua IReader::r_stringZ behaviour +static int load_file(lua_State* L) { - luabind::object(L, const_cast(&ScriptStorage())).pushvalue(); + LPCSTR path = lua_tostring(L, 1); + if (!path) + FATAL("Invalid path"); + + IReader* file = FS.r_open(path); + + if (!file) + FATAL("Invalid file"); + + lua_pushlstring(L, (LPCSTR)file->pointer(), file->length()); + + FS.r_close(file); + return (1); } @@ -404,6 +417,9 @@ void CScriptEngine::init() luabind::object(lua(), const_cast(&ScriptStorage())).pushvalue(); lua_setglobal(lua(), "_SCRIPT_STORAGE"); + lua_pushcfunction(lua(), load_file); + lua_setglobal(lua(), "_LOAD_FILE"); + Msg("* engine: loading init.lua"); // Fetch init.lua's path from the FS From cb6caae0acce462d22538fc0732bef809f181ea7 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 3 Jun 2025 21:44:25 +0100 Subject: [PATCH 37/76] Reinstate `unlocalizers.lua` --- gamedata/scripts/unlocalizers.lua | 65 +++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 gamedata/scripts/unlocalizers.lua diff --git a/gamedata/scripts/unlocalizers.lua b/gamedata/scripts/unlocalizers.lua new file mode 100644 index 0000000000..88a3e1ee7d --- /dev/null +++ b/gamedata/scripts/unlocalizers.lua @@ -0,0 +1,65 @@ +local unlocalizers = {} + +local function update() + local fs = getFS() + local list = fs:file_list_open( + "$game_config$", + "unlocalizers\\", + bit_or( + FS.FS_ListFiles, + FS.FS_RootOnly + ) + ) + + if not list then + return + end + + local count = list:Size() or 0 + if count == 0 then + return + end + + for i=1,count do + local id = list:GetAt(i - 1) + + if #id < 4 then + goto next_filename + end + + if string.sub(id, #id - 3, #id) ~= ".ltx" then + goto next_filename + end + + print("opening file:", id) + + local config = ini_file("unlocalizers\\" .. id) + config:section_for_each(function(section) + local name = string.lower(section) + local count = config:line_count(name) + for j=0,count-1 do + local res, sec = config:r_line(name, j) + if not res then + goto next_line + end + unlocalizers[name] = unlocalizers[name] or {} + table.insert(unlocalizers[name], sec) + + ::next_line:: + end + end) + + ::next_filename:: + end +end + +local function get(k) + return unlocalizers[k] +end + +update() + +return { + update = update, + get = get +} From f255ea25170d537aede53267f279636fe0ad0d50 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 3 Jun 2025 21:57:57 +0100 Subject: [PATCH 38/76] Integrate latest `wua` --- gamedata/scripts/macro/wua/compile.lua | 125 ++++++++++++++ gamedata/scripts/macro/wua/init.lua | 200 +--------------------- gamedata/scripts/macro/wua/unlocalize.lua | 117 +++++++++++++ gamedata/scripts/unlocalizers.lua | 65 ------- 4 files changed, 251 insertions(+), 256 deletions(-) create mode 100644 gamedata/scripts/macro/wua/compile.lua create mode 100644 gamedata/scripts/macro/wua/unlocalize.lua delete mode 100644 gamedata/scripts/unlocalizers.lua diff --git a/gamedata/scripts/macro/wua/compile.lua b/gamedata/scripts/macro/wua/compile.lua new file mode 100644 index 0000000000..53fc4f73ef --- /dev/null +++ b/gamedata/scripts/macro/wua/compile.lua @@ -0,0 +1,125 @@ +--local remap = require("moved").remap + +local G = setmetatable( + {}, + { + __index = function(self, key) + --[[ + -- Fetch the remap for this key + local redir = remap[key] + + -- If we have a redirection... + if redir ~= nil then + -- Check the no-overwrite flag; + -- If set and the key exists in _G, return its value + if redir.if_not_overwritten then + local gv = _G[key] + if gv then + return gv + end + + local res, out = pcall(require, key) + if res then + return out + end + end + + -- Otherwise, fetch the redirected key + if type(redir.to) ~= "string" then + error( + "Redirection from " .. key + .. " has invalid 'to' field: " .. redir.to + ) + end + + -- And recurse with it + local rv = self[redir.to] + + -- If if exists, return it + if rv ~= nil then + return rv + end + end + --]] + + -- Otherwise, check the global key's value and return if valid + local gv = _G[key] + if gv ~= nil then + return gv + end + + -- Otherwise, try to auto-load the key as a script + local res, out = pcall(require, key) + if res then + return out + end + end, + __newindex = _G + } +) + +local function handle_error(msg, namespace_name) + return function(err) + package.loaded[namespace_name] = nil + err = "! " .. _PACKAGE .. ": " + .. msg .. ":\n\n" + .. debug.traceback(err .. "\n", 2) + .. "\n" + print(err) + error(err) + end +end + +local function compile(src, namespace_name, script_name) + local is_g = namespace_name == "_G" + + local mt = { + __index = G + } + + if is_g then + mt.__newindex = G + end + + local env = setmetatable({ _G = G }, mt) + + if not is_g then + env._M = env + if namespace_name then + env._PACKAGE = namespace_name + env._FILE = script_name + env._COMPILER = _COMPILER + env.loadstring = _COMPILER + env[namespace_name] = env + end + end + + if namespace_name then + src = "local script_name = function() return _PACKAGE end " .. src + end + + src = "local this = _M " .. src + + local mod, err = loadstring(src, namespace_name) + if not mod then + handle_error("error loading " .. namespace_name, namespace_name)(err) + end + + local mac = setfenv(mod, env) + + return function() + package.loaded[namespace_name] = env + xpcall( + mac, + handle_error( + "error evaluating " .. namespace_name, + namespace_name + ) + ) + return package.loaded[namespace_name] + end +end + +return { + compile = compile +} diff --git a/gamedata/scripts/macro/wua/init.lua b/gamedata/scripts/macro/wua/init.lua index 912ffc499b..d9407b1942 100644 --- a/gamedata/scripts/macro/wua/init.lua +++ b/gamedata/scripts/macro/wua/init.lua @@ -1,199 +1,17 @@ -local unlocalizers = require("unlocalizers") -local macro = require("macro") +local unlocalize = require("macro/wua/unlocalize").unlocalize +local compile = require("macro/wua/compile").compile -local function string_trim(s, v) - if v == nil then - v = " \t\n\r\f\v" - end - local pattern = string.format("^[%s]*([^%s]*)[%s]*$", v, v, v) - print("pattern:", pattern) - return string.match(s, pattern) -end - -local function contains(lst, a) - for _,b in ipairs(lst) do - if a == b then - return true - end - end - - return false -end - -local function unlocal_regex(unlocals, s) - local pattern = [[^(local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(%(.*)$]] - local _, _, c, d, e, f, g = string.match(s, pattern) - - if e and contains(unlocals, e) then - print("[unlocal_regex] found variable " .. e .. " to unlocal") - print("s", s) - s = c .. d .. e .. f .. g - print("s'", s) - return s - end - - return nil -end - -local function unlocalize(src, namespace_name) - if not namespace_name then - return src - end - - local unlocalizer = unlocalizers.get(namespace_name) - if not unlocalizer then - return src - end - - local unlocal_performed = false - - local temp = src - local tokens = {} - for line in string.gmatch(temp, "[^\n]+") do - table.insert(tokens, line) - end - - for i,s in ipairs(tokens) do - print("s", s) - s = string_trim(s, "\n\r") - print("trimmed", s) - tokens[i] = s - - if s == "" then - goto next_token - end - - -- local function x(a,b,c) - local ur = unlocal_regex(unlocalizer, s) - if ur then - tokens[i] = ur - unlocal_performed = true - tokens[i] = s - goto next_token - end - - -- local a = ... - -- local a - -- local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) - -- local x; local y; - unsupported yet - local pattern = [[^local%s+(.*)]] - local c = string.match(s, pattern) or "" - if #c > 0 then - local r = [[(.*)--.*]] - local nc = string.match(c, r) - if nc then - c = nc - end - end - - local pattern = [[([^=]+)=(.*)]] - local variables, values = string.match(c, pattern) - if variables then - for v in string.gmatch(variables, "[^,]+") do - v = string_trim(v) - if contains(unlocalizer, v) then - unlocal_performed = true - print("found variable", v, "to unlocal") - s = c - if not values then - local r = [[(.*)(--.*)]] - local lhs, rhs = string.match(s, r) - if lhs and rhs then - s = lhs .. "= nil " .. rhs - else - s = s .. " = nil" - end - end - tokens[i] = s - break - end - end - end - - ::next_token:: - end - - if unlocal_performed then - return table.concat(tokens, "\n") - end - - return src -end - -local function compile(src, namespace_name) - return function() - local is_g = namespace_name == "_G" - - local G = setmetatable( - {}, - { - __index = function(_, key) - local gv = _G[key] - if gv ~= nil then - return gv - end - - local res, out = pcall(require, key) - if res then - return out - end - end, - __newindex = function(_, k, v) - _G[k] = v - end - } - ) - - local mt = { - __index = G - } - - if is_g then - mt.__newindex = function(_, k, v) - _G[k] = v - end - end - - local env = setmetatable({ _G = G }, mt) - - if not is_g then - env._M = env - if namespace_name then - env._PACKAGE = namespace_name - -- Prepopulate the environment in case of indirection - package.loaded[namespace_name] = env - end - end - - - if namespace_name then - src = [[ -local script_name = function() - return _PACKAGE -end - ]] .. src - end - - src = [[ -local this = _M - ]] .. src - - local mod = require("macro").load_src(src, namespace_name) - setfenv(mod, env)() - - -- Emplace in package.loaded so require returns env - package.loaded[namespace_name] = env - end -end - -local function expand(src, namespace_name) - print("wua: expanding " .. namespace_name) +local function expand(src, namespace_name, script_name) + print("* wua: expanding", namespace_name) return compile( unlocalize(src, namespace_name), - namespace_name + namespace_name, + script_name ) end -package.loaded["macro/wua"] = { +--require("scam/compiler").register_extension("script", expand) + +return { expand = expand } diff --git a/gamedata/scripts/macro/wua/unlocalize.lua b/gamedata/scripts/macro/wua/unlocalize.lua new file mode 100644 index 0000000000..60a555fd47 --- /dev/null +++ b/gamedata/scripts/macro/wua/unlocalize.lua @@ -0,0 +1,117 @@ +local function string_trim(s, v) + if v == nil then + v = " \t\n\r\f\v" + end + local pattern = string.format("^[%s]*([^%s]*)[%s]*$", v, v, v) + return string.match(s, pattern) +end + +local function contains(lst, a) + for _,b in ipairs(lst) do + if a == b then + return true + end + end + + return false +end + +local function unlocal_regex(unlocals, s) + local pattern = [[^(local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(%(.*)$]] + local _, _, c, d, e, f, g = string.match(s, pattern) + + if e and contains(unlocals, e) then + print("[unlocal_regex] found variable " .. e .. " to unlocal") + s = c .. d .. e .. f .. g + return s + end + + return nil +end + +local function unlocalize(src, namespace_name) + if not namespace_name then + return src + end + + local unlocalizer = require("scam/unlocalize").get(namespace_name) + if not unlocalizer then + return src + end + + local unlocal_performed = false + + local temp = src + local tokens = {} + for line in string.gmatch(temp, "[^\n]+") do + table.insert(tokens, line) + end + + for i,s in ipairs(tokens) do + s = string_trim(s, "\n\r") + tokens[i] = s + + if s == "" then + goto next_token + end + + -- local function x(a,b,c) + local ur = unlocal_regex(unlocalizer, s) + if ur then + tokens[i] = ur + unlocal_performed = true + tokens[i] = s + goto next_token + end + + -- local a = ... + -- local a + -- local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) + -- local x; local y; - unsupported yet + local pattern = [[^local%s+(.*)]] + local c = string.match(s, pattern) or "" + if #c > 0 then + local r = [[(.*)--.*]] + local nc = string.match(c, r) + if nc then + c = nc + end + end + + local pattern = [[([^=]+)=(.*)]] + local variables, values = string.match(c, pattern) + if variables then + for v in string.gmatch(variables, "[^,]+") do + v = string_trim(v) + if contains(unlocalizer, v) then + unlocal_performed = true + print("found variable", v, "to unlocal") + s = c + if not values then + local r = [[(.*)(--.*)]] + local lhs, rhs = string.match(s, r) + if lhs and rhs then + s = lhs .. "= nil " .. rhs + else + s = s .. " = nil" + end + end + tokens[i] = s + break + end + end + end + + ::next_token:: + end + + if unlocal_performed then + return table.concat(tokens, "\n") + end + + return src +end + +return { + unlocalize = unlocalize +} diff --git a/gamedata/scripts/unlocalizers.lua b/gamedata/scripts/unlocalizers.lua deleted file mode 100644 index 88a3e1ee7d..0000000000 --- a/gamedata/scripts/unlocalizers.lua +++ /dev/null @@ -1,65 +0,0 @@ -local unlocalizers = {} - -local function update() - local fs = getFS() - local list = fs:file_list_open( - "$game_config$", - "unlocalizers\\", - bit_or( - FS.FS_ListFiles, - FS.FS_RootOnly - ) - ) - - if not list then - return - end - - local count = list:Size() or 0 - if count == 0 then - return - end - - for i=1,count do - local id = list:GetAt(i - 1) - - if #id < 4 then - goto next_filename - end - - if string.sub(id, #id - 3, #id) ~= ".ltx" then - goto next_filename - end - - print("opening file:", id) - - local config = ini_file("unlocalizers\\" .. id) - config:section_for_each(function(section) - local name = string.lower(section) - local count = config:line_count(name) - for j=0,count-1 do - local res, sec = config:r_line(name, j) - if not res then - goto next_line - end - unlocalizers[name] = unlocalizers[name] or {} - table.insert(unlocalizers[name], sec) - - ::next_line:: - end - end) - - ::next_filename:: - end -end - -local function get(k) - return unlocalizers[k] -end - -update() - -return { - update = update, - get = get -} From 82b3076366e74a70a12108be9b2f391212498827 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 3 Jun 2025 22:01:50 +0100 Subject: [PATCH 39/76] Reintegrate latest `macro/wua` --- gamedata/scripts/macro/lua/init.lua | 60 +++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/gamedata/scripts/macro/lua/init.lua b/gamedata/scripts/macro/lua/init.lua index d829eae97a..fb39b36e56 100644 --- a/gamedata/scripts/macro/lua/init.lua +++ b/gamedata/scripts/macro/lua/init.lua @@ -1,11 +1,55 @@ -function expand(src, namespace_name) - print("lua: expanding " .. namespace_name) - return setfenv( - macro.load_src(src), - macro.extend_env { - script_name = function() - return namespace_name - end +local function handle_error(msg, namespace_name) + return function(err) + package.loaded[namespace_name] = nil + err = "! " .. _PACKAGE .. ": " + .. msg .. ":\n\n" + .. debug.traceback(err .. "\n", 2) + .. "\n" + print(err) + error(err) + end +end + +local function expand(src, namespace_name, script_name) + print("* " .. _PACKAGE .. ": expanding", namespace_name) + + local mod, err = loadstring(src, namespace_name) + if not mod then + handle_error( + "error loading " .. namespace_name, + namespace_name + )(err) + end + + local env = setmetatable( + { + _PACKAGE = namespace_name, + _FILE = script_name, + }, + { + __index = _G, + __newindex = _G, } ) + + local mac = setfenv(mod, env) + + return function() + package.loaded[namespace_name] = env + local _, out = xpcall( + mac, + handle_error( + "error evaluating " .. namespace_name, + namespace_name + ) + ) + + return out + end end + +require("scam/compiler").register_extension("lua", expand) + +return { + expand = expand +} From 33bfffface2aceb64bb7fc207b7df78e519fbe57 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 3 Jun 2025 22:24:07 +0100 Subject: [PATCH 40/76] Consistent logging for `init.lua` --- gamedata/scripts/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index 4046117b6c..0fa6218c2a 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -89,7 +89,7 @@ function read_io(name) end function _COMPILER(src, script_name, namespace_name) - print("lua: loading " .. namespace_name) + print("* init: loading " .. namespace_name) return loadstring(src, namespace_name) end From 52513b8a23bff165fa7f2e0dcf8065c003ed68f5 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 3 Jun 2025 22:24:19 +0100 Subject: [PATCH 41/76] Remove `macro/lua` --- gamedata/scripts/macro/lua/init.lua | 55 ----------------------------- 1 file changed, 55 deletions(-) delete mode 100644 gamedata/scripts/macro/lua/init.lua diff --git a/gamedata/scripts/macro/lua/init.lua b/gamedata/scripts/macro/lua/init.lua deleted file mode 100644 index fb39b36e56..0000000000 --- a/gamedata/scripts/macro/lua/init.lua +++ /dev/null @@ -1,55 +0,0 @@ -local function handle_error(msg, namespace_name) - return function(err) - package.loaded[namespace_name] = nil - err = "! " .. _PACKAGE .. ": " - .. msg .. ":\n\n" - .. debug.traceback(err .. "\n", 2) - .. "\n" - print(err) - error(err) - end -end - -local function expand(src, namespace_name, script_name) - print("* " .. _PACKAGE .. ": expanding", namespace_name) - - local mod, err = loadstring(src, namespace_name) - if not mod then - handle_error( - "error loading " .. namespace_name, - namespace_name - )(err) - end - - local env = setmetatable( - { - _PACKAGE = namespace_name, - _FILE = script_name, - }, - { - __index = _G, - __newindex = _G, - } - ) - - local mac = setfenv(mod, env) - - return function() - package.loaded[namespace_name] = env - local _, out = xpcall( - mac, - handle_error( - "error evaluating " .. namespace_name, - namespace_name - ) - ) - - return out - end -end - -require("scam/compiler").register_extension("lua", expand) - -return { - expand = expand -} From d56a8d262a6d5a50b912f4c6ca75044c6d1f635d Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 3 Jun 2025 22:24:27 +0100 Subject: [PATCH 42/76] Remove `macro/lisp` --- gamedata/scripts/macro/lisp/init.lua | 78 --------------------------- gamedata/scripts/macro/lisp/macro.lua | 22 -------- 2 files changed, 100 deletions(-) delete mode 100644 gamedata/scripts/macro/lisp/init.lua delete mode 100644 gamedata/scripts/macro/lisp/macro.lua diff --git a/gamedata/scripts/macro/lisp/init.lua b/gamedata/scripts/macro/lisp/init.lua deleted file mode 100644 index ce70ad0c70..0000000000 --- a/gamedata/scripts/macro/lisp/init.lua +++ /dev/null @@ -1,78 +0,0 @@ -local scam_unlocalize = require("scam/unlocalize") -local lisp_unlocalize = require("macro/lisp/unlocalize") - -COMPILER_OPTS = { - allowedGlobals = false, - correlate = true, - useBitLib = true, - ["error-pinpoint"] = false, -} - -function make_compiler_opts(env) - local opts = { env = env } - for k,v in pairs(COMPILER_OPTS) do - opts[k] = v - end - return opts -end - -function fennel_form(src) - local _, form = assert( - fennel.parser(src)() - ) - return form -end - -function fennel_forms(src) - local forms = {} - for ok, form in fennel.parser(src) do - assert(ok, "Invalid form") - table.insert(forms, form) - end - return forms -end - -function fennel_list(lst) - return fennel_form("[" .. table.concat(lst, " ") .. "]") -end - -function fennel_eval_ast(ast, opts) - local env = opts.env - opts.env = nil - - return fennel.loadCode( - fennel.compile( - ast, - opts - ), - env - )() -end - -function compile(src, namespace_name) - print("lisp: compiling " .. namespace_name) - - local unlocs = scam_unlocalize.get(namespace_name) - - return function() - local ast = fennel_forms(src) - - if #unlocs then - ast = lisp_unlocalize.unlocalize( - fennel_list(unlocs), - unpack(ast) - ) - end - - package.loaded[namespace_name] = fennel_eval_ast( - ast, - make_compiler_opts( - macro.extend_env { - script_name = function() - return namespace_name - end - } - ) - ) - end -end diff --git a/gamedata/scripts/macro/lisp/macro.lua b/gamedata/scripts/macro/lisp/macro.lua deleted file mode 100644 index 3f3b704487..0000000000 --- a/gamedata/scripts/macro/lisp/macro.lua +++ /dev/null @@ -1,22 +0,0 @@ -COMPILER_OPTS = { - correlate = true, - env = "_COMPILER", - useBitLib = true, - ["error-pinpoint"] = false, -} - -function compile(src, namespace_name) - print("lisp_macro: compiling " .. namespace_name) - - return function() - local macros = fennel.eval( - src, - COMPILER_OPTS - ) - - if namespace_name then - fennel["macro-loaded"][namespace_name] = macros - package.loaded[namespace_name] = macros - end - end -end From d65053469dcf019f0858d6e3721ba776494de132 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 3 Jun 2025 22:42:40 +0100 Subject: [PATCH 43/76] Reorganize `macro` and `scam`, add `amx` --- gamedata/scripts/{scam => amx}/classes.lua | 0 gamedata/scripts/amx/init.lua | 12 ++++++++++++ gamedata/scripts/{scam => amx}/sandbox.lua | 0 gamedata/scripts/{scam => amx}/scripts.lua | 0 gamedata/scripts/{scam => amx}/unlocalize.lua | 2 +- gamedata/scripts/{macro => amx}/wua/compile.lua | 0 gamedata/scripts/{macro => amx}/wua/init.lua | 4 ++-- .../scripts/{macro => amx}/wua/unlocalize.lua | 4 ++-- gamedata/scripts/init.lua | 7 ++----- gamedata/scripts/macro/init.lua | 15 --------------- gamedata/scripts/scam/compiler.lua | 2 +- gamedata/scripts/scam/init.lua | 4 ---- 12 files changed, 20 insertions(+), 30 deletions(-) rename gamedata/scripts/{scam => amx}/classes.lua (100%) create mode 100644 gamedata/scripts/amx/init.lua rename gamedata/scripts/{scam => amx}/sandbox.lua (100%) rename gamedata/scripts/{scam => amx}/scripts.lua (100%) rename gamedata/scripts/{scam => amx}/unlocalize.lua (97%) rename gamedata/scripts/{macro => amx}/wua/compile.lua (100%) rename gamedata/scripts/{macro => amx}/wua/init.lua (72%) rename gamedata/scripts/{macro => amx}/wua/unlocalize.lua (97%) delete mode 100644 gamedata/scripts/macro/init.lua diff --git a/gamedata/scripts/scam/classes.lua b/gamedata/scripts/amx/classes.lua similarity index 100% rename from gamedata/scripts/scam/classes.lua rename to gamedata/scripts/amx/classes.lua diff --git a/gamedata/scripts/amx/init.lua b/gamedata/scripts/amx/init.lua new file mode 100644 index 0000000000..6f92d44679 --- /dev/null +++ b/gamedata/scripts/amx/init.lua @@ -0,0 +1,12 @@ +require("amx/sandbox") + +local compiler = require("scam/compiler") + +require("amx/unlocalize") +require("amx/wua") +compiler.set_default_macro("amx/wua.expand") + +require("_G") + +require("amx/classes") +require("amx/scripts") diff --git a/gamedata/scripts/scam/sandbox.lua b/gamedata/scripts/amx/sandbox.lua similarity index 100% rename from gamedata/scripts/scam/sandbox.lua rename to gamedata/scripts/amx/sandbox.lua diff --git a/gamedata/scripts/scam/scripts.lua b/gamedata/scripts/amx/scripts.lua similarity index 100% rename from gamedata/scripts/scam/scripts.lua rename to gamedata/scripts/amx/scripts.lua diff --git a/gamedata/scripts/scam/unlocalize.lua b/gamedata/scripts/amx/unlocalize.lua similarity index 97% rename from gamedata/scripts/scam/unlocalize.lua rename to gamedata/scripts/amx/unlocalize.lua index 13c64dd2b7..2093e179d4 100644 --- a/gamedata/scripts/scam/unlocalize.lua +++ b/gamedata/scripts/amx/unlocalize.lua @@ -63,7 +63,7 @@ function get(k) end -package.loaded["scam/unlocalize"] = { +return { update = update, get = get } diff --git a/gamedata/scripts/macro/wua/compile.lua b/gamedata/scripts/amx/wua/compile.lua similarity index 100% rename from gamedata/scripts/macro/wua/compile.lua rename to gamedata/scripts/amx/wua/compile.lua diff --git a/gamedata/scripts/macro/wua/init.lua b/gamedata/scripts/amx/wua/init.lua similarity index 72% rename from gamedata/scripts/macro/wua/init.lua rename to gamedata/scripts/amx/wua/init.lua index d9407b1942..14217c9cde 100644 --- a/gamedata/scripts/macro/wua/init.lua +++ b/gamedata/scripts/amx/wua/init.lua @@ -1,5 +1,5 @@ -local unlocalize = require("macro/wua/unlocalize").unlocalize -local compile = require("macro/wua/compile").compile +local unlocalize = require("amx/wua/unlocalize").unlocalize +local compile = require("amx/wua/compile").compile local function expand(src, namespace_name, script_name) print("* wua: expanding", namespace_name) diff --git a/gamedata/scripts/macro/wua/unlocalize.lua b/gamedata/scripts/amx/wua/unlocalize.lua similarity index 97% rename from gamedata/scripts/macro/wua/unlocalize.lua rename to gamedata/scripts/amx/wua/unlocalize.lua index 60a555fd47..8512d7813a 100644 --- a/gamedata/scripts/macro/wua/unlocalize.lua +++ b/gamedata/scripts/amx/wua/unlocalize.lua @@ -33,8 +33,8 @@ local function unlocalize(src, namespace_name) if not namespace_name then return src end - - local unlocalizer = require("scam/unlocalize").get(namespace_name) + + local unlocalizer = require("amx/unlocalize").get(namespace_name) if not unlocalizer then return src end diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index 0fa6218c2a..f1d0bb7247 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -190,8 +190,5 @@ function function_object(str) return val end --- Pass control to scam init -local res, err = pcall(require, "scam") -if not res then - error("Failed to load scam:\n" .. err) -end +-- Pass control to amx entrypoint +require("amx") diff --git a/gamedata/scripts/macro/init.lua b/gamedata/scripts/macro/init.lua deleted file mode 100644 index d03e30ee21..0000000000 --- a/gamedata/scripts/macro/init.lua +++ /dev/null @@ -1,15 +0,0 @@ -function load_src(src, script_name) - return assert(loadstring(src, script_name)) -end - -function extend_env(dest) - for k,v in pairs(getfenv(0)) do - dest[k] = v - end - return dest -end - -package.loaded["macro"] = { - load_src = load_src, - extend_env = extend_env, -} diff --git a/gamedata/scripts/scam/compiler.lua b/gamedata/scripts/scam/compiler.lua index de6ae48d21..b22299390d 100644 --- a/gamedata/scripts/scam/compiler.lua +++ b/gamedata/scripts/scam/compiler.lua @@ -22,7 +22,7 @@ function _COMPILER(src, script_name, namespace_name) return old_compiler(src, script_name, namespace_name) end -package.loaded["scam/compiler"] = { +return { compile = _COMPILER, set_default_macro = set_default_macro } diff --git a/gamedata/scripts/scam/init.lua b/gamedata/scripts/scam/init.lua index f658e9fb99..0b53ec8301 100644 --- a/gamedata/scripts/scam/init.lua +++ b/gamedata/scripts/scam/init.lua @@ -1,11 +1,7 @@ print("Instigating S.C.A.M.") -require("scam/sandbox") - local compiler = require("scam/compiler") -require("macro") -require("scam/unlocalize") require("macro/wua") compiler.set_default_macro("macro/wua.expand") From 0f053c1773055d4a4effc2bcab5464a92f6babea Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 3 Jun 2025 23:14:35 +0100 Subject: [PATCH 44/76] Integrate up-to-date `init`, `boot`, `scam` --- gamedata/scripts/amx/init.lua | 5 +- gamedata/scripts/amx/scripts.lua | 1 - gamedata/scripts/amx/wua/init.lua | 2 +- gamedata/scripts/boot/function_object.lua | 27 +++ gamedata/scripts/boot/init.lua | 16 ++ gamedata/scripts/boot/loader.lua | 93 ++++++++++ gamedata/scripts/boot/paths.lua | 24 +++ gamedata/scripts/boot/sandbox.lua | 20 +++ gamedata/scripts/init.lua | 201 +++++----------------- gamedata/scripts/scam/compiler.lua | 66 +++++-- gamedata/scripts/scam/init.lua | 19 +- 11 files changed, 293 insertions(+), 181 deletions(-) create mode 100644 gamedata/scripts/boot/function_object.lua create mode 100644 gamedata/scripts/boot/init.lua create mode 100644 gamedata/scripts/boot/loader.lua create mode 100644 gamedata/scripts/boot/paths.lua create mode 100644 gamedata/scripts/boot/sandbox.lua diff --git a/gamedata/scripts/amx/init.lua b/gamedata/scripts/amx/init.lua index 6f92d44679..6e47beaae8 100644 --- a/gamedata/scripts/amx/init.lua +++ b/gamedata/scripts/amx/init.lua @@ -1,11 +1,10 @@ require("amx/sandbox") local compiler = require("scam/compiler") - require("amx/unlocalize") -require("amx/wua") -compiler.set_default_macro("amx/wua.expand") +compiler.set_default_macro(require("amx/wua").expand) +package.loaded._G = nil require("_G") require("amx/classes") diff --git a/gamedata/scripts/amx/scripts.lua b/gamedata/scripts/amx/scripts.lua index f7e275253c..b297f58ccb 100644 --- a/gamedata/scripts/amx/scripts.lua +++ b/gamedata/scripts/amx/scripts.lua @@ -20,7 +20,6 @@ end local scripts = ini:r_string("common", "script", "") for script in scripts:gmatch("[^,]+") do - print("script:", script) local mod = require(script) if type(mod) ~= "table" then print("Error: " .. script .. " module is not a table") diff --git a/gamedata/scripts/amx/wua/init.lua b/gamedata/scripts/amx/wua/init.lua index 14217c9cde..ae7d925ffe 100644 --- a/gamedata/scripts/amx/wua/init.lua +++ b/gamedata/scripts/amx/wua/init.lua @@ -10,7 +10,7 @@ local function expand(src, namespace_name, script_name) ) end ---require("scam/compiler").register_extension("script", expand) +require("scam/compiler").register_extension("script", expand) return { expand = expand diff --git a/gamedata/scripts/boot/function_object.lua b/gamedata/scripts/boot/function_object.lua new file mode 100644 index 0000000000..b5593f8bde --- /dev/null +++ b/gamedata/scripts/boot/function_object.lua @@ -0,0 +1,27 @@ +-- Engine interface; require with explicit _G and recursive indexing +function function_object(str) + local path = {} + for v in string.gmatch(str, "[^%.]+") do + table.insert(path, v) + end + + local mod_name = table.remove(path, 1) + + local mod = nil + if mod_name == "_G" then + mod = _G + elseif _G[mod_name] then + mod = _G[mod_name] + else + mod = require(mod_name) + end + + local val = mod + for _, seg in ipairs(path) do + val = val[seg] + end + + return val +end + +return {} diff --git a/gamedata/scripts/boot/init.lua b/gamedata/scripts/boot/init.lua new file mode 100644 index 0000000000..c6df1e33fc --- /dev/null +++ b/gamedata/scripts/boot/init.lua @@ -0,0 +1,16 @@ +--- Boot Kernel +--- Establishes a basic functioning X-Ray Lua environment + +_PACKAGE = "boot" + +-- Disable unsafe Lua primitives +require("boot/sandbox") + +-- Setup path machinery +require("boot/paths") + +-- Setup loading machinery +require("boot/loader") + +-- Setup engine interface +require("boot/function_object") diff --git a/gamedata/scripts/boot/loader.lua b/gamedata/scripts/boot/loader.lua new file mode 100644 index 0000000000..00e00d53b1 --- /dev/null +++ b/gamedata/scripts/boot/loader.lua @@ -0,0 +1,93 @@ +_PACKAGE = "boot/loader" + +local state = { + callbacks = {} +} + +-- Define xray FS loader +function _LOADERS.fs(name) + local fs = getFS() + local errs = "" + local base = fs:update_path("$game_scripts$", "") + for seg in package.path:gmatch("[^;]+") do + if seg:sub(1, #base) == base then + local fname = seg:sub(#base + 1):gsub("?", name):gsub("/", "\\") + local path = fs:update_path("$game_scripts$", fname) + if path and fs:exist(path) then + local src = _LOAD_FILE(path) + + local res, out = pcall(_COMPILER, src, name, path) + if not res then + print(out) + error(out) + end + + return out + end + + if #errs > 0 then + errs = errs .. "\n\t" + end + errs = errs .. "No db entry: " .. path + end + end + + return errs +end + +local loaders = { _LOADERS.fs } + +-- Lift into a memoized higher-order loader +local function io_loaders(name) + local io_miss = _SCRIPT_STORAGE:get("io_loader", name) + if io_miss then + return io_miss + end + + local err = "" + for i=1,#loaders do + local out = loaders[i](name) + + local ty = type(out) + if ty == "function" then + local already_loaded = package.loaded[name] + local res = out() + package.loaded[name] = res + if already_loaded == nil then + for _,f in ipairs(state.callbacks) do + f(name) + end + end + return function() + package.loaded[name] = res + return res + end + else + package.loaded[name] = nil + if #err > 0 then + err = err .. "\n" + end + if ty == "string" then + err = err .. out + elseif ty == "nil" then + error("No such module: " .. name) + else + error("Loader returned invalid value: " .. tostring(out)) + end + end + end + + _SCRIPT_STORAGE:set("io_loader", name, err) + return err +end + +-- Replace the loader list with the preloader plus our memoized IO loader +package.loaders = { _LOADERS.pre, io_loaders } + +local function register_on_load_callback(f) + table.insert(state.callbacks, f) +end + +return { + register_on_load_callback = register_on_load_callback +} diff --git a/gamedata/scripts/boot/paths.lua b/gamedata/scripts/boot/paths.lua new file mode 100644 index 0000000000..bef874c083 --- /dev/null +++ b/gamedata/scripts/boot/paths.lua @@ -0,0 +1,24 @@ +_PACKAGE = "boot/paths" + +-- Define load path registrator +function _REGISTER_PATHS(...) + local ps = {...} + for i=#ps,1,-1 do + local p = getFS():update_path("$game_scripts$", ps[i]) + package.path = p .. ";" .. package.path + end +end + +local fs = getFS() + +local base = fs:update_path("$game_scripts$", "") + +package.path = base .. [[?.lua]] + .. ";" .. base .. [[?/init.lua]] + .. ";" .. base .. [[packages/lib/?.lua]] + .. ";" .. base .. [[packages/lib/?/init.lua]] + +package.cpath = base .. [[packages/bin/?.dll]] + .. ";" .. base .. [[packages/bin/?/init.dll]] + .. ";" .. base .. [[packages/bin/?.so]] + .. ";" .. base .. [[packages/bin/?/init.so]] diff --git a/gamedata/scripts/boot/sandbox.lua b/gamedata/scripts/boot/sandbox.lua new file mode 100644 index 0000000000..a8976d41ab --- /dev/null +++ b/gamedata/scripts/boot/sandbox.lua @@ -0,0 +1,20 @@ +-- Disable OS functions +local disabled = { + os = { + "execute", + "rename", + "remove", + "exit", + }, + io = { + "popen" + } +} + +for k,v in pairs(disabled) do + for i=1,#v do + _G[k][v[i]] = nil + end +end + +return {} diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index f1d0bb7247..6331b52c06 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -1,4 +1,15 @@ -package.loaded._G = nil +--- Lua Entrypoint +--- Called by CScriptEngine at the end of Lua initialization + +_PACKAGE = "init" + +--- Store default Lua loaders for later +_LOADERS = { + pre = package.loaders[1], + lib = package.loaders[2], + bin = package.loaders[3], + aio = package.loaders[4], +} -- Emplace working print function function print(...) @@ -25,170 +36,50 @@ function print(...) end end --- Setup script load paths -local scripts_path = getFS():update_path("$game_scripts$", ""):gsub("\\", "/") -local paths = { - "?.script", - "?/init.script", - "?.lua", - "?/init.lua", - "?.fnl", - "?/init.fnl", -} - -for i=#paths,1,-1 do - local path = paths[i] - package.path = scripts_path .. path .. ";" .. package.path -end - --- Define *.db reader -function read_db(name) - local fs = getFS() - local fname = name:gsub("/", "\\") .. ".script" - local path = fs:update_path("$game_scripts$", fname) - local file = fs:r_open(path) - - if not file then - return nil, nil, "No db entry: gamedata/scripts/" .. fname - end - - local src = "" - while not file:r_eof() do - src = src .. string.char(file:r_u8()) - end - - return src, path -end - --- Define IO reader -function read_io(name) - local errs = "" - for seg in package.path:gmatch("[^;]+") do - local path = seg:gsub("?", name) - - local file, err = io.open(path) - if file == nil then - if #errs > 0 then - errs = errs .. "\n" - end - errs = errs .. err - goto next_seg - end - - local src = file:read("*a") - file:close() - - if src then - return src, path - end - - ::next_seg:: - end - - return nil, nil, errs -end - -function _COMPILER(src, script_name, namespace_name) +--- Emplace minimal compiler +function _COMPILER(src, namespace_name) print("* init: loading " .. namespace_name) - return loadstring(src, namespace_name) + return setfenv( + loadstring(src, namespace_name), + setmetatable( + { _PACKAGE = namespace_name }, + { + __index = _G, + __newindex = _G, + } + ) + ) end --- Define reader -> loader transformer -function loader(with) - return function(name) - local src, path, err = with(name) - if not src then - return "\n\t" .. err - end - - local mod = _COMPILER(src, path, name) - - if mod then - return mod - end - - return "\n\tFailed to compile " .. name +--- Emplace minimal X-Ray FS loader +function _LOADERS.init(name) + local fs = getFS() + local path = fs:update_path("$game_scripts$", name:gsub("/", "\\")) + if not path then + return "\n\tInvalid path " .. path end -end - --- Define the set of readers to register as loaders -local readers = { - read_io, - read_db -} --- Pop the preloader off the loader list -local preload_loader = table.remove(package.loaders, 1) - --- Pop the default textual script loader -table.remove(package.loaders, 1) - --- Emplace new loaders for filesystem and db -for i=#readers,1,-1 do - table.insert(package.loaders, 1, loader(readers[i])) -end - - --- Lift into a memoized higher-order loader -local loaders = package.loaders -local io_miss = {} -local function io_loader(name) - local io_miss = _SCRIPT_STORAGE:get("io_loader", name) - if io_miss then - return io_miss + if fs:exist(path .. ".lua") then + path = path .. ".lua" + elseif + fs:exist(path .. "\\init.lua") then + path = path .. "\\init.lua" + else + return "\n\tNo such package: " .. name end - local err = "" - for i=1,#loaders do - local res = loaders[i](name) - - local ty = type(res) - if ty == "function" then - return res - else - if #err > 0 then - err = err .. "\n" - end - if ty == "string" then - err = err .. res - else - err = err .. "Loader returned invalid type: " .. ty - end - end + local res, out = pcall(_COMPILER, _LOAD_FILE(path), name, path) + if not res then + print(out) + error(out) end - - _SCRIPT_STORAGE:set("io_loader", name, err) - return err + return out end --- Replace the loader list with the preloader plus our memoized IO loader -package.loaders = { preload_loader, io_loader } - --- Extend require with path support -function function_object(str) - local path = {} - for v in string.gmatch(str, "[^%.]+") do - table.insert(path, v) - end - - local mod_name = table.remove(path, 1) +package.loaders = { _LOADERS.init } - local mod = nil - if mod_name == "_G" then - mod = _G - elseif _G[mod_name] then - mod = _G[mod_name] - else - mod = require(mod_name) - end - - local val = mod - for _, seg in ipairs(path) do - val = val[seg] - end - - return val -end +--- Initialize environment via the boot module +require("boot") --- Pass control to amx entrypoint +-- Pass control to modded exes entrypoint require("amx") diff --git a/gamedata/scripts/scam/compiler.lua b/gamedata/scripts/scam/compiler.lua index b22299390d..3beced4496 100644 --- a/gamedata/scripts/scam/compiler.lua +++ b/gamedata/scripts/scam/compiler.lua @@ -1,28 +1,66 @@ -TAG_MACRO = "#macro " +local PATTERN_FILE_PATH = "^(.-)([^\\/]-)%.([^\\/%.]-)%.?$" +local PATTERN_MACRO_TAG = "[^ ]+ +=%*= +lang: +([^ ]+) +=%*=[^\n]*(\n.*)" +local extensions = {} local state = { - default_macro = nil + default = _COMPILER } -function set_default_macro(mac) - state.default_macro = mac +function _COMPILER(src, namespace_name, script_name) + local mac = nil + + if script_name then + local _,_,ext = script_name:match(PATTERN_FILE_PATH) + if extensions[ext] then + mac = extensions[ext] + end + end + + local tag,rest = src:match(PATTERN_MACRO_TAG) + if tag ~= nil then + src = rest + mac = function_object(tag) + end + + if mac == nil then + mac = state.default + end + + local res, out = pcall(mac, src, namespace_name, script_name) + if not res then + print(out) + error(out) + end + + return out end -local old_compiler = _COMPILER -function _COMPILER(src, script_name, namespace_name) - if string.sub(src, 1, #TAG_MACRO) == TAG_MACRO then - src = string.sub(src, #TAG_MACRO + 1) - local tag, rest = string.match(src, "([^%s]+)(%s+.*)") - local path = "macro/" .. tag - return function_object(path)(rest, namespace_name) - elseif state.default_macro then - return function_object(state.default_macro)(src, namespace_name) +local function register_extension(k, v) + print(_PACKAGE .. ": registering script extension: " .. k) + _REGISTER_PATHS( + "?." .. k, + "?/init." .. k + ) + extensions[k] = v +end + +local function get_extensions() + local out = {} + for k in pairs(extensions) do + table.insert(out, k) end + return out +end - return old_compiler(src, script_name, namespace_name) +local function set_default_macro(mac) + state.default = mac end return { + PATTERN_FILE_PATH = PATTERN_FILE_PATH, + PATTERN_MACRO_TAG = PATTERN_MACRO_TAG, compile = _COMPILER, + register_extension = register_extension, + get_extensions = get_extensions, set_default_macro = set_default_macro } diff --git a/gamedata/scripts/scam/init.lua b/gamedata/scripts/scam/init.lua index 0b53ec8301..f05a71ab28 100644 --- a/gamedata/scripts/scam/init.lua +++ b/gamedata/scripts/scam/init.lua @@ -1,12 +1,17 @@ -print("Instigating S.C.A.M.") +--- Script Compilers And Macros +--- Racket-inspired language-oriented programming in Lua +-- Setup compiler local compiler = require("scam/compiler") -require("macro/wua") +-- Load initial languages +require("scam/lua") +require("scam/teal") +require("scam/fennel") -compiler.set_default_macro("macro/wua.expand") +-- Setup import machinery +require("scam/import") -require("_G") - -require("scam/classes") -require("scam/scripts") +return { + compiler = compiler +} From 49ccc4e62d08041bb7b2d37fc13898f1e11923dd Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 3 Jun 2025 23:26:01 +0100 Subject: [PATCH 45/76] Integrate up-to-date `amx` --- gamedata/scripts/amx/classes.lua | 2 ++ gamedata/scripts/amx/init.lua | 18 +++++++++++++++--- gamedata/scripts/amx/registrator.lua | 25 +++++++++++++++++++++++++ gamedata/scripts/amx/sandbox.lua | 18 ------------------ gamedata/scripts/amx/scripts.lua | 2 ++ gamedata/scripts/amx/unlocalize.lua | 13 +++++-------- gamedata/scripts/amx/wua/compile.lua | 2 +- gamedata/scripts/amx/wua/init.lua | 2 +- gamedata/scripts/amx/wua/unlocalize.lua | 2 +- gamedata/scripts/scam/init.lua | 10 +--------- 10 files changed, 53 insertions(+), 41 deletions(-) create mode 100644 gamedata/scripts/amx/registrator.lua delete mode 100644 gamedata/scripts/amx/sandbox.lua diff --git a/gamedata/scripts/amx/classes.lua b/gamedata/scripts/amx/classes.lua index 6427fcae7c..e39d4c84b5 100644 --- a/gamedata/scripts/amx/classes.lua +++ b/gamedata/scripts/amx/classes.lua @@ -19,3 +19,5 @@ for reg_path in regs:gmatch("[^,]+") do end _OBJECT_FACTORY:register_script() + +return {} diff --git a/gamedata/scripts/amx/init.lua b/gamedata/scripts/amx/init.lua index 6e47beaae8..e598b3fbb9 100644 --- a/gamedata/scripts/amx/init.lua +++ b/gamedata/scripts/amx/init.lua @@ -1,11 +1,23 @@ -require("amx/sandbox") +_PACKAGE = "amx" +_FILE = "amx/init.lua" -local compiler = require("scam/compiler") +-- Initialize S.C.A.M. environment +local scam = require("scam") + +-- Load unlocalize before wua to avoid circular referencing require("amx/unlocalize") -compiler.set_default_macro(require("amx/wua").expand) +-- Setup wua as the default language +scam.compiler.set_default_macro( + require("amx/wua").expand +) + +-- Forcefully load _g.script package.loaded._G = nil require("_G") +-- Register classes require("amx/classes") + +-- Run common scripts require("amx/scripts") diff --git a/gamedata/scripts/amx/registrator.lua b/gamedata/scripts/amx/registrator.lua new file mode 100644 index 0000000000..f2f7912ea5 --- /dev/null +++ b/gamedata/scripts/amx/registrator.lua @@ -0,0 +1,25 @@ +-- Add custom classes to register here +local function cs_register(factory,client_object_class,server_object_class,clsid,script_clsid) + factory:register(client_object_class,server_object_class,clsid,script_clsid) +end + +local function c_register(factory,client_object_class,clsid,script_clsid) + if (editor() == false) then + factory:register(client_object_class,clsid,script_clsid) + end +end + +local function s_register(factory,server_object_class,clsid,script_clsid) + factory:register(server_object_class,clsid,script_clsid) +end + +local function register(object_factory) + cs_register(object_factory, "CWeaponSSRS", "se_item.se_weapon_magazined", "_WP_SSRS", "wpn_ssrs_s") +end + +return { + cs_register = cs_register, + c_register = c_register, + s_register = s_register, + register = register, +} diff --git a/gamedata/scripts/amx/sandbox.lua b/gamedata/scripts/amx/sandbox.lua deleted file mode 100644 index 46ebf49736..0000000000 --- a/gamedata/scripts/amx/sandbox.lua +++ /dev/null @@ -1,18 +0,0 @@ --- Disable OS functions -local disabled = { - os = { - "execute", - "rename", - "remove", - "exit", - }, - io = { - "popen" - } -} - -for k,v in pairs(disabled) do - for i=1,#v do - _G[k][v[i]] = nil - end -end diff --git a/gamedata/scripts/amx/scripts.lua b/gamedata/scripts/amx/scripts.lua index b297f58ccb..051aa91e0a 100644 --- a/gamedata/scripts/amx/scripts.lua +++ b/gamedata/scripts/amx/scripts.lua @@ -35,3 +35,5 @@ for script in scripts:gmatch("[^,]+") do ::next_script:: end + +return {} diff --git a/gamedata/scripts/amx/unlocalize.lua b/gamedata/scripts/amx/unlocalize.lua index 2093e179d4..1157111428 100644 --- a/gamedata/scripts/amx/unlocalize.lua +++ b/gamedata/scripts/amx/unlocalize.lua @@ -1,7 +1,6 @@ local unlocalizers = {} -local updated = false -function update() +local function update() local fs = getFS() local list = fs:file_list_open( "$game_config$", @@ -15,7 +14,7 @@ function update() if not list then return end - + local count = list:Size() or 0 if count == 0 then return @@ -54,16 +53,14 @@ function update() end end -function get(k) - if not updated then - updated = true - update() - end +local function get(k) return unlocalizers[k] end +update() return { update = update, get = get } + diff --git a/gamedata/scripts/amx/wua/compile.lua b/gamedata/scripts/amx/wua/compile.lua index 53fc4f73ef..1d4f803f52 100644 --- a/gamedata/scripts/amx/wua/compile.lua +++ b/gamedata/scripts/amx/wua/compile.lua @@ -1,4 +1,4 @@ ---local remap = require("moved").remap +--local remap = import("/moved").remap local G = setmetatable( {}, diff --git a/gamedata/scripts/amx/wua/init.lua b/gamedata/scripts/amx/wua/init.lua index ae7d925ffe..0fb374969d 100644 --- a/gamedata/scripts/amx/wua/init.lua +++ b/gamedata/scripts/amx/wua/init.lua @@ -2,7 +2,7 @@ local unlocalize = require("amx/wua/unlocalize").unlocalize local compile = require("amx/wua/compile").compile local function expand(src, namespace_name, script_name) - print("* wua: expanding", namespace_name) + print("* " .. _PACKAGE .. ": expanding", namespace_name) return compile( unlocalize(src, namespace_name), namespace_name, diff --git a/gamedata/scripts/amx/wua/unlocalize.lua b/gamedata/scripts/amx/wua/unlocalize.lua index 8512d7813a..ee832bb783 100644 --- a/gamedata/scripts/amx/wua/unlocalize.lua +++ b/gamedata/scripts/amx/wua/unlocalize.lua @@ -33,7 +33,7 @@ local function unlocalize(src, namespace_name) if not namespace_name then return src end - + local unlocalizer = require("amx/unlocalize").get(namespace_name) if not unlocalizer then return src diff --git a/gamedata/scripts/scam/init.lua b/gamedata/scripts/scam/init.lua index f05a71ab28..fa97b0030c 100644 --- a/gamedata/scripts/scam/init.lua +++ b/gamedata/scripts/scam/init.lua @@ -1,17 +1,9 @@ --- Script Compilers And Macros ---- Racket-inspired language-oriented programming in Lua +--- Script preprocess dispatch machinery -- Setup compiler local compiler = require("scam/compiler") --- Load initial languages -require("scam/lua") -require("scam/teal") -require("scam/fennel") - --- Setup import machinery -require("scam/import") - return { compiler = compiler } From c9eb2fd31038c17563dd9bd4df78f1b6f7501ad9 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 4 Jun 2025 04:12:25 +0100 Subject: [PATCH 46/76] Unify `pcall` / stack tracing into unwind-aware `init` compiler --- gamedata/scripts/amx/wua/compile.lua | 3 +-- gamedata/scripts/boot/loader.lua | 9 +-------- gamedata/scripts/init.lua | 27 ++++++++++++++++++++++++++- gamedata/scripts/scam/compiler.lua | 8 +------- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/gamedata/scripts/amx/wua/compile.lua b/gamedata/scripts/amx/wua/compile.lua index 1d4f803f52..b2f8a21d51 100644 --- a/gamedata/scripts/amx/wua/compile.lua +++ b/gamedata/scripts/amx/wua/compile.lua @@ -63,9 +63,8 @@ local function handle_error(msg, namespace_name) package.loaded[namespace_name] = nil err = "! " .. _PACKAGE .. ": " .. msg .. ":\n\n" - .. debug.traceback(err .. "\n", 2) + .. err .. "\n" - print(err) error(err) end end diff --git a/gamedata/scripts/boot/loader.lua b/gamedata/scripts/boot/loader.lua index 00e00d53b1..a05f2368c9 100644 --- a/gamedata/scripts/boot/loader.lua +++ b/gamedata/scripts/boot/loader.lua @@ -15,14 +15,7 @@ function _LOADERS.fs(name) local path = fs:update_path("$game_scripts$", fname) if path and fs:exist(path) then local src = _LOAD_FILE(path) - - local res, out = pcall(_COMPILER, src, name, path) - if not res then - print(out) - error(out) - end - - return out + return _COMPILER(src, name, path) end if #errs > 0 then diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index 6331b52c06..c00a40837a 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -36,11 +36,36 @@ function print(...) end end +-- Set to true if we're unwinding the stack following an error +_UNWIND = false + --- Emplace minimal compiler function _COMPILER(src, namespace_name) print("* init: loading " .. namespace_name) return setfenv( - loadstring(src, namespace_name), + function(...) + local f, err = loadstring(src, namespace_name) + if not f then + local err = "init: error loading " .. namespace_name .. ":\n\n" + .. err .. "\n" + if not _UNWIND then + print(debug.traceback(err, 2)) + _UNWIND = true + end + error(err) + end + + local res, out = pcall(f, ...) + if not res then + if not _UNWIND then + print(debug.traceback(out, 2)) + _UNWIND = true + end + error(out) + end + + return out + end, setmetatable( { _PACKAGE = namespace_name }, { diff --git a/gamedata/scripts/scam/compiler.lua b/gamedata/scripts/scam/compiler.lua index 3beced4496..4907fdaa9a 100644 --- a/gamedata/scripts/scam/compiler.lua +++ b/gamedata/scripts/scam/compiler.lua @@ -26,13 +26,7 @@ function _COMPILER(src, namespace_name, script_name) mac = state.default end - local res, out = pcall(mac, src, namespace_name, script_name) - if not res then - print(out) - error(out) - end - - return out + return mac(src, namespace_name, script_name) end local function register_extension(k, v) From 9d177a58fc292bc102501c1f426195f632c9f52d Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 5 Jun 2025 18:37:06 +0100 Subject: [PATCH 47/76] Register built-in `lua` compiler implicitly --- gamedata/scripts/scam/compiler.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamedata/scripts/scam/compiler.lua b/gamedata/scripts/scam/compiler.lua index 4907fdaa9a..2da79d54b8 100644 --- a/gamedata/scripts/scam/compiler.lua +++ b/gamedata/scripts/scam/compiler.lua @@ -1,7 +1,7 @@ local PATTERN_FILE_PATH = "^(.-)([^\\/]-)%.([^\\/%.]-)%.?$" local PATTERN_MACRO_TAG = "[^ ]+ +=%*= +lang: +([^ ]+) +=%*=[^\n]*(\n.*)" -local extensions = {} +local extensions = { lua = _COMPILER } local state = { default = _COMPILER } From 7716d87f0a8c98b27b9c5443c5f1a10ae5b0b1e6 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 5 Jun 2025 18:38:13 +0100 Subject: [PATCH 48/76] Bind `_FILE` in `lua` compiler, improve error reporting --- gamedata/scripts/init.lua | 69 ++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index c00a40837a..bae1d0988e 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -39,41 +39,56 @@ end -- Set to true if we're unwinding the stack following an error _UNWIND = false ---- Emplace minimal compiler -function _COMPILER(src, namespace_name) - print("* init: loading " .. namespace_name) - return setfenv( - function(...) - local f, err = loadstring(src, namespace_name) - if not f then - local err = "init: error loading " .. namespace_name .. ":\n\n" - .. err .. "\n" - if not _UNWIND then - print(debug.traceback(err, 2)) - _UNWIND = true - end - error(err) - end - - local res, out = pcall(f, ...) - if not res then - if not _UNWIND then - print(debug.traceback(out, 2)) - _UNWIND = true - end - error(out) - end +--- Emplace Lua passthrough compiler +function _COMPILER(src, namespace_name, script_name) + print("* lua: loading " .. namespace_name) + + local f, err = loadstring(src, namespace_name) + if not f then + err = "init: error loading " .. namespace_name .. ":\n\n" + .. err .. "\n" + if not _UNWIND then + err = debug.traceback(err, 2) + print(err) + _UNWIND = true + end + error(err) + end - return out - end, + local mac = setfenv( + f, setmetatable( - { _PACKAGE = namespace_name }, + { + _PACKAGE = namespace_name, + _FILE = script_name, + }, { __index = _G, __newindex = _G, } ) ) + + return function(...) + local args = {...} + local _, out = xpcall( + function() + return mac(unpack(args)) + end, + function(err) + if not res then + if not _UNWIND then + err = debug.traceback(err, 2) + print(err) + _UNWIND = true + end + error(err) + end + end + ) + + return out + end end --- Emplace minimal X-Ray FS loader From 7bc76d7f05b6438cfd72844e86cdc94857f51425 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Thu, 5 Jun 2025 21:12:14 +0100 Subject: [PATCH 49/76] Skip modules with non-table `require` output in `amx/scripts` --- gamedata/scripts/amx/classes.lua | 1 - gamedata/scripts/amx/scripts.lua | 19 +++++-------------- gamedata/scripts/boot/function_object.lua | 2 -- gamedata/scripts/boot/sandbox.lua | 2 -- 4 files changed, 5 insertions(+), 19 deletions(-) diff --git a/gamedata/scripts/amx/classes.lua b/gamedata/scripts/amx/classes.lua index e39d4c84b5..7bd014a6c6 100644 --- a/gamedata/scripts/amx/classes.lua +++ b/gamedata/scripts/amx/classes.lua @@ -20,4 +20,3 @@ end _OBJECT_FACTORY:register_script() -return {} diff --git a/gamedata/scripts/amx/scripts.lua b/gamedata/scripts/amx/scripts.lua index 051aa91e0a..22860e289e 100644 --- a/gamedata/scripts/amx/scripts.lua +++ b/gamedata/scripts/amx/scripts.lua @@ -21,19 +21,10 @@ local scripts = ini:r_string("common", "script", "") for script in scripts:gmatch("[^,]+") do local mod = require(script) - if type(mod) ~= "table" then - print("Error: " .. script .. " module is not a table") - return + if type(mod) == "table" then + local init = mod[script .. "_initialize"] + if init then + init() + end end - - local init = mod[script .. "_initialize"] - if not init then - goto next_script - end - - init() - - ::next_script:: end - -return {} diff --git a/gamedata/scripts/boot/function_object.lua b/gamedata/scripts/boot/function_object.lua index b5593f8bde..6fd6f1ea58 100644 --- a/gamedata/scripts/boot/function_object.lua +++ b/gamedata/scripts/boot/function_object.lua @@ -23,5 +23,3 @@ function function_object(str) return val end - -return {} diff --git a/gamedata/scripts/boot/sandbox.lua b/gamedata/scripts/boot/sandbox.lua index a8976d41ab..46ebf49736 100644 --- a/gamedata/scripts/boot/sandbox.lua +++ b/gamedata/scripts/boot/sandbox.lua @@ -16,5 +16,3 @@ for k,v in pairs(disabled) do _G[k][v[i]] = nil end end - -return {} From dce8d4fd2df1464bcf41a259f36e05a52e094b23 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 6 Jun 2025 00:29:38 +0100 Subject: [PATCH 50/76] Remove `_UNWIND` machinery, as it breaks consecutive error backtraces --- gamedata/scripts/init.lua | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index bae1d0988e..18ebcdc132 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -37,8 +37,6 @@ function print(...) end -- Set to true if we're unwinding the stack following an error -_UNWIND = false - --- Emplace Lua passthrough compiler function _COMPILER(src, namespace_name, script_name) print("* lua: loading " .. namespace_name) @@ -47,11 +45,8 @@ function _COMPILER(src, namespace_name, script_name) if not f then err = "init: error loading " .. namespace_name .. ":\n\n" .. err .. "\n" - if not _UNWIND then - err = debug.traceback(err, 2) - print(err) - _UNWIND = true - end + err = debug.traceback(err, 2) + print(err) error(err) end @@ -71,19 +66,15 @@ function _COMPILER(src, namespace_name, script_name) return function(...) local args = {...} + local _, out = xpcall( function() return mac(unpack(args)) end, function(err) - if not res then - if not _UNWIND then - err = debug.traceback(err, 2) - print(err) - _UNWIND = true - end - error(err) - end + err = debug.traceback(err, 2) + print(err) + error(err) end ) From 646b21842c9dab687f1a07351e7072c6e5cf4503 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 6 Jun 2025 00:30:53 +0100 Subject: [PATCH 51/76] Patch `load`, `loadfile`, proper handling of nameless wua modules --- gamedata/scripts/amx/wua/compile.lua | 79 ++++++++++++++++++++++++---- gamedata/scripts/boot/paths.lua | 3 ++ 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/gamedata/scripts/amx/wua/compile.lua b/gamedata/scripts/amx/wua/compile.lua index b2f8a21d51..86a44b3535 100644 --- a/gamedata/scripts/amx/wua/compile.lua +++ b/gamedata/scripts/amx/wua/compile.lua @@ -60,16 +60,23 @@ local G = setmetatable( local function handle_error(msg, namespace_name) return function(err) - package.loaded[namespace_name] = nil + if namespace_name then + package.loaded[namespace_name] = nil + end + err = "! " .. _PACKAGE .. ": " .. msg .. ":\n\n" .. err .. "\n" + err = debug.traceback(err, 2) + + print(err) error(err) end end -local function compile(src, namespace_name, script_name) +local compile +compile = function(src, namespace_name, script_name) local is_g = namespace_name == "_G" local mt = { @@ -84,13 +91,59 @@ local function compile(src, namespace_name, script_name) if not is_g then env._M = env + + -- If this is a named module, emplace relevant globals if namespace_name then env._PACKAGE = namespace_name env._FILE = script_name - env._COMPILER = _COMPILER - env.loadstring = _COMPILER env[namespace_name] = env end + + -- Redirect loadstring through wua + env.loadstring = compile + + -- Redirect load through wua + env.load = function(f, name) + local src = "" + + while true do + local part = f() + if part == nil then + break + elseif type(part == "string") then + if #part == 0 then + break + end + + src = src .. part + end + end + + return compile(src, name) + end + + -- Redirect loadfile through wua + env.loadfile = function(path) + local file = io.input(path) + local src = file:read("*a") + file:close() + return compile(src) + end + + -- Selectively patch the package module + -- to restore unconfigured Lua environment + local pkg = {} + for k,v in pairs(package) do + pkg[k] = v + end + pkg.path = _DEFAULT_PATH + pkg.loaders = { + _LOADERS.pre, + _LOADERS.lib, + _LOADERS.bin, + _LOADERS.aio, + } + env.package = pkg end if namespace_name then @@ -101,21 +154,29 @@ local function compile(src, namespace_name, script_name) local mod, err = loadstring(src, namespace_name) if not mod then - handle_error("error loading " .. namespace_name, namespace_name)(err) + handle_error("error loading " .. (namespace_name or "script"), namespace_name)(err) end local mac = setfenv(mod, env) return function() - package.loaded[namespace_name] = env - xpcall( + if namespace_name then + package.loaded[namespace_name] = env + end + + local _, out = xpcall( mac, handle_error( - "error evaluating " .. namespace_name, + "error evaluating " .. (namespace_name or "script"), namespace_name ) ) - return package.loaded[namespace_name] + + if namespace_name then + return package.loaded[namespace_name] + else + return out + end end end diff --git a/gamedata/scripts/boot/paths.lua b/gamedata/scripts/boot/paths.lua index bef874c083..c8bc20138d 100644 --- a/gamedata/scripts/boot/paths.lua +++ b/gamedata/scripts/boot/paths.lua @@ -1,5 +1,8 @@ _PACKAGE = "boot/paths" +-- Cache default path for later +_DEFAULT_PATH = package.path + -- Define load path registrator function _REGISTER_PATHS(...) local ps = {...} From 34a18ca41199da17cd6c28281ba25a882494c24a Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 6 Jun 2025 02:39:36 +0100 Subject: [PATCH 52/76] Don't try to unload console commands before running --- src/xrServerEntities/script_process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xrServerEntities/script_process.cpp b/src/xrServerEntities/script_process.cpp index 3459e66e27..ab1a016736 100644 --- a/src/xrServerEntities/script_process.cpp +++ b/src/xrServerEntities/script_process.cpp @@ -45,7 +45,7 @@ void CScriptProcess::run_scripts() S = xr_strdup(I); m_scripts_to_run.pop_back(); - if (reload) + if (!do_string && reload) ai().script_engine().unload_package(S); CScriptThread* script = xr_new(S, do_string); From 15e00b8d7aef4d25170cb0a29a2268a2fd7fd906 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 6 Jun 2025 02:40:54 +0100 Subject: [PATCH 53/76] Only populate `_M` for named modules --- gamedata/scripts/amx/wua/compile.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/gamedata/scripts/amx/wua/compile.lua b/gamedata/scripts/amx/wua/compile.lua index 86a44b3535..53c6fedce0 100644 --- a/gamedata/scripts/amx/wua/compile.lua +++ b/gamedata/scripts/amx/wua/compile.lua @@ -90,10 +90,9 @@ compile = function(src, namespace_name, script_name) local env = setmetatable({ _G = G }, mt) if not is_g then - env._M = env - -- If this is a named module, emplace relevant globals if namespace_name then + env._M = env env._PACKAGE = namespace_name env._FILE = script_name env[namespace_name] = env @@ -148,10 +147,9 @@ compile = function(src, namespace_name, script_name) if namespace_name then src = "local script_name = function() return _PACKAGE end " .. src + src = "local this = _M " .. src end - src = "local this = _M " .. src - local mod, err = loadstring(src, namespace_name) if not mod then handle_error("error loading " .. (namespace_name or "script"), namespace_name)(err) From cf76d3690df5892aa2814e97d2cce3df29ba08bb Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 6 Jun 2025 02:41:51 +0100 Subject: [PATCH 54/76] Replace old `eval_*` commands with `eval`, wraps `print` --- src/xrGame/console_commands.cpp | 58 +++------------------------------ 1 file changed, 5 insertions(+), 53 deletions(-) diff --git a/src/xrGame/console_commands.cpp b/src/xrGame/console_commands.cpp index 0a6a2ee572..efee2a6625 100644 --- a/src/xrGame/console_commands.cpp +++ b/src/xrGame/console_commands.cpp @@ -1723,8 +1723,6 @@ class CCC_ScriptCommand : public IConsole_Command return; } } - - ai().script_engine().print_output(ai().script_engine().lua(), *m_script_name, 0); } } //void Execute @@ -1749,55 +1747,15 @@ class CCC_ScriptCommand : public IConsole_Command } }; -class CCC_WuaCommand : public CCC_ScriptCommand -{ -public: - CCC_WuaCommand(LPCSTR N) : CCC_ScriptCommand(N) {} - - virtual void Execute(LPCSTR args) - { - string4096 S; - xr_sprintf(S, "--dialect wua %s", args); - CCC_ScriptCommand::Execute(S); - } -}; - -class CCC_LuaCommand : public CCC_ScriptCommand -{ -public: - CCC_LuaCommand(LPCSTR N) : CCC_ScriptCommand(N) {} - - virtual void Execute(LPCSTR args) - { - string4096 S; - xr_sprintf(S, "--dialect lua %s", args); - CCC_ScriptCommand::Execute(S); - } -}; - -class CCC_LispCommand : public CCC_ScriptCommand -{ -public: - CCC_LispCommand(LPCSTR N) : CCC_ScriptCommand(N) {} - - virtual void Execute(LPCSTR args) - { - string4096 S; - xr_sprintf(S, ";dialect lisp %s", args); - CCC_ScriptCommand::Execute(S); - } -}; - -// Unused for now, as console commands don't have a module-compatible script name -class CCC_LispMacroCommand : public CCC_ScriptCommand +class CCC_EvalCommand : public CCC_ScriptCommand { public: - CCC_LispMacroCommand(LPCSTR N) : CCC_ScriptCommand(N) {} + CCC_EvalCommand(LPCSTR N) : CCC_ScriptCommand(N) {} virtual void Execute(LPCSTR args) { string4096 S; - xr_sprintf(S, ";dialect lisp-macro %s", args); + xr_sprintf(S, "print(%s)", args); CCC_ScriptCommand::Execute(S); } }; @@ -2574,10 +2532,7 @@ void CCC_RegisterCommands() CMD3(CCC_Mask, "g_unlimitedammo", &psActorFlags, AF_UNLIMITEDAMMO); CMD1(CCC_Script, "run_script"); CMD1(CCC_ScriptCommand, "run_string"); - CMD1(CCC_WuaCommand, "eval_wua"); - CMD1(CCC_LuaCommand, "eval_lua"); - CMD1(CCC_LispCommand, "eval_lisp"); - //CMD1(CCC_LispMacroCommand, "eval_lisp_macro"); + CMD1(CCC_EvalCommand, "eval"); #endif // DEBUG /* AVO: changing restriction to -dbg key instead of DEBUG */ @@ -2590,10 +2545,7 @@ void CCC_RegisterCommands() CMD3(CCC_Mask, "g_unlimitedammo", &psActorFlags, AF_UNLIMITEDAMMO); CMD1(CCC_Script, "run_script"); CMD1(CCC_ScriptCommand, "run_string"); - CMD1(CCC_WuaCommand, "eval_wua"); - CMD1(CCC_LuaCommand, "eval_lua"); - CMD1(CCC_LispCommand, "eval_lisp"); - //CMD1(CCC_LispMacroCommand, "eval_lisp_macro"); + CMD1(CCC_EvalCommand, "eval"); //CMD3(CCC_Mask, "g_no_clip", &psActorFlags, AF_NO_CLIP); CMD1(CCC_PHGravity, "ph_gravity"); CMD3(CCC_Mask, "log_missing_ini", &FS.m_Flags, FS.flPrintLTX); From 11cdc346d3017a3f3fde9c54869d6721c8693505 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 8 Jun 2025 18:15:17 +0100 Subject: [PATCH 55/76] C++ Script Engine Cleanup - Move `CScriptProcess`, `CScriptThread` to Lua - Remove old Lua Studio hooks (LuaDkmDebugger covers this case directly in VS) - Cleanup respective `.cpp` / `.h` files - Privatize or remove remaining `CScriptEngine` members - Simplify public `CScriptEngine` load / run functions --- gamedata/scripts/amx/init.lua | 46 +- gamedata/scripts/amx/process.lua | 136 +++ gamedata/scripts/amx/processes.lua | 40 + gamedata/scripts/amx/wua/compile.lua | 6 +- gamedata/scripts/amx/wua/init.lua | 9 +- gamedata/scripts/init.lua | 2 +- src/xrGame/Level.cpp | 9 +- src/xrGame/Level_load.cpp | 15 - src/xrGame/ai_space.cpp | 5 - src/xrGame/console_commands.cpp | 38 +- src/xrGame/game_sv_base.cpp | 30 +- src/xrGame/script_engine_help.cpp | 300 ------ src/xrGame/ui/UIInventoryUpgradeWnd.cpp | 1 - src/xrGame/vs2022/xrGame.vcxproj | 41 +- src/xrGame/vs2022/xrGame.vcxproj.filters | 96 +- src/xrServerEntities/lua_studio.cpp | 854 ------------------ src/xrServerEntities/lua_studio.h | 154 ---- src/xrServerEntities/script_callStack.cpp | 71 -- src/xrServerEntities/script_callStack.h | 27 - src/xrServerEntities/script_debugger.cpp | 583 ------------ src/xrServerEntities/script_debugger.h | 110 --- .../script_debugger_messages.h | 107 --- .../script_debugger_threads.cpp | 72 -- .../script_debugger_threads.h | 25 - src/xrServerEntities/script_engine.cpp | 714 ++++----------- src/xrServerEntities/script_engine.h | 88 +- src/xrServerEntities/script_engine_inline.h | 41 - src/xrServerEntities/script_engine_script.cpp | 13 +- src/xrServerEntities/script_engine_space.h | 7 - src/xrServerEntities/script_lua_helper.cpp | 553 ------------ src/xrServerEntities/script_lua_helper.h | 52 -- src/xrServerEntities/script_process.cpp | 106 --- src/xrServerEntities/script_process.h | 90 +- src/xrServerEntities/script_process_inline.h | 19 - src/xrServerEntities/script_processes.h | 47 + src/xrServerEntities/script_stack_tracker.cpp | 92 -- src/xrServerEntities/script_stack_tracker.h | 33 - .../script_stack_tracker_inline.h | 9 - src/xrServerEntities/script_thread.cpp | 189 ---- src/xrServerEntities/script_thread.h | 44 - src/xrServerEntities/script_thread_inline.h | 29 - 41 files changed, 505 insertions(+), 4398 deletions(-) create mode 100644 gamedata/scripts/amx/process.lua create mode 100644 gamedata/scripts/amx/processes.lua delete mode 100644 src/xrGame/script_engine_help.cpp delete mode 100644 src/xrServerEntities/lua_studio.cpp delete mode 100644 src/xrServerEntities/lua_studio.h delete mode 100644 src/xrServerEntities/script_callStack.cpp delete mode 100644 src/xrServerEntities/script_callStack.h delete mode 100644 src/xrServerEntities/script_debugger.cpp delete mode 100644 src/xrServerEntities/script_debugger.h delete mode 100644 src/xrServerEntities/script_debugger_messages.h delete mode 100644 src/xrServerEntities/script_debugger_threads.cpp delete mode 100644 src/xrServerEntities/script_debugger_threads.h delete mode 100644 src/xrServerEntities/script_lua_helper.cpp delete mode 100644 src/xrServerEntities/script_lua_helper.h delete mode 100644 src/xrServerEntities/script_process.cpp delete mode 100644 src/xrServerEntities/script_process_inline.h create mode 100644 src/xrServerEntities/script_processes.h delete mode 100644 src/xrServerEntities/script_stack_tracker.cpp delete mode 100644 src/xrServerEntities/script_stack_tracker.h delete mode 100644 src/xrServerEntities/script_stack_tracker_inline.h delete mode 100644 src/xrServerEntities/script_thread.cpp delete mode 100644 src/xrServerEntities/script_thread.h delete mode 100644 src/xrServerEntities/script_thread_inline.h diff --git a/gamedata/scripts/amx/init.lua b/gamedata/scripts/amx/init.lua index e598b3fbb9..a30e176aa0 100644 --- a/gamedata/scripts/amx/init.lua +++ b/gamedata/scripts/amx/init.lua @@ -4,12 +4,12 @@ _FILE = "amx/init.lua" -- Initialize S.C.A.M. environment local scam = require("scam") --- Load unlocalize before wua to avoid circular referencing -require("amx/unlocalize") +-- Load amx/unlocalize before amx/lua to avoid circular referencing +require(_PACKAGE .. "/unlocalize") -- Setup wua as the default language scam.compiler.set_default_macro( - require("amx/wua").expand + require(_PACKAGE .. "/wua").expand ) -- Forcefully load _g.script @@ -17,7 +17,43 @@ package.loaded._G = nil require("_G") -- Register classes -require("amx/classes") +require(_PACKAGE .. "/classes") + +-- Setup script processes +local processes = require(_PACKAGE .. "/processes") + +-- Game process +local ini_script = ini_file("configs\\script.ltx") +print("ini_script:", ini_script) + +local game_scripts = "" +if ini_script:section_exist("single") + and ini_script:line_exist("single", "script") +then + print("reading from ini") + game_scripts = ini_script:r_string("single", "script"); +end + +print("game_scripts:", game_scripts) +processes:add("game", game_scripts) + +-- Level process +if level.present() then + local ini_level = ini_file( + string.format("levels\\%s\\level.ltx", level.name()) + ) + print("ini_level:", ini_level) + + local level_scripts = "" + if ini_level:section_exist("level_scripts") + and ini_level:line_exist("level_scripts", "script") + then + level_scripts = ini_level:r_string("level_scripts", "script"); + end + + processes:add("level", level_scripts) +end -- Run common scripts -require("amx/scripts") +require(_PACKAGE .. "/scripts") + diff --git a/gamedata/scripts/amx/process.lua b/gamedata/scripts/amx/process.lua new file mode 100644 index 0000000000..c350f485b1 --- /dev/null +++ b/gamedata/scripts/amx/process.lua @@ -0,0 +1,136 @@ +-- A collection of domain-scoped coroutines, +-- with time-sliced update logic to process one per frame. +-- +-- Formerly CScriptProcess and CScriptThread + +local DEBUG = false +local DISABLE_SCRIPTS = false + +ScriptProcess = {} + +function ScriptProcess.new(name, scripts) + if DEBUG then + print("* Initializing " .. name .. " script process") + end + + local out = setmetatable( + { + name = name, + coroutines = {}, + iterator = 0, + }, + { + __index = ScriptProcess, + __tostring = function(self) + return string.format( + "ScriptProcess {" + .. "\n name = " .. self.name + .. "\n coroutines = " .. tostring(self.coroutines) + .. "\n iterator = " .. tostring(self.iterator) + .. "\n}" + ) + end + } + ) + + for script in scripts:gmatch("[^;]+") do + out:add_script(script) + end + + return out +end + +function ScriptProcess:update() + if DISABLE_SCRIPTS then + while #self.coroutines > 0 do + table.remove(self.coroutines) + end + end + + if #self.coroutines == 0 then + self.iterator = 0 + return + end + + local co = self.coroutines[self.iterator + 1] + + if not co then + return + end + + local res, err = coroutine.resume(co) + + if res then + self.iterator = (self.iterator + 1) % #self.coroutines + else + if err ~= "cannot resume dead coroutine" then + print("! ScriptProcess: " .. err) + end + table.remove(self.coroutines, self.iterator + 1) + end +end + +-- Add a raw coroutine to the script process +function ScriptProcess:add_coroutine(co) + if DEBUG then + print( + "* Adding coroutine " .. tostring(co) + .. " to " .. self.name + .. " script process" + ) + end + + table.insert(self.coroutines, co) +end + +-- Add a function to the script process as a coroutine +function ScriptProcess:add_function(f) + if DEBUG then + print( + "* Adding function " .. tostring(f) + .. " to " .. self.name + .. " script process" + ) + end + + self:add_coroutine(coroutine.create(f)) +end + +function ScriptProcess:add_script(script_name, reload) + if DEBUG then + print("* Adding script ".. script_name .. " to " .. self.name .. " script process") + end + + self:add_function( + function() + if reload then + package.loaded[script_name] = nil + end + + local res = require(script_name) + + if type(res) ~= "table" then + return + end + + local main = res.main + if type(main) ~= "function" then + return + end + + main() + end + ) +end + +function ScriptProcess:add_string(src) + if DEBUG then + print( + "* Adding string ".. src .. " to " .. self.name .. " script process" + ) + end + + self:add_function(_COMPILER(src, nil, "console command")) +end + +return ScriptProcess diff --git a/gamedata/scripts/amx/processes.lua b/gamedata/scripts/amx/processes.lua new file mode 100644 index 0000000000..5384e2290d --- /dev/null +++ b/gamedata/scripts/amx/processes.lua @@ -0,0 +1,40 @@ +-- Engine interface to domain-scoped coroutines +-- Formerly part of CScriptManager + +local ScriptProcess = require("amx/process") + +local ScriptProcesses = {} + +function ScriptProcesses.new() + return setmetatable( + { + processes = {} + }, + { + __index = ScriptProcesses, + __tostring = function(self) + return "ScriptProcesses {" + .. "\n processes: " .. tostring(self.processes) + .. "\n}" + end + } + ) +end + +function ScriptProcesses:add(name, scripts) + self.processes[name] = ScriptProcess.new(name, scripts) +end + +function ScriptProcesses:remove(name) + self.processes[name] = nil +end + +function ScriptProcesses:has(name) + return self.processes[name] ~= nil +end + +function ScriptProcesses:get(name) + return self.processes[name] +end + +return ScriptProcesses.new() diff --git a/gamedata/scripts/amx/wua/compile.lua b/gamedata/scripts/amx/wua/compile.lua index 53c6fedce0..267e54f970 100644 --- a/gamedata/scripts/amx/wua/compile.lua +++ b/gamedata/scripts/amx/wua/compile.lua @@ -98,10 +98,10 @@ compile = function(src, namespace_name, script_name) env[namespace_name] = env end - -- Redirect loadstring through wua + -- Redirect loadstring through this compiler env.loadstring = compile - -- Redirect load through wua + -- Redirect load through this compiler env.load = function(f, name) local src = "" @@ -121,7 +121,7 @@ compile = function(src, namespace_name, script_name) return compile(src, name) end - -- Redirect loadfile through wua + -- Redirect loadfile through this compiler env.loadfile = function(path) local file = io.input(path) local src = file:read("*a") diff --git a/gamedata/scripts/amx/wua/init.lua b/gamedata/scripts/amx/wua/init.lua index 0fb374969d..6a091e7437 100644 --- a/gamedata/scripts/amx/wua/init.lua +++ b/gamedata/scripts/amx/wua/init.lua @@ -1,8 +1,11 @@ -local unlocalize = require("amx/wua/unlocalize").unlocalize -local compile = require("amx/wua/compile").compile +local unlocalize = require(_PACKAGE .. "/unlocalize").unlocalize +local compile = require(_PACKAGE .. "/compile").compile local function expand(src, namespace_name, script_name) - print("* " .. _PACKAGE .. ": expanding", namespace_name) + if namespace_name then + print("* " .. _PACKAGE .. ": expanding " .. namespace_name) + end + return compile( unlocalize(src, namespace_name), namespace_name, diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index 18ebcdc132..cdf80e856f 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -112,5 +112,5 @@ package.loaders = { _LOADERS.init } --- Initialize environment via the boot module require("boot") --- Pass control to modded exes entrypoint +-- Pass control to xray entrypoint require("amx") diff --git a/src/xrGame/Level.cpp b/src/xrGame/Level.cpp index 869b04bc93..bec44df7b8 100644 --- a/src/xrGame/Level.cpp +++ b/src/xrGame/Level.cpp @@ -15,7 +15,6 @@ #include "ShootingObject.h" #include "GameTaskManager.h" #include "Level_Bullet_Manager.h" -#include "script_process.h" #include "script_engine.h" #include "script_engine_space.h" #include "team_base_zone.h" @@ -253,8 +252,6 @@ CLevel::~CLevel() xr_delete(m_autosave_manager); xr_delete(m_debug_renderer); delete_data(m_debug_render_queue); - if (!g_dedicated_server) - ai().script_engine().remove_script_process(ScriptEngine::eScriptProcessorLevel); xr_delete(game); xr_delete(game_events); xr_delete(m_pBulletManager); @@ -729,8 +726,10 @@ void CLevel::OnFrame() #endif g_pGamePersistent->Environment().SetGameTime(GetEnvironmentGameDayTimeSec(), game->GetEnvironmentGameTimeFactor()); - if (!g_dedicated_server) - ai().script_engine().script_process(ScriptEngine::eScriptProcessorLevel)->update(); + + if (!g_dedicated_server && ai().script_engine().script_processes().has("level")) + ai().script_engine().script_processes().get("level").update(); + m_ph_commander->update(); m_ph_commander_scripts->update(); Device.Statistic->TEST0.Begin(); diff --git a/src/xrGame/Level_load.cpp b/src/xrGame/Level_load.cpp index bccd55c9bd..f9153acaaf 100644 --- a/src/xrGame/Level_load.cpp +++ b/src/xrGame/Level_load.cpp @@ -2,7 +2,6 @@ #include "LevelGameDef.h" #include "ai_space.h" #include "ParticlesObject.h" -#include "script_process.h" #include "script_engine.h" #include "script_engine_space.h" #include "level.h" @@ -161,20 +160,6 @@ bool CLevel::Load_GameSpecific_After() } } - if (!g_dedicated_server) - { - // loading scripts - ai().script_engine().remove_script_process(ScriptEngine::eScriptProcessorLevel); - - if (pLevel->section_exist("level_scripts") && pLevel->line_exist("level_scripts", "script")) - ai().script_engine().add_script_process(ScriptEngine::eScriptProcessorLevel, - xr_new( - "level", pLevel->r_string("level_scripts", "script"))); - else - ai().script_engine().add_script_process(ScriptEngine::eScriptProcessorLevel, - xr_new("level", "")); - } - BlockCheatLoad(); g_pGamePersistent->Environment().SetGameTime(GetEnvironmentGameDayTimeSec(), game->GetEnvironmentGameTimeFactor()); diff --git a/src/xrGame/ai_space.cpp b/src/xrGame/ai_space.cpp index b0022b3eae..d35473ee7f 100644 --- a/src/xrGame/ai_space.cpp +++ b/src/xrGame/ai_space.cpp @@ -67,11 +67,6 @@ void CAI_Space::init() VERIFY(!m_script_engine); m_script_engine = xr_new(); script_engine().init(); - -#ifndef NO_SINGLE - extern string4096 g_ca_stdout; - setvbuf(stderr, g_ca_stdout,_IOFBF, sizeof(g_ca_stdout)); -#endif //#ifndef NO_SINGLE } CAI_Space::~CAI_Space() diff --git a/src/xrGame/console_commands.cpp b/src/xrGame/console_commands.cpp index efee2a6625..14b457d5a6 100644 --- a/src/xrGame/console_commands.cpp +++ b/src/xrGame/console_commands.cpp @@ -7,7 +7,6 @@ #include "xrMessages.h" #include "xrserver.h" #include "level.h" -#include "script_debugger.h" #include "ai_debug.h" #include "alife_simulator.h" #include "game_cl_base.h" @@ -20,7 +19,6 @@ #include "customzone.h" #include "script_engine.h" #include "script_engine_space.h" -#include "script_process.h" #include "xrServer_Objects.h" #include "ui/UIMainIngameWnd.h" //#include "../xrphysics/PhysicsGamePars.h" @@ -1673,8 +1671,8 @@ class CCC_Script : public IConsole_Command P->m_Flags.set(FS_Path::flNeedRescan, TRUE); FS.rescan_pathes(); // run script - if (ai().script_engine().script_process(ScriptEngine::eScriptProcessorLevel)) - ai().script_engine().script_process(ScriptEngine::eScriptProcessorLevel)->add_script(args, false, true); + if (ai().script_engine().script_processes().has("level")) + ai().script_engine().script_processes().get("level").add_script(args, true); } } @@ -1700,30 +1698,22 @@ class CCC_ScriptCommand : public IConsole_Command virtual void Execute(LPCSTR args) { + // Early out if no arguments were provided if (!xr_strlen(args)) - Log("* Specify string to run!"); - else { - if (ai().script_engine().script_process(ScriptEngine::eScriptProcessorLevel)) - { - ai().script_engine().script_process(ScriptEngine::eScriptProcessorLevel)->add_script(args, true, true); - return; - } + Log("* Specify string to run!"); + return; + } - string4096 S; - shared_str m_script_name = "console command"; - xr_sprintf(S, "%s\n", args); - if (0 == ai().script_engine().load_buffer(ai().script_engine().lua(), S, xr_strlen(S), *m_script_name)) - { - int l_iErrorCode = lua_pcall(ai().script_engine().lua(), 0, 0, 0); - if (l_iErrorCode) - { - ai().script_engine().print_output(ai().script_engine().lua(), *m_script_name, l_iErrorCode); - ai().script_engine().on_error(ai().script_engine().lua()); - return; - } - } + // If we have a level script processor, use it to run the command as a coroutine + if (ai().script_engine().script_processes().has("level")) + { + ai().script_engine().script_processes().get("level").add_string(args); + return; } + + // Otherwise, + ai().script_engine().do_string(args, "console command"); } //void Execute virtual void Status(TStatus& S) diff --git a/src/xrGame/game_sv_base.cpp b/src/xrGame/game_sv_base.cpp index 6d52f1eba2..b3fae4a4b5 100644 --- a/src/xrGame/game_sv_base.cpp +++ b/src/xrGame/game_sv_base.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" #include "LevelGameDef.h" -#include "script_process.h" #include "xrServer_Objects_ALife_Monsters.h" #include "script_engine.h" #include "script_engine_space.h" @@ -448,27 +447,6 @@ void game_sv_GameState::Create(shared_str& options) FS.r_close(F); } - if (!g_dedicated_server) - { - // loading scripts - ai().script_engine().remove_script_process(ScriptEngine::eScriptProcessorGame); - string_path S; - FS.update_path(S, "$game_config$", "script.ltx"); - CInifile* l_tpIniFile = xr_new(S); - R_ASSERT(l_tpIniFile); - - if (l_tpIniFile->section_exist(type_name())) - if (l_tpIniFile->r_string(type_name(), "script")) - ai().script_engine().add_script_process(ScriptEngine::eScriptProcessorGame, - xr_new( - "game", l_tpIniFile->r_string(type_name(), "script"))); - else - ai().script_engine().add_script_process(ScriptEngine::eScriptProcessorGame, - xr_new("game", "")); - - xr_delete(l_tpIniFile); - } - //--------------------------------------------------------------------- ConsoleCommands_Create(); //--------------------------------------------------------------------- @@ -669,11 +647,9 @@ void game_sv_GameState::Update() if (!g_dedicated_server) { - if (Level().game) + if (Level().game && ai().script_engine().script_processes().has("game")) { - CScriptProcess* script_process = ai().script_engine().script_process(ScriptEngine::eScriptProcessorGame); - if (script_process) - script_process->update(); + ai().script_engine().script_processes().get("game").update(); } } } @@ -700,7 +676,7 @@ game_sv_GameState::game_sv_GameState() game_sv_GameState::~game_sv_GameState() { if (!g_dedicated_server) - ai().script_engine().remove_script_process(ScriptEngine::eScriptProcessorGame); + ai().script_engine().script_processes().remove("game"); xr_delete(m_event_queue); SaveMapList(); diff --git a/src/xrGame/script_engine_help.cpp b/src/xrGame/script_engine_help.cpp deleted file mode 100644 index 5cd80d8a67..0000000000 --- a/src/xrGame/script_engine_help.cpp +++ /dev/null @@ -1,300 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_engine_help.cpp -// Created : 01.04.2004 -// Modified : 01.04.2004 -// Author : Dmitriy Iassenev -// Description : Script Engine help -//////////////////////////////////////////////////////////////////////////// - -#include "pch_script.h" - -#ifdef DEBUG - -#ifndef BOOST_NO_STRINGSTREAM -//# include -#else -//# include -#endif - -xr_string to_string (luabind::object const& o) -{ - using namespace luabind; - if (o.type() == LUA_TSTRING) return object_cast(o).c_str(); - lua_State* L = o.lua_state(); - LUABIND_CHECK_STACK(L); - - if (o.type() == LUA_TNUMBER) - { - char buffer[_CVTBUFSIZE]; - _gcvt_s( buffer, object_cast(o), 16); - return buffer; - } - - return xr_string("<") + lua_typename(L, o.type()) + ">"; -} - -void strreplaceall (xr_string &str, LPCSTR S, LPCSTR N) -{ - LPCSTR A; - int S_len = xr_strlen(S); - while ((A = strstr(str.c_str(),S)) != 0) - str.replace(A - str.c_str(),S_len,N); -} - -xr_string &process_signature (xr_string &str) -{ - strreplaceall (str,"custom [",""); - strreplaceall (str,"]",""); - strreplaceall (str,"float","number"); - strreplaceall (str,"lua_State*, ",""); - strreplaceall (str," ,lua_State*",""); - return (str); -} - -xr_string member_to_string (luabind::object const& e, LPCSTR function_signature) -{ -#if 1 || !defined(LUABIND_NO_ERROR_CHECKING) - using namespace luabind; - lua_State* L = e.lua_state(); - LUABIND_CHECK_STACK(L); - - if (e.type() == LUA_TFUNCTION) - { - e.pushvalue(); - detail::stack_pop p(L, 1); - - { - if (lua_getupvalue(L, -1, 3) == 0) return to_string(e); - detail::stack_pop p2(L, 1); - if (lua_touserdata(L, -1) != reinterpret_cast(0x1337)) return to_string(e); - } - -// #ifdef BOOST_NO_STRINGSTREAM -// std::strstream s; -// #else -// std::stringstream s; -// #endif - xr_string s = ""; - - { - lua_getupvalue(L, -1, 2); - detail::stack_pop p2(L, 1); - } - - { - lua_getupvalue(L, -1, 1); - detail::stack_pop p2(L, 1); - detail::method_rep* m = static_cast(lua_touserdata(L, -1)); - - for (std::vector::const_iterator i = m->overloads().begin(); - i != m->overloads().end(); ++i) - { - luabind::internal_string str; - i->get_signature(L, str); - if (i != m->overloads().begin()) - s += "\n"; - - xr_string xr_str(str.c_str()); - s += function_signature + process_signature(xr_str) + ";"; - } - } -#ifdef BOOST_NO_STRINGSTREAM - s += "\n";// std::ends; -#endif - return s; - } - - return to_string(e); -#else - return ""; -#endif -} - -void print_class (lua_State *L, luabind::detail::class_rep *crep) -{ - xr_string S; - // print class and bases - { - S = (crep->get_class_type() != luabind::detail::class_rep::cpp_class) ? "LUA class " : "C++ class "; - S.append (crep->name()); - typedef luabind::internal_vector BASES; - const BASES &bases = crep->bases(); - BASES::const_iterator I = bases.begin(), B = I; - BASES::const_iterator E = bases.end(); - if (B != E) - S.append (" : "); - for ( ; I != E; ++I) { - if (I != B) - S.append(","); - S.append ((*I).base->name()); - } - Msg ("%s {",S.c_str()); - } - // print class constants - { - const luabind::detail::class_rep::STATIC_CONSTANTS &constants = crep->static_constants(); - luabind::detail::class_rep::STATIC_CONSTANTS::const_iterator I = constants.begin(); - luabind::detail::class_rep::STATIC_CONSTANTS::const_iterator E = constants.end(); - for ( ; I != E; ++I) -#ifndef USE_NATIVE_LUA_STRINGS - Msg (" const %s = %d;",(*I).first,(*I).second); -#else - Msg (" const %s = %d;",getstr((*I).first.m_object),(*I).second); -#endif - if (!constants.empty()) - Msg (" "); - } - // print class properties - { -#ifndef USE_NATIVE_LUA_STRINGS - typedef luabind::internal_map PROPERTIES; -#else - typedef luabind::detail::class_rep::callback_map PROPERTIES; -#endif - const PROPERTIES &properties = crep->properties(); - PROPERTIES::const_iterator I = properties.begin(); - PROPERTIES::const_iterator E = properties.end(); - for ( ; I != E; ++I) -#ifndef USE_NATIVE_LUA_STRINGS - Msg (" property %s;",(*I).first); -#else - Msg (" property %s;",getstr((*I).first.m_object)); -#endif - if (!properties.empty()) - Msg (" "); - } - // print class constructors - { - typedef luabind::internal_vector Constructors; - const Constructors &constructors = crep->constructors().overloads; - Constructors::const_iterator I = constructors.begin(); - Constructors::const_iterator E = constructors.end(); - for ( ; I != E; ++I) { - luabind::internal_string luaS; - (*I).get_signature(L,luaS); - xr_string S(luaS.c_str()); - strreplaceall (S,"custom [",""); - strreplaceall (S,"]",""); - strreplaceall (S,"float","number"); - strreplaceall (S,"lua_State*, ",""); - strreplaceall (S," ,lua_State*",""); - Msg (" %s %s;",crep->name(),S.c_str()); - } - if (!constructors.empty()) - Msg (" "); - } - // print class methods - { - crep->get_table (L); - luabind::object table(L); - table.set (); - for (luabind::object::iterator i = table.begin(); i != table.end(); ++i) { - luabind::object object = *i; - xr_string S; - S = " function "; - S.append (to_string(i.key()).c_str()); - - strreplaceall (S,"function __add","operator +"); - strreplaceall (S,"function __sub","operator -"); - strreplaceall (S,"function __mul","operator *"); - strreplaceall (S,"function __div","operator /"); - strreplaceall (S,"function __pow","operator ^"); - strreplaceall (S,"function __lt","operator <"); - strreplaceall (S,"function __le","operator <="); - strreplaceall (S,"function __gt","operator >"); - strreplaceall (S,"function __ge","operator >="); - strreplaceall (S,"function __eq","operator =="); - Msg ("%s",member_to_string(object,S.c_str()).c_str()); - } - } - Msg ("};\n"); -} - -void print_free_functions (lua_State *L, const luabind::object &object, LPCSTR header, const xr_string &indent) -{ - u32 count = 0; - luabind::object::iterator I = object.begin(); - luabind::object::iterator E = object.end(); - for ( ; I != E; ++I) { - if ((*I).type() != LUA_TFUNCTION) - continue; - (*I).pushvalue(); - luabind::detail::free_functions::function_rep* rep = 0; - if (lua_iscfunction(L, -1)) - { - if (lua_getupvalue(L, -1, 2) != 0) - { - // check the magic number that identifies luabind's functions - if (lua_touserdata(L, -1) == (void*)0x1337) - { - if (lua_getupvalue(L, -2, 1) != 0) - { - if (!count) - Msg("\n%snamespace %s {",indent.c_str(),header); - ++count; - rep = static_cast(lua_touserdata(L, -1)); - std::vector::const_iterator i = rep->overloads().begin(); - std::vector::const_iterator e = rep->overloads().end(); - for ( ; i != e; ++i) { - luabind::internal_string luaS; - (*i).get_signature(L,luaS); - xr_string S(luaS.c_str()); - Msg(" %sfunction %s%s;",indent.c_str(),rep->name(),process_signature(S).c_str()); - } - lua_pop(L, 1); - } - } - lua_pop(L, 1); - } - } - lua_pop(L, 1); - } - { - xr_string _indent = indent; - _indent.append (" "); - object.pushvalue(); - lua_pushnil (L); - while (lua_next(L, -2) != 0) { - if (lua_type(L, -1) == LUA_TTABLE) { - LPCSTR S = lua_tostring(L, -2); - if (xr_strcmp("_G",S) && xr_strcmp("package",S)) { - luabind::object object(L); - object.set (); - if (!xr_strcmp("security",S)) { - S = S; - } - print_free_functions(L,object,S,_indent); - } - } -#pragma todo("Dima to Dima : Remove this hack if find out why") - if (lua_isnumber(L,-2)) { - lua_pop(L,1); - lua_pop(L,1); - break; - } - lua_pop (L, 1); - } - } - if (count) - Msg("%s};",indent.c_str()); -} - -void print_help (lua_State *L) -{ - Msg ("\nList of the classes exported to LUA\n"); - luabind::detail::class_registry::get_registry(L)->iterate_classes(L,&print_class); - Msg ("End of list of the classes exported to LUA\n"); - Msg ("\nList of the namespaces exported to LUA\n"); - print_free_functions(L,luabind::get_globals(L),"",""); - Msg ("End of list of the namespaces exported to LUA\n"); -} -#else -void print_help(lua_State* L) -{ - Msg("! Release build doesn't support lua-help :("); -} -#endif - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// diff --git a/src/xrGame/ui/UIInventoryUpgradeWnd.cpp b/src/xrGame/ui/UIInventoryUpgradeWnd.cpp index 2f02649a81..8be61279fd 100644 --- a/src/xrGame/ui/UIInventoryUpgradeWnd.cpp +++ b/src/xrGame/ui/UIInventoryUpgradeWnd.cpp @@ -15,7 +15,6 @@ #include "../string_table.h" #include "../actor.h" -#include "../../xrServerEntities/script_process.h" #include "../inventory.h" #include "ai_space.h" diff --git a/src/xrGame/vs2022/xrGame.vcxproj b/src/xrGame/vs2022/xrGame.vcxproj index d9830106f2..cd60a00d87 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj +++ b/src/xrGame/vs2022/xrGame.vcxproj @@ -307,8 +307,6 @@ - - @@ -333,10 +331,6 @@ - - - - @@ -349,21 +343,15 @@ - - + - - - - - @@ -1935,10 +1923,6 @@ - - pch_script.h - $(IntDir)$(ProjectName)_script.pch - pch_script.h @@ -1958,9 +1942,6 @@ $(IntDir)$(ProjectName)_script.pch - - - pch_script.h $(IntDir)$(ProjectName)_script.pch @@ -1994,18 +1975,10 @@ pch_script.h $(IntDir)$(ProjectName)_script.pch - - pch_script.h - $(IntDir)$(ProjectName)_script.pch - pch_script.h $(IntDir)$(ProjectName)_script.pch - - pch_script.h - $(IntDir)$(ProjectName)_script.pch - pch_script.h $(IntDir)$(ProjectName)_script.pch @@ -2018,16 +1991,8 @@ pch_script.h $(IntDir)$(ProjectName)_script.pch - - pch_script.h - $(IntDir)$(ProjectName)_script.pch - - - pch_script.h - $(IntDir)$(ProjectName)_script.pch - pch_script.h @@ -3343,10 +3308,6 @@ pch_script.h $(IntDir)$(ProjectName)_script.pch - - pch_script.h - $(IntDir)$(ProjectName)_script.pch - pch_script.h $(IntDir)$(ProjectName)_script.pch diff --git a/src/xrGame/vs2022/xrGame.vcxproj.filters b/src/xrGame/vs2022/xrGame.vcxproj.filters index a3203bac36..3505cb374b 100644 --- a/src/xrGame/vs2022/xrGame.vcxproj.filters +++ b/src/xrGame/vs2022/xrGame.vcxproj.filters @@ -1342,27 +1342,12 @@ {7461340c-f13a-4ba4-a432-e8aeca7393cf} - - {a1df39ed-f84f-4b5e-9aa6-7310378e3614} - {c64d88d0-2cc0-440e-bed2-367ebd29671c} - - {2bfb6ae4-1fec-4054-bc45-5a6ed56f73ed} - {8ce0ad22-cee7-419e-b54c-65da67769b68} - - {0126fd57-f558-4910-ad5e-f63e20a12940} - - - {2f517721-a4fd-4e92-aee2-7c703d7b2abe} - - - {91189d3e-089f-4e5c-a9f4-b41fb1136e69} - {a568c889-96b8-41c7-9bee-0d4f24d1a47e} @@ -5196,57 +5181,12 @@ AI\AScript\ScriptClasses\ScriptSound - - AI\AScript\ScriptDebugger - - - AI\AScript\ScriptDebugger - - - AI\AScript\ScriptDebugger - - - AI\AScript\ScriptDebugger - - - AI\AScript\ScriptDebugger - - - AI\AScript\ScriptDebugger - AI\AScript\ScriptEngine - - AI\AScript\ScriptEngine - AI\AScript\ScriptEngine - - AI\AScript\ScriptProcess - - - AI\AScript\ScriptProcess - - - AI\AScript\ScriptStorage - - - AI\AScript\ScriptThread - - - AI\AScript\ScriptThread - - - AI\AScript\ScriptThread\ScriptStackTracker - - - AI\AScript\ScriptThread\ScriptStackTracker - - - AI\AScript\lua_studio - AI\ASound @@ -7392,6 +7332,15 @@ AI\AScript\ScriptStorage + + AI\AScript\ScriptEngine + + + AI\AScript\ScriptEngine + + + AI\AScript\ScriptEngine + @@ -8786,42 +8735,15 @@ AI\AScript\ScriptClasses\ScriptSound - - AI\AScript\ScriptDebugger - - - AI\AScript\ScriptDebugger - - - AI\AScript\ScriptDebugger - - - AI\AScript\ScriptDebugger - AI\AScript\ScriptEngine AI\AScript\ScriptEngine - - AI\AScript\ScriptEngine - AI\AScript\ScriptEngine - - AI\AScript\ScriptProcess - - - AI\AScript\ScriptThread - - - AI\AScript\ScriptThread\ScriptStackTracker - - - AI\AScript\lua_studio - AI\ASound diff --git a/src/xrServerEntities/lua_studio.cpp b/src/xrServerEntities/lua_studio.cpp deleted file mode 100644 index 8f3a7a60d4..0000000000 --- a/src/xrServerEntities/lua_studio.cpp +++ /dev/null @@ -1,854 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : lua_studio.cpp -// Created : 21.08.2008 -// Modified : 21.08.2008 -// Author : Dmitriy Iassenev -// Description : lua studio engine class (copied from the lua studio SDK) -//////////////////////////////////////////////////////////////////////////// - -#include "pch_script.h" -#include "lua_studio.h" - -#define pstr LPSTR -#define pcstr LPCSTR -#define pcvoid void const* -#define sz_cmp xr_strcmp -#define vector_class luabind::internal_vector -#define engine lua_studio_engine - -inline pstr sz_cpy(pstr destination, const u32& size, pcstr source) -{ - xr_strcpy(destination, size, source); - return (destination); -} - -template -inline pstr sz_cpy(char (&destination)[size], pcstr source) -{ - xr_strcpy(destination, size, source); - return (destination); -} - -inline pstr sz_cat(pstr destination, const u32& size, pcstr source) -{ - xr_strcat(destination, size, source); - return (destination); -} - -template -inline pstr sz_cat(char (&destination)[size], pcstr source) -{ - xr_strcat(destination, size, source); - return (destination); -} - -inline u32 sz_len(pcstr string) -{ - return ((u32)xr_strlen(string)); -} - -//////////////////////////////////////////////////////////////////////////// - -int engine::luaL_loadstring(lua_State* L, const char* s) -{ - return (::luaL_loadstring(L, s)); -} - -int engine::luaL_newmetatable(lua_State* L, const char* tname) -{ - return (::luaL_newmetatable(L, tname)); -} - -void engine::lua_createtable(lua_State* L, int narray, int nrec) -{ - return (::lua_createtable(L, narray, nrec)); -} - -int engine::lua_sethook(lua_State* L, lua_Hook func, lua_mask_type mask, int count) -{ - return (::lua_sethook(L, func, mask, count)); -} - -engine::lua_Hook engine::lua_gethook(lua_State* L) -{ - return (::lua_gethook(L)); -} - -int engine::lua_getinfo(lua_State* L, const char* what, lua_Debug* ar) -{ - return (::lua_getinfo(L, what, ar)); -} - -void engine::lua_getfenv(lua_State* L, int idx) -{ - return (::lua_getfenv(L, idx)); -} - -void engine::lua_getfield(lua_State* L, int idx, const char* k) -{ - return (::lua_getfield(L, idx, k)); -} - -char const* engine::lua_getlocal(lua_State* L, const lua_Debug* ar, int n) -{ - return (::lua_getlocal(L, ar, n)); -} - -void engine::lua_gettable(lua_State* L, int idx) -{ - return (::lua_gettable(L, idx)); -} - -int engine::lua_getstack(lua_State* L, int level, lua_Debug* ar) -{ - return (::lua_getstack(L, level, ar)); -} - -int engine::lua_gettop(lua_State* L) -{ - return (::lua_gettop(L)); -} - -char const* engine::lua_getupvalue(lua_State* L, int funcindex, int n) -{ - return (::lua_getupvalue(L, funcindex, n)); -} - -int engine::lua_iscfunction(lua_State* L, int idx) -{ - return (::lua_iscfunction(L, idx)); -} - -int engine::lua_next(lua_State* L, int idx) -{ - return (::lua_next(L, idx)); -} - -int engine::lua_pcall(lua_State* L, int nargs, int nresults, int errfunc) -{ - return (::lua_pcall(L, nargs, nresults, errfunc)); -} - -void engine::lua_pushcclosure(lua_State* L, lua_CFunction fn, int n) -{ - return (::lua_pushcclosure(L, fn, n)); -} - -void engine::lua_pushnil(lua_State* L) -{ - return (::lua_pushnil(L)); -} - -void engine::lua_pushstring(lua_State* L, const char* s) -{ - return (::lua_pushstring(L, s)); -} - -void engine::lua_pushvalue(lua_State* L, int idx) -{ - return (::lua_pushvalue(L, idx)); -} - -void engine::lua_pushnumber(lua_State* L, lua_Number idx) -{ - return (::lua_pushnumber(L, idx)); -} - -void engine::lua_remove(lua_State* L, int idx) -{ - return (::lua_remove(L, idx)); -} - -void engine::lua_replace(lua_State* L, int idx) -{ - return (::lua_replace(L, idx)); -} - -int engine::lua_setfenv(lua_State* L, int idx) -{ - return (::lua_setfenv(L, idx)); -} - -int engine::lua_setmetatable(lua_State* L, int objindex) -{ - return (::lua_setmetatable(L, objindex)); -} - -void engine::lua_settable(lua_State* L, int idx) -{ - return (::lua_settable(L, idx)); -} - -void engine::lua_settop(lua_State* L, int idx) -{ - return (::lua_settop(L, idx)); -} - -int engine::lua_toboolean(lua_State* L, int idx) -{ - return (::lua_toboolean(L, idx)); -} - -engine::lua_Integer engine::lua_tointeger(lua_State* L, int idx) -{ - return (::lua_tointeger(L, idx)); -} - -char const* engine::lua_tolstring(lua_State* L, int idx, size_t* len) -{ - return (::lua_tolstring(L, idx, len)); -} - -lua_Number engine::lua_tonumber(lua_State* L, int idx) -{ - return (::lua_tonumber(L, idx)); -} - -const void* engine::lua_topointer(lua_State* L, int idx) -{ - return (::lua_topointer(L, idx)); -} - -bool engine::lua_isnumber(lua_State* L, int idx) -{ - return (!!::lua_isnumber(L, idx)); -} - -int engine::lua_type(lua_State* L, int idx) -{ - return (::lua_type(L, idx)); -} - -char const* engine::lua_typename(lua_State* L, int t) -{ - return (::lua_typename(L, t)); -} - -lua_Debug* engine::lua_debug_create() -{ - VERIFY(m_instance_count < sizeof(m_instances)/sizeof(m_instances[0])); - return (&m_instances[m_instance_count++]); -} - -void engine::lua_debug_destroy(lua_Debug*& instance) -{ - instance = 0; - --m_instance_count; -} - -char const* engine::lua_debug_get_name(lua_Debug& instance) -{ - return (instance.name); -} - -char const* engine::lua_debug_get_source(lua_Debug& instance) -{ - return (instance.source); -} - -char const* engine::lua_debug_get_short_source(lua_Debug& instance) -{ - return (instance.short_src); -} - -int engine::lua_debug_get_current_line(lua_Debug& instance) -{ - return (instance.currentline); -} - -void engine::log(log_message_types const message_type, char const* const message) -{ -} - -char* engine::class_name(char* const buffer, unsigned int const size, luabind::detail::class_rep& class_rep) -{ - switch (class_rep.get_class_type()) - { - case luabind::detail::class_rep::cpp_class: - { - return (sz_cpy(buffer, size, "C++ class")); - } - case luabind::detail::class_rep::lua_class: - { - return (sz_cpy(buffer, size, "Lua class")); - } - default: NODEFAULT; - } -#ifdef DEBUG - return (sz_cpy(buffer, size, "unknown user data")); -#endif // #ifdef DEBUG -} - -void engine::type_convert_class(char* const buffer, unsigned int const size, lua_State* state, int index) -{ - luabind::detail::object_rep* object = luabind::detail::is_class_object(state, index); - VERIFY2(object, "invalid object userdata"); - - sz_cpy(buffer, size, ""); - sz_cat(buffer, size, "class \""); - sz_cat(buffer, size, object->crep()->name()); - sz_cat(buffer, size, "\" ("); - - u32 const length = sz_len(buffer); - class_name(buffer + length, size - length, *object->crep()); - - sz_cat(buffer, size, " instance)"); -} - -static bool is_luabind_class(lua_State* state, int const index) -{ - luabind::detail::class_rep* class_rep = static_cast(lua_touserdata(state, index)); - if (!class_rep) - return (false); - - if (class_rep->get_class_type() == luabind::detail::class_rep::lua_class) - return (true); - - if (luabind::detail::class_registry::get_registry(state)->find_class(class_rep->type()) != class_rep) - return (false); - - return (true); -} - -bool engine::type_convert_instance(char* buffer, unsigned int const size, lua_State* state, int index) -{ - if (!is_luabind_class(state, index)) - return (false); - - class_name(buffer, size, *static_cast(lua_touserdata(state, index))); - - return (true); -} - -void engine::type_convert_userdata(char* buffer, unsigned int const size, lua_State* state, int index) -{ - if (luabind::detail::is_class_object(state, index)) - { - type_convert_class(buffer, size, state, index); - return; - } - - if (type_convert_instance(buffer, size, state, index)) - return; - - sz_cpy(buffer, size, "unrecognized user data"); -} - -bool engine::type_to_string(char* const buffer, unsigned int const size, lua_State* const state, int const index, - bool& use_in_description) -{ - switch (lua_type(state, index)) - { - case engine::lua_type_string: - case engine::lua_type_table: - case engine::lua_type_nil: - case engine::lua_type_boolean: - case engine::lua_type_number: - case engine::lua_type_function: - case engine::lua_type_coroutine: - return (false); - case engine::lua_type_light_user_data: - case engine::lua_type_user_data: - { - type_convert_userdata(buffer, size, state, index); - return (true); - } - default: NODEFAULT; - } // switch (lua_type(state, index)) - -#ifdef DEBUG - return (false); -#endif // #ifdef DEBUG -} - -void engine::fill_class_info(cs::lua_studio::backend& backend, char* const buffer, unsigned int const size, - luabind::detail::object_rep* object, luabind::detail::class_rep* class_rep, - lua_State* state) -{ - pstr stream = buffer; - - stream += xr_sprintf(stream, size - (stream - buffer), "{"); - - typedef luabind::detail::class_rep::property_map property_map; - property_map::const_iterator I = class_rep->properties().begin(); - property_map::const_iterator E = class_rep->properties().end(); - for (u32 i = 0; I != E; ++I) - { - if (i == 3) - { - stream += xr_sprintf(stream, size - (stream - buffer), "..."); - break; - } - lua_pushstring(state, (*I).first); - lua_insert(state, 1); - lua_pushlightuserdata(state, object); - lua_insert(state, 1); - (*I).second.func(state, (*I).second.pointer_offset); - - string4096 type; - bool use_in_description; - backend.type_to_string(type, sizeof(type), state, -1, use_in_description); - - string4096 value; - cs::lua_studio::icon_type icon_type; - backend.value_to_string(value, sizeof(value), state, -1, icon_type, false); - - lua_pop_value(state, 1); - lua_remove(state, 1); - lua_remove(state, 1); - - if (use_in_description) - stream += xr_sprintf(stream, size - (stream - buffer), "%s[%s]=%s ", (*I).first, type, value); - else - stream += xr_sprintf(stream, size - (stream - buffer), "%s=%s ", (*I).first, value); - - ++i; - } - - stream += xr_sprintf(stream, size - (stream - buffer), "}%c", 0); -} - -void engine::value_convert_class(cs::lua_studio::backend& backend, char* buffer, unsigned int size, - luabind::detail::class_rep* class_rep, lua_State* state, int index, - cs::lua_studio::icon_type& icon_type, bool const full_description) -{ - icon_type = cs::lua_studio::icon_type_class; - - if (!full_description) - { - sz_cpy(buffer, size, "{...}"); - return; - } - - if (!class_rep->bases().empty()) - { - sz_cpy(buffer, size, "{...}"); - return; - } - - if (class_rep->properties().empty()) - { - sz_cpy(buffer, size, "{}"); - return; - } - - luabind::detail::object_rep* object = luabind::detail::is_class_object(state, index); - if (!object) - { - sz_cpy(buffer, size, "{...}"); - return; - } - - fill_class_info(backend, buffer, size, object, class_rep, state); -} - -bool engine::value_convert_instance(cs::lua_studio::backend& backend, char* buffer, unsigned int size, - luabind::detail::object_rep* object, lua_State* state) -{ - typedef luabind::detail::lua_reference lua_reference; - lua_reference const& tbl = object->get_lua_table(); - if (!tbl.is_valid()) - return (false); - - pstr stream = buffer; - stream += xr_sprintf(stream, size - (stream - buffer), "{"); - - tbl.get(state); - int i; - lua_pushnil(state); - for (i = 0; lua_next(state, -2); ++i) - { - if (i == 3) - { - lua_pop_value(state, 2); - stream += xr_sprintf(stream, size - (stream - buffer), "..."); - break; - } - - pcstr name = lua_to_string(state, -2); - - string4096 type; - bool use_in_description; - backend.type_to_string(type, sizeof(type), state, -1, use_in_description); - - string4096 value; - cs::lua_studio::icon_type icon_type; - backend.value_to_string(value, sizeof(value), state, -1, icon_type, false); - - if (use_in_description) - stream += xr_sprintf(stream, size - (stream - buffer), "%s[%s]=%s ", name, type, value); - else - stream += xr_sprintf(stream, size - (stream - buffer), "%s=%s ", name, value); - - lua_pop_value(state, 1); - } - - lua_pop_value(state, 1); - - if (!i) - return (false); - - stream += xr_sprintf(stream, size - (stream - buffer), "}%c", 0); - - return (true); -} - -bool engine::value_convert_instance(cs::lua_studio::backend& backend, char* buffer, unsigned int size, lua_State* state, - int index, cs::lua_studio::icon_type& icon_type, bool full_description) -{ - luabind::detail::object_rep* object = luabind::detail::is_class_object(state, index); - if (!object) - return (false); - - if (full_description && !value_convert_instance(backend, buffer, size, object, state)) - value_convert_class(backend, buffer, size, object->crep(), state, index, icon_type, full_description); - else - sz_cpy(buffer, size, " "); - - icon_type = cs::lua_studio::icon_type_class_instance; - - return (true); -} - -bool engine::value_to_string(cs::lua_studio::backend& backend, char* const buffer, unsigned int const size, - lua_State* const state, int const index, cs::lua_studio::icon_type& icon_type, - bool const full_description) -{ - switch (lua_type(state, index)) - { - case engine::lua_type_string: - case engine::lua_type_table: - case engine::lua_type_nil: - case engine::lua_type_boolean: - case engine::lua_type_number: - case engine::lua_type_function: - case engine::lua_type_coroutine: - return (false); - case engine::lua_type_light_user_data: - case engine::lua_type_user_data: - { - if (!luabind::detail::is_class_object(state, index)) - { - if (!is_luabind_class(state, index)) - { - icon_type = cs::lua_studio::icon_type_unknown; - pcvoid user_data = lua_topointer(state, index); - xr_sprintf(buffer, size, "0x%08x", *(u32 const*)&user_data); - return (true); - } - - luabind::detail::class_rep* class_rep = static_cast(lua_touserdata( - state, index)); - VERIFY(class_rep); - value_convert_class(backend, buffer, size, class_rep, state, index, icon_type, full_description); - return (true); - } - - if (value_convert_instance(backend, buffer, size, state, index, icon_type, full_description)) - return (true); - - icon_type = cs::lua_studio::icon_type_unknown; - pcvoid user_data = lua_topointer(state, index); - xr_sprintf(buffer, size, "0x%08x", *(u32 const*)&user_data); - return (true); - } - default: NODEFAULT; - } // switch (lua_type(state, index)) - -#ifdef DEBUG - return (false); -#endif // #ifdef DEBUG -} - -void engine::push_class(lua_State* const state, char const* const id) -{ - luabind::detail::object_rep* object = luabind::detail::is_class_object(state, -1); - VERIFY(object); - - luabind::detail::class_rep* class_rep = object->crep(); - R_ASSERT2(class_rep, "null class userdata"); - - R_ASSERT(!sz_cmp(class_rep->name(), id)); - lua_pushlightuserdata(state, class_rep); -} - -void engine::push_class_base(lua_State* const state, char const* const id) -{ - luabind::detail::class_rep* class_rep = static_cast(lua_touserdata(state, -1)); - VERIFY(class_rep); - - typedef luabind::detail::class_rep::base_info base_info; - typedef vector_class Bases; - Bases const& bases = class_rep->bases(); - Bases::const_iterator I = bases.begin(); - Bases::const_iterator E = bases.end(); - for (; I != E; ++I) - { - pcstr name = (*I).base->name(); - if (sz_cmp(id, name)) - continue; - - lua_pop_value(state, 1); - lua_pushlightuserdata(state, (*I).base); - return; - } - - NODEFAULT; -} - -void engine::push_class_instance(lua_State* const state, char const* const id) -{ - luabind::detail::object_rep* object = luabind::detail::is_class_object(state, -1); - if (!object) - { - lua_pop_value(state, 1); - object = luabind::detail::is_class_object(state, -1); - VERIFY(object); - } - - lua_insert(state, 1); - lua_pushstring(state, id); - lua_insert(state, 2); - object->crep()->gettable(state); - lua_remove(state, 2); - lua_pushvalue(state, 1); - lua_remove(state, 1); - lua_pushvalue(state, -2); - lua_remove(state, -3); - lua_remove(state, -2); -} - -void engine::push_user_data(lua_State* const state, char const* const id, cs::lua_studio::icon_type const icon_type) -{ - switch (icon_type) - { - case cs::lua_studio::icon_type_class: - { - push_class(state, id); - break; - } - case cs::lua_studio::icon_type_class_base: - { - push_class_base(state, id); - break; - } - case cs::lua_studio::icon_type_unknown: - case cs::lua_studio::icon_type_table: - case cs::lua_studio::icon_type_class_instance: - { - push_class_instance(state, id); - break; - } - default: NODEFAULT; - } -} - -bool engine::push_value(lua_State* const state, char const* const id, cs::lua_studio::icon_type const icon_type) -{ - switch (lua_type(state, -1)) - { - case engine::lua_type_table: - return (false); - case engine::lua_type_light_user_data: - case engine::lua_type_user_data: - { - push_user_data(state, id, icon_type); - return (true); - } - default: NODEFAULT; - } -#ifdef DEBUG - return (false); -#endif // #ifdef DEBUG -} - -void engine::fill_class_data( - cs::lua_studio::backend& backend, - cs::lua_studio::value_to_expand& value_to_expand, - lua_State* const state -) -{ - luabind::detail::object_rep* object = static_cast(lua_touserdata(state, -2)); - luabind::detail::class_rep* _class = static_cast(lua_touserdata(state, -1)); - R_ASSERT2(_class, "invalid class userdata"); - - { - string4096 type; - typedef luabind::detail::class_rep::base_info base_info; - vector_class::const_iterator i = _class->bases().begin(); - vector_class::const_iterator e = _class->bases().end(); - for (; i != e; ++i) - value_to_expand.add_value( - (*i).base->name(), - class_name(type, sizeof(type), *(*i).base), - "{...}", - cs::lua_studio::icon_type_class_base - ); - } - - if (!object) - return; - - typedef luabind::detail::class_rep::property_map property_map; - property_map::const_iterator i = _class->properties().begin(); - property_map::const_iterator e = _class->properties().end(); - for (; i != e; ++i) - { - lua_pushstring(state, (*i).first); - lua_insert(state, 1); - lua_pushlightuserdata(state, object); - lua_insert(state, 1); - (*i).second.func(state, (*i).second.pointer_offset); - - bool use_in_description; - - string4096 type; - backend.type_to_string(type, sizeof(type), state, -1, use_in_description); - - cs::lua_studio::icon_type icon_type; - string4096 value; - backend.value_to_string(value, sizeof(value), state, -1, icon_type, true); - - lua_pop_value(state, 1); - lua_remove(state, 1); - lua_remove(state, 1); - - value_to_expand.add_value( - (*i).first, - type, - value, - icon_type - ); - } -} - -void engine::expand_class( - cs::lua_studio::backend& backend, - cs::lua_studio::value_to_expand& value, - lua_State* const state -) -{ - int start = lua_gettop(state); - - luabind::detail::class_rep* class_object = static_cast(lua_touserdata(state, -1)); - R_ASSERT2(class_object, "invalid class userdata"); - - fill_class_data(backend, value, state); - - luabind::detail::object_rep* object = luabind::detail::is_class_object(state, -2); - if (!object) - lua_pushnil(state); - - if (lua_gettop(state) <= start + 1) - return; - - lua_pop_value(state, 1); -} - -void engine::expand_class_instance( - cs::lua_studio::backend& backend, - cs::lua_studio::value_to_expand& value_to_expand, - lua_State* const state -) -{ - typedef luabind::detail::object_rep object_rep; - object_rep* object = luabind::detail::is_class_object(state, -1); - VERIFY2(object, "invalid object userdata"); - - if (object->crep()) - { - luabind::detail::class_rep* class_rep = object->crep(); - - string4096 type; - class_name(type, sizeof(type), *class_rep); - - cs::lua_studio::icon_type icon_type; - string4096 value; - backend.value_to_string(value, sizeof(value), state, -1, icon_type, true); - value_to_expand.add_value( - class_rep->name(), - type, - value, - cs::lua_studio::icon_type_class - ); - } - - typedef luabind::detail::lua_reference lua_reference; - lua_reference const& tbl = object->get_lua_table(); - if (!tbl.is_valid()) - return; - - tbl.get(state); - int i; - lua_pushnil(state); - for (i = 0; lua_next(state, -2); ++i) - { - cs::lua_studio::icon_type icon_type; - bool use_in_description; - pcstr name = lua_to_string(state, -2); - - string4096 type; - backend.type_to_string(type, sizeof(type), state, -1, use_in_description); - - string4096 value; - backend.value_to_string(value, sizeof(value), state, -1, icon_type, true); - value_to_expand.add_value( - name, - type, - value, - icon_type - ); - - lua_pop_value(state, 1); - } - - lua_pop_value(state, 1); -} - -void engine::expand_user_data( - cs::lua_studio::backend& backend, - cs::lua_studio::value_to_expand& value, - lua_State* const state -) -{ - luabind::detail::object_rep* object = luabind::detail::is_class_object(state, -1); - if (object) - { - expand_class_instance(backend, value, state); - lua_pop_value(state, 1); - return; - } - - expand_class(backend, value, state); - lua_pop_value(state, 2); -} - -bool engine::expand_value( - cs::lua_studio::backend& backend, - cs::lua_studio::value_to_expand& value, - lua_State* const state -) -{ - switch (lua_type(state, -1)) - { - case engine::lua_type_nil: - case engine::lua_type_table: - return (false); - case engine::lua_type_light_user_data: - case engine::lua_type_user_data: - { - expand_user_data(backend, value, state); - return (true); - } - default: NODEFAULT; - } - -#ifdef DEBUG - return (false); -#endif // #ifdef DEBUG -} - -engine::engine() : - m_instance_count(0) -{ -} diff --git a/src/xrServerEntities/lua_studio.h b/src/xrServerEntities/lua_studio.h deleted file mode 100644 index 1b74cabab8..0000000000 --- a/src/xrServerEntities/lua_studio.h +++ /dev/null @@ -1,154 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : lua_studio.h -// Created : 21.08.2008 -// Modified : 21.08.2008 -// Author : Dmitriy Iassenev -// Description : lua studio engine class (copied from the lua studio SDK) -//////////////////////////////////////////////////////////////////////////// - -#ifndef LUA_STUDIO_H_INCLUDED -#define LUA_STUDIO_H_INCLUDED - -#ifdef DEBUG -# define CS_LUA_DEBUGGER_USE_DEBUG_LIBRARY -#endif// #ifdef DEBUG - -#include -#include - -namespace luabind -{ - namespace detail - { - class class_rep; - } // namespace detail -} // namespace luabind - -class lua_studio_engine : - public cs::lua_studio::engine, - private boost::noncopyable -{ -public: - virtual int CS_LUA_STUDIO_BACKEND_CALL luaL_loadstring(lua_State* L, const char* s); - virtual int CS_LUA_STUDIO_BACKEND_CALL luaL_newmetatable(lua_State* L, const char* tname); - -public: - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_createtable(lua_State* L, int narray, int nrec); - - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_sethook(lua_State* L, lua_Hook func, lua_mask_type mask, int count); - virtual lua_Hook CS_LUA_STUDIO_BACKEND_CALL lua_gethook(lua_State* L); - - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_getinfo(lua_State* L, const char* what, lua_Debug* ar); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_getfenv(lua_State* L, int idx); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_getfield(lua_State* L, int idx, const char* k); - virtual char const* CS_LUA_STUDIO_BACKEND_CALL lua_getlocal(lua_State* L, const lua_Debug* ar, int n); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_gettable(lua_State* L, int idx); - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_getstack(lua_State* L, int level, lua_Debug* ar); - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_gettop(lua_State* L); - virtual char const* CS_LUA_STUDIO_BACKEND_CALL lua_getupvalue(lua_State* L, int funcindex, int n); - - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_iscfunction(lua_State* L, int idx); - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_next(lua_State* L, int idx); - - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_pcall(lua_State* L, int nargs, int nresults, int errfunc); - - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_pushcclosure(lua_State* L, lua_CFunction fn, int n); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_pushnil(lua_State* L); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_pushstring(lua_State* L, const char* s); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_pushvalue(lua_State* L, int idx); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_pushnumber(lua_State* L, lua_Number idx); - - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_remove(lua_State* L, int idx); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_replace(lua_State* L, int idx); - - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_setfenv(lua_State* L, int idx); - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_setmetatable(lua_State* L, int objindex); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_settable(lua_State* L, int idx); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_settop(lua_State* L, int idx); - - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_toboolean(lua_State* L, int idx); - virtual lua_Integer CS_LUA_STUDIO_BACKEND_CALL lua_tointeger(lua_State* L, int idx); - virtual char const* CS_LUA_STUDIO_BACKEND_CALL lua_tolstring(lua_State* L, int idx, size_t* len); - virtual lua_Number CS_LUA_STUDIO_BACKEND_CALL lua_tonumber(lua_State* L, int idx); - virtual const void* CS_LUA_STUDIO_BACKEND_CALL lua_topointer(lua_State* L, int idx); - - virtual bool CS_LUA_STUDIO_BACKEND_CALL lua_isnumber(lua_State* L, int idx); - - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_type(lua_State* L, int idx); - virtual char const* CS_LUA_STUDIO_BACKEND_CALL lua_typename(lua_State* L, int t); - -public: - virtual lua_Debug* CS_LUA_STUDIO_BACKEND_CALL lua_debug_create(); - virtual void CS_LUA_STUDIO_BACKEND_CALL lua_debug_destroy(lua_Debug*& instance); - virtual char const* CS_LUA_STUDIO_BACKEND_CALL lua_debug_get_name(lua_Debug& instance); - virtual char const* CS_LUA_STUDIO_BACKEND_CALL lua_debug_get_source(lua_Debug& instance); - virtual char const* CS_LUA_STUDIO_BACKEND_CALL lua_debug_get_short_source(lua_Debug& instance); - virtual int CS_LUA_STUDIO_BACKEND_CALL lua_debug_get_current_line(lua_Debug& instance); - -public: - virtual void CS_LUA_STUDIO_BACKEND_CALL log(log_message_types message_type, char const* message); - virtual bool CS_LUA_STUDIO_BACKEND_CALL type_to_string(char* buffer, unsigned int size, lua_State* state, int index, - bool& use_in_description); - virtual bool CS_LUA_STUDIO_BACKEND_CALL value_to_string(cs::lua_studio::backend& backend, char* buffer, - unsigned int size, lua_State* state, int index, - cs::lua_studio::icon_type& icon_type, - bool full_description); - virtual bool CS_LUA_STUDIO_BACKEND_CALL expand_value(cs::lua_studio::backend& backend, - cs::lua_studio::value_to_expand& value, lua_State* state); - virtual bool CS_LUA_STUDIO_BACKEND_CALL push_value(lua_State* state, char const* id, - cs::lua_studio::icon_type icon_type); - -public: - lua_studio_engine(); - -private: - void type_convert_class(char* buffer, unsigned int size, lua_State* state, int index); - bool type_convert_instance(char* buffer, unsigned int size, lua_State* state, int index); - void type_convert_userdata(char* buffer, unsigned int size, lua_State* state, int index); - static char* class_name(char* buffer, unsigned int size, luabind::detail::class_rep& class_rep); - -private: - void fill_class_info(cs::lua_studio::backend& backend, char* buffer, unsigned int size, - luabind::detail::object_rep* object, luabind::detail::class_rep* class_rep, lua_State* state); - void value_convert_class(cs::lua_studio::backend& backend, char* buffer, unsigned int size, - luabind::detail::class_rep* class_rep, lua_State* state, int index, - cs::lua_studio::icon_type& icon_type, bool full_description); - bool value_convert_instance(cs::lua_studio::backend& backend, char* buffer, unsigned int size, - luabind::detail::object_rep* object, lua_State* state); - bool value_convert_instance(cs::lua_studio::backend& backend, char* buffer, unsigned int size, lua_State* state, - int index, cs::lua_studio::icon_type& icon_type, bool full_description); - -private: - void push_class(lua_State* state, char const* id); - void push_class_base(lua_State* state, char const* id); - void push_class_instance(lua_State* state, char const* id); - void push_user_data(lua_State* state, char const* id, cs::lua_studio::icon_type icon_type); - -private: - void fill_class_data( - cs::lua_studio::backend& backend, - cs::lua_studio::value_to_expand& value_to_expand, - lua_State* const state - ); - void expand_class( - cs::lua_studio::backend& backend, - cs::lua_studio::value_to_expand& value, - lua_State* const state - ); - void expand_class_instance( - cs::lua_studio::backend& backend, - cs::lua_studio::value_to_expand& value_to_expand, - lua_State* const state - ); - void expand_user_data( - cs::lua_studio::backend& backend, - cs::lua_studio::value_to_expand& value, - lua_State* const state - ); - -private: - lua_Debug m_instances[2]; - u32 m_instance_count; -}; - -#endif // #ifndef LUA_STUDIO_H_INCLUDED diff --git a/src/xrServerEntities/script_callStack.cpp b/src/xrServerEntities/script_callStack.cpp deleted file mode 100644 index 37228cb121..0000000000 --- a/src/xrServerEntities/script_callStack.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "stdafx.h" - -#include "script_CallStack.h" -#include "script_debugger.h" - -CScriptCallStack::CScriptCallStack(CScriptDebugger* d) - : m_debugger(d) -{ -} - -CScriptCallStack::~CScriptCallStack() -{ -} - -/* -int CCallStack::OnSci(CScintillaView* pView, SCNotification* pNotify) -{ - CLuaEditor* pEditor = ((CScintillaView*)GetView(0))->GetEditor(); - - CPoint pt; - int nLine; - CString strLine; - switch (pNotify->nmhdr.code) - { - case SCN_DOUBLECLICK: - GetCursorPos(&pt); - pEditor->ScreenToClient(&pt); - nLine = pEditor->LineFromPoint(pt); - GotoStackTraceLevel(nLine-1); - break; - }; - - return 0; -} -*/ - -void CScriptCallStack::Clear() -{ - m_nCurrentLevel = -1; - m_lines.clear(); - m_files.clear(); -} - -void CScriptCallStack::Add(const char* szDesc, const char* szFile, int nLine) -{ - m_lines.push_back(nLine); - - SPath sp; - sp.path[0] = 0; - m_files.push_back(sp); - xr_strcat(m_files.back().path, szFile); -} - -void CScriptCallStack::SetStackTraceLevel(int nLevel) -{ - m_nCurrentLevel = nLevel; - VERIFY(nLevel>=0 || (u32)nLevel < m_files.size()); -} - -void CScriptCallStack::GotoStackTraceLevel(int nLevel) -{ - if (nLevel < 0 || (u32)nLevel >= m_files.size()) - return; - - m_nCurrentLevel = nLevel; - - char* ppath = m_files[nLevel].path; - m_debugger->_SendMessage(DMSG_GOTO_FILELINE, - (WPARAM)ppath, - (LPARAM)m_lines[nLevel]); -} diff --git a/src/xrServerEntities/script_callStack.h b/src/xrServerEntities/script_callStack.h deleted file mode 100644 index 5fce60e908..0000000000 --- a/src/xrServerEntities/script_callStack.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -class CScriptDebugger; - -struct SPath -{ - string_path path; -}; - -class CScriptCallStack -{ -public: - CScriptDebugger* m_debugger; - void GotoStackTraceLevel(int nLevel); - void Add(const char* szDesc, const char* szFile, int nLine); - void Clear(); - CScriptCallStack(CScriptDebugger* d); - ~CScriptCallStack(); - - int GetLevel() { return m_nCurrentLevel; }; - void SetStackTraceLevel(int); -protected: - int m_nCurrentLevel; - xr_vector m_levels; - xr_vector m_lines; - xr_vector m_files; -}; diff --git a/src/xrServerEntities/script_debugger.cpp b/src/xrServerEntities/script_debugger.cpp deleted file mode 100644 index cf28e40012..0000000000 --- a/src/xrServerEntities/script_debugger.cpp +++ /dev/null @@ -1,583 +0,0 @@ -#include "stdafx.h" -#include "script_debugger.h" -#include "script_lua_helper.h" -#include "mslotutils.h" -// #include "../xrEngine/XR_IOConsole.h" - -//CScriptDebugger* CScriptDebugger::m_pDebugger = NULL; - - -void CScriptDebugger::SendMessageToIde(CMailSlotMsg& msg) -{ - if (CheckExisting(IDE_MAIL_SLOT)) - { - SendMailslotMessage(IDE_MAIL_SLOT, msg); - m_bIdePresent = true; - } - else - m_bIdePresent = false; -} - -LRESULT CScriptDebugger::_SendMessage(u32 message, WPARAM wParam, LPARAM lParam) -{ - // if ( (m_pDebugger)&&(m_pDebugger->Active())&&(message >= _DMSG_FIRST_MSG && message <= _DMSG_LAST_MSG) ) - // return m_pDebugger->DebugMessage(message, wParam, lParam); - if ((Active()) && (message >= _DMSG_FIRST_MSG && message <= _DMSG_LAST_MSG)) - return DebugMessage(message, wParam, lParam); - - return 0; -} - -LRESULT CScriptDebugger::DebugMessage(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - CMailSlotMsg msg; - - switch (nMsg) - { - case DMSG_NEW_CONNECTION: - { - msg.w_int(DMSG_NEW_CONNECTION); - SendMessageToIde(msg); - } - break; - - case DMSG_CLOSE_CONNECTION: - { - msg.w_int(DMSG_CLOSE_CONNECTION); - SendMessageToIde(msg); - } - break; - - case DMSG_WRITE_DEBUG: - { - msg.w_int(DMSG_WRITE_DEBUG); - msg.w_string((char*)wParam); - SendMessageToIde(msg); - } - break; - - case DMSG_GOTO_FILELINE: - { - msg.w_int(DMSG_GOTO_FILELINE); - msg.w_string((char*)wParam); - msg.w_int((int)lParam); - SendMessageToIde(msg); - } - break; - - case DMSG_DEBUG_BREAK: - { - msg.w_int(DMSG_ACTIVATE_IDE); - SendMessageToIde(msg); - WaitForReply(true); - } - break; - - case DMSG_CLEAR_STACKTRACE: - { - m_callStack->Clear(); - msg.w_int(DMSG_CLEAR_STACKTRACE); - SendMessageToIde(msg); - } - break; - - case DMSG_ADD_STACKTRACE: - { - m_callStack->Add(((StackTrace*)wParam)->szDesc, - ((StackTrace*)wParam)->szFile, - ((StackTrace*)wParam)->nLine); - - msg.w_int(DMSG_ADD_STACKTRACE); - msg.w_buff((StackTrace*)wParam, sizeof(StackTrace)); - SendMessageToIde(msg); - } - break; - - case DMSG_GOTO_STACKTRACE_LEVEL: - { - m_callStack->GotoStackTraceLevel((int)wParam); - StackLevelChanged(); - } - break; - - case DMSG_CLEAR_LOCALVARIABLES: - { - msg.w_int(DMSG_CLEAR_LOCALVARIABLES); - SendMessageToIde(msg); - } - break; - - case DMSG_ADD_LOCALVARIABLE: - { - msg.w_int(DMSG_ADD_LOCALVARIABLE); - msg.w_buff((void*)wParam, sizeof(Variable)); - SendMessageToIde(msg); - } - break; - - case DMSG_CLEAR_THREADS: - { - msg.w_int(DMSG_CLEAR_THREADS); - SendMessageToIde(msg); - } - break; - - case DMSG_ADD_THREAD: - { - msg.w_int(DMSG_ADD_THREAD); - msg.w_buff((void*)wParam, sizeof(SScriptThread)); - SendMessageToIde(msg); - } - break; - - case DMSG_THREAD_CHANGED: - { - int nThreadID = (int)wParam; - DrawThreadInfo(nThreadID); - } - break; - - case DMSG_GET_VAR_TABLE: - { - DrawVariableInfo((char*)wParam); - } - break; - - - case DMSG_EVAL_WATCH: - { - string2048 res; - res[0] = 0; - Eval((const char*)wParam, res, sizeof(res)); - - msg.w_int(DMSG_EVAL_WATCH); - msg.w_string(res); - msg.w_string((const char*)wParam); - SendMessageToIde(msg); - } - break; - } //case - - return 0; -} - - -BOOL CScriptDebugger::Active() -{ - return m_bIdePresent; -} - -CScriptDebugger::CScriptDebugger() -{ - m_threads = xr_new(this); - m_callStack = xr_new(this); - m_lua = xr_new(this); - - ZeroMemory(m_curr_connected_mslot, sizeof(m_curr_connected_mslot)); - // m_pDebugger = this; - m_nLevel = 0; - m_mailSlot = CreateMailSlotByName(DEBUGGER_MAIL_SLOT); - - if (m_mailSlot == INVALID_HANDLE_VALUE) - { - m_bIdePresent = false; - return; - } - Connect(IDE_MAIL_SLOT); -} - -void CScriptDebugger::Connect(LPCSTR mslot_name) -{ - m_bIdePresent = CheckExisting(IDE_MAIL_SLOT); - ZeroMemory(m_curr_connected_mslot, sizeof(m_curr_connected_mslot)); - if (Active()) - { - _SendMessage(DMSG_NEW_CONNECTION, 0, 0); - CMailSlotMsg msg; - msg.w_int(DMSG_GET_BREAKPOINTS); - SendMessageToIde(msg); - WaitForReply(false); - xr_strcat(m_curr_connected_mslot, mslot_name); - } -} - -CScriptDebugger::~CScriptDebugger() -{ - if (Active()) - _SendMessage(DMSG_CLOSE_CONNECTION, 0, 0); - - CloseHandle(m_mailSlot); - - xr_delete(m_threads); - xr_delete(m_callStack); - xr_delete(m_lua); -} - -void CScriptDebugger::UnPrepareLua(lua_State* l, int idx) -{ - if (idx == -1) return; // !Active() - m_lua->UnPrepareLua(l, idx); -} - -int CScriptDebugger::PrepareLua(lua_State* l) -{ - // call this function immediatly before calling lua_pcall. - //returns index in stack for errorFunc - if (!Active())return -1; - - m_nMode = DMOD_NONE; - return m_lua->PrepareLua(l); -} - -BOOL CScriptDebugger::PrepareLuaBind() -{ - if (!Active())return FALSE; - - m_lua->PrepareLuaBind(); - m_nMode = DMOD_NONE; - - return TRUE; -} - -void CScriptDebugger::initiateDebugBreak() -{ - m_nMode = DMOD_BREAK; -} - -void CScriptDebugger::Write(const char* szMsg) -{ - _SendMessage(DMSG_WRITE_DEBUG, (WPARAM)szMsg, 0); -} - -void CScriptDebugger::LineHook(const char* szFile, int nLine) -{ - CheckNewMessages(); - if (m_nMode == DMOD_STOP) - { - // Console->Execute("quit"); - return; - } - - if ( - HasBreakPoint(szFile, nLine) || - m_nMode == DMOD_STEP_INTO || - m_nMode == DMOD_BREAK || - (m_nMode == DMOD_STEP_OVER && m_nLevel <= 0) || - (m_nMode == DMOD_STEP_OUT && m_nLevel < 0) || - (m_nMode == DMOD_RUN_TO_CURSOR && - xr_strcmp(m_strPathName, szFile) && - m_nLine == nLine)) - { - DebugBreak(szFile, nLine); - GetBreakPointsFromIde(); - } -} - -void CScriptDebugger::FunctionHook(const char* szFile, int nLine, BOOL bCall) -{ - if (m_nMode == DMOD_STOP) - return; - - m_nLevel += (bCall ? 1 : -1); -} - -void CScriptDebugger::DrawThreadInfo(int nThreadID) -{ - //find corresponding lua_state - lua_State* ls = m_threads->FindScript(nThreadID); - if (!ls) - return; - m_lua->set_lua(ls); - DrawCurrentState(); -} - -void CScriptDebugger::DrawCurrentState() -{ - m_lua->DrawStackTrace(); - m_callStack->SetStackTraceLevel(0); - m_lua->DrawGlobalVariables(); - _SendMessage(DMSG_GOTO_STACKTRACE_LEVEL, GetStackTraceLevel(), 0); -} - -void CScriptDebugger::DebugBreak(const char* szFile, int nLine) -{ - m_nMode = DMOD_NONE; - - m_threads->Fill(); - m_threads->DrawThreads(); - - DrawCurrentState(); - - _SendMessage(DMSG_DEBUG_BREAK, 0, 0); -} - -void CScriptDebugger::GetBreakPointsFromIde() -{ - CMailSlotMsg msg; - msg.w_int(DMSG_GET_BREAKPOINTS); - SendMessageToIde(msg); - WaitForReply(false); -} - -void CScriptDebugger::ErrorBreak(const char* szFile, int nLine) -{ - if (Active()) - DebugBreak(szFile, nLine); -} - -void CScriptDebugger::ClearStackTrace() -{ - _SendMessage(DMSG_CLEAR_STACKTRACE, 0, 0); -} - -void CScriptDebugger::AddStackTrace(const char* szDesc, const char* szFile, int nLine) -{ - StackTrace st; - xr_strcat(st.szDesc, szDesc); - xr_strcat(st.szFile, szFile); - st.nLine = nLine; - _SendMessage(DMSG_ADD_STACKTRACE, (WPARAM)&st, 0); -} - -int CScriptDebugger::GetStackTraceLevel() -{ - return m_callStack->GetLevel(); -} - -void CScriptDebugger::StackLevelChanged() -{ - m_lua->DrawLocalVariables(); -} - -void CScriptDebugger::DrawVariableInfo(char* varName) -{ - m_lua->DrawVariableInfo(varName); -} - -void CScriptDebugger::ClearLocalVariables() -{ - _SendMessage(DMSG_CLEAR_LOCALVARIABLES, 0, 0); -} - -void CScriptDebugger::AddLocalVariable(const Variable& var) -{ - _SendMessage(DMSG_ADD_LOCALVARIABLE, (WPARAM)&var, 0); -} - -void CScriptDebugger::ClearGlobalVariables() -{ - _SendMessage(DMSG_CLEAR_GLOBALVARIABLES, 0, 0); -} - -void CScriptDebugger::AddGlobalVariable(const char* name, const char* type, const char* value) -{ - Variable var; - xr_strcat(var.szName, name); - xr_strcat(var.szType, type); - xr_strcat(var.szValue, value); - _SendMessage(DMSG_ADD_GLOBALVARIABLE, (WPARAM)&var, 0); -} - - -void CScriptDebugger::Eval(const char* strCode, char* res, int res_sz) -{ - string1024 strCodeFull; - strCodeFull[0] = 0; - const char* r = "return "; - strconcat(sizeof(strCodeFull), strCodeFull, r, strCode); - m_lua->Eval(strCodeFull, res, res_sz); -} - -void CScriptDebugger::CheckNewMessages() -{ - CMailSlotMsg msg; - while (CheckMailslotMessage(m_mailSlot, msg)) - { - TranslateIdeMessage(&msg); - }; -} - -void CScriptDebugger::WaitForReply(bool bWaitForModalResult) //UINT nMsg) -{ - bool mr = false; - do - { - CMailSlotMsg msg; - while (true) - { - if (CheckMailslotMessage(m_mailSlot, msg)) break; - Sleep(10); - }; - R_ASSERT(msg.GetLen()); - - mr = TranslateIdeMessage(&msg); //mr--is this an ide modalResult ? - } - while (bWaitForModalResult && !mr); -} - -bool CScriptDebugger::TranslateIdeMessage(CMailSlotMsg* msg) -{ - int nType; - msg->r_int(nType); - switch (nType) - { - case DMSG_DEBUG_GO: - { - m_nMode = DMOD_NONE; - return true; - } - break; - - case DMSG_DEBUG_BREAK: - { - m_nMode = DMOD_BREAK; - return true; - } - break; - - case DMSG_DEBUG_STEP_INTO: - { - m_nMode = DMOD_STEP_INTO; - return true; - } - break; - - case DMSG_DEBUG_STEP_OVER: - { - m_nLevel = 0; - m_nMode = DMOD_STEP_OVER; - return true; - } - break; - - case DMSG_DEBUG_STEP_OUT: - { - m_nLevel = 0; - m_nMode = DMOD_STEP_OUT; - return true; - } - break; - - case DMSG_DEBUG_RUN_TO_CURSOR: - { - //DMOD_RUN_TO_CURSOR; - return true; - } - break; - - case DMSG_STOP_DEBUGGING: - { - m_nMode = DMOD_STOP; - // Console->Execute("quit"); - return true; - } - break; - - case DMSG_GOTO_STACKTRACE_LEVEL: - { - int nLevel; - msg->r_int(nLevel); - _SendMessage(DMSG_GOTO_STACKTRACE_LEVEL, nLevel, 0); - return false; - } - break; - - case DMSG_GET_BREAKPOINTS: - { - FillBreakPointsIn(msg); - return false; - } - break; - - case DMSG_THREAD_CHANGED: - { - int nThreadID; - msg->r_int(nThreadID); - _SendMessage(DMSG_THREAD_CHANGED, nThreadID, 0); - return false; - } - break; - - case DMSG_GET_VAR_TABLE: - { - string512 varName; - varName[0] = 0; - msg->r_string(varName); - _SendMessage(DMSG_GET_VAR_TABLE, (WPARAM)varName, 0); - return false; - } - break; - - - case DMSG_EVAL_WATCH: - { - string2048 watch; - watch[0] = 0; - int iItem; - msg->r_string(watch); - msg->r_int(iItem); - _SendMessage(DMSG_EVAL_WATCH, (WPARAM)watch, (LPARAM)iItem); - return false; - } - break; - - - default: - return false; - } -} - -bool CScriptDebugger::HasBreakPoint(const char* fileName, s32 lineNum) -{ - string256 sFileName; - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - char ext[_MAX_EXT]; - - _splitpath(fileName, drive, dir, sFileName, ext); - - - for (u32 i = 0; i < m_breakPoints.size(); ++i) - { - SBreakPoint bp(m_breakPoints[i]); - if (bp.nLine == lineNum) - if (xr_strlen(bp.fileName) == xr_strlen(sFileName)) - { - if (stricmp(*bp.fileName, sFileName) == 0) - return true; - } - } - return false; -} - -void CScriptDebugger::FillBreakPointsIn(CMailSlotMsg* msg) -{ - m_breakPoints.clear(); - s32 nCount = 0; - msg->r_int(nCount); - for (s32 i = 0; i < nCount; ++i) - { - SBreakPoint bp; - string256 fn; - msg->r_string(fn); - bp.fileName = fn; - s32 bpCount = 0; - msg->r_int(bpCount); - - for (s32 j = 0; j < bpCount; ++j) - { - msg->r_int(bp.nLine); - m_breakPoints.push_back(bp); - } - } -} - -void CScriptDebugger::ClearThreads() -{ - _SendMessage(DMSG_CLEAR_THREADS, 0, 0); -} - -void CScriptDebugger::AddThread(SScriptThread& th) -{ - _SendMessage(DMSG_ADD_THREAD, (WPARAM)(&th), 0); -} diff --git a/src/xrServerEntities/script_debugger.h b/src/xrServerEntities/script_debugger.h deleted file mode 100644 index 66b41f20ba..0000000000 --- a/src/xrServerEntities/script_debugger.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -#include "script_lua_helper.h" -#include "script_debugger_threads.h" -#include "script_CallStack.h" -#include "script_debugger_messages.h" -//#include "script_debugger_utils.h" - -class CMailSlotMsg; -struct lua_State; - -#define DMOD_NONE 0 -#define DMOD_STEP_INTO 1 -#define DMOD_STEP_OVER 2 -#define DMOD_STEP_OUT 3 -#define DMOD_RUN_TO_CURSOR 4 -//#define DMOD_SHOW_STACK_LEVEL 5 - -#define DMOD_BREAK 10 -#define DMOD_STOP 11 - -struct SBreakPoint -{ - shared_str fileName; - s32 nLine; - SBreakPoint() { nLine = 0; }; - - SBreakPoint(const SBreakPoint& other) - { - operator =(other); - }; - - SBreakPoint& operator =(const SBreakPoint& other) - { - fileName = other.fileName; - nLine = other.nLine; - return *this; - } -}; - -class CScriptDebugger -{ -public: - void Connect(LPCSTR mslot_name); - void Eval(const char* strCode, char* res, int res_sz); - void AddLocalVariable(const Variable& var); - void ClearLocalVariables(); - void AddGlobalVariable(const char* name, const char* type, const char* value); - void ClearGlobalVariables(); - void StackLevelChanged(); - void initiateDebugBreak(); - void DebugBreak(const char* szFile, int nLine); - void ErrorBreak(const char* szFile = 0, int nLine = 0); - void LineHook(const char* szFile, int nLine); - void FunctionHook(const char* szFile, int nLine, BOOL bCall); - void Write(const char* szMsg); - - int PrepareLua(lua_State*); - void UnPrepareLua(lua_State* l, int idx); - BOOL PrepareLuaBind(); - - CScriptDebugger(); - virtual ~CScriptDebugger(); - - void Go(); - void StepInto(); - void StepOver(); - void StepOut(); - void RunToCursor(); - - void ClearThreads(); - void AddThread(SScriptThread&); - - void ClearStackTrace(); - void AddStackTrace(const char* strDesc, const char* strFile, int nLine); - int GetStackTraceLevel(); - - BOOL Active(); - // static CScriptDebugger* GetDebugger () { return m_pDebugger; }; - LRESULT _SendMessage(UINT message, WPARAM wParam, LPARAM lParam); - -protected: - void DrawVariableInfo(char* varName); - void DrawCurrentState(); - void DrawThreadInfo(int nThreadID); - void GetBreakPointsFromIde(); - void FillBreakPointsIn(CMailSlotMsg* msg); - bool HasBreakPoint(const char* fileName, s32 lineNum); - void CheckNewMessages(); - LRESULT DebugMessage(UINT nMsg, WPARAM wParam, LPARAM lParam); - void WaitForReply(bool bWaitForModalResult); - bool TranslateIdeMessage(CMailSlotMsg*); - void SendMessageToIde(CMailSlotMsg&); - - - CDbgScriptThreads* m_threads; - CDbgLuaHelper* m_lua; - CScriptCallStack* m_callStack; - // static CScriptDebugger* m_pDebugger; - int m_nMode; - int m_nLevel; //for step into/over/out - string_path m_strPathName; //for run_to_line_number - int m_nLine; //for run_to_line_number - - HANDLE m_mailSlot; - BOOL m_bIdePresent; - - xr_vector m_breakPoints; - string_path m_curr_connected_mslot; -}; diff --git a/src/xrServerEntities/script_debugger_messages.h b/src/xrServerEntities/script_debugger_messages.h deleted file mode 100644 index cc0993da49..0000000000 --- a/src/xrServerEntities/script_debugger_messages.h +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once - -struct StackTrace -{ - char szDesc[255]; - char szFile[255]; - int nLine; - - StackTrace() - { - szDesc[0] = 0; - szFile[0] = 0; - nLine = 0; - }; -}; - -struct Variable -{ - char szName[255]; - char szType[50]; - char szValue[255]; - - Variable() - { - szName[0] = 0; - szType[0] = 0; - szValue[0] = 0; - }; -}; - -struct lua_State; - -struct SScriptThread -{ - // void* pScript; - lua_State* lua; - int scriptID; - bool active; - char name[255]; - char process[255]; - - SScriptThread():/**pScript(0),/**/lua(0), scriptID(-1), active(false) - { - name[0] = 0; - process[0] = 0; - }; - - SScriptThread(const SScriptThread& other) - { - operator =(other); - }; - - SScriptThread& operator =(const SScriptThread& other) - { - // pScript = other.pScript; - lua = other.lua; - scriptID = other.scriptID; - active = other.active; - name[0] = 0; - process[0] = 0; - xr_strcat(name, other.name); - xr_strcat(process, other.process); - - return *this; - } -}; - - -#define DEBUGGER_MAIL_SLOT "\\\\.\\mailslot\\script_debugger_mailslot" -#define IDE_MAIL_SLOT "\\\\.\\mailslot\\script_ide_mailslot" - -enum dbg_messages -{ - _DMSG_FIRST_MSG =WM_USER + 1, - DMSG_WRITE_DEBUG, - DMSG_HAS_BREAKPOINT, - DMSG_GOTO_FILELINE, - DMSG_DEBUG_START, - DMSG_DEBUG_BREAK, - DMSG_DEBUG_END, - DMSG_CLEAR_STACKTRACE, - DMSG_ADD_STACKTRACE, - DMSG_GOTO_STACKTRACE_LEVEL, - DMSG_GET_STACKTRACE_LEVEL, - DMSG_CLEAR_LOCALVARIABLES, - DMSG_ADD_LOCALVARIABLE, - DMSG_CLEAR_GLOBALVARIABLES, - DMSG_ADD_GLOBALVARIABLE, - DMSG_EVAL_WATCH, - DMSG_ACTIVATE_IDE, - DMSG_DEBUG_STEP_INTO, - DMSG_DEBUG_STEP_OVER, - DMSG_DEBUG_STEP_OUT, - DMSG_DEBUG_RUN_TO_CURSOR, - DMSG_STOP_DEBUGGING, - DMSG_GOTO_IDE_STACKTRACE_LEVEL, - DMSG_NEW_CONNECTION, - DMSG_DEBUG_GO, - DMSG_GET_BREAKPOINTS, - DMSG_CLEAR_THREADS, - DMSG_ADD_THREAD, - DMSG_THREAD_CHANGED, - DMSG_GET_VAR_TABLE, - DMSG_CLOSE_CONNECTION, - - _DMSG_LAST_MSG, -}; diff --git a/src/xrServerEntities/script_debugger_threads.cpp b/src/xrServerEntities/script_debugger_threads.cpp deleted file mode 100644 index 1d9702785c..0000000000 --- a/src/xrServerEntities/script_debugger_threads.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "stdafx.h" -#include "script_debugger_threads.h" -#include "ai_space.h" -#include "script_process.h" -#include "script_engine.h" -#include "script_engine_space.h" -#include "script_thread.h" -#include "script_debugger.h" - - -u32 CDbgScriptThreads::Fill() -{ - u32 res = 0; - -#ifdef XRGAME_EXPORTS - CScriptProcess* sp = ai().script_engine().script_process(ScriptEngine::eScriptProcessorGame); - - if (sp) - res += FillFrom(sp); - - sp = ai().script_engine().script_process(ScriptEngine::eScriptProcessorLevel); - if (sp) - res += FillFrom(sp); - - return res; -#else - return res; -#endif -} - -u32 CDbgScriptThreads::FillFrom(CScriptProcess* sp) -{ - m_threads.clear(); - const CScriptProcess::SCRIPT_REGISTRY& vScripts = sp->scripts(); - CScriptProcess::SCRIPT_REGISTRY::const_iterator It = vScripts.begin(); - for (; It != vScripts.end(); ++It) - { - SScriptThread th; - // th.pScript = (*It); - th.lua = (*It)->lua(); - th.scriptID = (*It)->thread_reference(); - th.active = (*It)->active(); - xr_strcat(th.name, *(*It)->script_name()); - xr_strcat(th.process, *sp->name()); - m_threads.push_back(th); - } - return m_threads.size(); -} - -lua_State* CDbgScriptThreads::FindScript(int nThreadID) -{ - xr_vector::iterator It = m_threads.begin(); - for (; It != m_threads.end(); ++It) - { - if ((*It).scriptID == nThreadID) - return (*It).lua; - } - return 0; -} - -void CDbgScriptThreads::DrawThreads() -{ - //CScriptDebugger::GetDebugger()->ClearThreads(); - m_debugger->ClearThreads(); - xr_vector::iterator It = m_threads.begin(); - for (; It != m_threads.end(); ++It) - { - SScriptThread th; - th = *It; - m_debugger->AddThread(th); - } -} diff --git a/src/xrServerEntities/script_debugger_threads.h b/src/xrServerEntities/script_debugger_threads.h deleted file mode 100644 index d88aba7b11..0000000000 --- a/src/xrServerEntities/script_debugger_threads.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "script_debugger_messages.h" - -class CScriptProcess; -class CScriptDebugger; -struct lua_State; - -class CDbgScriptThreads -{ - xr_vector m_threads; -public: - CScriptDebugger* m_debugger; - - CDbgScriptThreads(CScriptDebugger* d): m_debugger(d) - { - }; - - ~CDbgScriptThreads() - { - }; - u32 FillFrom(CScriptProcess*); - u32 Fill(); - lua_State* FindScript(int nthreadID); - void DrawThreads(); -}; diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index d0d2a4ac0a..39b40ea541 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -11,14 +11,14 @@ #include "script_storage.h" #include "ai_space.h" #include "object_factory.h" -#include "script_process.h" #include "../build_config_defines.h" -#include "script_thread.h" #include "../xrCore/mezz_stringbuffer.h" #include #include #include #include +#include "luabind/object.hpp" +#include "luabind/functor.hpp" using namespace ScriptEngine; @@ -45,16 +45,15 @@ using namespace ScriptEngine; # include "ai_debug.h" #endif //!NO_XRGAME_SCRIPT_ENGINE -#ifdef USE_DEBUGGER -# include "script_debugger.h" -#endif - #ifndef PURE_ALLOC //# ifndef USE_MEMORY_MONITOR //# define USE_DL_ALLOCATOR //# endif //!USE_MEMORY_MONITOR #endif //!PURE_ALLOC +extern void export_classes(lua_State* L); +extern int luaopen_lua_extensions(lua_State* L); + struct raii_guard : private boost::noncopyable { int m_error_code; @@ -67,11 +66,6 @@ struct raii_guard : private boost::noncopyable ~raii_guard() { -#ifdef DEBUG - bool lua_studio_connected = !!ai().script_engine().debugger(); - if (!lua_studio_connected) -#endif //-DEBUG - { #ifdef DEBUG static bool const break_on_assert = !!strstr(Core.Params, "-break_on_assert"); #else //!DEBUG @@ -84,13 +78,9 @@ struct raii_guard : private boost::noncopyable R_ASSERT2(!m_error_code, m_error_description); else Msg("! [SCRIPT ERROR]: %s", m_error_description); - } } }; //-struct raii_guard -extern void export_classes(lua_State* L); -extern int luaopen_lua_extensions(lua_State* L); - #ifndef USE_DL_ALLOCATOR static void* lua_alloc(void* ud, void* ptr, size_t osize, size_t nsize) { @@ -298,25 +288,112 @@ static void put_function(lua_State* state, u8 const* buffer, u32 const buffer_si #endif //!DEBUG #endif //-USE_LUAJIT_ONE -CScriptEngine::CScriptEngine() +// demonized: get lua stack in array +static std::vector get_lua_stack(lua_State* L) +{ + std::vector res; + lua_Debug l_tDebugInfo; + for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); ++i) + { + lua_getinfo(L, "nSlu", &l_tDebugInfo); + if (!l_tDebugInfo.name) + { + res.push_back(make_string("%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, "")); + } + else + { + if (!xr_strcmp(l_tDebugInfo.what, "C")) + { + res.push_back(make_string("%2d : [C ] %s", i, l_tDebugInfo.name)); + } + else + { + res.push_back(make_string("%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name)); + } + } + } + return res; +} + +void printLuaStack() +{ + ai().script_engine().print_stack(); +} + +void on_lua_error(lua_State* L) +{ + ai().script_engine().print_stack(); + ai().script_engine().print_output(L, "", LUA_ERRRUN); + ai().script_engine().on_error(L); + + // demonized: print first line with lua error + auto stack = get_lua_stack(L); + std::string lua_error_line = ""; + for (auto const& s : stack) { + if (s.find("[Lua]") != std::string::npos) { + lua_error_line = s; + break; + } + } + + auto error_str = make_string("\n%s\n\nLUA error: %s\n\nCheck log for details", lua_error_line.c_str(), lua_tostring(L, -1)); + LPCSTR error_msg = error_str.c_str(); + +#if !XRAY_EXCEPTIONS + Debug.fatal(DEBUG_INFO, error_msg); +#else + throw lua_tostring(L, -1); +#endif +} + +int on_lua_pcall_failed(lua_State* L) +{ + ai().script_engine().print_stack(); + ai().script_engine().print_output(L, "", LUA_ERRRUN); + ai().script_engine().on_error(L); + + // demonized: print first line with lua error + auto stack = get_lua_stack(L); + std::string lua_error_line = ""; + for (auto const& s : stack) { + if (s.find("[Lua]") != std::string::npos) { + lua_error_line = s; + break; + } + } + + auto error_str = make_string("\n%s\n\nLUA error: %s\n\nCheck log for details", lua_error_line.c_str(), lua_isstring(L, -1) ? lua_tostring(L, -1) : ""); + LPCSTR error_msg = error_str.c_str(); + +#if !XRAY_EXCEPTIONS + Debug.fatal(DEBUG_INFO, error_msg); +#endif + if (lua_isstring(L, -1)) + lua_pop(L, 1); + return (LUA_ERRRUN); +} + +int on_lua_panic(lua_State* L) { - m_current_thread = 0; + ai().script_engine().print_stack(); + ai().script_engine().print_output(L, "PANIC", LUA_ERRRUN); + return (0); +} +void on_lua_cast_failed(lua_State* L, LUABIND_TYPE_INFO info) +{ + CScriptEngine::print_output(L, "", LUA_ERRRUN); + Debug.fatal(DEBUG_INFO, "LUA error: cannot cast lua value to %s", info->name()); +} + +CScriptEngine::CScriptEngine() +{ #ifdef DEBUG m_stack_is_ready = false; #endif //-DEBUG m_virtual_machine = 0; m_stack_level = 0; - -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - m_scriptDebugger = NULL; - restartDebugger(); -# else //USE_LUA_STUDIO - m_lua_studio_world = 0; -# endif //!USE_LUA_STUDIO -#endif } CScriptEngine::~CScriptEngine() @@ -325,19 +402,8 @@ CScriptEngine::~CScriptEngine() flush_log(); #endif //-LUA_DEBUG_PRINT -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - xr_delete(m_scriptDebugger); -# else // #ifndef USE_LUA_STUDIO - disconnect_from_debugger(); -# endif // #ifndef USE_LUA_STUDIO -#endif - if (m_virtual_machine) lua_close(m_virtual_machine); - - while (!m_script_processes.empty()) - remove_script_process(m_script_processes.begin()->first); } // Low level path -> string content loader to work around intractable Lua IReader::r_stringZ behaviour @@ -361,30 +427,8 @@ static int load_file(lua_State* L) void CScriptEngine::init() { -#ifdef USE_LUA_STUDIO - bool lua_studio_connected = !!m_lua_studio_world; - if (lua_studio_connected) - m_lua_studio_world->remove(lua()); -#endif // #ifdef USE_LUA_STUDIO - CScriptEngine::reinit(); -#ifdef USE_LUA_STUDIO - if (m_lua_studio_world || strstr(Core.Params, "-lua_studio")) { - if (!lua_studio_connected) - try_connect_to_debugger(); - else { -#ifdef USE_LUAJIT_ONE - jit_command(lua(), "debug=2"); - jit_command(lua(), "off"); -#else - luaJIT_setmode(lua(), 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); -#endif - m_lua_studio_world->add(lua()); - } - } -#endif // #ifdef USE_LUA_STUDIO - luabind::open(lua()); setup_callbacks(); export_classes(lua()); @@ -393,15 +437,7 @@ void CScriptEngine::init() m_stack_is_ready = true; #endif -#ifndef USE_LUA_STUDIO -# ifdef DEBUG -# if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO) - if (!debugger() || !debugger()->Active()) -# endif // #if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO) - lua_sethook(lua(), lua_hook_call, LUA_MASKLINE | LUA_MASKCALL | LUA_MASKRET, 0); -# endif // #ifdef DEBUG -#endif // #ifndef USE_LUA_STUDIO - // lua_sethook (lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); + // lua_sethook(lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); // Force the FS to recursively enumerate the scripts folder FS_Path* P = FS.get_path("$game_scripts$"); @@ -463,7 +499,6 @@ void CScriptEngine::reinit() return; } - #ifndef USE_LUAJIT_ONE luaL_openlibs(lua()); if (strstr(Core.Params, "-nojit")) @@ -513,228 +548,75 @@ void CScriptEngine::reinit() void CScriptEngine::unload() { + // Restore original stack level lua_settop(lua(), m_stack_level); } -int CScriptEngine::lua_panic(lua_State* L) -{ - ai().script_engine().print_stack(); - print_output(L, "PANIC", LUA_ERRRUN); - return (0); -} - -// demonized: get lua stack in array -static std::vector get_lua_stack(lua_State* L) -{ - std::vector res; - lua_Debug l_tDebugInfo; - for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); ++i) - { - lua_getinfo(L, "nSlu", &l_tDebugInfo); - if (!l_tDebugInfo.name) - { - res.push_back(make_string("%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, "")); - } - else - { - if (!xr_strcmp(l_tDebugInfo.what, "C")) - { - res.push_back(make_string("%2d : [C ] %s", i, l_tDebugInfo.name)); - } - else - { - res.push_back(make_string("%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, l_tDebugInfo.name)); - } - } - } - return res; -} - -void CScriptEngine::lua_error(lua_State* L) +void CScriptEngine::setup_callbacks() { - ai().script_engine().print_stack(); - print_output(L, "", LUA_ERRRUN); - ai().script_engine().on_error(L); - - // demonized: print first line with lua error - auto stack = get_lua_stack(L); - std::string lua_error_line = ""; - for (auto const& s : stack) { - if (s.find("[Lua]") != std::string::npos) { - lua_error_line = s; - break; - } - } - - auto error_str = make_string("\n%s\n\nLUA error: %s\n\nCheck log for details", lua_error_line.c_str(), lua_tostring(L, -1)); - LPCSTR error_msg = error_str.c_str(); - #if !XRAY_EXCEPTIONS - Debug.fatal(DEBUG_INFO, error_msg); -#else - throw lua_tostring(L, -1); + luabind::set_error_callback(on_lua_error); #endif -} - -void printLuaStack() -{ - ai().script_engine().print_stack(); -} - -int CScriptEngine::lua_pcall_failed(lua_State* L) -{ - ai().script_engine().print_stack(); - print_output(L, "", LUA_ERRRUN); - ai().script_engine().on_error(L); - // demonized: print first line with lua error - auto stack = get_lua_stack(L); - std::string lua_error_line = ""; - for (auto const& s : stack) { - if (s.find("[Lua]") != std::string::npos) { - lua_error_line = s; - break; - } - } - - auto error_str = make_string("\n%s\n\nLUA error: %s\n\nCheck log for details", lua_error_line.c_str(), lua_isstring(L, -1) ? lua_tostring(L, -1) : ""); - LPCSTR error_msg = error_str.c_str(); + luabind::set_pcall_callback(on_lua_pcall_failed); #if !XRAY_EXCEPTIONS - Debug.fatal(DEBUG_INFO, error_msg); + luabind::set_cast_failed_callback(on_lua_cast_failed); #endif - if (lua_isstring(L, -1)) - lua_pop(L, 1); - return (LUA_ERRRUN); + lua_atpanic(lua(), on_lua_panic); } -void lua_cast_failed(lua_State* L, LUABIND_TYPE_INFO info) -{ - CScriptEngine::print_output(L, "", LUA_ERRRUN); - - Debug.fatal(DEBUG_INFO, "LUA error: cannot cast lua value to %s", info->name()); -} - -int CScriptEngine::compile_buffer(lua_State* L, std::string caString, LPCSTR caScriptName, LPCSTR caNameSpaceName) -{ - luabind::functor compiler; - if (functor("_COMPILER", compiler)) - { - luabind::object result = compiler(caString.c_str(), caNameSpaceName, caScriptName); - result.pushvalue(); - return 0; - } - - Msg("* engine: loading %s", caNameSpaceName); - return luaL_loadbuffer(L, caString.c_str(), caString.length(), caScriptName); -} - -int CScriptEngine::load_buffer( - lua_State* L, - LPCSTR caBuffer, - size_t tSize, +int CScriptEngine::load_string( + LPCSTR caString, LPCSTR caScriptName, LPCSTR caNameSpaceName ) { - int l_iErrorCode = compile_buffer( - L, - std::string(caBuffer, caBuffer + tSize), - caScriptName, - caNameSpaceName - ); + lua_getglobal(lua(), "_COMPILER"); + if (!lua_isfunction(lua(), -1)) + { + FATAL("_COMPILER not available"); + } + + lua_pushstring(lua(), caString); + lua_pushstring(lua(), caNameSpaceName); + lua_pushstring(lua(), caScriptName); + int l_iErrorCode = lua_pcall(lua(), 3, 1, 0); if (l_iErrorCode) { //#ifdef DEBUG - if (strstr(Core.Params, "-dbg")) print_output(L, caScriptName, l_iErrorCode); + if (strstr(Core.Params, "-dbg")) print_output(lua(), caScriptName, l_iErrorCode); //#endif //-DEBUG - on_error(L); + on_error(lua()); } return l_iErrorCode; } -bool CScriptEngine::namespace_loaded(LPCSTR N, bool remove_from_stack) +int CScriptEngine::do_string( + LPCSTR caString, + LPCSTR caScriptName, + LPCSTR caNameSpaceName +) { - int start = lua_gettop(lua()); - lua_getglobal(lua(), "package"); - VERIFY(lua_istable(lua(), -1)); - lua_getfield(lua(), -1, "loaded"); - VERIFY(lua_istable(lua(), -1)); - lua_remove(lua(), -2); - string256 S2; - xr_strcpy(S2, N); - LPSTR S = S2; - for (;;) - { - if (!xr_strlen(S)) - { - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(start == lua_gettop(lua())); - return (false); - } - LPSTR S1 = strchr(S, '.'); - if (S1) - *S1 = 0; - lua_pushstring(lua(), S); - lua_rawget(lua(), -2); - if (lua_isnil(lua(), -1)) - { - // lua_settop (lua(),0); - VERIFY(lua_gettop(lua()) >= 2); - lua_pop(lua(), 2); - VERIFY(start == lua_gettop(lua())); - return (false); // there is no namespace! - } - else if (!lua_istable(lua(), -1)) - { - std::string tn(lua_typename(lua(), -1)); - // lua_settop (lua(),0); - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(start == lua_gettop(lua())); - if (S1) - FATAL((std::string("Error : the namespace name ") + N + " is already being used by non-table object of type " + tn + "\n").c_str()); - return (true); - } - lua_remove(lua(), -2); - if (S1) - S = ++S1; - else - break; - } - if (!remove_from_stack) - { - VERIFY(lua_gettop(lua()) == start + 1); - } - else + int l_iErrorCode; + + l_iErrorCode = load_string(caString, caScriptName, caNameSpaceName); + if (l_iErrorCode) { - VERIFY(lua_gettop(lua()) >= 1); - lua_pop(lua(), 1); - VERIFY(lua_gettop(lua()) == start); + ai().script_engine().print_output(ai().script_engine().lua(), caScriptName, l_iErrorCode); + ai().script_engine().on_error(ai().script_engine().lua()); + return l_iErrorCode; } - return (true); -} -luabind::object CScriptEngine::name_space(LPCSTR namespace_name) -{ - string256 S1; - xr_strcpy(S1, namespace_name); - LPSTR S = S1; - luabind::object lua_namespace = luabind::get_globals(lua()); - lua_namespace = lua_namespace["package"]; - lua_namespace = lua_namespace["loaded"]; - for (;;) + l_iErrorCode = lua_pcall(ai().script_engine().lua(), 0, 0, 0); + if (l_iErrorCode) { - if (!xr_strlen(S)) - return (lua_namespace); - LPSTR I = strchr(S, '.'); - if (!I) - return (lua_namespace[S]); - *I = 0; - lua_namespace = lua_namespace[S]; - S = I + 1; + ai().script_engine().print_output(ai().script_engine().lua(), caScriptName, l_iErrorCode); + ai().script_engine().on_error(ai().script_engine().lua()); + return l_iErrorCode; } + + return l_iErrorCode; } int CScriptEngine::vscript_log(ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker) @@ -947,28 +829,12 @@ bool CScriptEngine::print_output(lua_State* L, LPCSTR caScriptFileName, int iEro if (!xr_strcmp(S, "cannot resume dead coroutine")) { VERIFY2("Please do not return any values from main!!!", caScriptFileName); -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if (ai().script_engine().debugger() && ai().script_engine().debugger()->Active()) { - ai().script_engine().debugger()->Write(S); - ai().script_engine().debugger()->ErrorBreak(); - } -# endif //!USE_LUA_STUDIO -#endif //-USE_DEBUGGER } else { if (!iErorCode) script_log(eLuaMessageTypeInfo, "Output from %s", caScriptFileName); script_log(iErorCode ? eLuaMessageTypeError : eLuaMessageTypeMessage, "%s", S); -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if (ai().script_engine().debugger() && ai().script_engine().debugger()->Active()) { - ai().script_engine().debugger()->Write(S); - ai().script_engine().debugger()->ErrorBreak(); - } -# endif //!USE_LUA_STUDIO -#endif //-USE_DEBUGGER } return (true); } @@ -1040,21 +906,6 @@ int CScriptEngine::error_log(LPCSTR format, ...) return (result); } -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO -# include "script_debugger.h" -# else //USE_LUA_STUDIO -# include "lua_studio.h" -typedef cs::lua_studio::create_world_function_type create_world_function_type; -typedef cs::lua_studio::destroy_world_function_type destroy_world_function_type; - -static create_world_function_type s_create_world = 0; -static destroy_world_function_type s_destroy_world = 0; -static HMODULE s_script_debugger_handle = 0; -static LogCallback s_old_log_callback = 0; -# endif //!USE_LUA_STUDIO -#endif - #ifndef XRSE_FACTORY_EXPORTS # ifdef DEBUG # include "ai_debug.h" @@ -1067,252 +918,13 @@ extern Flags32 psAI_Flags; void jit_command(lua_State*, LPCSTR); #endif -#if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) -static void log_callback (LPCSTR message) -{ - if (s_old_log_callback) - s_old_log_callback (message); - - if (!ai().script_engine().debugger()) - return; - - ai().script_engine().debugger()->add_log_line (message); -} - -static void initialize_lua_studio ( lua_State* state, cs::lua_studio::world*& world, lua_studio_engine*& engine) -{ - engine = 0; - world = 0; - - u32 const old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS); - s_script_debugger_handle = LoadLibrary(CS_LUA_STUDIO_BACKEND_FILE_NAME); - SetErrorMode (old_error_mode); - if (!s_script_debugger_handle) { - Msg ("! cannot load %s dynamic library", CS_LUA_STUDIO_BACKEND_FILE_NAME); - return; - } - - R_ASSERT2 (s_script_debugger_handle, "can't load script debugger library"); - - s_create_world = (create_world_function_type) - GetProcAddress( - s_script_debugger_handle, - "_cs_lua_studio_backend_create_world@12" - ); - R_ASSERT2 (s_create_world, "can't find function \"cs_lua_studio_backend_create_world\""); - - s_destroy_world = (destroy_world_function_type) - GetProcAddress( - s_script_debugger_handle, - "_cs_lua_studio_backend_destroy_world@4" - ); - R_ASSERT2 (s_destroy_world, "can't find function \"cs_lua_studio_backend_destroy_world\" in the library"); - - engine = xr_new(); - world = s_create_world( *engine, false, false ); - VERIFY (world); - - s_old_log_callback = SetLogCB(&log_callback); - -#ifdef USE_LUAJIT_ONE - jit_command (state, "debug=2"); - jit_command (state, "off"); -#else - luaJIT_setmode(state, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF); -#endif - - world->add (state); -} - -static void finalize_lua_studio ( lua_State* state, cs::lua_studio::world*& world, lua_studio_engine*& engine) -{ - world->remove (state); - - VERIFY (world); - s_destroy_world (world); - world = 0; - - VERIFY (engine); - xr_delete (engine); - - FreeLibrary (s_script_debugger_handle); - s_script_debugger_handle = 0; - - SetLogCB (s_old_log_callback); -} - -void CScriptEngine::try_connect_to_debugger () -{ - if (m_lua_studio_world) - return; - - initialize_lua_studio ( lua(), m_lua_studio_world, m_lua_studio_engine ); -} - -void CScriptEngine::disconnect_from_debugger () -{ - if (!m_lua_studio_world) - return; - - finalize_lua_studio ( lua(), m_lua_studio_world, m_lua_studio_engine ); -} -#endif //-(USE_DEBUGGER) && defined(USE_LUA_STUDIO) - -void CScriptEngine::setup_callbacks() -{ -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if( debugger() ) - debugger()->PrepareLuaBind (); -# endif // #ifndef USE_LUA_STUDIO -#endif - -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if (!debugger() || !debugger()->Active() ) -# endif // #ifndef USE_LUA_STUDIO -#endif - { -#if !XRAY_EXCEPTIONS - luabind::set_error_callback(CScriptEngine::lua_error); -#endif - - luabind::set_pcall_callback(CScriptEngine::lua_pcall_failed); - } - -#if !XRAY_EXCEPTIONS - luabind::set_cast_failed_callback(lua_cast_failed); -#endif - lua_atpanic(lua(), CScriptEngine::lua_panic); -} - #ifdef DEBUG -# include "script_thread.h" -void CScriptEngine::lua_hook_call (lua_State *L, lua_Debug *dbg) +void CScriptEngine::lua_hook_call(lua_State *L, lua_Debug *dbg) { - if (ai().script_engine().current_thread()) - ai().script_engine().current_thread()->script_hook(L,dbg); - else - ai().script_engine().m_stack_is_ready = true; + ai().script_engine().m_stack_is_ready = true; } #endif -void CScriptEngine::remove_script_process(const EScriptProcessors& process_id) -{ - CScriptProcessStorage::iterator I = m_script_processes.find(process_id); - if (I != m_script_processes.end()) - { - xr_delete((*I).second); - m_script_processes.erase(I); - } -} - -bool CScriptEngine::load_package(LPCSTR caNamespaceName, bool warn_if_not_exist) -{ - if (*caNamespaceName && xr_strcmp(caNamespaceName, "_G") && namespace_loaded(caNamespaceName)) - { - return true; - } - - string_path caScriptName, S1; - FS.update_path(caScriptName, "$game_scripts$", strconcat(sizeof(S1), S1, caNamespaceName, ".script")); - if (!warn_if_not_exist && !FS.exist(caScriptName)) - { -#ifdef DEBUG -# ifndef XRSE_FACTORY_EXPORTS - if (psAI_Flags.test(aiNilObjectAccess)) -# endif - { - print_stack(); - Msg("* trying to access variable %s, which doesn't exist, or to load script %s, which doesn't exist too", file_name, S); - m_stack_is_ready = true; - } -#endif - return false; - } - - //#ifndef MASTER_GOLD - if (strstr(Core.Params, "-dbg")) - Msg("* loading script %s", S1); - //#endif // MASTER_GOLD - - if (!caNamespaceName) - caNamespaceName = "_G"; - - int start = lua_gettop(lua()); - string_path l_caLuaFileName; - IReader* l_tpFileReader = FS.r_open(caScriptName); - - if (!l_tpFileReader) - { - script_log(eLuaMessageTypeError, "Cannot open file \"%s\"", caScriptName); - return (false); - } - - auto scriptContents = static_cast(l_tpFileReader->pointer()); - auto scriptLength = (size_t)l_tpFileReader->length(); - - strconcat(sizeof(l_caLuaFileName), l_caLuaFileName, "@", caScriptName); - if (load_buffer(lua(), scriptContents, scriptLength, l_caLuaFileName, caNamespaceName)) - { - // VERIFY (lua_gettop(lua()) >= 4); - // lua_pop (lua(),4); - // VERIFY (lua_gettop(lua()) == start - 3); - lua_settop(lua(), start); - FS.r_close(l_tpFileReader); - return (false); - } - FS.r_close(l_tpFileReader); - - int errFuncId = -1; -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if (ai().script_engine().debugger()) - errFuncId = ai().script_engine().debugger()->PrepareLua(lua()); -# endif // #ifndef USE_LUA_STUDIO -#endif // #ifdef USE_DEBUGGER - if (0) //. - { - for (int i = 0; lua_type(lua(), -i - 1); i++) - Msg("%2d : %s", -i - 1, lua_typename(lua(), lua_type(lua(), -i - 1))); - } - - // because that's the first and the only call of the main chunk - there is no point to compile it - // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_OFF); // Oles - int l_iErrorCode = lua_pcall(lua(), 0, 0, (-1 == errFuncId) ? 0 : errFuncId); // new_Andy - // luaJIT_setmode (lua(),0,LUAJIT_MODE_ENGINE|LUAJIT_MODE_ON); // Oles - -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - if (ai().script_engine().debugger()) - ai().script_engine().debugger()->UnPrepareLua(lua(), errFuncId); -# endif // #ifndef USE_LUA_STUDIO -#endif // #ifdef USE_DEBUGGER - if (l_iErrorCode) - { - //#ifdef DEBUG - if (strstr(Core.Params, "-dbg")) print_output(lua(), caScriptName, l_iErrorCode); - //#endif - on_error(lua()); - Msg("! [ERROR] --- Failed to load script %s", caNamespaceName); - lua_settop(lua(), start); - return (false); - } - - VERIFY(lua_gettop(lua()) == start); - return (true); -} - -void CScriptEngine::unload_package(LPCSTR name) -{ - lua_getglobal(lua(), "package"); - lua_getfield(lua(), -1, "loaded"); - lua_remove(lua(), -2); - lua_pushnil(lua()); - lua_setfield(lua(), -2, name); - lua_remove(lua(), -1); -} - bool CScriptEngine::function_object(LPCSTR function_to_call, luabind::object& out, int type) { int start = lua_gettop(lua()); @@ -1335,40 +947,18 @@ bool CScriptEngine::function_object(LPCSTR function_to_call, luabind::object& ou return is_type; } -void CScriptEngine::collect_all_garbage() -{ - lua_gc(lua(), LUA_GCCOLLECT, 0); - lua_gc(lua(), LUA_GCCOLLECT, 0); -} - -void CScriptEngine::on_error(lua_State* state) +CScriptProcesses CScriptEngine::script_processes() { -#if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) - if (!debugger()) - return; - - debugger()->on_error(state); -#endif // #if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) + return CScriptProcesses(lua()); } -#if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO) -void CScriptEngine::stopDebugger () +void CScriptEngine::collect_all_garbage() { - if (debugger()){ - xr_delete (m_scriptDebugger); - Msg ("Script debugger succesfully stoped."); - } - else - Msg ("Script debugger not present."); + lua_gc(lua(), LUA_GCCOLLECT, 0); } -void CScriptEngine::restartDebugger () +void CScriptEngine::on_error(lua_State* L) { - if(debugger()) - stopDebugger(); - - m_scriptDebugger = xr_new(); - debugger()->PrepareLuaBind(); - Msg ("Script debugger succesfully restarted."); + CScriptEngine::print_output(L, "", LUA_ERRRUN); + FATAL("LUA error"); } -#endif // #if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO) diff --git a/src/xrServerEntities/script_engine.h b/src/xrServerEntities/script_engine.h index a859c18650..1fb254c846 100644 --- a/src/xrServerEntities/script_engine.h +++ b/src/xrServerEntities/script_engine.h @@ -11,6 +11,7 @@ #include "script_engine_space.h" #include "script_export_space.h" #include "script_space_forward.h" +#include "script_processes.h" #include "associative_vector.h" //AVO: lua re-org @@ -22,13 +23,6 @@ //#define DBG_DISABLE_SCRIPTS -#include "script_engine_space.h" - -#ifndef MASTER_GOLD -# define USE_DEBUGGER -# define USE_LUA_STUDIO -#endif //-!MASTER_GOLD - #ifdef XRGAME_EXPORTS # ifndef MASTER_GOLD # define PRINT_CALL_STACK @@ -50,49 +44,20 @@ using namespace ScriptEngine; -class CScriptProcess; -class CScriptThread; struct lua_State; struct lua_Debug; -typedef associative_vector CScriptProcessStorage; - -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - class CScriptDebugger; -# else // #ifndef USE_LUA_STUDIO - namespace cs { - namespace lua_studio { - struct world; - } // namespace lua_studio - } // namespace cs - - class lua_studio_engine; -# endif // #ifndef USE_LUA_STUDIO -#endif - class CScriptEngine { private: lua_State* m_virtual_machine; - CScriptThread* m_current_thread; protected: - CScriptProcessStorage m_script_processes; int m_stack_level; -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - CScriptDebugger* m_scriptDebugger; -# else // #ifndef USE_LUA_STUDIO - cs::lua_studio::world* m_lua_studio_world; - lua_studio_engine* m_lua_studio_engine; -# endif // #ifndef USE_LUA_STUDIO -#endif // #ifdef USE_DEBUGGER - #ifdef DEBUG public: - bool m_stack_is_ready; + bool m_stack_is_ready; #endif //-DEBUG #ifdef LUA_DEBUG_PRINT//PRINT_CALL_STACK @@ -110,44 +75,27 @@ class CScriptEngine ~CScriptEngine(); void init(); + void setup_callbacks(); void unload(); - IC void current_thread(CScriptThread* thread); - IC CScriptThread* current_thread() const; - - IC CScriptProcess* script_process(const EScriptProcessors& process_id) const; - IC void add_script_process(const EScriptProcessors& process_id, CScriptProcess* script_process); - void remove_script_process(const EScriptProcessors& process_id); - - IC lua_State* lua(); - static int lua_panic(lua_State* L); - static void lua_error(lua_State* L); - static int lua_pcall_failed(lua_State* L); + IC lua_State* lua() { return m_virtual_machine; } + CScriptProcesses script_processes(); #ifdef DEBUG - static void lua_hook_call(lua_State* L, lua_Debug* dbg); + static void lua_hook_call(lua_State* L, lua_Debug* dbg); #endif // #ifdef DEBUG - - void setup_callbacks(); - int compile_buffer( - lua_State* L, - std::string caString, + int load_string( + LPCSTR caString, LPCSTR caScriptName, LPCSTR caNameSpaceName = 0 ); - int load_buffer( - lua_State* L, - LPCSTR caBuffer, - size_t tSize, + + int do_string( + LPCSTR caString, LPCSTR caScriptName, LPCSTR caNameSpaceName = 0 ); - - bool namespace_loaded(LPCSTR caName, bool remove_from_stack = true); - luabind::object name_space(LPCSTR namespace_name); - bool load_package(LPCSTR file_name, bool warn_if_not_exist = true); - void unload_package(LPCSTR package); int error_log(LPCSTR caFormat, ...); static int __cdecl script_log(ELuaMessageType message, LPCSTR caFormat, ...); @@ -162,7 +110,7 @@ class CScriptEngine bool function_object(LPCSTR function_to_call, luabind::object& object, int type = LUA_TFUNCTION); template - IC bool functor(LPCSTR function_to_call, luabind::functor<_result_type>& lua_function); + bool functor(LPCSTR function_to_call, luabind::functor<_result_type>& lua_function); //#ifdef PRINT_CALL_STACK void print_stack(); @@ -173,18 +121,6 @@ class CScriptEngine void collect_all_garbage(); -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - void stopDebugger(); - void restartDebugger(); - CScriptDebugger* debugger(); -# else // ifndef USE_LUA_STUDIO - void try_connect_to_debugger(); - void disconnect_from_debugger(); - inline cs::lua_studio::world* debugger() const { return m_lua_studio_world; } -# endif // ifndef USE_LUA_STUDIO -#endif - protected: void reinit(); static int vscript_log(ELuaMessageType tLuaMessageType, LPCSTR caFormat, va_list marker); diff --git a/src/xrServerEntities/script_engine_inline.h b/src/xrServerEntities/script_engine_inline.h index 8124cfd6df..2af6fedbbc 100644 --- a/src/xrServerEntities/script_engine_inline.h +++ b/src/xrServerEntities/script_engine_inline.h @@ -8,37 +8,6 @@ #pragma once -IC lua_State* CScriptEngine::lua() -{ - return (m_virtual_machine); -} - -IC void CScriptEngine::current_thread(CScriptThread* thread) -{ - VERIFY((thread && !m_current_thread) || !thread); - m_current_thread = thread; -} - -IC CScriptThread* CScriptEngine::current_thread() const -{ - return (m_current_thread); -} - -IC void CScriptEngine::add_script_process(const EScriptProcessors& process_id, CScriptProcess* script_process) -{ - // CScriptProcessStorage::const_iterator I = m_script_processes.find(process_id); - // VERIFY (I == m_script_processes.end()); - m_script_processes.insert(std::make_pair(process_id, script_process)); -} - -CScriptProcess* CScriptEngine::script_process(const EScriptProcessors& process_id) const -{ - CScriptProcessStorage::const_iterator I = m_script_processes.find(process_id); - if ((I != m_script_processes.end())) - return ((*I).second); - return (0); -} - template IC bool CScriptEngine::functor(LPCSTR function_to_call, luabind::functor<_result_type>& lua_function) { @@ -57,13 +26,3 @@ IC bool CScriptEngine::functor(LPCSTR function_to_call, luabind::functor<_result return (true); } - -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO - IC CScriptDebugger *CScriptEngine::debugger () - { - return (m_scriptDebugger); - } -# else // ifndef USE_LUA_STUDIO -# endif // ifndef USE_LUA_STUDIO -#endif // #ifdef USE_DEBUGGER diff --git a/src/xrServerEntities/script_engine_script.cpp b/src/xrServerEntities/script_engine_script.cpp index 56c1d9a555..6f3de0e1f1 100644 --- a/src/xrServerEntities/script_engine_script.cpp +++ b/src/xrServerEntities/script_engine_script.cpp @@ -9,7 +9,6 @@ #include "pch_script.h" #include "script_engine.h" #include "ai_space.h" -#include "script_debugger.h" #include "new_sds.h" using namespace luabind; @@ -73,9 +72,9 @@ void FlushLogs() #endif // DEBUG } -void verify_if_thread_is_running() -{ - THROW2(ai().script_engine().current_thread(), "coroutine.yield() is called outside the LUA thread!"); +void verify_if_thread_is_running() { + // Dummied, as it is unused; only callsite is in _g, and commented out + // Lua threads (coroutines) are now managed by Lua, so should be verified in script } bool is_editor() @@ -83,7 +82,7 @@ bool is_editor() #ifdef XRGAME_EXPORTS return (false); #else - return (true); + return (true); #endif } @@ -121,7 +120,9 @@ LPCSTR user_name() void prefetch_module(LPCSTR file_name) { - ai().script_engine().load_package(file_name); + lua_getglobal(ai().script_engine().lua(), "require"); + lua_pushstring(ai().script_engine().lua(), file_name); + lua_call(ai().script_engine().lua(), 1, 0); } struct profile_timer_script diff --git a/src/xrServerEntities/script_engine_space.h b/src/xrServerEntities/script_engine_space.h index 15c4617c97..4c1fe630e9 100644 --- a/src/xrServerEntities/script_engine_space.h +++ b/src/xrServerEntities/script_engine_space.h @@ -21,11 +21,4 @@ namespace ScriptEngine eLuaMessageTypeHookCount, eLuaMessageTypeHookTailReturn = u32(-1), }; - - enum EScriptProcessors - { - eScriptProcessorLevel = u32(0), - eScriptProcessorGame, - eScriptProcessorDummy = u32(-1), - }; }; diff --git a/src/xrServerEntities/script_lua_helper.cpp b/src/xrServerEntities/script_lua_helper.cpp deleted file mode 100644 index e16d7cf1d5..0000000000 --- a/src/xrServerEntities/script_lua_helper.cpp +++ /dev/null @@ -1,553 +0,0 @@ -#include "pch_script.h" -#include "script_lua_helper.h" -#include "script_debugger.h" - -CDbgLuaHelper* CDbgLuaHelper::m_pThis = NULL; -lua_State* CDbgLuaHelper::L = NULL; - -CDbgLuaHelper::CDbgLuaHelper(CScriptDebugger* d) - : m_debugger(d) -{ - m_pThis = this; -} - -CDbgLuaHelper::~CDbgLuaHelper() -{ - m_pThis = NULL; -} - -void CDbgLuaHelper::UnPrepareLua(lua_State* l, int idx) -{ - lua_remove(l, idx); -} - -int CDbgLuaHelper::PrepareLua(lua_State* l) -{ - // call this function immediatly before calling lua_pcall. - //returns index in stack for errorFunc - // return 0; - lua_register(l, "DEBUGGER_ERRORMESSAGE", errormessageLua); - lua_sethook(l, hookLua, LUA_MASKLINE | LUA_MASKCALL | LUA_MASKRET, 0); - - int top = lua_gettop(l); - lua_getglobal(l, "DEBUGGER_ERRORMESSAGE"); - lua_insert(l, top); - return top; -} - - -void CDbgLuaHelper::PrepareLuaBind() -{ - luabind::set_pcall_callback(hookLuaBind); -#if !XRAY_EXCEPTIONS - luabind::set_error_callback(errormessageLuaBind); -#endif -} - - -int CDbgLuaHelper::OutputTop(lua_State* L) -{ - if (!m_pThis)return 0; - m_pThis->debugger()->Write(luaL_checkstring(L, -1)); - m_pThis->debugger()->Write("\n"); - return 0; -} - -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ - -void CDbgLuaHelper::errormessageLuaBind(lua_State* l) -{ - if (!m_pThis)return; - L = l; - - char err_msg[8192]; - xr_sprintf(err_msg, "%s",lua_tostring(L, -1)); - m_pThis->debugger()->Write(err_msg); - m_pThis->debugger()->Write("\n"); - m_pThis->debugger()->ErrorBreak(); - FATAL("LUABIND error"); -} - -int CDbgLuaHelper::errormessageLua(lua_State* l) -{ - if (!m_pThis)return 0; - L = l; - int level = 1; /* skip level 0 (it's this function) */ - - int firstpart = 1; /* still before eventual `...' */ - lua_Debug ar; - if (!lua_isstring(L, 1)) - return lua_gettop(L); - lua_settop(L, 1); - lua_pushliteral(L, "\n"); - lua_pushliteral(L, "stack traceback:\n"); - while (lua_getstack(L, level++, &ar)) - { - char buff[10]; - if (level > LEVELS1 && firstpart) - { - /* no more than `LEVELS2' more levels? */ - if (!lua_getstack(L, level + LEVELS2, &ar)) - level--; /* keep going */ - else - { - lua_pushliteral(L, " ...\n"); /* too many levels */ - while (lua_getstack(L, level + LEVELS2, &ar)) /* find last levels */ - level++; - } - firstpart = 0; - continue; - } - - xr_sprintf(buff, "%4d- ", level - 1); - lua_pushstring(L, buff); - lua_getinfo(L, "Snl", &ar); - lua_pushfstring(L, "%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - switch (*ar.namewhat) - { - case 'g': /* global */ - case 'l': /* local */ - case 'f': /* field */ - case 'm': /* method */ - lua_pushfstring(L, " in function `%s'", ar.name); - break; - default: - { - if (*ar.what == 'm') /* main? */ - lua_pushfstring(L, " in main chunk"); - else if (*ar.what == 'C') /* C function? */ - lua_pushfstring(L, "%s", ar.short_src); - else - lua_pushfstring(L, " in function <%s:%d>", ar.short_src, ar.linedefined); - } - } - - lua_pushliteral(L, "\n"); - lua_concat(L, lua_gettop(L)); - } - - lua_concat(L, lua_gettop(L)); - - OutputTop(L); - const char* szSource = NULL; - if (ar.source[0] == '@') - szSource = ar.source + 1; - m_pThis->debugger()->ErrorBreak(szSource, ar.currentline); - FATAL("LUA error"); - - return 0; -} - -void CDbgLuaHelper::set_lua(lua_State* l) -{ - if (!m_pThis) return; - m_pThis->L = l; -} - -void CDbgLuaHelper::line_hook(lua_State* l, lua_Debug* ar) -{ - if (!m_pThis) return; - lua_getinfo(L, "lnuS", ar); - m_pThis->m_pAr = ar; - - if (ar->source[0] == '@') - { - m_pThis->debugger()->LineHook(ar->source + 1, ar->currentline); - } -} - -void CDbgLuaHelper::func_hook(lua_State* l, lua_Debug* ar) -{ - if (!m_pThis) return; - lua_getinfo(L, "lnuS", ar); - m_pThis->m_pAr = ar; - - const char* szSource = NULL; - if (ar->source[0] == '@') - { - szSource = ar->source + 1; - }; - m_pThis->debugger()->FunctionHook(szSource, ar->currentline, ar->event == LUA_HOOKCALL); -} - -void print_stack(lua_State* L) -{ - Msg(" "); - for (int i = 0; lua_type(L, -i - 1); i++) - Msg("%2d : %s", -i - 1, lua_typename(L, lua_type(L, -i - 1))); -} - -int CDbgLuaHelper::hookLuaBind(lua_State* l) -{ - if (!m_pThis) return 0; - L = l; - int top1 = lua_gettop(L); - - Msg("hookLuaBind start"); - print_stack(L); - - if (lua_isstring(L, -1)) - errormessageLuaBind(L); - // Msg("Tope string %s",lua_tostring(L,-1)); - - lua_Debug ar; - lua_getstack(L, 0, &ar); - lua_getinfo(L, "lnuS", &ar); - hookLua(L, &ar); - - Msg("hookLuaBind end"); - print_stack(L); - - if (lua_isstring(L, -1)) - Msg("Tope string %s",lua_tostring(L, -1)); - - int top2 = lua_gettop(L); - VERIFY(top2==top1); - return 0; -} - -void CDbgLuaHelper::hookLua(lua_State* l, lua_Debug* ar) -{ - if (!m_pThis) return; - L = l; - int top1 = lua_gettop(L); - - // Msg ("hookLua start"); - // print_stack(L); - - switch (ar->event) - { - case LUA_HOOKTAILRET: - case LUA_HOOKRET: - case LUA_HOOKCALL: - func_hook(L, ar); - break; - case LUA_HOOKLINE: - line_hook(L, ar); - break; - } - - // Msg ("hookLua end"); - // print_stack(L); - - int top2 = lua_gettop(L); - VERIFY(top2==top1); -} - -const char* CDbgLuaHelper::GetSource() -{ - return m_pAr->source + 1; -}; - - -void CDbgLuaHelper::DrawStackTrace() -{ - debugger()->ClearStackTrace(); - - int nLevel = 0; - lua_Debug ar; - char szDesc[256]; - while (lua_getstack(L, nLevel, &ar)) - { - lua_getinfo(L, "lnuS", &ar); - if (ar.source[0] == '@') - { - szDesc[0] = '\0'; - /* if ( ar.name ) - xr_strcat(szDesc, ar.name); - xr_strcat(szDesc, ","); - if ( ar.namewhat ) - xr_strcat(szDesc, ar.namewhat); - xr_strcat(szDesc, ","); - if ( ar.what ) - xr_strcat(szDesc, ar.what); - xr_strcat(szDesc, ","); - */ - if (ar.name) - { - xr_strcat(szDesc, ar.name); - xr_strcat(szDesc, " "); - } - - char szTmp[6]; - - xr_strcat(szDesc, itoa(ar.currentline, szTmp, 10)); - xr_strcat(szDesc, " "); - - if (ar.short_src) - xr_strcat(szDesc, ar.short_src); - - debugger()->AddStackTrace(szDesc, ar.source + 1, ar.currentline); - } - - ++nLevel; - }; -} - -void CDbgLuaHelper::DrawLocalVariables() -{ - debugger()->ClearLocalVariables(); - - int nLevel = debugger()->GetStackTraceLevel(); - lua_Debug ar; - if (lua_getstack(L, nLevel, &ar)) - { - int i = 1; - const char* name; - while ((name = lua_getlocal(L, &ar, i++)) != NULL) - { - DrawVariable(L, name, true); - - lua_pop(L, 1); /* remove variable value */ - } - } -} - -void CDbgLuaHelper::DrawGlobalVariables() -{ - debugger()->ClearGlobalVariables(); - - lua_pushvalue(L, LUA_GLOBALSINDEX); - - lua_pushnil(L); /* first key */ - string1024 var; - var[0] = 0; - while (lua_next(L, -2)) - { - //!!!! TRACE2("%s - %s\n", lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1))); - // xr_sprintf(var, "%s-%s", lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1)) ); - // CScriptDebugger::GetDebugger()->AddLocalVariable(var, "global", "_g_"); - lua_pop(L, 1); // pop value, keep key for next iteration; - } - lua_pop(L, 1); // pop table of globals; -}; - -bool CDbgLuaHelper::GetCalltip(const char* szWord, char* szCalltip, int sz_calltip) -{ - int nLevel = debugger()->GetStackTraceLevel(); - lua_Debug ar; - if (lua_getstack(L, nLevel, &ar)) - { - int i = 1; - const char* name; - while ((name = lua_getlocal(L, &ar, i++)) != NULL) - { - if (xr_strcmp(name, szWord) == 0) - { - char szRet[64]; - Describe(szRet, -1, sizeof(szRet)); - xr_sprintf(szCalltip, sz_calltip, "local %s : %s ", name, szRet); - lua_pop(L, 1); /* remove variable value */ - return true; - } - - lua_pop(L, 1); /* remove variable value */ - } - } - - lua_pushvalue(L, LUA_GLOBALSINDEX); - - lua_pushnil(L); /* first key */ - while (lua_next(L, -2)) - { - const char* name = lua_tostring(L, -2); - if (xr_strcmp(name, szWord) == 0) - { - char szRet[64]; - Describe(szRet, -1, sizeof(szRet)); - xr_sprintf(szCalltip, sz_calltip, "global %s : %s ", name, szRet); - - lua_pop(L, 3); /* remove table, key, value */ - - return true; - } - - lua_pop(L, 1); // pop value, keep key for next iteration; - } - lua_pop(L, 1); // pop table of globals; - - return false; -} - - -bool CDbgLuaHelper::Eval(const char* szCode, char* szRet, int szret_size) -{ - CoverGlobals(); - - int top = lua_gettop(L); - int status = luaL_loadbuffer(L, szCode, xr_strlen(szCode), szCode); - if (status) - xr_sprintf(szRet, szret_size, "%s", luaL_checkstring(L, -1)); - else - { - status = lua_pcall(L, 0, LUA_MULTRET, 0); /* call main */ - if (status) - { - const char* szErr = luaL_checkstring(L, -1); - const char* szErr2 = strstr(szErr, ": "); - xr_sprintf(szRet, szret_size, "%s", szErr2 ? (szErr2 + 2) : szErr); - } - else - Describe(szRet, -1, szret_size); - } - - lua_settop(L, top); - - RestoreGlobals(); - - return !status; -} - -void CDbgLuaHelper::Describe(char* szRet, int nIndex, int szRet_size) -{ - int ntype = lua_type(L, nIndex); - const char* type = lua_typename(L, ntype); - char value[64]; - - switch (ntype) - { - case LUA_TNUMBER: - xr_sprintf(value, "%f", lua_tonumber(L, nIndex)); - break; - case LUA_TSTRING: - xr_sprintf(value, "%.63s", lua_tostring(L, nIndex)); - break; - case LUA_TBOOLEAN: - xr_sprintf(value, "%s", lua_toboolean(L, nIndex) ? "true" : "false"); - break; - default: - value[0] = '\0'; - break; - } - xr_sprintf(szRet, szRet_size, "%s : %.64s", type, value); -} - -void CDbgLuaHelper::CoverGlobals() -{ - lua_newtable(L); // save there globals covered by locals - - int nLevel = debugger()->GetStackTraceLevel(); - lua_Debug ar; - if (lua_getstack(L, nLevel, &ar)) - { - int i = 1; - const char* name; - while ((name = lua_getlocal(L, &ar, i++)) != NULL) - { - /* SAVE lvalue */ - lua_pushstring(L, name); /* SAVE lvalue name */ - lua_pushvalue(L, -1); /* SAVE lvalue name name */ - lua_pushvalue(L, -1); /* SAVE lvalue name name name */ - lua_insert(L, -4); /* SAVE name lvalue name name */ - lua_rawget(L, LUA_GLOBALSINDEX); /* SAVE name lvalue name gvalue */ - - lua_rawset(L, -5); // save global value in local table - /* SAVE name lvalue */ - - lua_rawset(L, LUA_GLOBALSINDEX); /* SAVE */ - } - } -} - -void CDbgLuaHelper::RestoreGlobals() -{ - // there is table of covered globals on top - - lua_pushnil(L); /* first key */ - /* SAVE nil */ - while (lua_next(L, -2)) /* SAVE key value */ - { - lua_pushvalue(L, -2); /* SAVE key value key */ - lua_insert(L, -2); /* SAVE key key value */ - - lua_rawset(L, LUA_GLOBALSINDEX); // restore global - /* SAVE key */ - } - - lua_pop(L, 1); // pop table of covered globals; -} - -void CDbgLuaHelper::DrawVariable(lua_State* l, const char* name, bool bOpenTable) -{ - Variable var; - xr_strcpy(var.szName, name); - - const char* type; - int ntype = lua_type(l, -1); - type = lua_typename(l, ntype); - xr_strcpy(var.szType, type); - - char value[64]; - - switch (ntype) - { - case LUA_TNUMBER: - xr_sprintf(value, "%f", lua_tonumber(l, -1)); - xr_strcpy(var.szValue, value); - break; - - case LUA_TBOOLEAN: - xr_sprintf(value, "%s", lua_toboolean(L, -1) ? "true" : "false"); - xr_strcpy(var.szValue, value); - break; - - case LUA_TSTRING: - xr_sprintf(value, "%.63s", lua_tostring(l, -1)); - xr_strcpy(var.szValue, value); - break; - - - case LUA_TTABLE: - var.szValue[0] = 0; - debugger()->AddLocalVariable(var); - if (bOpenTable) - DrawTable(l, name, false); - return; - break; - - - /* case LUA_TUSERDATA:{ - luabind::detail::object_rep* obj = static_cast(lua_touserdata(L, -1)); - luabind::detail::lua_reference& r = obj->get_lua_table(); - lua_State * ls = NULL; - r.get(ls); - DrawTable(ls, name); - return; - }break;*/ - - default: - value[0] = '\0'; - break; - } - - debugger()->AddLocalVariable(var); -} - -void CDbgLuaHelper::DrawTable(lua_State* l, LPCSTR S, bool bRecursive) -{ - // char str[1024]; - - if (!lua_istable(l, -1)) - return; - - lua_pushnil(l); /* first key */ - while (lua_next(l, -2) != 0) - { - char stype[256]; - char sname[256]; - char sFullName[256]; - xr_sprintf(stype, "%s", lua_typename(l, lua_type(l, -1))); - xr_sprintf(sname, "%s",lua_tostring(l, -2)); - xr_sprintf(sFullName, "%s.%s", S, sname); - DrawVariable(l, sFullName, false); - - lua_pop(l, 1); /* removes `value'; keeps `key' for next iteration */ - } -} - -void CDbgLuaHelper::DrawVariableInfo(char* varName) -{ -} diff --git a/src/xrServerEntities/script_lua_helper.h b/src/xrServerEntities/script_lua_helper.h deleted file mode 100644 index a4835706cc..0000000000 --- a/src/xrServerEntities/script_lua_helper.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -struct lua_State; -struct Proto; -struct lua_Debug; -class CScriptFile; -class CScriptDebugger; - -class CDbgLuaHelper -{ -public: - void RestoreGlobals(); - void CoverGlobals(); - void Describe(char* szRet, int nIndex, int szRet_size); - bool Eval(const char* szCode, char* szRet, int szret_size); - bool GetCalltip(const char* szWord, char* szCalltip, int sz_calltip); - void DrawGlobalVariables(); - void DrawLocalVariables(); - const char* GetSource(); - - CDbgLuaHelper(CScriptDebugger* d); - virtual ~CDbgLuaHelper(); - - // debugger functions - int PrepareLua(lua_State*); - void UnPrepareLua(lua_State*, int); - void PrepareLuaBind(); - - - void DrawStackTrace(); - static int OutputTop(lua_State*); - - static void hookLua(lua_State*, lua_Debug*); - static int hookLuaBind(lua_State*); - - static int errormessageLua(lua_State*); - static void errormessageLuaBind(lua_State*); - static void line_hook(lua_State*, lua_Debug*); - static void func_hook(lua_State*, lua_Debug*); - static void set_lua(lua_State*); - void DrawVariable(lua_State* l, const char* name, bool bOpenTable); - void DrawTable(lua_State* l, const char* name, bool bRecursive = true); - void DrawVariableInfo(char*); - CScriptDebugger* debugger() { return m_debugger; } -protected: - CScriptDebugger* m_debugger; - static CDbgLuaHelper* m_pThis; - - - static lua_State* L; - lua_Debug* m_pAr; -}; diff --git a/src/xrServerEntities/script_process.cpp b/src/xrServerEntities/script_process.cpp deleted file mode 100644 index ab1a016736..0000000000 --- a/src/xrServerEntities/script_process.cpp +++ /dev/null @@ -1,106 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_process.cpp -// Created : 19.09.2003 -// Modified : 29.06.2004 -// Author : Dmitriy Iassenev -// Description : Script process class -//////////////////////////////////////////////////////////////////////////// - -#include "pch_script.h" -#include "script_engine.h" -#include "script_process.h" -#include "script_thread.h" -#include "ai_space.h" -#include "object_broker.h" - -string4096 g_ca_stdout; - -CScriptProcess::CScriptProcess(shared_str name, shared_str scripts) : - m_name(name) -{ -#ifdef DEBUG - Msg ("* Initializing %s script process",*m_name); -#endif - - string256 I; - for (u32 i = 0, n = _GetItemCount(*scripts); i < n; ++i) - add_script(_GetItem(*scripts, i, I), false, false); - - m_iterator = 0; -} - -CScriptProcess::~CScriptProcess() -{ - delete_data(m_scripts); -} - -void CScriptProcess::run_scripts() -{ - LPSTR S; - for (; !m_scripts_to_run.empty();) - { - LPSTR I = m_scripts_to_run.back().m_script_name; - bool do_string = m_scripts_to_run.back().m_do_string; - bool reload = m_scripts_to_run.back().m_reload; - S = xr_strdup(I); - m_scripts_to_run.pop_back(); - - if (!do_string && reload) - ai().script_engine().unload_package(S); - - CScriptThread* script = xr_new(S, do_string); - xr_free(S); - - if (script->active()) - m_scripts.push_back(script); - else - xr_delete(script); - } -} - -// Oles: -// changed to process one script per-frame -// changed log-output to stack-based buffer (avoid persistent 4K storage) -void CScriptProcess::update() -{ -#ifdef DBG_DISABLE_SCRIPTS - m_scripts_to_run.clear(); - return; -#endif - - run_scripts(); - - if (m_scripts.empty()) - return; - - // update script - g_ca_stdout[0] = 0; - u32 _id = (++m_iterator) % m_scripts.size(); - if (!m_scripts[_id]->update()) - { - xr_delete(m_scripts[_id]); - m_scripts.erase(m_scripts.begin() + _id); - --m_iterator; // try to avoid skipping - } - - if (g_ca_stdout[0]) - { - fputc(0,stderr); - ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeInfo, "%s", g_ca_stdout); - fflush(stderr); - } - -#if defined(DEBUG) - try { -#pragma todo ("Dima cant find this function 'lua_setgcthreshold' ") - lua_gc (ai().script_engine().lua(), LUA_GCSTEP, 0); - } - catch(...) { - } -#endif -} - -void CScriptProcess::add_script(LPCSTR script_name, bool do_string, bool reload) -{ - m_scripts_to_run.push_back(CScriptToRun(script_name, do_string, reload)); -} diff --git a/src/xrServerEntities/script_process.h b/src/xrServerEntities/script_process.h index 3948a3e8e4..93180f05c7 100644 --- a/src/xrServerEntities/script_process.h +++ b/src/xrServerEntities/script_process.h @@ -1,68 +1,36 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_process.h -// Created : 19.09.2003 -// Modified : 29.06.2004 -// Author : Dmitriy Iassenev -// Description : Script process class -//////////////////////////////////////////////////////////////////////////// - -#pragma once - -class CScriptThread; +#include class CScriptProcess { -public: - typedef xr_vector SCRIPT_REGISTRY; - private: - struct CScriptToRun - { - LPSTR m_script_name; - bool m_do_string; - bool m_reload; - - IC CScriptToRun(LPCSTR script_name, bool do_string, bool reload = false) - { - m_script_name = xr_strdup(script_name); - m_do_string = do_string; - m_reload = reload; - } - - IC CScriptToRun(const CScriptToRun& script) - { - m_script_name = xr_strdup(script.m_script_name); - m_do_string = script.m_do_string; - m_reload = script.m_reload; - } - - virtual ~CScriptToRun() - { - xr_free(m_script_name); - } - }; + luabind::object m_obj; public: - typedef xr_vector SCRIPTS_TO_RUN; - -protected: - SCRIPT_REGISTRY m_scripts; - SCRIPTS_TO_RUN m_scripts_to_run; - shared_str m_name; - -protected: - u32 m_iterator; // Oles: iterative update - -protected: - void run_scripts(); - -public: - CScriptProcess(shared_str anme, shared_str scripts); - virtual ~CScriptProcess(); - void update(); - void add_script(LPCSTR script_name, bool string, bool reload); - IC const SCRIPT_REGISTRY& scripts() const; - IC shared_str name() const; + CScriptProcess(luabind::object obj) + { + m_obj = obj; + } + + ~CScriptProcess() {} + + template + luabind::functor functor(LPCSTR field) + { + return luabind::object_cast>(m_obj[field]); + } + + void update() + { + functor("update")(m_obj); + } + + void add_script(LPCSTR name, bool reload) + { + functor("add_script")(m_obj, name, reload); + } + + void add_string(LPCSTR src) + { + functor("add_string")(m_obj, src); + } }; - -#include "script_process_inline.h" diff --git a/src/xrServerEntities/script_process_inline.h b/src/xrServerEntities/script_process_inline.h deleted file mode 100644 index b20c033103..0000000000 --- a/src/xrServerEntities/script_process_inline.h +++ /dev/null @@ -1,19 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_process_inline.h -// Created : 19.09.2003 -// Modified : 29.06.2004 -// Author : Dmitriy Iassenev -// Description : Script process class inline functions -//////////////////////////////////////////////////////////////////////////// - -#pragma once - -IC const CScriptProcess::SCRIPT_REGISTRY& CScriptProcess::scripts() const -{ - return (m_scripts); -} - -IC shared_str CScriptProcess::name() const -{ - return (m_name); -} diff --git a/src/xrServerEntities/script_processes.h b/src/xrServerEntities/script_processes.h new file mode 100644 index 0000000000..6eb8a621e8 --- /dev/null +++ b/src/xrServerEntities/script_processes.h @@ -0,0 +1,47 @@ +#include +#include "script_process.h" + +class CScriptProcesses +{ +private: + luabind::object m_obj; + +public: + CScriptProcesses(lua_State* L) + { + lua_getglobal(L, "require"); + lua_pushstring(L, "amx/processes"); + lua_call(L, 1, 1); + + m_obj = luabind::object(L); + m_obj.set(); + } + + ~CScriptProcesses() {} + + template + luabind::functor functor(LPCSTR field) + { + return luabind::object_cast>(m_obj[field]); + } + + void add(LPCSTR name, LPCSTR scripts) + { + functor("add")(m_obj, name, scripts); + } + + void remove(LPCSTR name) + { + functor("remove")(m_obj, name); + } + + bool has(LPCSTR name) + { + return functor("has")(m_obj, name); + } + + CScriptProcess get(LPCSTR name) + { + return CScriptProcess(functor("get")(m_obj, name)); + } +}; \ No newline at end of file diff --git a/src/xrServerEntities/script_stack_tracker.cpp b/src/xrServerEntities/script_stack_tracker.cpp deleted file mode 100644 index 46da3cb340..0000000000 --- a/src/xrServerEntities/script_stack_tracker.cpp +++ /dev/null @@ -1,92 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_stack_tracker.cpp -// Created : 21.04.2004 -// Modified : 21.04.2004 -// Author : Dmitriy Iassenev -// Description : Script stack tracker -//////////////////////////////////////////////////////////////////////////// - -#include "pch_script.h" -#include "script_stack_tracker.h" -#include "ai_space.h" -#include "script_engine.h" - -CScriptStackTracker::CScriptStackTracker() -{ - m_current_stack_level = 0; - for (int i = 0; i < max_stack_size; ++i) - m_stack[i] = xr_new(); -} - -CScriptStackTracker::~CScriptStackTracker() -{ - for (int i = 0; i < max_stack_size; ++i) - xr_delete(m_stack[i]); -} - -void CScriptStackTracker::script_hook(lua_State* L, lua_Debug* dbg) -{ - VERIFY(L); // && (m_virtual_machine == L)); - - switch (dbg->event) - { - case LUA_HOOKCALL: - { - if (m_current_stack_level >= max_stack_size) - return; - if (!lua_getstack(L, 0, m_stack[m_current_stack_level])) - break; - lua_getinfo(L, "nSlu", m_stack[m_current_stack_level]); - if (m_current_stack_level && lua_getstack(L, 1, m_stack[m_current_stack_level - 1])) - lua_getinfo(L, "nSlu", m_stack[m_current_stack_level - 1]); - ++m_current_stack_level; - break; - } - case LUA_HOOKRET: - { - if (m_current_stack_level > 0) - --m_current_stack_level; - break; - } - case LUA_HOOKTAILRET: - { - if (m_current_stack_level > 0) - --m_current_stack_level; - break; - } - case LUA_HOOKLINE: - { - lua_getinfo(L, "l", dbg); - m_stack[m_current_stack_level]->currentline = dbg->currentline; - break; - } - case LUA_HOOKCOUNT: - { - lua_getinfo(L, "l", dbg); - m_stack[m_current_stack_level]->currentline = dbg->currentline; - break; - } - default: NODEFAULT; - } -} - -void CScriptStackTracker::print_stack(lua_State* L) -{ - VERIFY(L); // && (m_virtual_machine == L)); - - for (int j = m_current_stack_level - 1, k = 0; j >= 0; --j, ++k) - { - lua_Debug l_tDebugInfo = *m_stack[j]; - if (!l_tDebugInfo.name) - ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", k, - l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, ""); - else if (!xr_strcmp(l_tDebugInfo.what, "C")) - ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "%2d : [C ] %s", k, - l_tDebugInfo.name); - else - ai().script_engine().script_log(ScriptEngine::eLuaMessageTypeError, "%2d : [%s] %s(%d) : %s", k, - l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline, - l_tDebugInfo.name); - } - m_current_stack_level = 0; -} diff --git a/src/xrServerEntities/script_stack_tracker.h b/src/xrServerEntities/script_stack_tracker.h deleted file mode 100644 index 53d9e64cbc..0000000000 --- a/src/xrServerEntities/script_stack_tracker.h +++ /dev/null @@ -1,33 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_stack_tracker.h -// Created : 21.04.2004 -// Modified : 21.04.2004 -// Author : Dmitriy Iassenev -// Description : Script stack tracker -//////////////////////////////////////////////////////////////////////////// - -#pragma once - -struct lua_Debug; -struct lua_State; - -class CScriptStackTracker -{ -protected: - enum consts - { - max_stack_size = u32(256), - }; - -protected: - lua_Debug* m_stack[max_stack_size]; - int m_current_stack_level; - -public: - CScriptStackTracker(); - virtual ~CScriptStackTracker(); - void script_hook(lua_State* L, lua_Debug* dbg); - void print_stack(lua_State* L); -}; - -#include "script_stack_tracker_inline.h" diff --git a/src/xrServerEntities/script_stack_tracker_inline.h b/src/xrServerEntities/script_stack_tracker_inline.h deleted file mode 100644 index a9647ebea9..0000000000 --- a/src/xrServerEntities/script_stack_tracker_inline.h +++ /dev/null @@ -1,9 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_stack_tracker_inline.h -// Created : 21.04.2004 -// Modified : 21.04.2004 -// Author : Dmitriy Iassenev -// Description : Script stack tracker inline functions -//////////////////////////////////////////////////////////////////////////// - -#pragma once diff --git a/src/xrServerEntities/script_thread.cpp b/src/xrServerEntities/script_thread.cpp deleted file mode 100644 index 67d424bed9..0000000000 --- a/src/xrServerEntities/script_thread.cpp +++ /dev/null @@ -1,189 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_thread.cpp -// Created : 19.09.2003 -// Modified : 29.06.2004 -// Author : Dmitriy Iassenev -// Description : Script thread class -//////////////////////////////////////////////////////////////////////////// - -#include "pch_script.h" -//AVO: lua re-org -#include "lua.hpp" -/*extern "C" { - #include "lua/lua.h" -};*/ -//-AVO -#include "script_engine.h" -#include "script_thread.h" -#include "ai_space.h" - -#define LUABIND_HAS_BUGS_WITH_LUA_THREADS - -#ifdef USE_DEBUGGER -# ifndef USE_LUA_STUDIO -# include "script_debugger.h" -# else // #ifndef USE_LUA_STUDIO -# include "lua_studio.h" -# endif // #ifndef USE_LUA_STUDIO -#endif - -const LPCSTR main_function = "console_command_run_string_main_thread_function"; - -//void print_stack_(lua_State *L) -//{ -// Msg(" "); -// for (int i=0; lua_type(L, -i-1); i++) -// Msg("%2d : %s",-i-1,lua_typename(L, lua_type(L, -i-1))); -//} - -//extern "C" __declspec(dllimport) lua_State *lua_newcthread(lua_State *OL, int cstacksize); - -CScriptThread::CScriptThread(LPCSTR caBuffer, bool do_string) -{ - m_virtual_machine = 0; - m_active = false; - - try - { - std::string S; - - if (!do_string) - { - m_script_name = caBuffer; - ai().script_engine().load_package(caBuffer); - } - else - { - m_script_name = "console command"; - S += caBuffer; - int l_iErrorCode = ai().script_engine().compile_buffer(ai().script_engine().lua(), S, "@console_command"); - if (!l_iErrorCode) - { - lua_setglobal(ai().script_engine().lua(), main_function); - } - else - { - ai().script_engine().print_output(ai().script_engine().lua(), *m_script_name, l_iErrorCode); - ai().script_engine().on_error(ai().script_engine().lua()); - return; - } - } - - // print_stack_ (ai().script_engine().lua()); - m_virtual_machine = lua_newthread(ai().script_engine().lua()); - // m_virtual_machine = lua_newcthread(ai().script_engine().lua(),0); - VERIFY2(lua(), "Cannot create new Lua thread"); -#if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) - if ( ai().script_engine().debugger() ) - ai().script_engine().debugger()->add ( m_virtual_machine ); -#endif // #if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) - // print_stack_ (ai().script_engine().lua()); - // m_thread_reference = luaL_ref(ai().script_engine().lua(),LUA_REGISTRYINDEX); - // print_stack_ (ai().script_engine().lua()); - - // if (g_ca_stdout[0]) { - // fputc (0,stderr); - // ai().script_engine().script_log (ScriptStorage::eLuaMessageTypeInfo,"%s",g_ca_stdout); - // fflush (stderr); - // } - // Msg ("lua get top %d",lua_gettop(ai().script_engine().lua())); - // print_stack_ (ai().script_engine().lua()); - -#ifndef USE_LUA_STUDIO -# ifdef DEBUG -# ifdef USE_DEBUGGER - if (ai().script_engine().debugger() && ai().script_engine().debugger()->Active()) - lua_sethook (lua(), CDbgLuaHelper::hookLua, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); - else -# endif // #ifdef USE_DEBUGGER - lua_sethook (lua(),CScriptEngine::lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); -# endif // #ifdef DEBUG -#endif // #ifndef USE_LUA_STUDIO - - if (!do_string) - S = std::string(caBuffer) + ".main()"; - else - S = std::string(main_function) + "()"; - - if (ai().script_engine().load_buffer(lua(), S.c_str(), S.length(), "@_thread_main")) - return; - - m_active = true; - } - catch (...) - { - m_active = false; - } -} - -CScriptThread::~CScriptThread() -{ -#ifdef DEBUG - Msg ("* Destroying script thread %s",*m_script_name); -#endif - try - { -#if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) - if (ai().script_engine().debugger()) - ai().script_engine().debugger()->remove ( m_virtual_machine ); -#endif // #if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO) -#ifndef LUABIND_HAS_BUGS_WITH_LUA_THREADS - luaL_unref (ai().script_engine().lua(),LUA_REGISTRYINDEX,m_thread_reference); -#endif - } - catch (...) - { - } -} - -bool CScriptThread::update() -{ - if (!m_active) - R_ASSERT2(false, "Cannot resume dead Lua thread!"); - - try - { - ai().script_engine().current_thread(this); - - int l_iErrorCode = lua_resume(lua(), 0); - - if (l_iErrorCode && (l_iErrorCode != LUA_YIELD)) - { - ai().script_engine().print_output(lua(), *script_name(), l_iErrorCode); - ai().script_engine().on_error(ai().script_engine().lua()); -#ifdef DEBUG - print_stack (lua()); -#endif - m_active = false; - } - else - { - if (l_iErrorCode != LUA_YIELD) - { -#ifdef DEBUG - if (m_current_stack_level) { - ai().script_engine().print_output (lua(),*script_name(),l_iErrorCode); - ai().script_engine().on_error (ai().script_engine().lua()); -// print_stack (lua()); - } -#endif // DEBUG - m_active = false; -#ifdef DEBUG - ai().script_engine().script_log (ScriptStorage::eLuaMessageTypeInfo,"Script %s is finished!",*m_script_name); -#endif // DEBUG - } - else - { - VERIFY2(!lua_gettop(lua()), "Do not pass any value to coroutine.yield()!"); - } - } - - ai().script_engine().current_thread(0); - } - catch (...) - { - ai().script_engine().current_thread(0); - m_active = false; - } - return (m_active); -} diff --git a/src/xrServerEntities/script_thread.h b/src/xrServerEntities/script_thread.h deleted file mode 100644 index 67d290071f..0000000000 --- a/src/xrServerEntities/script_thread.h +++ /dev/null @@ -1,44 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_thread.h -// Created : 19.09.2003 -// Modified : 29.06.2004 -// Author : Dmitriy Iassenev -// Description : Script thread class -//////////////////////////////////////////////////////////////////////////// - -#pragma once - -#ifdef DEBUG -# include "script_stack_tracker.h" -#endif - -struct lua_State; - -#ifdef DEBUG - class CScriptThread : public CScriptStackTracker -#else -class CScriptThread -#endif -{ -private: - shared_str m_script_name; - int m_thread_reference; - bool m_active; - lua_State* m_virtual_machine; - -#ifdef DEBUG -protected: - static void lua_hook_call (lua_State *L, lua_Debug *dbg); -#endif - -public: - CScriptThread(LPCSTR caNamespaceName, bool do_string = false); - virtual ~CScriptThread(); - bool update(); - IC bool active() const; - IC shared_str script_name() const; - IC int thread_reference() const; - IC lua_State* lua() const; -}; - -#include "script_thread_inline.h" diff --git a/src/xrServerEntities/script_thread_inline.h b/src/xrServerEntities/script_thread_inline.h deleted file mode 100644 index eb5a07751f..0000000000 --- a/src/xrServerEntities/script_thread_inline.h +++ /dev/null @@ -1,29 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// Module : script_thread_inline.h -// Created : 19.09.2003 -// Modified : 29.06.2004 -// Author : Dmitriy Iassenev -// Description : Script thread class inline functions -//////////////////////////////////////////////////////////////////////////// - -#pragma once - -IC bool CScriptThread::active() const -{ - return (m_active); -} - -IC shared_str CScriptThread::script_name() const -{ - return (m_script_name); -} - -IC int CScriptThread::thread_reference() const -{ - return (m_thread_reference); -} - -IC lua_State* CScriptThread::lua() const -{ - return (m_virtual_machine); -} From f1106f619c19b7891579596a89a9f73b22c60476 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 8 Jun 2025 18:23:21 +0100 Subject: [PATCH 56/76] Rename `amx` to `xr`, `xr/wua` to `xr/lua` --- gamedata/scripts/init.lua | 2 +- gamedata/scripts/{amx => xr}/classes.lua | 0 gamedata/scripts/{amx => xr}/init.lua | 10 +++++----- gamedata/scripts/{amx/wua => xr/lua}/compile.lua | 0 gamedata/scripts/{amx/wua => xr/lua}/init.lua | 0 gamedata/scripts/{amx/wua => xr/lua}/unlocalize.lua | 2 +- gamedata/scripts/{amx => xr}/process.lua | 0 gamedata/scripts/{amx => xr}/processes.lua | 2 +- gamedata/scripts/{amx => xr}/registrator.lua | 0 gamedata/scripts/{amx => xr}/scripts.lua | 0 gamedata/scripts/{amx => xr}/unlocalize.lua | 0 src/xrServerEntities/script_processes.h | 2 +- 12 files changed, 9 insertions(+), 9 deletions(-) rename gamedata/scripts/{amx => xr}/classes.lua (100%) rename gamedata/scripts/{amx => xr}/init.lua (86%) rename gamedata/scripts/{amx/wua => xr/lua}/compile.lua (100%) rename gamedata/scripts/{amx/wua => xr/lua}/init.lua (100%) rename gamedata/scripts/{amx/wua => xr/lua}/unlocalize.lua (97%) rename gamedata/scripts/{amx => xr}/process.lua (100%) rename gamedata/scripts/{amx => xr}/processes.lua (94%) rename gamedata/scripts/{amx => xr}/registrator.lua (100%) rename gamedata/scripts/{amx => xr}/scripts.lua (100%) rename gamedata/scripts/{amx => xr}/unlocalize.lua (100%) diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index cdf80e856f..693a96ff13 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -113,4 +113,4 @@ package.loaders = { _LOADERS.init } require("boot") -- Pass control to xray entrypoint -require("amx") +require("xr") diff --git a/gamedata/scripts/amx/classes.lua b/gamedata/scripts/xr/classes.lua similarity index 100% rename from gamedata/scripts/amx/classes.lua rename to gamedata/scripts/xr/classes.lua diff --git a/gamedata/scripts/amx/init.lua b/gamedata/scripts/xr/init.lua similarity index 86% rename from gamedata/scripts/amx/init.lua rename to gamedata/scripts/xr/init.lua index a30e176aa0..b6502e3058 100644 --- a/gamedata/scripts/amx/init.lua +++ b/gamedata/scripts/xr/init.lua @@ -1,15 +1,15 @@ -_PACKAGE = "amx" -_FILE = "amx/init.lua" +_PACKAGE = "xr" +_FILE = "xr/init.lua" -- Initialize S.C.A.M. environment local scam = require("scam") --- Load amx/unlocalize before amx/lua to avoid circular referencing +-- Load xr/unlocalize before xr/lua to avoid circular referencing require(_PACKAGE .. "/unlocalize") --- Setup wua as the default language +-- Setup xr/lua as the default language scam.compiler.set_default_macro( - require(_PACKAGE .. "/wua").expand + require(_PACKAGE .. "/lua").expand ) -- Forcefully load _g.script diff --git a/gamedata/scripts/amx/wua/compile.lua b/gamedata/scripts/xr/lua/compile.lua similarity index 100% rename from gamedata/scripts/amx/wua/compile.lua rename to gamedata/scripts/xr/lua/compile.lua diff --git a/gamedata/scripts/amx/wua/init.lua b/gamedata/scripts/xr/lua/init.lua similarity index 100% rename from gamedata/scripts/amx/wua/init.lua rename to gamedata/scripts/xr/lua/init.lua diff --git a/gamedata/scripts/amx/wua/unlocalize.lua b/gamedata/scripts/xr/lua/unlocalize.lua similarity index 97% rename from gamedata/scripts/amx/wua/unlocalize.lua rename to gamedata/scripts/xr/lua/unlocalize.lua index ee832bb783..9bd7a65eaa 100644 --- a/gamedata/scripts/amx/wua/unlocalize.lua +++ b/gamedata/scripts/xr/lua/unlocalize.lua @@ -34,7 +34,7 @@ local function unlocalize(src, namespace_name) return src end - local unlocalizer = require("amx/unlocalize").get(namespace_name) + local unlocalizer = require("xr/unlocalize").get(namespace_name) if not unlocalizer then return src end diff --git a/gamedata/scripts/amx/process.lua b/gamedata/scripts/xr/process.lua similarity index 100% rename from gamedata/scripts/amx/process.lua rename to gamedata/scripts/xr/process.lua diff --git a/gamedata/scripts/amx/processes.lua b/gamedata/scripts/xr/processes.lua similarity index 94% rename from gamedata/scripts/amx/processes.lua rename to gamedata/scripts/xr/processes.lua index 5384e2290d..4ae766e0ec 100644 --- a/gamedata/scripts/amx/processes.lua +++ b/gamedata/scripts/xr/processes.lua @@ -1,7 +1,7 @@ -- Engine interface to domain-scoped coroutines -- Formerly part of CScriptManager -local ScriptProcess = require("amx/process") +local ScriptProcess = require("xr/process") local ScriptProcesses = {} diff --git a/gamedata/scripts/amx/registrator.lua b/gamedata/scripts/xr/registrator.lua similarity index 100% rename from gamedata/scripts/amx/registrator.lua rename to gamedata/scripts/xr/registrator.lua diff --git a/gamedata/scripts/amx/scripts.lua b/gamedata/scripts/xr/scripts.lua similarity index 100% rename from gamedata/scripts/amx/scripts.lua rename to gamedata/scripts/xr/scripts.lua diff --git a/gamedata/scripts/amx/unlocalize.lua b/gamedata/scripts/xr/unlocalize.lua similarity index 100% rename from gamedata/scripts/amx/unlocalize.lua rename to gamedata/scripts/xr/unlocalize.lua diff --git a/src/xrServerEntities/script_processes.h b/src/xrServerEntities/script_processes.h index 6eb8a621e8..49534a5258 100644 --- a/src/xrServerEntities/script_processes.h +++ b/src/xrServerEntities/script_processes.h @@ -10,7 +10,7 @@ class CScriptProcesses CScriptProcesses(lua_State* L) { lua_getglobal(L, "require"); - lua_pushstring(L, "amx/processes"); + lua_pushstring(L, "xr/processes"); lua_call(L, 1, 1); m_obj = luabind::object(L); From 7fe288be226563a2253e0ad8809ec7e49b119e0e Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 8 Jun 2025 19:29:05 +0100 Subject: [PATCH 57/76] Restructure boot process around `script.ltx` for flexibility --- gamedata/configs/mod_script_amx.ltx | 3 + gamedata/configs/mod_script_dxml.ltx | 3 - gamedata/scripts/amx/init.lua | 8 + gamedata/scripts/amx/lua/init.lua | 21 ++ .../scripts/{xr => amx}/lua/unlocalize.lua | 8 +- gamedata/scripts/amx/registrator.lua | 33 +++ gamedata/scripts/{xr => amx}/unlocalize.lua | 4 +- gamedata/scripts/boot/function_object.lua | 4 +- gamedata/scripts/boot/init.lua | 10 +- gamedata/scripts/boot/loader.lua | 3 + gamedata/scripts/boot/paths.lua | 4 + gamedata/scripts/boot/sandbox.lua | 4 +- gamedata/scripts/{xr => boot}/scripts.lua | 4 + gamedata/scripts/init.lua | 5 +- gamedata/scripts/scam/init.lua | 9 - gamedata/scripts/{scam => xr}/compiler.lua | 6 +- gamedata/scripts/xr/init.lua | 61 +----- gamedata/scripts/xr/lua/compile.lua | 183 ----------------- gamedata/scripts/xr/lua/init.lua | 189 +++++++++++++++++- gamedata/scripts/xr/processes.lua | 34 +++- gamedata/scripts/xr/registrator.lua | 25 --- 21 files changed, 316 insertions(+), 305 deletions(-) create mode 100644 gamedata/configs/mod_script_amx.ltx delete mode 100644 gamedata/configs/mod_script_dxml.ltx create mode 100644 gamedata/scripts/amx/init.lua create mode 100644 gamedata/scripts/amx/lua/init.lua rename gamedata/scripts/{xr => amx}/lua/unlocalize.lua (95%) create mode 100644 gamedata/scripts/amx/registrator.lua rename gamedata/scripts/{xr => amx}/unlocalize.lua (93%) rename gamedata/scripts/{xr => boot}/scripts.lua (86%) delete mode 100644 gamedata/scripts/scam/init.lua rename gamedata/scripts/{scam => xr}/compiler.lua (86%) delete mode 100644 gamedata/scripts/xr/lua/compile.lua delete mode 100644 gamedata/scripts/xr/registrator.lua diff --git a/gamedata/configs/mod_script_amx.ltx b/gamedata/configs/mod_script_amx.ltx new file mode 100644 index 0000000000..612501234c --- /dev/null +++ b/gamedata/configs/mod_script_amx.ltx @@ -0,0 +1,3 @@ +![common] +script = xr/compiler, xr/lua, amx, _G, _g_patches, xr/classes, xr/processes, dxml_core +>class_registrators = amx/registrator.register diff --git a/gamedata/configs/mod_script_dxml.ltx b/gamedata/configs/mod_script_dxml.ltx deleted file mode 100644 index 9e2ccf8610..0000000000 --- a/gamedata/configs/mod_script_dxml.ltx +++ /dev/null @@ -1,3 +0,0 @@ -![common] ->script = _g_patches, dxml_core ->class_registrators = class_registrator_modded_exes.register diff --git a/gamedata/scripts/amx/init.lua b/gamedata/scripts/amx/init.lua new file mode 100644 index 0000000000..25a4fc3666 --- /dev/null +++ b/gamedata/scripts/amx/init.lua @@ -0,0 +1,8 @@ +-- Anomaly Modded eXes Entrypoint +-- Extends base X-Ray script functionality + +--- Setup unlocalizer data model +require(_PACKAGE .. "/unlocalize") + +--- Patch xr/lua compiler with modded exes extensions +require(_PACKAGE .. "/lua") diff --git a/gamedata/scripts/amx/lua/init.lua b/gamedata/scripts/amx/lua/init.lua new file mode 100644 index 0000000000..8434c94c38 --- /dev/null +++ b/gamedata/scripts/amx/lua/init.lua @@ -0,0 +1,21 @@ +-- AMX Lua Compiler +-- Patches unlocalization onto the base XR Lua compiler + +local xr_lua = require("xr/lua") +local unlocalize = require(_PACKAGE .. "/unlocalize") + +local old_compile = xr_lua.compile +function xr_lua.compile(src, namespace_name, script_name) + if namespace_name then + print("* " .. _PACKAGE .. ": compiling " .. namespace_name) + end + + return old_compile( + unlocalize(src, namespace_name), + namespace_name, + script_name + ) +end + +require("xr/compiler").register_extension("script", xr_lua.compile) +require("xr/compiler").set_default_macro(xr_lua.compile) diff --git a/gamedata/scripts/xr/lua/unlocalize.lua b/gamedata/scripts/amx/lua/unlocalize.lua similarity index 95% rename from gamedata/scripts/xr/lua/unlocalize.lua rename to gamedata/scripts/amx/lua/unlocalize.lua index 9bd7a65eaa..1569f27c3a 100644 --- a/gamedata/scripts/xr/lua/unlocalize.lua +++ b/gamedata/scripts/amx/lua/unlocalize.lua @@ -1,3 +1,5 @@ +-- Unlocalizer for xr/lua scripts + local function string_trim(s, v) if v == nil then v = " \t\n\r\f\v" @@ -34,7 +36,7 @@ local function unlocalize(src, namespace_name) return src end - local unlocalizer = require("xr/unlocalize").get(namespace_name) + local unlocalizer = require("amx/unlocalize").get(namespace_name) if not unlocalizer then return src end @@ -112,6 +114,4 @@ local function unlocalize(src, namespace_name) return src end -return { - unlocalize = unlocalize -} +return unlocalize diff --git a/gamedata/scripts/amx/registrator.lua b/gamedata/scripts/amx/registrator.lua new file mode 100644 index 0000000000..951aa09fee --- /dev/null +++ b/gamedata/scripts/amx/registrator.lua @@ -0,0 +1,33 @@ +-- AMX Class Registrator +-- Add custom classes for registration here + +local function cs_register(factory, ...) + factory:register(...) +end + +local function c_register(factory, ...) + if editor() == false then + factory:register(...) + end +end + +local function s_register(factory, ...) + factory:register(...) +end + +local function register(object_factory) + cs_register( + object_factory, + "CWeaponSSRS", + "se_item.se_weapon_magazined", + "_WP_SSRS", + "wpn_ssrs_s" + ) +end + +return { + cs_register = cs_register, + c_register = c_register, + s_register = s_register, + register = register, +} diff --git a/gamedata/scripts/xr/unlocalize.lua b/gamedata/scripts/amx/unlocalize.lua similarity index 93% rename from gamedata/scripts/xr/unlocalize.lua rename to gamedata/scripts/amx/unlocalize.lua index 1157111428..a4174fd7ee 100644 --- a/gamedata/scripts/xr/unlocalize.lua +++ b/gamedata/scripts/amx/unlocalize.lua @@ -1,3 +1,6 @@ +-- AMX Unlocalizer Storage +-- Loads unlocalizers from disk and exposes them via `get` + local unlocalizers = {} local function update() @@ -63,4 +66,3 @@ return { update = update, get = get } - diff --git a/gamedata/scripts/boot/function_object.lua b/gamedata/scripts/boot/function_object.lua index 6fd6f1ea58..4a37cc4d03 100644 --- a/gamedata/scripts/boot/function_object.lua +++ b/gamedata/scripts/boot/function_object.lua @@ -1,4 +1,6 @@ --- Engine interface; require with explicit _G and recursive indexing +-- Engine interface +-- Behaves like _G-aware `require` with recursive . indexing + function function_object(str) local path = {} for v in string.gmatch(str, "[^%.]+") do diff --git a/gamedata/scripts/boot/init.lua b/gamedata/scripts/boot/init.lua index c6df1e33fc..337472dfec 100644 --- a/gamedata/scripts/boot/init.lua +++ b/gamedata/scripts/boot/init.lua @@ -6,11 +6,17 @@ _PACKAGE = "boot" -- Disable unsafe Lua primitives require("boot/sandbox") --- Setup path machinery +-- Setup package.path machinery require("boot/paths") --- Setup loading machinery +-- Setup package.loaders machinery require("boot/loader") -- Setup engine interface require("boot/function_object") + +-- Ensure _G loads on first require +package.loaded._G = nil + +-- Run startup modules defined in script.ltx +require("boot/scripts") diff --git a/gamedata/scripts/boot/loader.lua b/gamedata/scripts/boot/loader.lua index a05f2368c9..76c240f446 100644 --- a/gamedata/scripts/boot/loader.lua +++ b/gamedata/scripts/boot/loader.lua @@ -1,3 +1,6 @@ +-- Boot Loader +-- Configures package.loaders with support for X-Ray FS + _PACKAGE = "boot/loader" local state = { diff --git a/gamedata/scripts/boot/paths.lua b/gamedata/scripts/boot/paths.lua index c8bc20138d..432aa8926d 100644 --- a/gamedata/scripts/boot/paths.lua +++ b/gamedata/scripts/boot/paths.lua @@ -1,3 +1,7 @@ +-- Boot Paths +-- Configures package.path to root at gamedata/scripts, +-- and gamedata/scripts/packages + _PACKAGE = "boot/paths" -- Cache default path for later diff --git a/gamedata/scripts/boot/sandbox.lua b/gamedata/scripts/boot/sandbox.lua index 46ebf49736..adbb3a07db 100644 --- a/gamedata/scripts/boot/sandbox.lua +++ b/gamedata/scripts/boot/sandbox.lua @@ -1,4 +1,6 @@ --- Disable OS functions +-- Boot Sandbox +-- Disables dangerous Lua primitives + local disabled = { os = { "execute", diff --git a/gamedata/scripts/xr/scripts.lua b/gamedata/scripts/boot/scripts.lua similarity index 86% rename from gamedata/scripts/xr/scripts.lua rename to gamedata/scripts/boot/scripts.lua index 22860e289e..944199f618 100644 --- a/gamedata/scripts/xr/scripts.lua +++ b/gamedata/scripts/boot/scripts.lua @@ -1,3 +1,6 @@ +-- Boot Scripts +-- Loads scripts specified in script.ltx + local DISABLE_SCRIPTS = false if DISABLE_SCRIPTS then @@ -20,6 +23,7 @@ end local scripts = ini:r_string("common", "script", "") for script in scripts:gmatch("[^,]+") do + print("requiring " .. script) local mod = require(script) if type(mod) == "table" then local init = mod[script .. "_initialize"] diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index 693a96ff13..b2d3a6bba5 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -109,8 +109,5 @@ end package.loaders = { _LOADERS.init } ---- Initialize environment via the boot module +--- Hand control to the boot module require("boot") - --- Pass control to xray entrypoint -require("xr") diff --git a/gamedata/scripts/scam/init.lua b/gamedata/scripts/scam/init.lua deleted file mode 100644 index fa97b0030c..0000000000 --- a/gamedata/scripts/scam/init.lua +++ /dev/null @@ -1,9 +0,0 @@ ---- Script Compilers And Macros ---- Script preprocess dispatch machinery - --- Setup compiler -local compiler = require("scam/compiler") - -return { - compiler = compiler -} diff --git a/gamedata/scripts/scam/compiler.lua b/gamedata/scripts/xr/compiler.lua similarity index 86% rename from gamedata/scripts/scam/compiler.lua rename to gamedata/scripts/xr/compiler.lua index 2da79d54b8..74eb5fcfcd 100644 --- a/gamedata/scripts/scam/compiler.lua +++ b/gamedata/scripts/xr/compiler.lua @@ -1,3 +1,6 @@ +-- XR Lua Compiler +-- Lua-friendly virtualization of the original X-Ray script environment + local PATTERN_FILE_PATH = "^(.-)([^\\/]-)%.([^\\/%.]-)%.?$" local PATTERN_MACRO_TAG = "[^ ]+ +=%*= +lang: +([^ ]+) +=%*=[^\n]*(\n.*)" @@ -30,7 +33,7 @@ function _COMPILER(src, namespace_name, script_name) end local function register_extension(k, v) - print(_PACKAGE .. ": registering script extension: " .. k) + print(_PACKAGE .. ": registering extension: " .. k) _REGISTER_PATHS( "?." .. k, "?/init." .. k @@ -47,6 +50,7 @@ local function get_extensions() end local function set_default_macro(mac) + print(_PACKAGE .. ": setting default macro...") state.default = mac end diff --git a/gamedata/scripts/xr/init.lua b/gamedata/scripts/xr/init.lua index b6502e3058..f47d2cdb09 100644 --- a/gamedata/scripts/xr/init.lua +++ b/gamedata/scripts/xr/init.lua @@ -1,59 +1,2 @@ -_PACKAGE = "xr" -_FILE = "xr/init.lua" - --- Initialize S.C.A.M. environment -local scam = require("scam") - --- Load xr/unlocalize before xr/lua to avoid circular referencing -require(_PACKAGE .. "/unlocalize") - --- Setup xr/lua as the default language -scam.compiler.set_default_macro( - require(_PACKAGE .. "/lua").expand -) - --- Forcefully load _g.script -package.loaded._G = nil -require("_G") - --- Register classes -require(_PACKAGE .. "/classes") - --- Setup script processes -local processes = require(_PACKAGE .. "/processes") - --- Game process -local ini_script = ini_file("configs\\script.ltx") -print("ini_script:", ini_script) - -local game_scripts = "" -if ini_script:section_exist("single") - and ini_script:line_exist("single", "script") -then - print("reading from ini") - game_scripts = ini_script:r_string("single", "script"); -end - -print("game_scripts:", game_scripts) -processes:add("game", game_scripts) - --- Level process -if level.present() then - local ini_level = ini_file( - string.format("levels\\%s\\level.ltx", level.name()) - ) - print("ini_level:", ini_level) - - local level_scripts = "" - if ini_level:section_exist("level_scripts") - and ini_level:line_exist("level_scripts", "script") - then - level_scripts = ini_level:r_string("level_scripts", "script"); - end - - processes:add("level", level_scripts) -end - --- Run common scripts -require(_PACKAGE .. "/scripts") - +-- X-Ray Lua Core +-- Submodules are loaded by script.ltx for flexible initialization order diff --git a/gamedata/scripts/xr/lua/compile.lua b/gamedata/scripts/xr/lua/compile.lua deleted file mode 100644 index 267e54f970..0000000000 --- a/gamedata/scripts/xr/lua/compile.lua +++ /dev/null @@ -1,183 +0,0 @@ ---local remap = import("/moved").remap - -local G = setmetatable( - {}, - { - __index = function(self, key) - --[[ - -- Fetch the remap for this key - local redir = remap[key] - - -- If we have a redirection... - if redir ~= nil then - -- Check the no-overwrite flag; - -- If set and the key exists in _G, return its value - if redir.if_not_overwritten then - local gv = _G[key] - if gv then - return gv - end - - local res, out = pcall(require, key) - if res then - return out - end - end - - -- Otherwise, fetch the redirected key - if type(redir.to) ~= "string" then - error( - "Redirection from " .. key - .. " has invalid 'to' field: " .. redir.to - ) - end - - -- And recurse with it - local rv = self[redir.to] - - -- If if exists, return it - if rv ~= nil then - return rv - end - end - --]] - - -- Otherwise, check the global key's value and return if valid - local gv = _G[key] - if gv ~= nil then - return gv - end - - -- Otherwise, try to auto-load the key as a script - local res, out = pcall(require, key) - if res then - return out - end - end, - __newindex = _G - } -) - -local function handle_error(msg, namespace_name) - return function(err) - if namespace_name then - package.loaded[namespace_name] = nil - end - - err = "! " .. _PACKAGE .. ": " - .. msg .. ":\n\n" - .. err - .. "\n" - err = debug.traceback(err, 2) - - print(err) - error(err) - end -end - -local compile -compile = function(src, namespace_name, script_name) - local is_g = namespace_name == "_G" - - local mt = { - __index = G - } - - if is_g then - mt.__newindex = G - end - - local env = setmetatable({ _G = G }, mt) - - if not is_g then - -- If this is a named module, emplace relevant globals - if namespace_name then - env._M = env - env._PACKAGE = namespace_name - env._FILE = script_name - env[namespace_name] = env - end - - -- Redirect loadstring through this compiler - env.loadstring = compile - - -- Redirect load through this compiler - env.load = function(f, name) - local src = "" - - while true do - local part = f() - if part == nil then - break - elseif type(part == "string") then - if #part == 0 then - break - end - - src = src .. part - end - end - - return compile(src, name) - end - - -- Redirect loadfile through this compiler - env.loadfile = function(path) - local file = io.input(path) - local src = file:read("*a") - file:close() - return compile(src) - end - - -- Selectively patch the package module - -- to restore unconfigured Lua environment - local pkg = {} - for k,v in pairs(package) do - pkg[k] = v - end - pkg.path = _DEFAULT_PATH - pkg.loaders = { - _LOADERS.pre, - _LOADERS.lib, - _LOADERS.bin, - _LOADERS.aio, - } - env.package = pkg - end - - if namespace_name then - src = "local script_name = function() return _PACKAGE end " .. src - src = "local this = _M " .. src - end - - local mod, err = loadstring(src, namespace_name) - if not mod then - handle_error("error loading " .. (namespace_name or "script"), namespace_name)(err) - end - - local mac = setfenv(mod, env) - - return function() - if namespace_name then - package.loaded[namespace_name] = env - end - - local _, out = xpcall( - mac, - handle_error( - "error evaluating " .. (namespace_name or "script"), - namespace_name - ) - ) - - if namespace_name then - return package.loaded[namespace_name] - else - return out - end - end -end - -return { - compile = compile -} diff --git a/gamedata/scripts/xr/lua/init.lua b/gamedata/scripts/xr/lua/init.lua index 6a091e7437..a86df6980e 100644 --- a/gamedata/scripts/xr/lua/init.lua +++ b/gamedata/scripts/xr/lua/init.lua @@ -1,20 +1,187 @@ -local unlocalize = require(_PACKAGE .. "/unlocalize").unlocalize -local compile = require(_PACKAGE .. "/compile").compile +--local remap = import("/moved").remap + +local G = setmetatable( + {}, + { + __index = function(self, key) + --[[ + -- Fetch the remap for this key + local redir = remap[key] + + -- If we have a redirection... + if redir ~= nil then + -- Check the no-overwrite flag; + -- If set and the key exists in _G, return its value + if redir.if_not_overwritten then + local gv = _G[key] + if gv then + return gv + end + + local res, out = pcall(require, key) + if res then + return out + end + end + + -- Otherwise, fetch the redirected key + if type(redir.to) ~= "string" then + error( + "Redirection from " .. key + .. " has invalid 'to' field: " .. redir.to + ) + end + + -- And recurse with it + local rv = self[redir.to] + + -- If if exists, return it + if rv ~= nil then + return rv + end + end + --]] + + -- Otherwise, check the global key's value and return if valid + local gv = _G[key] + if gv ~= nil then + return gv + end + + -- Otherwise, try to auto-load the key as a script + local res, out = pcall(require, key) + if res then + return out + end + end, + __newindex = _G + } +) + +local function handle_error(msg, namespace_name) + return function(err) + if namespace_name then + package.loaded[namespace_name] = nil + end + + err = "! " .. _PACKAGE .. ": " + .. msg .. ":\n\n" + .. err + .. "\n" + err = debug.traceback(err, 2) + + print(err) + error(err) + end +end + +local compile +compile = function(src, namespace_name, script_name) + local is_g = namespace_name == "_G" + + local mt = { + __index = G + } + + if is_g then + mt.__newindex = G + end + + local env = setmetatable({ _G = G }, mt) + + if not is_g then + -- If this is a named module, emplace relevant globals + if namespace_name then + env._M = env + env._PACKAGE = namespace_name + env._FILE = script_name + env[namespace_name] = env + end + + -- Redirect loadstring through this compiler + env.loadstring = compile + + -- Redirect load through this compiler + env.load = function(f, name) + local src = "" + + while true do + local part = f() + if part == nil then + break + elseif type(part == "string") then + if #part == 0 then + break + end + + src = src .. part + end + end + + return compile(src, name) + end + + -- Redirect loadfile through this compiler + env.loadfile = function(path) + local file = io.input(path) + local src = file:read("*a") + file:close() + return compile(src) + end + + -- Selectively patch the package module + -- to restore unconfigured Lua environment + local pkg = {} + for k,v in pairs(package) do + pkg[k] = v + end + pkg.path = _DEFAULT_PATH + pkg.loaders = { + _LOADERS.pre, + _LOADERS.lib, + _LOADERS.bin, + _LOADERS.aio, + } + env.package = pkg + end -local function expand(src, namespace_name, script_name) if namespace_name then - print("* " .. _PACKAGE .. ": expanding " .. namespace_name) + src = "local script_name = function() return _PACKAGE end " .. src + src = "local this = _M " .. src + end + + local mod, err = loadstring(src, namespace_name) + if not mod then + handle_error("error loading " .. (namespace_name or "script"), namespace_name)(err) end - return compile( - unlocalize(src, namespace_name), - namespace_name, - script_name - ) + local mac = setfenv(mod, env) + + return function() + if namespace_name then + package.loaded[namespace_name] = env + end + + local _, out = xpcall( + mac, + handle_error( + "error evaluating " .. (namespace_name or "script"), + namespace_name + ) + ) + + if namespace_name then + return package.loaded[namespace_name] + else + return out + end + end end -require("scam/compiler").register_extension("script", expand) +local compiler = require("xr/compiler") +compiler.register_extension("script", compile) +compiler.set_default_macro(compile) return { - expand = expand + compile = compile } diff --git a/gamedata/scripts/xr/processes.lua b/gamedata/scripts/xr/processes.lua index 4ae766e0ec..c1472c1381 100644 --- a/gamedata/scripts/xr/processes.lua +++ b/gamedata/scripts/xr/processes.lua @@ -37,4 +37,36 @@ function ScriptProcesses:get(name) return self.processes[name] end -return ScriptProcesses.new() +-- Prepare module output +local processes = ScriptProcesses.new() + +-- Game process +local ini_script = ini_file("configs\\script.ltx") + +local game_scripts = "" +if ini_script:section_exist("single") + and ini_script:line_exist("single", "script") +then + game_scripts = ini_script:r_string("single", "script"); +end + +processes:add("game", game_scripts) + +-- Level process +if level.present() then + local ini_level = ini_file( + string.format("levels\\%s\\level.ltx", level.name()) + ) + + local level_scripts = "" + if ini_level:section_exist("level_scripts") + and ini_level:line_exist("level_scripts", "script") + then + level_scripts = ini_level:r_string("level_scripts", "script"); + end + + processes:add("level", level_scripts) +end + +-- Return module output +return processes diff --git a/gamedata/scripts/xr/registrator.lua b/gamedata/scripts/xr/registrator.lua deleted file mode 100644 index f2f7912ea5..0000000000 --- a/gamedata/scripts/xr/registrator.lua +++ /dev/null @@ -1,25 +0,0 @@ --- Add custom classes to register here -local function cs_register(factory,client_object_class,server_object_class,clsid,script_clsid) - factory:register(client_object_class,server_object_class,clsid,script_clsid) -end - -local function c_register(factory,client_object_class,clsid,script_clsid) - if (editor() == false) then - factory:register(client_object_class,clsid,script_clsid) - end -end - -local function s_register(factory,server_object_class,clsid,script_clsid) - factory:register(server_object_class,clsid,script_clsid) -end - -local function register(object_factory) - cs_register(object_factory, "CWeaponSSRS", "se_item.se_weapon_magazined", "_WP_SSRS", "wpn_ssrs_s") -end - -return { - cs_register = cs_register, - c_register = c_register, - s_register = s_register, - register = register, -} From 05810fc596be61b7ea7d69ef11a8602419687230 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 8 Jun 2025 20:32:34 +0100 Subject: [PATCH 58/76] Replace `_COMPILER` with `loadstring`, simplify `boot/loader` impl --- gamedata/scripts/boot/loader.lua | 118 ++++++++++++++++++------------- gamedata/scripts/init.lua | 49 ++++++++++--- gamedata/scripts/xr/compiler.lua | 7 +- gamedata/scripts/xr/lua/init.lua | 53 ++++---------- gamedata/scripts/xr/process.lua | 2 +- 5 files changed, 126 insertions(+), 103 deletions(-) diff --git a/gamedata/scripts/boot/loader.lua b/gamedata/scripts/boot/loader.lua index 76c240f446..ca2823605a 100644 --- a/gamedata/scripts/boot/loader.lua +++ b/gamedata/scripts/boot/loader.lua @@ -7,83 +7,101 @@ local state = { callbacks = {} } --- Define xray FS loader +-- X-Ray FS Loader function _LOADERS.fs(name) - local fs = getFS() + -- Check whether the target is known to not exist on the FS + local io_miss = _SCRIPT_STORAGE:get("io_loader", name) + if io_miss then + -- If so, early out + return io_miss + end + + -- Allocate error storage local errs = "" + + -- Fetch filesystem handle + local fs = getFS() + + -- Update the FS' view of our script directory local base = fs:update_path("$game_scripts$", "") + + -- Iterate over our search paths for seg in package.path:gmatch("[^;]+") do + -- If the segment begins with our base directory if seg:sub(1, #base) == base then + -- Strip the base path, interpolate package name, + -- and replace separators to produce a filename local fname = seg:sub(#base + 1):gsub("?", name):gsub("/", "\\") + + -- Get an xray path from our filename local path = fs:update_path("$game_scripts$", fname) + + -- If the path is valid and exists... if path and fs:exist(path) then + -- Load the corresponding file into a string local src = _LOAD_FILE(path) - return _COMPILER(src, name, path) - end - if #errs > 0 then - errs = errs .. "\n\t" - end - errs = errs .. "No db entry: " .. path - end - end + -- Compile it into a Lua function + local mac, err = loadstring(src, name, path) - return errs -end + -- If we don't have a result... + if not mac then + -- Print and throw the corresponding error + print(err) + error(err) + end -local loaders = { _LOADERS.fs } + -- Cache any loaded copy of this package + local already_loaded = package.loaded[name] --- Lift into a memoized higher-order loader -local function io_loaders(name) - local io_miss = _SCRIPT_STORAGE:get("io_loader", name) - if io_miss then - return io_miss - end + -- Evaluate the compiled Lua function + local res = mac() - local err = "" - for i=1,#loaders do - local out = loaders[i](name) - - local ty = type(out) - if ty == "function" then - local already_loaded = package.loaded[name] - local res = out() - package.loaded[name] = res - if already_loaded == nil then - for _,f in ipairs(state.callbacks) do - f(name) - end - end - return function() + -- Emplace the result in package.loaded so callbacks can see it package.loaded[name] = res - return res - end - else - package.loaded[name] = nil - if #err > 0 then - err = err .. "\n" - end - if ty == "string" then - err = err .. out - elseif ty == "nil" then - error("No such module: " .. name) + + -- If this package wasn't already loaded... + if already_loaded == nil then + -- Fire on-load callbacks + for _,f in ipairs(state.callbacks) do + f(name) + end + end + + -- Finally, return a function that populates package.loaded + -- with the result and returns it, + -- to ensure `require` returns the correct value + -- regardless of re-entrant loading that may occur in the interim + return function() + package.loaded[name] = res + return res + end else - error("Loader returned invalid value: " .. tostring(out)) + -- Otherwise, add to our error accumulator + if #errs > 0 then + errs = errs .. "\n\t" + end + errs = errs .. "No db entry: " .. path end end end - _SCRIPT_STORAGE:set("io_loader", name, err) - return err + -- Cache the IO miss for later + _SCRIPT_STORAGE:set("io_loader", name, errs) + + -- Return error accumulator + return errs end --- Replace the loader list with the preloader plus our memoized IO loader -package.loaders = { _LOADERS.pre, io_loaders } +-- Replace the loader list with the preloader plus our FS loader +package.loaders = { _LOADERS.pre, _LOADERS.fs } +-- Define callback registrator local function register_on_load_callback(f) table.insert(state.callbacks, f) end +-- Return final module return { register_on_load_callback = register_on_load_callback } diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index b2d3a6bba5..0da042006d 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -36,18 +36,18 @@ function print(...) end end --- Set to true if we're unwinding the stack following an error ---- Emplace Lua passthrough compiler -function _COMPILER(src, namespace_name, script_name) +--- Replace loadstring with our own override +_LOADSTRING = loadstring +function loadstring(src, namespace_name, script_name) print("* lua: loading " .. namespace_name) - local f, err = loadstring(src, namespace_name) + local f, err = _LOADSTRING(src, namespace_name) if not f then err = "init: error loading " .. namespace_name .. ":\n\n" .. err .. "\n" err = debug.traceback(err, 2) print(err) - error(err) + return nil, err end local mac = setfenv( @@ -82,6 +82,35 @@ function _COMPILER(src, namespace_name, script_name) end end +-- Redirect load through loadstring +load = function(f, name) + local src = "" + + while true do + local part = f() + if part == nil then + break + elseif type(part == "string") then + if #part == 0 then + break + end + + src = src .. part + end + end + + return loadstring(src, name) +end + +-- Redirect loadfile through loadstring +loadfile = function(path) + local file = io.input(path) + local src = file:read("*a") + file:close() + return loadstring(src) +end + + --- Emplace minimal X-Ray FS loader function _LOADERS.init(name) local fs = getFS() @@ -99,12 +128,12 @@ function _LOADERS.init(name) return "\n\tNo such package: " .. name end - local res, out = pcall(_COMPILER, _LOAD_FILE(path), name, path) - if not res then - print(out) - error(out) + local res, err = loadstring(_LOAD_FILE(path), name, path) + if res then + return res end - return out + + return err end package.loaders = { _LOADERS.init } diff --git a/gamedata/scripts/xr/compiler.lua b/gamedata/scripts/xr/compiler.lua index 74eb5fcfcd..376f96d78a 100644 --- a/gamedata/scripts/xr/compiler.lua +++ b/gamedata/scripts/xr/compiler.lua @@ -4,12 +4,12 @@ local PATTERN_FILE_PATH = "^(.-)([^\\/]-)%.([^\\/%.]-)%.?$" local PATTERN_MACRO_TAG = "[^ ]+ +=%*= +lang: +([^ ]+) +=%*=[^\n]*(\n.*)" -local extensions = { lua = _COMPILER } +local extensions = { lua = loadstring } local state = { - default = _COMPILER + default = loadstring } -function _COMPILER(src, namespace_name, script_name) +function loadstring(src, namespace_name, script_name) local mac = nil if script_name then @@ -57,7 +57,6 @@ end return { PATTERN_FILE_PATH = PATTERN_FILE_PATH, PATTERN_MACRO_TAG = PATTERN_MACRO_TAG, - compile = _COMPILER, register_extension = register_extension, get_extensions = get_extensions, set_default_macro = set_default_macro diff --git a/gamedata/scripts/xr/lua/init.lua b/gamedata/scripts/xr/lua/init.lua index a86df6980e..ead7b752ae 100644 --- a/gamedata/scripts/xr/lua/init.lua +++ b/gamedata/scripts/xr/lua/init.lua @@ -58,17 +58,24 @@ local G = setmetatable( } ) +local function format_error(msg, err, stack_level) + stack_level = stack_level or 2 + + err = "! " .. _PACKAGE .. ": " + .. msg .. ":\n\n" + .. err + .. "\n" + + return debug.traceback(err, stack_level) +end + local function handle_error(msg, namespace_name) return function(err) if namespace_name then package.loaded[namespace_name] = nil end - err = "! " .. _PACKAGE .. ": " - .. msg .. ":\n\n" - .. err - .. "\n" - err = debug.traceback(err, 2) + err = format_error(msg, err, 3) print(err) error(err) @@ -98,37 +105,6 @@ compile = function(src, namespace_name, script_name) env[namespace_name] = env end - -- Redirect loadstring through this compiler - env.loadstring = compile - - -- Redirect load through this compiler - env.load = function(f, name) - local src = "" - - while true do - local part = f() - if part == nil then - break - elseif type(part == "string") then - if #part == 0 then - break - end - - src = src .. part - end - end - - return compile(src, name) - end - - -- Redirect loadfile through this compiler - env.loadfile = function(path) - local file = io.input(path) - local src = file:read("*a") - file:close() - return compile(src) - end - -- Selectively patch the package module -- to restore unconfigured Lua environment local pkg = {} @@ -150,9 +126,10 @@ compile = function(src, namespace_name, script_name) src = "local this = _M " .. src end - local mod, err = loadstring(src, namespace_name) + local mod, err = _LOADSTRING(src, namespace_name) if not mod then - handle_error("error loading " .. (namespace_name or "script"), namespace_name)(err) + err = format_error("error loading " .. (namespace_name or "script"), err) + return nil, err end local mac = setfenv(mod, env) diff --git a/gamedata/scripts/xr/process.lua b/gamedata/scripts/xr/process.lua index c350f485b1..5bb343c42c 100644 --- a/gamedata/scripts/xr/process.lua +++ b/gamedata/scripts/xr/process.lua @@ -130,7 +130,7 @@ function ScriptProcess:add_string(src) ) end - self:add_function(_COMPILER(src, nil, "console command")) + self:add_function(loadstring(src, nil, "console command")) end return ScriptProcess From 88cbe1c4b5bb0e3a37b29d56036c75f7472762dc Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 8 Jun 2025 21:09:16 +0100 Subject: [PATCH 59/76] Use tables for compiler references, documentation pass --- gamedata/scripts/amx/lua/init.lua | 9 +-- gamedata/scripts/boot/init.lua | 2 +- gamedata/scripts/boot/paths.lua | 4 ++ gamedata/scripts/boot/sandbox.lua | 2 + gamedata/scripts/boot/scripts.lua | 6 +- gamedata/scripts/init.lua | 2 +- gamedata/scripts/xr/classes.lua | 10 ++- gamedata/scripts/xr/compiler.lua | 45 +++++++----- gamedata/scripts/xr/lua/init.lua | 70 ++++++------------- .../xr/{processes.lua => processes/init.lua} | 35 ++++++---- .../scripts/xr/{ => processes}/process.lua | 31 ++++---- src/xrServerEntities/script_process.h | 1 + src/xrServerEntities/script_processes.h | 1 + 13 files changed, 117 insertions(+), 101 deletions(-) rename gamedata/scripts/xr/{processes.lua => processes/init.lua} (63%) rename gamedata/scripts/xr/{ => processes}/process.lua (89%) diff --git a/gamedata/scripts/amx/lua/init.lua b/gamedata/scripts/amx/lua/init.lua index 8434c94c38..757663e344 100644 --- a/gamedata/scripts/amx/lua/init.lua +++ b/gamedata/scripts/amx/lua/init.lua @@ -4,18 +4,15 @@ local xr_lua = require("xr/lua") local unlocalize = require(_PACKAGE .. "/unlocalize") -local old_compile = xr_lua.compile -function xr_lua.compile(src, namespace_name, script_name) +local old_loadstring = xr_lua.loadstring +function xr_lua.loadstring(src, namespace_name, script_name) if namespace_name then print("* " .. _PACKAGE .. ": compiling " .. namespace_name) end - return old_compile( + return old_loadstring( unlocalize(src, namespace_name), namespace_name, script_name ) end - -require("xr/compiler").register_extension("script", xr_lua.compile) -require("xr/compiler").set_default_macro(xr_lua.compile) diff --git a/gamedata/scripts/boot/init.lua b/gamedata/scripts/boot/init.lua index 337472dfec..fcef399214 100644 --- a/gamedata/scripts/boot/init.lua +++ b/gamedata/scripts/boot/init.lua @@ -1,5 +1,5 @@ --- Boot Kernel ---- Establishes a basic functioning X-Ray Lua environment +--- Establishes a functioning X-Ray Lua environment _PACKAGE = "boot" diff --git a/gamedata/scripts/boot/paths.lua b/gamedata/scripts/boot/paths.lua index 432aa8926d..028317d05f 100644 --- a/gamedata/scripts/boot/paths.lua +++ b/gamedata/scripts/boot/paths.lua @@ -16,15 +16,19 @@ function _REGISTER_PATHS(...) end end +-- Fetch filesystem handle local fs = getFS() +-- Get base scripts folder path local base = fs:update_path("$game_scripts$", "") +-- Search for lua files in scripts, and scripts/packages/lib package.path = base .. [[?.lua]] .. ";" .. base .. [[?/init.lua]] .. ";" .. base .. [[packages/lib/?.lua]] .. ";" .. base .. [[packages/lib/?/init.lua]] +-- Search for binary libraries in packages/bin package.cpath = base .. [[packages/bin/?.dll]] .. ";" .. base .. [[packages/bin/?/init.dll]] .. ";" .. base .. [[packages/bin/?.so]] diff --git a/gamedata/scripts/boot/sandbox.lua b/gamedata/scripts/boot/sandbox.lua index adbb3a07db..23d97203db 100644 --- a/gamedata/scripts/boot/sandbox.lua +++ b/gamedata/scripts/boot/sandbox.lua @@ -1,6 +1,7 @@ -- Boot Sandbox -- Disables dangerous Lua primitives +-- Map from package name to dangerous primitives local disabled = { os = { "execute", @@ -13,6 +14,7 @@ local disabled = { } } +-- Iterate disabled map and nil corresponding primitives for k,v in pairs(disabled) do for i=1,#v do _G[k][v[i]] = nil diff --git a/gamedata/scripts/boot/scripts.lua b/gamedata/scripts/boot/scripts.lua index 944199f618..ce25e92d14 100644 --- a/gamedata/scripts/boot/scripts.lua +++ b/gamedata/scripts/boot/scripts.lua @@ -7,23 +7,27 @@ if DISABLE_SCRIPTS then return end +-- Open script.ltx local ini = ini_file("script.ltx") if not ini then return end +-- Check for the common section if not ini:section_exist("common") then error("Missing common section") end +-- Check for the script list if not ini:line_exist("common", "script") then error("Missing script line") end +-- Read the script list local scripts = ini:r_string("common", "script", "") +-- Iterate scripts, requiring each one and optionally calling an init function for script in scripts:gmatch("[^,]+") do - print("requiring " .. script) local mod = require(script) if type(mod) == "table" then local init = mod[script .. "_initialize"] diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index 0da042006d..909a2561fb 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -36,7 +36,7 @@ function print(...) end end ---- Replace loadstring with our own override +--- Replace loadstring with an error-checked version _LOADSTRING = loadstring function loadstring(src, namespace_name, script_name) print("* lua: loading " .. namespace_name) diff --git a/gamedata/scripts/xr/classes.lua b/gamedata/scripts/xr/classes.lua index 7bd014a6c6..91f884f931 100644 --- a/gamedata/scripts/xr/classes.lua +++ b/gamedata/scripts/xr/classes.lua @@ -1,22 +1,30 @@ +-- XR Class Registration + +-- Open script.ltx local ini = ini_file("script.ltx") if not ini then return end +-- Check for the `common` section if not ini:section_exist("common") then error("Missing common section") end +-- Check for class registrators if not ini:line_exist("common", "class_registrators") then error("Missing class_registrators line") end - +-- Read class registrators local regs = ini:r_string("common", "class_registrators", "") + +-- Iterate, load from environment, and invoke each with the object factory for reg_path in regs:gmatch("[^,]+") do local reg = function_object(reg_path) reg(_OBJECT_FACTORY) end +-- Invoke object factory registration method _OBJECT_FACTORY:register_script() diff --git a/gamedata/scripts/xr/compiler.lua b/gamedata/scripts/xr/compiler.lua index 376f96d78a..d77bb9bcdc 100644 --- a/gamedata/scripts/xr/compiler.lua +++ b/gamedata/scripts/xr/compiler.lua @@ -1,46 +1,53 @@ --- XR Lua Compiler --- Lua-friendly virtualization of the original X-Ray script environment +-- XR Compiler Dispatch +-- Extends loadstring with extension-aware dispatch local PATTERN_FILE_PATH = "^(.-)([^\\/]-)%.([^\\/%.]-)%.?$" local PATTERN_MACRO_TAG = "[^ ]+ +=%*= +lang: +([^ ]+) +=%*=[^\n]*(\n.*)" -local extensions = { lua = loadstring } -local state = { - default = loadstring -} +-- Store the original loadstring implementation into a compiler module +local default = { loadstring = loadstring } + +-- Map from file extension to compiler module +local extensions = {} + +-- Associate the default loadstring implementation with the lua file extension +extensions.lua = default +-- Override loadstring with extensible dispatch function loadstring(src, namespace_name, script_name) - local mac = nil + local mod = nil if script_name then local _,_,ext = script_name:match(PATTERN_FILE_PATH) if extensions[ext] then - mac = extensions[ext] + mod = extensions[ext] end end local tag,rest = src:match(PATTERN_MACRO_TAG) if tag ~= nil then src = rest - mac = function_object(tag) + mod = require(tag) end - if mac == nil then - mac = state.default + if mod == nil then + mod = default end - return mac(src, namespace_name, script_name) + return mod.loadstring(src, namespace_name, script_name) end -local function register_extension(k, v) +-- Associate a file extension with a compiler module +local function register_extension(k, mod) print(_PACKAGE .. ": registering extension: " .. k) _REGISTER_PATHS( "?." .. k, "?/init." .. k ) - extensions[k] = v + extensions[k] = mod end +-- Return a list of registered extensions local function get_extensions() local out = {} for k in pairs(extensions) do @@ -49,15 +56,17 @@ local function get_extensions() return out end -local function set_default_macro(mac) - print(_PACKAGE .. ": setting default macro...") - state.default = mac +-- Set the default compiler module +local function set_default_module(mod) + print(_PACKAGE .. ": setting default module...") + default = mod end +-- Return module result return { PATTERN_FILE_PATH = PATTERN_FILE_PATH, PATTERN_MACRO_TAG = PATTERN_MACRO_TAG, register_extension = register_extension, get_extensions = get_extensions, - set_default_macro = set_default_macro + set_default_module = set_default_module } diff --git a/gamedata/scripts/xr/lua/init.lua b/gamedata/scripts/xr/lua/init.lua index ead7b752ae..2392f34fd3 100644 --- a/gamedata/scripts/xr/lua/init.lua +++ b/gamedata/scripts/xr/lua/init.lua @@ -1,48 +1,14 @@ ---local remap = import("/moved").remap +-- XR Lua Compiler +-- The original X-Ray script environment, reimplemented as a loadstring wrapper +local compiler = require("xr/compiler") + +-- _G wrapper with redirection to package.loaded via `require` local G = setmetatable( {}, { __index = function(self, key) - --[[ - -- Fetch the remap for this key - local redir = remap[key] - - -- If we have a redirection... - if redir ~= nil then - -- Check the no-overwrite flag; - -- If set and the key exists in _G, return its value - if redir.if_not_overwritten then - local gv = _G[key] - if gv then - return gv - end - - local res, out = pcall(require, key) - if res then - return out - end - end - - -- Otherwise, fetch the redirected key - if type(redir.to) ~= "string" then - error( - "Redirection from " .. key - .. " has invalid 'to' field: " .. redir.to - ) - end - - -- And recurse with it - local rv = self[redir.to] - - -- If if exists, return it - if rv ~= nil then - return rv - end - end - --]] - - -- Otherwise, check the global key's value and return if valid + -- Check _G for our key and return the result if valid local gv = _G[key] if gv ~= nil then return gv @@ -58,6 +24,7 @@ local G = setmetatable( } ) +-- Error pretty-printer local function format_error(msg, err, stack_level) stack_level = stack_level or 2 @@ -69,6 +36,7 @@ local function format_error(msg, err, stack_level) return debug.traceback(err, stack_level) end +-- Error handler constructor local function handle_error(msg, namespace_name) return function(err) if namespace_name then @@ -82,8 +50,8 @@ local function handle_error(msg, namespace_name) end end -local compile -compile = function(src, namespace_name, script_name) +-- `loadstring` replacement specialized to X-Ray scripts +local function loadstring(src, namespace_name, script_name) local is_g = namespace_name == "_G" local mt = { @@ -155,10 +123,16 @@ compile = function(src, namespace_name, script_name) end end -local compiler = require("xr/compiler") -compiler.register_extension("script", compile) -compiler.set_default_macro(compile) - -return { - compile = compile +-- Prepare module value +local mod = { + loadstring = loadstring } + +-- Register this as the compiler for .script files +compiler.register_extension("script", mod) + +-- Register this as the default compiler +compiler.set_default_module(mod) + +-- Return module value +return mod diff --git a/gamedata/scripts/xr/processes.lua b/gamedata/scripts/xr/processes/init.lua similarity index 63% rename from gamedata/scripts/xr/processes.lua rename to gamedata/scripts/xr/processes/init.lua index c1472c1381..f3409fdb54 100644 --- a/gamedata/scripts/xr/processes.lua +++ b/gamedata/scripts/xr/processes/init.lua @@ -1,10 +1,12 @@ -- Engine interface to domain-scoped coroutines -- Formerly part of CScriptManager -local ScriptProcess = require("xr/process") +local ScriptProcess = require("xr/processes/process") +-- Script processes class local ScriptProcesses = {} +-- Constructor function ScriptProcesses.new() return setmetatable( { @@ -21,39 +23,46 @@ function ScriptProcesses.new() ) end +-- Add a script process by name, with a set of scripts to add by default function ScriptProcesses:add(name, scripts) self.processes[name] = ScriptProcess.new(name, scripts) end +-- Remove a script process by name function ScriptProcesses:remove(name) self.processes[name] = nil end +-- Test the existence of a script process by name function ScriptProcesses:has(name) return self.processes[name] ~= nil end +-- Get a script process by name function ScriptProcesses:get(name) return self.processes[name] end --- Prepare module output +-- Prepare package output local processes = ScriptProcesses.new() --- Game process -local ini_script = ini_file("configs\\script.ltx") +-- Setup game process +do + local ini_script = ini_file("configs\\script.ltx") -local game_scripts = "" -if ini_script:section_exist("single") - and ini_script:line_exist("single", "script") -then - game_scripts = ini_script:r_string("single", "script"); -end + local game_scripts = "" + if ini_script:section_exist("single") + and ini_script:line_exist("single", "script") + then + game_scripts = ini_script:r_string("single", "script"); + end -processes:add("game", game_scripts) + processes:add("game", game_scripts) +end --- Level process +-- If a level exists... if level.present() then + -- Setup level process local ini_level = ini_file( string.format("levels\\%s\\level.ltx", level.name()) ) @@ -68,5 +77,5 @@ if level.present() then processes:add("level", level_scripts) end --- Return module output +-- Return package output return processes diff --git a/gamedata/scripts/xr/process.lua b/gamedata/scripts/xr/processes/process.lua similarity index 89% rename from gamedata/scripts/xr/process.lua rename to gamedata/scripts/xr/processes/process.lua index 5bb343c42c..a4c34ca310 100644 --- a/gamedata/scripts/xr/process.lua +++ b/gamedata/scripts/xr/processes/process.lua @@ -6,8 +6,10 @@ local DEBUG = false local DISABLE_SCRIPTS = false +-- Script process class ScriptProcess = {} +-- Constructor function ScriptProcess.new(name, scripts) if DEBUG then print("* Initializing " .. name .. " script process") @@ -40,6 +42,7 @@ function ScriptProcess.new(name, scripts) return out end +-- Update entrypoint, called by the engine function ScriptProcess:update() if DISABLE_SCRIPTS then while #self.coroutines > 0 do @@ -70,7 +73,7 @@ function ScriptProcess:update() end end --- Add a raw coroutine to the script process +-- Add a raw coroutine to the process function ScriptProcess:add_coroutine(co) if DEBUG then print( @@ -83,7 +86,7 @@ function ScriptProcess:add_coroutine(co) table.insert(self.coroutines, co) end --- Add a function to the script process as a coroutine +-- Add a function to the process as a coroutine function ScriptProcess:add_function(f) if DEBUG then print( @@ -96,6 +99,19 @@ function ScriptProcess:add_function(f) self:add_coroutine(coroutine.create(f)) end +-- Add a string of source code to the script process +function ScriptProcess:add_string(src) + if DEBUG then + print( + "* Adding string ".. src .. " to " .. self.name .. " script process" + ) + end + + self:add_function(loadstring(src, nil, "console command")) +end + +-- Add a package's main function to the process by name +-- Optionally force-reloading it function ScriptProcess:add_script(script_name, reload) if DEBUG then print("* Adding script ".. script_name .. " to " .. self.name .. " script process") @@ -123,14 +139,5 @@ function ScriptProcess:add_script(script_name, reload) ) end -function ScriptProcess:add_string(src) - if DEBUG then - print( - "* Adding string ".. src .. " to " .. self.name .. " script process" - ) - end - - self:add_function(loadstring(src, nil, "console command")) -end - +-- Return class as package value return ScriptProcess diff --git a/src/xrServerEntities/script_process.h b/src/xrServerEntities/script_process.h index 93180f05c7..8c137a5182 100644 --- a/src/xrServerEntities/script_process.h +++ b/src/xrServerEntities/script_process.h @@ -1,5 +1,6 @@ #include +// Luabind wrapper for xr/processes/process class CScriptProcess { private: diff --git a/src/xrServerEntities/script_processes.h b/src/xrServerEntities/script_processes.h index 49534a5258..efb8e719fb 100644 --- a/src/xrServerEntities/script_processes.h +++ b/src/xrServerEntities/script_processes.h @@ -1,6 +1,7 @@ #include #include "script_process.h" +// Luabind wrapper for xr/processes class CScriptProcesses { private: From 9c4f25e71f5c373ab3bc44c60e48ca6f965ae4a5 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 10 Jun 2025 04:25:25 +0100 Subject: [PATCH 60/76] Fix broken `local function x(a, b, c)` unlocalization --- gamedata/scripts/amx/lua/unlocalize.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/gamedata/scripts/amx/lua/unlocalize.lua b/gamedata/scripts/amx/lua/unlocalize.lua index 1569f27c3a..ca07d92e62 100644 --- a/gamedata/scripts/amx/lua/unlocalize.lua +++ b/gamedata/scripts/amx/lua/unlocalize.lua @@ -62,7 +62,6 @@ local function unlocalize(src, namespace_name) if ur then tokens[i] = ur unlocal_performed = true - tokens[i] = s goto next_token end From 8c8fb1c24bb69f25bba57276208cb51e88942e67 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 10 Jun 2025 05:47:55 +0100 Subject: [PATCH 61/76] Account for `\r` endings when splitting Lua lines for unlocalization --- gamedata/scripts/amx/lua/unlocalize.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gamedata/scripts/amx/lua/unlocalize.lua b/gamedata/scripts/amx/lua/unlocalize.lua index ca07d92e62..c39b44dc8a 100644 --- a/gamedata/scripts/amx/lua/unlocalize.lua +++ b/gamedata/scripts/amx/lua/unlocalize.lua @@ -35,7 +35,7 @@ local function unlocalize(src, namespace_name) if not namespace_name then return src end - + local unlocalizer = require("amx/unlocalize").get(namespace_name) if not unlocalizer then return src @@ -45,7 +45,7 @@ local function unlocalize(src, namespace_name) local temp = src local tokens = {} - for line in string.gmatch(temp, "[^\n]+") do + for line in string.gmatch(temp, "[^\n\r]+") do table.insert(tokens, line) end From 883f58f2c7c2a5864c421bcfd834134e264deb49 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 10 Jun 2025 21:06:03 +0100 Subject: [PATCH 62/76] Use `@`-prefixed `script_name` instead of `namespace_name` for `xr/lua` - Fixes debug introspection of script paths --- gamedata/scripts/xr/lua/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamedata/scripts/xr/lua/init.lua b/gamedata/scripts/xr/lua/init.lua index 2392f34fd3..0b7be42b41 100644 --- a/gamedata/scripts/xr/lua/init.lua +++ b/gamedata/scripts/xr/lua/init.lua @@ -94,7 +94,7 @@ local function loadstring(src, namespace_name, script_name) src = "local this = _M " .. src end - local mod, err = _LOADSTRING(src, namespace_name) + local mod, err = _LOADSTRING(src, script_name and ("@" .. script_name)) if not mod then err = format_error("error loading " .. (namespace_name or "script"), err) return nil, err From 126aa01e4fb8e41f938fb3411840aca14601a41b Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Tue, 10 Jun 2025 21:49:29 +0100 Subject: [PATCH 63/76] Pass `loadstring` to base impl with env extension in `xr/lua` - Prevents breakage of `debug.dump` use cases --- gamedata/scripts/xr/lua/init.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gamedata/scripts/xr/lua/init.lua b/gamedata/scripts/xr/lua/init.lua index 0b7be42b41..ed85d4c2bb 100644 --- a/gamedata/scripts/xr/lua/init.lua +++ b/gamedata/scripts/xr/lua/init.lua @@ -73,6 +73,15 @@ local function loadstring(src, namespace_name, script_name) env[namespace_name] = env end + -- Pass loadstring through to base _LOADSTRING within our environment + -- Ensures any uses of debug.dump function as expected + env.loadstring = function(src, name) + return setfenv( + _LOADSTRING(src, name), + env + ) + end + -- Selectively patch the package module -- to restore unconfigured Lua environment local pkg = {} From 2c0b7d8ea2b85042b201c3d08d09952e321f132c Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 11 Jun 2025 05:02:09 +0100 Subject: [PATCH 64/76] Replace all stateful `xr/lua` environment with metatable indirection - Prevents injected values from appearing in key iterations, inadvertent infinite loops --- gamedata/scripts/xr/lua/init.lua | 143 +++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 47 deletions(-) diff --git a/gamedata/scripts/xr/lua/init.lua b/gamedata/scripts/xr/lua/init.lua index ed85d4c2bb..d8b48c4599 100644 --- a/gamedata/scripts/xr/lua/init.lua +++ b/gamedata/scripts/xr/lua/init.lua @@ -1,14 +1,65 @@ --- XR Lua Compiler --- The original X-Ray script environment, reimplemented as a loadstring wrapper +--- XR Lua Compiler +--- The original X-Ray script environment, reimplemented as a loadstring wrapper local compiler = require("xr/compiler") --- _G wrapper with redirection to package.loaded via `require` -local G = setmetatable( - {}, +-- `package` module override for X-Ray Lua scripts +local XR_PACKAGE = setmetatable( + { + -- Use unconfigured Lua path + path = _DEFAULT_PATH, + -- Use unconfigured Lua loaders + loaders = { + _LOADERS.pre, + _LOADERS.lib, + _LOADERS.bin, + _LOADERS.aio, + }, + }, { __index = function(self, key) - -- Check _G for our key and return the result if valid + + if key == "path" then + return XR_PATH + end + + if key == "loaders" then + return XR_LOADERS + end + + return package[key] + end, + __newindex = package, + } +) + +-- Pass loadstring through to base _LOADSTRING for X-Ray Lua scripts +-- Ensures any uses of debug.dump function as expected +local XR_LOADSTRING = function(src, name) + return setfenv( + _LOADSTRING(src, name), + env + ) +end + +-- Global scope wrapper for X-Ray Lua scripts +-- Indirects through `_G`, and `package.loaded` via `require` +local XR_G = setmetatable( + { + -- Indirect package to our wrapper + package = XR_PACKAGE, + -- Indirect loadstring to our wrapper + loadstring = XR_LOADSTRING, + }, + { + -- Override key reads + __index = function(self, key) + -- If the index is _G, indirect back to this object + if key == "_G" then + return self + end + + -- Check the real _G for our key and return the result if valid local gv = _G[key] if gv ~= nil then return gv @@ -20,6 +71,7 @@ local G = setmetatable( return out end end, + -- Send key writes straight to `_G` __newindex = _G } ) @@ -52,70 +104,64 @@ end -- `loadstring` replacement specialized to X-Ray scripts local function loadstring(src, namespace_name, script_name) - local is_g = namespace_name == "_G" - - local mt = { - __index = G - } - - if is_g then - mt.__newindex = G + -- Construct our script's environment table + local env = {} + + -- Create a wrapper around lua's base loadstring that runs in our environment + local function loadstring(src, name) + return setfenv( + _LOADSTRING(src, name), + env + ) end - local env = setmetatable({ _G = G }, mt) - - if not is_g then - -- If this is a named module, emplace relevant globals - if namespace_name then - env._M = env - env._PACKAGE = namespace_name - env._FILE = script_name - env[namespace_name] = env - end + -- Construct the metatable for our environment + local mt = { + __index = function(self, key) + -- Dynamically indirect to our loadstring wrapper when required + if key == "loadstring" then + return loadstring + end - -- Pass loadstring through to base _LOADSTRING within our environment - -- Ensures any uses of debug.dump function as expected - env.loadstring = function(src, name) - return setfenv( - _LOADSTRING(src, name), - env - ) + -- Otherwise, indirect to XR_G + return XR_G[key] end + } - -- Selectively patch the package module - -- to restore unconfigured Lua environment - local pkg = {} - for k,v in pairs(package) do - pkg[k] = v - end - pkg.path = _DEFAULT_PATH - pkg.loaders = { - _LOADERS.pre, - _LOADERS.lib, - _LOADERS.bin, - _LOADERS.aio, - } - env.package = pkg + -- If we're loading _g.script, forward environment writes to _G + if namespace_name == "_G" then + mt.__newindex = XR_G end + -- Associate our environment with its metatable + setmetatable(env, mt) + + -- If we have a namespace name, inject locals that derive from it if namespace_name then - src = "local script_name = function() return _PACKAGE end " .. src - src = "local this = _M " .. src + src = "local this = _G[script_name()] " .. src + src = "local script_name = function() return \"" .. namespace_name .. "\" end " .. src end + -- Load the resulting script, using the filename to ensure `debug` compat local mod, err = _LOADSTRING(src, script_name and ("@" .. script_name)) + + -- On load failure, annotate the error and early-out if not mod then err = format_error("error loading " .. (namespace_name or "script"), err) return nil, err end + -- Apply our environment to the resulting function local mac = setfenv(mod, env) + -- Return a package constructor for the loaded module return function() + -- Prepopulate `package.loaded` in case of reentrancy if namespace_name then package.loaded[namespace_name] = env end + -- Call our script function with an appropriate error handler local _, out = xpcall( mac, handle_error( @@ -124,9 +170,12 @@ local function loadstring(src, namespace_name, script_name) ) ) + -- If we have a namespace name... if namespace_name then + -- Return the prepopulated package return package.loaded[namespace_name] else + -- Otherwise, return the module output directly return out end end From d1057c4b7102c99912f7448a68c19fac8d2668d3 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 11 Jun 2025 06:28:28 +0100 Subject: [PATCH 65/76] Fix broken unlocalization of `local a, b` definitions --- gamedata/scripts/amx/lua/unlocalize.lua | 36 +++++++++---------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/gamedata/scripts/amx/lua/unlocalize.lua b/gamedata/scripts/amx/lua/unlocalize.lua index c39b44dc8a..c8ecfec753 100644 --- a/gamedata/scripts/amx/lua/unlocalize.lua +++ b/gamedata/scripts/amx/lua/unlocalize.lua @@ -18,19 +18,6 @@ local function contains(lst, a) return false end -local function unlocal_regex(unlocals, s) - local pattern = [[^(local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(%(.*)$]] - local _, _, c, d, e, f, g = string.match(s, pattern) - - if e and contains(unlocals, e) then - print("[unlocal_regex] found variable " .. e .. " to unlocal") - s = c .. d .. e .. f .. g - return s - end - - return nil -end - local function unlocalize(src, namespace_name) if not namespace_name then return src @@ -58,9 +45,14 @@ local function unlocalize(src, namespace_name) end -- local function x(a,b,c) - local ur = unlocal_regex(unlocalizer, s) - if ur then - tokens[i] = ur + local _, _, c, d, e, f, g = string.match( + s, + [[^(local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(%(.*)$]] + ) + + if e and contains(unlocalizer, e) then + print("[unlocal_regex] found variable " .. e .. " to unlocal") + tokens[i] = c .. d .. e .. f .. g unlocal_performed = true goto next_token end @@ -69,8 +61,7 @@ local function unlocalize(src, namespace_name) -- local a -- local a,b,c = ... (if one of a,b,c is in unlocalizers list - all of them will be unlocalized) -- local x; local y; - unsupported yet - local pattern = [[^local%s+(.*)]] - local c = string.match(s, pattern) or "" + local c = string.match(s, [[^local%s+(.*)]]) or "" if #c > 0 then local r = [[(.*)--.*]] local nc = string.match(c, r) @@ -79,18 +70,17 @@ local function unlocalize(src, namespace_name) end end - local pattern = [[([^=]+)=(.*)]] - local variables, values = string.match(c, pattern) + local variables = string.match(c, [[^([^=]+)]]) + local values = string.match(c, [[=([^=]+)$]]) if variables then - for v in string.gmatch(variables, "[^,]+") do + for v in string.gmatch(variables, "[^, ]+") do v = string_trim(v) if contains(unlocalizer, v) then unlocal_performed = true print("found variable", v, "to unlocal") s = c if not values then - local r = [[(.*)(--.*)]] - local lhs, rhs = string.match(s, r) + local lhs, rhs = string.match(s, [[(.*)(--.*)]]) if lhs and rhs then s = lhs .. "= nil " .. rhs else From 36d9ec6033f6dc0c19d3deab2f640f7d17a7ddfd Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 11 Jun 2025 19:39:30 +0100 Subject: [PATCH 66/76] Remove unnecessary key redirection from `XR_PACKAGE` --- gamedata/scripts/xr/lua/init.lua | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/gamedata/scripts/xr/lua/init.lua b/gamedata/scripts/xr/lua/init.lua index d8b48c4599..7a9223a692 100644 --- a/gamedata/scripts/xr/lua/init.lua +++ b/gamedata/scripts/xr/lua/init.lua @@ -17,18 +17,7 @@ local XR_PACKAGE = setmetatable( }, }, { - __index = function(self, key) - - if key == "path" then - return XR_PATH - end - - if key == "loaders" then - return XR_LOADERS - end - - return package[key] - end, + __index = package, __newindex = package, } ) From 69eaff4cf6450365a4ed0eff58933ad243b9605b Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 11 Jun 2025 19:40:07 +0100 Subject: [PATCH 67/76] Unlocalizer: Fix `local function` early-out, comment matching --- gamedata/scripts/amx/lua/init.lua | 2 +- gamedata/scripts/amx/lua/unlocalize.lua | 51 ++++++++++++++++--------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/gamedata/scripts/amx/lua/init.lua b/gamedata/scripts/amx/lua/init.lua index 757663e344..32f9629037 100644 --- a/gamedata/scripts/amx/lua/init.lua +++ b/gamedata/scripts/amx/lua/init.lua @@ -2,7 +2,7 @@ -- Patches unlocalization onto the base XR Lua compiler local xr_lua = require("xr/lua") -local unlocalize = require(_PACKAGE .. "/unlocalize") +local unlocalize = require(_PACKAGE .. "/unlocalize").unlocalize local old_loadstring = xr_lua.loadstring function xr_lua.loadstring(src, namespace_name, script_name) diff --git a/gamedata/scripts/amx/lua/unlocalize.lua b/gamedata/scripts/amx/lua/unlocalize.lua index c8ecfec753..572ade97f6 100644 --- a/gamedata/scripts/amx/lua/unlocalize.lua +++ b/gamedata/scripts/amx/lua/unlocalize.lua @@ -1,5 +1,7 @@ -- Unlocalizer for xr/lua scripts +local DEBUG = false + local function string_trim(s, v) if v == nil then v = " \t\n\r\f\v" @@ -18,16 +20,7 @@ local function contains(lst, a) return false end -local function unlocalize(src, namespace_name) - if not namespace_name then - return src - end - - local unlocalizer = require("amx/unlocalize").get(namespace_name) - if not unlocalizer then - return src - end - +local function unlocalize_with(src, unlocalizer) local unlocal_performed = false local temp = src @@ -50,10 +43,14 @@ local function unlocalize(src, namespace_name) [[^(local)([\t ]+)(function)([\t ]+)([_a-zA-Z].*)([\t ]*)(%(.*)$]] ) - if e and contains(unlocalizer, e) then - print("[unlocal_regex] found variable " .. e .. " to unlocal") - tokens[i] = c .. d .. e .. f .. g - unlocal_performed = true + if e then + if contains(unlocalizer, e) then + if DEBUG then + print("[unlocal_regex] found variable " .. e .. " to unlocal") + end + tokens[i] = c .. d .. e .. f .. g + unlocal_performed = true + end goto next_token end @@ -77,14 +74,16 @@ local function unlocalize(src, namespace_name) v = string_trim(v) if contains(unlocalizer, v) then unlocal_performed = true - print("found variable", v, "to unlocal") + if DEBUG then + print("found variable", v, "to unlocal") + end s = c if not values then - local lhs, rhs = string.match(s, [[(.*)(--.*)]]) + local lhs, rhs = string.match(s, [[([^-]+)(%-%-[^-]*)]]) if lhs and rhs then s = lhs .. "= nil " .. rhs else - s = s .. " = nil" + s = s .. "= nil" end end tokens[i] = s @@ -103,4 +102,20 @@ local function unlocalize(src, namespace_name) return src end -return unlocalize +local function unlocalize(src, namespace_name) + if not namespace_name then + return src + end + + local unlocalizer = require("amx/unlocalize").get(namespace_name) + if not unlocalizer then + return src + end + + return unlocalize_with(src, unlocalizer) +end + +return { + unlocalize_with = unlocalize_with, + unlocalize = unlocalize, +} From 0490053be68b411c6f885f8fef46ebf2c085290b Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 11 Jun 2025 19:40:46 +0100 Subject: [PATCH 68/76] Implement basic unit testing machinery in `tests` --- gamedata/scripts/tests/init.lua | 5 +++++ gamedata/scripts/tests/util.lua | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 gamedata/scripts/tests/init.lua create mode 100644 gamedata/scripts/tests/util.lua diff --git a/gamedata/scripts/tests/init.lua b/gamedata/scripts/tests/init.lua new file mode 100644 index 0000000000..9b464d82d6 --- /dev/null +++ b/gamedata/scripts/tests/init.lua @@ -0,0 +1,5 @@ +--- Unit testing framework + +-- Currently just a container for reusable code. +-- Can be extended into a robust test runner once +-- nested directory machinery is implemented. diff --git a/gamedata/scripts/tests/util.lua b/gamedata/scripts/tests/util.lua new file mode 100644 index 0000000000..edc862c6b5 --- /dev/null +++ b/gamedata/scripts/tests/util.lua @@ -0,0 +1,28 @@ +-- Given a named set of tests, run them and report their results +function run_tests(name, tests) + print("+ [TEST] " .. name) + + local passes = {} + local fails = {} + + for k,v in pairs(tests) do + local res, err = v() + if res then + table.insert(passes, k) + else + table.insert(fails, k .. ": " .. err) + end + end + + for _,v in ipairs(passes) do + print("- [PASS] " .. v) + end + + for _,v in ipairs(fails) do + print("! [FAIL] " .. v) + end +end + +return { + run_tests = run_tests, +} From 5218de6e8a4d144815fecbcacb2ee69137d5b4c0 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 11 Jun 2025 19:41:01 +0100 Subject: [PATCH 69/76] Implement unlocalizer unit tests --- gamedata/scripts/amx/lua/init.lua | 3 + gamedata/scripts/amx/lua/tests.lua | 110 +++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 gamedata/scripts/amx/lua/tests.lua diff --git a/gamedata/scripts/amx/lua/init.lua b/gamedata/scripts/amx/lua/init.lua index 32f9629037..994c6590be 100644 --- a/gamedata/scripts/amx/lua/init.lua +++ b/gamedata/scripts/amx/lua/init.lua @@ -16,3 +16,6 @@ function xr_lua.loadstring(src, namespace_name, script_name) script_name ) end + +-- Run unit tests +require("amx/lua/tests") diff --git a/gamedata/scripts/amx/lua/tests.lua b/gamedata/scripts/amx/lua/tests.lua new file mode 100644 index 0000000000..f7fe38ab0a --- /dev/null +++ b/gamedata/scripts/amx/lua/tests.lua @@ -0,0 +1,110 @@ +local run_tests = require("tests/util").run_tests +local unlocalize_with = require("amx/lua/unlocalize").unlocalize_with + +local SRC = { + declare_function = [[ +local function x(a, b, c) -- define a function + return a, b, c +end + ]], + + declare_var_single = [[ +local a -- declare a single var + ]], + + define_var_single = [[ +local a = 1 -- define a single var + ]], + declare_var_multi = [[ +local a, b, c -- declare multiple vars + ]], + define_var_multi = [[ +local a, b, c = 1, 2, 3 -- define multiple vars + ]], + declare_var_single_sequence = [[ +local a; local b; local c; -- declare a sequence of vars + ]], + define_var_single_sequence = [[ +local a = 1; local b = 2; local c = 3; define a sequence of vars + ]], +} + +local PASSES = { + declare_function = [[ +function x(a, b, c) -- define a function + return a, b, c +end + ]], + + declare_var_single = [[ +a = nil -- declare a single var + ]], + + define_var_single = [[ +a = 1 -- define a single var + ]], + declare_var_multi = [[ +a, b, c = nil -- declare multiple vars + ]], + define_var_multi = [[ +a, b, c = 1, 2, 3 -- define multiple vars + ]], +} + +local FAILS = { + declare_var_single_sequence = [[ +a = nil; b = nil; c = nil; -- declare a sequence of vars + ]], + define_var_single_sequence = [[ +a = 1; b = 2; c = 3; -- define a sequence of vars + ]], +} + +local unlocalizer = {"x", "a", "b", "c"} + +local tests = {} + +local ERR_MISMATCHED = +[[Mismatched unlocalizer output +src: +%s +unlocalized: +%s +target: +%s]] + +for k,targ in pairs(PASSES) do + tests[k] = function() + local src = SRC[k] + local res = unlocalize_with(src, unlocalizer) + + if res == targ then + return true + else + return false, string.format(ERR_MISMATCHED, v, res, targ) + end + end +end + +local ERR_UNEXPECTED = +[[Unexpected unlocalizer output +src: +%s +unlocalized: +%s +target: +%s]] + +for k,targ in pairs(FAILS) do + tests[k .. " (unsupported)"] = function() + local src = SRC[k] + local res = unlocalize_with(src, unlocalizer) + if res ~= targ then + return true + else + return false, string.format(ERR_UNEXPECTED, src, res, targ) + end + end +end + +run_tests("amx/lua", tests) From 4bb0e7321110eaf743ed370fa9d694fa46089ad1 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 11 Jun 2025 19:41:20 +0100 Subject: [PATCH 70/76] Use `loadstring` instead of `_COMPILER` in `CScriptEngine` --- src/xrServerEntities/script_engine.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 39b40ea541..4ff645eed3 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -572,10 +572,11 @@ int CScriptEngine::load_string( LPCSTR caNameSpaceName ) { - lua_getglobal(lua(), "_COMPILER"); + // Use the Lua-side loadstring primitive, since luaL_loadstring would step around script compiler machinery + lua_getglobal(lua(), "loadstring"); if (!lua_isfunction(lua(), -1)) { - FATAL("_COMPILER not available"); + FATAL("loadstring not available"); } lua_pushstring(lua(), caString); From ca369d4aadf39ecc9362a099e7c9986a41d93ba6 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 13 Jun 2025 22:16:06 +0100 Subject: [PATCH 71/76] Preserve results of recursive filesystem scans to prevent loss of listings --- src/xrGame/fs_registrator_script.cpp | 4 ++-- src/xrServerEntities/script_engine.cpp | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/xrGame/fs_registrator_script.cpp b/src/xrGame/fs_registrator_script.cpp index 5f775e77d2..65943ae546 100644 --- a/src/xrGame/fs_registrator_script.cpp +++ b/src/xrGame/fs_registrator_script.cpp @@ -131,8 +131,8 @@ class FS_file_list_ex FS_file_list_ex::FS_file_list_ex(LPCSTR path, u32 flags, LPCSTR mask) { FS_Path* P = FS.get_path(path); - P->m_Flags.set(FS_Path::flNeedRescan,TRUE); - FS.m_Flags.set(CLocatorAPI::flNeedCheck,TRUE); + P->m_Flags.set(FS_Path::flNeedRescan, !(flags & FS_RootOnly)); + FS.m_Flags.set(CLocatorAPI::flNeedCheck, flags & FS_RootOnly); FS.rescan_pathes(); FS_FileSet files; diff --git a/src/xrServerEntities/script_engine.cpp b/src/xrServerEntities/script_engine.cpp index 4ff645eed3..c839b3d615 100644 --- a/src/xrServerEntities/script_engine.cpp +++ b/src/xrServerEntities/script_engine.cpp @@ -439,11 +439,6 @@ void CScriptEngine::init() // lua_sethook(lua(), lua_hook_call, LUA_MASKLINE|LUA_MASKCALL|LUA_MASKRET, 0); - // Force the FS to recursively enumerate the scripts folder - FS_Path* P = FS.get_path("$game_scripts$"); - P->m_Flags.set(FS_Path::flNeedRescan, TRUE); - FS.rescan_pathes(); - // Emplace the object factory luabind::object(lua(), const_cast(&object_factory())).pushvalue(); lua_setglobal(lua(), "_OBJECT_FACTORY"); From e0aafea6c152cc6c980645d099dc745bbb2bdff1 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 13 Jun 2025 22:19:46 +0100 Subject: [PATCH 72/76] Migrate module path separators from `/` to idiomatic Lua `.` --- gamedata/configs/mod_script_amx.ltx | 4 ++-- gamedata/scripts/amx/init.lua | 9 +++++++-- gamedata/scripts/amx/lua/init.lua | 6 +++--- gamedata/scripts/amx/lua/tests.lua | 4 ++-- gamedata/scripts/amx/lua/unlocalize.lua | 2 +- gamedata/scripts/boot/function_object.lua | 1 + gamedata/scripts/boot/init.lua | 10 +++++----- gamedata/scripts/boot/loader.lua | 4 +++- gamedata/scripts/boot/paths.lua | 14 +++++++------- gamedata/scripts/init.lua | 3 ++- gamedata/scripts/xr/compiler.lua | 2 +- gamedata/scripts/xr/lua/init.lua | 2 +- gamedata/scripts/xr/processes/init.lua | 2 +- src/xrServerEntities/script_processes.h | 2 +- 14 files changed, 37 insertions(+), 28 deletions(-) diff --git a/gamedata/configs/mod_script_amx.ltx b/gamedata/configs/mod_script_amx.ltx index 612501234c..eebff96c0d 100644 --- a/gamedata/configs/mod_script_amx.ltx +++ b/gamedata/configs/mod_script_amx.ltx @@ -1,3 +1,3 @@ ![common] -script = xr/compiler, xr/lua, amx, _G, _g_patches, xr/classes, xr/processes, dxml_core ->class_registrators = amx/registrator.register +script = xr.compiler, xr.lua, amx, _G, _g_patches, xr.classes, xr.processes, dxml_core +>class_registrators = amx.registrator.register diff --git a/gamedata/scripts/amx/init.lua b/gamedata/scripts/amx/init.lua index 25a4fc3666..25a4c1a753 100644 --- a/gamedata/scripts/amx/init.lua +++ b/gamedata/scripts/amx/init.lua @@ -2,7 +2,12 @@ -- Extends base X-Ray script functionality --- Setup unlocalizer data model -require(_PACKAGE .. "/unlocalize") +require(_PACKAGE .. ".unlocalize") --- Patch xr/lua compiler with modded exes extensions -require(_PACKAGE .. "/lua") +require(_PACKAGE .. ".lua") + +--- Export registrator from module to allow foo.bar.baz syntax in script.ltx +return { + registrator = require(_PACKAGE .. ".registrator") +} diff --git a/gamedata/scripts/amx/lua/init.lua b/gamedata/scripts/amx/lua/init.lua index 994c6590be..8c8ba24cab 100644 --- a/gamedata/scripts/amx/lua/init.lua +++ b/gamedata/scripts/amx/lua/init.lua @@ -1,8 +1,8 @@ -- AMX Lua Compiler -- Patches unlocalization onto the base XR Lua compiler -local xr_lua = require("xr/lua") -local unlocalize = require(_PACKAGE .. "/unlocalize").unlocalize +local xr_lua = require("xr.lua") +local unlocalize = require(_PACKAGE .. ".unlocalize").unlocalize local old_loadstring = xr_lua.loadstring function xr_lua.loadstring(src, namespace_name, script_name) @@ -18,4 +18,4 @@ function xr_lua.loadstring(src, namespace_name, script_name) end -- Run unit tests -require("amx/lua/tests") +require("amx.lua.tests") diff --git a/gamedata/scripts/amx/lua/tests.lua b/gamedata/scripts/amx/lua/tests.lua index f7fe38ab0a..f19f2139a3 100644 --- a/gamedata/scripts/amx/lua/tests.lua +++ b/gamedata/scripts/amx/lua/tests.lua @@ -1,5 +1,5 @@ -local run_tests = require("tests/util").run_tests -local unlocalize_with = require("amx/lua/unlocalize").unlocalize_with +local run_tests = require("tests.util").run_tests +local unlocalize_with = require("amx.lua.unlocalize").unlocalize_with local SRC = { declare_function = [[ diff --git a/gamedata/scripts/amx/lua/unlocalize.lua b/gamedata/scripts/amx/lua/unlocalize.lua index 572ade97f6..1f39a6e512 100644 --- a/gamedata/scripts/amx/lua/unlocalize.lua +++ b/gamedata/scripts/amx/lua/unlocalize.lua @@ -107,7 +107,7 @@ local function unlocalize(src, namespace_name) return src end - local unlocalizer = require("amx/unlocalize").get(namespace_name) + local unlocalizer = require("amx.unlocalize").get(namespace_name) if not unlocalizer then return src end diff --git a/gamedata/scripts/boot/function_object.lua b/gamedata/scripts/boot/function_object.lua index 4a37cc4d03..98ab22189b 100644 --- a/gamedata/scripts/boot/function_object.lua +++ b/gamedata/scripts/boot/function_object.lua @@ -4,6 +4,7 @@ function function_object(str) local path = {} for v in string.gmatch(str, "[^%.]+") do + v = v:gsub("/", ".") table.insert(path, v) end diff --git a/gamedata/scripts/boot/init.lua b/gamedata/scripts/boot/init.lua index fcef399214..0700035911 100644 --- a/gamedata/scripts/boot/init.lua +++ b/gamedata/scripts/boot/init.lua @@ -4,19 +4,19 @@ _PACKAGE = "boot" -- Disable unsafe Lua primitives -require("boot/sandbox") +require("boot.sandbox") -- Setup package.path machinery -require("boot/paths") +require("boot.paths") -- Setup package.loaders machinery -require("boot/loader") +require("boot.loader") -- Setup engine interface -require("boot/function_object") +require("boot.function_object") -- Ensure _G loads on first require package.loaded._G = nil -- Run startup modules defined in script.ltx -require("boot/scripts") +require("boot.scripts") diff --git a/gamedata/scripts/boot/loader.lua b/gamedata/scripts/boot/loader.lua index ca2823605a..d1da228ec5 100644 --- a/gamedata/scripts/boot/loader.lua +++ b/gamedata/scripts/boot/loader.lua @@ -31,7 +31,9 @@ function _LOADERS.fs(name) if seg:sub(1, #base) == base then -- Strip the base path, interpolate package name, -- and replace separators to produce a filename - local fname = seg:sub(#base + 1):gsub("?", name):gsub("/", "\\") + local sname = name:gsub("%.", "\\") + local fname = seg:sub(#base + 1) + fname = fname:gsub("?", sname) -- Get an xray path from our filename local path = fs:update_path("$game_scripts$", fname) diff --git a/gamedata/scripts/boot/paths.lua b/gamedata/scripts/boot/paths.lua index 028317d05f..d2e59b8a04 100644 --- a/gamedata/scripts/boot/paths.lua +++ b/gamedata/scripts/boot/paths.lua @@ -24,12 +24,12 @@ local base = fs:update_path("$game_scripts$", "") -- Search for lua files in scripts, and scripts/packages/lib package.path = base .. [[?.lua]] - .. ";" .. base .. [[?/init.lua]] - .. ";" .. base .. [[packages/lib/?.lua]] - .. ";" .. base .. [[packages/lib/?/init.lua]] + .. ";" .. base .. [[?\init.lua]] + .. ";" .. base .. [[packages\lib\?.lua]] + .. ";" .. base .. [[packages\lib\?\init.lua]] -- Search for binary libraries in packages/bin -package.cpath = base .. [[packages/bin/?.dll]] - .. ";" .. base .. [[packages/bin/?/init.dll]] - .. ";" .. base .. [[packages/bin/?.so]] - .. ";" .. base .. [[packages/bin/?/init.so]] +package.cpath = base .. [[packages\bin\?.dll]] + .. ";" .. base .. [[packages\bin\?\init.dll]] + .. ";" .. base .. [[packages\bin\?.so]] + .. ";" .. base .. [[packages\bin\?\init.so]] diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index 909a2561fb..fe0bb3f058 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -114,7 +114,8 @@ end --- Emplace minimal X-Ray FS loader function _LOADERS.init(name) local fs = getFS() - local path = fs:update_path("$game_scripts$", name:gsub("/", "\\")) + local sname = name:gsub("%.", "\\") + local path = fs:update_path("$game_scripts$", sname) if not path then return "\n\tInvalid path " .. path end diff --git a/gamedata/scripts/xr/compiler.lua b/gamedata/scripts/xr/compiler.lua index d77bb9bcdc..14a6498c1e 100644 --- a/gamedata/scripts/xr/compiler.lua +++ b/gamedata/scripts/xr/compiler.lua @@ -42,7 +42,7 @@ local function register_extension(k, mod) print(_PACKAGE .. ": registering extension: " .. k) _REGISTER_PATHS( "?." .. k, - "?/init." .. k + "?\\init." .. k ) extensions[k] = mod end diff --git a/gamedata/scripts/xr/lua/init.lua b/gamedata/scripts/xr/lua/init.lua index 7a9223a692..1eb796b95e 100644 --- a/gamedata/scripts/xr/lua/init.lua +++ b/gamedata/scripts/xr/lua/init.lua @@ -1,7 +1,7 @@ --- XR Lua Compiler --- The original X-Ray script environment, reimplemented as a loadstring wrapper -local compiler = require("xr/compiler") +local compiler = require("xr.compiler") -- `package` module override for X-Ray Lua scripts local XR_PACKAGE = setmetatable( diff --git a/gamedata/scripts/xr/processes/init.lua b/gamedata/scripts/xr/processes/init.lua index f3409fdb54..591a949c80 100644 --- a/gamedata/scripts/xr/processes/init.lua +++ b/gamedata/scripts/xr/processes/init.lua @@ -1,7 +1,7 @@ -- Engine interface to domain-scoped coroutines -- Formerly part of CScriptManager -local ScriptProcess = require("xr/processes/process") +local ScriptProcess = require("xr.processes.process") -- Script processes class local ScriptProcesses = {} diff --git a/src/xrServerEntities/script_processes.h b/src/xrServerEntities/script_processes.h index efb8e719fb..7f9b339004 100644 --- a/src/xrServerEntities/script_processes.h +++ b/src/xrServerEntities/script_processes.h @@ -11,7 +11,7 @@ class CScriptProcesses CScriptProcesses(lua_State* L) { lua_getglobal(L, "require"); - lua_pushstring(L, "xr/processes"); + lua_pushstring(L, "xr.processes"); lua_call(L, 1, 1); m_obj = luabind::object(L); From e48329d4c207e8271bea7bafb1cc7e4c5cacfd1d Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 13 Jun 2025 22:20:12 +0100 Subject: [PATCH 73/76] Improve `boot/loader` error aggregation --- gamedata/scripts/boot/loader.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gamedata/scripts/boot/loader.lua b/gamedata/scripts/boot/loader.lua index d1da228ec5..ac1ec148dc 100644 --- a/gamedata/scripts/boot/loader.lua +++ b/gamedata/scripts/boot/loader.lua @@ -80,10 +80,7 @@ function _LOADERS.fs(name) end else -- Otherwise, add to our error accumulator - if #errs > 0 then - errs = errs .. "\n\t" - end - errs = errs .. "No db entry: " .. path + errs = errs .. "\n\tNo db entry: " .. path end end end From 30f75e85ee98157494ea699329c153b0578bf75b Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Fri, 13 Jun 2025 22:21:52 +0100 Subject: [PATCH 74/76] Fix `_G` inheritance in `.lua` loaded from `.script`, add missing `xr/lua` print --- gamedata/scripts/amx/lua/init.lua | 5 ++- gamedata/scripts/init.lua | 12 ++++--- gamedata/scripts/xr/lua/init.lua | 55 +++++++++++++++++-------------- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/gamedata/scripts/amx/lua/init.lua b/gamedata/scripts/amx/lua/init.lua index 8c8ba24cab..dcf92eaa85 100644 --- a/gamedata/scripts/amx/lua/init.lua +++ b/gamedata/scripts/amx/lua/init.lua @@ -4,13 +4,12 @@ local xr_lua = require("xr.lua") local unlocalize = require(_PACKAGE .. ".unlocalize").unlocalize -local old_loadstring = xr_lua.loadstring function xr_lua.loadstring(src, namespace_name, script_name) if namespace_name then - print("* " .. _PACKAGE .. ": compiling " .. namespace_name) + print("* [" .. _PACKAGE .. "] compiling " .. namespace_name) end - return old_loadstring( + return xr_lua.compile( unlocalize(src, namespace_name), namespace_name, script_name diff --git a/gamedata/scripts/init.lua b/gamedata/scripts/init.lua index fe0bb3f058..68ac855e76 100644 --- a/gamedata/scripts/init.lua +++ b/gamedata/scripts/init.lua @@ -36,10 +36,14 @@ function print(...) end end ---- Replace loadstring with an error-checked version +--- Customizable environment for .lua files +--- Needed so .script files can propagate their extended _G when requiring .lua +_LUA_G = _G + +--- Emplace an error-checked lua compiler with customizable environment _LOADSTRING = loadstring function loadstring(src, namespace_name, script_name) - print("* lua: loading " .. namespace_name) + print("* [lua] loading " .. namespace_name) local f, err = _LOADSTRING(src, namespace_name) if not f then @@ -58,8 +62,8 @@ function loadstring(src, namespace_name, script_name) _FILE = script_name, }, { - __index = _G, - __newindex = _G, + __index = _LUA_G, + __newindex = _LUA_G, } ) ) diff --git a/gamedata/scripts/xr/lua/init.lua b/gamedata/scripts/xr/lua/init.lua index 1eb796b95e..8d5f58a7b0 100644 --- a/gamedata/scripts/xr/lua/init.lua +++ b/gamedata/scripts/xr/lua/init.lua @@ -3,42 +3,32 @@ local compiler = require("xr.compiler") +local XR_LOADERS = { + _LOADERS.pre, + _LOADERS.lib, + _LOADERS.bin, + _LOADERS.aio, +} + -- `package` module override for X-Ray Lua scripts local XR_PACKAGE = setmetatable( { -- Use unconfigured Lua path path = _DEFAULT_PATH, -- Use unconfigured Lua loaders - loaders = { - _LOADERS.pre, - _LOADERS.lib, - _LOADERS.bin, - _LOADERS.aio, - }, + loaders = XR_LOADERS, }, { __index = package, - __newindex = package, } ) --- Pass loadstring through to base _LOADSTRING for X-Ray Lua scripts --- Ensures any uses of debug.dump function as expected -local XR_LOADSTRING = function(src, name) - return setfenv( - _LOADSTRING(src, name), - env - ) -end - -- Global scope wrapper for X-Ray Lua scripts -- Indirects through `_G`, and `package.loaded` via `require` local XR_G = setmetatable( { -- Indirect package to our wrapper package = XR_PACKAGE, - -- Indirect loadstring to our wrapper - loadstring = XR_LOADSTRING, }, { -- Override key reads @@ -92,14 +82,17 @@ local function handle_error(msg, namespace_name) end -- `loadstring` replacement specialized to X-Ray scripts -local function loadstring(src, namespace_name, script_name) +local function compile(src, namespace_name, script_name) -- Construct our script's environment table - local env = {} + local env = { + _PACKAGE = namespace_name, + _FILE = script_name, + } -- Create a wrapper around lua's base loadstring that runs in our environment - local function loadstring(src, name) + local function base_loadstring(s, name) return setfenv( - _LOADSTRING(src, name), + _LOADSTRING(s, name), env ) end @@ -107,9 +100,9 @@ local function loadstring(src, namespace_name, script_name) -- Construct the metatable for our environment local mt = { __index = function(self, key) - -- Dynamically indirect to our loadstring wrapper when required + -- Dynamically indirect to our loadstring wrapper if key == "loadstring" then - return loadstring + return base_loadstring end -- Otherwise, indirect to XR_G @@ -150,6 +143,9 @@ local function loadstring(src, namespace_name, script_name) package.loaded[namespace_name] = env end + local lua_g_old = _LUA_G + _LUA_G = env + -- Call our script function with an appropriate error handler local _, out = xpcall( mac, @@ -159,6 +155,8 @@ local function loadstring(src, namespace_name, script_name) ) ) + _LUA_G = lua_g_old + -- If we have a namespace name... if namespace_name then -- Return the prepopulated package @@ -170,8 +168,17 @@ local function loadstring(src, namespace_name, script_name) end end +local function loadstring(src, namespace_name, script_name) + if namespace_name then + print("* [" .. _PACKAGE .. "] compiling " .. namespace_name) + end + + return compile(src, namespace_name, script_name) +end + -- Prepare module value local mod = { + compile = compile, loadstring = loadstring } From 7eaddb31b7f922058a7b0eb1c0d902de5ca3b6a7 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Wed, 18 Jun 2025 18:31:03 +0100 Subject: [PATCH 75/76] Update `gamedata` directory tree in VS solution --- src/engine-vs2022.sln | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/engine-vs2022.sln b/src/engine-vs2022.sln index 79fb401214..9682646e9f 100644 --- a/src/engine-vs2022.sln +++ b/src/engine-vs2022.sln @@ -110,8 +110,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{8EC4 ..\gamedata\scripts\class_registrator_modded_exes.script = ..\gamedata\scripts\class_registrator_modded_exes.script ..\gamedata\scripts\dxml_core.script = ..\gamedata\scripts\dxml_core.script ..\gamedata\scripts\fakelens.script = ..\gamedata\scripts\fakelens.script + ..\gamedata\scripts\imgui_helper.script = ..\gamedata\scripts\imgui_helper.script + ..\gamedata\scripts\init.lua = ..\gamedata\scripts\init.lua ..\gamedata\scripts\ltx_help_ex.script = ..\gamedata\scripts\ltx_help_ex.script ..\gamedata\scripts\lua_help_ex.script = ..\gamedata\scripts\lua_help_ex.script + ..\gamedata\scripts\lua_help_imgui.script = ..\gamedata\scripts\lua_help_imgui.script ..\gamedata\scripts\modxml_inject_keybinds.script = ..\gamedata\scripts\modxml_inject_keybinds.script ..\gamedata\scripts\modxml_test.script = ..\gamedata\scripts\modxml_test.script ..\gamedata\scripts\options_builder.script = ..\gamedata\scripts\options_builder.script @@ -251,6 +254,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imgui", "3rd party\imgui\im {A0F7D1FB-59A7-4717-A7E4-96F37E91998E} = {A0F7D1FB-59A7-4717-A7E4-96F37E91998E} EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "amx", "amx", "{04EC24DC-AB94-4F19-8056-23DE855052D7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "boot", "boot", "{2B4D82D1-8DFD-4CF4-A8B5-923ED00EFFC1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{7188B178-0BAC-4DB1-80EE-0B3C32775905}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "xr", "xr", "{277AEE51-4F38-46F9-BF6E-78F198D718B5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lua", "lua", "{EC96D3E8-1D33-4EAD-9D67-01A07903C3FC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lua", "lua", "{3CC5A577-05F4-4C38-946B-FB99F37CCA19}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "processes", "processes", "{96150BF0-7065-45D8-8ACB-47D2B6646849}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution DX10|x64 = DX10|x64 @@ -1053,6 +1070,13 @@ Global {44A08F7F-E393-4E0B-B9E6-94AF30774CE7} = {8537520E-5391-4DA0-A369-D7B22852C696} {91413BC1-731E-470B-AA8C-8C1F6290D8D7} = {44A08F7F-E393-4E0B-B9E6-94AF30774CE7} {D0843040-7706-4FBF-A931-582748BAFBB1} = {2BFC806B-CE92-4EA4-8FE8-5F2EA54BA348} + {04EC24DC-AB94-4F19-8056-23DE855052D7} = {8EC462FD-D22E-90A8-E5CE-7E832BA40C5D} + {2B4D82D1-8DFD-4CF4-A8B5-923ED00EFFC1} = {8EC462FD-D22E-90A8-E5CE-7E832BA40C5D} + {7188B178-0BAC-4DB1-80EE-0B3C32775905} = {8EC462FD-D22E-90A8-E5CE-7E832BA40C5D} + {277AEE51-4F38-46F9-BF6E-78F198D718B5} = {8EC462FD-D22E-90A8-E5CE-7E832BA40C5D} + {EC96D3E8-1D33-4EAD-9D67-01A07903C3FC} = {04EC24DC-AB94-4F19-8056-23DE855052D7} + {3CC5A577-05F4-4C38-946B-FB99F37CCA19} = {277AEE51-4F38-46F9-BF6E-78F198D718B5} + {96150BF0-7065-45D8-8ACB-47D2B6646849} = {277AEE51-4F38-46F9-BF6E-78F198D718B5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {76CF157A-A169-443B-AE3A-F17AD29325C6} From 677459fdd7dd3f3bd08ef6e7f32a6e04f4d58477 Mon Sep 17 00:00:00 2001 From: ProfLander <1253239+ProfLander@users.noreply.github.com.> Date: Sun, 22 Jun 2025 18:19:17 +0100 Subject: [PATCH 76/76] Reintegrate binary package loader --- gamedata/scripts/boot/loader.lua | 16 +++++++++++++++- gamedata/scripts/boot/paths.lua | 3 ++- gamedata/scripts/xr/lua/init.lua | 16 +++++++++++++--- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/gamedata/scripts/boot/loader.lua b/gamedata/scripts/boot/loader.lua index ac1ec148dc..58ffe33c24 100644 --- a/gamedata/scripts/boot/loader.lua +++ b/gamedata/scripts/boot/loader.lua @@ -92,8 +92,22 @@ function _LOADERS.fs(name) return errs end +function memoize(f) + local cache = {} + return function(v) + if cache[v] then + return cache[v] + end + + local out = f(v) + cache[v] = out + + return out + end +end + -- Replace the loader list with the preloader plus our FS loader -package.loaders = { _LOADERS.pre, _LOADERS.fs } +package.loaders = { _LOADERS.pre, _LOADERS.fs, memoize(_LOADERS.bin) } -- Define callback registrator local function register_on_load_callback(f) diff --git a/gamedata/scripts/boot/paths.lua b/gamedata/scripts/boot/paths.lua index d2e59b8a04..5c700ed4e4 100644 --- a/gamedata/scripts/boot/paths.lua +++ b/gamedata/scripts/boot/paths.lua @@ -4,8 +4,9 @@ _PACKAGE = "boot/paths" --- Cache default path for later +-- Cache default paths for later _DEFAULT_PATH = package.path +_DEFAULT_CPATH = package.cpath -- Define load path registrator function _REGISTER_PATHS(...) diff --git a/gamedata/scripts/xr/lua/init.lua b/gamedata/scripts/xr/lua/init.lua index 8d5f58a7b0..dd2f8bb852 100644 --- a/gamedata/scripts/xr/lua/init.lua +++ b/gamedata/scripts/xr/lua/init.lua @@ -13,8 +13,6 @@ local XR_LOADERS = { -- `package` module override for X-Ray Lua scripts local XR_PACKAGE = setmetatable( { - -- Use unconfigured Lua path - path = _DEFAULT_PATH, -- Use unconfigured Lua loaders loaders = XR_LOADERS, }, @@ -44,11 +42,23 @@ local XR_G = setmetatable( return gv end - -- Otherwise, try to auto-load the key as a script + -- Otherwise, try to auto-load via the global package.path local res, out = pcall(require, key) if res then return out end + + -- Otherwise, try to auto-load via xr/lua's local package.path + local package_path_old = package.path + local package_cpath_old = package.cpath + package.path = _DEFAULT_PATH + package.cpath = _DEFAULT_CPATH + res, out = pcall(require, key) + package.path = package_path_old + package.cpath = package_cpath_old + if res then + return out + end end, -- Send key writes straight to `_G` __newindex = _G