예제 #1
0
        public void AddAuction(AuctionEntry auction)
        {
            Cypher.Assert(auction != null);

            AuctionsMap[auction.Id] = auction;
            Global.ScriptMgr.OnAuctionAdd(this, auction);
        }
예제 #2
0
        //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 = Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(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);
            }
        }
예제 #3
0
        public void LoadAuctions()
        {
            uint oldMSTime = Time.GetMSTime();

            PreparedStatement stmt   = DB.Characters.GetPreparedStatement(CharStatements.SEL_AUCTIONS);
            SQLResult         result = DB.Characters.Query(stmt);

            if (result.IsEmpty())
            {
                Log.outInfo(LogFilter.ServerLoading, "Loaded 0 auctions. DB table `auctionhouse` is empty.");
                return;
            }

            uint           count = 0;
            SQLTransaction trans = new SQLTransaction();

            do
            {
                AuctionEntry aItem = new AuctionEntry();
                if (!aItem.LoadFromDB(result.GetFields()))
                {
                    aItem.DeleteFromDB(trans);
                    continue;
                }

                GetAuctionsMap(aItem.factionTemplateId).AddAuction(aItem);
                ++count;
            } while (result.NextRow());

            DB.Characters.CommitTransaction(trans);

            Log.outInfo(LogFilter.ServerLoading, "Loaded {0} auctions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
        }
예제 #4
0
        //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 = Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(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);
            }
        }
예제 #5
0
        //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 = Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(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));
            }
        }
예제 #6
0
        public void SendAuctionWonNotification(AuctionEntry auction, Item item)
        {
            AuctionWonNotification packet = new AuctionWonNotification();

            packet.Info.Initialize(auction, item);
            SendPacket(packet);
        }
예제 #7
0
        public void SendAuctionOwnerBidNotification(AuctionEntry auction, Item item)
        {
            AuctionOwnerBidNotification packet = new AuctionOwnerBidNotification();

            packet.Info.Initialize(auction, item);
            packet.Bidder       = ObjectGuid.Create(HighGuid.Player, auction.bidder);
            packet.MinIncrement = auction.GetAuctionOutBid();
            SendPacket(packet);
        }
예제 #8
0
        public void SendAuctionCommandResult(AuctionEntry auction, AuctionAction action, AuctionError errorCode, uint bidError = 0)
        {
            AuctionCommandResult auctionCommandResult = new AuctionCommandResult();

            auctionCommandResult.InitializeAuction(auction);
            auctionCommandResult.Command   = action;
            auctionCommandResult.ErrorCode = errorCode;
            SendPacket(auctionCommandResult);
        }
예제 #9
0
        public void SendAuctionOutBidNotification(AuctionEntry auction, Item item)
        {
            AuctionOutBidNotification packet = new AuctionOutBidNotification();

            packet.BidAmount    = auction.bid;
            packet.MinIncrement = auction.GetAuctionOutBid();
            packet.Info.Initialize(auction, item);
            SendPacket(packet);
        }
예제 #10
0
        public void SendAuctionClosedNotification(AuctionEntry auction, float mailDelay, bool sold, Item item)
        {
            AuctionClosedNotification packet = new AuctionClosedNotification();

            packet.Info.Initialize(auction, item);
            packet.ProceedsMailDelay = mailDelay;
            packet.Sold = sold;
            SendPacket(packet);
        }
예제 #11
0
        public bool RemoveAuction(AuctionEntry auction)
        {
            bool wasInMap = AuctionsMap.Remove(auction.Id) ? true : false;

            Global.ScriptMgr.OnAuctionRemove(this, auction);

            // we need to delete the entry, it is not referenced any more
            auction = null;

            return(wasInMap);
        }
예제 #12
0
        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 = Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(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);
            }
        }
예제 #13
0
        //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 = Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(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);
            }
        }
