fix 6x70 handling in dc/pc cross-play
This commit is contained in:
@@ -4547,8 +4547,11 @@ struct G_Unknown_6x6F {
|
|||||||
// 6x70: Sync player disp data and inventory (used while loading into game)
|
// 6x70: Sync player disp data and inventory (used while loading into game)
|
||||||
// Annoyingly, they didn't use the same format as the 65/67/68 commands here,
|
// Annoyingly, they didn't use the same format as the 65/67/68 commands here,
|
||||||
// and instead rearranged a bunch of things.
|
// and instead rearranged a bunch of things.
|
||||||
|
// The format appears to be the same for all pre-BB PSO versions, although
|
||||||
|
// Episode 3 does not send this command at all since the relevant data is sent
|
||||||
|
// tothe joining player in the 64 command instead.
|
||||||
|
|
||||||
struct G_SyncPlayerDispAndInventory_V3_6x70 {
|
struct G_SyncPlayerDispAndInventory_DC_PC_V3_6x70 {
|
||||||
G_ExtendedHeader<G_UnusedHeader> header;
|
G_ExtendedHeader<G_UnusedHeader> header;
|
||||||
// Offsets in this struct are relative to the overall command header
|
// Offsets in this struct are relative to the overall command header
|
||||||
/* 000C */ le_uint16_t client_id;
|
/* 000C */ le_uint16_t client_id;
|
||||||
|
|||||||
+29
-25
@@ -243,9 +243,12 @@ static void on_sync_joining_player_item_state(shared_ptr<Client> c, uint8_t comm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_sync_joining_player_disp_and_inventory(shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
static void on_sync_joining_player_disp_and_inventory(
|
||||||
|
shared_ptr<Client> c, uint8_t command, uint8_t flag, const void* data, size_t size) {
|
||||||
auto l = c->require_lobby();
|
auto l = c->require_lobby();
|
||||||
if (!l->is_game() || !l->any_client_loading()) {
|
// In V1/V2 games, this command sometimes is sent after the new client has
|
||||||
|
// finished loading, so we don't check l->any_client_loading() here.
|
||||||
|
if (!l->is_game()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,33 +257,34 @@ static void on_sync_joining_player_disp_and_inventory(shared_ptr<Client> c, uint
|
|||||||
if (!command_is_private(command)) {
|
if (!command_is_private(command)) {
|
||||||
throw runtime_error("6x70 sent via public command");
|
throw runtime_error("6x70 sent via public command");
|
||||||
}
|
}
|
||||||
|
if (flag >= l->max_clients) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto target = l->clients[flag];
|
||||||
|
if (!target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// For non-V3 versions, just forward the data verbatim. For V3, we need to
|
// This command's format is different on BB and non-BB
|
||||||
// byteswap mags' data2 fields if exactly one of the sender and recipient are
|
bool sender_is_bb = (c->version() == GameVersion::BB);
|
||||||
// PSO GC
|
bool target_is_bb = (target->version() == GameVersion::BB);
|
||||||
|
if (sender_is_bb != target_is_bb) {
|
||||||
|
// TODO: Figure out the BB 6x70 format and implement this
|
||||||
|
throw runtime_error("6x70 command cannot be translated across BB boundary");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to byteswap mags' data2 fields if exactly one of the sender and
|
||||||
|
// recipient are PSO GC
|
||||||
bool sender_is_gc = (c->version() == GameVersion::GC);
|
bool sender_is_gc = (c->version() == GameVersion::GC);
|
||||||
if (!sender_is_gc && (c->version() != GameVersion::XB)) {
|
bool target_is_gc = (target->version() == GameVersion::GC);
|
||||||
forward_subcommand(c, command, flag, data, size);
|
if (target_is_gc == sender_is_gc) {
|
||||||
|
send_command(target, command, flag, data, size);
|
||||||
} else {
|
} else {
|
||||||
if (flag >= l->max_clients) {
|
auto out_cmd = check_size_t<G_SyncPlayerDispAndInventory_DC_PC_V3_6x70>(data, size);
|
||||||
return;
|
for (size_t z = 0; z < 30; z++) {
|
||||||
}
|
out_cmd.inventory.items[z].data.bswap_data2_if_mag();
|
||||||
auto target = l->clients[flag];
|
|
||||||
if (!target) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bool target_is_gc = (target->version() == GameVersion::GC);
|
|
||||||
|
|
||||||
if (target_is_gc == sender_is_gc) {
|
|
||||||
send_command(target, command, flag, data, size);
|
|
||||||
} else {
|
|
||||||
auto out_cmd = check_size_t<G_SyncPlayerDispAndInventory_V3_6x70>(data, size);
|
|
||||||
for (size_t z = 0; z < 30; z++) {
|
|
||||||
out_cmd.inventory.items[z].data.bswap_data2_if_mag();
|
|
||||||
}
|
|
||||||
send_command_t(target, command, flag, out_cmd);
|
|
||||||
}
|
}
|
||||||
|
send_command_t(target, command, flag, out_cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user