2V2-a: game.GameWindow opens after Loading and sends CG_ENTERGAME
The 2V0 stub modules now carry the 40250 module constants (copied from each module's init function by stub_constants.py) and return zero values shaped like each reference function's Py_BuildValue, so interfaceModule.MakeInterface runs through (uiSafebox no longer divides by a zero SAFEBOX_SLOT_Y_COUNT). UserInterface/StdAfx.h includes Locale.h before GameType.h as the 40250 PCH does; the reversed order dropped GameType.h's ENABLE_NEW_EQUIPMENT_SYSTEM branches. port.login_flow's fake server checks CG_ENTERGAME; port.login_live reaches the GameWindow on 192.168.21.203. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
0073469dd1
commit
d16fabf61c
@@ -434,7 +434,13 @@ bool FakeLoginServer::ServeGame(Connection& c, int index)
|
||||
c.sequence = (c.sequence + 1) % SEQUENCE_TABLE_SIZE;
|
||||
Event(name + ":client_version");
|
||||
|
||||
// Hold the connection (the loading screen) until the test stops us.
|
||||
// game.GameWindow.Open (after the loading steps' net.StartGame()) sends CG_ENTERGAME.
|
||||
auto enter = zeroed<CGEnterGame>();
|
||||
if (read_packet(c, HDR_CG_ENTERGAME, &enter, sizeof(enter), &error) != 1)
|
||||
return Fail(name + ": CG_ENTERGAME: " + error);
|
||||
Event(name + ":entergame");
|
||||
|
||||
// Hold the connection until the test stops us.
|
||||
std::uint8_t byte = 0;
|
||||
while (!m_stop && c.Read(&byte, 1) == 1)
|
||||
;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 批次 2V1-d: the real 40250 login → select → loading path, offline.
|
||||
// 批次 2V1-d/2V2: the real 40250 login → select → loading → game path, offline.
|
||||
//
|
||||
// The 40250 root scripts (intrologin.py, introselect.py, introloading.py, networkmodule.py) drive the
|
||||
// ported CPythonNetworkStream and CAccountConnector against FakeLoginServer (port_login_flow_server.h),
|
||||
@@ -13,7 +13,9 @@
|
||||
// slot's addr/port, logs in again, and in direct-enter mode the select phase goes straight to
|
||||
// introLoading.LoadingWindow, which sends CG_CHARACTER_SELECT;
|
||||
// 5. PHASE_LOADING, GC_MAIN_CHARACTER, GC_CHARACTER_POINTS: the loading phase answers the main
|
||||
// character with CG_CLIENT_VERSION(2), the server's proof the client reached Loading.
|
||||
// character with CG_CLIENT_VERSION(2), the server's proof the client reached Loading;
|
||||
// 6. (批次 2V2) the loading steps end in net.StartGame(): networkModule.SetGamePhase opens
|
||||
// game.GameWindow, whose Open sends CG_ENTERGAME.
|
||||
//
|
||||
// The server checks every sequence byte against the 40250 table, so a skipped or extra sequenced
|
||||
// packet fails the run.
|
||||
@@ -21,9 +23,9 @@
|
||||
// port_login_flow_test <40250 Client dir> <python27.zip> [live]
|
||||
//
|
||||
// With `live` (批次 2V1-e, ctest port.login_live) the same path runs against a real 40250 server and
|
||||
// the client's own state is the proof: the character list arrived, and the loading window got
|
||||
// the client's own state is the proof: the character list arrived, the loading window got
|
||||
// LoadData from GC_MAIN_CHARACTER, which CPythonNetworkStream::RecvMainCharacter answers with
|
||||
// CG_CLIENT_VERSION. The test exits before net.StartGame() would enter the game. Everything about the
|
||||
// CG_CLIENT_VERSION, and game.GameWindow is open, which sent CG_ENTERGAME. Everything about the
|
||||
// server comes from the environment and nothing of it is printed:
|
||||
//
|
||||
// MT_LIVE_HOST, MT_LIVE_LOGIN, MT_LIVE_PASSWORD required; without them the test is skipped
|
||||
@@ -226,16 +228,23 @@ int main(int argc, char** argv)
|
||||
return failed() || (server ? server->Has("game2:client_version") : py_true(loaded));
|
||||
});
|
||||
CHECK(loading && !failed());
|
||||
// Checked right away: introLoading's own update steps end in net.StartGame(), after which the stream
|
||||
// opens game.GameWindow itself (CPythonNetworkStream::Process, m_isStartGame), which is 2V2.
|
||||
CHECK(py_true(loaded));
|
||||
}
|
||||
|
||||
// 6. introLoading's update steps end in net.StartGame(); the next CPythonNetworkStream::Process calls
|
||||
// networkModule's SetGamePhase, which builds game.GameWindow (interfaceModule.MakeInterface) and
|
||||
// opens it, and GameWindow.Open sends CG_ENTERGAME.
|
||||
CHECK(py("import game"));
|
||||
const char* gaming = "isinstance(_stream.curPhaseWindow, game.GameWindow) and _stream.curPhaseWindow.IsShow()";
|
||||
const bool entered = pump_until(30, [&] {
|
||||
return failed() || (py_true(gaming) && (!server || server->Has("game2:entergame")));
|
||||
});
|
||||
CHECK(entered && !failed());
|
||||
}
|
||||
if (server)
|
||||
{
|
||||
const std::vector<std::string> expected = {
|
||||
"auth:handshake", "auth:login3", "game1:handshake", "game1:login2", "auth:closed",
|
||||
"game1:closed", "game2:handshake", "game2:login2", "game2:select", "game2:client_version",
|
||||
"game1:closed", "game2:handshake", "game2:login2", "game2:select", "game2:client_version", "game2:entergame",
|
||||
};
|
||||
auto events = server->Events();
|
||||
// auth:closed races game1's handshake; compare the order within each connection.
|
||||
|
||||
Reference in New Issue
Block a user