diff --git a/blcrack/cracker/cracker.cpp b/blcrack/cracker/cracker.cpp index 8a46f40ed..01e6b59fa 100644 --- a/blcrack/cracker/cracker.cpp +++ b/blcrack/cracker/cracker.cpp @@ -42,6 +42,50 @@ static fnset_TimeScaleT get_Time_set_timeScale() { return fn; } +std::atomic_bool g_pause_flag = ATOMIC_FLAG_INIT; +std::atomic_bool g_loaded_flag = ATOMIC_FLAG_INIT; +extern bool g_is_game_loaded; + +void cracker_loaded() { + g_loaded_flag = true; + g_loaded_flag.notify_all(); +} + +void wait_pause() { + g_pause_flag.wait(false); +} + +void lua_paused() { + g_pause_flag = true; + g_pause_flag.notify_all(); +} + +void wait_cracker_loaded() { + g_loaded_flag.wait(false); +} + +void debug_hook(lua_State *L, lua_Debug *ar) { + if (g_is_game_loaded) { + SPDLOG_INFO("pause triggered, notify to load cracker"); + lua_paused(); + wait_cracker_loaded(); + } +} + +void setup_pause_hook(lua_State *L) { + int ret = lua_sethook(L, debug_hook, LUA_MASKCALL, 0); + if (ret != 1) { + SPDLOG_INFO("set pause hook failed with code: {}", ret); + } +} + +void remove_pause_hook(lua_State *L) { + int ret = lua_sethook(L, nullptr, 0, 0); + if (ret != 1) { + SPDLOG_INFO("remove pause hook failed with code: {}", ret); + } +} + #define IS_ENABLED(f) m_flag.f.load() #define ENABLE(n) \ @@ -57,16 +101,18 @@ static fnset_TimeScaleT get_Time_set_timeScale() { SPDLOG_INFO("{} called", #f); \ } -Cracker::Cracker() +Cracker::Cracker(bool need_pause) : m_state([]() -> lua_State* { auto new_tr = lua_newthread(Utils::get_lua_state()); SPDLOG_INFO("new lua_State: {}", (void*)new_tr); return new_tr; }()) { try { - load_lua_resources(); - hook_all_lua_functions(); - load_real_lua_func(); + if (need_pause) { + load_cracker_with_pause(); + } else { + load_cracker_without_pause(); + } } catch(std::exception& e) { SPDLOG_ERROR("Cracker load error: {}", e.what()); exit(-1); @@ -81,8 +127,8 @@ Cracker& Cracker::Instance() { return *instance; } #else -Cracker& Cracker::Instance() { - static auto* instance = new Cracker; +Cracker& Cracker::Instance(bool need_pause) { + static auto* instance = new Cracker(need_pause); return *instance; } #endif @@ -1581,6 +1627,24 @@ void Cracker::apply_config(Config& config) { } } +void Cracker::load_cracker_with_pause() { + SPDLOG_INFO("Load cracker with lua pause"); + setup_pause_hook(Utils::get_lua_state()); + wait_pause(); + load_lua_resources(); + hook_all_lua_functions(); + load_real_lua_func(); + remove_pause_hook(Utils::get_lua_state()); + cracker_loaded(); +} + +void Cracker::load_cracker_without_pause() { + SPDLOG_INFO("Load cracker directly"); + load_lua_resources(); + hook_all_lua_functions(); + load_real_lua_func(); +} + void Cracker::load_real_lua_func() { m_real_func.Chapter_IsAutoFight = m_state["Chapter"]["IsAutoFight"]; m_real_func.LevelStageView_tryAutoTrigger = m_state["LevelStageView"]["tryAutoTrigger"]; diff --git a/blcrack/cracker/cracker.hpp b/blcrack/cracker/cracker.hpp index ec3cd17d1..f28a378ad 100644 --- a/blcrack/cracker/cracker.hpp +++ b/blcrack/cracker/cracker.hpp @@ -106,9 +106,9 @@ public: }; public: - Cracker(); + Cracker(bool need_pause); - static Cracker& Instance(); + static Cracker& Instance(bool need_pause = true); int get_coin(); int get_oil(); @@ -229,6 +229,9 @@ public: void apply_config(Config& config); private: + void load_cracker_with_pause(); + void load_cracker_without_pause(); + void load_real_lua_func(); void ensure_data_proxies(); diff --git a/blcrack/cracker/ui/ui.cpp b/blcrack/cracker/ui/ui.cpp index f9853989b..9eff2c6c2 100644 --- a/blcrack/cracker/ui/ui.cpp +++ b/blcrack/cracker/ui/ui.cpp @@ -81,11 +81,11 @@ void CrackerUI::draw_menu() { ImGui::SameLine(); if(ImGui::Button("刷新")) { - m_cracker_config = Cracker::Instance().get_config(); + m_cracker_config = Cracker::Instance(false).get_config(); } ImGui::SameLine(); if(ImGui::Button("应用")) { - Cracker::Instance().apply_config(m_cracker_config); + Cracker::Instance(false).apply_config(m_cracker_config); } ImGui::SameLine(); if(ImGui::Button("关闭UI")) { diff --git a/blcrack/cracker/utils.cpp b/blcrack/cracker/utils.cpp index 0ca38d539..cbaf4640c 100644 --- a/blcrack/cracker/utils.cpp +++ b/blcrack/cracker/utils.cpp @@ -59,19 +59,23 @@ static LuaScriptMgr_get_Inst get_lua_script_mgr_get_inst() { } lua_State* Utils::get_lua_state() { - LuaScriptMgr_get_Inst get_instance = get_lua_script_mgr_get_inst(); - struct LuaScriptMgr_o* lua_script_mgr = get_instance(); + static lua_State* g_state = [] () { + LuaScriptMgr_get_Inst get_instance = get_lua_script_mgr_get_inst(); + struct LuaScriptMgr_o* lua_script_mgr = get_instance(); - LuaInterface_LuaState_o* luaState = nullptr; - while (luaState == nullptr) { - luaState = lua_script_mgr->fields.luaState; - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - SPDLOG_INFO("lua_State: {}", (void*)luaState->fields.L); + LuaInterface_LuaState_o* luaState = nullptr; + while (luaState == nullptr) { + luaState = lua_script_mgr->fields.luaState; + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + SPDLOG_INFO("lua_State: {}", (void*)luaState->fields.L); - // std::this_thread::sleep_for(std::chrono::seconds(10)); + // std::this_thread::sleep_for(std::chrono::seconds(10)); - return (lua_State*)luaState->fields.L; + return (lua_State*)luaState->fields.L; + } (); + + return g_state; } Utils::FuncTrace::FuncTrace(const std::string& func) : m_func(func) {