From b492a2fac61ab53c08abb9435df1b5dfacc188f2 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Wed, 15 Nov 2023 18:14:04 -0800 Subject: [PATCH] handle rejected tekker results properly --- src/Items.cc | 2 +- src/ReceiveSubcommands.cc | 29 +++++++++++++++++------------ src/SendCommands.cc | 9 +-------- src/SendCommands.hh | 2 +- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/Items.cc b/src/Items.cc index 156b5dfa..a938c279 100644 --- a/src/Items.cc +++ b/src/Items.cc @@ -194,7 +194,7 @@ void player_use_item(shared_ptr c, size_t item_index) { auto l = c->lobby.lock(); if (l) { - send_create_inventory_item(c, item.data, false); + send_create_inventory_item(c, item.data); } break; } diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index 1e5e7949..68289561 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -1384,7 +1384,7 @@ static void on_ep3_private_word_select_bb_bank_action(shared_ptr c, uint auto item = p->bank.remove_item(cmd.item_id, cmd.item_amount); item.id = l->generate_item_id(c->lobby_client_id); p->add_item(item); - send_create_inventory_item(c, item, true); + send_create_inventory_item(c, item); string name = s->item_name_index->describe_item(GameVersion::BB, item); l->log.info("Player %hu withdrew item %08" PRIX32 " (x%hhu) (%s) from the bank", @@ -1997,7 +1997,7 @@ void on_meseta_reward_request_bb(shared_ptr c, uint8_t, uint8_t, const v item.data2d = cmd.amount.load(); item.id = l->generate_item_id(c->lobby_client_id); p->add_item(item); - send_create_inventory_item(c, item, true); + send_create_inventory_item(c, item); } } @@ -2009,7 +2009,7 @@ void on_item_reward_request_bb(shared_ptr c, uint8_t, uint8_t, const voi item = cmd.item_data; item.id = l->generate_item_id(c->lobby_client_id); c->game_data.character()->add_item(item); - send_create_inventory_item(c, item, true); + send_create_inventory_item(c, item); } static void on_destroy_inventory_item(shared_ptr c, uint8_t command, uint8_t flag, const void* data, size_t size) { @@ -2080,9 +2080,14 @@ static void on_identify_item_bb(shared_ptr c, uint8_t command, uint8_t f auto p = c->game_data.character(); size_t x = p->inventory.find_item(cmd.item_id); if (p->inventory.items[x].data.data1[0] != 0) { - return; // Only weapons can be identified + throw runtime_error("non-weapon items cannot be unidentified"); } + // It seems the client expects an item ID to be consumed here, even though + // the returned item has the same ID as the original item. Perhaps this was + // not the case on Sega's original server, and the returned item had a new + // ID instead. + l->generate_item_id(c->lobby_client_id); p->disp.stats.meseta -= 100; c->game_data.identify_result = p->inventory.items[x].data; c->game_data.identify_result.data1[4] &= 0x7F; @@ -2110,7 +2115,7 @@ static void on_accept_identify_item_bb(shared_ptr c, uint8_t command, ui throw runtime_error("accepted item ID does not match previous identify request"); } c->game_data.character()->add_item(c->game_data.identify_result); - send_create_inventory_item(c, c->game_data.identify_result, false); + send_create_inventory_item(c, c->game_data.identify_result); c->game_data.identify_result.clear(); } else { @@ -2171,7 +2176,7 @@ static void on_buy_shop_item_bb(shared_ptr c, uint8_t, uint8_t, const vo item.id = l->generate_item_id(c->lobby_client_id); p->add_item(item); - send_create_inventory_item(c, item, true); + send_create_inventory_item(c, item); auto s = c->require_server_state(); auto name = s->describe_item(c->version(), item, false); @@ -2260,7 +2265,7 @@ static void on_quest_exchange_item_bb(shared_ptr c, uint8_t, uint8_t, co ItemData new_item = cmd.replace_item; new_item.id = l->generate_item_id(c->lobby_client_id); p->add_item(new_item); - send_create_inventory_item(c, new_item, true); + send_create_inventory_item(c, new_item); send_quest_function_call(c, cmd.success_function_id); @@ -2281,7 +2286,7 @@ static void on_wrap_item_bb(shared_ptr c, uint8_t, uint8_t, const void* send_destroy_item(c, item.id, 1); item.wrap(); p->add_item(cmd.item); - send_create_inventory_item(c, item, false); + send_create_inventory_item(c, item); } } @@ -2302,7 +2307,7 @@ static void on_photon_drop_exchange_bb(shared_ptr c, uint8_t, uint8_t, c ItemData new_item = cmd.new_item; new_item.id = l->generate_item_id(c->lobby_client_id); p->add_item(new_item); - send_create_inventory_item(c, new_item, true); + send_create_inventory_item(c, new_item); send_quest_function_call(c, cmd.success_function_id); @@ -2349,7 +2354,7 @@ static void on_secret_lottery_ticket_exchange_bb(shared_ptr c, uint8_t, : s->secret_lottery_results[random_object() % s->secret_lottery_results.size()]; item.id = l->generate_item_id(c->lobby_client_id); p->add_item(item); - send_create_inventory_item(c, item, true); + send_create_inventory_item(c, item); } S_ExchangeSecretLotteryTicketResult_BB_24 out_cmd; @@ -2429,7 +2434,7 @@ static void on_momoka_item_exchange_bb(shared_ptr c, uint8_t, uint8_t, c ItemData new_item = cmd.replace_item; new_item.id = l->generate_item_id(c->lobby_client_id); p->add_item(new_item); - send_create_inventory_item(c, new_item, true); + send_create_inventory_item(c, new_item); send_command(c, 0x23, 0x00); } catch (const exception& e) { @@ -2483,7 +2488,7 @@ static void on_upgrade_weapon_attribute_bb(shared_ptr c, uint8_t, uint8_ item.data1[attribute_index] += attribute_amount; send_destroy_item(c, item.id, 1); - send_create_inventory_item(c, item, false); + send_create_inventory_item(c, item); send_quest_function_call(c, cmd.success_function_id); } catch (const exception& e) { diff --git a/src/SendCommands.cc b/src/SendCommands.cc index c5f518c8..ab996744 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -2180,18 +2180,11 @@ void send_pick_up_item(shared_ptr c, uint32_t item_id, uint8_t floor) { send_command_t(l, 0x60, 0x00, cmd); } -void send_create_inventory_item(shared_ptr c, const ItemData& item, bool has_newest_item_id) { +void send_create_inventory_item(shared_ptr c, const ItemData& item) { auto l = c->require_lobby(); if (c->version() != GameVersion::BB) { throw logic_error("6xBE can only be sent to BB clients"); } - // This command consumes an item ID on the client even though it's never used, - // because the passed-in item's ID overwrites it. If the passed-in ID was just - // generated by calling l->generate_item_id, then we shouldn't waste one here, - // but if not, we should (to keep our state in sync with the client). - if (!has_newest_item_id) { - l->generate_item_id(c->lobby_client_id); - } uint16_t client_id = c->lobby_client_id; G_CreateInventoryItem_BB_6xBE cmd = {{0xBE, 0x07, client_id}, item, 0}; send_command_t(l, 0x60, 0x00, cmd); diff --git a/src/SendCommands.hh b/src/SendCommands.hh index 3539dc5a..5f26af20 100644 --- a/src/SendCommands.hh +++ b/src/SendCommands.hh @@ -301,7 +301,7 @@ void send_drop_stacked_item(std::shared_ptr s, Channel& ch, const I void send_drop_stacked_item(std::shared_ptr l, const ItemData& item, uint8_t floor, float x, float z); void send_pick_up_item(std::shared_ptr c, uint32_t id, uint8_t floor); -void send_create_inventory_item(std::shared_ptr c, const ItemData& item, bool has_newest_item_id); +void send_create_inventory_item(std::shared_ptr c, const ItemData& item); void send_destroy_item(std::shared_ptr c, uint32_t item_id, uint32_t amount); void send_item_identify_result(std::shared_ptr c); void send_bank(std::shared_ptr c);