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)); }
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 }); }
/// <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); }