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