public static ClientZoneInfo Create(IReadOnlyZoneInfo zoneInfo)
 => new ClientZoneInfo
 {
     bitmapLayerOne = TilesetProvider
                      .GetAnimatedCellBitmapSetIdFor(zoneInfo, x => x.LayerOne),
     bitmapLayerTwo = TilesetProvider
                      .GetAnimatedCellBitmapSetIdFor(zoneInfo, x => x.LayerTwo.WithResultIfHasMatch(y => y)),
     x = zoneInfo.Point.X,
     y = zoneInfo.Point.Y
 };
Exemple #2
0
        public GameServer(ISimulationSession simulationSession, string url, bool controlVehicles)
        {
            if (string.IsNullOrWhiteSpace(url))
            {
                throw new ArgumentException("", nameof(url));
            }

            _simulationSession = simulationSession ?? throw new ArgumentNullException(nameof(simulationSession));
            _url             = url;
            _controlVehicles = controlVehicles;

            List <ClientZoneInfo> previous = null;

            _simulationSession.OnAreaMessage            += SimulationSession_OnAreaMessage;
            _simulationSession.OnYearAndOrMonthChanged  += SimulationSession_OnYearAndOrMonthChanged;
            _simulationSession.OnCityBudgetValueChanged += SimulationSession_OnCityBudgetValueChanged;
            _simulationSession.OnAreaHotMessage         += SimulationSession_OnAreaHotMessage;

            var zoneInfoBatchLooper = new LoopBatchEnumerator <IReadOnlyZoneInfo>(_simulationSession.Area.EnumerateZoneInfos().ToList());

            var dataMeterStateManager = new DataMeterPublishStateManager(simulationSession);

            _dataMeterStateLooper = new NeverEndingTask("Data meter state submission", async() =>
            {
                foreach (var x in dataMeterStateManager.DataMeterPublishStates)
                {
                    await Startup.WithSimulationHub(async hub =>
                    {
                        foreach (var batch in x.GetChanged().GetBatched(100))
                        {
                            await hub
                            .Clients
                            .Group(SimulationHub.GetDataMeterGroupName(x.DataMeter.WebId))
                            .SendAsync("submitDataMeterInfos", batch);
                        }
                    });
                }
            }, _cancellationTokenSource.Token, 10);

            _looper = new NeverEndingTask("SignalR Game state submission", async() =>
            {
                await Startup.WithSimulationHub(async simulationHub =>
                {
                    await simulationHub
                    .Clients
                    .All
                    .SendAsync("submitZoneInfos", zoneInfoBatchLooper.GetBatch().Select(ClientZoneInfo.Create), _cancellationTokenSource.Token);

                    var zoneInfos = _simulationSession.Area.EnumerateZoneInfos()
                                    .Select(ClientZoneInfo.Create)
                                    .ToList();

                    var toBeSubmitted = zoneInfos;

                    if (previous != null)
                    {
                        var previousUids = previous.Select(x => x.GetIdentityString()).ToHashSet();

                        toBeSubmitted = zoneInfos.Where(z => !previousUids.Contains(z.GetIdentityString())).ToList();
                    }

                    foreach (var toBeSubmittedBatch in toBeSubmitted.GetBatched(20))
                    {
                        await simulationHub
                        .Clients
                        .All
                        .SendAsync("submitZoneInfos", toBeSubmittedBatch);
                    }

                    previous = zoneInfos;

                    try
                    {
                        var list = new List <ClientVehiclePositionInfo>();
                        foreach (var vehicleController in _simulationSession.Area.EnumerateVehicleControllers())
                        {
                            vehicleController
                            .ForEachActiveVehicle(_controlVehicles,
                                                  vehicle =>
                            {
                                list.AddRange(TilesetProvider
                                              .GetBitmapsAndPointsFor(vehicle)
                                              .Select(ClientVehiclePositionInfo.Create)
                                              );
                            });
                        }

                        await simulationHub
                        .Clients
                        .All
                        .SendAsync("submitVehicleStates", list);
                    }
                    catch (Exception ex)
                    {
                        Logger.Instance.WriteLine("Possible race condition-based exception:: " + ex);
                    }
                });
            }, _cancellationTokenSource.Token, 10);

            if (Instance == null)
            {
                Instance = this;
            }
            else
            {
                throw new InvalidOperationException();
            }
        }