implement player records command

This commit is contained in:
Martin Michelsen
2023-07-09 16:22:11 -07:00
parent 7dd00c75a9
commit b1531139c0
25 changed files with 478 additions and 111 deletions
+49 -21
View File
@@ -632,10 +632,8 @@ void send_complete_player_bb(shared_ptr<Client> c) {
cmd.shortcuts = account->shortcuts;
cmd.auto_reply = player->auto_reply;
cmd.info_board = player->info_board;
cmd.battle_records.place_counts.clear(0);
cmd.battle_records.disconnect_count = 0;
cmd.battle_records.unknown_a1.clear(0);
cmd.unknown_a4 = 0;
cmd.battle_records = player->battle_records;
cmd.unknown_a4.clear(0);
cmd.challenge_records = player->challenge_records;
cmd.tech_menu_config = player->tech_menu_config;
cmd.unknown_a6.clear(0);
@@ -1383,6 +1381,30 @@ void send_lobby_list(shared_ptr<Client> c, shared_ptr<ServerState> s) {
////////////////////////////////////////////////////////////////////////////////
// lobby joining
template <typename EntryT>
void send_player_records(shared_ptr<Client> c, shared_ptr<Lobby> l, shared_ptr<Client> joining_client) {
vector<EntryT> entries;
auto add_client = [&](shared_ptr<Client> lc) -> void {
auto lp = lc->game_data.player();
auto& e = entries.emplace_back();
e.client_id = lc->lobby_client_id;
e.challenge = lp->challenge_records;
e.battle = lp->battle_records;
};
if (joining_client) {
add_client(joining_client);
} else {
entries.reserve(12);
for (auto lc : l->clients) {
if (lc) {
add_client(lc);
}
}
}
send_command_vt(c->channel, 0xC5, entries.size(), entries);
}
static void send_join_spectator_team(shared_ptr<Client> c, shared_ptr<Lobby> l) {
if (!(c->flags & Client::Flag::IS_EPISODE_3)) {
throw runtime_error("lobby is not Episode 3");
@@ -1598,7 +1620,7 @@ void send_join_game_dc_nte(shared_ptr<Client> c, shared_ptr<Lobby> l) {
send_command_t(c, 0x64, player_count, cmd);
}
template <typename LobbyDataT, typename DispDataT>
template <typename LobbyDataT, typename DispDataT, typename RecordsT>
void send_join_lobby_t(shared_ptr<Client> c, shared_ptr<Lobby> l,
shared_ptr<Client> joining_client = nullptr) {
uint8_t command;
@@ -1612,6 +1634,10 @@ void send_join_lobby_t(shared_ptr<Client> c, shared_ptr<Lobby> l,
command = joining_client ? 0x68 : 0x67;
}
if ((c->version() != GameVersion::DC) || !(c->flags & Client::Flag::IS_DC_V1)) {
send_player_records<RecordsT>(c, l, joining_client);
}
uint8_t lobby_type = (l->type > 14) ? (l->block - 1) : l->type;
// Allow non-canonical lobby types on GC. They may work on other versions too,
// but I haven't verified which values don't crash on each version.
@@ -1745,23 +1771,24 @@ void send_join_lobby(shared_ptr<Client> c, shared_ptr<Lobby> l) {
}
} else {
switch (c->version()) {
case GameVersion::PC:
send_join_lobby_t<PlayerLobbyDataPC, PlayerDispDataDCPCV3>(c, l);
break;
case GameVersion::DC:
if (c->flags & (Client::Flag::IS_TRIAL_EDITION | Client::Flag::IS_DC_V1_PROTOTYPE)) {
send_join_lobby_dc_nte(c, l);
break;
} else {
send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_DC>(c, l);
}
[[fallthrough]];
break;
case GameVersion::PC:
send_join_lobby_t<PlayerLobbyDataPC, PlayerDispDataDCPCV3, PlayerRecordsEntry_PC>(c, l);
break;
case GameVersion::GC:
send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3>(c, l);
send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_V3>(c, l);
break;
case GameVersion::XB:
send_join_lobby_t<PlayerLobbyDataXB, PlayerDispDataDCPCV3>(c, l);
send_join_lobby_t<PlayerLobbyDataXB, PlayerDispDataDCPCV3, PlayerRecordsEntry_V3>(c, l);
break;
case GameVersion::BB:
send_join_lobby_t<PlayerLobbyDataBB, PlayerDispDataBB>(c, l);
send_join_lobby_t<PlayerLobbyDataBB, PlayerDispDataBB, PlayerRecordsEntry_BB>(c, l);
break;
default:
throw logic_error("unimplemented versioned command");
@@ -1779,23 +1806,24 @@ void send_join_lobby(shared_ptr<Client> c, shared_ptr<Lobby> l) {
void send_player_join_notification(shared_ptr<Client> c,
shared_ptr<Lobby> l, shared_ptr<Client> joining_client) {
switch (c->version()) {
case GameVersion::PC:
send_join_lobby_t<PlayerLobbyDataPC, PlayerDispDataDCPCV3>(c, l, joining_client);
break;
case GameVersion::DC:
if (c->flags & (Client::Flag::IS_TRIAL_EDITION | Client::Flag::IS_DC_V1_PROTOTYPE)) {
send_join_lobby_dc_nte(c, l, joining_client);
break;
} else {
send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_DC>(c, l, joining_client);
}
[[fallthrough]];
break;
case GameVersion::PC:
send_join_lobby_t<PlayerLobbyDataPC, PlayerDispDataDCPCV3, PlayerRecordsEntry_PC>(c, l, joining_client);
break;
case GameVersion::GC:
send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3>(c, l, joining_client);
send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_V3>(c, l, joining_client);
break;
case GameVersion::XB:
send_join_lobby_t<PlayerLobbyDataXB, PlayerDispDataDCPCV3>(c, l, joining_client);
send_join_lobby_t<PlayerLobbyDataXB, PlayerDispDataDCPCV3, PlayerRecordsEntry_V3>(c, l, joining_client);
break;
case GameVersion::BB:
send_join_lobby_t<PlayerLobbyDataBB, PlayerDispDataBB>(c, l, joining_client);
send_join_lobby_t<PlayerLobbyDataBB, PlayerDispDataBB, PlayerRecordsEntry_BB>(c, l, joining_client);
break;
default:
throw logic_error("unimplemented versioned command");