예제 #1
0
        public Dictionary <Guid, string> GetTraderNames(IEnumerable <Guid> traderIds)
        {
            var currentUser = GetCurrentTraderInfo();
            var ret         = new Dictionary <Guid, string>();

            foreach (var traderId in traderIds.Distinct())
            {
                if (Traders.TryGetValue(traderId, out Trader trader))
                {
                    ret.Add(traderId, trader.Name);
                }
            }

            Log.Information("Retrieved {count} trader names for user {UserId}", ret.Count, currentUser.Id);
            return(ret);
        }
예제 #2
0
        public bool AcceptTrade(Guid offerId)
        {
            var buyer = GetCurrentTraderInfo();

            if (buyer == null)
            {
                Log.Warning("Failed to accept trade offer {TradeOfferId} for session {SessionId} because no user is logged on", offerId, OperationContext.Current.SessionId);
            }

            if (!TradeOffers.TryGetValue(offerId, out TradeOffer tradeOffer))
            {
                Log.Information("Trader {UserId} attempted to accept trade offer {TradeOfferId} but it was not available", buyer.Id, offerId);
                return(false);
            }

            if (!Traders.TryGetValue(tradeOffer.SellerId, out Trader seller))
            {
                Log.Information("Trader {UserId} attempted to accept trade offer {TradeOfferId} but seller ({UserId}) was not found.", buyer.Id, offerId, tradeOffer.SellerId);
                return(false);
            }

            // Lock the buyer to make sure that they don't make multiple transactions at once, potentially overspending
            lock (buyer)
            {
                if (!TraderHasFunds(buyer, tradeOffer.Asking))
                {
                    Log.Information("Trader {UserId} attempted to accept trade offer {TradeOfferId} but had insufficient funds", buyer.Id, offerId);
                    return(false);
                }

                // If all else checks out (buyer funds, seller presence, etc.), attempt to grab the trade offer and remove
                // it from availabilty
                if (!TradeOffers.TryRemove(offerId, out tradeOffer))
                {
                    Log.Information("Trader {UserId} attempted to accept trade offer {TradeOfferId} but it was not available (2)", buyer.Id, offerId);
                    return(false);
                }

                // Transfer beans
                RemoveBeans(buyer, tradeOffer.Asking);
            }

            // Beans can be added without locking. Nested locks for the buyer and seller would cause deadlocks.
            AddBeans(buyer, tradeOffer.Offering);
            AddBeans(seller, tradeOffer.Asking);
            Log.Information("Trader {UserId} has accepted trade offer {TradeOfferId} from seller {UserId}", buyer.Id, offerId, tradeOffer.SellerId);

            // Alert traders that the trade has been accepted and is no longer available
            var invalidCallbacks = new List <string>();

            foreach (var callback in Callbacks)
            {
                try
                {
                    callback.Value?.TradeAccepted(tradeOffer, buyer.Id);
                    callback.Value?.RemoveTradeOffer(offerId);
                }
                catch (CommunicationException)
                {
                    Log.Warning("Session {SessionId}'s channel closed unexpectedly; will remove from callback list", callback.Key);
                    invalidCallbacks.Add(callback.Key);
                }
            }
            foreach (var id in invalidCallbacks)
            {
                Callbacks.TryRemove(id, out _);
            }

            return(true);
        }