예제 #14
0
        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 = Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(bidderGuid);
                logGmTrade  = Global.AccountMgr.HasPermission(bidderAccId, RBACPermissions.LogGmTrade, Global.WorldMgr.GetRealm().Id.Realm);

                if (logGmTrade && !Global.CharacterCacheStorage.GetCharacterNameByGuid(bidderGuid, out bidderName))
                {
                    bidderName = Global.ObjectMgr.GetCypherString(CypherStrings.Unknown);
                }
            }

            if (logGmTrade)
            {
                ObjectGuid ownerGuid = ObjectGuid.Create(HighGuid.Player, auction.owner);
                string     ownerName;
                if (!Global.CharacterCacheStorage.GetCharacterNameByGuid(ownerGuid, out ownerName))
                {
                    ownerName = Global.ObjectMgr.GetCypherString(CypherStrings.Unknown);
                }

                uint ownerAccId = Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(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);
            }
        }
예제 #15
0
        public bool RemoveAuction(AuctionEntry auction)
        {
            Global.ScriptMgr.OnAuctionRemove(this, auction);

            return(AuctionsMap.TryRemove(auction.Id, out AuctionEntry removedItem));
        }
예제 #16
0
        void HandleAuctionRemoveItem(AuctionRemoveItem packet)
        {
            Creature creature = GetPlayer().GetNPCIfCanInteractWith(packet.Auctioneer, NPCFlags.Auctioneer, NPCFlags2.None);

            if (!creature)
            {
                Log.outDebug(LogFilter.Network, "WORLD: HandleAuctionRemoveItem - {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((uint)packet.AuctionItemID);
            Player       player  = GetPlayer();

            SQLTransaction trans = new SQLTransaction();

            if (auction != null && auction.owner == player.GetGUID().GetCounter())
            {
                Item pItem = Global.AuctionMgr.GetAItem(auction.itemGUIDLow);
                if (pItem)
                {
                    if (auction.bidder > 0)                        // If we have a bidder, we have to send him the money he paid
                    {
                        ulong auctionCut = auction.GetAuctionCut();
                        if (!player.HasEnoughMoney(auctionCut))          //player doesn't have enough money, maybe message needed
                        {
                            return;
                        }
                        Global.AuctionMgr.SendAuctionCancelledToBidderMail(auction, trans);
                        player.ModifyMoney(-(long)auctionCut);
                    }

                    // item will deleted or added to received mail list
                    new MailDraft(auction.BuildAuctionMailSubject(MailAuctionAnswers.Canceled), AuctionEntry.BuildAuctionMailBody(0, 0, auction.buyout, auction.deposit, 0))
                    .AddItem(pItem)
                    .SendMailTo(trans, new MailReceiver(player), new MailSender(auction), MailCheckMask.Copied);
                }
                else
                {
                    Log.outError(LogFilter.Network, "Auction id: {0} got non existing item (item guid : {1})!", auction.Id, auction.itemGUIDLow);
                    SendAuctionCommandResult(null, AuctionAction.Cancel, AuctionError.DatabaseError);
                    return;
                }
            }
            else
            {
                SendAuctionCommandResult(null, AuctionAction.Cancel, AuctionError.DatabaseError);
                //this code isn't possible ... maybe there should be assert
                Log.outError(LogFilter.Network, "CHEATER: {0} tried to cancel auction (id: {1}) of another player or auction is null", player.GetGUID().ToString(), packet.AuctionItemID);
                return;
            }

            //inform player, that auction is removed
            SendAuctionCommandResult(auction, AuctionAction.Cancel, AuctionError.Ok);

            // Now remove the auction
            player.SaveInventoryAndGoldToDB(trans);
            auction.DeleteFromDB(trans);
            DB.Characters.CommitTransaction(trans);

            Global.AuctionMgr.RemoveAItem(auction.itemGUIDLow);
            auctionHouse.RemoveAuction(auction);
        }
예제 #17
0
        void HandleAuctionPlaceBid(AuctionPlaceBid packet)
        {
            if (packet.AuctionItemID == 0 || packet.BidAmount == 0)
            {
                return; // check for cheaters
            }
            Creature creature = GetPlayer().GetNPCIfCanInteractWith(packet.Auctioneer, NPCFlags.Auctioneer, NPCFlags2.None);

            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 && Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(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);
        }
예제 #18
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);
        }