assign bank item IDs at game join time
This commit is contained in:
+10
-3
@@ -214,7 +214,7 @@ void Lobby::add_client(shared_ptr<Client> c, ssize_t required_client_id) {
|
||||
// If the lobby is a game and item tracking is enabled, assign the inventory's
|
||||
// item IDs
|
||||
if (this->is_game() && this->check_flag(Lobby::Flag::ITEM_TRACKING_ENABLED)) {
|
||||
this->assign_inventory_item_ids(c);
|
||||
this->assign_inventory_and_bank_item_ids(c);
|
||||
}
|
||||
|
||||
// If the lobby is recording a battle record, add the player join event
|
||||
@@ -383,13 +383,20 @@ void Lobby::on_item_id_generated_externally(uint32_t item_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void Lobby::assign_inventory_item_ids(shared_ptr<Client> c) {
|
||||
void Lobby::assign_inventory_and_bank_item_ids(shared_ptr<Client> c) {
|
||||
auto p = c->game_data.character();
|
||||
for (size_t z = 0; z < p->inventory.num_items; z++) {
|
||||
p->inventory.items[z].data.id = this->generate_item_id(c->lobby_client_id);
|
||||
}
|
||||
c->log.info("Assigned item IDs");
|
||||
c->log.info("Assigned inventory item IDs");
|
||||
p->print_inventory(stderr, c->version(), c->require_server_state()->item_name_index);
|
||||
if (p->bank.num_items) {
|
||||
p->bank.assign_ids(0x99000000 + (c->lobby_client_id << 20));
|
||||
c->log.info("Assigned bank item IDs");
|
||||
p->print_bank(stderr, c->version(), c->require_server_state()->item_name_index);
|
||||
} else {
|
||||
c->log.info("Bank is empty");
|
||||
}
|
||||
}
|
||||
|
||||
unordered_map<uint32_t, shared_ptr<Client>> Lobby::clients_by_serial_number() const {
|
||||
|
||||
+1
-1
@@ -191,7 +191,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
ItemData remove_item(uint32_t item_id);
|
||||
uint32_t generate_item_id(uint8_t client_id);
|
||||
void on_item_id_generated_externally(uint32_t item_id);
|
||||
void assign_inventory_item_ids(std::shared_ptr<Client> c);
|
||||
void assign_inventory_and_bank_item_ids(std::shared_ptr<Client> c);
|
||||
|
||||
QuestIndex::IncludeCondition quest_include_condition() const;
|
||||
|
||||
|
||||
@@ -479,7 +479,8 @@ void PlayerBank::add_item(const ItemData& item) {
|
||||
this->num_items++;
|
||||
}
|
||||
|
||||
ItemData PlayerBank::remove_item_by_index(size_t index, uint32_t amount) {
|
||||
ItemData PlayerBank::remove_item(uint32_t item_id, uint32_t amount) {
|
||||
size_t index = this->find_item(item_id);
|
||||
auto& bank_item = this->items[index];
|
||||
|
||||
ItemData ret;
|
||||
@@ -680,6 +681,12 @@ void PlayerBank::sort() {
|
||||
std::sort(this->items.data(), this->items.data() + this->num_items);
|
||||
}
|
||||
|
||||
void PlayerBank::assign_ids(uint32_t base_id) {
|
||||
for (size_t z = 0; z < this->num_items; z++) {
|
||||
this->items[z].data.id = base_id + z;
|
||||
}
|
||||
}
|
||||
|
||||
BattleRules::BattleRules(const JSON& json) {
|
||||
static const JSON empty_list = JSON::list();
|
||||
|
||||
|
||||
@@ -101,10 +101,11 @@ struct PlayerBank {
|
||||
/* 12C8 */
|
||||
|
||||
void add_item(const ItemData& item);
|
||||
ItemData remove_item_by_index(size_t index, uint32_t amount);
|
||||
ItemData remove_item(uint32_t item_id, uint32_t amount);
|
||||
size_t find_item(uint32_t item_id);
|
||||
|
||||
void sort();
|
||||
void assign_ids(uint32_t base_id);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct PlayerDispDataBB;
|
||||
|
||||
@@ -1899,7 +1899,7 @@ static void on_quest_loaded(shared_ptr<Lobby> l) {
|
||||
} else if (l->quest->challenge_template_index >= 0) {
|
||||
lc->game_data.create_challenge_overlay(lc->version(), l->quest->challenge_template_index, s->level_table);
|
||||
lc->log.info("Created challenge overlay");
|
||||
l->assign_inventory_item_ids(lc);
|
||||
l->assign_inventory_and_bank_item_ids(lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3441,7 +3441,7 @@ static void on_DF_BB(shared_ptr<Client> c, uint16_t command, uint32_t, string& d
|
||||
if (lc) {
|
||||
lc->game_data.create_challenge_overlay(lc->version(), l->quest->challenge_template_index, s->level_table);
|
||||
lc->log.info("Created challenge overlay");
|
||||
l->assign_inventory_item_ids(lc);
|
||||
l->assign_inventory_and_bank_item_ids(lc);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1471,6 +1471,13 @@ static void on_ep3_private_word_select_bb_bank_action(shared_ptr<Client> c, uint
|
||||
|
||||
} else { // Deposit item
|
||||
auto item = p->remove_item(cmd.item_id, cmd.item_amount, c->version() != Version::BB_V4);
|
||||
// If a stack was split, the bank item retains the same item ID as the
|
||||
// inventory item. This is annoying but doesn't cause any problems
|
||||
// because we always generate a new item ID when withdrawing from the
|
||||
// bank, so there's no chance of conflict later.
|
||||
if (item.id == 0xFFFFFFFF) {
|
||||
item.id = cmd.item_id;
|
||||
}
|
||||
bank.add_item(item);
|
||||
send_destroy_item(c, cmd.item_id, cmd.item_amount, true);
|
||||
|
||||
@@ -1496,7 +1503,7 @@ static void on_ep3_private_word_select_bb_bank_action(shared_ptr<Client> c, uint
|
||||
}
|
||||
|
||||
} else { // Take item
|
||||
auto item = bank.remove_item_by_index(cmd.item_index, cmd.item_amount);
|
||||
auto item = 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);
|
||||
|
||||
@@ -584,6 +584,18 @@ void PSOBBCharacterFile::print_inventory(FILE* stream, Version version, shared_p
|
||||
}
|
||||
}
|
||||
|
||||
void PSOBBCharacterFile::print_bank(FILE* stream, Version version, shared_ptr<const ItemNameIndex> name_index) const {
|
||||
fprintf(stream, "[PlayerBank] Meseta: %" PRIu32 "\n", this->bank.meseta.load());
|
||||
fprintf(stream, "[PlayerBank] %" PRIu32 " items\n", this->bank.num_items.load());
|
||||
for (size_t x = 0; x < this->bank.num_items; x++) {
|
||||
const auto& item = this->bank.items[x];
|
||||
const char* present_token = item.present ? "" : " (missing present flag)";
|
||||
auto name = name_index->describe_item(version, item.data);
|
||||
auto hex = item.data.hex();
|
||||
fprintf(stream, "[PlayerBank] %3zu: %s (%s) (x%hu) %s\n", x, hex.c_str(), name.c_str(), item.amount.load(), present_token);
|
||||
}
|
||||
}
|
||||
|
||||
const array<PSOBBCharacterFile::DefaultSymbolChatEntry, 6> PSOBBCharacterFile::DEFAULT_SYMBOL_CHATS = {
|
||||
DefaultSymbolChatEntry{"\tEHello", 0x28, {0xFFFF, 0x000D, 0xFFFF, 0xFFFF}, {SymbolChat::FacePart{0x05, 0x18, 0x1D, 0x00}, {0x05, 0x28, 0x1D, 0x01}, {0x36, 0x20, 0x2A, 0x00}, {0x3C, 0x00, 0x32, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}}},
|
||||
DefaultSymbolChatEntry{"\tEGood-bye", 0x74, {0x0476, 0x000C, 0xFFFF, 0xFFFF}, {SymbolChat::FacePart{0x06, 0x15, 0x14, 0x00}, {0x06, 0x2B, 0x14, 0x01}, {0x05, 0x18, 0x1F, 0x00}, {0x05, 0x28, 0x1F, 0x01}, {0x36, 0x20, 0x2A, 0x00}, {0x3C, 0x00, 0x32, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}}},
|
||||
|
||||
@@ -254,6 +254,7 @@ struct PSOBBCharacterFile {
|
||||
void clear_all_material_usage();
|
||||
|
||||
void print_inventory(FILE* stream, Version version, std::shared_ptr<const ItemNameIndex> name_index) const;
|
||||
void print_bank(FILE* stream, Version version, std::shared_ptr<const ItemNameIndex> name_index) const;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct PSOBBGuildCardFile {
|
||||
|
||||
Reference in New Issue
Block a user