port 4-a: text input through CPythonIME (login typed, in-game chat)
- UserInterface/PythonIME(+Module) ported verbatim; ime module stubs removed, initime() after initdbg() - EterLib/IME.cpp in platform/: 40250 buffer/WMChar bodies, IMM/TSF processors no-op; committed multi-byte text via PythonBoot::UIChar emulating GCS_RESULTSTR - GameApplicationAdapter RunIME* -> CWindowManager; Godot keys -> ui_ime_key/ui_char - port.login_flow/login_live type the account through the IME; chat CG_CHAT round-trip on the fake server - python_game_render_test logs in with Godot key events Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1bda4390d6
commit
6ea0fa9889
@@ -244,9 +244,29 @@ int main(int argc, char** argv)
|
||||
char ports[128];
|
||||
std::snprintf(ports, sizeof(ports), "_auth_port, _game_port, _slot = %d, %d, %d", auth_port, game_port, slot);
|
||||
CHECK(py(ports));
|
||||
CHECK(py("_stream.SetConnectInfo(_host, _game_port, _host, _auth_port)\n"
|
||||
"_stream.curPhaseWindow.Connect(_login, _password)\n"
|
||||
"del __main__._login, __main__._password"));
|
||||
CHECK(py("_stream.SetConnectInfo(_host, _game_port, _host, _auth_port)"));
|
||||
// Typed into the login board through the 40250 IME (WM_CHAR -> CPythonIME::WMChar, WM_KEYDOWN ->
|
||||
// OnIMEKeyDown): Tab moves to the password line, Return runs __OnClickLoginButton -> Connect.
|
||||
// The IME only reaches a rendering EditLine: open the login board as the server list's OK button does.
|
||||
CHECK(py("_w = _stream.curPhaseWindow\n"
|
||||
"_w._LoginWindow__OpenLoginBoard()\n"
|
||||
"_w.idEditLine.SetText('')\n"
|
||||
"_w.pwdEditLine.SetText('')\n"
|
||||
"_w.idEditLine.SetFocus()"));
|
||||
auto type = [](const std::string& text) {
|
||||
for (unsigned char c : text)
|
||||
PythonBoot::UIChar(c);
|
||||
};
|
||||
type(login + "xy");
|
||||
PythonBoot::UIIMEKeyDown(VK_LEFT);
|
||||
PythonBoot::UIIMEKeyDown(VK_DELETE); // y
|
||||
PythonBoot::UIChar(VK_BACK); // x
|
||||
CHECK(py("assert _w.idEditLine.GetText() == _login, repr(_w.idEditLine.GetText())"));
|
||||
PythonBoot::UIChar(VK_TAB);
|
||||
type(password);
|
||||
CHECK(py("assert _w.pwdEditLine.GetText() == _password, len(_w.pwdEditLine.GetText())\n"
|
||||
"del __main__._login, __main__._password, __main__._w"));
|
||||
PythonBoot::UIChar(VK_RETURN);
|
||||
|
||||
// 3. The character list.
|
||||
const bool selecting = pump_until(live ? 30 : 20, [&] {
|
||||
@@ -614,6 +634,22 @@ int main(int argc, char** argv)
|
||||
// uiexchange.CloseDialog armed wndMgr.OnceIgnoreMouseLeftButtonUpEvent (in the client that release belongs
|
||||
// to the click that closed the dialog); spend it so step 8's click-release is not swallowed.
|
||||
PythonBoot::UIMouseButton(1, false, 400, 520);
|
||||
|
||||
// Chat (批次 4-a): Return on the focused game.GameWindow → OnIMEReturn → interface.ToggleChat opens the
|
||||
// chat line; the typed text goes through CPythonIME, a second Return sends CG_CHAT (TALKING) and the fake
|
||||
// server echoes GC_CHAT back.
|
||||
CHECK(py_true("not _stream.curPhaseWindow.interface.IsOpenChat()"));
|
||||
PythonBoot::UIChar(VK_RETURN);
|
||||
CHECK(pump_until(1, [] { return py_true("_stream.curPhaseWindow.interface.IsOpenChat()"); }));
|
||||
for (char c : std::string("hello"))
|
||||
PythonBoot::UIChar((unsigned char)c);
|
||||
pump_until(0.05, [] { return false; });
|
||||
PythonBoot::UIChar(VK_RETURN);
|
||||
CHECK(pump_until(2, [&] { return server->Has("game2:chat 0 hello"); }));
|
||||
// uichat.__SendTalkingChatPacket only resets the line; a Return on the empty line closes it (eventReturn).
|
||||
CHECK(py_true("_stream.curPhaseWindow.interface.IsOpenChat() and __import__('ime').GetText(0) == ''"));
|
||||
PythonBoot::UIChar(VK_RETURN);
|
||||
CHECK(pump_until(1, [] { return py_true("not _stream.curPhaseWindow.interface.IsOpenChat()"); }));
|
||||
}
|
||||
|
||||
// 8. (批次 2V3) Click-to-move: a left click on the ground below the actor reaches game.GameWindow's
|
||||
@@ -664,7 +700,7 @@ int main(int argc, char** argv)
|
||||
for (const auto& e : events)
|
||||
if (e.rfind(prefix, 0) == 0 && e.find(":move ") == std::string::npos &&
|
||||
e.find(":pickup ") == std::string::npos &&
|
||||
e.find(":exchange ") == std::string::npos)
|
||||
e.find(":exchange ") == std::string::npos && e.find(":chat ") == std::string::npos)
|
||||
got.push_back(e);
|
||||
CHECK(want == got);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user