Eluna tweak load order. You can now freely use require() on any script. all lua files are loaded alphabetically (path is taken into account) and the extensions folder is loaded first always

This commit is contained in:
Rochet2
2014-07-02 00:44:54 +03:00
parent 6b01113a70
commit 637ee5fff9
3 changed files with 76 additions and 26 deletions

View File

@@ -10,7 +10,9 @@
#include "LuaEngine.h" #include "LuaEngine.h"
#include "Includes.h" #include "Includes.h"
Eluna::ScriptPaths Eluna::scripts; Eluna::ScriptList Eluna::lua_scripts;
Eluna::ScriptList Eluna::lua_extensions;
std::string Eluna::lua_folderpath;
Eluna* Eluna::GEluna = NULL; Eluna* Eluna::GEluna = NULL;
bool Eluna::reload = false; bool Eluna::reload = false;
@@ -20,19 +22,20 @@ void Eluna::Initialize()
{ {
uint32 oldMSTime = GetCurrTime(); uint32 oldMSTime = GetCurrTime();
scripts.clear(); lua_scripts.clear();
lua_extensions.clear();
std::string folderpath = eConfigMgr->GetStringDefault("Eluna.ScriptPath", "lua_scripts"); lua_folderpath = eConfigMgr->GetStringDefault("Eluna.ScriptPath", "lua_scripts");
#if PLATFORM == PLATFORM_UNIX || PLATFORM == PLATFORM_APPLE #if PLATFORM == PLATFORM_UNIX || PLATFORM == PLATFORM_APPLE
if (folderpath[0] == '~') if (folderpath[0] == '~')
if (const char* home = getenv("HOME")) if (const char* home = getenv("HOME"))
folderpath.replace(0, 1, home); folderpath.replace(0, 1, home);
#endif #endif
ELUNA_LOG_INFO("[Eluna]: Searching scripts from `%s`", folderpath.c_str()); ELUNA_LOG_INFO("[Eluna]: Searching scripts from `%s`", lua_folderpath.c_str());
GetScripts(folderpath, scripts); GetScripts(lua_folderpath + "/extensions", lua_extensions);
GetScripts(folderpath + "/extensions", scripts); GetScripts(lua_folderpath, lua_scripts);
ELUNA_LOG_INFO("[Eluna]: Loaded %u scripts in %u ms", uint32(scripts.size()), GetTimeDiff(oldMSTime)); ELUNA_LOG_DEBUG("[Eluna]: Loaded %u scripts in %u ms", uint32(lua_scripts.size()), GetTimeDiff(oldMSTime));
// Create global eluna // Create global eluna
new Eluna(); new Eluna();
@@ -41,7 +44,8 @@ void Eluna::Initialize()
void Eluna::Uninitialize() void Eluna::Uninitialize()
{ {
delete GEluna; delete GEluna;
scripts.clear(); lua_scripts.clear();
lua_extensions.clear();
} }
void Eluna::ReloadEluna() void Eluna::ReloadEluna()
@@ -102,7 +106,7 @@ playerGossipBindings(new EntryBind<HookMgr::GossipEvents>("GossipEvents (player)
Eluna::GEluna = this; Eluna::GEluna = this;
// run scripts // run scripts
RunScripts(scripts); RunScripts();
} }
Eluna::~Eluna() Eluna::~Eluna()
@@ -134,7 +138,7 @@ Eluna::~Eluna()
} }
// Finds lua script files from given path (including subdirectories) and pushes them to scripts // Finds lua script files from given path (including subdirectories) and pushes them to scripts
void Eluna::GetScripts(std::string path, ScriptPaths& scripts) void Eluna::GetScripts(std::string path, ScriptList& scripts)
{ {
ELUNA_LOG_DEBUG("[Eluna]: GetScripts from path `%s`", path.c_str()); ELUNA_LOG_DEBUG("[Eluna]: GetScripts from path `%s`", path.c_str());
@@ -168,34 +172,71 @@ void Eluna::GetScripts(std::string path, ScriptPaths& scripts)
// was file, check extension // was file, check extension
ELUNA_LOG_DEBUG("[Eluna]: GetScripts Checking file `%s`", fullpath.c_str()); ELUNA_LOG_DEBUG("[Eluna]: GetScripts Checking file `%s`", fullpath.c_str());
std::string ext = fullpath.substr(fullpath.length() - 4, 4);
// split file name
std::string filename = directory->d_name;
uint32 extDot = filename.find_last_of('.');
if (extDot == std::string::npos)
continue;
std::string ext = filename.substr(extDot);
filename = filename.substr(0, extDot);
// check extension and add path to scripts to load
if (ext != ".lua" && ext != ".dll") if (ext != ".lua" && ext != ".dll")
continue; continue;
// was correct, add path to scripts to load LuaScript script;
script.fileext = ext;
script.filename = filename;
script.filepath = fullpath;
script.modulepath = fullpath.substr(0, fullpath.length() - ext.length());
scripts.push_back(script);
ELUNA_LOG_DEBUG("[Eluna]: GetScripts add path `%s`", fullpath.c_str()); ELUNA_LOG_DEBUG("[Eluna]: GetScripts add path `%s`", fullpath.c_str());
scripts.erase(fullpath);
scripts.insert(fullpath);
} }
} }
void Eluna::RunScripts(ScriptPaths& scripts) void Eluna::RunScripts()
{ {
uint32 oldMSTime = GetCurrTime();
uint32 count = 0; uint32 count = 0;
// load last first to load extensions first
for (ScriptPaths::const_reverse_iterator it = scripts.rbegin(); it != scripts.rend(); ++it) ScriptList scripts;
scripts.insert(scripts.end(), lua_extensions.begin(), lua_extensions.end());
scripts.insert(scripts.end(), lua_scripts.begin(), lua_scripts.end());
lua_getglobal(L, "package");
luaL_getsubtable(L, -1, "loaded");
int modules = lua_gettop(L);
for (ScriptList::const_iterator it = scripts.begin(); it != scripts.end(); ++it)
{ {
if (!luaL_loadfile(L, it->c_str()) && !lua_pcall(L, 0, 0, 0)) lua_getfield(L, modules, it->modulepath.c_str());
if (!lua_isnoneornil(L, -1))
{ {
lua_pop(L, 1);
ELUNA_LOG_DEBUG("[Eluna]: Extension was already loaded or required `%s`", it->filepath.c_str());
continue;
}
lua_pop(L, 1);
if (!luaL_loadfile(L, it->filepath.c_str()) && !lua_pcall(L, 0, 1, 0))
{
if (!lua_toboolean(L, -1))
{
lua_pop(L, 1);
Push(L, true);
}
lua_setfield(L, modules, it->modulepath.c_str());
// successfully loaded and ran file // successfully loaded and ran file
ELUNA_LOG_DEBUG("[Eluna]: Successfully loaded `%s`", it->c_str()); ELUNA_LOG_DEBUG("[Eluna]: Successfully loaded `%s`", it->filepath.c_str());
++count; ++count;
continue; continue;
} }
ELUNA_LOG_ERROR("[Eluna]: Error loading file `%s`", it->c_str()); ELUNA_LOG_ERROR("[Eluna]: Error loading extension `%s`", it->filepath.c_str());
report(L); report(L);
} }
ELUNA_LOG_DEBUG("[Eluna]: Loaded %u Lua scripts", count); lua_pop(L, 2);
ELUNA_LOG_INFO("[Eluna]: Executed %u Lua scripts in %u ms", count, GetTimeDiff(oldMSTime));
} }
void Eluna::RemoveRef(const void* obj) void Eluna::RemoveRef(const void* obj)

