diff --git a/src/host/touch_controller.h b/src/host/touch_controller.h index a4615a88..3bbc95d9 100644 --- a/src/host/touch_controller.h +++ b/src/host/touch_controller.h @@ -588,7 +588,7 @@ public: private: bool gameplay_controls_visible() const { #ifdef MT_NATIVE_HAS_LIVE_CLIENT - return !PythonBoot::CurrentMapName().empty(); + return PythonBoot::InGamePhase() && !PythonBoot::CurrentMapName().empty(); #else return false; #endif diff --git a/src/platform/ScriptLib/PythonBoot.cpp b/src/platform/ScriptLib/PythonBoot.cpp index 9e6a4631..bbfa65ba 100644 --- a/src/platform/ScriptLib/PythonBoot.cpp +++ b/src/platform/ScriptLib/PythonBoot.cpp @@ -277,6 +277,11 @@ std::string CurrentMapName() return CPythonBackground::Instance().GetWarpMapName(); } +bool InGamePhase() +{ + return g_network_stream && g_network_stream->PORT_IsGamePhase(); +} + bool IsRunning() { return g_launcher != nullptr; diff --git a/src/platform/ScriptLib/PythonBoot.h b/src/platform/ScriptLib/PythonBoot.h index c2059677..dce18aab 100644 --- a/src/platform/ScriptLib/PythonBoot.h +++ b/src/platform/ScriptLib/PythonBoot.h @@ -46,6 +46,8 @@ int ScriptThreadId(); bool AppFrame(); // Native CPythonBackground map selection, in the local coordinate frame of RenderGame. std::string CurrentMapName(); +// CPythonNetworkStream is in the game phase (SetGamePhase opened game.GameWindow); false while loading. +bool InGamePhase(); // Used by the platform CPythonApplication: Loop() calls AppLoopWait() before each Process() and stops // when it returns false; Exit()/Abort() call AppRequestQuit() (40250: PostQuitMessage). diff --git a/src/port/UserInterface/PythonNetworkStream.h b/src/port/UserInterface/PythonNetworkStream.h index 70e1f701..18b8cb01 100644 --- a/src/port/UserInterface/PythonNetworkStream.h +++ b/src/port/UserInterface/PythonNetworkStream.h @@ -118,6 +118,8 @@ class CPythonNetworkStream : public CNetworkStream, public CSingletonHas("game2:entergame"))); }); CHECK(entered && !failed()); + // CG_ENTERGAME's PHASE_GAME answer switches the stream to "Game" a round trip after the window opens. + CHECK(pump_until(5, [] { return PythonBoot::InGamePhase(); }) && !PythonBoot::CurrentMapName().empty()); // 7. (批次 2V2-b) The server answers CG_ENTERGAME with the character's own insert packets and // PHASE_GAME, then the Entergame burst (PVP/land list, time, channel, greet chat, ...). GamePhase