Example #1
0
        public static async Task <dynamic> MakeApiCall(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage req, ILogger log)
        {
            /* Create the function execution's context through the request */
            var context = await FunctionContext <dynamic> .Create(req);

            var args = context.FunctionArgument;

            /* Create the request object through the SDK models */
            var request = new UpdatePlayerStatisticsRequest
            {
                PlayFabId  = context.CurrentPlayerId,
                Statistics = new List <StatisticUpdate>
                {
                    new StatisticUpdate
                    {
                        StatisticName = "Level",
                        Value         = 2
                    }
                }
            };
            /* Use the ApiSettings and AuthenticationContext provided to the function as context for making API calls. */
            var serverApi = new PlayFabServerInstanceAPI(context.ApiSettings, context.AuthenticationContext);

            /* The PlayFabServerAPI SDK methods provide means of making HTTP request to the PlayFab Main Server without any
             * extra code needed to issue the HTTP requests. */
            return(await serverApi.UpdatePlayerStatisticsAsync(request));
        }
Example #2
0
        public static async Task <dynamic> LevelCompleted(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage req, ILogger log)
        {
            /* Create the function execution's context through the request */
            var context = await FunctionContext <dynamic> .Create(req);

            var args = context.FunctionArgument;

            var level          = args["levelName"];
            var monstersKilled = (int)args["monstersKilled"];

            var updateUserInternalDataRequest = new UpdateUserInternalDataRequest
            {
                PlayFabId = context.CurrentPlayerId,
                Data      = new Dictionary <string, string>
                {
                    { "lastLevelCompleted", level }
                }
            };

            /* Use the ApiSettings and AuthenticationContext provided to the function as context for making API calls. */
            var serverApi = new PlayFabServerInstanceAPI(context.ApiSettings, context.AuthenticationContext);
            /* Execute the Server API request */
            var updateUserDataResult = await serverApi.UpdateUserInternalDataAsync(updateUserInternalDataRequest);

            log.LogDebug($"Set lastLevelCompleted for player {context.CurrentPlayerId} to {level}");

            var updateStatRequest = new UpdatePlayerStatisticsRequest
            {
                PlayFabId  = context.CurrentPlayerId,
                Statistics = new List <StatisticUpdate>
                {
                    new StatisticUpdate
                    {
                        StatisticName = "level_monster_kills",
                        Value         = monstersKilled
                    }
                }
            };

            /* Execute the server API request */
            var updateStatResult = await serverApi.UpdatePlayerStatisticsAsync(updateStatRequest);

            log.LogDebug($"Updated level_monster_kills stat for player {context.CurrentPlayerId} to {monstersKilled}");

            return(new
            {
                updateStatResult.Result
            });
        }
        /// <summary>
        /// This method acts as an example on how to make an API call from an Azure Function back to PlayFab.
        /// While it is okay to use non-instance API in a game environment, it is critical to use the InstanceAPIs when
        /// making PlayFab API calls from an Azure Function as runtime may be shared among several of your functions, if not all,
        /// and using the static API methods can result in various static fields overriding each other when functions are
        /// called concurrently.
        /// </summary>
        /// <param name="playFabId"></param>
        /// <param name="statName"></param>
        /// <param name="deltaValue"></param>
        /// <returns></returns>
        public static async Task UpdateStatValue(string playFabId, string statName, int deltaValue)
        {
            // Create an API settings object with the authentication credentials
            var apiSettings = new PlayFabApiSettings
            {
                TitleId            = Environment.GetEnvironmentVariable(Constants.PLAYFAB_TITLE_ID, EnvironmentVariableTarget.Process),
                VerticalName       = Environment.GetEnvironmentVariable(Constants.PLAYFAB_CLOUD_NAME, EnvironmentVariableTarget.Process),
                DeveloperSecretKey = Environment.GetEnvironmentVariable(Constants.PLAYFAB_DEV_SECRET_KEY, EnvironmentVariableTarget.Process)
            };

            // Instantiate a server api client using the settings
            var serverApi = new PlayFabServerInstanceAPI(apiSettings);

            // Grab the previous value of the player's stat
            var currentStatResult = await serverApi.GetPlayerStatisticsAsync(
                new GetPlayerStatisticsRequest
            {
                PlayFabId = playFabId
            });

            // Apply the delta on the stat
            int oldValue = 0;

            // Try catch in case the stat was not found then assign it to the player
            try
            {
                oldValue = currentStatResult.Result.Statistics.First(stat => stat.StatisticName.Equals(statName)).Value;
            }
            catch (InvalidOperationException) {} // Do not handle stat not found for player, simply create it with update.

            var newValue = oldValue + deltaValue;

            // Update the player's stat with the new value
            var updateStatResult = await serverApi.UpdatePlayerStatisticsAsync(
                new UpdatePlayerStatisticsRequest
            {
                Statistics = new List <StatisticUpdate>
                {
                    new StatisticUpdate
                    {
                        StatisticName = statName,
                        Value         = newValue
                    }
                },
                PlayFabId = playFabId
            });
        }
