Exemple #1
0
        private async Task <ContentResult> NewGameRequestHelper(string roomid, string playerid, string roomtype, Player player)
        {
            // Request a newgame in the room we want to join
            int    key = Partitioners.GetRoomPartition(roomid);
            string url = this.proxy + $"NewGame/?playerid={playerid}&roomid={roomid}" +
                         $"&playerdata={JsonConvert.SerializeObject(player)}" +
                         $"&roomtype={roomtype}" +
                         $"&PartitionKind=Int64Range&PartitionKey={key}";
            HttpResponseMessage response = await this.httpClient.GetAsync(url);

            if ((int)response.StatusCode == 404)
            {
                this.RenewProxy();

                url = this.proxy + $"NewGame/?playerid={playerid}&roomid={roomid}" +
                      $"&playerdata={JsonConvert.SerializeObject(player)}" +
                      $"&roomtype={roomtype}" +
                      $"&PartitionKind=Int64Range&PartitionKey={key}";
                response = await this.httpClient.GetAsync(url);
            }

            // If this was successful we are now in agreement state, otherwise we may be in a failure state, handled below
            string responseMessage = await response.Content.ReadAsStringAsync();

            return((int)response.StatusCode == 200
                ? new ContentResult {
                StatusCode = 200, Content = roomtype
            }
                : new ContentResult {
                StatusCode = 500, Content = responseMessage
            });
        }
Exemple #2
0
        public async Task <IActionResult> UpdateGameAsync(string playerid, string roomid, string player)
        {
            //Unpackage the player data from its JSON representation
            Player p = JsonConvert.DeserializeObject <Player>(player);

            int    key = Partitioners.GetRoomPartition(roomid);
            string url = this.proxy +
                         $"UpdateGame/?roomid={roomid}&playerid={playerid}" +
                         $"&playerdata={JsonConvert.SerializeObject(p)}&PartitionKind=Int64Range&PartitionKey={key}";

            HttpResponseMessage response = await this.httpClient.GetAsync(url);

            if ((int)response.StatusCode == 404)
            {
                this.RenewProxy();

                url = this.proxy +
                      $"UpdateGame/?roomid={roomid}&playerid={playerid}" +
                      $"&playerdata={JsonConvert.SerializeObject(p)}&PartitionKind=Int64Range&PartitionKey={key}";

                response = await this.httpClient.GetAsync(url);
            }

            return(this.StatusCode((int)response.StatusCode, await response.Content.ReadAsStringAsync()));
        }
Exemple #3
0
        public async Task <IActionResult> EndGameAsync(string playerid, string roomid)
        {
            int    key = Partitioners.GetRoomPartition(roomid);
            string url = this.proxy + $"EndGame/?roomid={roomid}&playerid={playerid}&PartitionKind=Int64Range&PartitionKey={key}";
            HttpResponseMessage response = await this.httpClient.GetAsync(url);

            if ((int)response.StatusCode == 404)
            {
                this.RenewProxy();

                url      = this.proxy + $"EndGame/?roomid={roomid}&playerid={playerid}&PartitionKind=Int64Range&PartitionKey={key}";
                response = await this.httpClient.GetAsync(url);
            }

            return(this.StatusCode((int)response.StatusCode, await response.Content.ReadAsStringAsync()));
        }
Exemple #4
0
        public async Task <IActionResult> GetGameAsync(string roomid)
        {
            int    key = Partitioners.GetRoomPartition(roomid);
            string url = this.proxy + $"GetGame/?roomid={roomid}&PartitionKind=Int64Range&PartitionKey={key}";
            HttpResponseMessage response = await this.httpClient.GetAsync(url);

            //Renew the proxy if the stateful service has moved
            if ((int)response.StatusCode == 404)
            {
                this.RenewProxy();

                url      = this.proxy + $"GetGame/?roomid={roomid}&PartitionKind=Int64Range&PartitionKey={key}";
                response = await this.httpClient.GetAsync(url);
            }

            return(this.StatusCode((int)response.StatusCode, await response.Content.ReadAsStringAsync()));
        }
