From 4bf7bdca0cc2891820851528e5c80729a97d5dc7 Mon Sep 17 00:00:00 2001 From: fiddlegiant Date: Thu, 30 May 2024 22:21:15 -0700 Subject: [PATCH 1/6] Partial update to support: - PlayFabAllSDK 1.182.240524 - PlayFabCloudScriptPlugin 1.53.190627-alpha Modified CSharp functions to get unity Tic-Tac-Toe working through playfab to azure. This is a partial submission .. the Tic-Tac-Toe code needs to be integrated with tho fork and committed too. --- .../Functions/MakeAIMove.cs | 123 ++++++++++++------ .../Functions/MakePlayerMove.cs | 84 +++++++----- .../Functions/ResetGameState.cs | 81 +++++++----- .../Functions/WinChecker.cs | 85 +++++++----- .../TicTacToeFunctions/Util/GameStateUtil.cs | 69 +++++----- .../Util/GamesPlayedUtil.cs | 39 +++--- .../TicTacToeFunctions/Util/Settings.cs | 10 +- 7 files changed, 289 insertions(+), 202 deletions(-) diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs index a08b91d1..bed43adf 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs @@ -1,70 +1,113 @@ // Copyright (C) Microsoft Corporation. All rights reserved. -using System.Threading.Tasks; -using Microsoft.Azure.WebJobs; -using Microsoft.Azure.WebJobs.Extensions.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PlayFab; +using PlayFab.Samples; using PlayFab.TicTacToeDemo.Models; -using System.Net.Http; -using PlayFab.Plugins.CloudScript; using PlayFab.TicTacToeDemo.Util; +using FunctionContext = PlayFab.Plugins.CloudScript.FunctionContext; -namespace TicTacToeFunctions.Functions -{ - public static class MakeAIMove - { - [FunctionName("MakeRandomAIMove")] - public static async Task MakeRandomAIMove( - [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage req, - ILogger log) - { - var context = await FunctionContext.Create(req); +namespace Shuffle.TicTacToe.Functions { + public class MakeAiMove { + private readonly ILogger _logger; - Settings.TrySetSecretKey(context.ApiSettings); - Settings.TrySetCloudName(context.ApiSettings); + public MakeAiMove(ILoggerFactory loggerFactory) { + _logger = loggerFactory.CreateLogger(); + } + + [Function("MakeRandomAiMove")] + public async Task MakeRandomAiMove( + [HttpTrigger(AuthorizationLevel.Function, "post")] + HttpRequestData requestData, + FunctionContext executionContext) { + + string zRequest = await requestData.ReadAsStringAsync() ?? string.Empty; + PlayerPlayStreamFunctionExecutionContext? context = + JsonConvert.DeserializeObject>(zRequest); - var playFabId = context.FunctionArgument.PlayFabId; + // Pretty print requestData + string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); + _logger.LogInformation("Request Data: {prettyRequestBody}\n", prettyRequestBody); + + // Pretty print executionContext + string executionContextString = JsonConvert.SerializeObject(context); + string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); + _logger.LogInformation("Execution Context: {prettyExecutionContext}\n", prettyExecutionContext); + + if (context == null) { + return new BadRequestObjectResult("Invalid context"); + } + + PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; + Settings.TrySetSecretKey(ref settings); + Settings.TrySetCloudName(ref settings); + + PlayFabIdRequest playFabIdRequest = context.FunctionArgument.ToObject(); // Attempt to load the player's game state - var state = await GameStateUtil.GetCurrentGameState(playFabId, context.ApiSettings, context.AuthenticationContext); + TicTacToeState state = await GameStateUtil.GetCurrentGameState(playFabIdRequest.PlayFabId, settings); // Look for a random AI move to make - var aiMove = TicTacToeAI.GetNextRandomMove(state); + TicTacToeMove aiMove = TicTacToeAI.GetNextRandomMove(state); // Store the AI move on the current game state - var oneDimMoveIndex = aiMove.row * 3 + aiMove.col; - state.Data[oneDimMoveIndex] = (int) OccupantType.AI; - await GameStateUtil.UpdateCurrentGameState(state, playFabId, context.ApiSettings, context.AuthenticationContext); - + int oneDimMoveIndex = aiMove.row * 3 + aiMove.col; + state.Data[oneDimMoveIndex] = (int)OccupantType.AI; + await GameStateUtil.UpdateCurrentGameState(state, playFabIdRequest.PlayFabId, settings); + // Respond with the AI move - return aiMove; + return new OkObjectResult(aiMove); } - [FunctionName("MakeMinimaxAIMove")] - public static async Task MakeMinimaxAIMove( - [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage req, - ILogger log) - { - var context = await FunctionContext.Create(req); - Settings.TrySetSecretKey(context.ApiSettings); - Settings.TrySetCloudName(context.ApiSettings); + //[Function("MakeAiMove")] + [Function("MakeMinMaxAiMove")] + public async Task MakeMinMaxAiMove( + [HttpTrigger(AuthorizationLevel.Function, "post")] + HttpRequestData requestData, + FunctionContext executionContext) { + + string zRequest = await requestData.ReadAsStringAsync() ?? string.Empty; + PlayerPlayStreamFunctionExecutionContext? context = + JsonConvert.DeserializeObject>(zRequest); + + // Pretty print requestData + string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); + _logger.LogInformation("Request Data: \n" + prettyRequestBody); + + // Pretty print executionContext + string executionContextString = JsonConvert.SerializeObject(context); + string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); + _logger.LogInformation("Execution Context: \n" + prettyExecutionContext); + + if (context == null) { + return new BadRequestObjectResult("Invalid context"); + } + + PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; + Settings.TrySetSecretKey(ref settings); + Settings.TrySetCloudName(ref settings); - var playFabId = context.FunctionArgument.PlayFabId; + PlayFabIdRequest playFabIdRequest = context.FunctionArgument.ToObject(); // Attempt to load the Player's game state - var state = await GameStateUtil.GetCurrentGameState(playFabId, context.ApiSettings, context.AuthenticationContext); + TicTacToeState state = await GameStateUtil.GetCurrentGameState(playFabIdRequest.PlayFabId, settings); // Look for a minimax AI move to make - var aiMove = TicTacToeAI.GetNextMinimaxMove(state); + TicTacToeMove aiMove = TicTacToeAI.GetNextMinimaxMove(state); // Store the AI move on the current game state - var oneDimMoveIndex = aiMove.row * 3 + aiMove.col; - state.Data[oneDimMoveIndex] = (int) OccupantType.AI; - await GameStateUtil.UpdateCurrentGameState(state, playFabId, context.ApiSettings, context.AuthenticationContext); + int oneDimMoveIndex = aiMove.row * 3 + aiMove.col; + state.Data[oneDimMoveIndex] = (int)OccupantType.AI; + await GameStateUtil.UpdateCurrentGameState(state, playFabIdRequest.PlayFabId, settings); // Respond with the AI move - return aiMove; + return new OkObjectResult(aiMove); } } } diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs index 9de5f3b4..1306e487 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs @@ -1,57 +1,69 @@ // Copyright (C) Microsoft Corporation. All rights reserved. -using System.Threading.Tasks; -using Microsoft.Azure.WebJobs; -using Microsoft.Azure.WebJobs.Extensions.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PlayFab.Samples; using PlayFab.TicTacToeDemo.Models; -using System.Net.Http; -using PlayFab.Plugins.CloudScript; using PlayFab.TicTacToeDemo.Util; +using FunctionContext = PlayFab.Plugins.CloudScript.FunctionContext; -namespace PlayFab.TicTacToeDemo.Functions -{ - public static class MakePlayerMove - { - [FunctionName("MakePlayerMove")] - public static async Task Run( - [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage req, - ILogger log) - { - var context = await FunctionContext.Create(req); - var move = context.FunctionArgument.Move; +namespace PlayFab.TicTacToeDemo.Functions { + public class MakePlayerMove { + private readonly ILogger _logger; - Settings.TrySetSecretKey(context.ApiSettings); - Settings.TrySetCloudName(context.ApiSettings); + public MakePlayerMove(ILoggerFactory loggerFactory) { + _logger = loggerFactory.CreateLogger(); + } + + [Function("MakePlayerMove")] + public async Task Run( + [HttpTrigger(AuthorizationLevel.Function, "post")] + HttpRequestData requestData, + FunctionContext executionContext) { + + string zRequest = await requestData.ReadAsStringAsync() ?? string.Empty; + PlayerPlayStreamFunctionExecutionContext? context = + JsonConvert.DeserializeObject>(zRequest); + + // Pretty print requestData + string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); + _logger.LogInformation("Request Data: {prettyRequestBody}\n", prettyRequestBody); - var playFabId = context.FunctionArgument.PlayFabId; + // Pretty print executionContext + string executionContextString = JsonConvert.SerializeObject(context); + string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); + _logger.LogInformation("Execution Context: {prettyExecutionContext}\n", prettyExecutionContext); + + if (context == null) { + return new BadRequestObjectResult("Invalid context"); + } + + PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; + Settings.TrySetSecretKey(ref settings); + Settings.TrySetCloudName(ref settings); + + MakePlayerMoveRequest moveRequest = context.FunctionArgument.ToObject(); // Attempt to load the player's game state - var state = await GameStateUtil.GetCurrentGameState(playFabId, context.ApiSettings, context.AuthenticationContext); + TicTacToeState state = await GameStateUtil.GetCurrentGameState(moveRequest.PlayFabId, settings); + TicTacToeMove move = moveRequest.Move; - var oneDimMoveIndex = move.row * 3 + move.col; + int oneDimMoveIndex = move.row * 3 + move.col; // Move can only be made if spot was empty if (state.Data[oneDimMoveIndex] == (int) OccupantType.NONE) { state.Data[oneDimMoveIndex] = (int) OccupantType.PLAYER; - await GameStateUtil.UpdateCurrentGameState(state, playFabId, context.ApiSettings, context.AuthenticationContext); - return new MakePlayerMoveResult() - { - Valid = true - }; + await GameStateUtil.UpdateCurrentGameState(state, moveRequest.PlayFabId, settings); + return new OkObjectResult(new MakePlayerMoveResult { Valid = true }); } + // Move attempt was invalid - else - { - return new MakePlayerMoveResult() - { - Valid = false - }; - } + return new OkObjectResult(new MakePlayerMoveResult { Valid = false }); } - - - } } diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/ResetGameState.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/ResetGameState.cs index b52bbc46..a4898d3e 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/ResetGameState.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/ResetGameState.cs @@ -1,40 +1,59 @@ // Copyright (C) Microsoft Corporation. All rights reserved. -using System.Threading.Tasks; -using Microsoft.Azure.WebJobs; -using Microsoft.Azure.WebJobs.Extensions.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; -using System.Net.Http; -using PlayFab.TicTacToeDemo.Util; -using PlayFab.Plugins.CloudScript; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PlayFab; +using PlayFab.Samples; using PlayFab.TicTacToeDemo.Models; +using PlayFab.TicTacToeDemo.Util; +using FunctionContext = PlayFab.Plugins.CloudScript.FunctionContext; + +namespace TicTacToeFunctions.Functions { + public class ResetGameState { + private readonly ILogger _logger; + + public ResetGameState(ILoggerFactory loggerFactory) { + _logger = loggerFactory.CreateLogger(); + } + + [Function("ResetGameState")] + public async Task Run( + [HttpTrigger(AuthorizationLevel.Function, "post")] + HttpRequestData requestData, + FunctionContext executionContext) { + + string zRequest = await requestData.ReadAsStringAsync() ?? string.Empty; + FunctionExecutionContext? context = + JsonConvert.DeserializeObject>(zRequest); + + // Pretty print requestData + string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); + _logger.LogInformation("Request Data: {prettyRequestBody}\n", prettyRequestBody); + + // Pretty print executionContext + string executionContextString = JsonConvert.SerializeObject(context); + string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); + _logger.LogInformation("Execution Context: {prettyExecutionContext}\n", prettyExecutionContext); + + if (context == null) { + return new BadRequestObjectResult("Invalid context"); + } + + PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; + Settings.TrySetSecretKey(ref settings); + Settings.TrySetCloudName(ref settings); + + string playFabId = context.CallerEntityProfile.Lineage.MasterPlayerAccountId; + + TicTacToeState newCurrentGameState = new() { Data = new int[9] }; -namespace TicTacToeFunctions.Functions -{ - public static class ResetGameState - { - [FunctionName("ResetGameState")] - public static async Task Run( - [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage req, - ILogger log) - { - var context = await FunctionContext.Create(req); - var playFabId = context.FunctionArgument.PlayFabId; - - Settings.TrySetSecretKey(context.ApiSettings); - Settings.TrySetCloudName(context.ApiSettings); - - var newCurrentGameState = new TicTacToeState() - { - Data = new int[9] - }; - - await GameStateUtil.UpdateCurrentGameState( - newCurrentGameState, - playFabId, - context.ApiSettings, - context.AuthenticationContext); + await GameStateUtil.UpdateCurrentGameState(newCurrentGameState, playFabId, settings); + return new OkResult(); } } } diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/WinChecker.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/WinChecker.cs index a0ad08ec..b952a3b1 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/WinChecker.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/WinChecker.cs @@ -1,52 +1,75 @@ // Copyright (C) Microsoft Corporation. All rights reserved. -using System.Threading.Tasks; -using Microsoft.Azure.WebJobs; -using Microsoft.Azure.WebJobs.Extensions.Http; -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PlayFab; +using PlayFab.Samples; using PlayFab.TicTacToeDemo.Models; -using System.Net.Http; -using PlayFab.Plugins.CloudScript; using PlayFab.TicTacToeDemo.Util; +using FunctionContext = PlayFab.Plugins.CloudScript.FunctionContext; -namespace PlayFab.TicTacToeDemo.Functions +namespace TicTacToeFunctions.Functions { - public static class WinChecker + public class WinChecker { - [FunctionName("WinCheck")] - public static async Task Run( - [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage entityRequest, HttpRequest httpRequest, - ILogger log) - { - // Extract the context from the incoming request - var context = await FunctionContext.Create(entityRequest); + private readonly ILogger _logger; - string playFabId = context.FunctionArgument.PlayFabId; + public WinChecker(ILoggerFactory loggerFactory) { + _logger = loggerFactory.CreateLogger(); + } + + [Function("WinCheck")] + public async Task Run( + [HttpTrigger(AuthorizationLevel.Function, "post")] + HttpRequestData requestData, + FunctionContext executionContext) { + + string zRequest = await requestData.ReadAsStringAsync() ?? string.Empty; + PlayerPlayStreamFunctionExecutionContext? context = + JsonConvert.DeserializeObject>(zRequest); + + // Pretty print requestData + string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); + _logger.LogInformation("Request Data: {prettyRequestBody}\n", prettyRequestBody); - Settings.TrySetSecretKey(context.ApiSettings); - Settings.TrySetCloudName(context.ApiSettings); + // Pretty print executionContext + string executionContextString = JsonConvert.SerializeObject(context); + string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); + _logger.LogInformation("Execution Context: {prettyExecutionContext}\n", prettyExecutionContext); - // Grab the current player's game state - var state = await GameStateUtil.GetCurrentGameState(playFabId, context.ApiSettings, context.AuthenticationContext); + if (context == null) { + return new BadRequestObjectResult("Invalid context"); + } - var winCheckResult = WinCheckUtil.Check(state); + PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; + Settings.TrySetSecretKey(ref settings); + Settings.TrySetCloudName(ref settings); - if (winCheckResult.Winner != GameWinnerType.NONE) - { - // Update the leaderboard accordingly - await LeaderboardUtils.UpdateLeaderboard(playFabId, winCheckResult.Winner); + PlayFabIdRequest playFabIdRequest = context.FunctionArgument.ToObject(); - // Store the game history - await GameStateUtil.AddGameStateHistory(state, playFabId, context.ApiSettings, context.AuthenticationContext); + // Grab the current player's game state + TicTacToeState state = await GameStateUtil.GetCurrentGameState(playFabIdRequest.PlayFabId, settings); + + WinCheckResult winCheckResult = WinCheckUtil.Check(state); - // Clear the current game state - await GameStateUtil.UpdateCurrentGameState(new TicTacToeState(), playFabId, context.ApiSettings, context.AuthenticationContext); + if (winCheckResult.Winner == GameWinnerType.NONE) { + return new OkObjectResult(winCheckResult); } - + // Update the leaderboard accordingly + await LeaderboardUtils.UpdateLeaderboard(playFabIdRequest.PlayFabId, winCheckResult.Winner); + + // Store the game history + await GameStateUtil.AddGameStateHistory(state, playFabIdRequest.PlayFabId, settings); + + // Clear the current game state + await GameStateUtil.UpdateCurrentGameState(new TicTacToeState(), playFabIdRequest.PlayFabId, settings); - return winCheckResult; + return new OkObjectResult(winCheckResult); } } } diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GameStateUtil.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GameStateUtil.cs index 57bf1bbe..2e017d5b 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GameStateUtil.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GameStateUtil.cs @@ -3,60 +3,57 @@ using PlayFab.Json; using PlayFab.ServerModels; using PlayFab.TicTacToeDemo.Models; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; namespace PlayFab.TicTacToeDemo.Util { public static class GameStateUtil { - public static async Task GetCurrentGameState(string playFabId, PlayFabApiSettings apiSettings, PlayFabAuthenticationContext authenticationContext) + public static async Task GetCurrentGameState(string playFabId, PlayFabApiSettings apiSettings) { - var request = new GetUserDataRequest() - { - PlayFabId = playFabId, - Keys = new List() { Constants.GAME_CURRENT_STATE_KEY } - }; + GetUserDataRequest request = new() + { + PlayFabId = playFabId, + Keys = new List() { Constants.GAME_CURRENT_STATE_KEY } + }; - var serverApi = new PlayFabServerInstanceAPI(apiSettings, authenticationContext); + PlayFabServerInstanceAPI serverApi = new(apiSettings); - var result = await serverApi.GetUserDataAsync(request); + PlayFabResult? result = await serverApi.GetUserDataAsync(request); if (result.Error != null) { throw new Exception($"An error occurred while fetching the current game state: Error: {result.Error.GenerateErrorReport()}"); } - var resultData = result.Result.Data; + Dictionary? resultData = result.Result.Data; // Current state found - if (resultData.Count > 0 && resultData.TryGetValue(Constants.GAME_CURRENT_STATE_KEY, out var currentGameStateRecord)) + if (resultData.Count > 0 && resultData.TryGetValue(Constants.GAME_CURRENT_STATE_KEY, out UserDataRecord? currentGameStateRecord)) { return PlayFabSimpleJson.DeserializeObject(currentGameStateRecord.Value); } // Current game record does not exist and so must be created else { - var newState = new TicTacToeState() { Data = new int[9] }; - await UpdateCurrentGameState(newState, playFabId, apiSettings, authenticationContext); + TicTacToeState newState = new() { Data = new int[9] }; + await UpdateCurrentGameState(newState, playFabId, apiSettings); return newState; } } - public static async Task UpdateCurrentGameState(TicTacToeState state, string playFabId, PlayFabApiSettings apiSettings, PlayFabAuthenticationContext authenticationContext) + public static async Task UpdateCurrentGameState(TicTacToeState state, string entityId, PlayFabApiSettings apiSettings) { - var serializedNewGameState = PlayFabSimpleJson.SerializeObject(state); + string? serializedNewGameState = PlayFabSimpleJson.SerializeObject(state); - var request = new UpdateUserDataRequest() - { - PlayFabId = playFabId, - Data = new Dictionary() { { Constants.GAME_CURRENT_STATE_KEY, serializedNewGameState} } - }; + UpdateUserDataRequest request = new() + { + PlayFabId = entityId, + Data = new Dictionary() { { Constants.GAME_CURRENT_STATE_KEY, serializedNewGameState} } + }; - var serverApi = new PlayFabServerInstanceAPI(apiSettings, authenticationContext); + PlayFabServerInstanceAPI serverApi = new(apiSettings); - var result = await serverApi.UpdateUserDataAsync(request); + PlayFabResult? result = await serverApi.UpdateUserDataAsync(request); if (result.Error != null) { @@ -64,30 +61,30 @@ public static async Task UpdateCurrentGameState(TicTacToeState state, string pla } } - public static async Task AddGameStateHistory(TicTacToeState gameState, string playFabId, PlayFabApiSettings apiSettings, PlayFabAuthenticationContext authenticationContext) + public static async Task AddGameStateHistory(TicTacToeState gameState, string playFabId, PlayFabApiSettings apiSettings) { - var gamesPlayed = await GameDataUtil.GetGamesPlayed(playFabId, apiSettings, authenticationContext); + int gamesPlayed = await GameDataUtil.GetGamesPlayed(playFabId, apiSettings); - var key = $"{Constants.GAME_STATE_KEY}_{gamesPlayed + 1}"; + string key = $"{Constants.GAME_STATE_KEY}_{gamesPlayed + 1}"; - var serializedGameState = PlayFabSimpleJson.SerializeObject(gameState); + string? serializedGameState = PlayFabSimpleJson.SerializeObject(gameState); - var request = new UpdateUserDataRequest() - { - PlayFabId = playFabId, - Data = new Dictionary() { { key, serializedGameState } } - }; + UpdateUserDataRequest request = new() + { + PlayFabId = playFabId, + Data = new Dictionary() { { key, serializedGameState } } + }; - var serverApi = new PlayFabServerInstanceAPI(apiSettings, authenticationContext); + PlayFabServerInstanceAPI serverApi = new(apiSettings); - var result = await serverApi.UpdateUserDataAsync(request); + PlayFabResult? result = await serverApi.UpdateUserDataAsync(request); if (result.Error != null) { throw new Exception($"An error occured while updating the game state: Error: {result.Error.GenerateErrorReport()}"); } - await GameDataUtil.SetGamesPlayed(gamesPlayed + 1, playFabId, apiSettings, authenticationContext); + await GameDataUtil.SetGamesPlayed(gamesPlayed + 1, playFabId, apiSettings); } } } diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GamesPlayedUtil.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GamesPlayedUtil.cs index cdee8392..e49609e5 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GamesPlayedUtil.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GamesPlayedUtil.cs @@ -1,54 +1,49 @@ // Copyright (C) Microsoft Corporation. All rights reserved. using PlayFab.ServerModels; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; namespace PlayFab.TicTacToeDemo.Util { public static class GameDataUtil { - public static async Task GetGamesPlayed(string playFabId, PlayFabApiSettings apiSettings, PlayFabAuthenticationContext authenticationContext) + public static async Task GetGamesPlayed(string playFabId, PlayFabApiSettings apiSettings) { - var request = new GetUserDataRequest - { - PlayFabId = playFabId, - Keys = new List { Constants.GAMES_PLAYED_KEY } - }; + GetUserDataRequest request = new() { + PlayFabId = playFabId, + Keys = new List { Constants.GAMES_PLAYED_KEY } + }; - var serverApi = new PlayFabServerInstanceAPI(apiSettings, authenticationContext); + PlayFabServerInstanceAPI serverApi = new(apiSettings); - var result = await serverApi.GetUserDataAsync(request); + PlayFabResult? result = await serverApi.GetUserDataAsync(request); if (result.Error != null) { throw new Exception($"An error occured while fetching the number of games played: Error: {result.Error.GenerateErrorReport()}"); } - var resultData = result.Result.Data; + Dictionary? resultData = result.Result.Data; - if (resultData.Count > 0 && resultData.TryGetValue(Constants.GAMES_PLAYED_KEY, out var gamesPlayedRecord)) + if (resultData.Count > 0 && resultData.TryGetValue(Constants.GAMES_PLAYED_KEY, out UserDataRecord? gamesPlayedRecord)) { return int.Parse(gamesPlayedRecord.Value); } // Set the number of games played to be 0 since the record doesn't exist - await SetGamesPlayed(0, playFabId, apiSettings, authenticationContext); + await SetGamesPlayed(0, playFabId, apiSettings); return 0; } - public static async Task SetGamesPlayed(int gamesPlayed, string playFabId, PlayFabApiSettings apiSettings, PlayFabAuthenticationContext authenticationContext) + public static async Task SetGamesPlayed(int gamesPlayed, string playFabId, PlayFabApiSettings apiSettings) { - var request = new UpdateUserDataRequest - { - PlayFabId = playFabId, - Data = new Dictionary { { Constants.GAMES_PLAYED_KEY.ToString(), gamesPlayed.ToString() } } - }; + UpdateUserDataRequest request = new() { + PlayFabId = playFabId, + Data = new Dictionary { { Constants.GAMES_PLAYED_KEY, gamesPlayed.ToString() } } + }; - var serverApi = new PlayFabServerInstanceAPI(apiSettings, authenticationContext); + PlayFabServerInstanceAPI serverApi = new(apiSettings); - var result = await serverApi.UpdateUserDataAsync(request); + PlayFabResult? result = await serverApi.UpdateUserDataAsync(request); if (result.Error != null) { diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Settings.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Settings.cs index c57ae332..c3773dfe 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Settings.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Settings.cs @@ -1,14 +1,12 @@ // Copyright (C) Microsoft Corporation. All rights reserved. -using System; - namespace PlayFab.TicTacToeDemo.Util { public static class Settings { - public static void TrySetSecretKey(PlayFabApiSettings settings) + public static void TrySetSecretKey(ref PlayFabApiSettings settings) { - var secretKey = Environment.GetEnvironmentVariable(Constants.PLAYFAB_DEV_SECRET_KEY, EnvironmentVariableTarget.Process); + string? secretKey = Environment.GetEnvironmentVariable(Constants.PLAYFAB_DEV_SECRET_KEY, EnvironmentVariableTarget.Process); if (!string.IsNullOrEmpty(secretKey)) { @@ -16,9 +14,9 @@ public static void TrySetSecretKey(PlayFabApiSettings settings) } } - public static void TrySetCloudName(PlayFabApiSettings settings) + public static void TrySetCloudName(ref PlayFabApiSettings settings) { - var cloud = Environment.GetEnvironmentVariable(Constants.PLAYFAB_CLOUD_NAME, EnvironmentVariableTarget.Process); + string? cloud = Environment.GetEnvironmentVariable(Constants.PLAYFAB_CLOUD_NAME, EnvironmentVariableTarget.Process); if (!string.IsNullOrEmpty(cloud)) { From 5d2ede56a4cdd2f1aa6d8079dd0bfb5edff7dd3b Mon Sep 17 00:00:00 2001 From: fiddlegiant Date: Thu, 30 May 2024 23:02:12 -0700 Subject: [PATCH 2/6] Fix err in namespaces --- .../AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs | 3 +-- .../TicTacToeFunctions/Functions/MakePlayerMove.cs | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs index bed43adf..25ea5f5e 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs @@ -12,7 +12,7 @@ using PlayFab.TicTacToeDemo.Util; using FunctionContext = PlayFab.Plugins.CloudScript.FunctionContext; -namespace Shuffle.TicTacToe.Functions { +namespace TicTacToeFunctions.Functions { public class MakeAiMove { private readonly ILogger _logger; @@ -38,7 +38,6 @@ public async Task MakeRandomAiMove( string executionContextString = JsonConvert.SerializeObject(context); string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); _logger.LogInformation("Execution Context: {prettyExecutionContext}\n", prettyExecutionContext); - if (context == null) { return new BadRequestObjectResult("Invalid context"); } diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs index 1306e487..c4c8df50 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs @@ -6,12 +6,13 @@ using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using PlayFab; using PlayFab.Samples; using PlayFab.TicTacToeDemo.Models; using PlayFab.TicTacToeDemo.Util; using FunctionContext = PlayFab.Plugins.CloudScript.FunctionContext; -namespace PlayFab.TicTacToeDemo.Functions { +namespace TicTacToeDemo.Functions { public class MakePlayerMove { private readonly ILogger _logger; From da6ac0afdd1fce1d50293cb4fcf51cc4f9a7f0ea Mon Sep 17 00:00:00 2001 From: fiddlegiant Date: Sun, 2 Jun 2024 13:09:55 -0700 Subject: [PATCH 3/6] Reducing whitespace and coding format differences for merge to fork. --- .../Functions/MakeAIMove.cs | 112 +++---- .../Functions/MakePlayerMove.cs | 56 +--- .../Functions/ResetGameState.cs | 66 ++-- .../Functions/WinChecker.cs | 73 ++-- .../TicTacToeFunctions/Util/Settings.cs | 10 +- .../TicTacToeFunctions/Util/Util.cs | 27 ++ .../Unity/TicTacToe/Assets/PlayFabSDK.meta | 5 +- .../Assets/Scripts/Handlers/AIMoveHandler.cs | 10 +- .../Scripts/Handlers/PlayerMoveHandler.cs | 10 +- .../Scripts/Handlers/ResetGameStateHandler.cs | 10 +- .../Scripts/Handlers/WinCheckHandler.cs | 10 +- .../TicTacToe/Assets/Scripts/Settings.cs | 2 - .../Unity/TicTacToe/Packages/manifest.json | 14 +- .../ProjectSettings/ProjectSettings.asset | 311 ++++++++++++++---- .../ProjectSettings/ProjectVersion.txt | 4 +- 15 files changed, 420 insertions(+), 300 deletions(-) mode change 100644 => 100755 Samples/Unity/TicTacToe/Assets/PlayFabSDK.meta diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs index 25ea5f5e..f30ee74f 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs @@ -4,109 +4,73 @@ using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using PlayFab; -using PlayFab.Samples; using PlayFab.TicTacToeDemo.Models; using PlayFab.TicTacToeDemo.Util; -using FunctionContext = PlayFab.Plugins.CloudScript.FunctionContext; +using PlayFab; -namespace TicTacToeFunctions.Functions { - public class MakeAiMove { - private readonly ILogger _logger; +namespace TicTacToeFunctions.Functions +{ + public class MakeAIMove(ILoggerFactory loggerFactory) + { + [Function("MakeRandomAIMove")] + public async Task MakeRandomAIMove( + [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req, + FunctionContext executionContext) + { + var context = await PlayFabFunctionHelper.GetContext(_logger, req); + if (context is null) return new BadRequestObjectResult("Invalid context"); - public MakeAiMove(ILoggerFactory loggerFactory) { - _logger = loggerFactory.CreateLogger(); - } - - [Function("MakeRandomAiMove")] - public async Task MakeRandomAiMove( - [HttpTrigger(AuthorizationLevel.Function, "post")] - HttpRequestData requestData, - FunctionContext executionContext) { - - string zRequest = await requestData.ReadAsStringAsync() ?? string.Empty; - PlayerPlayStreamFunctionExecutionContext? context = - JsonConvert.DeserializeObject>(zRequest); - - // Pretty print requestData - string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); - _logger.LogInformation("Request Data: {prettyRequestBody}\n", prettyRequestBody); - - // Pretty print executionContext - string executionContextString = JsonConvert.SerializeObject(context); - string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); - _logger.LogInformation("Execution Context: {prettyExecutionContext}\n", prettyExecutionContext); - if (context == null) { - return new BadRequestObjectResult("Invalid context"); - } + var settings = new PlayFabApiSettings { TitleId = context.TitleAuthenticationContext.Id, }; + Settings.TrySetSecretKey(settings); + Settings.TrySetCloudName(settings); - PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; - Settings.TrySetSecretKey(ref settings); - Settings.TrySetCloudName(ref settings); - - PlayFabIdRequest playFabIdRequest = context.FunctionArgument.ToObject(); + var playFabId = context.FunctionArgument.ToObject().PlayFabId; // Attempt to load the player's game state - TicTacToeState state = await GameStateUtil.GetCurrentGameState(playFabIdRequest.PlayFabId, settings); + var state = await GameStateUtil.GetCurrentGameState(playFabId, settings); // Look for a random AI move to make - TicTacToeMove aiMove = TicTacToeAI.GetNextRandomMove(state); + var aiMove = TicTacToeAI.GetNextRandomMove(state); // Store the AI move on the current game state - int oneDimMoveIndex = aiMove.row * 3 + aiMove.col; - state.Data[oneDimMoveIndex] = (int)OccupantType.AI; - await GameStateUtil.UpdateCurrentGameState(state, playFabIdRequest.PlayFabId, settings); + var oneDimMoveIndex = aiMove.row * 3 + aiMove.col; + state.Data[oneDimMoveIndex] = (int) OccupantType.AI; + await GameStateUtil.UpdateCurrentGameState(state, playFabId, settings); // Respond with the AI move return new OkObjectResult(aiMove); } - //[Function("MakeAiMove")] - [Function("MakeMinMaxAiMove")] - public async Task MakeMinMaxAiMove( - [HttpTrigger(AuthorizationLevel.Function, "post")] - HttpRequestData requestData, - FunctionContext executionContext) { - - string zRequest = await requestData.ReadAsStringAsync() ?? string.Empty; - PlayerPlayStreamFunctionExecutionContext? context = - JsonConvert.DeserializeObject>(zRequest); - - // Pretty print requestData - string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); - _logger.LogInformation("Request Data: \n" + prettyRequestBody); - - // Pretty print executionContext - string executionContextString = JsonConvert.SerializeObject(context); - string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); - _logger.LogInformation("Execution Context: \n" + prettyExecutionContext); - - if (context == null) { - return new BadRequestObjectResult("Invalid context"); - } + [Function("MakeMinMaxAIMove")] + public async Task MakeMinMaxAIMove( + [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req, + FunctionContext executionContext) + { + var context = await PlayFabFunctionHelper.GetContext(_logger, req); + if (context is null) return new BadRequestObjectResult("Invalid context"); PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; - Settings.TrySetSecretKey(ref settings); - Settings.TrySetCloudName(ref settings); + Settings.TrySetSecretKey(settings); + Settings.TrySetCloudName(settings); - PlayFabIdRequest playFabIdRequest = context.FunctionArgument.ToObject(); + var playFabId = context.FunctionArgument.ToObject().PlayFabId; // Attempt to load the Player's game state - TicTacToeState state = await GameStateUtil.GetCurrentGameState(playFabIdRequest.PlayFabId, settings); + var state = await GameStateUtil.GetCurrentGameState(playFabId, settings); // Look for a minimax AI move to make - TicTacToeMove aiMove = TicTacToeAI.GetNextMinimaxMove(state); + var aiMove = TicTacToeAI.GetNextMinimaxMove(state); // Store the AI move on the current game state - int oneDimMoveIndex = aiMove.row * 3 + aiMove.col; - state.Data[oneDimMoveIndex] = (int)OccupantType.AI; - await GameStateUtil.UpdateCurrentGameState(state, playFabIdRequest.PlayFabId, settings); + var oneDimMoveIndex = aiMove.row * 3 + aiMove.col; + state.Data[oneDimMoveIndex] = (int) OccupantType.AI; + await GameStateUtil.UpdateCurrentGameState(state, playFabId, settings); // Respond with the AI move return new OkObjectResult(aiMove); } + + private readonly ILogger _logger = loggerFactory.CreateLogger(); } } diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs index c4c8df50..464b32db 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakePlayerMove.cs @@ -4,54 +4,30 @@ using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using PlayFab; -using PlayFab.Samples; using PlayFab.TicTacToeDemo.Models; using PlayFab.TicTacToeDemo.Util; -using FunctionContext = PlayFab.Plugins.CloudScript.FunctionContext; - -namespace TicTacToeDemo.Functions { - public class MakePlayerMove { - private readonly ILogger _logger; - - public MakePlayerMove(ILoggerFactory loggerFactory) { - _logger = loggerFactory.CreateLogger(); - } +namespace PlayFab.TicTacToeDemo.Functions +{ + public class MakePlayerMove(ILoggerFactory loggerFactory) + { [Function("MakePlayerMove")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Function, "post")] - HttpRequestData requestData, - FunctionContext executionContext) { - - string zRequest = await requestData.ReadAsStringAsync() ?? string.Empty; - PlayerPlayStreamFunctionExecutionContext? context = - JsonConvert.DeserializeObject>(zRequest); - - // Pretty print requestData - string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); - _logger.LogInformation("Request Data: {prettyRequestBody}\n", prettyRequestBody); + [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req, + FunctionContext executionContext) + { + var context = await PlayFabFunctionHelper.GetContext(_logger, req); + if (context is null) return new BadRequestObjectResult("Invalid context"); - // Pretty print executionContext - string executionContextString = JsonConvert.SerializeObject(context); - string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); - _logger.LogInformation("Execution Context: {prettyExecutionContext}\n", prettyExecutionContext); - - if (context == null) { - return new BadRequestObjectResult("Invalid context"); - } - - PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; - Settings.TrySetSecretKey(ref settings); - Settings.TrySetCloudName(ref settings); + var settings = new PlayFabApiSettings { TitleId = context.TitleAuthenticationContext.Id, }; + Settings.TrySetSecretKey(settings); + Settings.TrySetCloudName(settings); - MakePlayerMoveRequest moveRequest = context.FunctionArgument.ToObject(); + var moveRequest = context.FunctionArgument.ToObject(); // Attempt to load the player's game state - TicTacToeState state = await GameStateUtil.GetCurrentGameState(moveRequest.PlayFabId, settings); - TicTacToeMove move = moveRequest.Move; + var state = await GameStateUtil.GetCurrentGameState(moveRequest.PlayFabId, settings); + var move = moveRequest.Move; int oneDimMoveIndex = move.row * 3 + move.col; @@ -66,5 +42,7 @@ public async Task Run( // Move attempt was invalid return new OkObjectResult(new MakePlayerMoveResult { Valid = false }); } + + private readonly ILogger _logger = loggerFactory.CreateLogger(); } } diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/ResetGameState.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/ResetGameState.cs index a4898d3e..f928ce51 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/ResetGameState.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/ResetGameState.cs @@ -4,56 +4,46 @@ using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using PlayFab; -using PlayFab.Samples; using PlayFab.TicTacToeDemo.Models; using PlayFab.TicTacToeDemo.Util; -using FunctionContext = PlayFab.Plugins.CloudScript.FunctionContext; - -namespace TicTacToeFunctions.Functions { - public class ResetGameState { - private readonly ILogger _logger; - - public ResetGameState(ILoggerFactory loggerFactory) { - _logger = loggerFactory.CreateLogger(); - } +namespace TicTacToeFunctions.Functions +{ + public class ResetGameState + { [Function("ResetGameState")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Function, "post")] - HttpRequestData requestData, - FunctionContext executionContext) { - - string zRequest = await requestData.ReadAsStringAsync() ?? string.Empty; - FunctionExecutionContext? context = - JsonConvert.DeserializeObject>(zRequest); - - // Pretty print requestData - string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); - _logger.LogInformation("Request Data: {prettyRequestBody}\n", prettyRequestBody); - - // Pretty print executionContext - string executionContextString = JsonConvert.SerializeObject(context); - string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); - _logger.LogInformation("Execution Context: {prettyExecutionContext}\n", prettyExecutionContext); - - if (context == null) { - return new BadRequestObjectResult("Invalid context"); - } - - PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; - Settings.TrySetSecretKey(ref settings); - Settings.TrySetCloudName(ref settings); + [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req, + FunctionContext executionContext) + { + var context = await PlayFabFunctionHelper.GetContext(_logger, req); + if (context is null) return new BadRequestObjectResult("Invalid context"); + + var settings = new PlayFabApiSettings { TitleId = context.TitleAuthenticationContext.Id, }; + Settings.TrySetSecretKey(settings); + Settings.TrySetCloudName(settings); string playFabId = context.CallerEntityProfile.Lineage.MasterPlayerAccountId; - TicTacToeState newCurrentGameState = new() { Data = new int[9] }; + var newCurrentGameState = new TicTacToeState + { + Data = new int[9] + }; - await GameStateUtil.UpdateCurrentGameState(newCurrentGameState, playFabId, settings); + await GameStateUtil.UpdateCurrentGameState( + newCurrentGameState, + playFabId, + settings); return new OkResult(); } + + private readonly ILogger _logger; + + public ResetGameState(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); + } } } diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/WinChecker.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/WinChecker.cs index b952a3b1..115838dc 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/WinChecker.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/WinChecker.cs @@ -4,72 +4,47 @@ using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using PlayFab; -using PlayFab.Samples; using PlayFab.TicTacToeDemo.Models; using PlayFab.TicTacToeDemo.Util; -using FunctionContext = PlayFab.Plugins.CloudScript.FunctionContext; namespace TicTacToeFunctions.Functions { public class WinChecker { - private readonly ILogger _logger; - - public WinChecker(ILoggerFactory loggerFactory) { - _logger = loggerFactory.CreateLogger(); - } - [Function("WinCheck")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Function, "post")] - HttpRequestData requestData, - FunctionContext executionContext) { + [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestData req, + FunctionContext executionContext) + { + var context = await PlayFabFunctionHelper.GetContext(_logger, req); + if (context is null) return new BadRequestObjectResult("Invalid context"); + + // TODO: check if can be done with currentplayerid directly from context + // Extract the Player's PlayFabId from the request + string playFabId = context.FunctionArgument.ToObject().PlayFabId; - string zRequest = await requestData.ReadAsStringAsync() ?? string.Empty; - PlayerPlayStreamFunctionExecutionContext? context = - JsonConvert.DeserializeObject>(zRequest); - - // Pretty print requestData - string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); - _logger.LogInformation("Request Data: {prettyRequestBody}\n", prettyRequestBody); - - // Pretty print executionContext - string executionContextString = JsonConvert.SerializeObject(context); - string prettyExecutionContext = JObject.Parse(executionContextString).ToString(Formatting.Indented); - _logger.LogInformation("Execution Context: {prettyExecutionContext}\n", prettyExecutionContext); - - if (context == null) { - return new BadRequestObjectResult("Invalid context"); - } - - PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; - Settings.TrySetSecretKey(ref settings); - Settings.TrySetCloudName(ref settings); - - PlayFabIdRequest playFabIdRequest = context.FunctionArgument.ToObject(); - // Grab the current player's game state - TicTacToeState state = await GameStateUtil.GetCurrentGameState(playFabIdRequest.PlayFabId, settings); + PlayFabApiSettings settings = new() { TitleId = context.TitleAuthenticationContext.Id, }; + Settings.TrySetSecretKey(settings); + Settings.TrySetCloudName(settings); - WinCheckResult winCheckResult = WinCheckUtil.Check(state); - - if (winCheckResult.Winner == GameWinnerType.NONE) { - return new OkObjectResult(winCheckResult); - } + var state = await GameStateUtil.GetCurrentGameState(playFabId, settings); - // Update the leaderboard accordingly - await LeaderboardUtils.UpdateLeaderboard(playFabIdRequest.PlayFabId, winCheckResult.Winner); + // Determine the winner (if any) + var winResult = WinCheckUtil.Check(state); - // Store the game history - await GameStateUtil.AddGameStateHistory(state, playFabIdRequest.PlayFabId, settings); + // Update the leaderboard accordingly + await LeaderboardUtils.UpdateLeaderboard(playFabId, winResult.Winner); + + return new OkObjectResult(winResult); + } - // Clear the current game state - await GameStateUtil.UpdateCurrentGameState(new TicTacToeState(), playFabIdRequest.PlayFabId, settings); + private readonly ILogger _logger; - return new OkObjectResult(winCheckResult); + public WinChecker(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); } } } diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Settings.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Settings.cs index c3773dfe..c57ae332 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Settings.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Settings.cs @@ -1,12 +1,14 @@ // Copyright (C) Microsoft Corporation. All rights reserved. +using System; + namespace PlayFab.TicTacToeDemo.Util { public static class Settings { - public static void TrySetSecretKey(ref PlayFabApiSettings settings) + public static void TrySetSecretKey(PlayFabApiSettings settings) { - string? secretKey = Environment.GetEnvironmentVariable(Constants.PLAYFAB_DEV_SECRET_KEY, EnvironmentVariableTarget.Process); + var secretKey = Environment.GetEnvironmentVariable(Constants.PLAYFAB_DEV_SECRET_KEY, EnvironmentVariableTarget.Process); if (!string.IsNullOrEmpty(secretKey)) { @@ -14,9 +16,9 @@ public static void TrySetSecretKey(ref PlayFabApiSettings settings) } } - public static void TrySetCloudName(ref PlayFabApiSettings settings) + public static void TrySetCloudName(PlayFabApiSettings settings) { - string? cloud = Environment.GetEnvironmentVariable(Constants.PLAYFAB_CLOUD_NAME, EnvironmentVariableTarget.Process); + var cloud = Environment.GetEnvironmentVariable(Constants.PLAYFAB_CLOUD_NAME, EnvironmentVariableTarget.Process); if (!string.IsNullOrEmpty(cloud)) { diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Util.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Util.cs index 9aaee7c9..a3f416ca 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Util.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/Util.cs @@ -1,7 +1,34 @@ // Copyright (C) Microsoft Corporation. All rights reserved. +using Microsoft.Azure.Functions.Worker.Http; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PlayFab.Samples; + namespace PlayFab.TicTacToeDemo.Util { + public static class PlayFabFunctionHelper + { + internal static async Task?> GetContext(ILogger logger, HttpRequestData req) + { + string zRequest = await req.ReadAsStringAsync() ?? string.Empty; + var context = JsonConvert.DeserializeObject>(zRequest); + if (context is null) return null; + + // Pretty print requestData + string prettyRequestBody = JObject.Parse(zRequest).ToString(Formatting.Indented); + logger.LogInformation("Request Data: {prettyRequestBody}\n", prettyRequestBody); + + // Pretty print FunctionContext + string zContext = JsonConvert.SerializeObject(context); + string prettyExecutionContext = JObject.Parse(zContext).ToString(Formatting.Indented); + logger.LogInformation("Execution Context: {prettyExecutionContext}\n", prettyExecutionContext); + + return context; + } + } + public class ArrayUtil { public static T[,] Make2DArray(T[] input, int height, int width) diff --git a/Samples/Unity/TicTacToe/Assets/PlayFabSDK.meta b/Samples/Unity/TicTacToe/Assets/PlayFabSDK.meta old mode 100644 new mode 100755 index b739181a..0f7c1908 --- a/Samples/Unity/TicTacToe/Assets/PlayFabSDK.meta +++ b/Samples/Unity/TicTacToe/Assets/PlayFabSDK.meta @@ -1,8 +1,9 @@ fileFormatVersion: 2 -guid: 6b12ba363ed527a4490f01b752e337e1 +guid: e53d5e839d5caa945b9b859abe15689b folderAsset: yes +timeCreated: 1558474635 +licenseType: Pro DefaultImporter: - externalObjects: {} userData: assetBundleName: assetBundleVariant: diff --git a/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/AIMoveHandler.cs b/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/AIMoveHandler.cs index a6fa81a2..4c0bb75d 100644 --- a/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/AIMoveHandler.cs +++ b/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/AIMoveHandler.cs @@ -18,15 +18,17 @@ public override IEnumerator ExecuteRequest() { var request = new ExecuteFunctionRequest { + Entity = new EntityKey + { + Id = PlayFabSettings.staticPlayer.EntityId, + Type = PlayFabSettings.staticPlayer.EntityType, + }, FunctionName = Constants.AI_MOVE_FUNCTION_NAME, FunctionParameter = new PlayFabIdRequest { PlayFabId = Player.PlayFabId }, - AuthenticationContext = new PlayFabAuthenticationContext - { - EntityToken = Player.EntityToken - } + GeneratePlayStreamEvent = true }; PlayFabCloudScriptAPI.ExecuteFunction(request, diff --git a/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/PlayerMoveHandler.cs b/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/PlayerMoveHandler.cs index 15ad871a..dcc710e4 100644 --- a/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/PlayerMoveHandler.cs +++ b/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/PlayerMoveHandler.cs @@ -23,16 +23,18 @@ public override IEnumerator ExecuteRequest() // Create the move request var request = new ExecuteFunctionRequest { + Entity = new EntityKey + { + Id = PlayFabSettings.staticPlayer.EntityId, + Type = PlayFabSettings.staticPlayer.EntityType, + }, FunctionName = Constants.PLAYER_MOVE_FUNCTION_NAME, FunctionParameter = new MakePlayerMoveRequest { PlayFabId = Player.PlayFabId, Move = MoveToExecute }, - AuthenticationContext = new PlayFabAuthenticationContext - { - EntityToken = Player.EntityToken - } + GeneratePlayStreamEvent = true }; // Execute the move request diff --git a/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/ResetGameStateHandler.cs b/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/ResetGameStateHandler.cs index 14929593..342e9c28 100644 --- a/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/ResetGameStateHandler.cs +++ b/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/ResetGameStateHandler.cs @@ -16,15 +16,17 @@ public override IEnumerator ExecuteRequest() // Create the reset request var request = new ExecuteFunctionRequest { + Entity = new EntityKey + { + Id = PlayFabSettings.staticPlayer.EntityId, + Type = PlayFabSettings.staticPlayer.EntityType, + }, FunctionName = Constants.RESET_GAME_STATE_FUNCTION_NAME, FunctionParameter = new PlayFabIdRequest { PlayFabId = Player.PlayFabId }, - AuthenticationContext = new PlayFabAuthenticationContext - { - EntityToken = Player.EntityToken - } + GeneratePlayStreamEvent = true }; // Execute the reset request diff --git a/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/WinCheckHandler.cs b/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/WinCheckHandler.cs index 841f9d05..8561b972 100644 --- a/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/WinCheckHandler.cs +++ b/Samples/Unity/TicTacToe/Assets/Scripts/Handlers/WinCheckHandler.cs @@ -18,15 +18,17 @@ public override IEnumerator ExecuteRequest() { var request = new ExecuteFunctionRequest { + Entity = new EntityKey + { + Id = PlayFabSettings.staticPlayer.EntityId, + Type = PlayFabSettings.staticPlayer.EntityType, + }, FunctionName = Constants.WIN_CHECK_FUNCTION_NAME, FunctionParameter = new PlayFabIdRequest { PlayFabId = Player.PlayFabId }, - AuthenticationContext = new PlayFabAuthenticationContext - { - EntityToken = Player.EntityToken - } + GeneratePlayStreamEvent = true }; PlayFabCloudScriptAPI.ExecuteFunction(request, diff --git a/Samples/Unity/TicTacToe/Assets/Scripts/Settings.cs b/Samples/Unity/TicTacToe/Assets/Scripts/Settings.cs index 300da295..9528d3d0 100644 --- a/Samples/Unity/TicTacToe/Assets/Scripts/Settings.cs +++ b/Samples/Unity/TicTacToe/Assets/Scripts/Settings.cs @@ -7,8 +7,6 @@ public static class Settings public static void UpdateSettings() { PlayFabSettings.TitleId = Constants.TITLE_ID; - PlayFabSettings.VerticalName = Constants.CLOUD_NAME; - PlayFabSettings.CompressApiData = Constants.COMPRESS_API_DATA; } } } diff --git a/Samples/Unity/TicTacToe/Packages/manifest.json b/Samples/Unity/TicTacToe/Packages/manifest.json index 8151e8cb..5948c441 100644 --- a/Samples/Unity/TicTacToe/Packages/manifest.json +++ b/Samples/Unity/TicTacToe/Packages/manifest.json @@ -1,14 +1,12 @@ { "dependencies": { - "com.unity.ads": "2.0.8", - "com.unity.analytics": "3.3.2", - "com.unity.collab-proxy": "1.2.16", + "com.unity.analytics": "3.6.12", + "com.unity.ide.rider": "3.0.28", "com.unity.multiplayer-hlapi": "1.0.2", - "com.unity.package-manager-ui": "2.1.2", - "com.unity.purchasing": "2.0.6", - "com.unity.textmeshpro": "2.0.1", - "com.unity.timeline": "1.0.0", - "com.unity.xr.legacyinputhelpers": "2.0.2", + "com.unity.ugui": "1.0.0", + "com.unity.textmeshpro": "3.0.9", + "com.unity.timeline": "1.8.7", + "com.unity.xr.legacyinputhelpers": "2.1.10", "com.unity.modules.ai": "1.0.0", "com.unity.modules.animation": "1.0.0", "com.unity.modules.assetbundle": "1.0.0", diff --git a/Samples/Unity/TicTacToe/ProjectSettings/ProjectSettings.asset b/Samples/Unity/TicTacToe/ProjectSettings/ProjectSettings.asset index 52a575c3..2befe7df 100644 --- a/Samples/Unity/TicTacToe/ProjectSettings/ProjectSettings.asset +++ b/Samples/Unity/TicTacToe/ProjectSettings/ProjectSettings.asset @@ -3,7 +3,7 @@ --- !u!129 &1 PlayerSettings: m_ObjectHideFlags: 0 - serializedVersion: 15 + serializedVersion: 23 productGUID: 6eed28ec462b3954380ef81aaff8c591 AndroidProfiler: 0 AndroidFilterTouchesWhenObscured: 0 @@ -49,11 +49,12 @@ PlayerSettings: m_StereoRenderingPath: 0 m_ActiveColorSpace: 0 m_MTRendering: 1 + mipStripping: 0 + numberOfMipsStripped: 0 m_StackTraceTypes: 010000000100000001000000010000000100000001000000 iosShowActivityIndicatorOnLoading: -1 androidShowActivityIndicatorOnLoading: -1 - iosAppInBackgroundBehavior: 0 - displayResolutionDialog: 1 + iosUseCustomAppBackgroundBehavior: 0 iosAllowHTTPDownload: 1 allowedAutorotateToPortrait: 1 allowedAutorotateToPortraitUpsideDown: 1 @@ -65,7 +66,14 @@ PlayerSettings: disableDepthAndStencilBuffers: 0 androidStartInFullscreen: 1 androidRenderOutsideSafeArea: 0 + androidUseSwappy: 0 androidBlitType: 0 + androidResizableWindow: 0 + androidDefaultWindowWidth: 1920 + androidDefaultWindowHeight: 1080 + androidMinimumWindowWidth: 400 + androidMinimumWindowHeight: 300 + androidFullscreenMode: 1 defaultIsNativeResolution: 1 macRetinaSupport: 1 runInBackground: 1 @@ -79,11 +87,11 @@ PlayerSettings: usePlayerLog: 1 bakeCollisionMeshes: 0 forceSingleInstance: 0 + useFlipModelSwapchain: 1 resizableWindow: 0 useMacAppStoreValidation: 0 macAppStoreCategory: public.app-category.games gpuSkinning: 1 - graphicsJobs: 0 xboxPIXTextureCapture: 0 xboxEnableAvatar: 0 xboxEnableKinect: 0 @@ -91,7 +99,6 @@ PlayerSettings: xboxEnableFitness: 0 visibleInBackground: 1 allowFullscreenSwitch: 1 - graphicsJobMode: 0 fullscreenMode: 1 xboxSpeechDB: 0 xboxEnableHeadOrientation: 0 @@ -104,6 +111,7 @@ PlayerSettings: xboxOneMonoLoggingLevel: 0 xboxOneLoggingLevel: 1 xboxOneDisableEsram: 0 + xboxOneEnableTypeOptimization: 0 xboxOnePresentImmediateThreshold: 0 switchQueueCommandMemory: 1048576 switchQueueControlMemory: 16384 @@ -111,7 +119,15 @@ PlayerSettings: switchNVNShaderPoolsGranularity: 33554432 switchNVNDefaultPoolsGranularity: 16777216 switchNVNOtherPoolsGranularity: 16777216 + switchNVNMaxPublicTextureIDCount: 0 + switchNVNMaxPublicSamplerIDCount: 0 + stadiaPresentMode: 0 + stadiaTargetFramerate: 0 + vulkanNumSwapchainBuffers: 3 vulkanEnableSetSRGBWrite: 0 + vulkanEnablePreTransform: 0 + vulkanEnableLateAcquireNextImage: 0 + vulkanEnableCommandBufferRecycling: 1 m_SupportedAspectRatios: 4:3: 1 5:4: 1 @@ -125,37 +141,28 @@ PlayerSettings: m_HolographicPauseOnTrackingLoss: 1 xboxOneDisableKinectGpuReservation: 0 xboxOneEnable7thCore: 0 - isWsaHolographicRemotingEnabled: 0 vrSettings: - cardboard: - depthFormat: 0 - enableTransitionView: 0 - daydream: - depthFormat: 0 - useSustainedPerformanceMode: 0 - enableVideoLayer: 0 - useProtectedVideoMemory: 0 - minimumSupportedHeadTracking: 0 - maximumSupportedHeadTracking: 1 - hololens: - depthFormat: 1 - depthBufferSharingEnabled: 0 - oculus: - sharedDepthBuffer: 1 - dashSupport: 1 enable360StereoCapture: 0 - protectGraphicsMemory: 0 + isWsaHolographicRemotingEnabled: 0 enableFrameTimingStats: 0 + enableOpenGLProfilerGPURecorders: 1 useHDRDisplay: 0 + D3DHDRBitDepth: 0 m_ColorGamuts: 00000000 targetPixelDensity: 30 resolutionScalingMode: 0 + resetResolutionOnWindowResize: 0 androidSupportedAspectRatio: 1 androidMaxAspectRatio: 2.1 - applicationIdentifier: {} - buildNumber: {} + applicationIdentifier: + Standalone: com.DefaultCompany.Tic-Tac-Toe + buildNumber: + Standalone: 0 + iPhone: 0 + tvOS: 0 + overrideDefaultApplicationIdentifier: 0 AndroidBundleVersionCode: 1 - AndroidMinSdkVersion: 16 + AndroidMinSdkVersion: 22 AndroidTargetSdkVersion: 0 AndroidPreferredInstallLocation: 1 aotOptions: @@ -170,28 +177,16 @@ PlayerSettings: StripUnusedMeshComponents: 1 VertexChannelCompressionMask: 4054 iPhoneSdkVersion: 988 - iOSTargetOSVersionString: 9.0 + iOSTargetOSVersionString: 11.0 tvOSSdkVersion: 0 tvOSRequireExtendedGameController: 0 - tvOSTargetOSVersionString: 9.0 + tvOSTargetOSVersionString: 11.0 uIPrerenderedIcon: 0 uIRequiresPersistentWiFi: 0 uIRequiresFullScreen: 1 uIStatusBarHidden: 1 uIExitOnSuspend: 0 uIStatusBarStyle: 0 - iPhoneSplashScreen: {fileID: 0} - iPhoneHighResSplashScreen: {fileID: 0} - iPhoneTallHighResSplashScreen: {fileID: 0} - iPhone47inSplashScreen: {fileID: 0} - iPhone55inPortraitSplashScreen: {fileID: 0} - iPhone55inLandscapeSplashScreen: {fileID: 0} - iPhone58inPortraitSplashScreen: {fileID: 0} - iPhone58inLandscapeSplashScreen: {fileID: 0} - iPadPortraitSplashScreen: {fileID: 0} - iPadHighResPortraitSplashScreen: {fileID: 0} - iPadLandscapeSplashScreen: {fileID: 0} - iPadHighResLandscapeSplashScreen: {fileID: 0} appleTVSplashScreen: {fileID: 0} appleTVSplashScreen2x: {fileID: 0} tvOSSmallIconLayers: [] @@ -219,15 +214,17 @@ PlayerSettings: iOSLaunchScreeniPadFillPct: 100 iOSLaunchScreeniPadSize: 100 iOSLaunchScreeniPadCustomXibPath: - iOSUseLaunchScreenStoryboard: 0 iOSLaunchScreenCustomStoryboardPath: + iOSLaunchScreeniPadCustomStoryboardPath: iOSDeviceRequirements: [] iOSURLSchemes: [] + macOSURLSchemes: [] iOSBackgroundModes: 0 iOSMetalForceHardShadows: 0 metalEditorSupport: 1 metalAPIValidation: 1 iOSRenderExtraFrameOnPause: 0 + iosCopyPluginsCodeInsteadOfSymlink: 0 appleDeveloperTeamID: iOSManualSigningProvisioningProfileID: tvOSManualSigningProvisioningProfileID: @@ -235,14 +232,24 @@ PlayerSettings: tvOSManualSigningProvisioningProfileType: 0 appleEnableAutomaticSigning: 0 iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 appleEnableProMotion: 0 + shaderPrecisionModel: 0 clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea templatePackageId: com.unity.template.3d@1.0.4 templateDefaultScene: Assets/Scenes/SampleScene.unity + useCustomMainManifest: 0 + useCustomLauncherManifest: 0 + useCustomMainGradleTemplate: 0 + useCustomLauncherGradleManifest: 0 + useCustomBaseGradleTemplate: 0 + useCustomGradlePropertiesTemplate: 0 + useCustomProguardFile: 0 AndroidTargetArchitectures: 5 + AndroidTargetDevices: 0 AndroidSplashScreenScale: 0 androidSplashScreen: {fileID: 0} - AndroidKeystoreName: + AndroidKeystoreName: '{inproject}: ' AndroidKeyaliasName: AndroidBuildApkPerCpuArchitecture: 0 AndroidTVCompatibility: 1 @@ -250,14 +257,117 @@ PlayerSettings: AndroidEnableTango: 0 androidEnableBanner: 1 androidUseLowAccuracyLocation: 0 + androidUseCustomKeystore: 0 m_AndroidBanners: - width: 320 height: 180 banner: {fileID: 0} androidGamepadSupportLevel: 0 - resolutionDialogBanner: {fileID: 0} + chromeosInputEmulation: 1 + AndroidMinifyWithR8: 0 + AndroidMinifyRelease: 0 + AndroidMinifyDebug: 0 + AndroidValidateAppBundleSize: 1 + AndroidAppBundleSizeToValidate: 150 m_BuildTargetIcons: [] - m_BuildTargetPlatformIcons: [] + m_BuildTargetPlatformIcons: + - m_BuildTarget: iPhone + m_Icons: + - m_Textures: [] + m_Width: 180 + m_Height: 180 + m_Kind: 0 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 120 + m_Height: 120 + m_Kind: 0 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 167 + m_Height: 167 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 152 + m_Height: 152 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 76 + m_Height: 76 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 120 + m_Height: 120 + m_Kind: 3 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 80 + m_Height: 80 + m_Kind: 3 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 80 + m_Height: 80 + m_Kind: 3 + m_SubKind: iPad + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 3 + m_SubKind: iPad + - m_Textures: [] + m_Width: 87 + m_Height: 87 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 58 + m_Height: 58 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 29 + m_Height: 29 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 58 + m_Height: 58 + m_Kind: 1 + m_SubKind: iPad + - m_Textures: [] + m_Width: 29 + m_Height: 29 + m_Kind: 1 + m_SubKind: iPad + - m_Textures: [] + m_Width: 60 + m_Height: 60 + m_Kind: 2 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 2 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 2 + m_SubKind: iPad + - m_Textures: [] + m_Width: 20 + m_Height: 20 + m_Kind: 2 + m_SubKind: iPad + - m_Textures: [] + m_Width: 1024 + m_Height: 1024 + m_Kind: 4 + m_SubKind: App Store m_BuildTargetBatching: - m_BuildTarget: Standalone m_StaticBatching: 1 @@ -274,16 +384,58 @@ PlayerSettings: - m_BuildTarget: WebGL m_StaticBatching: 0 m_DynamicBatching: 0 + m_BuildTargetGraphicsJobs: + - m_BuildTarget: WindowsStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: MacStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: LinuxStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: AndroidPlayer + m_GraphicsJobs: 0 + - m_BuildTarget: iOSSupport + m_GraphicsJobs: 0 + - m_BuildTarget: PS4Player + m_GraphicsJobs: 0 + - m_BuildTarget: PS5Player + m_GraphicsJobs: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobs: 0 + - m_BuildTarget: GameCoreXboxOneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: GameCoreScarlettSupport + m_GraphicsJobs: 0 + - m_BuildTarget: Switch + m_GraphicsJobs: 0 + - m_BuildTarget: WebGLSupport + m_GraphicsJobs: 0 + - m_BuildTarget: MetroSupport + m_GraphicsJobs: 0 + - m_BuildTarget: AppleTVSupport + m_GraphicsJobs: 0 + - m_BuildTarget: BJMSupport + m_GraphicsJobs: 0 + - m_BuildTarget: LuminSupport + m_GraphicsJobs: 0 + - m_BuildTarget: CloudRendering + m_GraphicsJobs: 0 + - m_BuildTarget: EmbeddedLinux + m_GraphicsJobs: 0 + m_BuildTargetGraphicsJobMode: + - m_BuildTarget: PS4Player + m_GraphicsJobMode: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobMode: 0 m_BuildTargetGraphicsAPIs: - m_BuildTarget: AndroidPlayer m_APIs: 0b00000008000000 - m_Automatic: 1 + m_Automatic: 0 - m_BuildTarget: iOSSupport m_APIs: 10000000 m_Automatic: 1 - m_BuildTarget: AppleTVSupport m_APIs: 10000000 - m_Automatic: 0 + m_Automatic: 1 - m_BuildTarget: WebGLSupport m_APIs: 0b000000 m_Automatic: 1 @@ -293,9 +445,9 @@ PlayerSettings: m_Devices: - Oculus - OpenVR - m_BuildTargetEnableVuforiaSettings: [] openGLRequireES31: 0 openGLRequireES31AEP: 0 + openGLRequireES32: 0 m_TemplateCustomTags: {} mobileMTRendering: Android: 1 @@ -303,6 +455,8 @@ PlayerSettings: tvOS: 1 m_BuildTargetGroupLightmapEncodingQuality: [] m_BuildTargetGroupLightmapSettings: [] + m_BuildTargetNormalMapEncoding: [] + m_BuildTargetDefaultTextureCompressionFormat: [] playModeTestRunnerEnabled: 0 runPlayModeTestAsEditModeTest: 0 actionOnDotNetUnhandledException: 1 @@ -312,12 +466,16 @@ PlayerSettings: cameraUsageDescription: locationUsageDescription: microphoneUsageDescription: + bluetoothUsageDescription: + switchNMETAOverride: switchNetLibKey: switchSocketMemoryPoolSize: 6144 switchSocketAllocatorPoolSize: 128 switchSocketConcurrencyLimit: 14 switchScreenResolutionBehavior: 2 switchUseCPUProfiler: 0 + switchUseGOLDLinker: 0 + switchLTOSetting: 0 switchApplicationID: 0x01004b9000490000 switchNSODependencies: switchTitleNames_0: @@ -335,6 +493,7 @@ PlayerSettings: switchTitleNames_12: switchTitleNames_13: switchTitleNames_14: + switchTitleNames_15: switchPublisherNames_0: switchPublisherNames_1: switchPublisherNames_2: @@ -350,6 +509,7 @@ PlayerSettings: switchPublisherNames_12: switchPublisherNames_13: switchPublisherNames_14: + switchPublisherNames_15: switchIcons_0: {fileID: 0} switchIcons_1: {fileID: 0} switchIcons_2: {fileID: 0} @@ -365,6 +525,7 @@ PlayerSettings: switchIcons_12: {fileID: 0} switchIcons_13: {fileID: 0} switchIcons_14: {fileID: 0} + switchIcons_15: {fileID: 0} switchSmallIcons_0: {fileID: 0} switchSmallIcons_1: {fileID: 0} switchSmallIcons_2: {fileID: 0} @@ -380,6 +541,7 @@ PlayerSettings: switchSmallIcons_12: {fileID: 0} switchSmallIcons_13: {fileID: 0} switchSmallIcons_14: {fileID: 0} + switchSmallIcons_15: {fileID: 0} switchManualHTML: switchAccessibleURLs: switchLegalInformation: @@ -411,6 +573,7 @@ PlayerSettings: switchRatingsInt_9: 0 switchRatingsInt_10: 0 switchRatingsInt_11: 0 + switchRatingsInt_12: 0 switchLocalCommunicationIds_0: switchLocalCommunicationIds_1: switchLocalCommunicationIds_2: @@ -441,6 +604,11 @@ PlayerSettings: switchSocketInitializeEnabled: 1 switchNetworkInterfaceManagerInitializeEnabled: 1 switchPlayerConnectionEnabled: 1 + switchUseNewStyleFilepaths: 0 + switchUseMicroSleepForYield: 1 + switchEnableRamDiskSupport: 0 + switchMicroSleepForYieldTime: 25 + switchRamDiskSpaceSize: 12 ps4NPAgeRating: 12 ps4NPTitleSecret: ps4NPTrophyPackPath: @@ -467,6 +635,7 @@ PlayerSettings: ps4ShareFilePath: ps4ShareOverlayImagePath: ps4PrivacyGuardImagePath: + ps4ExtraSceSysFile: ps4NPtitleDatPath: ps4RemotePlayKeyAssignment: -1 ps4RemotePlayKeyMappingDir: @@ -479,6 +648,7 @@ PlayerSettings: ps4DownloadDataSize: 0 ps4GarlicHeapSize: 2048 ps4ProGarlicHeapSize: 2560 + playerPrefsMaxSize: 32768 ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ ps4pnSessions: 1 ps4pnPresence: 1 @@ -491,6 +661,7 @@ PlayerSettings: ps4UseResolutionFallback: 0 ps4ReprojectionSupport: 0 ps4UseAudio3dBackend: 0 + ps4UseLowGarlicFragmentationMode: 1 ps4SocialScreenEnabled: 0 ps4ScriptOptimizationLevel: 0 ps4Audio3dVirtualSpeakerCount: 14 @@ -507,11 +678,16 @@ PlayerSettings: ps4disableAutoHideSplash: 0 ps4videoRecordingFeaturesUsed: 0 ps4contentSearchFeaturesUsed: 0 + ps4CompatibilityPS5: 0 + ps4AllowPS5Detection: 0 + ps4GPU800MHz: 1 ps4attribEyeToEyeDistanceSettingVR: 0 ps4IncludedModules: [] + ps4attribVROutputEnabled: 0 monoEnv: splashScreenBackgroundSourceLandscape: {fileID: 0} splashScreenBackgroundSourcePortrait: {fileID: 0} + blurSplashScreenBackground: 1 spritePackerPolicy: webGLMemorySize: 256 webGLExceptionSupport: 1 @@ -524,17 +700,26 @@ PlayerSettings: webGLAnalyzeBuildSize: 0 webGLUseEmbeddedResources: 0 webGLCompressionFormat: 1 + webGLWasmArithmeticExceptions: 0 webGLLinkerTarget: 1 webGLThreadsSupport: 0 + webGLDecompressionFallback: 0 scriptingDefineSymbols: {} + additionalCompilerArguments: {} platformArchitecture: {} scriptingBackend: {} il2cppCompilerConfiguration: {} managedStrippingLevel: {} incrementalIl2cppBuild: {} + suppressCommonWarnings: 1 allowUnsafeCode: 0 + useDeterministicCompilation: 0 + enableRoslynAnalyzers: 1 additionalIl2CppArgs: scriptingRuntimeVersion: 1 + gcIncremental: 1 + assemblyVersionValidation: 1 + gcWBarrierValidation: 0 apiCompatibilityLevelPerPlatform: {} m_RenderingPath: 1 m_MobileRenderingPath: 1 @@ -565,7 +750,7 @@ PlayerSettings: metroFTAName: metroFTAFileTypes: [] metroProtocolName: - metroCompilationOverrides: 1 + vcxProjDefaultLanguage: XboxOneProductId: XboxOneUpdateKey: XboxOneSandboxId: @@ -584,18 +769,16 @@ PlayerSettings: XboxOneCapability: [] XboxOneGameRating: {} XboxOneIsContentPackage: 0 + XboxOneEnhancedXboxCompatibilityMode: 0 XboxOneEnableGPUVariability: 0 XboxOneSockets: {} XboxOneSplashScreen: {fileID: 0} XboxOneAllowedProductIds: [] XboxOnePersistentLocalStorageSize: 0 XboxOneXTitleMemory: 8 - xboxOneScriptCompiler: 0 XboxOneOverrideIdentityName: - vrEditorSettings: - daydream: - daydreamIconForeground: {fileID: 0} - daydreamIconBackground: {fileID: 0} + XboxOneOverrideIdentityPublisher: + vrEditorSettings: {} cloudServicesEnabled: UNet: 1 luminIcon: @@ -604,24 +787,20 @@ PlayerSettings: m_PortalFolderPath: luminCert: m_CertPath: - m_PrivateKeyPath: + m_SignPackage: 1 luminIsChannelApp: 0 luminVersion: m_VersionCode: 1 m_VersionName: - facebookSdkVersion: 7.9.4 - facebookAppId: - facebookCookies: 1 - facebookLogging: 1 - facebookStatus: 1 - facebookXfbml: 0 - facebookFrictionlessRequests: 1 apiCompatibilityLevel: 6 - cloudProjectId: 43bd96bd-0875-4c34-8532-5a5a8bb511d0 + activeInputHandler: 0 + cloudProjectId: bbd4451e-3e6f-45a1-95cb-37881895fdf7 framebufferDepthMemorylessMode: 0 - projectName: Tic-Tac-Toe - organizationId: niadibpo + qualitySettingsNames: [] + projectName: TicTacToe + organizationId: shuffleinc cloudEnabled: 0 - enableNativePlatformBackendsForNewInputSystem: 0 - disableOldInputManagerSupport: 0 legacyClampBlendShapeWeights: 0 + playerDataPath: + forceSRGBBlit: 1 + virtualTexturingSupportEnabled: 0 diff --git a/Samples/Unity/TicTacToe/ProjectSettings/ProjectVersion.txt b/Samples/Unity/TicTacToe/ProjectSettings/ProjectVersion.txt index a5b74926..85465a19 100644 --- a/Samples/Unity/TicTacToe/ProjectSettings/ProjectVersion.txt +++ b/Samples/Unity/TicTacToe/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2019.1.8f1 -m_EditorVersionWithRevision: 2019.1.8f1 (7938dd008a75) +m_EditorVersion: 2021.3.8f1 +m_EditorVersionWithRevision: 2021.3.8f1 (b30333d56e81) From ccbaefbe440f90a2cbbef6ee6dbbe8639b0bb3f5 Mon Sep 17 00:00:00 2001 From: fiddlegiant Date: Sun, 2 Jun 2024 13:28:57 -0700 Subject: [PATCH 4/6] Add route for MakeAIMove so that local/loopback will be able to resolve the function. In the sample the mapping is supplied during the automation mapping on the PlayFab server. --- .../TicTacToeFunctions/Functions/MakeAIMove.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs index f30ee74f..00a13b5a 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Functions/MakeAIMove.cs @@ -12,6 +12,15 @@ namespace TicTacToeFunctions.Functions { public class MakeAIMove(ILoggerFactory loggerFactory) { + [Function("MakeAIMove")] + public async Task Run( + [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] + HttpRequestData req, + FunctionContext executionContext) + { + return await MakeMinMaxAIMove(req, executionContext); + } + [Function("MakeRandomAIMove")] public async Task MakeRandomAIMove( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req, From fa78786785a9a905c0dc9943f56851e3a32fe17c Mon Sep 17 00:00:00 2001 From: fiddlegiant Date: Sun, 2 Jun 2024 13:45:11 -0700 Subject: [PATCH 5/6] Reduce whitespace and other deltas from fork. --- .../TicTacToeFunctions/Util/GameStateUtil.cs | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GameStateUtil.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GameStateUtil.cs index 2e017d5b..78db4e19 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GameStateUtil.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GameStateUtil.cs @@ -10,22 +10,22 @@ public static class GameStateUtil { public static async Task GetCurrentGameState(string playFabId, PlayFabApiSettings apiSettings) { - GetUserDataRequest request = new() - { - PlayFabId = playFabId, - Keys = new List() { Constants.GAME_CURRENT_STATE_KEY } - }; + var request = new GetUserDataRequest() + { + PlayFabId = playFabId, + Keys = new List() { Constants.GAME_CURRENT_STATE_KEY } + }; - PlayFabServerInstanceAPI serverApi = new(apiSettings); + var serverApi = new PlayFabServerInstanceAPI(apiSettings); - PlayFabResult? result = await serverApi.GetUserDataAsync(request); + var result = await serverApi.GetUserDataAsync(request); if (result.Error != null) { throw new Exception($"An error occurred while fetching the current game state: Error: {result.Error.GenerateErrorReport()}"); } - Dictionary? resultData = result.Result.Data; + var resultData = result.Result.Data; // Current state found if (resultData.Count > 0 && resultData.TryGetValue(Constants.GAME_CURRENT_STATE_KEY, out UserDataRecord? currentGameStateRecord)) @@ -35,7 +35,7 @@ public static async Task GetCurrentGameState(string playFabId, P // Current game record does not exist and so must be created else { - TicTacToeState newState = new() { Data = new int[9] }; + var newState = new TicTacToeState { Data = new int[9] }; await UpdateCurrentGameState(newState, playFabId, apiSettings); return newState; } @@ -43,17 +43,17 @@ public static async Task GetCurrentGameState(string playFabId, P public static async Task UpdateCurrentGameState(TicTacToeState state, string entityId, PlayFabApiSettings apiSettings) { - string? serializedNewGameState = PlayFabSimpleJson.SerializeObject(state); + var serializedNewGameState = PlayFabSimpleJson.SerializeObject(state); - UpdateUserDataRequest request = new() - { - PlayFabId = entityId, - Data = new Dictionary() { { Constants.GAME_CURRENT_STATE_KEY, serializedNewGameState} } - }; + var request = new UpdateUserDataRequest() + { + PlayFabId = entityId, + Data = new Dictionary() { { Constants.GAME_CURRENT_STATE_KEY, serializedNewGameState } } + }; - PlayFabServerInstanceAPI serverApi = new(apiSettings); + var serverApi = new PlayFabServerInstanceAPI(apiSettings); - PlayFabResult? result = await serverApi.UpdateUserDataAsync(request); + var result = await serverApi.UpdateUserDataAsync(request); if (result.Error != null) { @@ -63,21 +63,21 @@ public static async Task UpdateCurrentGameState(TicTacToeState state, string ent public static async Task AddGameStateHistory(TicTacToeState gameState, string playFabId, PlayFabApiSettings apiSettings) { - int gamesPlayed = await GameDataUtil.GetGamesPlayed(playFabId, apiSettings); + var gamesPlayed = await GameDataUtil.GetGamesPlayed(playFabId, apiSettings); - string key = $"{Constants.GAME_STATE_KEY}_{gamesPlayed + 1}"; + var key = $"{Constants.GAME_STATE_KEY}_{gamesPlayed + 1}"; - string? serializedGameState = PlayFabSimpleJson.SerializeObject(gameState); + var serializedGameState = PlayFabSimpleJson.SerializeObject(gameState); - UpdateUserDataRequest request = new() - { - PlayFabId = playFabId, - Data = new Dictionary() { { key, serializedGameState } } - }; + var request = new UpdateUserDataRequest() + { + PlayFabId = playFabId, + Data = new Dictionary() { { key, serializedGameState } } + }; - PlayFabServerInstanceAPI serverApi = new(apiSettings); + var serverApi = new PlayFabServerInstanceAPI(apiSettings); - PlayFabResult? result = await serverApi.UpdateUserDataAsync(request); + var result = await serverApi.UpdateUserDataAsync(request); if (result.Error != null) { From 11596b30f3d9f38a11f17c14e5e944c56b382e35 Mon Sep 17 00:00:00 2001 From: fiddlegiant Date: Sun, 2 Jun 2024 13:50:58 -0700 Subject: [PATCH 6/6] Reduce whitespace and other layout deltas --- .../Util/GamesPlayedUtil.cs | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GamesPlayedUtil.cs b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GamesPlayedUtil.cs index e49609e5..b82feb66 100644 --- a/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GamesPlayedUtil.cs +++ b/Samples/CSharp/AzureFunctions/TicTacToeFunctions/Util/GamesPlayedUtil.cs @@ -8,23 +8,24 @@ public static class GameDataUtil { public static async Task GetGamesPlayed(string playFabId, PlayFabApiSettings apiSettings) { - GetUserDataRequest request = new() { - PlayFabId = playFabId, - Keys = new List { Constants.GAMES_PLAYED_KEY } - }; + var request = new GetUserDataRequest + { + PlayFabId = playFabId, + Keys = new List { Constants.GAMES_PLAYED_KEY } + }; - PlayFabServerInstanceAPI serverApi = new(apiSettings); + var serverApi = new PlayFabServerInstanceAPI(apiSettings); - PlayFabResult? result = await serverApi.GetUserDataAsync(request); + var result = await serverApi.GetUserDataAsync(request); if (result.Error != null) { throw new Exception($"An error occured while fetching the number of games played: Error: {result.Error.GenerateErrorReport()}"); } - Dictionary? resultData = result.Result.Data; + var resultData = result.Result.Data; - if (resultData.Count > 0 && resultData.TryGetValue(Constants.GAMES_PLAYED_KEY, out UserDataRecord? gamesPlayedRecord)) + if (resultData.Count > 0 && resultData.TryGetValue(Constants.GAMES_PLAYED_KEY, out var gamesPlayedRecord)) { return int.Parse(gamesPlayedRecord.Value); } @@ -36,14 +37,15 @@ public static async Task GetGamesPlayed(string playFabId, PlayFabApiSetting public static async Task SetGamesPlayed(int gamesPlayed, string playFabId, PlayFabApiSettings apiSettings) { - UpdateUserDataRequest request = new() { - PlayFabId = playFabId, - Data = new Dictionary { { Constants.GAMES_PLAYED_KEY, gamesPlayed.ToString() } } - }; + var request = new UpdateUserDataRequest + { + PlayFabId = playFabId, + Data = new Dictionary { { Constants.GAMES_PLAYED_KEY.ToString(), gamesPlayed.ToString() } } + }; - PlayFabServerInstanceAPI serverApi = new(apiSettings); + var serverApi = new PlayFabServerInstanceAPI(apiSettings); - PlayFabResult? result = await serverApi.UpdateUserDataAsync(request); + var result = await serverApi.UpdateUserDataAsync(request); if (result.Error != null) {