private async Task DoLocalUpdate()
        {
            try
            {
                foreach (var registration in this._serverRegistrations)
                {
                    ServerStatusUpdate statusUpdate = new ServerStatusUpdate();
                    try
                    {
                        Logger.Debug("Start: {0}", registration.LocalEndpoint);
                        statusUpdate = await GenerateServerStatusUpdateAsync(registration);

                        PostServerStatusUpdate(registration, registration.UpdateCallback, statusUpdate);
                    }
                    catch (Exception ex)
                    {
                        // We don't want to stop other registration queries or break the ActionBlock
                        Logger.Debug("Exception in local update: {0} \n {1}", ex.Message, ex.StackTrace);
                        Debugger.Break();
                    }
                    finally
                    {
                        Logger.Debug("End: {0}: {1}", registration.LocalEndpoint, statusUpdate.Status);
                    }
                }
            }
            finally
            {
                Task.Delay(LOCAL_STATUS_QUERY_DELAY).ContinueWith(_ => _eventQueue.Post(DoLocalUpdate)).DoNotWait();
            }
        }
        private async Task <ServerStatusUpdate> GenerateServerStatusUpdateAsync(ServerStatusUpdateRegistration registration)
        {
            var registrationKey = registration.SteamEndpoint.ToString();

            //
            // First check the process status
            //
            Process process;
            var     processStatus = GetServerProcessStatus(registration, out process);

            switch (processStatus)
            {
            case ServerProcessStatus.NotInstalled:
                return(new ServerStatusUpdate {
                    Status = ServerStatus.NotInstalled
                });

            case ServerProcessStatus.Stopped:
                return(new ServerStatusUpdate {
                    Status = ServerStatus.Stopped
                });

            case ServerProcessStatus.Unknown:
                return(new ServerStatusUpdate {
                    Status = ServerStatus.Unknown
                });

            case ServerProcessStatus.Running:
                break;

            default:
                Debugger.Break();
                break;
            }

            var currentStatus = ServerStatus.Initializing;

            //
            // If the process was running do we then perform network checks.
            //
            Logger.Debug("Checking server local status at {0}", registration.LocalEndpoint);

            // get the server information direct from the server using local connection.
            ReadOnlyCollection <Player> players;
            var localInfo = GetLocalNetworkStatus(registration.LocalEndpoint, out players);

            if (localInfo != null)
            {
                currentStatus = ServerStatus.RunningLocalCheck;

                //
                // Now that it's running, we can check the publication status.
                //
                Logger.Debug("Checking server public status at {0}", registration.SteamEndpoint);

                // get the server information direct from the server using public connection.
                var serverStatus = NetworkUtils.CheckServerStatusDirect(registration.SteamEndpoint);
                // check if the server returned the information.
                if (!serverStatus)
                {
                    // server did not return any information
                    var lastExternalStatusQuery = _lastExternalStatusQuery.ContainsKey(registrationKey) ? _lastExternalStatusQuery[registrationKey] : DateTime.MinValue;
                    if (DateTime.Now >= lastExternalStatusQuery.AddMilliseconds(REMOTE_STATUS_QUERY_DELAY))
                    {
                        currentStatus = ServerStatus.RunningExternalCheck;

                        // get the server information direct from the server using external connection.
                        var uri = new Uri(string.Format(Config.Default.ServerStatusUrlFormat, Config.Default.ServerManagerCode, registration.SteamEndpoint.Address, registration.SteamEndpoint.Port));
                        serverStatus = await NetworkUtils.CheckServerStatusViaAPI(uri, registration.SteamEndpoint);

                        _lastExternalStatusQuery[registrationKey] = DateTime.Now;
                    }
                }

                //var lastExternalCallQuery = _lastExternalCallQuery.ContainsKey(registrationKey) ? _lastExternalCallQuery[registrationKey] : DateTime.MinValue;
                //if (lastExternalCallQuery == DateTime.MinValue)
                //{
                //    // perform a server call to the web api.
                //    var uri = new Uri(string.Format(Config.Default.ServerCallUrlFormat, Config.Default.ServerManagerCode, registration.SteamEndpoint.Address, registration.SteamEndpoint.Port, Config.Default.ServerManagerUniqueKey, registration.ProfileId));
                //    await NetworkUtils.PerformServerCallToAPI(uri, registration.SteamEndpoint);

                //    _lastExternalCallQuery[registrationKey] = DateTime.Now;
                //}

                // check if the server returned the information.
                if (serverStatus)
                {
                    currentStatus = ServerStatus.Published;
                }
                else
                {
                    Logger.Debug("No public status returned for {0}", registration.SteamEndpoint);
                }
            }

            var statusUpdate = new ServerStatusUpdate
            {
                Process    = process,
                Status     = currentStatus,
                ServerInfo = localInfo,
                Players    = players
            };

            return(await Task.FromResult(statusUpdate));
        }
 private void PostServerStatusUpdate(ServerStatusUpdateRegistration registration, StatusCallback callback, ServerStatusUpdate statusUpdate)
 {
     _eventQueue.Post(() =>
     {
         if (this._serverRegistrations.Contains(registration))
         {
             try
             {
                 callback(registration, statusUpdate);
             }
             catch (Exception ex)
             {
                 DebugUtils.WriteFormatThreadSafeAsync("Exception during local status update callback: {0}\n{1}", ex.Message, ex.StackTrace).DoNotWait();
             }
         }
         return(TaskUtils.FinishedTask);
     });
 }
