public void Received(NetworkStateContext context, IMessage message) { // Change state to PendingLogOn so if the client sends any messages // in the meantime, that state will take over. context.SetState(NetworkStateId.PendingLogOn); var attempt = (LogOnMessage)message; if (attempt.Version != BspConstants.Version) { _sender.Send(new RejectLogOnMessage(BspConstants.Version)); return; } if (!_userRepo.TryLogIn(attempt.Username, attempt.Password, _sender)) { _sender.Send(new RejectLogOnMessage(BspConstants.Version)); return; } // Client has successfully logged in, so we update our record. _state.Username = attempt.Username; // Let the user know they were successful. _sender.Send(new BasicMessage(MessageTypeId.AcceptLogOn)); // Send them the game types. foreach (var gameType in _gameTypeRepo.GetAll()) { _sender.Send(new GameTypeMessage(gameType)); } }
public void PromptLogOn() { Write("Username: "******"Password: "); var password = Console.ReadLine(); _sender.Send(new LogOnMessage(BspConstants.Version, username, password)); }
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)); } } }
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(); }
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)); }
public void Received(NetworkStateContext context, IMessage message) { context.SetState(NetworkStateId.PendingBoard); var submission = (SubmitBoardMessage)message; var placements = submission.ShipPlacements; var isValidGameType = _gameTypeRepo.TryGet(submission.GameTypeId, out var gameType); if (!isValidGameType) { SendRejection(RejectBoardErrorId.UnsupportedGameType); return; } if (placements.Count != gameType.ShipLengths.Count) { SendRejection(RejectBoardErrorId.WrongShips); return; } var board = new Board(gameType); for (var i = 0; i < placements.Count; i++) { if (board.IsOutOfBounds(placements[i], i)) { SendRejection(RejectBoardErrorId.OutOfBounds); return; } if (board.IsOverlapping(placements[i], i)) { SendRejection(RejectBoardErrorId.ShipOverlap); return; } if (!board.TryPlace(placements[i], i)) { // This shouldn't happen because we just checked the error // conditions. If this somehow happens, we want to crash the // server. throw new Exception(); } } _sender.Send(new BasicMessage(MessageTypeId.AcceptBoard)); var userBoard = new UserBoard(_state.Username, board); var match = _matchMaker.FindMatchAsync(userBoard).GetAwaiter().GetResult(); if (match == null) { // This could happen if the server somehow ends up in an // inconsistent state where it can't add the user to match making. throw new Exception(); } _state.Match = match; _sender.Send(new BasicMessage(MessageTypeId.FoundGame)); }