From f65b1f1c14522f0887b77294d56c617dc06c153c Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Fri, 25 Apr 2025 08:56:19 -0700 Subject: [PATCH] make login faster with MoreSaveSlots --- src/CommandFormats.hh | 4 ++ src/ReceiveCommands.cc | 41 +++++++++++++------ .../MoreSaveSlots.59NL.patch.s | 22 ++++++++++ 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index e2b8e494..36080c4f 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -3109,6 +3109,10 @@ check_struct_size(S_TournamentGameDetails_Ep3NTE_E3, 0x734); check_struct_size(S_TournamentGameDetails_Ep3_E3, 0x73C); // E3 (C->S): Player preview request (BB) +// header.flag is not used by the vanilla client, but newserv's MoreSaveSlots +// patch uses header.flag to tell the server how many save slots the client +// expects. The server uses this to send all the character previews at once, +// thus reducing the number of network roundtrips during login. struct C_PlayerPreviewRequest_BB_E3 { le_int32_t character_index = 0; diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index 8075e71a..d06f3121 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -3616,13 +3616,12 @@ static void on_E0_BB(shared_ptr c, uint16_t, uint32_t, string& data) { send_system_file_bb(c); } -static void on_E3_BB(shared_ptr c, uint16_t, uint32_t, string& data) { +static void on_E3_BB(shared_ptr c, uint16_t, uint32_t flag, string& data) { const auto& cmd = check_size_t(data); - c->save_and_unload_character(); - c->bb_character_index = cmd.character_index; - if (c->bb_connection_phase != 0x00) { + c->save_and_unload_character(); + c->bb_character_index = cmd.character_index; send_approve_player_choice_bb(c); } else { @@ -3631,15 +3630,33 @@ static void on_E3_BB(shared_ptr c, uint16_t, uint32_t, string& data) { return; } - auto s = c->require_server_state(); - try { - auto preview = c->character()->to_preview(); - send_player_preview_bb(c, cmd.character_index, &preview); + auto send_preview = [&c](size_t index) -> void { + c->save_and_unload_character(); + c->bb_character_index = index; + try { + auto preview = c->character()->to_preview(); + send_player_preview_bb(c, c->bb_character_index, &preview); - } catch (const exception& e) { - // Player doesn't exist - c->log.warning("Can\'t load character data: %s", e.what()); - send_player_preview_bb(c, cmd.character_index, nullptr); + } catch (const exception& e) { + // Player doesn't exist + c->log.warning("Can\'t load character data: %s", e.what()); + send_player_preview_bb(c, c->bb_character_index, nullptr); + } + }; + + if (flag == 0) { + if (cmd.character_index < 0 || cmd.character_index >= 0x80) { + throw runtime_error("client requested invalid character slot"); + } + send_preview(cmd.character_index); + } else if (cmd.character_index == 0) { + if (flag >= 0x80) { + throw runtime_error("client requested too many character slots"); + } + auto s = c->require_server_state(); + for (size_t z = 0; z < flag; z++) { + send_preview(z); + } } } } diff --git a/system/client-functions/BlueBurstExclusive/MoreSaveSlots.59NL.patch.s b/system/client-functions/BlueBurstExclusive/MoreSaveSlots.59NL.patch.s index 629ff583..78d58b3b 100644 --- a/system/client-functions/BlueBurstExclusive/MoreSaveSlots.59NL.patch.s +++ b/system/client-functions/BlueBurstExclusive/MoreSaveSlots.59NL.patch.s @@ -479,6 +479,28 @@ sig_bad: .binary CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC sig_check_end: # 006C1C76 + # Send slot count in E3 command + .data 0x0046EB20 # TDataProtocol::send_E3_for_index + .deltaof send_slot_count_in_E3_begin, send_slot_count_in_E3_end +send_slot_count_in_E3_begin: + # ecx = this (TDataProtocol*) + # [esp + 4] = slot_index + push 0 + push dword [esp + 8] # slot_index + push 0x0C # slot count + push 0x00E30010 + mov eax, esp + push 0x10 + push eax + mov eax, [ecx] + call [eax + 0x20] # this->send_command(&cmd, 0x10) // ret 8 + add esp, 8 + mov eax, 0x006C1A80 + call eax # set_current_char_slot(slot_index) // ret 0 + add esp, 8 + ret 4 +send_slot_count_in_E3_end: + # Show slot number in each menu item .data 0x00401D57 .deltaof show_slot_number_begin, show_slot_number_end