Exemplo n.º 4
0
        private void MessageReceived()
        {
            lock (_receivedData)
            {
                _receivedData.Seek(0, SeekOrigin.Begin);

                int messageType        = _receivedData.ReadByte();
                ServerMessageType type = (ServerMessageType)messageType;

                switch (type)
                {
                case ServerMessageType.Map:
                    Map map = Serializer.DeserializeWithLengthPrefix <Map>(_receivedData, PrefixStyle.Base128);
                    Debug.WriteLine("Map received.");

                    // Map successfully received, change game state to wait for start
                    _gameInfo.Level = map;
                    _gameInfo.State = RunStates.WaitingForGameStart;

                    // Update status display
                    Deployment.Current.Dispatcher.BeginInvoke(() => _mainState.DisplayStatusMessage("Waiting for players to be ready...\nYou are NOT ready."));

                    SendResponse(new ClientStatusUpdate(ClientUpdate.MapOk));
                    break;

                case ServerMessageType.Player:
                    PlayerInfo playerInfo = Serializer.DeserializeWithLengthPrefix <PlayerInfo>(_receivedData, PrefixStyle.Base128);

                    _gameInfo.AddPlayer(playerInfo.Color, playerInfo.X, playerInfo.Y);
                    SendResponse(new ClientStatusUpdate(ClientUpdate.PlayerInfoOk));

                    Debug.WriteLine("Player info received...");
                    break;

                case ServerMessageType.StatusUpdate:
                    ServerStatusUpdate update = Serializer.DeserializeWithLengthPrefix <ServerStatusUpdate>(_receivedData, PrefixStyle.Base128);
                    _gameInfo.UpdateStatus(update);
                    break;

                case ServerMessageType.BombExplosion:
                    BombExplode explosion = Serializer.DeserializeWithLengthPrefix <BombExplode>(_receivedData, PrefixStyle.Base128);
                    _gameInfo.ExplodeBomb(explosion);
                    break;

                case ServerMessageType.PlayerDeath:
                    PlayerDeath playerDeath = Serializer.DeserializeWithLengthPrefix <PlayerDeath>(_receivedData, PrefixStyle.Base128);
                    _gameInfo.KillPlayer(playerDeath);
                    break;

                case ServerMessageType.GameOver:
                    GameOverUpdate gameOverUpdate = Serializer.DeserializeWithLengthPrefix <GameOverUpdate>(_receivedData, PrefixStyle.Base128);
                    _gameInfo.EndGame(gameOverUpdate);
                    SendResponseSync("GO OK");
                    break;

                default:
                    Debug.WriteLine("Unrecognised package received!");
                    break;
                }

                _receivedData = new MemoryStream();
            }
        }
        private static async Task <ServerStatusUpdate> GenerateServerStatusUpdateAsync(ServerStatusUpdateRegistration registration)
        {
            //
            // First check the process status
            //
            Process process;
            var     processStatus = GetServerProcessStatus(registration, out process);

            switch (processStatus)
            {
            case ServerProcessStatus.NotInstalled:
                return(new ServerStatusUpdate {
                    Status = ServerStatus.NotInstalled
                });

            case ServerProcessStatus.Stopped:
                return(new ServerStatusUpdate {
                    Status = ServerStatus.Stopped
                });

            case ServerProcessStatus.Running:
                break;

            default:
                Debugger.Break();
                break;
            }

            ServerStatus currentStatus = ServerStatus.Initializing;
            //
            // If the process was running do we then perform network checks.
            //
            ServerInfo localInfo;
            ReadOnlyCollection <Player> players;

            localInfo = GetLocalNetworkStatus(registration.LocalEndpoint, out players);

            if (localInfo != null)
            {
                currentStatus = ServerStatus.Running;

                //
                // Now that it's running, we can check the publication status.
                //
                logger.Debug("Checking server public status at {0}", registration.SteamEndpoint);
                var serverInfo = await NetworkUtils.GetServerNetworkInfo(registration.SteamEndpoint);

                if (serverInfo != null)
                {
                    currentStatus = ServerStatus.Published;
                }
                else
                {
                    logger.Debug("No public status returned for {0}", registration.SteamEndpoint);
                }
            }

            var statusUpdate = new ServerStatusUpdate
            {
                Process    = process,
                Status     = currentStatus,
                ServerInfo = localInfo,
                Players    = players
            };

            return(await Task.FromResult(statusUpdate));
        }
