Fix 40250 classic login and world loading

This commit is contained in:
shen
2026-09-02 07:03:25 +08:00
parent 8f61990a83
commit 44bdcb0781
17 changed files with 446 additions and 45 deletions
+25 -6
View File
@@ -455,18 +455,26 @@ void M2Client::connect_to_server(const String &auth_host, int auth_port, const S
have_cfg = true;
suspended = false;
// MT_PROTOCOL=classic -> 40250 backend: direct connect to the game host,
// with the same post-login feature surface as the shared M2Client API.
// MT_PROTOCOL=classic -> 40250 backend: authenticate on auth_host first,
// then connect to game_host with the returned login ticket.
if (OS::get_singleton()->get_environment("MT_PROTOCOL") == "classic") {
classic_sess = std::make_unique<mtnet::classic::ClassicSession>();
// The 40250 server expects CG_ENTERGAME shortly after the loading phase
// starts. Keep the live client in the same timing window as m2dev while
// allowing a deployment-specific override for unusually large bursts.
const String enter_delay = OS::get_singleton()->get_environment("MT_CLASSIC_ENTER_DELAY");
classic_sess->set_auto_entergame_delay(enter_delay.is_empty() ? 1500 :
static_cast<uint32_t>(MAX(0, enter_delay.to_int())));
last_login_key = 0;
classic_list_emitted = false;
classic_last_stage = -1;
classic_last_empire = -1;
shop_open_seen = false;
mall_open_seen = false;
last_game_phase = -1;
if (!classic_sess->connect(std::string(g_host.utf8().get_data()), (uint16_t)g_port,
std::string(id.utf8().get_data()), std::string(pw.utf8().get_data()))) {
if (!classic_sess->connect(std::string(auth_host.utf8().get_data()), (uint16_t)auth_port,
std::string(g_host.utf8().get_data()), (uint16_t)g_port,
std::string(id.utf8().get_data()), std::string(pw.utf8().get_data()))) {
emit_signal("login_failed", String(classic_sess->last_error().c_str()));
set_stage(Stage::Failed);
classic_sess.reset();
@@ -2646,8 +2654,16 @@ void M2Client::warp_to_game_server(const String &host, int port) {
mall_open_seen = false;
dead_seen.clear();
classic_sess = std::make_unique<mtnet::classic::ClassicSession>();
if (!classic_sess->connect(std::string(host.utf8().get_data()), (uint16_t)port,
std::string(cfg_id.utf8().get_data()), std::string(cfg_pw.utf8().get_data()))) {
bool connected = false;
if (last_login_key != 0) {
connected = classic_sess->connect_with_login_key(std::string(host.utf8().get_data()),
(uint16_t)port, std::string(cfg_id.utf8().get_data()), last_login_key);
} else {
connected = classic_sess->connect(std::string(cfg_auth_host.utf8().get_data()),
(uint16_t)cfg_auth_port, std::string(host.utf8().get_data()), (uint16_t)port,
std::string(cfg_id.utf8().get_data()), std::string(cfg_pw.utf8().get_data()));
}
if (!connected) {
emit_signal("login_failed", String(classic_sess->last_error().c_str()));
set_stage(Stage::Failed);
classic_sess.reset();
@@ -2691,6 +2707,9 @@ void M2Client::pump_classic() {
classic_sess->set_now((uint32_t)Time::get_singleton()->get_ticks_msec());
classic_sess->pump();
if (classic_sess->login_key() != 0) {
last_login_key = classic_sess->login_key();
}
const int empire = (int)classic_sess->parser().empire();
if (empire != classic_last_empire) {
classic_last_empire = empire;