public TradingStationLotInfo(TradingStationLot lot) { this.ProtoItem = lot.ProtoItem; this.State = lot.State; this.LotQuantity = lot.LotQuantity; this.CountAvailable = lot.CountAvailable; this.PriceCoinShiny = lot.PriceCoinShiny; this.PriceCoinPenny = lot.PriceCoinPenny; }
public static void ServerInitialize(IStaticWorldObject tradingStation) { if (!(tradingStation.ProtoStaticWorldObject is IProtoObjectTradingStation protoTradingStation)) { throw new Exception($"Not an {typeof(IProtoObjectTradingStation).FullName}: {tradingStation}"); } TradingStationsMapMarksSystem.ServerTryAddMark(tradingStation); var privateState = GetPrivateState(tradingStation); var publicState = GetPublicState(tradingStation); if (privateState.StockItemsContainer == null) { privateState.StockItemsContainer = ServerItems.CreateContainer(tradingStation, protoTradingStation .StockItemsContainerSlotsCount); } else { ServerItems.SetSlotsCount(privateState.StockItemsContainer, protoTradingStation.StockItemsContainerSlotsCount); } var lots = publicState.Lots; if (lots == null) { publicState.Lots = lots = new NetworkSyncList <TradingStationLot>(capacity: protoTradingStation.LotsCount); } // ensure that the lots count is not exceeded while (lots.Count > protoTradingStation.LotsCount) { lots.RemoveAt(protoTradingStation.LotsCount - 1); } for (var i = 0; i < protoTradingStation.LotsCount; i++) { if (lots.Count <= i) { lots.Add(new TradingStationLot()); } else if (lots[i] == null) { lots[i] = new TradingStationLot(); } } ServerRefreshTradingStationLots(tradingStation, privateState, publicState); }
private static void ClientShowErrorNotification( TradingStationLot lot, TradingResult error, bool isPlayerBuying) { var message = error.GetDescription(); if (error == TradingResult.ErrorNotEnoughMoneyOnPlayer) { // calculate how many coins are needed var character = Client.Characters.CurrentPlayerCharacter; long deficitShiny = 0, deficitPenny = 0; if (lot.PriceCoinShiny > 0) { deficitShiny = lot.PriceCoinShiny - character.CountItemsOfType(ProtoItemCoinShiny.Value); } if (lot.PriceCoinPenny > 0) { deficitPenny = lot.PriceCoinPenny - character.CountItemsOfType(ProtoItemCoinPenny.Value); } if (deficitShiny > 0 || deficitPenny > 0) { if (deficitShiny > 0) { // ReSharper disable once CanExtractXamlLocalizableStringCSharp message += "[br]" + string.Format(NotificationNeedMoreShinyCoins, deficitShiny); } if (deficitPenny > 0) { // ReSharper disable once CanExtractXamlLocalizableStringCSharp message += "[br]" + string.Format(NotificationNeedMorePennyCoins, deficitPenny); } } } NotificationSystem.ClientShowNotification( isPlayerBuying ? NotiticationCannotBuy_Title : NotiticationCannotSell_Title, message, NotificationColor.Bad, icon: lot.ProtoItem.Icon); }
private static void ClientShowErrorNotification( TradingStationLot lot, TradingResult error, bool isPlayerBuying) { var message = error.GetDescription(); if (error == TradingResult.ErrorNotEnoughMoneyOnPlayer) { // calculate how many coins are needed long shinyNotEnough = 0, pennyNotEnough = 0; if (lot.PriceCoinShiny > 0) { shinyNotEnough = lot.PriceCoinShiny - Client.Characters.CurrentPlayerCharacter.CountItemsOfType( ProtoItemCoinShiny.Value); } if (lot.PriceCoinPenny > 0) { pennyNotEnough = lot.PriceCoinPenny - Client.Characters.CurrentPlayerCharacter.CountItemsOfType( ProtoItemCoinPenny.Value); } if (shinyNotEnough > 0 || pennyNotEnough > 0) { if (shinyNotEnough > 0) { message += Environment.NewLine + string.Format(NotificationNeedMoreShinyCoins, shinyNotEnough); } if (pennyNotEnough > 0) { message += Environment.NewLine + string.Format(NotificationNeedMorePennyCoins, pennyNotEnough); } } } NotificationSystem.ClientShowNotification( isPlayerBuying ? NotiticationCannotBuy_Title : NotiticationCannotSell_Title, message, NotificationColor.Bad, icon: lot.ProtoItem.Icon); }
public ViewModelTradingStationLot( TradingStationLot lot, Action <TradingStationLot, ViewModelTradingStationLotEditor> callbackSaveHandler = null) { this.lot = lot; this.callbackSaveHandler = callbackSaveHandler; this.lot.ClientSubscribe(_ => _.ProtoItem, _ => { this.NotifyPropertyChanged(nameof(this.ProtoItem)); this.NotifyPropertyChanged(nameof(this.Icon)); }, this); this.lot.ClientSubscribe(_ => _.ItemOnSale, _ => { this.NotifyPropertyChanged(nameof(this.ItemOnSaleInstance)); this.NotifyPropertyChanged(nameof(this.Icon)); this.RefreshOverlayControls(); }, this); this.RefreshOverlayControls(); this.lot.ClientSubscribe(_ => _.LotQuantity, _ => this.NotifyPropertyChanged(nameof(this.LotQuantity)), this); this.lot.ClientSubscribe(_ => _.PriceCoinPenny, _ => this.NotifyPropertyChanged(nameof(this.PriceCoinPenny)), this); this.lot.ClientSubscribe(_ => _.PriceCoinShiny, _ => this.NotifyPropertyChanged(nameof(this.PriceCoinShiny)), this); this.lot.ClientSubscribe(_ => _.State, _ => { this.NotifyPropertyChanged(nameof(this.IsAvailable)); this.NotifyPropertyChanged(nameof(this.IsEnabled)); this.NotifyPropertyChanged(nameof(this.ProblemText)); }, this); handItemsContainer.StateHashChanged += this.HandItemsContainerItemsChanged; }
private static void ClientShowSuccessNotification( TradingStationLot lot, bool isPlayerBuying) { Client.Audio.PlayOneShot(new SoundResource("UI/Notifications/ItemTradeSuccess")); NotificationSystem.ClientShowNotification( title: isPlayerBuying ? NotificationBoughtTitle : NotificationSoldTitle, // ReSharper disable once CanExtractXamlLocalizableStringCSharp message: $"{lot.ProtoItem.Name} ({lot.LotQuantity}).", color: NotificationColor.Good, icon: lot.ProtoItem.Icon, playSound: false); }
public ViewModelTradingStationLotEditor(TradingStationLot lot, Action callbackSave, Action callbackCancel) { this.lot = lot; this.callbackCancel = callbackCancel; this.callbackSave = callbackSave; this.selectedProtoItem = lot.ProtoItem; this.PriceCoinShiny = lot.PriceCoinShiny; this.PriceCoinPenny = lot.PriceCoinPenny; this.LotQuantity = Math.Max((ushort)1, lot.LotQuantity); // no need to order as the ordering is applied later this.allItemsList = Api.FindProtoEntities <IProtoItem>().ToList(); this.existingItemsList = this.GetExistingItemsList(); this.RefreshLists(); }
public static void ClientSendTradingLotModification( TradingStationLot lot, IProtoItem protoItem, ushort lotQuantity, ushort priceCoinPenny, ushort priceCoinShiny) { var tradingStation = lot.GameObject as IStaticWorldObject; var publicState = GetPublicState(tradingStation); var lotIndex = publicState.Lots.IndexOf(lot); Instance.CallServer( _ => _.ServerRemote_SetTradingLot(tradingStation, (byte)lotIndex, protoItem, lotQuantity, priceCoinPenny, priceCoinShiny)); }
public static async void ClientRequestExecuteTrade( IStaticWorldObject tradingStation, TradingStationLot lot, bool isPlayerBuying) { var mode = isPlayerBuying ? TradingStationMode.StationSelling : TradingStationMode.StationBuying; if (!Instance.SharedValidateCanTrade(tradingStation, lot, mode, Client.Characters.CurrentPlayerCharacter, out var checkResult)) { ClientShowErrorNotification(lot, checkResult, isPlayerBuying); return; } var publicState = GetPublicState(tradingStation); var lotIndex = publicState.Lots.IndexOf(lot); checkResult = await Instance.CallServer( _ => _.ServerRemote_ExecuteTrade(tradingStation, (byte)lotIndex, mode)); if (checkResult != TradingResult.Success) { ClientShowErrorNotification(lot, checkResult, isPlayerBuying); } else { ClientShowSuccessNotification(lot, isPlayerBuying); } }
public ViewModelTradingStationLotEditor( TradingStationLot lot, Action callbackSave, Action callbackCancel) { this.lot = lot; this.IsStationBuying = ProtoObjectTradingStation.GetPublicState( (IStaticWorldObject)lot.GameObject).Mode == TradingStationMode.StationBuying; this.callbackCancel = callbackCancel; this.callbackSave = callbackSave; this.selectedProtoItem = lot.ProtoItem; this.PriceCoinShiny = lot.PriceCoinShiny; this.PriceCoinPenny = lot.PriceCoinPenny; this.LotQuantity = Math.Max((ushort)1, lot.LotQuantity); this.MinQualityPercent = lot.MinQualityPercent; // no need to order as the ordering is applied later this.allItemsList = Api.FindProtoEntities <IProtoItem>().ToList(); this.existingItemsList = this.GetExistingItemsList(); this.RefreshLists(); }
private bool SharedValidateCanTrade( IStaticWorldObject tradingStation, TradingStationLot lot, TradingStationMode mode, ICharacter character, out TradingResult error) { var protoTradingStation = tradingStation.ProtoStaticWorldObject; var publicState = GetPublicState(tradingStation); if (publicState.Mode != mode) { throw new Exception("Trading station has different trading mode"); } if (!protoTradingStation .SharedCanInteract(character, tradingStation, writeToLog: false)) { error = TradingResult.ErrorCannotInteract; return(false); } var lots = publicState.Lots; var isLotFound = false; foreach (var otherLot in lots) { if (otherLot == lot) { // found lot isLotFound = true; break; } } if (!isLotFound) { error = TradingResult.ErrorLotNotFound; return(false); } if (lot.State == TradingStationLotState.Disabled) { error = TradingResult.ErrorLotNotActive; return(false); } if (mode == TradingStationMode.StationBuying) { // ensure that the character has required item count to sell if (lot.LotQuantity > character.CountItemsOfType(lot.ProtoItem)) { error = TradingResult.ErrorNotEnoughItemsOnPlayer; return(false); } if (IsServer) { // ensure station has enough money to pay for these items var tradingStationItemsContainer = GetPrivateState(tradingStation).StockItemsContainer; if (!tradingStationItemsContainer.ContainsItemsOfType( ProtoItemCoinPenny.Value, requiredCount: lot.PriceCoinPenny) || !tradingStationItemsContainer.ContainsItemsOfType( ProtoItemCoinShiny.Value, requiredCount: lot.PriceCoinShiny)) { error = TradingResult.ErrorNotEnoughMoneyOnStation; return(false); } } } else // if station selling { if (lot.CountAvailable == 0) { error = TradingResult.ErrorNotEnoughItemsOnStation; return(false); } // ensure player has enough money to pay for these items if (!character.ContainsItemsOfType( ProtoItemCoinPenny.Value, requiredCount: lot.PriceCoinPenny) || !character.ContainsItemsOfType( ProtoItemCoinShiny.Value, requiredCount: lot.PriceCoinShiny)) { error = TradingResult.ErrorNotEnoughMoneyOnPlayer; return(false); } } // no error error = TradingResult.Success; return(true); }
private static TradingResult ServerExecuteTrade( TradingStationLot lot, IItemsContainerProvider sellerContainers, IItemsContainerProvider buyerContainers, bool isPlayerBuying) { // find items to buy by other party if (!SharedTryFindItemsOfType(sellerContainers, lot.ProtoItem, lot.LotQuantity, out var itemsToSell)) { return(isPlayerBuying ? TradingResult.ErrorNotEnoughItemsOnStation : TradingResult.ErrorNotEnoughItemsOnPlayer); } // try to find money to pay to other party var countCoinPenny = (uint)lot.PriceCoinPenny; var countCoinShiny = (uint)lot.PriceCoinShiny; if (!SharedTryFindItemsOfType(buyerContainers, ProtoItemCoinPenny.Value, countCoinPenny, out _) || !SharedTryFindItemsOfType(buyerContainers, ProtoItemCoinShiny.Value, countCoinShiny, out _)) { return(isPlayerBuying ? TradingResult.ErrorNotEnoughMoneyOnStation : TradingResult.ErrorNotEnoughMoneyOnPlayer); } // ensure there is enough space to store the sold items if (!ServerItems.CanCreateItem(buyerContainers, lot.ProtoItem, lot.LotQuantity)) { return(isPlayerBuying ? TradingResult.ErrorNotEnoughSpaceOnPlayerForPurchasedItem : TradingResult.ErrorNotEnoughSpaceOnStationForSoldItem); } // try create money in the source containers var sourceContainerResult = new CreateItemResult() { IsEverythingCreated = true }; if (lot.PriceCoinPenny > 0) { sourceContainerResult.MergeWith( ServerItems.CreateItem(ProtoItemCoinPenny.Value, sellerContainers, countCoinPenny)); } if (lot.PriceCoinShiny > 0) { sourceContainerResult.MergeWith( ServerItems.CreateItem(ProtoItemCoinShiny.Value, sellerContainers, countCoinShiny)); } if (!sourceContainerResult.IsEverythingCreated) { sourceContainerResult.Rollback(); // TODO: check this return(isPlayerBuying ? TradingResult.ErrorNotEnoughSpaceOnStationForSoldItem : TradingResult.ErrorNotEnoughSpaceOnPlayerForPurchasedItem); } // try moving (bought) items var itemsCountToDestroyRemains = (int)lot.LotQuantity; foreach (var item in itemsToSell) { if (itemsCountToDestroyRemains <= 0) { break; } ServerItems.MoveOrSwapItem(item, buyerContainers, out var movedCount, countToMove: (ushort)itemsCountToDestroyRemains); itemsCountToDestroyRemains -= movedCount; } if (itemsCountToDestroyRemains > 0) { // should be impossible Logger.Error( "Cannot move all sold items! But we've verified that the sellerContainers have them all..."); } if (countCoinPenny > 0) { ServerItems.DestroyItemsOfType(buyerContainers, ProtoItemCoinPenny.Value, countCoinPenny, out _); } if (countCoinShiny > 0) { ServerItems.DestroyItemsOfType(buyerContainers, ProtoItemCoinShiny.Value, countCoinShiny, out _); } Logger.Important($"Successfully completed trading transaction: {lot}"); return(TradingResult.Success); }
public WindowTradingStationLotEditor(TradingStationLot lot) { this.lot = lot; }