public void HandleRequest(IRequest request)
        {
            using (var scope = Db.CreateTransaction())
            {
                var buyer                     = request.Session.Character;
                var itemDefinition            = request.Data.GetOrDefault <int>(k.definition);
                var duration                  = request.Data.GetOrDefault <int>(k.duration);
                var pricePerPiece             = request.Data.GetOrDefault <double>(k.price);
                var quantity                  = request.Data.GetOrDefault(k.quantity, 1);
                var useBuyerCorporationWallet = request.Data.GetOrDefault <int>(k.useCorporationWallet) == 1;
                var forMyCorporation          = request.Data.GetOrDefault <int>(k.forMembersOf) == 1;

                quantity.ThrowIfLessOrEqual(0, ErrorCodes.AmountTooLow);

                buyer.IsDocked.ThrowIfFalse(ErrorCodes.CharacterHasToBeDocked);
                buyer.CheckPrivilegedTransactionsAndThrowIfFailed();

                pricePerPiece.ThrowIfLessOrEqual(0, ErrorCodes.IllegalMarketPrice);

                duration.ThrowIfLessOrEqual(1, ErrorCodes.MinimalDurationNotReached);

                var ed = EntityDefault.Get(itemDefinition).ThrowIfEqual(EntityDefault.None, ErrorCodes.DefinitionNotSupported);

                ed.IsSellable.ThrowIfFalse(ErrorCodes.ItemNotSellable);

                var market = buyer.GetCurrentDockingBase().GetMarketOrThrow();

                var realMarketFee = Market.GetRealMarketFee(buyer, duration);

                var corporationEid = buyer.CorporationEid;

                //cash market fee anyways
                _marketHelper.CashInMarketFee(buyer, useBuyerCorporationWallet, realMarketFee);

                buyer.GetCurrentDockingBase().AddCentralBank(TransactionType.marketFee, realMarketFee);

                if (_marketInfoService.CheckAveragePrice)
                {
                    var avgPrice = _marketHandler.GetAveragePriceByMarket(market, itemDefinition);

                    if (avgPrice != null && avgPrice.AveragePrice > 0)
                    {
                        if (pricePerPiece < avgPrice.AveragePrice * (1 - _marketInfoService.Margin) || pricePerPiece > avgPrice.AveragePrice * (1 + _marketInfoService.Margin))
                        {
                            throw new PerpetuumException(ErrorCodes.PriceOutOfAverageRange);
                        }
                    }
                }

                var publicContainer = buyer.GetPublicContainerWithItems();

                long?forMembersOf = null;
                if (forMyCorporation)
                {
                    if (!DefaultCorporationDataCache.IsCorporationDefault(corporationEid))
                    {
                        forMembersOf = corporationEid;
                    }
                    else
                    {
                        forMyCorporation = false;
                    }
                }

                if (!forMyCorporation)
                {
                    _marketHelper.CheckBuyOrderCounts(buyer).ThrowIfFalse(ErrorCodes.MarketItemsExceed);
                }

                var lowestSellOrder = _marketOrderRepository.GetLowestSellOrder(itemDefinition, pricePerPiece, buyer.Eid, market, corporationEid);

                if (!forMyCorporation && lowestSellOrder != null)
                {
                    // requested item was found on the market, make immediate transaction
                    market.FulfillBuyOrderInstantly(buyer, useBuyerCorporationWallet, lowestSellOrder, pricePerPiece, duration, quantity, publicContainer, forMembersOf);
                }
                else
                {
                    var deposit = pricePerPiece * quantity;

                    // take the deposit from the character
                    _marketHelper.CashIn(buyer, useBuyerCorporationWallet, pricePerPiece, itemDefinition, quantity, TransactionType.buyOrderDeposit);

                    //store the deposit in the central bank
                    market.AddCentralBank(TransactionType.buyOrderDeposit, deposit);

                    // create a new buy order
                    var newBuyOrder = market.CreateBuyOrder(buyer, itemDefinition, duration, pricePerPiece, quantity, useBuyerCorporationWallet, forMembersOf);

                    var data = new Dictionary <string, object>
                    {
                        { k.buyOrder, newBuyOrder.ToDictionary() }
                    };

                    Message.Builder.SetCommand(Commands.MarketBuyOrderCreated)
                    .WithData(data)
                    .ToCharacter(buyer)
                    .Send();
                }

                publicContainer.Save();

                Message.Builder.SetCommand(Commands.ListContainer)
                .WithData(publicContainer.ToDictionary())
                .ToCharacter(buyer)
                .Send();

                scope.Complete();
            }
        }
