implement $switchchar command

This commit is contained in:
Martin Michelsen
2025-08-14 23:44:16 -07:00
parent 16bff52575
commit 377d8beac3
2 changed files with 41 additions and 0 deletions
+1
View File
@@ -604,6 +604,7 @@ Some commands only work for clients not in proxy sessions. The chat commands are
* `$patch <name>`: Run a patch on your client. `<name>` must exactly match the name of a patch on the server.
* Character data commands (non-proxy only)
* `$switchchar <slot>` (BB only): Switch to a different character from your account without logging out.
* `$savechar <slot>`: Save your current character data on the server in the specified slot. See the [server-side saves section](#server-side-saves) for more details.
* `$loadchar <slot>`: Load character data from the specified slot on the server, and replace your current character with it. See the [server-side saves section](#server-side-saves) for more details.
* `$bbchar <username> <password> <slot>`: Save your current character data on the server in a different account's BB character slots. See the [server-side saves section](#server-side-saves) for more details.
+40
View File
@@ -2640,6 +2640,46 @@ ChatCommandDefinition cc_swsetall(
co_return;
});
ChatCommandDefinition cc_switchchar(
{"$switchchar"},
+[](const Args& a) -> asio::awaitable<void> {
auto l = a.c->require_lobby();
auto s = a.c->require_server_state();
a.check_is_proxy(false);
a.check_is_game(false);
if (a.c->version() != Version::BB_V4) {
throw precondition_failed("This command can only\nbe used on BB");
}
int32_t index = stol(a.text, nullptr, 0) - 1;
if (index < 0) {
throw precondition_failed("Invalid slot number");
}
auto filename = Client::character_filename(a.c->login->bb_license->username, index);
if (!std::filesystem::is_regular_file(filename)) {
throw precondition_failed("No character exists\nin that slot");
}
a.c->save_and_unload_character();
a.c->bb_character_index = index;
// TODO: This can trigger a client bug where the previous character's
// name label object isn't deleted if the leave and join notifications
// are received on the same frame. This results in the receiving player
// seeing both labels over the new character, with the latest one
// appearing on top. We could fix this by requiring each recipient to
// reply to a ping between the two commands, similar to how the 64 and
// 6x6D commands are split during game joining, but implementing that
// here seems not worth the effort given the low likelihood and impact of
// this bug.
send_complete_player_bb(a.c);
send_player_leave_notification(l, a.c->lobby_client_id);
s->send_lobby_join_notifications(l, a.c);
co_return;
});
ChatCommandDefinition cc_unset(
{"$unset"},
+[](const Args& a) -> asio::awaitable<void> {