private TradingResult ServerRemote_ExecuteTrade(
            IStaticWorldObject tradingStation,
            byte lotIndex,
            TradingStationMode mode)
        {
            var character = ServerRemoteContext.Character;
            var lot       = GetPublicState(tradingStation).Lots[lotIndex];

            if (!this.SharedValidateCanTrade(tradingStation, lot, mode, character, out var error))
            {
                return(error);
            }

            Logger.Important($"Processing trading transaction: {lot}, mode={mode}", character);

            var tradingStationPrivateState   = GetPrivateState(tradingStation);
            var tradingStationItemsContainer = tradingStationPrivateState.StockItemsContainer;

            if (mode == TradingStationMode.StationSelling)
            {
                return(ServerExecuteTrade(
                           lot,
                           sellerContainers: new AggregatedItemsContainers(tradingStationItemsContainer),
                           buyerContainers: new AggregatedItemsContainers(character, includeEquipmentContainer: false),
                           isPlayerBuying: true));
            }

            // station buying
            return(ServerExecuteTrade(
                       lot,
                       sellerContainers: new AggregatedItemsContainers(character, includeEquipmentContainer: false),
                       buyerContainers: new AggregatedItemsContainers(tradingStationItemsContainer),
                       isPlayerBuying: false));
        }
        private void ServerRemote_StationSetMode(IStaticWorldObject tradingStation, TradingStationMode mode)
        {
            ValidateCanAdminAndInteract(ServerRemoteContext.Character, tradingStation);

            var publicState = GetPublicState(tradingStation);

            publicState.Mode = mode;

            foreach (var lot in publicState.Lots)
            {
                lot.State = TradingStationLotState.Disabled;
            }

            Logger.Important($"{tradingStation} mode switched to {mode}");
            ServerRefreshTradingStationLots(GetPrivateState(tradingStation), publicState);
        }
 public static void ClientSendStationSetMode(
     IStaticWorldObject tradingStation,
     TradingStationMode mode)
 {
     Instance.CallServer(_ => _.ServerRemote_StationSetMode(tradingStation, mode));
 }
        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);
        }