diff --git a/src/core/settings.hpp b/src/core/settings.hpp index 9c535ee6..bdc08797 100644 --- a/src/core/settings.hpp +++ b/src/core/settings.hpp @@ -891,7 +891,14 @@ namespace big NLOHMANN_DEFINE_TYPE_INTRUSIVE(stat_editor, stat, packed_stat) } stat_editor{}; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(menu_settings, debug, tunables, notifications, player, player_db, protections, self, session, settings, spawn_vehicle, clone_pv, spoofing, vehicle, weapons, window, context_menu, esp, session_browser, ugc, reactions, world, stat_editor) + struct lua + { + bool enable_auto_reload_changed_scripts = false; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(lua, enable_auto_reload_changed_scripts) + } lua{}; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(menu_settings, debug, tunables, notifications, player, player_db, protections, self, session, settings, spawn_vehicle, clone_pv, spoofing, vehicle, weapons, window, context_menu, esp, session_browser, ugc, reactions, world, stat_editor, lua) }; inline auto g = menu_settings(); diff --git a/src/lua/lua_manager.cpp b/src/lua/lua_manager.cpp index df6914ef..2bbbbe88 100644 --- a/src/lua/lua_manager.cpp +++ b/src/lua/lua_manager.cpp @@ -8,6 +8,9 @@ namespace big { m_schedule_reload_modules = false; + m_wake_time_changed_scripts_check = + std::chrono::high_resolution_clock::now() + m_delay_between_changed_scripts_check; + load_all_modules(); g_lua_manager = this; @@ -58,6 +61,39 @@ namespace big m_modules.push_back(std::make_shared(module_name)); } + void lua_manager::reload_changed_scripts() + { + if (!g.lua.enable_auto_reload_changed_scripts) + { + return; + } + + if (m_wake_time_changed_scripts_check <= std::chrono::high_resolution_clock::now()) + { + for (const auto& entry : std::filesystem::directory_iterator(g_file_manager->get_project_folder("scripts").get_path())) + { + if (entry.is_regular_file()) + { + const auto module_name = entry.path().filename().string(); + const auto last_write_time = entry.last_write_time(); + + for (const auto& module : m_modules) + { + if (module->module_name() == module_name && + module->last_write_time() < last_write_time) + { + unload_module(module->module_id()); + queue_load_module(module_name, nullptr); + break; + } + } + } + } + + m_wake_time_changed_scripts_check = std::chrono::high_resolution_clock::now() + m_delay_between_changed_scripts_check; + } + } + void lua_manager::queue_load_module(const std::string& module_name, std::function)> on_module_loaded) { m_modules_load_queue.push({module_name, on_module_loaded}); @@ -73,7 +109,8 @@ namespace big load_module(module_load_info.m_name); auto loaded_module = get_module(id); - module_load_info.m_on_module_loaded(loaded_module); + if (module_load_info.m_on_module_loaded) + module_load_info.m_on_module_loaded(loaded_module); m_modules_load_queue.pop(); } diff --git a/src/lua/lua_manager.hpp b/src/lua/lua_manager.hpp index 4523217b..78221b50 100644 --- a/src/lua/lua_manager.hpp +++ b/src/lua/lua_manager.hpp @@ -6,7 +6,19 @@ namespace big { class lua_manager { + private: std::mutex m_module_lock; + std::vector> m_modules; + + struct module_load_info + { + std::string m_name; + std::function)> m_on_module_loaded; + }; + std::queue m_modules_load_queue; + + static constexpr std::chrono::seconds m_delay_between_changed_scripts_check = 3s; + std::chrono::high_resolution_clock::time_point m_wake_time_changed_scripts_check; public: bool m_schedule_reload_modules; @@ -28,6 +40,8 @@ namespace big void unload_module(rage::joaat_t module_id); void load_module(const std::string& module_name); + void reload_changed_scripts(); + void queue_load_module(const std::string& module_name, std::function)> on_module_loaded); void load_modules_from_queue(); @@ -81,16 +95,6 @@ namespace big func(module); } } - - private: - std::vector> m_modules; - - struct module_load_info - { - std::string m_name; - std::function)> m_on_module_loaded; - }; - std::queue m_modules_load_queue; }; inline lua_manager* g_lua_manager; diff --git a/src/lua/lua_module.cpp b/src/lua/lua_module.cpp index 1b0051c2..7a9ae4a2 100644 --- a/src/lua/lua_module.cpp +++ b/src/lua/lua_module.cpp @@ -63,7 +63,9 @@ namespace big m_state.set_exception_handler((sol::exception_handler_function)exception_handler); m_state.set_panic(panic_handler); - auto result = m_state.load_file(scripts_folder.get_file(module_name).get_path().string()); + const auto script_file_path = scripts_folder.get_file(module_name).get_path(); + m_last_write_time = std::filesystem::last_write_time(script_file_path); + auto result = m_state.load_file(script_file_path.string()); if (!result.valid()) { @@ -90,16 +92,21 @@ namespace big m_registered_patches.clear(); } - rage::joaat_t lua_module::module_id() + rage::joaat_t lua_module::module_id() const { return m_module_id; } - const std::string& lua_module::module_name() + const std::string& lua_module::module_name() const { return m_module_name; } + const std::chrono::time_point lua_module::last_write_time() const + { + return m_last_write_time; + } + void lua_module::add_folder_to_require_available_paths(const big::folder& scripts_folder) { const std::string package_path = m_state["package"]["path"]; diff --git a/src/lua/lua_module.hpp b/src/lua/lua_module.hpp index 8c2c19d9..01bc0585 100644 --- a/src/lua/lua_module.hpp +++ b/src/lua/lua_module.hpp @@ -11,9 +11,12 @@ namespace big class lua_module { sol::state m_state; + std::string m_module_name; rage::joaat_t m_module_id; + std::chrono::time_point m_last_write_time; + public: std::vector m_registered_scripts; std::vector> m_registered_patches; @@ -24,8 +27,9 @@ namespace big lua_module(std::string module_name); ~lua_module(); - rage::joaat_t module_id(); - const std::string& module_name(); + rage::joaat_t module_id() const; + const std::string& module_name() const; + const std::chrono::time_point last_write_time() const; // used for adding our own paths to the search paths of the lua require function void add_folder_to_require_available_paths(const big::folder& scripts_folder); diff --git a/src/script_mgr.cpp b/src/script_mgr.cpp index 1ac81075..8005ee16 100644 --- a/src/script_mgr.cpp +++ b/src/script_mgr.cpp @@ -49,6 +49,8 @@ namespace big g_lua_manager->unload_all_modules(); } + g_lua_manager->reload_changed_scripts(); + std::erase_if(m_scripts, [](std::unique_ptr