Ejemplo n.º 1
0
        /// <summary>
        /// Call with a received message. If this message is not the current state's
        /// ValidReceives list, the connection will be disconnected.
        /// </summary>
        /// <param name="message">A received message</param>
        public void Received(IMessage message)
        {
            if (!_state.ValidReceives.Contains(message.TypeId))
            {
                _disconnecter.Disconnect();
                return;
            }

            _state.Received(this, message);
        }
Ejemplo n.º 2
0
        public void Sent(NetworkStateContext context, IMessage message)
        {
            // The only valid send is FoundGame
            context.SetState(NetworkStateId.FoundGame);

            // Get the opponents connection.
            if (!_userRepo.TryGetSender(_state.Match.Opponent.Username, out var opponent))
            {
                // Somehow the opponent is not logged in.
                _disconnecter.Disconnect();
                return;
            }

            _state.SetMatchTimeoutCallback((s, e) =>
            {
                // If the opponent has responded already, send a RejectGame to them.
                if (_state.Match.Opponent.AcceptedGame != MatchResponse.None)
                {
                    opponent.Send(new BasicMessage(MessageTypeId.RejectGame));
                }

                _sender.Send(new BasicMessage(MessageTypeId.GameExpired));
            });

            _state.StartMatchTimer();
        }
Ejemplo n.º 3
0
        public void Received(NetworkStateContext context, IMessage message)
        {
            // Only valid receive is MyGuess
            context.SetState(NetworkStateId.Waiting);

            var guess       = ((MyGuessMessage)message).Position;
            var guessResult = _state.Match.Opponent.Board.Guess(guess);

            var id = guessResult switch
            {
                GuessResult.Miss => MessageTypeId.Miss,
                GuessResult.Hit => MessageTypeId.Hit,
                GuessResult.Sunk => MessageTypeId.Sunk,
                GuessResult.Win => MessageTypeId.YouWin,
                _ => throw new ArgumentOutOfRangeException()
            };

            _sender.Send(new BasicMessage(id));

            // Get the opponents connection.
            if (!_userRepo.TryGetSender(_state.Match.Opponent.Username, out var opponent))
            {
                // Somehow the opponent is not logged in.
                _disconnecter.Disconnect();
                return;
            }

            if (id == MessageTypeId.YouWin)
            {
                opponent.Send(new YouLoseMessage(guess));
                return;
            }

            opponent.Send(new TheirGuessMessage(guess));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Asynchronously receive and parse data terminating if anything unexpected
        /// is received.
        /// </summary>
        public async Task StartReceivingAsync()
        {
            var reader = PipeReader.Create(_stream);

            _logger.LogInfo("Connected to " + _socket.RemoteEndPoint);

            while (true)
            {
                // Suspend this method until reader returns data.
                var result = await reader.ReadAsync();

                // Parse contents until we run out of valid & complete messages.
                var position = _parser.Parse(result.Buffer);

                // Disconnect if we receive any invalid data.
                if (position == null)
                {
                    break;
                }

                // Tell the reader how much data we evaluated so it does not return
                // data we have already seen.
                reader.AdvanceTo(position.Value, result.Buffer.End);
            }

            await reader.CompleteAsync();

            _disconnecter.Disconnect();
        }
Ejemplo n.º 5
0
        public void Received(NetworkStateContext context, IMessage message)
        {
            // Get the opponents connection.
            if (!_userRepo.TryGetSender(_state.Match.Opponent.Username, out var opponent))
            {
                // Somehow the opponent is not logged in.
                _disconnecter.Disconnect();
                return;
            }

            _state.CancelMatchTimer();

            // The player is rejecting the game.
            if (message.TypeId == MessageTypeId.RejectGame)
            {
                // Mark the player as accepting the game.
                _state.Match.Player.AcceptedGame = MatchResponse.Reject;

                // Update our state.
                context.SetState(NetworkStateId.WaitingForBoard);

                // Let the opponent know that the player has rejected the game.
                opponent.Send(new BasicMessage(MessageTypeId.RejectGame));
                return;
            }

            // The only remaining valid message is AcceptGame. So mark the player as accept.
            _state.Match.Player.AcceptedGame = MatchResponse.Accept;

            // If the opponent has also sent AcceptGame, we let both know to start the game.
            if (_state.Match.Opponent.AcceptedGame == MatchResponse.Accept)
            {
                // Let both know that the game has been accepted.
                _sender.Send(new BasicMessage(MessageTypeId.AcceptGame));
                opponent.Send(new BasicMessage(MessageTypeId.AcceptGame));

                // Notify who goes first
                if (_state.Match.PlayerGoesFirst)
                {
                    _sender.Send(new BasicMessage(MessageTypeId.AssignRed));
                    opponent.Send(new BasicMessage(MessageTypeId.AssignBlue));
                }
                else
                {
                    _sender.Send(new BasicMessage(MessageTypeId.AssignBlue));
                    opponent.Send(new BasicMessage(MessageTypeId.AssignRed));
                }
            }
        }