Exemple #1
0
        void HandleAuctionSellItem(AuctionSellItem packet)
        {
            foreach (var aitem in packet.Items)
            {
                if (aitem.Guid.IsEmpty() || aitem.UseCount == 0 || aitem.UseCount > 1000)
                {
                    return;
                }
            }

            if (packet.MinBid == 0 || packet.RunTime == 0)
            {
                return;
            }

            if (packet.MinBid > PlayerConst.MaxMoneyAmount || packet.BuyoutPrice > PlayerConst.MaxMoneyAmount)
            {
                Log.outDebug(LogFilter.Network, "WORLD: HandleAuctionSellItem - Player {0} ({1}) attempted to sell item with higher price than max gold amount.", GetPlayer().GetName(), GetPlayer().GetGUID().ToString());
                SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError);
                return;
            }

            Creature creature = GetPlayer().GetNPCIfCanInteractWith(packet.Auctioneer, NPCFlags.Auctioneer, NPCFlags2.None);

            if (!creature)
            {
                Log.outDebug(LogFilter.Network, "WORLD: HandleAuctionSellItem - {0} not found or you can't interact with him.", packet.Auctioneer.ToString());
                return;
            }

            uint houseId = 0;
            AuctionHouseRecord auctionHouseEntry = Global.AuctionMgr.GetAuctionHouseEntry(creature.GetFaction(), ref houseId);

            if (auctionHouseEntry == null)
            {
                Log.outDebug(LogFilter.Network, "WORLD: HandleAuctionSellItem - {0} has wrong faction.", packet.Auctioneer.ToString());
                return;
            }

            packet.RunTime *= Time.Minute;
            switch (packet.RunTime)
            {
            case 1 * SharedConst.MinAuctionTime:
            case 2 * SharedConst.MinAuctionTime:
            case 4 * SharedConst.MinAuctionTime:
                break;

            default:
                return;
            }

            if (GetPlayer().HasUnitState(UnitState.Died))
            {
                GetPlayer().RemoveAurasByType(AuraType.FeignDeath);
            }

            uint finalCount = 0;

            Item[] items = new Item[packet.Items.Count];
            for (var i = 0; i < packet.Items.Count; ++i)
            {
                items[i] = GetPlayer().GetItemByGuid(packet.Items[i].Guid);
                if (!items[i])
                {
                    SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.ItemNotFound);
                    return;
                }

                if (Global.AuctionMgr.GetAItem(items[i].GetGUID().GetCounter()) || !items[i].CanBeTraded() || items[i].IsNotEmptyBag() ||
                    items[i].GetTemplate().GetFlags().HasAnyFlag(ItemFlags.Conjured) || items[i].m_itemData.Expiration != 0 ||
                    items[i].GetCount() < packet.Items[i].UseCount)
                {
                    SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError);
                    return;
                }

                finalCount += packet.Items[i].UseCount;
            }

            if (packet.Items.Empty())
            {
                SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError);
                return;
            }

            if (finalCount == 0)
            {
                SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError);
                return;
            }

            // check if there are 2 identical guids, in this case user is most likely cheating
            for (int i = 0; i < packet.Items.Count; ++i)
            {
                for (int j = i + 1; j < packet.Items.Count; ++j)
                {
                    if (packet.Items[i].Guid == packet.Items[j].Guid)
                    {
                        SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError);
                        return;
                    }
                    if (items[i].GetEntry() != items[j].GetEntry())
                    {
                        SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.ItemNotFound);
                        return;
                    }
                }
            }

            for (var i = 0; i < packet.Items.Count; ++i)
            {
                if (items[i].GetMaxStackCount() < finalCount)
                {
                    SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError);
                    return;
                }
            }

            Item item = items[0];

            uint auctionTime = (uint)(packet.RunTime * WorldConfig.GetFloatValue(WorldCfg.RateAuctionTime));
            AuctionHouseObject auctionHouse = Global.AuctionMgr.GetAuctionsMap(creature.GetFaction());

            ulong deposit = Global.AuctionMgr.GetAuctionDeposit(auctionHouseEntry, packet.RunTime, item, finalCount);

            if (!GetPlayer().HasEnoughMoney(deposit))
            {
                SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.NotEnoughtMoney);
                return;
            }

            AuctionEntry   AH = new AuctionEntry();
            SQLTransaction trans;

            if (WorldConfig.GetBoolValue(WorldCfg.AllowTwoSideInteractionAuction))
            {
                AH.auctioneer = 23442;     //@TODO - HARDCODED DB GUID, BAD BAD BAD
            }
            else
            {
                AH.auctioneer = creature.GetSpawnId();
            }

            // Required stack size of auction matches to current item stack size, just move item to auctionhouse
            if (packet.Items.Count == 1 && item.GetCount() == packet.Items[0].UseCount)
            {
                if (HasPermission(RBACPermissions.LogGmTrade))
                {
                    Log.outCommand(GetAccountId(), "GM {0} (Account: {1}) create auction: {2} (Entry: {3} Count: {4})",
                                   GetPlayerName(), GetAccountId(), item.GetTemplate().GetName(), item.GetEntry(), item.GetCount());
                }

                AH.Id                = Global.ObjectMgr.GenerateAuctionID();
                AH.itemGUIDLow       = item.GetGUID().GetCounter();
                AH.itemEntry         = item.GetEntry();
                AH.itemCount         = item.GetCount();
                AH.owner             = GetPlayer().GetGUID().GetCounter();
                AH.startbid          = (uint)packet.MinBid;
                AH.bidder            = 0;
                AH.bid               = 0;
                AH.buyout            = (uint)packet.BuyoutPrice;
                AH.expire_time       = Time.UnixTime + auctionTime;
                AH.deposit           = deposit;
                AH.etime             = packet.RunTime;
                AH.auctionHouseEntry = auctionHouseEntry;

                Log.outInfo(LogFilter.Network, "CMSG_AUCTION_SELL_ITEM: {0} {1} is selling item {2} {3} to auctioneer {4} with count {5} with initial bid {6} with buyout {7} and with time {8} (in sec) in auctionhouse {9}",
                            GetPlayer().GetGUID().ToString(), GetPlayer().GetName(), item.GetGUID().ToString(), item.GetTemplate().GetName(), AH.auctioneer, item.GetCount(), packet.MinBid, packet.BuyoutPrice, auctionTime, AH.GetHouseId());
                Global.AuctionMgr.AddAItem(item);
                auctionHouse.AddAuction(AH);

                GetPlayer().MoveItemFromInventory(item.GetBagSlot(), item.GetSlot(), true);

                trans = new SQLTransaction();
                item.DeleteFromInventoryDB(trans);
                item.SaveToDB(trans);
                AH.SaveToDB(trans);
                GetPlayer().SaveInventoryAndGoldToDB(trans);
                DB.Characters.CommitTransaction(trans);

                SendAuctionCommandResult(AH, AuctionAction.SellItem, AuctionError.Ok);

                GetPlayer().UpdateCriteria(CriteriaTypes.CreateAuction, 1);
            }
            else // Required stack size of auction does not match to current item stack size, clone item and set correct stack size
            {
                Item newItem = item.CloneItem(finalCount, GetPlayer());
                if (!newItem)
                {
                    Log.outError(LogFilter.Network, "CMSG_AuctionAction.SellItem: Could not create clone of item {0}", item.GetEntry());
                    SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError);
                    return;
                }

                if (HasPermission(RBACPermissions.LogGmTrade))
                {
                    Log.outCommand(GetAccountId(), "GM {0} (Account: {1}) create auction: {2} (Entry: {3} Count: {4})",
                                   GetPlayerName(), GetAccountId(), newItem.GetTemplate().GetName(), newItem.GetEntry(), newItem.GetCount());
                }

                AH.Id                = Global.ObjectMgr.GenerateAuctionID();
                AH.itemGUIDLow       = newItem.GetGUID().GetCounter();
                AH.itemEntry         = newItem.GetEntry();
                AH.itemCount         = newItem.GetCount();
                AH.owner             = GetPlayer().GetGUID().GetCounter();
                AH.startbid          = (uint)packet.MinBid;
                AH.bidder            = 0;
                AH.bid               = 0;
                AH.buyout            = (uint)packet.BuyoutPrice;
                AH.expire_time       = Time.UnixTime + auctionTime;
                AH.deposit           = deposit;
                AH.etime             = packet.RunTime;
                AH.auctionHouseEntry = auctionHouseEntry;

                Log.outInfo(LogFilter.Network, "CMSG_AuctionAction.SellItem: {0} {1} is selling {2} {3} to auctioneer {4} with count {5} with initial bid {6} with buyout {7} and with time {8} (in sec) in auctionhouse {9}",
                            GetPlayer().GetGUID().ToString(), GetPlayer().GetName(), newItem.GetGUID().ToString(), newItem.GetTemplate().GetName(), AH.auctioneer, newItem.GetCount(), packet.MinBid, packet.BuyoutPrice, auctionTime, AH.GetHouseId());
                Global.AuctionMgr.AddAItem(newItem);
                auctionHouse.AddAuction(AH);

                for (var i = 0; i < packet.Items.Count; ++i)
                {
                    Item item2 = items[i];

                    // Item stack count equals required count, ready to delete item - cloned item will be used for auction
                    if (item2.GetCount() == packet.Items[i].UseCount)
                    {
                        GetPlayer().MoveItemFromInventory(item2.GetBagSlot(), item2.GetSlot(), true);

                        trans = new SQLTransaction();
                        item2.DeleteFromInventoryDB(trans);
                        item2.DeleteFromDB(trans);
                        DB.Characters.CommitTransaction(trans);
                    }
                    else // Item stack count is bigger than required count, update item stack count and save to database - cloned item will be used for auction
                    {
                        item2.SetCount(item2.GetCount() - packet.Items[i].UseCount);
                        item2.SetState(ItemUpdateState.Changed, GetPlayer());
                        GetPlayer().ItemRemovedQuestCheck(item2.GetEntry(), packet.Items[i].UseCount);
                        item2.SendUpdateToPlayer(GetPlayer());

                        trans = new SQLTransaction();
                        item2.SaveToDB(trans);
                        DB.Characters.CommitTransaction(trans);
                    }
                }

                trans = new SQLTransaction();
                newItem.SaveToDB(trans);
                AH.SaveToDB(trans);
                GetPlayer().SaveInventoryAndGoldToDB(trans);
                DB.Characters.CommitTransaction(trans);

                SendAuctionCommandResult(AH, AuctionAction.SellItem, AuctionError.Ok);

                GetPlayer().UpdateCriteria(CriteriaTypes.CreateAuction, 1);
            }

            GetPlayer().ModifyMoney(-(long)deposit);
        }