Пример #2
0
        public void HandleRequest(IRequest request)
        {
            using (var scope = Db.CreateTransaction())
            {
                var seller        = request.Session.Character;
                var itemEid       = request.Data.GetOrDefault <long>(k.itemEID);
                var duration      = request.Data.GetOrDefault <int>(k.duration);
                var pricePerPiece = request.Data.GetOrDefault <double>(k.price);
                var quantity      = request.Data.GetOrDefault <int>(k.quantity);
                var useSellerCorporationWallet = request.Data.GetOrDefault <int>(k.useCorporationWallet) == 1;
                var containerEid     = request.Data.GetOrDefault <long>(k.container);
                var forMyCorporation = request.Data.GetOrDefault <int>(k.forMembersOf) == 1;
                var targetOrderId    = request.Data.GetOrDefault <int>(k.targetOrder);

                seller.IsDocked.ThrowIfFalse(ErrorCodes.CharacterHasToBeDocked);
                seller.CheckPrivilegedTransactionsAndThrowIfFailed();

                quantity.ThrowIfLessOrEqual(0, ErrorCodes.WTFErrorMedicalAttentionSuggested);
                pricePerPiece.ThrowIfLessOrEqual(0, ErrorCodes.IllegalMarketPrice);
                duration.ThrowIfLess(1, ErrorCodes.MinimalDurationNotReached);

                var market = seller.GetCurrentDockingBase().GetMarketOrThrow();

                var corporationEid = seller.CorporationEid;

                var publicContainer = seller.GetPublicContainerWithItems();

                var sourceContainer = (Container)publicContainer.GetItemOrThrow(containerEid, true);

                long?forMembersOf = null;
                if (forMyCorporation)
                {
                    if (!DefaultCorporationDataCache.IsCorporationDefault(corporationEid))
                    {
                        forMembersOf = corporationEid;
                    }
                    else
                    {
                        forMyCorporation = false;
                    }
                }

                //unstack a fraction or take the whole item, check for conditions
                var itemToSell = market.PrepareItemForSale(seller, itemEid, quantity, sourceContainer);

                if (_marketInfoService.CheckAveragePrice)
                {
                    var avgPrice = _marketHandler.GetAveragePriceByMarket(market, itemToSell.Definition);

                    if (avgPrice != null && avgPrice.AveragePrice > 0)
                    {
                        (pricePerPiece <avgPrice.AveragePrice * (1 - _marketInfoService.Margin) ||
                                        pricePerPiece> avgPrice.AveragePrice * (1 + _marketInfoService.Margin)).ThrowIfTrue(ErrorCodes.PriceOutOfAverageRange);
                    }
                }

                MarketOrder highestBuyOrder;

                if (targetOrderId > 0)
                {
                    //target order was defined by user
                    highestBuyOrder = _marketOrderRepository.Get(targetOrderId).ThrowIfNull(ErrorCodes.ItemNotFound);

                    //for my corp?
                    highestBuyOrder.forMembersOf?.ThrowIfNotEqual(corporationEid, ErrorCodes.AccessDenied);

                    //sell to order
                    market.FulfillSellOrderInstantly(seller, useSellerCorporationWallet, highestBuyOrder, itemToSell, sourceContainer);
                }
                else
                {
                    //try to find a buy order for the currently submitted item, it finds the closest buy order
                    highestBuyOrder = _marketOrderRepository.GetHighestBuyOrder(itemToSell.Definition, pricePerPiece, seller.Eid, market, corporationEid);

                    if (!forMyCorporation && highestBuyOrder != null)
                    {
                        //sell to order
                        market.FulfillSellOrderInstantly(seller, useSellerCorporationWallet, highestBuyOrder, itemToSell, sourceContainer);
                    }
                    else
                    {
                        if (!forMyCorporation)
                        {
                            _marketHelper.CheckSellOrderCounts(seller).ThrowIfFalse(ErrorCodes.MarketItemsExceed);
                        }

                        var realMarketFee = Market.GetRealMarketFee(seller, duration);

                        //cash market fee anyways
                        _marketHelper.CashInMarketFee(seller, useSellerCorporationWallet, realMarketFee);
                        market.GetDockingBase().AddCentralBank(TransactionType.marketFee, realMarketFee);

                        market.CreateSellOrder(seller.Eid, itemToSell, duration, pricePerPiece, quantity, useSellerCorporationWallet, forMembersOf);
                    }
                }

                publicContainer.Save();

                var containerData = publicContainer.ToDictionary();

                Message.Builder.SetCommand(Commands.ListContainer)
                .WithData(containerData)
                .ToCharacter(seller)
                .Send();
                scope.Complete();
            }
        }