From 9cd6f64e860e5ceb1cc72079f5e631ba117a77e8 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Fri, 22 May 2020 13:54:15 -0400 Subject: [PATCH] Core/AuctionHouse: Don't overflow mail attachments, send max 16 items per mail Port From (https://github.com/TrinityCore/TrinityCore/commit/7e18255ee24f6c8b133f197120e18934cfa50395) --- Source/Framework/Constants/SharedConst.cs | 3 +- Source/Game/AuctionHouse/AuctionManager.cs | 90 +++++++++++++++------- Source/Game/Handlers/MailHandler.cs | 2 +- 3 files changed, 67 insertions(+), 28 deletions(-) diff --git a/Source/Framework/Constants/SharedConst.cs b/Source/Framework/Constants/SharedConst.cs index 7ea4d0f96..ac1f96e68 100644 --- a/Source/Framework/Constants/SharedConst.cs +++ b/Source/Framework/Constants/SharedConst.cs @@ -28,7 +28,8 @@ namespace Framework.Constants public const int GTMaxRating = 32; // gtOCTClassCombatRatingScalar.dbc stores data for 32 ratings, look at MAX_COMBAT_RATING for real used amount public const int ReputationCap = 42999; public const int ReputationBottom = -42000; - public const int MaxMailItems = 12; + public const int MaxClientMailItems = 12; // max number of items a player is allowed to attach + public const int MaxMailItems = 16; public const int MaxDeclinedNameCases = 5; public const int MaxHolidayDurations = 10; public const int MaxHolidayDates = 26; diff --git a/Source/Game/AuctionHouse/AuctionManager.cs b/Source/Game/AuctionHouse/AuctionManager.cs index b4941ec2f..f329e64cf 100644 --- a/Source/Game/AuctionHouse/AuctionManager.cs +++ b/Source/Game/AuctionHouse/AuctionManager.cs @@ -1213,7 +1213,9 @@ namespace Game Optional uniqueSeller = new Optional(); // prepare items - List items = new List(); + List items = new List(); + items.Add(new MailedItemsBatch()); + remainingQuantity = quantity; List removedItemsFromAuction = new List(); @@ -1229,6 +1231,13 @@ namespace Game int removedItems = 0; foreach (Item auctionItem in auction.Items) { + MailedItemsBatch itemsBatch = items.Last(); + if (itemsBatch.IsFull()) + { + items.Add(new MailedItemsBatch()); + itemsBatch = items.Last(); + } + if (auctionItem.GetCount() >= remainingQuantity) { Item clonedItem = auctionItem.CloneItem(remainingQuantity, player); @@ -1241,14 +1250,14 @@ namespace Game auctionItem.SetCount(auctionItem.GetCount() - remainingQuantity); auctionItem.FSetState(ItemUpdateState.Changed); auctionItem.SaveToDB(trans); - items.Add(clonedItem); + itemsBatch.AddItem(clonedItem, auction.BuyoutOrUnitPrice); boughtFromAuction += remainingQuantity; remainingQuantity = 0; i = bucketItr.Auctions.Count; break; } - items.Add(auctionItem); + itemsBatch.AddItem(auctionItem, auction.BuyoutOrUnitPrice); boughtFromAuction += auctionItem.GetCount(); remainingQuantity -= auctionItem.GetCount(); ++removedItems; @@ -1262,12 +1271,12 @@ namespace Game if (!Global.CharacterCacheStorage.GetCharacterNameByGuid(auction.Owner, out string ownerName)) ownerName = Global.ObjectMgr.GetCypherString(CypherStrings.Unknown); - Log.outCommand(bidderAccId, $"GM {player.GetName()} (Account: {bidderAccId}) bought commodity in auction: {items[0].GetName(Global.WorldMgr.GetDefaultDbcLocale())} (Entry: {items[0].GetEntry()} " + + Log.outCommand(bidderAccId, $"GM {player.GetName()} (Account: {bidderAccId}) bought commodity in auction: {items[0].Items[0].GetName(Global.WorldMgr.GetDefaultDbcLocale())} (Entry: {items[0].Items[0].GetEntry()} " + $"Count: {boughtFromAuction}) and pay money: { auction.BuyoutOrUnitPrice * boughtFromAuction}. Original owner {ownerName} (Account: {Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(auction.Owner)})"); } ulong auctionHouseCut = CalcualteAuctionHouseCut(auction.BuyoutOrUnitPrice * boughtFromAuction); - ulong depositPart = Global.AuctionHouseMgr.GetCommodityAuctionDeposit(items[0].GetTemplate(), (auction.EndTime - auction.StartTime), boughtFromAuction); + ulong depositPart = Global.AuctionHouseMgr.GetCommodityAuctionDeposit(items[0].Items[0].GetTemplate(), (auction.EndTime - auction.StartTime), boughtFromAuction); ulong profit = auction.BuyoutOrUnitPrice * boughtFromAuction + depositPart - auctionHouseCut; Player owner = Global.ObjAccessor.FindConnectedPlayer(auction.Owner); @@ -1284,24 +1293,27 @@ namespace Game .SendMailTo(trans, new MailReceiver(Global.ObjAccessor.FindConnectedPlayer(auction.Owner), auction.Owner), new MailSender(this), MailCheckMask.Copied, WorldConfig.GetUIntValue(WorldCfg.MailDeliveryDelay)); } - MailDraft mail = new MailDraft(Global.AuctionHouseMgr.BuildCommodityAuctionMailSubject(AuctionMailType.Won, itemId, quantity), - Global.AuctionHouseMgr.BuildAuctionWonMailBody(uniqueSeller.Value, totalPrice, quantity)); - - foreach (Item item in items) + foreach (MailedItemsBatch batch in items) { - PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_AUCTION_ITEMS_BY_ITEM); - stmt.AddValue(0, item.GetGUID().GetCounter()); - trans.Append(stmt); + MailDraft mail = new MailDraft(Global.AuctionHouseMgr.BuildCommodityAuctionMailSubject(AuctionMailType.Won, itemId, batch.Quantity), + Global.AuctionHouseMgr.BuildAuctionWonMailBody(uniqueSeller.Value, batch.TotalPrice, batch.Quantity)); - item.SetOwnerGUID(player.GetGUID()); - item.SaveToDB(trans); - mail.AddItem(item); + for (int i = 0; i < batch.ItemsCount; ++i) + { + PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_AUCTION_ITEMS_BY_ITEM); + stmt.AddValue(0, batch.Items[i].GetGUID().GetCounter()); + trans.Append(stmt); + + batch.Items[i].SetOwnerGUID(player.GetGUID()); + batch.Items[i].SaveToDB(trans); + mail.AddItem(batch.Items[i]); + } + + mail.SendMailTo(trans, player, new MailSender(this), MailCheckMask.Copied); } - mail.SendMailTo(trans, player, new MailSender(this), MailCheckMask.Copied); - AuctionWonNotification packet = new AuctionWonNotification(); - packet.Info.Initialize(auctions[0], items[0]); + packet.Info.Initialize(auctions[0], items[0].Items[0]); player.SendPacket(packet); for (int i = 0; i < auctions.Count; ++i) @@ -1459,12 +1471,16 @@ namespace Game if (owner) owner.GetSession().SendAuctionClosedNotification(auction, 0.0f, false); - MailDraft mail = new MailDraft(Global.AuctionHouseMgr.BuildItemAuctionMailSubject(AuctionMailType.Expired, auction), ""); + int itemIndex = 0; + while (auction.Items.Count > itemIndex) + { + MailDraft mail = new MailDraft(Global.AuctionHouseMgr.BuildItemAuctionMailSubject(AuctionMailType.Expired, auction), ""); - foreach (Item item in auction.Items) - mail.AddItem(item); + for (int i = 0; i < SharedConst.MaxMailItems && auction.Items[itemIndex] != null; ++i, ++itemIndex) + mail.AddItem(auction.Items[itemIndex]); - mail.SendMailTo(trans, new MailReceiver(owner, auction.Owner), new MailSender(this), MailCheckMask.Copied, 0); + mail.SendMailTo(trans, new MailReceiver(owner, auction.Owner), new MailSender(this), MailCheckMask.Copied, 0); + } } else { @@ -1476,12 +1492,16 @@ namespace Game public void SendAuctionRemoved(AuctionPosting auction, Player owner, SQLTransaction trans) { - MailDraft draft = new MailDraft(Global.AuctionHouseMgr.BuildItemAuctionMailSubject(AuctionMailType.Cancelled, auction), ""); + int itemIndex = 0; + while (auction.Items.Count > itemIndex) + { + MailDraft draft = new MailDraft(Global.AuctionHouseMgr.BuildItemAuctionMailSubject(AuctionMailType.Cancelled, auction), ""); - foreach (Item item in auction.Items) - draft.AddItem(item); + for (int i = 0; i < SharedConst.MaxMailItems && auction.Items[itemIndex] != null; ++i, ++itemIndex) + draft.AddItem(auction.Items[itemIndex]); - draft.SendMailTo(trans, owner, new MailSender(this), MailCheckMask.Copied); + draft.SendMailTo(trans, owner, new MailSender(this), MailCheckMask.Copied); + } } //this function sends mail, when auction is cancelled to old bidder @@ -1525,6 +1545,24 @@ namespace Game public bool IsReplicationInProgress() { return Cursor != Tombstone && Global != 0; } } + class MailedItemsBatch + { + public Item[] Items = new Item[SharedConst.MaxMailItems]; + public ulong TotalPrice; + public uint Quantity; + + public int ItemsCount; + + public bool IsFull() { return ItemsCount >= Items.Length; } + + public void AddItem(Item item, ulong unitPrice) + { + Items[ItemsCount++] = item; + Quantity += item.GetCount(); + TotalPrice += unitPrice * item.GetCount(); + } + } + AuctionHouseRecord _auctionHouse; SortedList _itemsByAuctionId = new SortedList(); // ordered for replicate diff --git a/Source/Game/Handlers/MailHandler.cs b/Source/Game/Handlers/MailHandler.cs index c3ad1b583..93524598b 100644 --- a/Source/Game/Handlers/MailHandler.cs +++ b/Source/Game/Handlers/MailHandler.cs @@ -61,7 +61,7 @@ namespace Game [WorldPacketHandler(ClientOpcodes.SendMail)] void HandleSendMail(SendMail packet) { - if (packet.Info.Attachments.Count > SharedConst.MaxMailItems) // client limit + if (packet.Info.Attachments.Count > SharedConst.MaxClientMailItems) // client limit { GetPlayer().SendMailResult(0, MailResponseType.Send, MailResponseResult.TooManyAttachments); return;