fix(Core/Mail): do not show expired mails in packets (#10560)

Fixed #5920
This commit is contained in:
UltraNix
2022-03-01 13:57:37 +01:00
committed by GitHub
parent 66b95f8d9d
commit 73957b95f6
8 changed files with 13 additions and 69 deletions

View File

@@ -0,0 +1,3 @@
INSERT INTO `version_db_characters` (`sql_rev`) VALUES ('1644159033376794200');
ALTER TABLE `mail` DROP COLUMN `auctionId`;

View File

@@ -119,12 +119,12 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_AUCTION, "INSERT INTO auctionhouse (id, houseid, itemguid, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_AUCTION, "DELETE FROM auctionhouse WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_AUCTION_BID, "UPDATE auctionhouse SET buyguid = ?, lastbid = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_MAIL, "INSERT INTO mail(id, messageType, stationery, mailTemplateId, sender, receiver, subject, body, has_items, expire_time, deliver_time, money, cod, checked, auctionId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_MAIL, "INSERT INTO mail(id, messageType, stationery, mailTemplateId, sender, receiver, subject, body, has_items, expire_time, deliver_time, money, cod, checked) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_MAIL_BY_ID, "DELETE FROM mail WHERE id = ?", CONNECTION_ASYNC);
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, stationery, 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 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);
@@ -417,7 +417,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHAR_SOCIAL, "SELECT DISTINCT guid FROM character_social WHERE friend = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_OLD_CHARS, "SELECT guid, deleteInfos_Account FROM characters WHERE deleteDate IS NOT NULL AND deleteDate < ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_ARENA_TEAM_ID_BY_PLAYER_GUID, "SELECT arena_team_member.arenateamid FROM arena_team_member JOIN arena_team ON arena_team_member.arenateamid = arena_team.arenateamid WHERE guid = ? AND type = ? LIMIT 1", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_MAIL, "SELECT id, messageType, sender, receiver, subject, body, expire_time, deliver_time, money, cod, checked, stationery, mailTemplateId, auctionId FROM mail WHERE receiver = ? AND deliver_time <= ? ORDER BY id DESC", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_MAIL, "SELECT id, messageType, sender, receiver, subject, body, expire_time, deliver_time, money, cod, checked, stationery, mailTemplateId FROM mail WHERE receiver = ? AND deliver_time <= ? ORDER BY id DESC", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_NEXT_MAIL_DELIVERYTIME, "SELECT MIN(deliver_time) FROM mail WHERE receiver = ? AND deliver_time > ? AND (checked & 1) = 0 LIMIT 1", CONNECTION_SYNCH);
PrepareStatement(CHAR_DEL_CHAR_AURA_FROZEN, "DELETE FROM character_aura WHERE spell = 9454 AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item WHERE itemEntry = ?", CONNECTION_SYNCH);

View File

@@ -351,7 +351,7 @@ void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry* auction, Characte
if (sendMail) // can be changed in the hook
MailDraft(auction->BuildAuctionMailSubject(AUCTION_SALE_PENDING),
AuctionEntry::BuildAuctionMailBody(auction->bidder, auction->bid, auction->buyout, auction->deposit, auction->GetAuctionCut(), deliveryDelay, timePacker.read<uint32>()))
.SendMailTo(trans, MailReceiver(owner, auction->owner.GetCounter()), auction, MAIL_CHECK_MASK_COPIED, 0, 0, false, true, -static_cast<int32>(auction->Id));
.SendMailTo(trans, MailReceiver(owner, auction->owner.GetCounter()), auction, MAIL_CHECK_MASK_COPIED);
}
}
@@ -381,7 +381,7 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry* auction, Character
if (sendMail) // can be changed in the hook
MailDraft(auction->BuildAuctionMailSubject(AUCTION_SUCCESSFUL), AuctionEntry::BuildAuctionMailBody(auction->bidder, auction->bid, auction->buyout, auction->deposit, auction->GetAuctionCut()))
.AddMoney(profit)
.SendMailTo(trans, MailReceiver(owner, auction->owner.GetCounter()), auction, MAIL_CHECK_MASK_COPIED, sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY), 0, false, true, auction->Id);
.SendMailTo(trans, MailReceiver(owner, auction->owner.GetCounter()), auction, MAIL_CHECK_MASK_COPIED, sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY));
if (auction->bid >= 500 * GOLD)
if (CharacterCacheEntry const* gpd = sCharacterCache->GetCharacterCacheByGuid(auction->bidder))

View File

