From 9330df59da60c832d7b7eff1ee14c8d765a5935a Mon Sep 17 00:00:00 2001 From: Skjalf <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 4 Oct 2021 10:45:33 -0300 Subject: [PATCH] fix(Core/Mails): mails containing items not being returned if they were read and ensure mails sent by GMs are not returned (#8095) --- .../Implementation/CharacterDatabase.cpp | 2 +- src/server/game/Globals/ObjectMgr.cpp | 16 ++++++++-------- src/server/game/Mails/Mail.h | 4 ++++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 9341eac38..64ea0bb0f 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -126,7 +126,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_INS_MAIL_ITEM, "INSERT INTO mail_items(mail_id, item_guid, receiver) VALUES (?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_MAIL_ITEM, "DELETE FROM mail_items WHERE item_guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_INVALID_MAIL_ITEM, "DELETE FROM mail_items WHERE item_guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_EXPIRED_MAIL, "SELECT id, messageType, sender, receiver, has_items, expire_time, cod, checked, mailTemplateId, auctionId FROM mail WHERE expire_time < ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_EXPIRED_MAIL, "SELECT id, messageType, sender, receiver, has_items, expire_time, stationery, checked, mailTemplateId, auctionId FROM mail WHERE expire_time < ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_EXPIRED_MAIL_ITEMS, "SELECT item_guid, itemEntry, mail_id FROM mail_items mi INNER JOIN item_instance ii ON ii.guid = mi.item_guid LEFT JOIN mail mm ON mi.mail_id = mm.id WHERE mm.id IS NOT NULL AND mm.expire_time < ?", CONNECTION_SYNCH); PrepareStatement(CHAR_UPD_MAIL_RETURNED, "UPDATE mail SET sender = ?, receiver = ?, expire_time = ?, deliver_time = ?, cod = 0, checked = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_MAIL_ITEM_RECEIVER, "UPDATE mail_items SET receiver = ? WHERE item_guid = ?", CONNECTION_ASYNC); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index c501da38a..a1eb9e0e3 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -5731,7 +5731,7 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) bool has_items = fields[4].GetBool(); m->expire_time = time_t(fields[5].GetUInt32()); m->deliver_time = time_t(0); - m->COD = fields[6].GetUInt32(); + m->stationery = fields[6].GetUInt8(); m->checked = fields[7].GetUInt8(); m->mailTemplateId = fields[8].GetInt16(); m->auctionId = fields[9].GetInt32(); @@ -5752,13 +5752,13 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) // read items from cache m->items.swap(itemsCache[m->messageID]); - // don't return if: is mail from non-player, or sent to self, or already returned, or read and isn't COD - if (m->messageType != MAIL_NORMAL || m->receiver == m->sender || (m->checked & (MAIL_CHECK_MASK_COD_PAYMENT | MAIL_CHECK_MASK_RETURNED)) || ((m->checked & MAIL_CHECK_MASK_READ) && !m->COD)) + // If it is mail from non-player, or if it's already return mail, it shouldn't be returned, but deleted + if (!m->IsSentByPlayer() || m->IsSentByGM() || (m->IsCODPayment() || m->IsReturnedMail())) { - for (MailItemInfoVec::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) + for (auto const& mailedItem : m->items) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE); - stmt->setUInt32(0, itr2->item_guid); + stmt->setUInt32(0, mailedItem.item_guid); CharacterDatabase.Execute(stmt); } @@ -5777,17 +5777,17 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) stmt->setUInt8 (4, uint8(MAIL_CHECK_MASK_RETURNED)); stmt->setUInt32(5, m->messageID); CharacterDatabase.Execute(stmt); - for (MailItemInfoVec::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) + for (auto const& mailedItem : m->items) { // Update receiver in mail items for its proper delivery, and in instance_item for avoid lost item at sender delete stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_MAIL_ITEM_RECEIVER); stmt->setUInt32(0, m->sender); - stmt->setUInt32(1, itr2->item_guid); + stmt->setUInt32(1, mailedItem.item_guid); CharacterDatabase.Execute(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ITEM_OWNER); stmt->setUInt32(0, m->sender); - stmt->setUInt32(1, itr2->item_guid); + stmt->setUInt32(1, mailedItem.item_guid); CharacterDatabase.Execute(stmt); } diff --git a/src/server/game/Mails/Mail.h b/src/server/game/Mails/Mail.h index 48af5c65c..179f50a92 100644 --- a/src/server/game/Mails/Mail.h +++ b/src/server/game/Mails/Mail.h @@ -207,6 +207,10 @@ struct Mail } [[nodiscard]] bool HasItems() const { return !items.empty(); } + [[nodiscard]] bool IsSentByPlayer() const { return messageType == MAIL_NORMAL; } + [[nodiscard]] bool IsSentByGM() const { return stationery == MAIL_STATIONERY_GM; } + [[nodiscard]] bool IsCODPayment() const { return checked & MAIL_CHECK_MASK_COD_PAYMENT; } + [[nodiscard]] bool IsReturnedMail() const { return checked & MAIL_CHECK_MASK_RETURNED; } }; #endif