Exemple #2
0
        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 = Global.CharacterCacheStorage.GetCharacterGuidByName(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;
            uint receiverBnetAccountId = 0;

            if (receiver)
            {
                receiverTeam          = receiver.GetTeam();
                mailsCount            = (byte)receiver.GetMails().Count;
                receiverLevel         = (byte)receiver.getLevel();
                receiverAccountId     = receiver.GetSession().GetAccountId();
                receiverBnetAccountId = receiver.GetSession().GetBattlenetAccountId();
            }
            else
            {
                CharacterCacheEntry characterInfo = Global.CharacterCacheStorage.GetCharacterCacheByGuid(receiverGuid);
                if (characterInfo != null)
                {
                    receiverTeam      = Player.TeamForRace(characterInfo.RaceId);
                    receiverLevel     = characterInfo.Level;
                    receiverAccountId = characterInfo.AccountId;
                }

                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);
                }

                receiverBnetAccountId = Global.BNetAccountMgr.GetIdByGameAccount(receiverAccountId);
            }

            // 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)
                {
                    if (!item.IsBattlenetAccountBound() || player.GetSession().GetBattlenetAccountId() == 0 || player.GetSession().GetBattlenetAccountId() != receiverBnetAccountId)
                    {
                        player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.NotSameAccount);
                        return;
                    }
                }

                if (item.GetTemplate().GetFlags().HasAnyFlag(ItemFlags.Conjured) || item.m_itemData.Expiration != 0)
                {
                    player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.MailBoundItem);
                    return;
                }

                if (packet.Info.Cod != 0 && item.HasItemFlag(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);
        }