@@ -6180,10 +6180,6 @@ Item* Player::_LoadMailedItem(ObjectGuid const& playerGuid, Player* player, uint
void Player::_LoadMail(PreparedQueryResult mailsResult, PreparedQueryResult mailItemsResult)
{
std::set<uint32> pendingAuctions;
std::unordered_map<uint32, Mail*> pendingAuctionMails;
CharacterDatabaseTransaction pendingAuctionsTrans = CharacterDatabase.BeginTransaction();
m_mail.clear();
std::unordered_map<uint32, Mail*> mailById;
@@ -6208,7 +6204,6 @@ void Player::_LoadMail(PreparedQueryResult mailsResult, PreparedQueryResult mail
m->checked = fields[10].Get<uint8>();
m->stationery = fields[11].Get<uint8>();
m->mailTemplateId = fields[12].Get<int16>();
m->auctionId = fields[13].Get<int32>();
if (m->mailTemplateId && !sMailTemplateStore.LookupEntry(m->mailTemplateId))
{
@@ -6218,52 +6213,6 @@ void Player::_LoadMail(PreparedQueryResult mailsResult, PreparedQueryResult mail
m->state = MAIL_STATE_UNCHANGED;
// Do not load expired pending sale mail if there is already delivery auction mail
if (m->auctionId < 0 && m->expire_time <= GameTime::GetGameTime().count())
{
uint32 auctionId = std::abs(m->auctionId);
if (pendingAuctions.count(auctionId))
{
CharacterDatabasePreparedStatement* stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_BY_ID);
stmt2->SetData(0, m->messageID);
pendingAuctionsTrans->Append(stmt2);
if (unReadMails > 0 && (m->checked & MAIL_CHECK_MASK_READ) == 0)
--unReadMails;
delete m;
continue;
}
pendingAuctionMails[auctionId] = m;
}
else if (m->auctionId > 0)
{
pendingAuctions.insert(m->auctionId);
}
for (auto itr : pendingAuctionMails)
{
uint32 auctionId = itr.first;
if (pendingAuctions.count(auctionId))
{
Mail* mail = itr.second;
CharacterDatabasePreparedStatement* stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_BY_ID);
stmt2->SetData(0, mail->messageID);
pendingAuctionsTrans->Append(stmt2);
if (unReadMails > 0 && (mail->checked & MAIL_CHECK_MASK_READ) == 0)
{
--unReadMails;
}
m_mail.erase(std::remove(m_mail.begin(), m_mail.end(), mail));
delete mail;
}
}
m_mail.push_back(m);
mailById[m->messageID] = m;
} while (mailsResult->NextRow());
@@ -6279,7 +6228,6 @@ void Player::_LoadMail(PreparedQueryResult mailsResult, PreparedQueryResult mail
} while (mailItemsResult->NextRow());
}
CharacterDatabase.CommitTransaction(pendingAuctionsTrans);
UpdateNextMailTimeAndUnreads();
}

View File

@@ -5974,7 +5974,6 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
m->stationery = fields[6].Get<uint8>();
m->checked = fields[7].Get<uint8>();
m->mailTemplateId = fields[8].Get<int16>();
m->auctionId = fields[9].Get<int32>();
Player* player = nullptr;
if (serverUp)

View File

@@ -626,7 +626,7 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData)
}
// skip deleted or not delivered (deliver delay not expired) mails
if (mail->state == MAIL_STATE_DELETED || cur_time < mail->deliver_time)
if (mail->state == MAIL_STATE_DELETED || cur_time < mail->deliver_time || cur_time > mail->expire_time)
{
continue;
}
@@ -811,8 +811,8 @@ void WorldSession::HandleQueryNextMailTime(WorldPacket& /*recvData*/)
if (mail->checked & MAIL_CHECK_MASK_READ)
continue;
// and already delivered
if (now < mail->deliver_time)
// and already delivered or expired
if (now < mail->deliver_time || now > mail->expire_time)
continue;
// only send each mail sender once

View File

@@ -189,7 +189,7 @@ void MailDraft::SendReturnToSender(uint32 /*sender_acc*/, ObjectGuid::LowType se
SendMailTo(trans, MailReceiver(receiver, receiver_guid), MailSender(MAIL_NORMAL, sender_guid), MAIL_CHECK_MASK_RETURNED, 0);
}
void MailDraft::SendMailTo(CharacterDatabaseTransaction trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay, uint32 custom_expiration, bool deleteMailItemsFromDB, bool sendMail, int32 auctionId)
void MailDraft::SendMailTo(CharacterDatabaseTransaction trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay, uint32 custom_expiration, bool deleteMailItemsFromDB, bool sendMail)
{
sScriptMgr->OnBeforeMailDraftSendMailTo(this, receiver, sender, checked, deliver_delay, custom_expiration, deleteMailItemsFromDB, sendMail);
@@ -248,7 +248,6 @@ void MailDraft::SendMailTo(CharacterDatabaseTransaction trans, MailReceiver cons
stmt->SetData(++index, m_money);
stmt->SetData(++index, m_COD);
stmt->SetData (++index, uint8(checked));
stmt->SetData(++index, auctionId);
trans->Append(stmt);
for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter)
@@ -289,7 +288,6 @@ void MailDraft::SendMailTo(CharacterDatabaseTransaction trans, MailReceiver cons
m->expire_time = expire_time;
m->deliver_time = deliver_time;
m->checked = checked;
m->auctionId = auctionId;
m->state = MAIL_STATE_UNCHANGED;
pReceiver->AddMail(m); // to insert new mail to beginning of maillist

View File

@@ -140,7 +140,7 @@ public: // modifiers
public: // finishers
void SendReturnToSender(uint32 sender_acc, ObjectGuid::LowType sender_guid, ObjectGuid::LowType receiver_guid, CharacterDatabaseTransaction trans);
void SendMailTo(CharacterDatabaseTransaction trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked = MAIL_CHECK_MASK_NONE, uint32 deliver_delay = 0, uint32 custom_expiration = 0, bool deleteMailItemsFromDB = false, bool sendMail = true, int32 auctionId = 0);
void SendMailTo(CharacterDatabaseTransaction trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked = MAIL_CHECK_MASK_NONE, uint32 deliver_delay = 0, uint32 custom_expiration = 0, bool deleteMailItemsFromDB = false, bool sendMail = true);
private:
void deleteIncludedItems(CharacterDatabaseTransaction trans, bool inDB = false);
@@ -183,10 +183,6 @@ struct Mail
uint32 checked;
MailState state;
// < 0 Pending
// > 0 Delivery
int32 auctionId;
void AddItem(ObjectGuid::LowType itemGuidLow, uint32 item_template)
{
MailItemInfo mii;