fix meseta overdraft disconnect bug

This commit is contained in:
Martin Michelsen
2023-03-02 17:06:15 -08:00
parent 94bbd5685e
commit c3aca29d9c
5 changed files with 19 additions and 13 deletions
-3
View File
@@ -1495,9 +1495,6 @@ DataIndex::DataIndex(const string& directory, uint32_t behavior_flags)
add_maps_from_dir(directory + "/maps-free", false);
add_maps_from_dir(directory + "/maps-quest", true);
// Generate (and cache) the map list to ensure it's not too large
this->get_compressed_map_list();
try {
auto json = JSONObject::parse(load_file(directory + "/com-decks.json"));
for (const auto& def_json : json->as_list()) {
+3 -1
View File
@@ -231,7 +231,9 @@ void player_use_item(shared_ptr<Client> c, size_t item_index) {
}
if (should_delete_item) {
c->game_data.player()->remove_item(item.data.id, 1);
// Allow overdrafting meseta if the client is not BB, since the server isn't
// informed when meseta is added or removed from the bank.
c->game_data.player()->remove_item(item.data.id, 1, c->version() != GameVersion::BB);
}
}
+6 -3
View File
@@ -793,18 +793,21 @@ void PlayerBank::add_item(const PlayerBankItem& item) {
// TODO: Eliminate code duplication between this function and the parallel
// function in PlayerBank
PlayerInventoryItem SavedPlayerDataBB::remove_item(
uint32_t item_id, uint32_t amount) {
uint32_t item_id, uint32_t amount, bool allow_meseta_overdraft) {
PlayerInventoryItem ret;
// If we're removing meseta (signaled by an invalid item ID), then create a
// meseta item.
if (item_id == 0xFFFFFFFF) {
if (amount > this->disp.meseta) {
if (amount <= this->disp.meseta) {
this->disp.meseta -= amount;
} else if (allow_meseta_overdraft) {
this->disp.meseta = 0;
} else {
throw out_of_range("player does not have enough meseta");
}
ret.data.data1[0] = 0x04;
ret.data.data2d = amount;
this->disp.meseta -= amount;
return ret;
}
+2 -1
View File
@@ -483,7 +483,8 @@ struct SavedPlayerDataBB { // .nsc file format
parray<uint8_t, 0x0028> tech_menu_config;
void add_item(const PlayerInventoryItem& item);
PlayerInventoryItem remove_item(uint32_t item_id, uint32_t amount);
PlayerInventoryItem remove_item(
uint32_t item_id, uint32_t amount, bool allow_meseta_overdraft);
void print_inventory(FILE* stream) const;
} __attribute__((packed));
+8 -5
View File
@@ -476,8 +476,8 @@ static void on_player_drop_item(shared_ptr<ServerState>,
}
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
l->add_item(c->game_data.player()->remove_item(cmd.item_id, 0), cmd.area,
cmd.x, cmd.z);
auto item = c->game_data.player()->remove_item(cmd.item_id, 0, c->version() != GameVersion::BB);
l->add_item(item, cmd.area, cmd.x, cmd.z);
l->log.info("Player %hu dropped item %08" PRIX32 " at %hu:(%g, %g)",
cmd.header.client_id.load(), cmd.item_id.load(), cmd.area.load(),
@@ -563,7 +563,8 @@ static void on_drop_partial_stack_bb(shared_ptr<ServerState>,
throw logic_error("item tracking not enabled in BB game");
}
auto item = c->game_data.player()->remove_item(cmd.item_id, cmd.amount);
auto item = c->game_data.player()->remove_item(
cmd.item_id, cmd.amount, c->version() != GameVersion::BB);
// if a stack was split, the original item still exists, so the dropped item
// needs a new ID. remove_item signals this by returning an item with id=-1
@@ -814,7 +815,8 @@ static void on_bank_action_bb(shared_ptr<ServerState>,
c->game_data.player()->bank.meseta += cmd.meseta_amount;
c->game_data.player()->disp.meseta -= cmd.meseta_amount;
} else { // item
auto item = c->game_data.player()->remove_item(cmd.item_id, cmd.item_amount);
auto item = c->game_data.player()->remove_item(
cmd.item_id, cmd.item_amount, c->version() != GameVersion::BB);
c->game_data.player()->bank.add_item(item);
send_destroy_item(l, c, cmd.item_id, cmd.item_amount);
}
@@ -1130,7 +1132,8 @@ static void on_destroy_inventory_item(shared_ptr<ServerState>,
return;
}
if (l->flags & Lobby::Flag::ITEM_TRACKING_ENABLED) {
c->game_data.player()->remove_item(cmd.item_id, cmd.amount);
c->game_data.player()->remove_item(
cmd.item_id, cmd.amount, c->version() != GameVersion::BB);
l->log.info("Inventory item %hu:%08" PRIX32 " destroyed (%" PRIX32 " of them)",
cmd.header.client_id.load(), cmd.item_id.load(), cmd.amount.load());
c->game_data.player()->print_inventory(stderr);