public void CancelGamePreparation(AsyncUserToken userToken)
        {
            ServerSideTokenIdentity identity = (ServerSideTokenIdentity)userToken.info;

            lock (identity.MatchmakingLock)
            {
                if (identity.MatchmakingStatus != UserMatchmakingStatus.PREPARING_GAME)
                {
                    return;
                }

                GameWrapper gameWrapper = identity.GameWrapper;

                var game = gameWrapper.Game;

                lock (gameWrapper.@lock)
                {
                    GameCanceledNotification gameCanceledNotification = new GameCanceledNotification();

                    foreach (var token in gameWrapper.Tokens)
                    {
                        if (token != userToken)
                        {
                            Config.GameServer.Send(token, gameCanceledNotification);
                        }
                    }

                    TerminateGame(gameWrapper);
                }
            }
        }
 private void FinalizeGamePreparation(GameWrapper gameWrapper)
 {
     lock (gameWrapper.@lock)
     {
         gameWrapper.IsReady = true;
         var game = gameWrapper.Game;
         for (int i = 0; i < gameWrapper.Tokens.Length; i++)
         {
             executionEngine.DrawStartingHand(gameWrapper.Game, i, GameConfig.INITIAL_HAND_SIZE);
             var token         = gameWrapper.Tokens[i];
             var tokenIdentity = (ServerSideTokenIdentity)token.info;
             lock (tokenIdentity.MatchmakingLock)
             {
                 tokenIdentity.MatchmakingStatus = UserMatchmakingStatus.GAME;
                 if (!game.Players[i].Cards.TryGetValue(PossibleCardPlace.HAND, out LinkedList <CardInGame> startingHand))
                 {
                     Console.WriteLine("No hand in player cards dictionary");
                     startingHand = new LinkedList <CardInGame>();
                 }
                 Config.GameServer.Send(token, new StartingUserGameState
                 {
                     PlayerIndex  = i,
                     StartingDeck = startingHand
                 });
             }
         }
         NextTurn(gameWrapper, true);
     }
 }
        public void SuddenlyEndGameOnPlayerDisconnect(AsyncUserToken userToken)
        {
            ServerSideTokenIdentity identity = (ServerSideTokenIdentity)userToken.info;

            lock (identity.MatchmakingLock)
            {
                if (identity.MatchmakingStatus != UserMatchmakingStatus.GAME)
                {
                    return;
                }

                GameWrapper gameWrapper = identity.GameWrapper;

                var game = gameWrapper.Game;

                if (game.Players.Length != 2)
                {
                    // Only for 2 player games
                    return;
                }

                lock (gameWrapper.@lock)
                {
                    GameFinishedNotification gameFinishedNotification = new GameFinishedNotification();


                    for (int i = 0; i < gameWrapper.Tokens.Length; i++)
                    {
                        var token = gameWrapper.Tokens[i];
                        if (token == userToken)
                        {
                            gameFinishedNotification.WinnerPlayerId = 1 - i;
                            break;
                        }
                    }

                    foreach (var token in gameWrapper.Tokens)
                    {
                        if (token != userToken)
                        {
                            Config.GameServer.Send(token, gameFinishedNotification);
                        }
                    }

                    TerminateGame(gameWrapper);
                }
            }
        }
        private void TerminateGame(GameWrapper gameWrapper)
        {
            if (gameWrapper == null)
            {
                throw new ArgumentNullException(nameof(gameWrapper));
            }

            lock (gameWrapper.@lock)
            {
                foreach (var token in gameWrapper.Tokens)
                {
                    var identity = (ServerSideTokenIdentity)token.info;
                    lock (identity.MatchmakingLock)
                    {
                        identity.MatchmakingStatus = UserMatchmakingStatus.LOBBY;
                        identity.GameWrapper       = null;
                    }
                }
                m_gameWrapperObjectPool.ReleaseObject(gameWrapper);
            }
        }
        // This works only for 2 player game because only that is implemented in first iteration
        // 2 players can't loose health as cause of single action in current state of the game
        private void CheckIfPlayerDied(GameWrapper gameWrapper)
        {
            if (gameWrapper == null)
            {
                throw new ArgumentNullException(nameof(gameWrapper));
            }

            lock (gameWrapper.@lock)
            {
                var game = gameWrapper.Game;
                if (game.Players.Length != 2)
                {
                    throw new ArgumentException("Meyhod works only for 2 player games");
                }

                int?winner = null;
                for (int i = 0; i < game.Players.Length && winner == null; i++)
                {
                    if (game.Players[i].Health <= 0)
                    {
                        winner = 1 - i;
                    }
                }

                if (winner != null)
                {
                    GameFinishedNotification gameFinishedNotification = new GameFinishedNotification {
                        WinnerPlayerId = (int)winner
                    };

                    foreach (var token in gameWrapper.Tokens)
                    {
                        Config.GameServer.Send(token, gameFinishedNotification);
                    }

                    TerminateGame(gameWrapper);
                }
            }
        }
 private void NextTurn(GameWrapper gameWrapper, bool isFirstTurn = false)
 {
     lock (gameWrapper.@lock)
     {
         CardDrawingOutcome drawingOutcome =
             executionEngine.NewTurn(gameWrapper.Game, out int playerIndex, out CardInGame card, out int mana, out int fatiqueDamage, isFirstTurn);
         for (int i = 0; i < gameWrapper.Tokens.Length; i++)
         {
             var token = gameWrapper.Tokens[i];
             Config.GameServer.Send(token, new NewTurnNotification
             {
                 PlayerIndex           = playerIndex,
                 DrawnCard             = (i == playerIndex) ? card : null,
                 DrawingOutcome        = drawingOutcome,
                 Mana                  = mana,
                 FatiqueDamage         = fatiqueDamage,
                 RemainingHealth       = gameWrapper.Game.Players[playerIndex].Health,
                 AccumulativeTurnCount = gameWrapper.Game.AccumulativeTurn
             });
         }
     }
 }