Skip to content

Commit

Permalink
Merge branch 'master' into stacktrace-improve
Browse files Browse the repository at this point in the history
  • Loading branch information
Rochet2 authored Apr 7, 2024
2 parents f3eef31 + 11f42ba commit 7b63103
Showing 1 changed file with 49 additions and 41 deletions.
90 changes: 49 additions & 41 deletions LuaEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,27 @@ void Eluna::CloseLua()
continentDataRefs.clear();
}

static int PrecompiledLoader(lua_State* L)
{
const char* modname = lua_tostring(L, 1);
if (modname == NULL)
return 0;
auto it = std::find_if(sElunaLoader->combined_scripts.begin(), sElunaLoader->combined_scripts.end(), [modname](const LuaScript& script) { return script.filename == modname; });
if (it == sElunaLoader->combined_scripts.end()) {
lua_pushfstring(L, "\n\tno precompiled script '%s' found", modname);
return 1;
}
if (luaL_loadbuffer(L, reinterpret_cast<const char*>(&it->bytecode[0]), it->bytecode.size(), it->filename.c_str()))
{
// Stack: modname, errmsg
return lua_error(L);
}
// Stack: modname, filefunction
lua_pushstring(L, it->filepath.c_str());
// Stack: modname, filefunction, modpath
return 2;
}

void Eluna::OpenLua()
{
L = luaL_newstate();
Expand All @@ -126,7 +147,22 @@ void Eluna::OpenLua()
lua_setfield(L, -2, "path");
lua_pushstring(L, sElunaLoader->lua_requirecpath.c_str());
lua_setfield(L, -2, "cpath");
lua_pop(L, 1);
// 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");
}
// insert the new loader to the loaders table by shifting other elements down by one
const int newLoaderIndex = 2;
for (int i = lua_rawlen(L, -1); i >= newLoaderIndex; --i) {
lua_rawgeti(L, -1, i);
lua_rawseti(L, -2, i + 1);
}
lua_pushcfunction(L, &PrecompiledLoader);
lua_rawseti(L, -2, newLoaderIndex);
lua_pop(L, 2); // pop loaders/searchers table, pop package table

// Leave StackTrace function on stack and save reference to it
lua_pushcfunction(L, &StackTrace);
Expand Down Expand Up @@ -215,11 +251,8 @@ void Eluna::RunScripts()

std::unordered_map<std::string, std::string> loaded; // filename, path

lua_getglobal(L, "package");
// Stack: package
luaL_getsubtable(L, -1, "loaded");
// Stack: package, modules
int modules = lua_gettop(L);
lua_getglobal(L, "require");
// Stack: require

for (auto it = sElunaLoader->combined_scripts.begin(); it != sElunaLoader->combined_scripts.end(); ++it)
{
Expand All @@ -242,47 +275,22 @@ void Eluna::RunScripts()
}
loaded[it->filename] = it->filepath;

lua_getfield(L, modules, it->filename.c_str());
// Stack: package, modules, module
if (!lua_isnoneornil(L, -1))
{
lua_pop(L, 1);
ELUNA_LOG_DEBUG("[Eluna]: `%s` was already loaded or required", it->filepath.c_str());
continue;
}
lua_pop(L, 1);
// Stack: package, modules

if (luaL_loadbuffer(L, reinterpret_cast<const char*>(&it->bytecode[0]), it->bytecode.size(), it->filename.c_str()))
{
// Stack: package, modules, errmsg
ELUNA_LOG_ERROR("[Eluna]: Error loading `%s`", it->filepath.c_str());
Report(L);
// Stack: package, modules
continue;
}
// Stack: package, modules, filefunc

if (ExecuteCall(0, 1))
// We call require on the filename to load the script
// A custom loader is used to load the script from the combined_scripts table
// The loader is set up in Eluna::OpenLua
lua_pushvalue(L, -1); // Stack: require, require
lua_pushstring(L, it->filename.c_str()); // Stack: require, require, filename
if (ExecuteCall(1, 0))
{
// Stack: package, modules, result
if (lua_isnoneornil(L, -1) || (lua_isboolean(L, -1) && !lua_toboolean(L, -1)))
{
// if result evaluates to false, change it to true
lua_pop(L, 1);
Push(true);
}
lua_setfield(L, modules, it->filename.c_str());
// Stack: package, modules

// successfully loaded and ran file
// Successfully called require on the script
ELUNA_LOG_DEBUG("[Eluna]: Successfully loaded `%s`", it->filepath.c_str());
++count;
continue;
}
// Stack: require
}
// Stack: package, modules
lua_pop(L, 2);
// Stack: require
lua_pop(L, 1);
ELUNA_LOG_INFO("[Eluna]: Executed %u Lua scripts in %u ms for map: %i, instance: %u", count, ElunaUtil::GetTimeDiff(oldMSTime), boundMapId, boundInstanceId);

OnLuaStateOpen();
Expand Down

0 comments on commit 7b63103

Please sign in to comment.