//does not clear ram public void SendAuctionExpiredMail(AuctionEntry auction, SQLTransaction trans) { //return an item in auction to its owner by mail Item item = GetAItem(auction.itemGUIDLow); if (!item) { return; } ObjectGuid owner_guid = ObjectGuid.Create(HighGuid.Player, auction.owner); Player owner = Global.ObjAccessor.FindPlayer(owner_guid); uint owner_accId = ObjectManager.GetPlayerAccountIdByGUID(owner_guid); // owner exist if (owner || owner_accId != 0) { if (owner) { owner.GetSession().SendAuctionClosedNotification(auction, 0f, false, item); } new MailDraft(auction.BuildAuctionMailSubject(MailAuctionAnswers.Expired), AuctionEntry.BuildAuctionMailBody(0, 0, auction.buyout, auction.deposit, 0)) .AddItem(item) .SendMailTo(trans, new MailReceiver(owner, auction.owner), new MailSender(auction), MailCheckMask.Copied, 0); } else { // owner doesn't exist, delete the item Global.AuctionMgr.RemoveAItem(auction.itemGUIDLow, true); } }
//this function sends mail to old bidder public void SendAuctionOutbiddedMail(AuctionEntry auction, ulong newPrice, Player newBidder, SQLTransaction trans) { ObjectGuid oldBidder_guid = ObjectGuid.Create(HighGuid.Player, auction.bidder); Player oldBidder = Global.ObjAccessor.FindPlayer(oldBidder_guid); uint oldBidder_accId = 0; if (oldBidder == null) { oldBidder_accId = ObjectManager.GetPlayerAccountIdByGUID(oldBidder_guid); } Item item = GetAItem(auction.itemGUIDLow); // old bidder exist if (oldBidder || oldBidder_accId != 0) { if (oldBidder && item) { oldBidder.GetSession().SendAuctionOutBidNotification(auction, item); } new MailDraft(auction.BuildAuctionMailSubject(MailAuctionAnswers.Outbidded), AuctionEntry.BuildAuctionMailBody(auction.owner, auction.bid, auction.buyout, auction.deposit, auction.GetAuctionCut())) .AddMoney(auction.bid) .SendMailTo(trans, new MailReceiver(oldBidder, auction.bidder), new MailSender(auction), MailCheckMask.Copied); } }
//call this method to send mail to auction owner, when auction is successful, it does not clear ram public void SendAuctionSuccessfulMail(AuctionEntry auction, SQLTransaction trans) { ObjectGuid owner_guid = ObjectGuid.Create(HighGuid.Player, auction.owner); Player owner = Global.ObjAccessor.FindPlayer(owner_guid); uint owner_accId = ObjectManager.GetPlayerAccountIdByGUID(owner_guid); Item item = GetAItem(auction.itemGUIDLow); // owner exist if (owner || owner_accId != 0) { ulong profit = auction.bid + auction.deposit - auction.GetAuctionCut(); //FIXME: what do if owner offline if (owner && item) { owner.UpdateCriteria(CriteriaTypes.GoldEarnedByAuctions, profit); owner.UpdateCriteria(CriteriaTypes.HighestAuctionSold, auction.bid); // send auction owner notification, bidder must be current! owner.GetSession().SendAuctionClosedNotification(auction, WorldConfig.GetIntValue(WorldCfg.MailDeliveryDelay), true, item); } new MailDraft(auction.BuildAuctionMailSubject(MailAuctionAnswers.Successful), AuctionEntry.BuildAuctionMailBody(auction.bidder, auction.bid, auction.buyout, auction.deposit, auction.GetAuctionCut())) .AddMoney(profit) .SendMailTo(trans, new MailReceiver(owner, auction.owner), new MailSender(auction), MailCheckMask.Copied, WorldConfig.GetUIntValue(WorldCfg.MailDeliveryDelay)); } }
void HandlePetitionShowSignatures(PetitionShowSignatures packet) { Log.outDebug(LogFilter.Network, "Received opcode CMSG_PETITION_SHOW_SIGNATURES"); // if has guild => error, return; if (GetPlayer().GetGuildId() != 0) { return; } PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_PETITION_SIGNATURE); stmt.AddValue(0, packet.Item.GetCounter()); SQLResult result = DB.Characters.Query(stmt); ServerPetitionShowSignatures signaturesPacket = new ServerPetitionShowSignatures(); signaturesPacket.Item = packet.Item; signaturesPacket.Owner = GetPlayer().GetGUID(); signaturesPacket.OwnerAccountID = ObjectGuid.Create(HighGuid.WowAccount, ObjectManager.GetPlayerAccountIdByGUID(GetPlayer().GetGUID())); signaturesPacket.PetitionID = (int)packet.Item.GetCounter(); // @todo verify that... do { ObjectGuid signerGUID = ObjectGuid.Create(HighGuid.Player, result.Read <ulong>(0)); ServerPetitionShowSignatures.PetitionSignature signature = new ServerPetitionShowSignatures.PetitionSignature(); signature.Signer = signerGUID; signature.Choice = 0; signaturesPacket.Signatures.Add(signature); }while (result.NextRow()); SendPacket(signaturesPacket); }
public void SendAuctionSalePendingMail(AuctionEntry auction, SQLTransaction trans) { ObjectGuid owner_guid = ObjectGuid.Create(HighGuid.Player, auction.owner); Player owner = Global.ObjAccessor.FindPlayer(owner_guid); uint owner_accId = ObjectManager.GetPlayerAccountIdByGUID(owner_guid); // owner exist (online or offline) if (owner || owner_accId != 0) { new MailDraft(auction.BuildAuctionMailSubject(MailAuctionAnswers.SalePending), AuctionEntry.BuildAuctionMailBody(auction.bidder, auction.bid, auction.buyout, auction.deposit, auction.GetAuctionCut())) .SendMailTo(trans, new MailReceiver(owner, auction.owner), new MailSender(auction), MailCheckMask.Copied); } }
//this function sends mail, when auction is cancelled to old bidder public void SendAuctionCancelledToBidderMail(AuctionEntry auction, SQLTransaction trans) { ObjectGuid bidder_guid = ObjectGuid.Create(HighGuid.Player, auction.bidder); Player bidder = Global.ObjAccessor.FindPlayer(bidder_guid); uint bidder_accId = 0; if (!bidder) { bidder_accId = ObjectManager.GetPlayerAccountIdByGUID(bidder_guid); } // bidder exist if (bidder || bidder_accId != 0) { new MailDraft(auction.BuildAuctionMailSubject(MailAuctionAnswers.CancelledToBidder), AuctionEntry.BuildAuctionMailBody(auction.owner, auction.bid, auction.buyout, auction.deposit, 0)) .AddMoney(auction.bid) .SendMailTo(trans, new MailReceiver(bidder, auction.bidder), new MailSender(auction), MailCheckMask.Copied); } }
void HandleAuctionPlaceBid(AuctionPlaceBid packet) { if (packet.AuctionItemID == 0 || packet.BidAmount == 0) { return; // check for cheaters } Creature creature = GetPlayer().GetNPCIfCanInteractWith(packet.Auctioneer, NPCFlags.Auctioneer); if (!creature) { Log.outDebug(LogFilter.Network, "WORLD: HandleAuctionPlaceBid - {0} not found or you can't interact with him.", packet.Auctioneer.ToString()); return; } // remove fake death if (GetPlayer().HasUnitState(UnitState.Died)) { GetPlayer().RemoveAurasByType(AuraType.FeignDeath); } AuctionHouseObject auctionHouse = Global.AuctionMgr.GetAuctionsMap(creature.getFaction()); AuctionEntry auction = auctionHouse.GetAuction(packet.AuctionItemID); Player player = GetPlayer(); if (auction == null || auction.owner == player.GetGUID().GetCounter()) { //you cannot bid your own auction: SendAuctionCommandResult(null, AuctionAction.PlaceBid, AuctionError.BidOwn); return; } // impossible have online own another character (use this for speedup check in case online owner) ObjectGuid ownerGuid = ObjectGuid.Create(HighGuid.Player, auction.owner); Player auction_owner = Global.ObjAccessor.FindPlayer(ownerGuid); if (!auction_owner && ObjectManager.GetPlayerAccountIdByGUID(ownerGuid) == player.GetSession().GetAccountId()) { //you cannot bid your another character auction: SendAuctionCommandResult(null, AuctionAction.PlaceBid, AuctionError.BidOwn); return; } // cheating if (packet.BidAmount <= auction.bid || packet.BidAmount < auction.startbid) { return; } // price too low for next bid if not buyout if ((packet.BidAmount < auction.buyout || auction.buyout == 0) && packet.BidAmount < auction.bid + auction.GetAuctionOutBid()) { // client already test it but just in case ... SendAuctionCommandResult(auction, AuctionAction.PlaceBid, AuctionError.HigherBid); return; } if (!player.HasEnoughMoney(packet.BidAmount)) { // client already test it but just in case ... SendAuctionCommandResult(auction, AuctionAction.PlaceBid, AuctionError.NotEnoughtMoney); return; } SQLTransaction trans = new SQLTransaction(); if (packet.BidAmount < auction.buyout || auction.buyout == 0) { if (auction.bidder > 0) { if (auction.bidder == player.GetGUID().GetCounter()) { player.ModifyMoney(-(long)(packet.BidAmount - auction.bid)); } else { // mail to last bidder and return money Global.AuctionMgr.SendAuctionOutbiddedMail(auction, packet.BidAmount, GetPlayer(), trans); player.ModifyMoney(-(long)packet.BidAmount); } } else { player.ModifyMoney(-(long)packet.BidAmount); } auction.bidder = player.GetGUID().GetCounter(); auction.bid = (uint)packet.BidAmount; GetPlayer().UpdateCriteria(CriteriaTypes.HighestAuctionBid, packet.BidAmount); PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_AUCTION_BID); stmt.AddValue(0, auction.bidder); stmt.AddValue(1, auction.bid); stmt.AddValue(2, auction.Id); trans.Append(stmt); SendAuctionCommandResult(auction, AuctionAction.PlaceBid, AuctionError.Ok); // Not sure if we must send this now. Player owner = Global.ObjAccessor.FindConnectedPlayer(ObjectGuid.Create(HighGuid.Player, auction.owner)); Item item = Global.AuctionMgr.GetAItem(auction.itemGUIDLow); if (owner && item) { owner.GetSession().SendAuctionOwnerBidNotification(auction, item); } } else { //buyout: if (player.GetGUID().GetCounter() == auction.bidder) { player.ModifyMoney(-(long)(auction.buyout - auction.bid)); } else { player.ModifyMoney(-(long)auction.buyout); if (auction.bidder != 0) //buyout for bidded auction .. { Global.AuctionMgr.SendAuctionOutbiddedMail(auction, auction.buyout, GetPlayer(), trans); } } auction.bidder = player.GetGUID().GetCounter(); auction.bid = auction.buyout; GetPlayer().UpdateCriteria(CriteriaTypes.HighestAuctionBid, auction.buyout); SendAuctionCommandResult(auction, AuctionAction.PlaceBid, AuctionError.Ok); //- Mails must be under transaction control too to prevent data loss Global.AuctionMgr.SendAuctionSalePendingMail(auction, trans); Global.AuctionMgr.SendAuctionSuccessfulMail(auction, trans); Global.AuctionMgr.SendAuctionWonMail(auction, trans); auction.DeleteFromDB(trans); Global.AuctionMgr.RemoveAItem(auction.itemGUIDLow); auctionHouse.RemoveAuction(auction); } player.SaveInventoryAndGoldToDB(trans); DB.Characters.CommitTransaction(trans); }
public void SendAuctionWonMail(AuctionEntry auction, SQLTransaction trans) { Item item = GetAItem(auction.itemGUIDLow); if (!item) { return; } uint bidderAccId = 0; ObjectGuid bidderGuid = ObjectGuid.Create(HighGuid.Player, auction.bidder); Player bidder = Global.ObjAccessor.FindPlayer(bidderGuid); // data for gm.log string bidderName = ""; bool logGmTrade = false; if (bidder) { bidderAccId = bidder.GetSession().GetAccountId(); bidderName = bidder.GetName(); logGmTrade = bidder.GetSession().HasPermission(RBACPermissions.LogGmTrade); } else { bidderAccId = ObjectManager.GetPlayerAccountIdByGUID(bidderGuid); logGmTrade = Global.AccountMgr.HasPermission(bidderAccId, RBACPermissions.LogGmTrade, Global.WorldMgr.GetRealm().Id.Realm); if (logGmTrade && !ObjectManager.GetPlayerNameByGUID(bidderGuid, out bidderName)) { bidderName = Global.ObjectMgr.GetCypherString(CypherStrings.Unknown); } } if (logGmTrade) { ObjectGuid ownerGuid = ObjectGuid.Create(HighGuid.Player, auction.owner); string ownerName; if (!ObjectManager.GetPlayerNameByGUID(ownerGuid, out ownerName)) { ownerName = Global.ObjectMgr.GetCypherString(CypherStrings.Unknown); } uint ownerAccId = ObjectManager.GetPlayerAccountIdByGUID(ownerGuid); Log.outCommand(bidderAccId, $"GM {bidderName} (Account: {bidderAccId}) won item in auction: {item.GetTemplate().GetName()} (Entry: {item.GetEntry()} Count: {item.GetCount()}) and pay money: {auction.bid}. Original owner {ownerName} (Account: {ownerAccId})"); } // receiver exist if (bidder || bidderAccId != 0) { // set owner to bidder (to prevent delete item with sender char deleting) // owner in `data` will set at mail receive and item extracting PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_ITEM_OWNER); stmt.AddValue(0, auction.bidder); stmt.AddValue(1, item.GetGUID().GetCounter()); trans.Append(stmt); if (bidder) { bidder.GetSession().SendAuctionWonNotification(auction, item); // FIXME: for offline player need also bidder.UpdateCriteria(CriteriaTypes.WonAuctions, 1); } new MailDraft(auction.BuildAuctionMailSubject(MailAuctionAnswers.Won), AuctionEntry.BuildAuctionMailBody(auction.owner, auction.bid, auction.buyout, 0, 0)) .AddItem(item) .SendMailTo(trans, new MailReceiver(bidder, auction.bidder), new MailSender(auction), MailCheckMask.Copied); } else { // bidder doesn't exist, delete the item Global.AuctionMgr.RemoveAItem(auction.itemGUIDLow, true); } }
public void BuildAuctionInfo(List <AuctionItem> items, bool listAuctionItems) { Item item = Global.AuctionMgr.GetAItem(itemGUIDLow); if (!item) { Log.outError(LogFilter.Server, "AuctionEntry:BuildAuctionInfo: Auction {0} has a non-existent item: {1}", Id, itemGUIDLow); return; } AuctionItem auctionItem = new AuctionItem(); auctionItem.AuctionItemID = (int)Id; auctionItem.Item = new ItemInstance(item); auctionItem.BuyoutPrice = buyout; auctionItem.CensorBidInfo = false; auctionItem.CensorServerSideInfo = listAuctionItems; auctionItem.Charges = item.GetSpellCharges(); auctionItem.Count = (int)item.GetCount(); auctionItem.DeleteReason = 0; // Always 0 ? auctionItem.DurationLeft = (int)((expire_time - Time.UnixTime) * Time.InMilliseconds); auctionItem.EndTime = (uint)expire_time; auctionItem.Flags = 0; // todo auctionItem.ItemGuid = item.GetGUID(); auctionItem.MinBid = startbid; auctionItem.Owner = ObjectGuid.Create(HighGuid.Player, owner); auctionItem.OwnerAccountID = ObjectGuid.Create(HighGuid.WowAccount, ObjectManager.GetPlayerAccountIdByGUID(auctionItem.Owner)); auctionItem.MinIncrement = bidder != 0 ? GetAuctionOutBid() : 0; auctionItem.Bidder = bidder != 0 ? ObjectGuid.Create(HighGuid.Player, bidder) : ObjectGuid.Empty; auctionItem.BidAmount = bidder != 0 ? bid : 0; for (EnchantmentSlot c = 0; c < EnchantmentSlot.MaxInspected; c++) { if (item.GetEnchantmentId(c) == 0) { continue; } auctionItem.Enchantments.Add(new ItemEnchantData((int)item.GetEnchantmentId(c), item.GetEnchantmentDuration(c), (int)item.GetEnchantmentCharges(c), (byte)c)); } byte i = 0; foreach (ItemDynamicFieldGems gemData in item.GetGems()) { if (gemData.ItemId != 0) { ItemGemData gem = new ItemGemData(); gem.Slot = i; gem.Item = new ItemInstance(gemData); auctionItem.Gems.Add(gem); } ++i; } items.Add(auctionItem); }
void HandleSendMail(SendMail packet) { if (packet.Info.Attachments.Count > SharedConst.MaxMailItems) // client limit { GetPlayer().SendMailResult(0, MailResponseType.Send, MailResponseResult.TooManyAttachments); return; } if (!CanOpenMailBox(packet.Info.Mailbox)) { return; } if (string.IsNullOrEmpty(packet.Info.Target)) { return; } Player player = GetPlayer(); if (player.getLevel() < WorldConfig.GetIntValue(WorldCfg.MailLevelReq)) { SendNotification(CypherStrings.MailSenderReq, WorldConfig.GetIntValue(WorldCfg.MailLevelReq)); return; } ObjectGuid receiverGuid = ObjectGuid.Empty; if (ObjectManager.NormalizePlayerName(ref packet.Info.Target)) { receiverGuid = ObjectManager.GetPlayerGUIDByName(packet.Info.Target); } if (receiverGuid.IsEmpty()) { Log.outInfo(LogFilter.Network, "Player {0} is sending mail to {1} (GUID: not existed!) with subject {2}" + "and body {3} includes {4} items, {5} copper and {6} COD copper with StationeryID = {7}", GetPlayerInfo(), packet.Info.Target, packet.Info.Subject, packet.Info.Body, packet.Info.Attachments.Count, packet.Info.SendMoney, packet.Info.Cod, packet.Info.StationeryID); player.SendMailResult(0, MailResponseType.Send, MailResponseResult.RecipientNotFound); return; } if (packet.Info.SendMoney < 0) { GetPlayer().SendMailResult(0, MailResponseType.Send, MailResponseResult.InternalError); Log.outWarn(LogFilter.Server, "Player {0} attempted to send mail to {1} ({2}) with negative money value (SendMoney: {3})", GetPlayerInfo(), packet.Info.Target, receiverGuid.ToString(), packet.Info.SendMoney); return; } if (packet.Info.Cod < 0) { GetPlayer().SendMailResult(0, MailResponseType.Send, MailResponseResult.InternalError); Log.outWarn(LogFilter.Server, "Player {0} attempted to send mail to {1} ({2}) with negative COD value (Cod: {3})", GetPlayerInfo(), packet.Info.Target, receiverGuid.ToString(), packet.Info.Cod); return; } Log.outInfo(LogFilter.Network, "Player {0} is sending mail to {1} ({2}) with subject {3} and body {4}" + "includes {5} items, {6} copper and {7} COD copper with StationeryID = {8}", GetPlayerInfo(), packet.Info.Target, receiverGuid.ToString(), packet.Info.Subject, packet.Info.Body, packet.Info.Attachments.Count, packet.Info.SendMoney, packet.Info.Cod, packet.Info.StationeryID); if (player.GetGUID() == receiverGuid) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.CannotSendToSelf); return; } uint cost = (uint)(!packet.Info.Attachments.Empty() ? 30 * packet.Info.Attachments.Count : 30); // price hardcoded in client long reqmoney = cost + packet.Info.SendMoney; // Check for overflow if (reqmoney < packet.Info.SendMoney) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.NotEnoughMoney); return; } if (!player.HasEnoughMoney(reqmoney) && !player.IsGameMaster()) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.NotEnoughMoney); return; } Player receiver = Global.ObjAccessor.FindPlayer(receiverGuid); Team receiverTeam = 0; byte mailsCount = 0; //do not allow to send to one player more than 100 mails byte receiverLevel = 0; uint receiverAccountId = 0; if (receiver) { receiverTeam = receiver.GetTeam(); mailsCount = (byte)receiver.GetMails().Count; receiverLevel = (byte)receiver.getLevel(); receiverAccountId = receiver.GetSession().GetAccountId(); } else { receiverTeam = ObjectManager.GetPlayerTeamByGUID(receiverGuid); PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAIL_COUNT); stmt.AddValue(0, receiverGuid.GetCounter()); SQLResult result = DB.Characters.Query(stmt); if (!result.IsEmpty()) { mailsCount = (byte)result.Read <ulong>(0); } stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHAR_LEVEL); stmt.AddValue(0, receiverGuid.GetCounter()); result = DB.Characters.Query(stmt); if (!result.IsEmpty()) { receiverLevel = result.Read <byte>(0); } receiverAccountId = ObjectManager.GetPlayerAccountIdByGUID(receiverGuid); } // do not allow to have more than 100 mails in mailbox.. mails count is in opcode byte!!! - so max can be 255.. if (mailsCount > 100) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.RecipientCapReached); return; } // test the receiver's Faction... or all items are account bound bool accountBound = !packet.Info.Attachments.Empty(); foreach (var att in packet.Info.Attachments) { Item item = player.GetItemByGuid(att.ItemGUID); if (item) { ItemTemplate itemProto = item.GetTemplate(); if (itemProto == null || !itemProto.GetFlags().HasAnyFlag(ItemFlags.IsBoundToAccount)) { accountBound = false; break; } } } if (!accountBound && player.GetTeam() != receiverTeam && !HasPermission(RBACPermissions.TwoSideInteractionMail)) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.NotYourTeam); return; } if (receiverLevel < WorldConfig.GetIntValue(WorldCfg.MailLevelReq)) { SendNotification(CypherStrings.MailReceiverReq, WorldConfig.GetIntValue(WorldCfg.MailLevelReq)); return; } List <Item> items = new List <Item>(); foreach (var att in packet.Info.Attachments) { if (att.ItemGUID.IsEmpty()) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.MailAttachmentInvalid); return; } Item item = player.GetItemByGuid(att.ItemGUID); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if (!item) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.MailAttachmentInvalid); return; } if (!item.CanBeTraded(true)) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.MailBoundItem); return; } if (item.IsBoundAccountWide() && item.IsSoulBound() && player.GetSession().GetAccountId() != receiverAccountId) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.NotSameAccount); return; } if (item.GetTemplate().GetFlags().HasAnyFlag(ItemFlags.Conjured) || item.GetUInt32Value(ItemFields.Duration) != 0) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.MailBoundItem); return; } if (packet.Info.Cod != 0 && item.HasFlag(ItemFields.Flags, ItemFieldFlags.Wrapped)) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.CantSendWrappedCod); return; } if (item.IsNotEmptyBag()) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.DestroyNonemptyBag); return; } items.Add(item); } player.SendMailResult(0, MailResponseType.Send, MailResponseResult.Ok); player.ModifyMoney(-reqmoney); player.UpdateCriteria(CriteriaTypes.GoldSpentForMail, cost); bool needItemDelay = false; MailDraft draft = new MailDraft(packet.Info.Subject, packet.Info.Body); SQLTransaction trans = new SQLTransaction(); if (!packet.Info.Attachments.Empty() || packet.Info.SendMoney > 0) { bool log = HasPermission(RBACPermissions.LogGmTrade); if (!packet.Info.Attachments.Empty()) { foreach (var item in items) { if (log) { Log.outCommand(GetAccountId(), "GM {0} ({1}) (Account: {2}) mail item: {3} (Entry: {4} Count: {5}) to player: {6} ({7}) (Account: {8})", GetPlayerName(), GetPlayer().GetGUID().ToString(), GetAccountId(), item.GetTemplate().GetName(), item.GetEntry(), item.GetCount(), packet.Info.Target, receiverGuid.ToString(), receiverAccountId); } item.SetNotRefundable(GetPlayer()); // makes the item no longer refundable player.MoveItemFromInventory(item.GetBagSlot(), item.GetSlot(), true); item.DeleteFromInventoryDB(trans); // deletes item from character's inventory item.SetOwnerGUID(receiverGuid); item.SetState(ItemUpdateState.Changed); item.SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay needItemDelay = player.GetSession().GetAccountId() != receiverAccountId; } if (log && packet.Info.SendMoney > 0) { Log.outCommand(GetAccountId(), "GM {0} ({1}) (Account: {{2}) mail money: {3} to player: {4} ({5}) (Account: {6})", GetPlayerName(), GetPlayer().GetGUID().ToString(), GetAccountId(), packet.Info.SendMoney, packet.Info.Target, receiverGuid.ToString(), receiverAccountId); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint deliver_delay = needItemDelay ? WorldConfig.GetUIntValue(WorldCfg.MailDeliveryDelay) : 0; // Mail sent between guild members arrives instantly Guild guild = Global.GuildMgr.GetGuildById(player.GetGuildId()); if (guild) { if (guild.IsMember(receiverGuid)) { deliver_delay = 0; } } // don't ask for COD if there are no items if (packet.Info.Attachments.Empty()) { packet.Info.Cod = 0; } // will delete item or place to receiver mail list draft.AddMoney((ulong)packet.Info.SendMoney).AddCOD((uint)packet.Info.Cod).SendMailTo(trans, new MailReceiver(receiver, receiverGuid.GetCounter()), new MailSender(player), string.IsNullOrEmpty(packet.Info.Body) ? MailCheckMask.Copied : MailCheckMask.HasBody, deliver_delay); player.SaveInventoryAndGoldToDB(trans); DB.Characters.CommitTransaction(trans); }
void HandleMailTakeItem(MailTakeItem packet) { uint AttachID = packet.AttachID; if (!CanOpenMailBox(packet.Mailbox)) { return; } Player player = GetPlayer(); Mail m = player.GetMail(packet.MailID); if (m == null || m.state == MailState.Deleted || m.deliver_time > Time.UnixTime) { player.SendMailResult(packet.MailID, MailResponseType.ItemTaken, MailResponseResult.InternalError); return; } // verify that the mail has the item to avoid cheaters taking COD items without paying if (!m.items.Any(p => p.item_guid == AttachID)) { player.SendMailResult(packet.MailID, MailResponseType.ItemTaken, MailResponseResult.InternalError); return; } // prevent cheating with skip client money check if (!player.HasEnoughMoney(m.COD)) { player.SendMailResult(packet.MailID, MailResponseType.ItemTaken, MailResponseResult.NotEnoughMoney); return; } Item it = player.GetMItem(packet.AttachID); List <ItemPosCount> dest = new List <ItemPosCount>(); InventoryResult msg = GetPlayer().CanStoreItem(ItemConst.NullBag, ItemConst.NullSlot, dest, it, false); if (msg == InventoryResult.Ok) { SQLTransaction trans = new SQLTransaction(); m.RemoveItem(packet.AttachID); m.removedItems.Add(packet.AttachID); if (m.COD > 0) //if there is COD, take COD money from player and send them to sender by mail { ObjectGuid sender_guid = ObjectGuid.Create(HighGuid.Player, m.sender); Player receiver = Global.ObjAccessor.FindPlayer(sender_guid); uint sender_accId = 0; if (HasPermission(RBACPermissions.LogGmTrade)) { string sender_name; if (receiver) { sender_accId = receiver.GetSession().GetAccountId(); sender_name = receiver.GetName(); } else { // can be calculated early sender_accId = ObjectManager.GetPlayerAccountIdByGUID(sender_guid); if (!ObjectManager.GetPlayerNameByGUID(sender_guid, out sender_name)) { sender_name = Global.ObjectMgr.GetCypherString(CypherStrings.Unknown); } } Log.outCommand(GetAccountId(), "GM {0} (Account: {1}) receiver mail item: {2} (Entry: {3} Count: {4}) and send COD money: {5} to player: {6} (Account: {7})", GetPlayerName(), GetAccountId(), it.GetTemplate().GetName(), it.GetEntry(), it.GetCount(), m.COD, sender_name, sender_accId); } else if (!receiver) { sender_accId = ObjectManager.GetPlayerAccountIdByGUID(sender_guid); } // check player existence if (receiver || sender_accId != 0) { new MailDraft(m.subject, "") .AddMoney(m.COD) .SendMailTo(trans, new MailReceiver(receiver, m.sender), new MailSender(MailMessageType.Normal, m.receiver), MailCheckMask.CodPayment); } player.ModifyMoney(-(long)m.COD); } m.COD = 0; m.state = MailState.Changed; player.m_mailsUpdated = true; player.RemoveMItem(it.GetGUID().GetCounter()); uint count = it.GetCount(); // save counts before store and possible merge with deleting it.SetState(ItemUpdateState.Unchanged); // need to set this state, otherwise item cannot be removed later, if neccessary player.MoveItemToInventory(dest, it, true); player.SaveInventoryAndGoldToDB(trans); player._SaveMail(trans); DB.Characters.CommitTransaction(trans); player.SendMailResult(packet.MailID, MailResponseType.ItemTaken, MailResponseResult.Ok, 0, packet.AttachID, count); } else { player.SendMailResult(packet.MailID, MailResponseType.ItemTaken, MailResponseResult.EquipError, msg); } }