diff --git a/src/pc/lua/smlua.h b/src/pc/lua/smlua.h index ddaf22182..5b3eebd04 100644 --- a/src/pc/lua/smlua.h +++ b/src/pc/lua/smlua.h @@ -15,6 +15,7 @@ #include "smlua_functions_autogen.h" #include "smlua_hooks.h" #include "smlua_sync_table.h" +#include "smlua_mod_funcs.h" #include "pc/debuglog.h" #include "pc/djui/djui_console.h" diff --git a/src/pc/lua/smlua_functions.c b/src/pc/lua/smlua_functions.c index dadf70c51..d6eb3dff0 100644 --- a/src/pc/lua/smlua_functions.c +++ b/src/pc/lua/smlua_functions.c @@ -1,5 +1,6 @@ #include "smlua.h" #include "smlua_cobject.h" +#include "smlua_mod_funcs.h" #include @@ -21,6 +22,8 @@ #include "utils/smlua_collision_utils.h" #include "game/hardcoded.h" #include "include/macros.h" +#include "pc/mods/mods.h" +#include "pc/network/network.h" bool smlua_functions_valid_param_count(lua_State* L, int expected) { int top = lua_gettop(L); @@ -1071,4 +1074,10 @@ void smlua_bind_functions(void) { smlua_bind_function(L, "gfx_set_command", smlua_func_gfx_set_command); smlua_bind_function(L, "gfx_get_from_name", smlua_func_gfx_get_from_name); smlua_bind_function(L, "vtx_get_from_name", smlua_func_vtx_get_from_name); + + // Mod management functions + smlua_bind_function(L, "mods_enable", smlua_func_mods_enable); + smlua_bind_function(L, "mods_disable", smlua_func_mods_disable); + smlua_bind_function(L, "mods_get_list", smlua_func_mods_get_list); + smlua_bind_function(L, "network_reconnect", smlua_func_network_reconnect); } diff --git a/src/pc/lua/smlua_mod_funcs.c b/src/pc/lua/smlua_mod_funcs.c new file mode 100644 index 000000000..60187f421 --- /dev/null +++ b/src/pc/lua/smlua_mod_funcs.c @@ -0,0 +1,105 @@ +#include "smlua.h" +#include "smlua_cobject.h" +#include "pc/mods/mods.h" +#include "pc/network/network.h" + +// Mod management functions +int smlua_func_mods_enable(lua_State *L) { + LUA_STACK_CHECK_BEGIN_NUM(0); + + if (!smlua_functions_valid_param_count(L, 1)) { return 0; } + + const char* relativePath = smlua_to_string(L, 1); + if (relativePath == NULL || !gSmLuaConvertSuccess) { + LOG_LUA_LINE("mods_enable: invalid relativePath parameter"); + return 0; + } + + mods_enable((char*)relativePath); + + LUA_STACK_CHECK_END(); + return 0; +} + +int smlua_func_mods_disable(lua_State *L) { + LUA_STACK_CHECK_BEGIN_NUM(0); + + if (!smlua_functions_valid_param_count(L, 1)) { return 0; } + + const char* relativePath = smlua_to_string(L, 1); + if (relativePath == NULL || !gSmLuaConvertSuccess) { + LOG_LUA_LINE("mods_disable: invalid relativePath parameter"); + return 0; + } + + mods_disable((char*)relativePath); + + LUA_STACK_CHECK_END(); + return 0; +} + +// Function to list available mods +int smlua_func_mods_get_list(lua_State *L) { + LUA_STACK_CHECK_BEGIN_NUM(1); + + // Create table for mods list + lua_newtable(L); + int modTable = lua_gettop(L); + + // Iterate through all local mods + for (unsigned int i = 0; i < gLocalMods.entryCount; i++) { + struct Mod* mod = gLocalMods.entries[i]; + + // Push mod index as array index + lua_pushinteger(L, i + 1); + + // Create table for this mod's properties + lua_newtable(L); + + // Add mod properties + lua_pushstring(L, "name"); + lua_pushstring(L, mod->name ? mod->name : "Unknown"); + lua_settable(L, -3); + + lua_pushstring(L, "relativePath"); + lua_pushstring(L, mod->relativePath); + lua_settable(L, -3); + + lua_pushstring(L, "enabled"); + lua_pushboolean(L, mod->enabled); + lua_settable(L, -3); + + if (mod->category) { + lua_pushstring(L, "category"); + lua_pushstring(L, mod->category); + lua_settable(L, -3); + } + + if (mod->description) { + lua_pushstring(L, "description"); + lua_pushstring(L, mod->description); + lua_settable(L, -3); + } + + // Add mod table to mods list + lua_settable(L, modTable); + } + + LUA_STACK_CHECK_END(); + return 1; // Return the table +} + +// Global flag to indicate that reconnection was requested by Lua +bool gReconnectRequested = false; + +int smlua_func_network_reconnect(lua_State *L) { + LUA_STACK_CHECK_BEGIN_NUM(0); + + if (!smlua_functions_valid_param_count(L, 0)) { return 0; } + + // Set flag instead of calling directly + gReconnectRequested = true; + + LUA_STACK_CHECK_END(); + return 0; +} diff --git a/src/pc/lua/smlua_mod_funcs.h b/src/pc/lua/smlua_mod_funcs.h new file mode 100644 index 000000000..16572c158 --- /dev/null +++ b/src/pc/lua/smlua_mod_funcs.h @@ -0,0 +1,16 @@ +#ifndef SMLUA_MOD_FUNCS_H +#define SMLUA_MOD_FUNCS_H + +#include +#include + +// Mod management functions +int smlua_func_mods_enable(lua_State *L); +int smlua_func_mods_disable(lua_State *L); +int smlua_func_mods_get_list(lua_State *L); +int smlua_func_network_reconnect(lua_State *L); + +// Global flag to indicate that reconnection was requested by Lua +extern bool gReconnectRequested; + +#endif diff --git a/src/pc/mods/mods.c b/src/pc/mods/mods.c index 9af7ab2b3..7cd4f2eb2 100644 --- a/src/pc/mods/mods.c +++ b/src/pc/mods/mods.c @@ -316,6 +316,18 @@ void mods_enable(char* relativePath) { } } +void mods_disable(char* relativePath) { + if (!relativePath) { return; } + + for (unsigned int i = 0; i < gLocalMods.entryCount; i++) { + struct Mod* mod = gLocalMods.entries[i]; + if (!strcmp(relativePath, mod->relativePath)) { + mod->enabled = false; + break; + } + } +} + void mods_init(void) { // load mod cache diff --git a/src/pc/mods/mods.h b/src/pc/mods/mods.h index 4f4a7de4a..61fb9ae0f 100644 --- a/src/pc/mods/mods.h +++ b/src/pc/mods/mods.h @@ -32,6 +32,7 @@ void mods_clear(struct Mods* mods); void mods_delete_folder(char* path); void mods_refresh_local(void); void mods_enable(char* relativePath); +void mods_disable(char* relativePath); void mods_init(void); void mods_shutdown(void); diff --git a/src/pc/network/network.c b/src/pc/network/network.c index d267d7cb8..bad063cf5 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -11,6 +11,7 @@ #include "pc/djui/djui_panel.h" #include "pc/djui/djui_hud_utils.h" #include "pc/djui/djui_panel_main.h" +#include "pc/djui/djui_panel_modlist.h" #include "pc/utils/misc.h" #include "pc/lua/smlua.h" #include "pc/lua/utils/smlua_model_utils.h" @@ -562,6 +563,17 @@ void network_update(void) { gNetworkStartupTimer--; } + // Handle Lua reconnection requests + if (gReconnectRequested) { + gReconnectRequested = false; + if (gNetworkType == NT_SERVER) { + mods_activate(&gLocalMods); + + network_rehost_begin(); + LOG_INFO("Sent reconnect signals to all clients"); + } + } + network_rehost_update(); network_reconnect_update(); diff --git a/src/pc/network/network.h b/src/pc/network/network.h index 1ba8e6320..8dcb6a10a 100644 --- a/src/pc/network/network.h +++ b/src/pc/network/network.h @@ -99,6 +99,7 @@ struct NametagsSettings { extern struct NetworkSystem* gNetworkSystem; extern enum NetworkType gNetworkType; extern bool gNetworkAreaLoaded; +extern bool gReconnectRequested; extern bool gNetworkAreaSyncing; extern u32 gNetworkAreaTimer; extern u32 gNetworkAreaTimerClock;