Exemple #5
0
        public async Task <IActionResult> NewGame(string playerid, string roomid, string roomtype)
        {
            try
            {
                if (!PlayerManager.IsActive)
                {
                    return new ContentResult {
                               StatusCode = 500, Content = "Service is still starting up. Please retry."
                    }
                }
                ;

                IReliableDictionary <string, PlayerPackage> playdict =
                    await this.stateManager.GetOrAddAsync <IReliableDictionary <string, PlayerPackage> >(PlayersDictionaryName);

                PlayerPackage playerPackage; //for handing up player information if login is needed in scenario 2

                using (ITransaction tx = this.stateManager.CreateTransaction())
                {
                    ConditionalValue <PlayerPackage> playerOption = await playdict.TryGetValueAsync(tx, playerid, LockMode.Update);

                    /////////////////////////////////////////////////
                    // SCENARIO 1: PLAYER DOES NOT HAVE AN ACCOUNT //
                    /////////////////////////////////////////////////

                    if (!playerOption.HasValue)
                    {
                        //State: Player does not exist / Cannot be in a game
                        Random rand = new Random(Environment.TickCount);
                        //Generate a new player with a random position
                        Player newPlayer = new Player(
                            rand.Next() % 100 - 6,
                            rand.Next() % 96 - 6,
                            this.startingColors[rand.Next() % this.startingColors.Length]);

                        //Package the new player with its baseline statistics
                        PlayerPackage newPlayerPackage = new PlayerPackage(newPlayer, LogState.LoggedIn, 1, DateTime.UtcNow, roomid);
                        await playdict.AddAsync(tx, playerid, newPlayerPackage);

                        await tx.CommitAsync();


                        return(await this.NewGameRequestHelper(roomid, playerid, roomtype, newPlayer));
                    }

                    //////////////////////////////////////////////////////
                    // SCENARIO 2: PLAYER HAS ACCOUNT AND IS LOGGED OUT //
                    //////////////////////////////////////////////////////

                    if (playerOption.Value.State == LogState.LoggedOut)
                    {
                        /*
                         * Scenario: We think player is logged out (LO-N), in which case this is normal functionality.
                         * The state could also be (LO-LI), which could happen if an EndGame failed halfway through.
                         * If this is the case, there are two scenarios: The first is that the room we are about to log into was
                         * the room that failed to log out, in which case we will override that data since we have the most updated
                         * data and the situation is resolved. The second case is that we are trying to log into a different room.
                         * In this case we trust that the protocol has removed that clients access to the player, which means the
                         * player will eventually be cleaned up by the timeout, keeping the game consistent.
                         */

                        //Grab our player data and update the package
                        PlayerPackage updatedPlayerPackage = playerOption.Value;
                        updatedPlayerPackage.State  = LogState.LoggedIn;
                        updatedPlayerPackage.RoomId = roomid;
                        updatedPlayerPackage.NumLogins++;
                        await playdict.SetAsync(tx, playerid, updatedPlayerPackage);

                        //finish our transaction
                        await tx.CommitAsync();

                        // Request a newgame in the room we want to join
                        return(await this.NewGameRequestHelper(roomid, playerid, roomtype, playerOption.Value.Player));
                    }

                    await tx.CommitAsync();

                    playerPackage = playerOption.Value;
                } // end of tx

                /////////////////////////////////////////////////////
                // SCENARIO 3: PLAYER HAS ACCOUNT AND IS LOGGED IN //
                /////////////////////////////////////////////////////

                if (playerPackage.State == LogState.LoggedIn)
                {
                    // Scenario: This state will generally be the success state, where the player thinks they are logged in and the
                    // appropriate room has the game. However, during login, it is possible that the process crashed between the time
                    // that the login transaction marked the data as logged in and that data being put in the room. We must check to
                    // verify that this is not the state we are in.

                    int key = Partitioners.GetRoomPartition(playerPackage.RoomId);

                    // We first ask if the room has the data to determine which of the above states we are in.
                    string url = this.proxy + $"Exists/?playerid={playerid}&roomid={playerPackage.RoomId}&PartitionKind=Int64Range&PartitionKey={key}";
                    HttpResponseMessage response = await this.httpClient.GetAsync(url);

                    if ((int)response.StatusCode == 404)
                    {
                        this.RenewProxy();

                        url      = this.proxy + $"Exists/?playerid={playerid}&roomid={playerPackage.RoomId}&PartitionKind=Int64Range&PartitionKey={key}";
                        response = await this.httpClient.GetAsync(url);
                    }

                    string responseMessage = await response.Content.ReadAsStringAsync();

                    if ((int)response.StatusCode == 200)
                    {
                        //Player is logged in, so we must deny this request
                        if (responseMessage == "true")
                        {
                            return new ContentResult {
                                       StatusCode = 400, Content = "This player is already logged in"
                            }
                        }
                        ;

                        //Player is not logged in, so we can log into whichever room we want
                        if (responseMessage == "false")
                        {
                            using (ITransaction tx1 = this.stateManager.CreateTransaction())
                            {
                                playerPackage.RoomId = roomid;
                                playerPackage.NumLogins++;
                                await playdict.SetAsync(tx1, playerid, playerPackage);

                                await tx1.CommitAsync();
                            }

                            return(await this.NewGameRequestHelper(roomid, playerid, roomtype, playerPackage.Player));
                        }

                        Environment.FailFast("If returning a success code, the message must be either true or false.");
                    }
                    else
                    {
                        return(new ContentResult {
                            StatusCode = 500, Content = "Something went wrong, please retry"
                        });
                    }
                }

                Environment.FailFast("Players must exist with a valid state attached to them");
                return(new ContentResult {
                    StatusCode = 500
                });
            }
            catch (Exception e)
            {
                return(exceptionHandler(e));
            }
        }