document the CARD lobby battle table commands
This commit is contained in:
@@ -53,6 +53,8 @@ Client::Client(
|
|||||||
bufferevent_get_base(bev), -1, EV_TIMEOUT | EV_PERSIST,
|
bufferevent_get_base(bev), -1, EV_TIMEOUT | EV_PERSIST,
|
||||||
&Client::dispatch_save_game_data, this),
|
&Client::dispatch_save_game_data, this),
|
||||||
event_free),
|
event_free),
|
||||||
|
card_battle_table_number(-1),
|
||||||
|
card_battle_table_seat_number(0),
|
||||||
next_exp_value(0),
|
next_exp_value(0),
|
||||||
override_section_id(-1),
|
override_section_id(-1),
|
||||||
override_random_seed(-1),
|
override_random_seed(-1),
|
||||||
|
|||||||
@@ -105,6 +105,8 @@ struct Client {
|
|||||||
int64_t preferred_lobby_id; // <0 = no preference
|
int64_t preferred_lobby_id; // <0 = no preference
|
||||||
ClientGameData game_data;
|
ClientGameData game_data;
|
||||||
std::unique_ptr<struct event, void(*)(struct event*)> save_game_data_event;
|
std::unique_ptr<struct event, void(*)(struct event*)> save_game_data_event;
|
||||||
|
int16_t card_battle_table_number;
|
||||||
|
uint8_t card_battle_table_seat_number;
|
||||||
|
|
||||||
// Miscellaneous (used by chat commands)
|
// Miscellaneous (used by chat commands)
|
||||||
uint32_t next_exp_value; // next EXP value to give
|
uint32_t next_exp_value; // next EXP value to give
|
||||||
|
|||||||
@@ -2430,10 +2430,12 @@ struct S_PlayerPreview_NoPlayer_BB_00E4 {
|
|||||||
le_uint32_t error; // 2 = no player present
|
le_uint32_t error; // 2 = no player present
|
||||||
};
|
};
|
||||||
|
|
||||||
// E5 (C->S): Unknown (CARD lobby battle table) (Episode 3)
|
// E5 (C->S): Confirm CARD lobby battle table choice (Episode 3)
|
||||||
|
// header.flag specifies whether the client answered "Yes" (1) or "No" (0).
|
||||||
|
|
||||||
struct S_CardBattleTable_Unknown_GC_Ep3_E5 {
|
struct S_CardBattleTableConfirmation_GC_Ep3_E5 {
|
||||||
le_uint32_t unknown_a1;
|
le_uint16_t table_number;
|
||||||
|
le_uint16_t seat_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
// E5 (S->C): Player preview (BB)
|
// E5 (S->C): Player preview (BB)
|
||||||
|
|||||||
+37
-2
@@ -770,6 +770,41 @@ static void on_ep3_meseta_transaction(shared_ptr<ServerState>,
|
|||||||
send_command(c, command, 0x03, &out_cmd, sizeof(out_cmd));
|
send_command(c, command, 0x03, &out_cmd, sizeof(out_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_ep3_battle_table_state(shared_ptr<ServerState> s,
|
||||||
|
shared_ptr<Client> c, uint16_t, uint32_t flag, const string& data) { // E4
|
||||||
|
const auto& cmd = check_size_t<C_CardBattleTableState_GC_Ep3_E4>(data);
|
||||||
|
auto l = s->find_lobby(c->lobby_id);
|
||||||
|
if (l->is_game() || !(l->flags & Lobby::Flag::EPISODE_3_ONLY)) {
|
||||||
|
throw runtime_error("battle table command sent in non-CARD lobby");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
c->card_battle_table_number = cmd.table_number;
|
||||||
|
c->card_battle_table_seat_number = cmd.seat_number;
|
||||||
|
} else {
|
||||||
|
c->card_battle_table_number = -1;
|
||||||
|
c->card_battle_table_seat_number = 0;
|
||||||
|
}
|
||||||
|
send_ep3_card_battle_table_state(l, c->card_battle_table_number);
|
||||||
|
// TODO: If a client disconnects while at the battle table, we need to send
|
||||||
|
// a table update to all the other clients at the table (if any). Use a
|
||||||
|
// disconnect hook for this.
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_ep3_battle_table_confirm(shared_ptr<ServerState> s,
|
||||||
|
shared_ptr<Client> c, uint16_t, uint32_t flag, const string& data) { // E4
|
||||||
|
check_size_t<S_CardBattleTableConfirmation_GC_Ep3_E5>(data);
|
||||||
|
auto l = s->find_lobby(c->lobby_id);
|
||||||
|
if (l->is_game() || !(l->flags & Lobby::Flag::EPISODE_3_ONLY)) {
|
||||||
|
throw runtime_error("battle table command sent in non-CARD lobby");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
// TODO
|
||||||
|
send_lobby_message_box(c, u"CARD battles are\nnot yet supported.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void on_ep3_counter_state(shared_ptr<ServerState>, shared_ptr<Client> c,
|
static void on_ep3_counter_state(shared_ptr<ServerState>, shared_ptr<Client> c,
|
||||||
uint16_t, uint32_t flag, const string& data) { // DC
|
uint16_t, uint32_t flag, const string& data) { // DC
|
||||||
check_size_v(data.size(), 0);
|
check_size_v(data.size(), 0);
|
||||||
@@ -3226,8 +3261,8 @@ static on_command_t handlers[0x100][6] = {
|
|||||||
/* E1 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, }, /* E1 */
|
/* E1 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, }, /* E1 */
|
||||||
/* E2 */ {nullptr, nullptr, nullptr, on_ep3_tournament_control, nullptr, on_update_key_config_bb, }, /* E2 */
|
/* E2 */ {nullptr, nullptr, nullptr, on_ep3_tournament_control, nullptr, on_update_key_config_bb, }, /* E2 */
|
||||||
/* E3 */ {nullptr, nullptr, nullptr, nullptr, nullptr, on_player_preview_request_bb, }, /* E3 */
|
/* E3 */ {nullptr, nullptr, nullptr, nullptr, nullptr, on_player_preview_request_bb, }, /* E3 */
|
||||||
/* E4 */ {nullptr, nullptr, nullptr, on_ignored_command, nullptr, nullptr, }, /* E4 */
|
/* E4 */ {nullptr, nullptr, nullptr, on_ep3_battle_table_state, nullptr, nullptr, }, /* E4 */
|
||||||
/* E5 */ {nullptr, nullptr, nullptr, nullptr, nullptr, on_create_character_bb, }, /* E5 */
|
/* E5 */ {nullptr, nullptr, nullptr, on_ep3_battle_table_confirm, nullptr, on_create_character_bb, }, /* E5 */
|
||||||
/* E6 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, }, /* E6 */
|
/* E6 */ {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, }, /* E6 */
|
||||||
/* E7 */ {nullptr, nullptr, nullptr, nullptr, nullptr, on_return_player_data_bb, }, /* E7 */
|
/* E7 */ {nullptr, nullptr, nullptr, nullptr, nullptr, on_return_player_data_bb, }, /* E7 */
|
||||||
/* E8 */ {nullptr, nullptr, nullptr, nullptr, nullptr, on_client_checksum_bb, }, /* E8 */
|
/* E8 */ {nullptr, nullptr, nullptr, nullptr, nullptr, on_client_checksum_bb, }, /* E8 */
|
||||||
|
|||||||
@@ -1649,6 +1649,38 @@ void send_ep3_map_data(shared_ptr<ServerState> s, shared_ptr<Lobby> l, uint32_t
|
|||||||
send_command(l, 0x6C, 0x00, w.str());
|
send_command(l, 0x6C, 0x00, w.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void send_ep3_card_battle_table_state(shared_ptr<Lobby> l, uint16_t table_number) {
|
||||||
|
S_CardBattleTableState_GC_Ep3_E4 cmd;
|
||||||
|
for (size_t z = 0; z < 4; z++) {
|
||||||
|
cmd.entries[z].present = 0;
|
||||||
|
cmd.entries[z].unknown_a1 = 0;
|
||||||
|
cmd.entries[z].guild_card_number = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
set<shared_ptr<Client>> clients;
|
||||||
|
for (const auto& c : l->clients) {
|
||||||
|
if (!c) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c->card_battle_table_number == table_number) {
|
||||||
|
if (c->card_battle_table_seat_number > 3) {
|
||||||
|
throw runtime_error("invalid battle table seat number");
|
||||||
|
}
|
||||||
|
auto& e = cmd.entries[c->card_battle_table_seat_number];
|
||||||
|
if (e.present) {
|
||||||
|
throw runtime_error("multiple clients in the same battle table seat");
|
||||||
|
}
|
||||||
|
e.present = 1;
|
||||||
|
e.guild_card_number = c->license->serial_number;
|
||||||
|
clients.emplace(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& c : clients) {
|
||||||
|
send_command_t(c, 0xE4, table_number, cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void set_mask_for_ep3_game_command(void* vdata, size_t size, uint8_t mask_key) {
|
void set_mask_for_ep3_game_command(void* vdata, size_t size, uint8_t mask_key) {
|
||||||
if (size < 8) {
|
if (size < 8) {
|
||||||
throw logic_error("Episode 3 game command is too short for masking");
|
throw logic_error("Episode 3 game command is too short for masking");
|
||||||
|
|||||||
@@ -264,6 +264,7 @@ void send_ep3_map_list(
|
|||||||
std::shared_ptr<ServerState> s, std::shared_ptr<Lobby> l);
|
std::shared_ptr<ServerState> s, std::shared_ptr<Lobby> l);
|
||||||
void send_ep3_map_data(
|
void send_ep3_map_data(
|
||||||
std::shared_ptr<ServerState> s, std::shared_ptr<Lobby> l, uint32_t map_id);
|
std::shared_ptr<ServerState> s, std::shared_ptr<Lobby> l, uint32_t map_id);
|
||||||
|
void send_ep3_card_battle_table_state(std::shared_ptr<Lobby> l, uint16_t table_number);
|
||||||
|
|
||||||
// Pass mask_key = 0 to unmask the command
|
// Pass mask_key = 0 to unmask the command
|
||||||
void set_mask_for_ep3_game_command(void* vdata, size_t size, uint8_t mask_key);
|
void set_mask_for_ep3_game_command(void* vdata, size_t size, uint8_t mask_key);
|
||||||
|
|||||||
Reference in New Issue
Block a user