Beispiel #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);
        }
Beispiel #2
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);
            }
        }
Beispiel #3
0
        void HandleAcceptTrade(AcceptTrade acceptTrade)
        {
            TradeData my_trade = GetPlayer().GetTradeData();

            if (my_trade == null)
            {
                return;
            }

            Player trader = my_trade.GetTrader();

            TradeData his_trade = trader.GetTradeData();

            if (his_trade == null)
            {
                return;
            }

            Item[] myItems  = new Item[(int)TradeSlots.Count];
            Item[] hisItems = new Item[(int)TradeSlots.Count];

            // set before checks for propertly undo at problems (it already set in to client)
            my_trade.SetAccepted(true);

            TradeStatusPkt info = new TradeStatusPkt();

            if (his_trade.GetServerStateIndex() != acceptTrade.StateIndex)
            {
                info.Status = TradeStatus.StateChanged;
                SendTradeStatus(info);
                my_trade.SetAccepted(false);
                return;
            }

            if (!GetPlayer().IsWithinDistInMap(trader, 11.11f, false))
            {
                info.Status = TradeStatus.TooFarAway;
                SendTradeStatus(info);
                my_trade.SetAccepted(false);
                return;
            }

            // not accept case incorrect money amount
            if (!GetPlayer().HasEnoughMoney(my_trade.GetMoney()))
            {
                info.Status    = TradeStatus.Failed;
                info.BagResult = InventoryResult.NotEnoughMoney;
                SendTradeStatus(info);
                my_trade.SetAccepted(false, true);
                return;
            }

            // not accept case incorrect money amount
            if (!trader.HasEnoughMoney(his_trade.GetMoney()))
            {
                info.Status    = TradeStatus.Failed;
                info.BagResult = InventoryResult.NotEnoughMoney;
                trader.GetSession().SendTradeStatus(info);
                his_trade.SetAccepted(false, true);
                return;
            }

            if (GetPlayer().GetMoney() >= PlayerConst.MaxMoneyAmount - his_trade.GetMoney())
            {
                info.Status    = TradeStatus.Failed;
                info.BagResult = InventoryResult.TooMuchGold;
                SendTradeStatus(info);
                my_trade.SetAccepted(false, true);
                return;
            }

            if (trader.GetMoney() >= PlayerConst.MaxMoneyAmount - my_trade.GetMoney())
            {
                info.Status    = TradeStatus.Failed;
                info.BagResult = InventoryResult.TooMuchGold;
                trader.GetSession().SendTradeStatus(info);
                his_trade.SetAccepted(false, true);
                return;
            }

            // not accept if some items now can't be trade (cheating)
            for (byte i = 0; i < (byte)TradeSlots.Count; ++i)
            {
                Item item = my_trade.GetItem((TradeSlots)i);
                if (item)
                {
                    if (!item.CanBeTraded(false, true))
                    {
                        info.Status = TradeStatus.Cancelled;
                        SendTradeStatus(info);
                        return;
                    }

                    if (item.IsBindedNotWith(trader))
                    {
                        info.Status    = TradeStatus.Failed;
                        info.BagResult = InventoryResult.TradeBoundItem;
                        SendTradeStatus(info);
                        return;
                    }
                }
                item = his_trade.GetItem((TradeSlots)i);
                if (item)
                {
                    if (!item.CanBeTraded(false, true))
                    {
                        info.Status = TradeStatus.Cancelled;
                        SendTradeStatus(info);
                        return;
                    }
                }
            }

            if (his_trade.IsAccepted())
            {
                SetAcceptTradeMode(my_trade, his_trade, myItems, hisItems);

                Spell            my_spell   = null;
                SpellCastTargets my_targets = new SpellCastTargets();

                Spell            his_spell   = null;
                SpellCastTargets his_targets = new SpellCastTargets();

                // not accept if spell can't be casted now (cheating)
                uint my_spell_id = my_trade.GetSpell();
                if (my_spell_id != 0)
                {
                    SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(my_spell_id);
                    Item      castItem   = my_trade.GetSpellCastItem();

                    if (spellEntry == null || !his_trade.GetItem(TradeSlots.NonTraded) ||
                        (my_trade.HasSpellCastItem() && !castItem))
                    {
                        ClearAcceptTradeMode(my_trade, his_trade);
                        ClearAcceptTradeMode(myItems, hisItems);

                        my_trade.SetSpell(0);
                        return;
                    }

                    my_spell            = new Spell(GetPlayer(), spellEntry, TriggerCastFlags.FullMask);
                    my_spell.m_CastItem = castItem;
                    my_targets.SetTradeItemTarget(GetPlayer());
                    my_spell.m_targets = my_targets;

                    SpellCastResult res = my_spell.CheckCast(true);
                    if (res != SpellCastResult.SpellCastOk)
                    {
                        my_spell.SendCastResult(res);

                        ClearAcceptTradeMode(my_trade, his_trade);
                        ClearAcceptTradeMode(myItems, hisItems);

                        my_spell.Dispose();
                        my_trade.SetSpell(0);
                        return;
                    }
                }

                // not accept if spell can't be casted now (cheating)
                uint his_spell_id = his_trade.GetSpell();
                if (his_spell_id != 0)
                {
                    SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(his_spell_id);
                    Item      castItem   = his_trade.GetSpellCastItem();

                    if (spellEntry == null || !my_trade.GetItem(TradeSlots.NonTraded) || (his_trade.HasSpellCastItem() && !castItem))
                    {
                        his_trade.SetSpell(0);

                        ClearAcceptTradeMode(my_trade, his_trade);
                        ClearAcceptTradeMode(myItems, hisItems);
                        return;
                    }

                    his_spell            = new Spell(trader, spellEntry, TriggerCastFlags.FullMask);
                    his_spell.m_CastItem = castItem;
                    his_targets.SetTradeItemTarget(trader);
                    his_spell.m_targets = his_targets;

                    SpellCastResult res = his_spell.CheckCast(true);
                    if (res != SpellCastResult.SpellCastOk)
                    {
                        his_spell.SendCastResult(res);

                        ClearAcceptTradeMode(my_trade, his_trade);
                        ClearAcceptTradeMode(myItems, hisItems);

                        my_spell.Dispose();
                        his_spell.Dispose();

                        his_trade.SetSpell(0);
                        return;
                    }
                }

                // inform partner client
                info.Status = TradeStatus.Accepted;
                trader.GetSession().SendTradeStatus(info);

                // test if item will fit in each inventory
                TradeStatusPkt myCanCompleteInfo  = new TradeStatusPkt();
                TradeStatusPkt hisCanCompleteInfo = new TradeStatusPkt();
                hisCanCompleteInfo.BagResult = trader.CanStoreItems(myItems, (int)TradeSlots.TradedCount, ref hisCanCompleteInfo.ItemID);
                myCanCompleteInfo.BagResult  = GetPlayer().CanStoreItems(hisItems, (int)TradeSlots.TradedCount, ref myCanCompleteInfo.ItemID);

                ClearAcceptTradeMode(myItems, hisItems);

                // in case of missing space report error
                if (myCanCompleteInfo.BagResult != InventoryResult.Ok)
                {
                    ClearAcceptTradeMode(my_trade, his_trade);

                    myCanCompleteInfo.Status = TradeStatus.Failed;
                    trader.GetSession().SendTradeStatus(myCanCompleteInfo);
                    myCanCompleteInfo.FailureForYou = true;
                    SendTradeStatus(myCanCompleteInfo);
                    my_trade.SetAccepted(false);
                    his_trade.SetAccepted(false);
                    return;
                }
                else if (hisCanCompleteInfo.BagResult != InventoryResult.Ok)
                {
                    ClearAcceptTradeMode(my_trade, his_trade);

                    hisCanCompleteInfo.Status = TradeStatus.Failed;
                    SendTradeStatus(hisCanCompleteInfo);
                    hisCanCompleteInfo.FailureForYou = true;
                    trader.GetSession().SendTradeStatus(hisCanCompleteInfo);
                    my_trade.SetAccepted(false);
                    his_trade.SetAccepted(false);
                    return;
                }

                // execute trade: 1. remove
                for (byte i = 0; i < (int)TradeSlots.TradedCount; ++i)
                {
                    if (myItems[i])
                    {
                        myItems[i].SetGiftCreator(GetPlayer().GetGUID());
                        GetPlayer().MoveItemFromInventory(myItems[i].GetBagSlot(), myItems[i].GetSlot(), true);
                    }
                    if (hisItems[i])
                    {
                        hisItems[i].SetGiftCreator(trader.GetGUID());
                        trader.MoveItemFromInventory(hisItems[i].GetBagSlot(), hisItems[i].GetSlot(), true);
                    }
                }

                // execute trade: 2. store
                MoveItems(myItems, hisItems);

                // logging money
                if (HasPermission(RBACPermissions.LogGmTrade))
                {
                    if (my_trade.GetMoney() > 0)
                    {
                        Log.outCommand(GetPlayer().GetSession().GetAccountId(), "GM {0} (Account: {1}) give money (Amount: {2}) to player: {3} (Account: {4})",
                                       GetPlayer().GetName(), GetPlayer().GetSession().GetAccountId(), my_trade.GetMoney(), trader.GetName(), trader.GetSession().GetAccountId());
                    }

                    if (his_trade.GetMoney() > 0)
                    {
                        Log.outCommand(GetPlayer().GetSession().GetAccountId(), "GM {0} (Account: {1}) give money (Amount: {2}) to player: {3} (Account: {4})",
                                       trader.GetName(), trader.GetSession().GetAccountId(), his_trade.GetMoney(), GetPlayer().GetName(), GetPlayer().GetSession().GetAccountId());
                    }
                }


                // update money
                GetPlayer().ModifyMoney(-(long)my_trade.GetMoney());
                GetPlayer().ModifyMoney((long)his_trade.GetMoney());
                trader.ModifyMoney(-(long)his_trade.GetMoney());
                trader.ModifyMoney((long)my_trade.GetMoney());

                if (my_spell)
                {
                    my_spell.Prepare(my_targets);
                }

                if (his_spell)
                {
                    his_spell.Prepare(his_targets);
                }

                // cleanup
                ClearAcceptTradeMode(my_trade, his_trade);
                GetPlayer().SetTradeData(null);
                trader.SetTradeData(null);

                // desynchronized with the other saves here (SaveInventoryAndGoldToDB() not have own transaction guards)
                SQLTransaction trans = new SQLTransaction();
                GetPlayer().SaveInventoryAndGoldToDB(trans);
                trader.SaveInventoryAndGoldToDB(trans);
                DB.Characters.CommitTransaction(trans);

                info.Status = TradeStatus.Complete;
                trader.GetSession().SendTradeStatus(info);
                SendTradeStatus(info);
            }
            else
            {
                info.Status = TradeStatus.Accepted;
                trader.GetSession().SendTradeStatus(info);
            }
        }
