diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 8ccae64..b687427 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -118,6 +118,8 @@ namespace big static bool editing_gui_keybind = false; + static auto g_lua_file_watcher_last_time = std::chrono::high_resolution_clock::now(); + void gui::dx_on_tick() { std::scoped_lock l(big::g_lua_manager_mutex); @@ -125,12 +127,76 @@ namespace big { sol::state_view lua(*g_pointers->m_hades2.m_lua_state); - for (const auto& f : g_lua_imgui_callbacks) + const auto time_now = std::chrono::high_resolution_clock::now(); + if ((time_now - g_lua_file_watcher_last_time) > 500ms) + { + g_lua_file_watcher_last_time = time_now; + + const auto script_folder = g_file_manager.get_project_folder("plugins"); + for (const auto& entry : std::filesystem::recursive_directory_iterator(script_folder.get_path(), std::filesystem::directory_options::skip_permission_denied)) + { + if (!entry.exists() || entry.path().extension() != ".lua") + { + continue; + } + + bool should_load = true; + bool should_delete_existing_entry = false; + size_t i = 0; + for (const auto& existing_entry : g_lua_modules) + { + const auto is_already_loaded = existing_entry.m_file_entry.path() == entry.path(); + if (is_already_loaded) + { + const auto is_disk_newer = entry.last_write_time() > existing_entry.m_file_entry.last_write_time(); + if (is_disk_newer) + { + should_delete_existing_entry = true; + } + else + { + should_load = false; + } + + break; + } + i++; + } + if (should_delete_existing_entry) + { + g_lua_modules.erase(g_lua_modules.begin() + i); + } + + if (should_load) + { + g_lua_modules.push_back({.m_file_entry = entry, .m_imgui_callbacks = {}}); + g_lua_current_guid = entry; + auto result = lua.safe_script_file((char*)entry.path().u8string().c_str(), &sol::script_pass_on_error, sol::load_mode::text); + + if (!result.valid()) + { + LOG(FATAL) << (char*)entry.path().u8string().c_str() + << " failed to load: " << result.get().what(); + Logger::FlushQueue(); + + g_lua_modules.pop_back(); + } + } + } + } + + if (m_is_open) { - auto res = f(); - if (!res.valid()) + for (const auto& lua_module : g_lua_modules) { - LOG(FATAL) << "Failed executing imgui callback: "; + for (const auto& f : lua_module.m_imgui_callbacks) + { + auto res = f(); + if (!res.valid()) + { + LOG(FATAL) << "Failed executing imgui callback: "; + } + } } } } diff --git a/src/hooks/hooking.cpp b/src/hooks/hooking.cpp index 3d3ebd4..3fac93c 100644 --- a/src/hooks/hooking.cpp +++ b/src/hooks/hooking.cpp @@ -79,7 +79,7 @@ namespace big std::scoped_lock l(g_lua_manager_mutex); g_is_lua_state_valid = false; - g_lua_imgui_callbacks.clear(); + g_lua_modules.clear(); g_lua_state_view.reset(); LOG(FATAL) << "state is no longer valid!"; } @@ -108,7 +108,13 @@ namespace big g_table.create_named("gui").set_function("add_imgui", [](sol::protected_function cb) { - g_lua_imgui_callbacks.push_back(cb); + for (auto& lua_mod : g_lua_modules) + { + if (lua_mod.m_file_entry == g_lua_current_guid) + { + lua_mod.m_imgui_callbacks.push_back(cb); + } + } }); lua::imgui::bind(g_table); //lua::log::bind(g_table); @@ -121,12 +127,16 @@ namespace big continue; } + g_lua_modules.push_back({.m_file_entry = entry, .m_imgui_callbacks = {}}); + g_lua_current_guid = entry; auto result = g_lua_state_view->safe_script_file((char*)entry.path().u8string().c_str(), &sol::script_pass_on_error, sol::load_mode::text); if (!result.valid()) { LOG(FATAL) << (char*)entry.path().u8string().c_str() << " failed to load: " << result.get().what(); Logger::FlushQueue(); + + g_lua_modules.pop_back(); } } diff --git a/src/lua/lua_manager.hpp b/src/lua/lua_manager.hpp index ea51aa6..64ce563 100644 --- a/src/lua/lua_manager.hpp +++ b/src/lua/lua_manager.hpp @@ -79,7 +79,15 @@ namespace big }; inline std::recursive_mutex g_lua_manager_mutex; + + struct lua_module_info + { + std::filesystem::directory_entry m_file_entry; + std::vector m_imgui_callbacks; + }; + + inline std::filesystem::directory_entry g_lua_current_guid; inline bool g_is_lua_state_valid = false; - inline std::vector g_lua_imgui_callbacks; + inline std::vector g_lua_modules; inline lua_manager* g_lua_manager; } // namespace big