/// <summary> /// Returns null if either ship is already trading. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> ShipShipTrade TryInitializeTrade(IShip a, IShip b) { lock (TRADELOCK) { if (_shipIDToTradeID.ContainsKey(a.Id)) { return(null); } if (_shipIDToTradeID.ContainsKey(b.Id)) { return(null); } Player aPlayer = a.GetPlayer(); Player bPlayer = b.GetPlayer(); if (!aPlayer.IsOnline || !bPlayer.IsOnline) { return(null); } if (_tradingPlayerIDs.Contains(aPlayer.Id) || _tradingPlayerIDs.Contains(bPlayer.Id)) { return(null); } ShipShipTrade t = new ShipShipTrade(a, b, _tradeIDManager.PopFreeID(), DateTime.Now, (int)_slaveIDProvider.SlaveID, TimeKeeper.MsSinceInitialization); _shipShipTrades.TryAdd(t.Id, t); _tradingPlayerIDs.Add(aPlayer.Id); _tradingPlayerIDs.Add(bPlayer.Id); _shipIDToTradeID.TryAdd(a.Id, t.Id); _shipIDToTradeID.TryAdd(b.Id, t.Id); return(t); } }
async Task <TradeResult> _executeTrade(ShipShipTrade t) { if (t.IsProcessed || !t.Pending) { return(TradeResult.TradeAlreadyProcessed); } t.Pending = false; CargoHandler_ReadOnlyVM <CargoHandlerModel> cargoA = t.ShipA.GetCargo(); CargoHandler_ReadOnlyVM <CargoHandlerModel> cargoB = t.ShipB.GetCargo(); float holdsAfterTrade_A = cargoA.FilledHolds - t.CargoOffered_A.FilledHolds + t.CargoOffered_B.FilledHolds; float holdsAfterTrade_B = cargoB.FilledHolds - t.CargoOffered_B.FilledHolds + t.CargoOffered_A.FilledHolds; if (holdsAfterTrade_A > cargoA.TotalHolds) { t.IsProcessed = true; return(TradeResult.ShipANotEnoughCargoSpace); } if (holdsAfterTrade_B > cargoB.TotalHolds) { t.IsProcessed = true; return(TradeResult.ShipBNotEnoughCargoSpace); } CargoTransactionSequence ts = new CargoTransactionSequence(); foreach (var v in t.CargoOffered_A.StatefulCargo) { ts.Add(new TransactionRemoveStatefulCargo(t.ShipA, StatefulCargoTypes.Null, v.Value.Id, true)); ts.Add(new TransactionAddStatefulCargo(t.ShipB, null, true)); } foreach (var v in t.CargoOffered_B.StatefulCargo) { ts.Add(new TransactionRemoveStatefulCargo(t.ShipB, StatefulCargoTypes.Null, v.Value.Id, true)); ts.Add(new TransactionAddStatefulCargo(t.ShipA, null, true)); } foreach (var v in t.CargoOffered_A.StatelessCargo) { ts.Add(new TransactionRemoveStatelessCargo(t.ShipA, v.Key, v.Value.Quantity)); ts.Add(new TransactionAddStatelessCargo(t.ShipB, v.Key, v.Value.Quantity, true)); } foreach (var v in t.CargoOffered_B.StatelessCargo) { ts.Add(new TransactionRemoveStatelessCargo(t.ShipB, v.Key, v.Value.Quantity)); ts.Add(new TransactionAddStatelessCargo(t.ShipA, v.Key, v.Value.Quantity, true)); } _cargoSynchronizer.RequestAtomicTransactionSequence(ts); var res = await ts.ResultTask; if (res == CargoResult.Success) { t.IsProcessed = true; //Record the trade in the DB, fire and forget t.DateTime = DateTime.Now; _databaseManager.SaveAsync(t); _databaseManager.SaveAsync((ISerializable)t.ShipA); _databaseManager.SaveAsync((ISerializable)t.ShipB); return(TradeResult.Success); } else { return(TradeResult.FailedReasonUnknown);//TODO: Implement translator } }