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