View File

@@ -350,7 +350,14 @@ private:
Eluna& operator=(const Eluna&); Eluna& operator=(const Eluna&);
public: public:
typedef std::set<std::string> ScriptPaths; struct LuaScript
{
std::string fileext;
std::string filename;
std::string filepath;
std::string modulepath;
};
typedef std::list<LuaScript> ScriptList;
static Eluna* GEluna; static Eluna* GEluna;
static bool reload; static bool reload;
@@ -378,18 +385,20 @@ public:
Eluna(); Eluna();
~Eluna(); ~Eluna();
static ScriptPaths scripts; static ScriptList lua_scripts;
static ScriptList lua_extensions;
static std::string lua_folderpath;
static void Initialize(); static void Initialize();
static void Uninitialize(); static void Uninitialize();
// Use Eluna::reload = true; instead. // Use Eluna::reload = true; instead.
// This will be called on next update // This will be called on next update
static void ReloadEluna(); static void ReloadEluna();
void static GetScripts(std::string path, ScriptPaths& scripts); static void GetScripts(std::string path, ScriptList& scripts);
static void report(lua_State*); static void report(lua_State*);
static void ExecuteCall(lua_State* L, int params, int res); static void ExecuteCall(lua_State* L, int params, int res);
void Register(uint8 reg, uint32 id, uint32 evt, int func); void Register(uint8 reg, uint32 id, uint32 evt, int func);
void RunScripts(ScriptPaths& scripts); void RunScripts();
static void RemoveRef(const void* obj); static void RemoveRef(const void* obj);
// Pushes // Pushes

View File

@@ -5,6 +5,6 @@
-- --
-- Set correct require paths -- Set correct require paths
package.path = package.path.."lua_scripts\\?;lua_scripts\\?.dll;lua_scripts\\?.lua;lua_scripts\\extensions\\?;lua_scripts\\extensions\\?.dll;lua_scripts\\extensions\\?.lua" package.path = package.path.."lua_scripts\\?;lua_scripts\\?.dll;lua_scripts\\?.lua"
-- Randomize random -- Randomize random
math.randomseed(tonumber(tostring(os.time()):reverse():sub(1,6))) math.randomseed(tonumber(tostring(os.time()):reverse():sub(1,6)))