diff --git a/src/Mods.cpp b/src/Mods.cpp index b681dd64..98d41a1f 100644 --- a/src/Mods.cpp +++ b/src/Mods.cpp @@ -96,7 +96,7 @@ std::optional Mods::on_initialize() const { std::optional Mods::on_initialize_d3d_thread() const { - std::scoped_lock _{g_framework->get_hook_monitor_mutex()}; + auto do_not_hook_d3d = g_framework->acquire_do_not_hook_d3d(); utility::Config cfg{ (REFramework::get_persistent_dir() / REFrameworkConfig::REFRAMEWORK_CONFIG_NAME).string() }; diff --git a/src/REFramework.cpp b/src/REFramework.cpp index b052dc83..32114a3f 100644 --- a/src/REFramework.cpp +++ b/src/REFramework.cpp @@ -47,17 +47,25 @@ using namespace std::literals; std::unique_ptr g_framework{}; void REFramework::hook_monitor() { + if (m_do_not_hook_d3d_count.load() > 0) { + // Wait until nothing important is happening + m_last_present_time = std::chrono::steady_clock::now() + std::chrono::seconds(5); + m_last_chance_time = std::chrono::steady_clock::now() + std::chrono::seconds(1); + m_has_last_chance = true; + return; + } + if (!m_hook_monitor_mutex.try_lock()) { // If this happens then we can assume execution is going as planned // so we can just reset the times so we dont break something m_last_present_time = std::chrono::steady_clock::now() + std::chrono::seconds(5); m_last_chance_time = std::chrono::steady_clock::now() + std::chrono::seconds(1); m_has_last_chance = true; - } else { - m_hook_monitor_mutex.unlock(); + return; } - std::scoped_lock _{ m_hook_monitor_mutex }; + // Take ownership of the mutex with adopt_lock + std::lock_guard _{ m_hook_monitor_mutex, std::adopt_lock }; if (g_framework == nullptr) { return; @@ -2018,7 +2026,7 @@ bool REFramework::first_frame_initialize() { return is_init_ok; } - std::scoped_lock _{get_hook_monitor_mutex()}; + auto do_not_hook_d3d = acquire_do_not_hook_d3d(); spdlog::info("Running first frame D3D initialization of mods..."); diff --git a/src/REFramework.hpp b/src/REFramework.hpp index f29d6849..f90d14cf 100644 --- a/src/REFramework.hpp +++ b/src/REFramework.hpp @@ -24,6 +24,26 @@ class RETypes; class REFramework { private: void hook_monitor(); + std::atomic m_do_not_hook_d3d_count{0}; + +public: + struct DoNotHook { + DoNotHook(std::atomic& count) : m_count(count) { + ++m_count; + } + + ~DoNotHook() { + --m_count; + } + + private: + std::atomic& m_count; + }; + + DoNotHook acquire_do_not_hook_d3d() { + return DoNotHook{m_do_not_hook_d3d_count}; + } + public: REFramework(HMODULE reframework_module); @@ -121,6 +141,10 @@ class REFramework { return m_hook_monitor_mutex; } + auto& get_startup_mutex() { + return m_startup_mutex; + } + void set_font_size(int size) { if (m_font_size != size) { m_font_size = size; diff --git a/src/mods/ScriptRunner.cpp b/src/mods/ScriptRunner.cpp index b306986e..c4b97c9e 100644 --- a/src/mods/ScriptRunner.cpp +++ b/src/mods/ScriptRunner.cpp @@ -1168,7 +1168,8 @@ void ScriptRunner::spew_error(const std::string& p) { void ScriptRunner::reset_scripts() { - std::scoped_lock __{ g_framework->get_hook_monitor_mutex() }; // Stops D3D monitor from attempting to re-hook during long script startups + auto do_not_hook_d3d = g_framework->acquire_do_not_hook_d3d(); + std::scoped_lock _{ m_access_mutex }; {