Beispiel #4
0
        void MoveItems(Item[] myItems, Item[] hisItems)
        {
            Player trader = GetPlayer().GetTrader();

            if (!trader)
            {
                return;
            }

            for (byte i = 0; i < (int)TradeSlots.TradedCount; ++i)
            {
                List <ItemPosCount> traderDst = new List <ItemPosCount>();
                List <ItemPosCount> playerDst = new List <ItemPosCount>();
                bool traderCanTrade           = (myItems[i] == null || trader.CanStoreItem(ItemConst.NullBag, ItemConst.NullSlot, traderDst, myItems[i], false) == InventoryResult.Ok);
                bool playerCanTrade           = (hisItems[i] == null || GetPlayer().CanStoreItem(ItemConst.NullBag, ItemConst.NullSlot, playerDst, hisItems[i], false) == InventoryResult.Ok);
                if (traderCanTrade && playerCanTrade)
                {
                    // Ok, if trade item exists and can be stored
                    // If we trade in both directions we had to check, if the trade will work before we actually do it
                    // A roll back is not possible after we stored it
                    if (myItems[i])
                    {
                        // logging
                        Log.outDebug(LogFilter.Network, "partner storing: {0}", myItems[i].GetGUID().ToString());

                        if (HasPermission(RBACPermissions.LogGmTrade))
                        {
                            Log.outCommand(_player.GetSession().GetAccountId(), "GM {0} (Account: {1}) trade: {2} (Entry: {3} Count: {4}) to player: {5} (Account: {6})",
                                           GetPlayer().GetName(), GetPlayer().GetSession().GetAccountId(), myItems[i].GetTemplate().GetName(), myItems[i].GetEntry(), myItems[i].GetCount(),
                                           trader.GetName(), trader.GetSession().GetAccountId());
                        }

                        // adjust time (depends on /played)
                        if (myItems[i].HasItemFlag(ItemFieldFlags.BopTradeable))
                        {
                            myItems[i].SetCreatePlayedTime(trader.GetTotalPlayedTime() - (GetPlayer().GetTotalPlayedTime() - myItems[i].m_itemData.CreatePlayedTime));
                        }
                        // store
                        trader.MoveItemToInventory(traderDst, myItems[i], true, true);
                    }
                    if (hisItems[i])
                    {
                        // logging
                        Log.outDebug(LogFilter.Network, "player storing: {0}", hisItems[i].GetGUID().ToString());

                        if (HasPermission(RBACPermissions.LogGmTrade))
                        {
                            Log.outCommand(trader.GetSession().GetAccountId(), "GM {0} (Account: {1}) trade: {2} (Entry: {3} Count: {4}) to player: {5} (Account: {6})",
                                           trader.GetName(), trader.GetSession().GetAccountId(), hisItems[i].GetTemplate().GetName(), hisItems[i].GetEntry(), hisItems[i].GetCount(),
                                           GetPlayer().GetName(), GetPlayer().GetSession().GetAccountId());
                        }


                        // adjust time (depends on /played)
                        if (hisItems[i].HasItemFlag(ItemFieldFlags.BopTradeable))
                        {
                            hisItems[i].SetCreatePlayedTime(GetPlayer().GetTotalPlayedTime() - (trader.GetTotalPlayedTime() - hisItems[i].m_itemData.CreatePlayedTime));
                        }
                        // store
                        GetPlayer().MoveItemToInventory(playerDst, hisItems[i], true, true);
                    }
                }
                else
                {
                    // in case of fatal error log error message
                    // return the already removed items to the original owner
                    if (myItems[i])
                    {
                        if (!traderCanTrade)
                        {
                            Log.outError(LogFilter.Network, "trader can't store item: {0}", myItems[i].GetGUID().ToString());
                        }
                        if (GetPlayer().CanStoreItem(ItemConst.NullBag, ItemConst.NullSlot, playerDst, myItems[i], false) == InventoryResult.Ok)
                        {
                            GetPlayer().MoveItemToInventory(playerDst, myItems[i], true, true);
                        }
                        else
                        {
                            Log.outError(LogFilter.Network, "player can't take item back: {0}", myItems[i].GetGUID().ToString());
                        }
                    }
                    // return the already removed items to the original owner
                    if (hisItems[i])
                    {
                        if (!playerCanTrade)
                        {
                            Log.outError(LogFilter.Network, "player can't store item: {0}", hisItems[i].GetGUID().ToString());
                        }
                        if (trader.CanStoreItem(ItemConst.NullBag, ItemConst.NullSlot, traderDst, hisItems[i], false) == InventoryResult.Ok)
                        {
                            trader.MoveItemToInventory(traderDst, hisItems[i], true, true);
                        }
                        else
                        {
                            Log.outError(LogFilter.Network, "trader can't take item back: {0}", hisItems[i].GetGUID().ToString());
                        }
                    }
                }
            }
        }
Beispiel #5
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);
        }
Beispiel #6
0
        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 = Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(sender_guid);

                            if (!Global.CharacterCacheStorage.GetCharacterNameByGuid(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 = Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(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);
            }
        }