refine more commands

This commit is contained in:
Martin Michelsen
2025-01-23 09:51:48 -08:00
parent 2e6e1adcf3
commit 65a1b97093
4 changed files with 31 additions and 24 deletions
+4 -4
View File
@@ -2538,7 +2538,7 @@ static void server_command_swset_swclear(const ServerArgs& a, bool should_set) {
}
uint8_t cmd_flags = should_set ? 0x01 : 0x00;
G_SwitchStateChanged_6x05 cmd = {{0x05, 0x03, 0xFFFF}, 0, 0, flag_num, floor, cmd_flags};
G_WriteSwitchFlag_6x05 cmd = {{0x05, 0x03, 0xFFFF}, 0, 0, flag_num, floor, cmd_flags};
send_command_t(l, 0x60, 0x00, cmd);
}
@@ -2560,7 +2560,7 @@ static void proxy_command_swset_swclear(const ProxyArgs& a, bool should_set) {
}
uint8_t cmd_flags = should_set ? 0x01 : 0x00;
G_SwitchStateChanged_6x05 cmd = {{0x05, 0x03, 0xFFFF}, 0, 0, flag_num, floor, cmd_flags};
G_WriteSwitchFlag_6x05 cmd = {{0x05, 0x03, 0xFFFF}, 0, 0, flag_num, floor, cmd_flags};
a.ses->client_channel.send(0x60, 0x00, &cmd, sizeof(cmd));
a.ses->server_channel.send(0x60, 0x00, &cmd, sizeof(cmd));
}
@@ -2595,7 +2595,7 @@ ChatCommandDefinition cc_swsetall(
l->switch_flags->data[a.c->floor].clear(0xFF);
parray<G_SwitchStateChanged_6x05, 0x100> cmds;
parray<G_WriteSwitchFlag_6x05, 0x100> cmds;
for (size_t z = 0; z < cmds.size(); z++) {
auto& cmd = cmds[z];
cmd.header.subcommand = 0x05;
@@ -2613,7 +2613,7 @@ ChatCommandDefinition cc_swsetall(
throw precondition_failed("$C6This command cannot\nbe used in the lobby");
}
parray<G_SwitchStateChanged_6x05, 0x100> cmds;
parray<G_WriteSwitchFlag_6x05, 0x100> cmds;
for (size_t z = 0; z < cmds.size(); z++) {
auto& cmd = cmds[z];
cmd.header.subcommand = 0x05;
+24 -17
View File
@@ -2458,7 +2458,7 @@ struct S_TournamentSpectatorTeamList_Ep3_BB {
uint8_t locked = 0;
uint8_t count = 0;
uint8_t max_count = 0;
uint8_t unknown_a1 = 0; // Possibly unused
uint8_t unused = 0;
} __packed_ws__(GameEntry, 0x24);
/* 04A4 */ parray<GameEntry, 0x40> match_entries;
/* 0DA4 */
@@ -2818,19 +2818,19 @@ struct C_VerifyAccount_BB_DB {
// DC: Guild card data (BB)
struct S_GuildCardHeader_BB_01DC {
le_uint32_t unknown = 1;
le_uint32_t filesize = 0x0000D590;
le_uint32_t unknown_a1 = 1;
le_uint32_t file_size = 0x0000D590;
le_uint32_t checksum = 0; // CRC32 of entire guild card file (0xD590 bytes)
} __packed_ws__(S_GuildCardHeader_BB_01DC, 0x0C);
struct S_GuildCardFileChunk_02DC {
le_uint32_t unknown = 0; // 0
le_uint32_t unknown_a1 = 0; // Must NOT match unknown_a1 from 01DC
le_uint32_t chunk_index = 0;
parray<uint8_t, 0x6800> data; // Command may be shorter if this is the last chunk
} __packed_ws__(S_GuildCardFileChunk_02DC, 0x6808);
struct C_GuildCardDataRequest_BB_03DC {
le_uint32_t unknown = 0;
le_uint32_t unknown_a1 = 0; // Matches unknown_a1 from 01DC
le_uint32_t chunk_index = 0;
le_uint32_t cont = 0;
} __packed_ws__(C_GuildCardDataRequest_BB_03DC, 0x0C);
@@ -3127,7 +3127,7 @@ struct S_CardBattleTableState_Ep3_E4 {
// 2 = player present, confirmed
// 3 = player present, declined
le_uint16_t state = 0;
le_uint16_t unknown_a1 = 0;
le_uint16_t unused = 0;
le_uint32_t guild_card_number = 0;
} __packed_ws__(Entry, 8);
parray<Entry, 4> entries;
@@ -3154,7 +3154,10 @@ struct S_CardBattleTableConfirmation_Ep3_E5 {
} __packed_ws__(S_CardBattleTableConfirmation_Ep3_E5, 4);
// E5 (S->C): Player preview (BB)
// E5 (C->S): Create character (BB)
// E5 (C->S): Create character or apply dressing room updates (BB)
// In the C->S case, the server can know whether it's a new character or
// dressing room updates based on the value of connection_phase from the 93
// command.
struct SC_PlayerPreview_CreateCharacter_BB_00E5 {
le_int32_t character_index = 0;
@@ -3437,7 +3440,7 @@ struct S_TeamMemberList_BB_09EA {
} __packed_ws__(S_TeamMemberList_BB_09EA, 4);
// 0CEA (S->C): Unknown
// The client appears to ignore this command.
// The client ignores this command.
struct S_Unknown_BB_0CEA {
parray<uint8_t, 0x20> unknown_a1;
@@ -3894,8 +3897,8 @@ struct G_ExtendedHeaderT {
// 6x02: Unknown
// 6x03: Unknown
// These subcommands are completely ignored on V3 and later.
// On all known DC versions (NTE through V2), these commands writes their
// contents to a global array, but nothing reads from this array.
// On all known DC versions (NTE through V2), the contents of these commands
// are written to a global array, but nothing reads from this array.
struct G_Unknown_6x02_6x03 {
G_ClientIDHeader header;
@@ -3906,8 +3909,11 @@ struct G_Unknown_6x02_6x03 {
le_float unknown_a5;
} __packed_ws__(G_Unknown_6x02_6x03, 0x14);
// 6x04: Unknown
// TODO: This does something with TObjDoorKey objects
// 6x04: Activate switch by token (deprecated)
// This appears to be an early version of 6x0B; it only affects TObjDoorKey
// objects and can only activate them, not deactivate them. 6x0B is much more
// versatile and is used instead in all known versions of the game. This
// command is likely a relic from pre-NTE development.
struct G_Unknown_6x04 {
G_ParameterHeader header; // param = door token (NOT entity ID or index)
@@ -3915,27 +3921,27 @@ struct G_Unknown_6x04 {
le_uint16_t unused2 = 0;
} __packed_ws__(G_Unknown_6x04, 8);
// 6x05: Switch state changed
// 6x05: Write switch flag
// Some things that don't look like switches are implemented as switches using
// this subcommand. For example, when all enemies in a room are defeated, this
// subcommand is used to unlock the doors.
// Note: In the client, this is a subclass of 6x04, similar to how 6xA2 is a
// subclass of 6x60.
struct G_SwitchStateChanged_6x05 {
struct G_WriteSwitchFlag_6x05 {
// Note: header.object_id is 0xFFFF for room clear when all enemies defeated
G_EntityIDHeader header;
// TODO: Some of these might be big-endian on GC; it only byteswaps
// switch_flag_num. Are the others actually uint16, or are they uint8[2]?
le_uint16_t client_id = 0;
le_uint16_t unknown_a2 = 0;
le_uint16_t unused = 0;
le_uint16_t switch_flag_num = 0;
uint8_t switch_flag_floor = 0;
// Only two bits in flags have meanings:
// 01 - set unlock flag (if not set, the flag is cleared instead)
// 01 - set switch flag (if not set, the flag is cleared instead)
// 02 - play room unlock sound if floor matches client's floor
uint8_t flags = 0;
} __packed_ws__(G_SwitchStateChanged_6x05, 0x0C);
} __packed_ws__(G_WriteSwitchFlag_6x05, 0x0C);
// 6x06: Send guild card
@@ -3988,6 +3994,7 @@ struct G_SymbolChat_6x07 {
// 6x08: Invalid subcommand
// 6x09: Unknown
// header.entity_id is expected to be an enemy ID.
struct G_Unknown_6x09 {
G_EntityIDHeader header;
+1 -1
View File
@@ -2033,7 +2033,7 @@ template <>
HandlerResult C_6x<void>(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t, uint32_t, string& data) {
if (!data.empty()) {
if ((data[0] == 0x05) && ses->config.check_flag(Client::Flag::SWITCH_ASSIST_ENABLED)) {
auto& cmd = check_size_t<G_SwitchStateChanged_6x05>(data);
auto& cmd = check_size_t<G_WriteSwitchFlag_6x05>(data);
if (ses->map_state && (cmd.flags & 1) && (cmd.header.entity_id != 0xFFFF)) {
auto door_states = ses->map_state->door_states_for_switch_flag(
ses->version(), cmd.switch_flag_floor, cmd.switch_flag_num);
+2 -2
View File
@@ -1727,7 +1727,7 @@ static void on_npc_control(shared_ptr<Client> c, uint8_t command, uint8_t flag,
}
static void on_switch_state_changed(shared_ptr<Client> c, uint8_t command, uint8_t flag, void* data, size_t size) {
auto& cmd = check_size_t<G_SwitchStateChanged_6x05>(data, size);
auto& cmd = check_size_t<G_WriteSwitchFlag_6x05>(data, size);
auto l = c->require_lobby();
if (!l->is_game()) {
@@ -1793,7 +1793,7 @@ static void on_switch_state_changed(shared_ptr<Client> c, uint8_t command, uint8
}
}
forward_subcommand_with_entity_id_transcode_t<G_SwitchStateChanged_6x05, true>(c, command, flag, data, size);
forward_subcommand_with_entity_id_transcode_t<G_WriteSwitchFlag_6x05, true>(c, command, flag, data, size);
}
static void on_play_sound_from_player(shared_ptr<Client> c, uint8_t command, uint8_t flag, void* data, size_t size) {