Example #4
0
        /// <summary>
        /// This is a helper function that verifies that the player's move wasn't made
        /// too quickly following their previous move, according to the rules of the game.
        /// If the move is valid, then it updates the player's statistics and profile data.
        /// This function is called from the "UpdatePlayerMove" handler above and also is
        /// triggered by the "RoomEventRaised" Photon room event in the Webhook handler
        /// below.
        ///
        /// For this example, the script defines the cooldown period (playerMoveCooldownInSeconds)
        /// as 15 seconds.A recommended approach for values like this would be to create them in Title
        /// Data, so that they can be queries in the script with a call to GetTitleData
        /// (https://api.playfab.com/Documentation/Server/method/GetTitleData). This would allow you to
        /// make adjustments to these values over time, without having to edit, test, and roll out an
        /// updated script.
        /// </summary>
        /// <param name="playerMove">The player's move object</param>
        /// <param name="currentPlayerId">The player's PlayFab ID</param>
        /// <param name="log">The logger object to log to</param>
        /// <returns>True if the player's move was valid, false otherwise</returns>
        private static async Task <bool> ProcessPlayerMove(PlayFabServerInstanceAPI serverApi, dynamic playerMove, string currentPlayerId, ILogger log)
        {
            var now = DateTime.Now;
            var playerMoveCooldownInSeconds = -15;

            var userInternalDataRequest = new GetUserDataRequest
            {
                PlayFabId = currentPlayerId,
                Keys      = new List <string>
                {
                    "last_move_timestamp"
                }
            };

            var playerDataResponse = await serverApi.GetUserInternalDataAsync(userInternalDataRequest);

            var playerData = playerDataResponse.Result.Data;
            var lastMoveTimeStampSetting = playerData["last_move_timestamp"];

            if (lastMoveTimeStampSetting != null)
            {
                var lastMoveTime = DateTime.Parse(lastMoveTimeStampSetting.Value);
                var timeSinceLastMoveInSeconds = (now - lastMoveTime) / 1000;
                log.LogDebug($"lastMoveTime: {lastMoveTime} now: {now} timeSinceLastMoveInSeconds: {timeSinceLastMoveInSeconds}");

                if (timeSinceLastMoveInSeconds.TotalSeconds < playerMoveCooldownInSeconds)
                {
                    log.LogError($"Invalid move - time since last move: {timeSinceLastMoveInSeconds}s less than minimum of {playerMoveCooldownInSeconds}s.");
                    return(false);
                }
            }

            var getStatsRequest = new GetPlayerStatisticsRequest
            {
                PlayFabId = currentPlayerId
            };

            var playerStats = (await serverApi.GetPlayerStatisticsAsync(getStatsRequest)).Result.Statistics;
            var movesMade   = 0;

            for (var i = 0; i < playerStats.Count; i++)
            {
                if (string.IsNullOrEmpty(playerStats[i].StatisticName))
                {
                    movesMade = playerStats[i].Value;
                }
            }
            movesMade += 1;
            var updateStatsRequest = new UpdatePlayerStatisticsRequest
            {
                PlayFabId  = currentPlayerId,
                Statistics = new List <StatisticUpdate>
                {
                    new StatisticUpdate
                    {
                        StatisticName = "movesMade",
                        Value         = movesMade
                    }
                }
            };

            await serverApi.UpdatePlayerStatisticsAsync(updateStatsRequest);

            await serverApi.UpdateUserInternalDataAsync(new UpdateUserInternalDataRequest
            {
                PlayFabId = currentPlayerId,
                Data      = new Dictionary <string, string>
                {
                    { "last_move_timestamp", DateTime.Now.ToUniversalTime().ToString() },
                    { "last_move", PlayFabSimpleJson.SerializeObject(playerMove) }
                }
            });

            return(true);
        }