/// <summary> /// Proxy function that processes the selected color and sends it to the Game host /// </summary> /// <param name="color"></param> /// <param name="effects"></param> public async Task SendColorToHost(string color, SpecialCardActions effects) { ServerGameSession session = MvcApplication.Manager.FindSessionByClientConnectionId(Context.ConnectionId); if (session != null) { PlayerObject player = session.game.Players.FirstOrDefault(n => n.connid == Context.ConnectionId); if (player != null) { switch (color) { case "green": case "yellow": case "red": case "blue": await session.UpdateColorInHost(player, color, effects); break; case "error": default: await session.UpdateColorInHost(player, null, null); break; } } } }
/// <summary> /// Proxy function that sends the pressed card to the Game host /// </summary> /// <param name="cardName"></param> public async Task PostCard(string cardName) { ServerGameSession sGame = MvcApplication.Manager.FindSessionByClientConnectionId(Context.ConnectionId); if (sGame != null) { UnoGame game = sGame.game; //get the player object PlayerObject player = game.Players.FirstOrDefault(n => n.connid == Context.ConnectionId); if (player != null) { //get the card object CardObject card = player.cards.FirstOrDefault(n => n.name == cardName); if (card != null) { //send the game to the host, and let the host process it await sGame.PlayCard(player.id, card); } else { //todo: maybe not end the session, but there is some cheating going on await Clients.Caller.endSession("The card you played was not in your posession."); } } else { await Clients.Caller.endSession("You are not a member of this game"); } } else { await Clients.Caller.endSession("You are not a member of a game"); } }
/// <summary> /// Proxy function that is called after a user picks a color, the function checks if it needs to send cards from the draw four card. /// </summary> /// <param name="game">game object</param> /// <param name="effects">the effects object</param> /// <returns></returns> public async Task HandleSpecialAfterColorPick(UnoGame game, SpecialCardActions effects) { ServerGameSession sGame = MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId); if (effects.sendColorWheel) { if (effects.cardDrawAmount != 0) { //send the NEXT client the amount of cards. game.CurrentPlayer = GetNextPlayerId(game, null); string targetPlayer = new string(game.CurrentPlayer.ToCharArray()); game.CurrentPlayer = GetNextPlayerId(game, null); await PushGame(game); Clients.Caller.drawCardFromSpecial(targetPlayer, effects.cardDrawAmount); } else { game.CurrentPlayer = GetNextPlayerId(game, null); } await PushGame(game); //set the current playing name: await MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId).UpdateCurrentPlayingName(game.Players.FirstOrDefault(n => n.id == game.CurrentPlayer)); } }
/// <summary> /// Checks if the password belongs to a game and if the game is still available /// </summary> /// <param name="password"></param> /// <returns>Returns the status message, if the game exists, a redirect will happen through a seperate client call.</returns> public string CreateClientSessionFromPassword(string password) { ServerGameSession session = MvcApplication.Manager.FindSessionByPassword(password); if (session == null) { return("Game does not exists, try again please."); } if (!session.game.HasAvailablePlayerSpots()) { return("This game is full, you can create a new one or check if you have the correct code."); } if (session.GameStarted) { return("Game has already started, ask the game owner to wait longer next time."); } lock (PlayerSelectionLock) //this is going to cause issues with more active games, players will have to wait a bit longer before they get a selectable game assigned { PlayerObject p = session.game.Players.FirstOrDefault(n => n.connid == "" && !n.UserPicked); p.UserPicked = true; string clientId = p.id; //todo prevent racecondition / deadlock if 2 players join at the same time by using a request queue of some sort. Clients.Caller.redirectToClientGame(clientId); } return("Game has been found, you will be redirected shortly..."); }
/// <summary> /// Proxy function that stops the game and sends the clients back to the lobby /// </summary> /// <returns></returns> public async Task EndGame() { ServerGameSession sGame = MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId); await sGame?.EndGameForClients(); MvcApplication.Manager.EndGame(sGame); await GlobalHost.ConnectionManager.GetHubContext <SessionHub>().Clients.All.setSessions(MvcApplication.Manager.GetGameSessions()); }
/// <summary> /// Proxy function that reports uno to the Game host /// </summary> /// <returns></returns> public async Task ReportUno() { ServerGameSession game = MvcApplication.Manager.FindSessionByClientConnectionId(Context.ConnectionId); if (game != null) { PlayerObject player = game.game.Players.FirstOrDefault(n => n.connid == Context.ConnectionId); player.reportedUno = true; await game.UpdateHost(); } }
/// <summary> /// Proxy function that requests a card from the Draw Pile at the Game host /// </summary> public async Task DrawCardFromDeck() { string connId = Context.ConnectionId; ServerGameSession session = MvcApplication.Manager.FindSessionByClientConnectionId(Context.ConnectionId); if (session != null) { UnoGame game = session.game; PlayerObject player = game.Players.FirstOrDefault(n => n.connid == connId); await session.DrawCard(player.id); } }
/// <summary> /// Proxy function that causes a game update on every connected screen /// </summary> /// <returns></returns> public async Task Update() { ServerGameSession game = MvcApplication.Manager.FindSessionByClientConnectionId(Context.ConnectionId); if (game != null) { await game.UpdateAll(); } else { await Clients.Caller.endSession("unkown game id was passed to the server."); } }
// GET: Host public ActionResult Index(string id) { ServerGameSession game = MvcApplication.Manager.FindSession(id); if (game != null) { return(View(game)); } else { return(View("Error")); } }
/// <summary> /// Proxy function that allows the host to send a message to all connected clients (this is only implemented in the console atm) /// </summary> /// <param name="message">the message to relay</param> public async Task RelayMessage(string message) { ServerGameSession sGame = MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId); if (sGame != null) { await sGame.MessageClients(message); } else { Clients.Caller.endSession("unkown game id was passed to the server."); } }
/// <summary> /// Proxy function that processes the game after someone won. /// </summary> /// <param name="PlayerId">id of the player that won</param> /// <returns></returns> public async Task ProcessGameWon(string PlayerId) { ServerGameSession game = MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId); if (game != null) { await game.GameWon(PlayerId); } else { Clients.Caller.endSession("unkown game id was passed to the server."); } }
/// <summary> /// Proxy function that is called when an Action card is used in the game, the function decides what the game should do. /// </summary> /// <param name="game">current game object</param> /// <param name="effects">effects object</param> /// <returns></returns> public async Task HandleSpecialCard(UnoGame game, SpecialCardActions effects) { ServerGameSession sGame = MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId); string currentPlayer = game.CurrentPlayer; if (effects.sendColorWheel) { //send the colorwheel update to the current client. //after receiving the color wheel update advance the turn await sGame.ShowColorWheelInClient(effects); } else if (effects.cardDrawAmount != 0) { //send the NEXT client the amount of cards. game.CurrentPlayer = GetNextPlayerId(game, null); string targetPlayer = new string(game.CurrentPlayer.ToCharArray()); game.CurrentPlayer = GetNextPlayerId(game, null); await PushGame(game); await Clients.Caller.drawCardFromSpecial(targetPlayer, effects.cardDrawAmount); } else if (effects.skipNextPerson) { //the skip is handled in code game.CurrentPlayer = GetNextPlayerId(game, effects); } else if (effects.reverseOrder) { game.DirectionClockwise = !game.DirectionClockwise; if (game.Players.Count > 2) { game.CurrentPlayer = GetNextPlayerId(game, null); } } int drawCards = CheckUno(game, currentPlayer); await PushGame(game); //set the current playing name: PlayerObject pObject = game.Players.FirstOrDefault(n => n.id == game.CurrentPlayer); await MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId).UpdateCurrentPlayingName(pObject); if (drawCards > 0) { await Clients.Caller.drawCardFromSpecial(currentPlayer, drawCards); } else if (drawCards == -69) { await Clients.Caller.gameWon(currentPlayer); } }
/// <summary> /// Proxy function that creates the game object server side. /// </summary> /// <param name="gameId"></param> /// <returns>Return the games password to display to the viewers.</returns> public async Task <string> InitGame(string gameId) { ServerGameSession game = MvcApplication.Manager.FindSession(gameId); if (game != null) { if (string.IsNullOrEmpty(game.GameConnectionId) && !game.GameStarted) { game.GameConnectionId = Context.ConnectionId; await Clients.Caller.setGameMode("AWAITING_PLAYERS"); if (game.game.Players.Count == 0) { game.game.CreateNewPlayerObjects(); } else { if (game.game.HasConnectedPlayers()) { await Clients.Caller.setGameMode("AWAITING_PLAYERS_REFRESHED"); await game.UpdateHost(); } } } else if (string.IsNullOrEmpty(game.GameConnectionId) && game.GameStarted) { game.GameConnectionId = Context.ConnectionId; await Clients.Caller.setGameMode("RESUMING_GAME"); await game.UpdateHost(); PlayerObject pObject = game.game.Players.FirstOrDefault(n => n.id == game.game.CurrentPlayer); await game.UpdateCurrentPlayingName(pObject); await Clients.Caller.displayMessage($"Game is resuming"); } else { Clients.Caller.endSession("game is already being hosted somewhere else."); return(null); } return(game.GamePassword); } else { Clients.Caller.endSession("unkown game id was passed to the server."); } return(null); }
/// <summary> /// Proxy funtion that causes an update on all connected screens. /// </summary> /// <returns></returns> public async Task Update() { ServerGameSession game = MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId); if (game != null) { await game.UpdateAll(); PlayerObject pObject = game.game.Players.FirstOrDefault(n => n.id == game.game.CurrentPlayer); await game.UpdateCurrentPlayingName(pObject); } else { Clients.Caller.endSession("unkown game id was passed to the server."); } }
public override Task OnDisconnected(bool stopCalled) { //find game by connection id -> dbe1b95e-ea84-40f9-a570-455ca8edf6e2 ServerGameSession game = MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId); if (game != null) { game.GameConnectionId = null; if (game.HasGameEnded || !game.game.HasConnectedPlayers()) { MvcApplication.Manager.EndGame(game); } } return(base.OnDisconnected(stopCalled)); }
// GET: Client public ActionResult Index(string id) { ServerGameSession game = MvcApplication.Manager.FindSessionByClientId(id); if (game != null) { ClientGameSession session = new ClientGameSession(); session.ClientId = id; session.GameId = game.GameId; session.GameName = game.GameName; return(View(session)); } else { return(View("Error")); } }
public override Task OnDisconnected(bool stopCalled) { ServerGameSession game = MvcApplication.Manager.FindSessionByClientConnectionId(Context.ConnectionId); if (game != null) { lock (PlayerSelectionLock) { game.game.Players.First(n => n.connid == Context.ConnectionId).connid = ""; } //check if this is the last client disconnecting, and if there is no more host, remove the game if (game.game.Players.Where(n => n.connid != "").Count() == game.game.Players.Count && game.GameConnectionId == "") { MvcApplication.Manager.EndGame(game); } } return(base.OnDisconnected(stopCalled)); }
/// <summary> /// Proxy function that starts the game /// </summary> /// <returns></returns> public async Task StartGame() { ServerGameSession game = MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId); if (game != null) { game.GameStarted = true; //remove the empty player objects: no need for new players to connect after the game has started game.game.Players.RemoveAll(n => n.connid == ""); await Clients.Caller.startGame(game.game.Players); await Clients.Caller.displayMessage($"Game has started"); await game.UpdateCurrentPlayingName(game.game.Players[0]); } else { await Clients.Caller.endSession("unkown game id was passed to the server."); } }
/// <summary> /// Proxy function that connects this client with a Game host /// </summary> /// <param name="hostId">id of the host</param> /// <param name="clientId">id of the current client (not connection id)</param> /// <param name="playername">the name provided by the client.</param> /// <returns></returns> public async Task SubscribeToHost(string hostId, string clientId, string playername) { string connId = Context.ConnectionId; //find the session in memory ServerGameSession game = MvcApplication.Manager.FindSession(hostId); if (game != null) { //check if game is at max players if (game.game.Players.Where(n => n.connid != "").Count() < game.MaxClients) { if (game.game.Players.First(n => n.id == clientId).connid != "") { //game slot is in use await Clients.Caller.endSession("This place has already been taken by another player."); } else { lock (PlayerSelectionLock) { PlayerObject p = game.game.Players.First(n => n.id == clientId); p.connid = connId; p.name = playername; } await game.UpdateAll(); } } else { await Clients.Caller.endSession("This game is already at its max players."); } } else { await Clients.Caller.endSession("This game does not exist"); } }
/// <summary> /// Proxy and local function that syncs the JS and C# backend with eachother. /// </summary> /// <param name="game"></param> /// <returns></returns> public async Task PushGame(UnoGame game) { ServerGameSession sGame = MvcApplication.Manager.FindSessionByConnectionId(Context.ConnectionId); if (sGame != null) { if (sGame.game.FullDeck.Count == 0 || sGame.game.CurrentPlayer == null) { //new game, select first player from list. sGame.game = game; sGame.game.CurrentPlayer = sGame.game.Players[0].id; } else { sGame.game = game; } await sGame.UpdateAll(); } else { await Clients.Caller.endSession("unkown game id was passed to the server."); } }
public void EndGame(ServerGameSession session) { Sessions.Remove(session); }