From bff72db960f9688cacc81bf9583bf260c83391e3 Mon Sep 17 00:00:00 2001 From: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com> Date: Tue, 22 Apr 2025 09:47:26 +1000 Subject: [PATCH] add a more accurate way to know the last active mod --- src/pc/lua/smlua_cobject.c | 5 +- src/pc/lua/smlua_utils.c | 74 +++++++++++++++++----- src/pc/lua/smlua_utils.h | 1 + src/pc/lua/utils/smlua_misc_utils.c | 2 +- src/pc/mods/mod_storage.cpp | 4 +- src/pc/network/packets/packet_lua_custom.c | 5 +- 6 files changed, 70 insertions(+), 21 deletions(-) diff --git a/src/pc/lua/smlua_cobject.c b/src/pc/lua/smlua_cobject.c index 558b17cfb..b51e29d06 100644 --- a/src/pc/lua/smlua_cobject.c +++ b/src/pc/lua/smlua_cobject.c @@ -304,14 +304,15 @@ struct LuaObjectField* smlua_get_custom_field(lua_State* L, u32 lot, int keyInde static struct LuaObjectField lof = { 0 }; if (lot != LOT_OBJECT) { return NULL; } - if (gLuaActiveMod == NULL) { + struct Mod *mod = smlua_get_last_active_mod(L); + if (mod == NULL) { LOG_LUA_LINE("Failed to retrieve active mod entry."); return NULL; } // get _custom_object_fields lua_getglobal(L, "_G"); // get global table - lua_getfield(L, LUA_REGISTRYINDEX, gLuaActiveMod->relativePath); // push file's "global" table + lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath); // push file's "global" table int fileGlobalIndex = lua_gettop(L); lua_getfield(L, fileGlobalIndex, "_custom_object_fields"); lua_remove(L, -2); // remove file's "global" table diff --git a/src/pc/lua/smlua_utils.c b/src/pc/lua/smlua_utils.c index 98c024380..666f61ad2 100644 --- a/src/pc/lua/smlua_utils.c +++ b/src/pc/lua/smlua_utils.c @@ -739,27 +739,71 @@ void smlua_dump_table(int index) { printf("--------------\n"); } +// Get the folder and file +// in the format: "folder/file.lua" +static const char *smlua_lua_path_to_relative(const char *src) { + int slashCount = 0; + for (const char* p = src + strlen(src); p > src; --p) { + if (*p == '/' || *p == '\\') { + if (++slashCount == 2) { + return p + 1; + } + } + } + return src; +} + +// Get the folder from the path +static const char *smlua_lua_path_to_folder(const char *src) { + static char convertedBuffer[SYS_MAX_PATH]; + memcpy(convertedBuffer, src, strlen(src)); // Assumes the sub string will be smaller + int slashCount = 0; + char *lastSlash = convertedBuffer; + for (char* p = convertedBuffer + strlen(convertedBuffer); p > convertedBuffer; --p) { + if (*p == '/' || *p == '\\') { + if (++slashCount == 2) { + *lastSlash = '\0'; // Insert a null terminator + return p + 1; + } + lastSlash = p; + } + } + return src; +} + +// Get the last run mod via stack trace +// not the most efficient way, but its the most accurate +// try to call as little as possible, and use gLuaActiveMod +struct Mod *smlua_get_last_active_mod() { + lua_State* L = gLuaState; + lua_Debug info; + for (int level = 0; lua_getstack(L, level, &info); level++) { + if (!lua_getinfo(L, "S", &info)) { break; } + if (strcmp(info.what, "C") == 0) { continue; } // Skip C functions + + // We found the first instance of Lua code + // compare the folder to all active mods + const char *modFolder = smlua_lua_path_to_folder(info.source); + for (u16 i = 0; i < gLocalMods.entryCount; i++) { + struct Mod *mod = gLocalMods.entries[i]; + if (!mod->enabled) { continue; } + if (strcmp(mod->relativePath, modFolder) == 0) { + gLuaActiveMod = mod; + return mod; + } + } + break; + } + return NULL; +} + void smlua_logline(void) { lua_State* L = gLuaState; lua_Debug info; int level = 0; while (lua_getstack(L, level, &info)) { lua_getinfo(L, "nSl", &info); - - // Get the folder and file - // in the format: "folder/file.lua" - const char* src = info.source; - int slashCount = 0; - const char* folderStart = NULL; - for (const char* p = src + strlen(src); p > src; --p) { - if (*p == '/' || *p == '\\') { - if (++slashCount == 2) { - folderStart = p + 1; - break; - } - } - } - + const char* folderStart = smlua_lua_path_to_relative(info.source); LOG_LUA(" [%d] '%s':%d -- %s [%s]", level, (folderStart ? folderStart : info.short_src), info.currentline, (info.name ? info.name : ""), info.what); diff --git a/src/pc/lua/smlua_utils.h b/src/pc/lua/smlua_utils.h index 09b60797f..3886e3fe1 100644 --- a/src/pc/lua/smlua_utils.h +++ b/src/pc/lua/smlua_utils.h @@ -50,6 +50,7 @@ s64 smlua_get_any_integer_mod_variable(const char* variable); LuaFunction smlua_get_function_mod_variable(u16 modIndex, const char *variable); LuaFunction smlua_get_any_function_mod_variable(const char *variable); +struct Mod *smlua_get_last_active_mod(); void smlua_logline(void); void smlua_dump_stack(void); void smlua_dump_globals(void); diff --git a/src/pc/lua/utils/smlua_misc_utils.c b/src/pc/lua/utils/smlua_misc_utils.c index d100b2d05..459a0dada 100644 --- a/src/pc/lua/utils/smlua_misc_utils.c +++ b/src/pc/lua/utils/smlua_misc_utils.c @@ -515,7 +515,7 @@ bool mod_file_exists(const char* filename) { } struct Mod* get_active_mod(void) { - return gLuaActiveMod; + return smlua_get_last_active_mod(); } /// diff --git a/src/pc/mods/mod_storage.cpp b/src/pc/mods/mod_storage.cpp index f75686df3..ec20c5aa4 100644 --- a/src/pc/mods/mod_storage.cpp +++ b/src/pc/mods/mod_storage.cpp @@ -58,8 +58,10 @@ bool char_valid(const char* buffer, bool isKey) { } void mod_storage_get_filename(char* dest) { + struct Mod *mod = smlua_get_last_active_mod(); + if (mod == NULL) { return; } const char* path = fs_get_write_path(SAVE_DIRECTORY); // get user path - snprintf(dest, SYS_MAX_PATH - 1, "%s/%s", path, gLuaActiveMod->relativePath); // append sav folder + snprintf(dest, SYS_MAX_PATH - 1, "%s/%s", path, mod->relativePath); // append sav folder strdelete(dest, ".lua"); // delete ".lua" from sav name strcat(dest, SAVE_EXTENSION); // append SAVE_EXTENSION normalize_path(dest); // fix any out of place slashes diff --git a/src/pc/network/packets/packet_lua_custom.c b/src/pc/network/packets/packet_lua_custom.c index ef392d872..7563b6ed8 100644 --- a/src/pc/network/packets/packet_lua_custom.c +++ b/src/pc/network/packets/packet_lua_custom.c @@ -17,11 +17,12 @@ void network_send_lua_custom(bool broadcast) { } // figure out mod index - if (gLuaActiveMod == NULL) { + struct Mod *activeMod = smlua_get_last_active_mod(); + if (activeMod == NULL) { LOG_LUA_LINE("Could not figure out the current active mod!"); return; } - u16 modIndex = gLuaActiveMod->index; + u16 modIndex = activeMod->index; // get local index s32 toLocalIndex = 0;