Feat lua file watch (#1584)
* feat lua: file watcher for lua script file: reload scripts if they got changed since they were initially loaded * feat lua auto reload: enable / disable the feature through the ui and settings
This commit is contained in:
parent
e4ac08496c
commit
a4d623ca74
@ -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();
|
||||
|
@ -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<lua_module>(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<void(std::weak_ptr<lua_module>)> 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();
|
||||
}
|
||||
|
@ -6,7 +6,19 @@ namespace big
|
||||
{
|
||||
class lua_manager
|
||||
{
|
||||
private:
|
||||
std::mutex m_module_lock;
|
||||
std::vector<std::shared_ptr<lua_module>> m_modules;
|
||||
|
||||
struct module_load_info
|
||||
{
|
||||
std::string m_name;
|
||||
std::function<void(std::weak_ptr<lua_module>)> m_on_module_loaded;
|
||||
};
|
||||
std::queue<module_load_info> 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<void(std::weak_ptr<lua_module>)> on_module_loaded);
|
||||
void load_modules_from_queue();
|
||||
|
||||
@ -81,16 +95,6 @@ namespace big
|
||||
func(module);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<lua_module>> m_modules;
|
||||
|
||||
struct module_load_info
|
||||
{
|
||||
std::string m_name;
|
||||
std::function<void(std::weak_ptr<lua_module>)> m_on_module_loaded;
|
||||
};
|
||||
std::queue<module_load_info> m_modules_load_queue;
|
||||
};
|
||||
|
||||
inline lua_manager* g_lua_manager;
|
||||
|
@ -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<std::chrono::file_clock> 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"];
|
||||
|
@ -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<std::chrono::file_clock> m_last_write_time;
|
||||
|
||||
public:
|
||||
std::vector<script*> m_registered_scripts;
|
||||
std::vector<std::shared_ptr<lua_patch>> 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<std::chrono::file_clock> 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);
|
||||
|
@ -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<script>& iter) {
|
||||
return iter->m_should_be_deleted;
|
||||
});
|
||||
|
@ -53,5 +53,7 @@ namespace big
|
||||
{
|
||||
g_lua_manager->m_schedule_reload_modules = true;
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Auto Reload Changed Scripts", &g.lua.enable_auto_reload_changed_scripts);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user