fix data race in 6xCA command
This commit is contained in:
@@ -3535,8 +3535,35 @@ void on_item_reward_request_bb(shared_ptr<Client> c, uint8_t, uint8_t, void* dat
|
|||||||
item = cmd.item_data;
|
item = cmd.item_data;
|
||||||
item.enforce_min_stack_size(limits);
|
item.enforce_min_stack_size(limits);
|
||||||
item.id = l->generate_item_id(c->lobby_client_id);
|
item.id = l->generate_item_id(c->lobby_client_id);
|
||||||
c->character()->add_item(item, limits);
|
|
||||||
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item);
|
// The logic for the item_create and item_create2 opcodes (B3 and B4)
|
||||||
|
// includes a precondition check to see if the player can actually add the
|
||||||
|
// item to their inventory or not, and the entire command is skipped if not.
|
||||||
|
// However, on BB, the implementation performs this check and sends a 6xCA
|
||||||
|
// command instead - the item is not immediately added to the inventory, and
|
||||||
|
// is instead added when the server sends back a 6xBE command. So if a quest
|
||||||
|
// creates multiple items in quick succession, there may be another 6xCA/6xBE
|
||||||
|
// sequence in flight, and the client's check if an item can be created may
|
||||||
|
// pass when a 6xBE command that would make it fail is already on the way
|
||||||
|
// from the server. To handle this, we simply ignore any 6xCA command if the
|
||||||
|
// item can't be created.
|
||||||
|
try {
|
||||||
|
c->character()->add_item(item, limits);
|
||||||
|
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item);
|
||||||
|
if (l->log.should_log(LogLevel::INFO)) {
|
||||||
|
auto name = s->describe_item(c->version(), item, false);
|
||||||
|
l->log.info("Player %hu created inventory item %08" PRIX32 " (%s) via quest command",
|
||||||
|
c->lobby_client_id, item.id.load(), name.c_str());
|
||||||
|
c->print_inventory(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (const out_of_range&) {
|
||||||
|
if (l->log.should_log(LogLevel::INFO)) {
|
||||||
|
auto name = s->describe_item(c->version(), item, false);
|
||||||
|
l->log.info("Player %hu attempted to create inventory item %08" PRIX32 " (%s) via quest command, but it cannot be placed in their inventory",
|
||||||
|
c->lobby_client_id, item.id.load(), name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_transfer_item_via_mail_message_bb(shared_ptr<Client> c, uint8_t command, uint8_t flag, void* data, size_t size) {
|
void on_transfer_item_via_mail_message_bb(shared_ptr<Client> c, uint8_t command, uint8_t flag, void* data, size_t size) {
|
||||||
|
|||||||
Reference in New Issue
Block a user