fix incorrect next item ID during game join
This commit is contained in:
@@ -4203,6 +4203,17 @@ static void on_0C_C1_E7_EC(shared_ptr<Client> c, uint16_t command, uint32_t, str
|
||||
if (game) {
|
||||
s->change_client_lobby(c, game);
|
||||
c->config.set_flag(Client::Flag::LOADING);
|
||||
|
||||
// There is a bug in DC NTE and 11/2000 that causes them to assign item IDs
|
||||
// twice when joining a game. If there are other players in the game, this
|
||||
// isn't an issue because the equivalent of the 6x6D command resets the next
|
||||
// item ID before the second assignment, so the item IDs stay in sync with
|
||||
// the server. If there was no one else in the game, however (as in this
|
||||
// case, when it was just created), we need to artificially change the next
|
||||
// item IDs during the client's loading procedure.
|
||||
if (is_pre_v1(c->version())) {
|
||||
c->config.set_flag(Client::Flag::SHOULD_SEND_ARTIFICIAL_ITEM_STATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -905,12 +905,9 @@ static void on_change_floor_6x1F(shared_ptr<Client> c, uint8_t command, uint8_t
|
||||
if (is_pre_v1(c->version())) {
|
||||
check_size_t<G_SetPlayerFloor_DCNTE_6x1F>(data, size);
|
||||
// DC NTE and 11/2000 don't send 6F when they're done loading, so we clear
|
||||
// the loading flag here instead. On these versions, it also seems to be
|
||||
// necessary to assign item IDs again here.
|
||||
// the loading flag here instead.
|
||||
if (c->config.check_flag(Client::Flag::LOADING)) {
|
||||
c->config.clear_flag(Client::Flag::LOADING);
|
||||
auto l = c->require_lobby();
|
||||
l->assign_inventory_and_bank_item_ids(c);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
+18
-1
@@ -2360,8 +2360,25 @@ void send_game_item_state(shared_ptr<Client> c) {
|
||||
|
||||
G_SyncItemState_6x6D_Decompressed decompressed_header;
|
||||
for (size_t z = 0; z < 12; z++) {
|
||||
decompressed_header.next_item_id_per_player[z] = l->next_item_id_for_client[z];
|
||||
if (z == c->lobby_client_id) {
|
||||
// If the player is joining, adjust the next item ID to use the value
|
||||
// before inventory item IDs are assigned
|
||||
size_t num_items = c->character()->inventory.num_items;
|
||||
uint32_t next_id = l->next_item_id_for_client[z] - num_items;
|
||||
if ((next_id & 0xFFE00000) != (l->next_item_id_for_client[z] & 0xFFE00000)) {
|
||||
throw runtime_error("next item ID underflow during joining player item state generation");
|
||||
}
|
||||
decompressed_header.next_item_id_per_player[z] = next_id;
|
||||
} else {
|
||||
decompressed_header.next_item_id_per_player[z] = l->next_item_id_for_client[z];
|
||||
}
|
||||
}
|
||||
l->log.info("Sending next item IDs to client: %08" PRIX32 " %08" PRIX32 " %08" PRIX32 " %08" PRIX32,
|
||||
decompressed_header.next_item_id_per_player[0].load(),
|
||||
decompressed_header.next_item_id_per_player[1].load(),
|
||||
decompressed_header.next_item_id_per_player[2].load(),
|
||||
decompressed_header.next_item_id_per_player[3].load());
|
||||
|
||||
for (size_t floor = 0; floor < 0x10; floor++) {
|
||||
const auto& m = l->floor_item_managers.at(floor);
|
||||
for (const auto& it : m.queue_for_client.at(c->lobby_client_id)) {
|
||||
|
||||
Reference in New Issue
Block a user