public Task <IPlayerGrain> NewPlayer(IAccountGrain account, string name) { if (_state == GameState.Unstarted) { var accountKey = account.GetPrimaryKey(); IPlayerGrain playerGrain; if (_players.TryGetValue(accountKey, out playerGrain)) { return(Task.FromResult(playerGrain)); } var playerGuid = Guid.NewGuid(); playerGrain = PlayerGrainFactory.GetGrain(playerGuid); playerGrain.Create(this, account, name); _players.Add(accountKey, playerGrain); account.JoinGame(this, playerGrain); Console.WriteLine(" -- {0,-10} -- New player joined {1}.", "Game", _name); return(Task.FromResult(playerGrain)); } else { Console.WriteLine(" -- {0,-10} -- Cannot join a started game.", "Game"); return(Task.FromResult <IPlayerGrain>(null)); } }
public async Task <ActionResult> Join(Guid id) { var guid = GetGuid(); var player = PlayerGrainFactory.GetGrain(guid); var state = await player.JoinGame(id); return(RedirectToAction("Index", id)); }
public async Task <ActionResult> Join(Guid id) { var guid = GetGuid(); var player = PlayerGrainFactory.GetGrain(guid); var state = await player.JoinGame(id); return(Json(new { GameState = state }, JsonRequestBehavior.AllowGet)); }
public async Task <ActionResult> CreateGame() { var guid = GetGuid(); var player = PlayerGrainFactory.GetGrain(guid); var gameIdTask = await player.CreateGame(); return(Json(new { GameId = gameIdTask }, JsonRequestBehavior.AllowGet)); }
public async Task <ActionResult> SetUser(string id) { var guid = GetGuid(); var player = PlayerGrainFactory.GetGrain(guid); await player.SetUsername(id); return(Json(new { })); }
public async Task <ActionResult> Index() { var guid = GetGuid(); var player = PlayerGrainFactory.GetGrain(guid); var gamesTask = player.GetGameSummaries(); var availableTask = player.GetAvailableGames(); await Task.WhenAll(gamesTask, availableTask); return(Json(new object[] { gamesTask.Result, availableTask.Result }, JsonRequestBehavior.AllowGet)); }
/// <summary> /// Presense grain calls this method to update the game with its latest status /// </summary> public async Task UpdateGameStatus(GameStatus status) { this.status = status; // Check for new players that joined since last update foreach (Guid player in status.Players) { if (!players.Contains(player)) { try { // Here we call player grains serially, which is less efficient than a fan-out but simpler to express. await PlayerGrainFactory.GetGrain(player).JoinGame(this); players.Add(player); } catch (Exception) { // Ignore exceptions while telling player grains to join the game. // Since we didn't add the player to the list, this will be tried again with next update. } } } // Check for players that left the game since last update List <Task> promises = new List <Task>(); foreach (Guid player in players) { if (!status.Players.Contains(player)) { try { // Here we do a fan-out with multiple calls going out in parallel. We join the promisses later. // More code to write but we get lower latency when calling multiple player grains. promises.Add(PlayerGrainFactory.GetGrain(player).LeaveGame(this)); players.Remove(player); } catch (Exception) { // Ignore exceptions while telling player grains to leave the game. // Since we didn't remove the player from the list, this will be tried again with next update. } } } // Joining promises await Task.WhenAll(promises); // Notify subsribers about the latest game score subscribers.Notify((s) => s.UpdateGameScore(status.Score)); return; }
async Task IPlayerRegistrationGrain.Register(IPlayerObserver playerObserver) { var playerId = this.GetPrimaryKey(); // first have someone else to wait for future notifications from the GameServerGrain IPlayerGrain playerInGame = PlayerGrainFactory.GetGrain(playerId); // Forward subscription to the corresponding PlayerInGameGrain and trigger lobby service. var playerInfo = await playerInGame.Subscribe(playerObserver); // *then* ask to start a GameServerGrain via lobby await _lobby.RegisterPlayer(playerInGame, playerInfo); }
/// <summary> /// Simulates a companion application that connects to the game that a particular player is currently part of /// and subscribes to receive live notifications about its progress. /// </summary> static void Main(string[] args) { try { GrainClient.Initialize(); // Hardcoded player ID Guid playerId = new Guid("{2349992C-860A-4EDA-9590-000000000006}"); IPlayerGrain player = PlayerGrainFactory.GetGrain(playerId); IGameGrain game = null; while (game == null) { Console.WriteLine("Getting current game for player {0}...", playerId); try { game = player.GetCurrentGame().Result; if (game == null) // Wait until the player joins a game { game = null; Thread.Sleep(5000); } } catch (Exception exc) { Console.WriteLine("Exception: ", exc.GetBaseException()); } } Console.WriteLine("Subscribing to updates for game {0}...", game.GetPrimaryKey()); // Subscribe for updates var watcher = new GameObserver(); game.SubscribeForGameUpdates(GameObserverFactory.CreateObjectReference(watcher).Result).Wait(); // Block main thread so that the process doesn't exit. Updates arrive on thread pool threads. Console.WriteLine("Subscribed successfully. Press <Enter> to stop."); Console.ReadLine(); } catch (Exception exc) { Console.WriteLine("Unexpected Error: {0}", exc.GetBaseException()); } }
public async Task <GameSummary> GetSummary(Guid player) { var promises = new List <Task <string> >(); foreach (var p in this.ListOfPlayers.Where(p => p != player)) { promises.Add(PlayerGrainFactory.GetGrain(p).GetUsername()); } await Task.WhenAll(promises); return(new GameSummary { NumMoves = this.ListOfMoves.Count, State = this.GameState, YourMove = this.GameState == GameState.InPlay && player == this.ListOfPlayers[this.indexNextPlayerToMove], NumPlayers = this.ListOfPlayers.Count, GameId = this.GetPrimaryKey(), Usernames = promises.Select(x => x.Result).ToArray(), Name = this.name, GameStarter = this.ListOfPlayers.FirstOrDefault() == player }); }
// make a move during the game public async Task <GameState> MakeMove(GameMove move) { // check if its a legal move to make if (this.GameState != GameState.InPlay) { throw new ApplicationException("This game is not in play"); } if (ListOfPlayers.IndexOf(move.PlayerId) < 0) { throw new ArgumentException("No such playerid for this game", "move"); } if (move.PlayerId != ListOfPlayers[indexNextPlayerToMove]) { throw new ArgumentException("The wrong player tried to make a move", "move"); } if (move.X < 0 || move.X > 2 || move.Y < 0 || move.Y > 2) { throw new ArgumentException("Bad co-ordinates for a move", "move"); } if (theBoard[move.X, move.Y] != -1) { throw new ArgumentException("That square is not empty", "move"); } // record move this.ListOfMoves.Add(move); this.theBoard[move.X, move.Y] = indexNextPlayerToMove; // check for a winning move var win = false; if (!win) { for (int i = 0; i < 3 && !win; i++) { win = isWinningLine(theBoard[i, 0], theBoard[i, 1], theBoard[i, 2]); } } if (!win) { for (int i = 0; i < 3 && !win; i++) { win = isWinningLine(theBoard[0, i], theBoard[1, i], theBoard[2, i]); } } if (!win) { win = isWinningLine(theBoard[0, 0], theBoard[1, 1], theBoard[2, 2]); } if (!win) { win = isWinningLine(theBoard[0, 2], theBoard[1, 1], theBoard[2, 0]); } // check for draw var draw = false; if (this.ListOfMoves.Count() == 9) { draw = true; // we could try to look for stalemate earlier, if we wanted } // handle end of game if (win || draw) { // game over this.GameState = GameState.Finished; if (win) { WinnerId = ListOfPlayers[indexNextPlayerToMove]; LoserId = ListOfPlayers[(indexNextPlayerToMove + 1) % 2]; } // collect tasks up, so we await both notifications at the same time var promises = new List <Task>(); // inform this player of outcome var playerGrain = PlayerGrainFactory.GetGrain(ListOfPlayers[indexNextPlayerToMove]); promises.Add(playerGrain.LeaveGame(this.GetPrimaryKey(), win ? GameOutcome.Win : GameOutcome.Draw)); // inform other player of outcome playerGrain = PlayerGrainFactory.GetGrain(ListOfPlayers[(indexNextPlayerToMove + 1) % 2]); promises.Add(playerGrain.LeaveGame(this.GetPrimaryKey(), win ? GameOutcome.Lose : GameOutcome.Draw)); await Task.WhenAll(promises); return(this.GameState); } // if game hasnt ended, prepare for next players move indexNextPlayerToMove = (indexNextPlayerToMove + 1) % 2; return(this.GameState); }