1
0
mirror of https://github.com/0O0o0oOoO00/Alas.git synced 2026-05-14 13:39:25 +08:00

fix: call lua operation at lua state pause thread

This commit is contained in:
0O0o0oOoO00
2025-11-22 14:57:58 +08:00
parent c306e5841d
commit 4d00273ba3
2 changed files with 45 additions and 88 deletions

View File

@@ -59,34 +59,34 @@ static fnset_TimeScaleT get_Time_set_timeScale() {
LuaStatePauser::LuaStatePauser(lua_State* L) : m_L(L) {
thiz = this;
register_debug_hook();
ensure_debug_hook();
}
void LuaStatePauser::set() {
void LuaStatePauser::do_when_paused(const std::function<void()>& func) {
auto _ = std::lock_guard<std::mutex>(m_atomic_pause);
ensure_debug_hook();
auto lk = std::mutex();
auto fn = std::function<void()>([&]() {
g_lua_state_operation.store(nullptr);
func();
lk.unlock();
});
lk.lock();
g_lua_state_operation.store(&fn);
lk.lock();
}
void LuaStatePauser::ensure_debug_hook() {
if (lua_gethook(m_L) != LuaStatePauser::debug_hook) {
register_debug_hook();
}
m_ready_flag = false;
}
void LuaStatePauser::wait_paused() {
m_need_pause = true;
m_pause_flag.wait(false);
}
void LuaStatePauser::ready() {
SPDLOG_INFO("lua operation ready");
m_ready_flag = true;
m_ready_flag.notify_all();
}
void LuaStatePauser::release() {
m_need_pause = false;
m_pause_flag = false;
}
LuaStatePauser* LuaStatePauser::thiz = nullptr;
std::atomic<std::function<void()>*> LuaStatePauser::g_lua_state_operation = nullptr;
void LuaStatePauser::register_debug_hook() {
SPDLOG_INFO("registering debug hook");
int ret = lua_sethook(m_L, LuaStatePauser::debug_hook, LUA_MASKCALL, 0);
@@ -95,26 +95,6 @@ void LuaStatePauser::register_debug_hook() {
}
}
void LuaStatePauser::unregister_debug_hook() {
int ret = lua_sethook(m_L, nullptr, 0, 0);
if (ret != 1) {
SPDLOG_INFO("remove pause hook failed with code: {}", ret);
}
}
void LuaStatePauser::paused() {
m_pause_flag = true;
m_pause_flag.notify_all();
}
void LuaStatePauser::wait_ready() {
m_ready_flag.wait(false);
}
bool LuaStatePauser::need_pause() {
return m_need_pause.load();
}
extern bool g_is_game_loaded;
void LuaStatePauser::debug_hook(lua_State *L, lua_Debug *ar) {
@@ -122,30 +102,15 @@ void LuaStatePauser::debug_hook(lua_State *L, lua_Debug *ar) {
if (!thiz) {
return;
}
if (!thiz->need_pause()) {
auto callback = g_lua_state_operation.load();
if (!callback) {
return;
}
SPDLOG_INFO("pause triggered, notify to operate lua state");
thiz->paused();
thiz->wait_ready();
SPDLOG_INFO("pause triggered, operate lua state");
(*callback)();
}
}
LuaStatePauserGuard::LuaStatePauserGuard(LuaStatePauser* p) : m_p(p) {
m_p->set();
m_p->wait_paused();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
LuaStatePauserGuard::~LuaStatePauserGuard() {
m_p->ready();
m_p->release();
}
#define LUA_STATUS_PAUSER_GUARD() \
auto __pc = std::lock_guard<std::mutex>(m_pauser_lock); \
auto __pg = LuaStatePauserGuard(&m_lua_state_pauser);
Cracker::Cracker(bool need_pause)
: m_state([]() -> lua_State* {
auto new_tr = lua_newthread(Utils::get_lua_state());
@@ -644,9 +609,10 @@ void Cracker::fast_stage_move_set_duration(double duration) {
}
void Cracker::fast_stage_move_set_duration_with_pause(double duration) {
LUA_STATUS_PAUSER_GUARD();
m_state["ChapterConst"]["ShipStepDuration"] = duration;
m_state["ChapterConst"]["ShipStepQuickPlayScale"] = duration;
m_lua_state_pauser.do_when_paused([&] () {
m_state["ChapterConst"]["ShipStepDuration"] = duration;
m_state["ChapterConst"]["ShipStepQuickPlayScale"] = duration;
});
}
void Cracker::fast_stage_move_set_duration_without_pause(double duration) {
@@ -663,8 +629,9 @@ void Cracker::skip_battle_celebrate_set_duration(double duration) {
}
void Cracker::skip_battle_celebrate_set_duration_with_pause(double duration) {
LUA_STATUS_PAUSER_GUARD();
m_state["ys"]["Battle"]["BattleConfig"]["CelebrateDuration"] = duration;
m_lua_state_pauser.do_when_paused([&]() {
m_state["ys"]["Battle"]["BattleConfig"]["CelebrateDuration"] = duration;
});
}
void Cracker::skip_battle_celebrate_set_duration_without_pause(double duration) {
@@ -1528,9 +1495,10 @@ void Cracker::better_global_speedup_set_rate(double rate) {
}
void Cracker::better_global_speedup_set_rate_with_pause(double rate) {
LUA_STATUS_PAUSER_GUARD();
m_state["ys"]["Battle"]["BattleConfig"]["BASIC_TIME_SCALE"] = rate;
m_state["Time"]["timeScale"] = rate;
m_lua_state_pauser.do_when_paused([&]() {
m_state["ys"]["Battle"]["BattleConfig"]["BASIC_TIME_SCALE"] = rate;
m_state["Time"]["timeScale"] = rate;
});
}
void Cracker::better_global_speedup_set_rate_without_pause(double rate) {
@@ -1737,11 +1705,12 @@ void Cracker::apply_config(Config& config) {
}
void Cracker::load_cracker_with_pause() {
SPDLOG_INFO("Load cracker with lua pause");
LUA_STATUS_PAUSER_GUARD();
load_lua_resources();
hook_all_lua_functions();
load_real_lua_func();
m_lua_state_pauser.do_when_paused([&]() {
SPDLOG_INFO("Load cracker with lua pause");
load_lua_resources();
hook_all_lua_functions();
load_real_lua_func();
});
}
void Cracker::load_cracker_without_pause() {

View File

@@ -25,34 +25,23 @@ class LuaStatePauser {
public:
LuaStatePauser(lua_State* L);
void do_when_paused(const std::function<void()>& func);
void set();
void wait_paused();
void ready();
void release();
private:
void ensure_debug_hook();
void register_debug_hook();
void unregister_debug_hook();
void paused();
void wait_ready();
bool need_pause();
static LuaStatePauser* thiz;
static std::atomic<std::function<void()>*> g_lua_state_operation;
static void debug_hook(lua_State *L, lua_Debug *ar);
std::atomic_bool m_pause_flag = ATOMIC_FLAG_INIT;
std::atomic_bool m_ready_flag = ATOMIC_FLAG_INIT;
std::mutex m_atomic_pause;
lua_State* m_L;
std::atomic<bool> m_need_pause = false;
};
class LuaStatePauserGuard {
public:
LuaStatePauserGuard(LuaStatePauser* p);
~LuaStatePauserGuard();
private:
LuaStatePauser* m_p;
};
class Cracker {
@@ -453,7 +442,6 @@ private:
std::atomic<float> m_global_speedup_rate = 1.0;
std::atomic<double> m_better_global_speedup_rate = 1.0;
LuaStatePauser m_lua_state_pauser;
std::mutex m_pauser_lock;
std::atomic<bool> m_better_global_speedup_need_pause = false;
std::atomic<bool> m_skip_battle_celebrate_need_pause = false;
std::atomic<bool> m_fast_stage_move_need_pause = false;