From 54d494da36269eb071141010ab558dc0f480ad18 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Tue, 21 Apr 2020 00:40:18 -0400 Subject: [PATCH 1/3] Fix errant merchant full messages and add logging for later use (#1035) * Fix errant merchant full issues, add logging for later use * Rename merchant list dump more clearly * spaces around '=' * Added line spacing, Co-authored-by: Noudess --- zone/inventory.cpp | 44 ++++++----- zone/zone.cpp | 185 ++++++++++++++++++++++++++++++++------------- zone/zone.h | 1 + 3 files changed, 159 insertions(+), 71 deletions(-) diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 3ee86df47..f9438b32c 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -2913,23 +2913,33 @@ void Client::SendItemPacket(int16 slot_id, const EQEmu::ItemInstance* inst, Item if (!inst) return; - if (slot_id <= EQEmu::invslot::POSSESSIONS_END && slot_id >= EQEmu::invslot::POSSESSIONS_BEGIN) { - if ((((uint64)1 << slot_id) & GetInv().GetLookup()->PossessionsBitmask) == 0) - return; - } - else if (slot_id <= EQEmu::invbag::GENERAL_BAGS_END && slot_id >= EQEmu::invbag::GENERAL_BAGS_BEGIN) { - auto temp_slot = EQEmu::invslot::GENERAL_BEGIN + ((slot_id - EQEmu::invbag::GENERAL_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT); - if ((((uint64)1 << temp_slot) & GetInv().GetLookup()->PossessionsBitmask) == 0) - return; - } - else if (slot_id <= EQEmu::invslot::BANK_END && slot_id >= EQEmu::invslot::BANK_BEGIN) { - if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank) - return; - } - else if (slot_id <= EQEmu::invbag::BANK_BAGS_END && slot_id >= EQEmu::invbag::BANK_BAGS_BEGIN) { - auto temp_slot = (slot_id - EQEmu::invbag::BANK_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT; - if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize.Bank) - return; + if (packet_type != ItemPacketMerchant) { + if (slot_id <= EQEmu::invslot::POSSESSIONS_END && slot_id >= EQEmu::invslot::POSSESSIONS_BEGIN) { + if ((((uint64)1 << slot_id) & GetInv().GetLookup()->PossessionsBitmask) == 0) { + LogError("Item not sent to merchant : slot [{}]", slot_id); + return; + } + } + else if (slot_id <= EQEmu::invbag::GENERAL_BAGS_END && slot_id >= EQEmu::invbag::GENERAL_BAGS_BEGIN) { + auto temp_slot = EQEmu::invslot::GENERAL_BEGIN + ((slot_id - EQEmu::invbag::GENERAL_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT); + if ((((uint64)1 << temp_slot) & GetInv().GetLookup()->PossessionsBitmask) == 0) { + LogError("Item not sent to merchant2 : slot [{}]", slot_id); + return; + } + } + else if (slot_id <= EQEmu::invslot::BANK_END && slot_id >= EQEmu::invslot::BANK_BEGIN) { + if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank) { + LogError("Item not sent to merchant3 : slot [{}]", slot_id); + return; + } + } + else if (slot_id <= EQEmu::invbag::BANK_BAGS_END && slot_id >= EQEmu::invbag::BANK_BAGS_BEGIN) { + auto temp_slot = (slot_id - EQEmu::invbag::BANK_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT; + if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize.Bank) { + LogError("Item not sent to merchant4 : slot [{}]", slot_id); + return; + } + } } // Serialize item into |-delimited string (Titanium- uses '|' delimiter .. newer clients use pure data serialization) diff --git a/zone/zone.cpp b/zone/zone.cpp index 398c985c6..d64c198d3 100755 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -330,81 +330,156 @@ bool Zone::LoadGroundSpawns() { return(true); } -int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold) { - int freeslot = 0; - std::list merlist = merchanttable[merchantid]; - std::list::const_iterator itr; - uint32 i = 1; - for (itr = merlist.begin(); itr != merlist.end(); ++itr) { - MerchantList ml = *itr; - if (ml.item == item) - return 0; - - // Account for merchant lists with gaps in them. - if (ml.slot >= i) - i = ml.slot + 1; - } +void Zone::DumpMerchantList(uint32 npcid) { std::list tmp_merlist = tmpmerchanttable[npcid]; std::list::const_iterator tmp_itr; - bool update_charges = false; TempMerchantList ml; - while (freeslot == 0 && !update_charges) { - freeslot = i; - for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) { - ml = *tmp_itr; - if (ml.item == item) { - update_charges = true; - freeslot = 0; - break; - } - if ((ml.slot == i) || (ml.origslot == i)) { - freeslot = 0; - } - } - i++; + + for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) { + ml = *tmp_itr; + + LogInventory("slot[{}] Orig[{}] Item[{}] Charges[{}]", ml.slot, ml.origslot, ml.item, ml.charges); } - if (update_charges) { +} + +int Zone::SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold) { + + LogInventory("Transaction of [{}] [{}]", charges, item); + //DumpMerchantList(npcid); + // Iterate past main items. + // If the item being transacted is in this list, return 0; + std::list merlist = merchanttable[merchantid]; + std::list::const_iterator itr; + uint32 temp_slot_index = 1; + for (itr = merlist.begin(); itr != merlist.end(); ++itr) { + MerchantList ml = *itr; + if (ml.item == item) { + return 0; + } + + // Account for merchant lists with gaps in them. + if (ml.slot >= temp_slot_index) { + temp_slot_index = ml.slot + 1; + } + } + + LogInventory("Searching Temporary List. Main list ended at [{}]", temp_slot_index-1); + + // Now search the temporary list. + std::list tmp_merlist = tmpmerchanttable[npcid]; + std::list::const_iterator tmp_itr; + TempMerchantList ml; + uint32 first_empty_slot = 0; // Save 1st vacant slot while searching.. + bool found = false; + + for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) { + ml = *tmp_itr; + + if (ml.item == item) { + found = true; + LogInventory("Item found in temp list at [{}] with [{}] charges", ml.origslot, ml.charges); + break; + } + } + + if (found) { tmp_merlist.clear(); std::list oldtmp_merlist = tmpmerchanttable[npcid]; for (tmp_itr = oldtmp_merlist.begin(); tmp_itr != oldtmp_merlist.end(); ++tmp_itr) { TempMerchantList ml2 = *tmp_itr; if(ml2.item != item) tmp_merlist.push_back(ml2); + else { + if (sold) { + LogInventory("Total charges is [{}] + [{}] charges", ml.charges, charges); + ml.charges = ml.charges + charges; + } + else { + ml.charges = charges; + LogInventory("new charges is [{}] charges", ml.charges); + } + + if (!ml.origslot) { + ml.origslot = ml.slot; + } + + if (charges > 0) { + database.SaveMerchantTemp(npcid, ml.origslot, item, ml.charges); + tmp_merlist.push_back(ml); + } + else { + database.DeleteMerchantTemp(npcid, ml.origslot); + } + } } - if (sold) - ml.charges = ml.charges + charges; - else - ml.charges = charges; - if (!ml.origslot) - ml.origslot = ml.slot; - if (charges > 0) { - database.SaveMerchantTemp(npcid, ml.origslot, item, ml.charges); - tmp_merlist.push_back(ml); - } - else { - database.DeleteMerchantTemp(npcid, ml.origslot); - } + tmpmerchanttable[npcid] = tmp_merlist; - - if (sold) - return ml.slot; - + //DumpMerchantList(npcid); + return ml.slot; } - if (freeslot) { - if (charges < 0) //sanity check only, shouldnt happen + else { + if (charges < 0) { //sanity check only, shouldnt happen charges = 0x7FFF; - database.SaveMerchantTemp(npcid, freeslot, item, charges); + } + + // Find an ununsed db slot # + std::list slots; + TempMerchantList ml3; + for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) { + ml3 = *tmp_itr; + slots.push_back(ml3.origslot); + } + slots.sort(); + std::list::const_iterator slots_itr; + uint32 first_empty_slot = 0; + uint32 idx = temp_slot_index; + for (slots_itr = slots.begin(); slots_itr != slots.end(); ++slots_itr) { + if (!first_empty_slot && *slots_itr > idx) { + LogInventory("Popped [{}]", *slots_itr); + LogInventory("First Gap Found at [{}]", idx); + break; + } + + ++idx; + } + + first_empty_slot = idx; + + // Find an ununsed mslot + slots.clear(); + for (tmp_itr = tmp_merlist.begin(); tmp_itr != tmp_merlist.end(); ++tmp_itr) { + ml3 = *tmp_itr; + slots.push_back(ml3.slot); + } + slots.sort(); + uint32 first_empty_mslot=0; + idx = temp_slot_index; + for (slots_itr = slots.begin(); slots_itr != slots.end(); ++slots_itr) { + if (!first_empty_mslot && *slots_itr > idx) { + LogInventory("Popped [{}]", *slots_itr); + LogInventory("First Gap Found at [{}]", idx); + break; + } + + ++idx; + } + + first_empty_mslot = idx; + + database.SaveMerchantTemp(npcid, first_empty_slot, item, charges); tmp_merlist = tmpmerchanttable[npcid]; TempMerchantList ml2; ml2.charges = charges; + LogInventory("Adding slot [{}] with [{}] charges.", first_empty_mslot, charges); ml2.item = item; ml2.npcid = npcid; - ml2.slot = freeslot; - ml2.origslot = ml2.slot; + ml2.slot = first_empty_mslot; + ml2.origslot = first_empty_slot; tmp_merlist.push_back(ml2); tmpmerchanttable[npcid] = tmp_merlist; + //DumpMerchantList(npcid); + return ml2.slot; } - return freeslot; } uint32 Zone::GetTempMerchantQuantity(uint32 NPCID, uint32 Slot) { @@ -413,8 +488,10 @@ uint32 Zone::GetTempMerchantQuantity(uint32 NPCID, uint32 Slot) { std::list::const_iterator Iterator; for (Iterator = TmpMerchantList.begin(); Iterator != TmpMerchantList.end(); ++Iterator) - if ((*Iterator).slot == Slot) + if ((*Iterator).slot == Slot) { + LogInventory("Slot [{}] has [{}] charges.", Slot, (*Iterator).charges); return (*Iterator).charges; + } return 0; } diff --git a/zone/zone.h b/zone/zone.h index fc7fa8bf7..6d8fc54e6 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -163,6 +163,7 @@ public: inline void ShowNPCGlobalLoot(Client *to, NPC *who) { m_global_loot.ShowNPCGlobalLoot(to, who); } inline void ShowZoneGlobalLoot(Client *to) { m_global_loot.ShowZoneGlobalLoot(to); } int GetZoneTotalBlockedSpells() { return zone_total_blocked_spells; } + void DumpMerchantList(uint32 npcid); int SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold = false); int32 MobsAggroCount() { return aggroedmobs; } From 387e1668a5bc3b27e1460dbff74d5337fdfb6383 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 24 Apr 2020 01:25:09 -0500 Subject: [PATCH 2/3] Remove hard delete from `DeleteInstance` so that the purge timer can pick it up later --- common/database_instances.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 10a2ce032..0e6e8b380 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -515,8 +515,8 @@ void Database::BuryCorpsesInInstance(uint16 instance_id) { void Database::DeleteInstance(uint16 instance_id) { - std::string query = StringFormat("DELETE FROM instance_list WHERE id=%u", instance_id); - QueryDatabase(query); +// std::string query = StringFormat("DELETE FROM instance_list WHERE id=%u", instance_id); +// QueryDatabase(query); query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id); QueryDatabase(query); From 954247956e6e2c8e3351b6760b0d003d90c842ad Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 24 Apr 2020 02:11:06 -0500 Subject: [PATCH 3/3] Adjust syntax --- common/database_instances.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 0e6e8b380..617a2baf6 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -515,8 +515,7 @@ void Database::BuryCorpsesInInstance(uint16 instance_id) { void Database::DeleteInstance(uint16 instance_id) { -// std::string query = StringFormat("DELETE FROM instance_list WHERE id=%u", instance_id); -// QueryDatabase(query); + std::string query; query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id); QueryDatabase(query);