Exemplo n.º 6
0
        public void UpdateStatus(ServerStatusUpdate update)
        {
            // Update players first
            foreach (PlayerInfo player in update.Players)
            {
                // Don't change coordinates of the local player
                if (player.Color == _mainState.LocalPlayer.Color)
                {
                    continue;
                }

                var ply = GetPlayer(player.Color);

                if (ply == null)
                {
                    AddPlayer(player.Color, player.X, player.Y);
                }
                else
                {
                    // Dispatch position change to the UI thread
                    PlayerInfo info = player;

                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        ply.X         = info.X;
                        ply.Y         = info.Y;
                        ply.Direction = info.Direction;
                        ply.Moving    = info.Moving;
                    });
                }
            }

            // Check for command
            switch (update.Update)
            {
            case ServerCommand.StartGame:
                GameStart();
                break;

            case ServerCommand.PlayerUpdate:
                // Do nothing, players were already updated
                break;

            // A new bomb was set, display it
            case ServerCommand.BombSet:

                AutoResetEvent rst  = new AutoResetEvent(false);
                Bomb           bomb = null;

                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    bomb = new Bomb(_mainState.GameCanvas, update.X, update.Y);
                    rst.Set();
                });

                rst.WaitOne();

                lock (_bombs)
                {
                    _bombs.Add(bomb);
                }

                Debug.WriteLine("Bomb set on " + bomb.Position);

                break;

            case ServerCommand.ScrambleControls:
                _mainState.LocalPlayer.ScrambleControls();
                RemovePowerup(update.X, update.Y);
                break;

            case ServerCommand.ClearPowerup:
                RemovePowerup(update.X, update.Y);
                break;

            default:
                throw new NotImplementedException();
            }
        }