From f987a52003707f5bb921ec4afcb5055e8ecb240f Mon Sep 17 00:00:00 2001 From: iThorgrim <125808072+iThorgrim@users.noreply.github.com> Date: Sat, 25 Jan 2025 15:46:17 +0100 Subject: [PATCH] feat: support for external lib and moonscript (#229) Co-authored-by: 55Honey <71938210+55Honey@users.noreply.github.com> --- conf/mod_eluna.conf.dist | 15 +++++++++ src/LuaEngine/LuaEngine.cpp | 67 +++++++++++++++++++++++++++++++------ src/LuaEngine/LuaEngine.h | 4 +++ 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/conf/mod_eluna.conf.dist b/conf/mod_eluna.conf.dist index cc2c864..40a771b 100644 --- a/conf/mod_eluna.conf.dist +++ b/conf/mod_eluna.conf.dist @@ -24,11 +24,26 @@ # Default: false - (disabled) # true - (enabled) # +# Eluna.RequirePaths +# Description: Sets the location of additional require paths. +# These paths are absolute and follows the standard Lua require path patterns. +# Below are a set of "standard" paths used by most package managers. +# "/usr/share/%s/?.lua;/usr/local/share/lua/%s/?.lua;/usr/local/share/lua/%s/?/init.lua;/usr/share/lua/%s/?.lua;/usr/share/lua/%s/?/init.lua;" +# Default: "" +# +# Eluna.RequireCPaths +# Description: Sets the location of additional require C paths. +# These paths are absolute and follows the standard Lua require path patterns. +# Below are a set of "standard" paths used by most package managers. +# "/usr/local/lib/lua/%s/?.so;/usr/lib/x86_64-linux-gnu/lua/%s/?.so;/usr/local/lib/lua/%s/loadall.so;" +# Default: "" Eluna.Enabled = true Eluna.TraceBack = false Eluna.ScriptPath = "lua_scripts" Eluna.PlayerAnnounceReload = false +Eluna.RequirePaths = "" +Eluna.RequirecPaths = "" ################################################################################################### diff --git a/src/LuaEngine/LuaEngine.cpp b/src/LuaEngine/LuaEngine.cpp index 96f7650..f7baa2f 100644 --- a/src/LuaEngine/LuaEngine.cpp +++ b/src/LuaEngine/LuaEngine.cpp @@ -40,6 +40,7 @@ Eluna::ScriptList Eluna::lua_scripts; Eluna::ScriptList Eluna::lua_extensions; std::string Eluna::lua_folderpath; std::string Eluna::lua_requirepath; +std::string Eluna::lua_requirecpath; Eluna* Eluna::GEluna = NULL; bool Eluna::reload = false; bool Eluna::initialized = false; @@ -88,6 +89,8 @@ void Eluna::LoadScriptPaths() lua_extensions.clear(); lua_folderpath = eConfigMgr->GetOption("Eluna.ScriptPath", "lua_scripts"); + const std::string& lua_path_extra = eConfigMgr->GetOption("Eluna.RequirePaths", ""); + const std::string& lua_cpath_extra = eConfigMgr->GetOption("Eluna.RequireCPaths", ""); #ifndef ELUNA_WINDOWS if (lua_folderpath[0] == '~') @@ -95,12 +98,27 @@ void Eluna::LoadScriptPaths() lua_folderpath.replace(0, 1, home); #endif ELUNA_LOG_INFO("[Eluna]: Searching scripts from `{}`", lua_folderpath); + + // clear all cache variables lua_requirepath.clear(); + lua_requirecpath.clear(); + GetScripts(lua_folderpath); + + // append our custom require paths and cpaths if the config variables are not empty + if (!lua_path_extra.empty()) + lua_requirepath += lua_path_extra; + + if (!lua_cpath_extra.empty()) + lua_requirecpath += lua_cpath_extra; + // Erase last ; if (!lua_requirepath.empty()) lua_requirepath.erase(lua_requirepath.end() - 1); + if (!lua_requirecpath.empty()) + lua_requirecpath.erase(lua_requirecpath.end() - 1); + ELUNA_LOG_DEBUG("[Eluna]: Loaded {} scripts in {} ms", lua_scripts.size() + lua_extensions.size(), ElunaUtil::GetTimeDiff(oldMSTime)); } @@ -226,10 +244,19 @@ void Eluna::OpenLua() // Set lua require folder paths (scripts folder structure) lua_getglobal(L, "package"); - lua_pushstring(L, lua_requirepath.c_str()); + lua_pushstring(L, GetRequirePath().c_str()); lua_setfield(L, -2, "path"); - lua_pushstring(L, ""); // erase cpath + lua_pushstring(L, GetRequireCPath().c_str()); lua_setfield(L, -2, "cpath"); + + // Set package.loaders loader for precompiled scripts + lua_getfield(L, -1, "loaders"); + if (lua_isnil(L, -1)) { + // Lua 5.2+ uses searchers instead of loaders + lua_pop(L, 1); + lua_getfield(L, -1, "searchers"); + } + lua_pop(L, 1); } @@ -316,7 +343,7 @@ void Eluna::AddScriptPath(std::string filename, const std::string& fullpath) filename = filename.substr(0, extDot); // check extension and add path to scripts to load - if (ext != ".lua" && ext != ".dll" && ext != ".so" && ext != ".ext") + if (ext != ".lua" && ext != ".dll" && ext != ".so" && ext != ".ext" && ext !=".moon") return; bool extension = ext == ".ext"; @@ -344,7 +371,10 @@ void Eluna::GetScripts(std::string path) { lua_requirepath += path + "/?.lua;" + - path + "/?.ext;" + + path + "/?.moon" + + path + "/?.ext;"; + + lua_requirecpath += path + "/?.dll;" + path + "/?.so;"; @@ -428,16 +458,31 @@ void Eluna::RunScripts() lua_pop(L, 1); // Stack: package, modules - if (luaL_loadfile(L, it->filepath.c_str())) + if (it->fileext == ".moon") { - // Stack: package, modules, errmsg - ELUNA_LOG_ERROR("[Eluna]: Error loading `{}`", it->filepath); - Report(L); - // Stack: package, modules - continue; + std::string str = "return require('moonscript').loadfile([[" + it->filepath + "]])"; + if (luaL_loadstring(L, str.c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) + { + // Stack: package, modules, errmsg + ELUNA_LOG_ERROR("[Eluna]: Error loading MoonScript `{}`", it->filepath); + Report(L); + // Stack: package, modules + continue; + } + } + else + { + if (luaL_loadfile(L, it->filepath.c_str())) + { + // Stack: package, modules, errmsg + ELUNA_LOG_ERROR("[Eluna]: Error loading `{}`", it->filepath); + Report(L); + // Stack: package, modules + continue; + } } - // Stack: package, modules, filefunc + // Stack: package, modules, filefunc if (ExecuteCall(0, 1)) { // Stack: package, modules, result diff --git a/src/LuaEngine/LuaEngine.h b/src/LuaEngine/LuaEngine.h index f8a9bf7..11aad10 100644 --- a/src/LuaEngine/LuaEngine.h +++ b/src/LuaEngine/LuaEngine.h @@ -92,6 +92,9 @@ public: typedef std::recursive_mutex LockType; typedef std::lock_guard Guard; + const std::string& GetRequirePath() const { return lua_requirepath; } + const std::string& GetRequireCPath() const { return lua_requirecpath; } + private: static bool reload; static bool initialized; @@ -105,6 +108,7 @@ private: static std::string lua_folderpath; // lua path variable for require() function static std::string lua_requirepath; + static std::string lua_requirecpath; // A counter for lua event stacks that occur (see event_level). // This is used to determine whether an object belongs to the current call stack or not.