question

Ankur Ranpariya avatar image
Ankur Ranpariya asked

Getting issue while use Azure Function with Prize Table and Leaderboard.

Hi Support Team,

We are facing an issue using the Prize table with Azure function.

Requirement:

We want to give Custom but multiple rewards to player bucket like 1 to x. Our game has multiple buckets for each leaderboard and each bucket has X number of players.

Bucket data is stored in Title Internal data.

In the current implementation, we are an execute Prize table when we reset the Leaderboard. The prize table will execute a cloud script.

Could script has two parameter args (argument set in prize table) and context (will hold information about player master account id and Player position in Leaderboard)

this implementation is working almost fine, but due to a few limitations, we are moving this whole implementation to Azure function.


Azure Function:
In normal Azure function whatever data we pass it will be part of FunctionContext. which we can create via the below code.

/* Create the function execution's context through the request */
var context = await FunctionContext<dynamic>.Create(req);

The above code is workings fine when we try to execute Azure function using Unity PlayFab SDK.

PlayFab SDK for Azure has three types of Context

  1. FunctionContext
  2. FunctionPlayerPlayStreamContext
  3. FunctionTaskContext


The Issue:

As we trying to call Azure function from the Prize table we are facing various issues for all 3 types of Context creation.


1. FunctionContext

When we try to create normal FunctionContext for Azure Function which we are calling via Prize table we are getting some Null reference error.

Log from Azure Function monitor is given below.

Error While Create `FunctionContext` when Execute function from Prize Table
2020-06-11T14:40:39Z   [Information]   Executing 'OnLeaderboardReset' (Reason='This function was programmatically called via the host APIs.', Id=ea3d8669-3217-4cf0-9e98-68ca0bbab790)
2020-06-11T14:40:39Z   [Information]   Json parser received True
2020-06-11T14:40:39Z   [Information]   Creating context
2020-06-11T14:40:40Z   [Error]   Error: System.NullReferenceException: Object reference not set to an instance of an object.
   at PlayFab.Plugins.CloudScript.FunctionContext`1.Create(HttpRequestMessage request)
   at Nukebox.Function.Leaderboard.LeaderboardReset.OnLeaderboardReset(HttpRequestMessage req, ILogger log) in D:\Ankur\Project\Azure\AzureWithPlayFab\AzureFunctions\Feauters\Leaderboard\LeaderboardReset.cs:line 37
2020-06-11T14:40:40Z   [Error]   Executed 'OnLeaderboardReset' (Failed, Id=ea3d8669-3217-4cf0-9e98-68ca0bbab790)

2. FunctionPlayerPlayStreamContext

We also tried to create FunctionPlayerPlayStreamContext to check is it works or not. When we try it we are getting Invalid cast exception for some Login LoginIdentityProvider Provider.

Error Log from the Azure Function monitor provided below.

2020-06-12T04:58:32Z   [Information]   Executing 'OnLeaderboardReset' (Reason='This function was programmatically called via the host APIs.', Id=bbc39445-4cca-4cfe-880c-2c86c3d4bc93)
2020-06-12T04:58:32Z   [Information]   Json parser received True
2020-06-12T04:58:32Z   [Information]   Creating playeStream context
2020-06-12T04:58:32Z   [Error]   Error: System.InvalidCastException: Invalid cast from 'System.String' to 'System.Nullable`1[[PlayFab.ServerModels.LoginIdentityProvider, PlayFabAllSDK, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'.
   at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   at System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at PlayFab.Json.PocoJsonSerializerStrategy.DeserializeObject(Object value, Type type)
   at PlayFab.Json.PocoJsonSerializerStrategy.DeserializeObject(Object value, Type type)
   at PlayFab.Json.PocoJsonSerializerStrategy.DeserializeObject(Object value, Type type)
   at PlayFab.Json.PocoJsonSerializerStrategy.DeserializeObject(Object value, Type type)
   at PlayFab.Json.PocoJsonSerializerStrategy.DeserializeObject(Object value, Type type)
   at PlayFab.Json.PlayFabSimpleJson.DeserializeObject(String json, Type type, IJsonSerializerStrategy jsonSerializerStrategy)
   at PlayFab.Json.PlayFabSimpleJson.DeserializeObject[T](String json)
   at PlayFab.Plugins.CloudScript.FunctionPlayerPlayStreamContext`1.Create(HttpRequestMessage request)
   at Nukebox.Function.Leaderboard.LeaderboardReset.OnLeaderboardReset(HttpRequestMessage req, ILogger log) in D:\Ankur\Project\Azure\AzureWithPlayFab\AzureFunctions\Feauters\Leaderboard\LeaderboardReset.cs:line 43
2020-06-12T04:58:32Z   [Error]   Executed 'OnLeaderboardReset' (Failed, Id=bbc39445-4cca-4cfe-880c-2c86c3d4bc93)

3. FunctionTaskContext

We also tried to use FunctionTask Context, when we trying to use that. The context created successfully, but it's task context it does not have any info which would be passed by Prize table. We have converted FunctionTaskContext into JSON string.

Note: For security reasons, I have replaced DeveloeprSecretKey and Entity token with dummy data. rest of the data in JSON is not modified

Converted JSON string

{"ApiSettings":{"RequestGetParams":{"sdk":"CSharpSDK-1.73.200602"},"ProductionEnvironmentUrl":"playfabapi.com","VerticalName":null,"DeveloperSecretKey":"DEV_Secret_KEY","TitleId":"1XXX6","DisableAdvertising":false,"AdvertisingIdType":null,"AdvertisingIdValue":null},"AuthenticationContext":{"ClientSessionTicket":null,"PlayFabId":null,"EntityToken":"Mnx7ImkiOiIyMDIwLTA2LTEyVDA1OjM0OjAzLjU4NjE2MDNaIiwiaWRwIjoiUGxheUZDKLhYiIsImUiOiIyMDIwLTA2LTEzVDA1OjM0OjAzLjU4NjE2MDNaIiwiaCI6IjFBREUyMEVGMzRCNTkyRTkiLCJzIjoicytCY3hkTDBkeFYxRXRxbU4vNFV1NTlkdUVwdGZaaHk3NDM1MnFnK1pOTDLJLOT0iLCJlYyI6InRpdGxlITU4OTc0RUU3NDZBMTVBQUUvMTgxNDYvIiwiZWkiOiIxODE0NiIsImV0IjoidGl0bGUifQ==","EntityId":null,"EntityType":null},"ScheduledTaskNameId":null,"EventHistory":null,"FunctionArgument":{"world":"9","restaurant":"0"}}
CloudScriptLeaderboards and Statistics
2 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Hernando avatar image Hernando commented ·

Could you provide the code about deserializing the json into context object, so that we can locate the issue or find a solution? Usually, we use following code to do it:

PlayerPlayStreamFunctionExecutionContext<object[]> req =JsonConvert.DeserializeObject<PlayerPlayStreamFunctionExecutionContext<object[]>>(body);
0 Likes 0 ·
Ankur Ranpariya avatar image Ankur Ranpariya Hernando commented ·

Hi Hernando,

Here is the code which converts the request in the context. The simpleJson object is an instance of SimpleJsonInstance Class

public static async Task<IActionResult> OnLeaderboardReset(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req,
            ILogger log)
        {
            IDictionary result;
            IDictionary args;
            try
            {
                /* Create the function execution's context through the request */
                SimpleJsonInstance simpleJson = PlayFabCommonUtility.GetSharedSimpleJson();
                var playStreamContext = await FunctionPlayerPlayStreamContext<dynamic>.Create(req);
                log.LogWarning("playStreamContext: {0}", simpleJson.SerializeObject(playStreamContext));

                return new OkResult();
            }

            catch (Exception ex)
            {
                log.LogError("Error: {0}", ex);
            }
            return new OkObjectResult(result);
        }
    }

Please let me know if you have any questions about our requirements...

0 Likes 0 ·

1 Answer

·
Hernando avatar image
Hernando answered

We recommend that you use CloudScript context model PlayerPlayStreamFunctionExecutionContext to determines the available data model and provides context specific data that is used in your script.

Following code shows how to obtain the information from PlayerPlayStreamFunctionExecutionContext:

[FunctionName("OnLeaderboardReset")]  
public static async Task<object> OnLeaderboardReset( 
    [HttpTrigger(AuthorizationLevel.Function, "post", Route =null)] HttpRequest httpRequest, ILogger log)  
 
{  
 
    string body = await
    httpRequest.ReadAsStringAsync(); 
    PlayerPlayStreamFunctionExecutionContext<object[]> req =
    JsonConvert.DeserializeObject<PlayerPlayStreamFunctionExecutionContext<object[]>>(body);  
 
    return await Task.FromResult(req.FunctionArgument);  
 
}

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Ankur Ranpariya avatar image Ankur Ranpariya commented ·

Hi Hernando,

Thanks for the reply and solution. that solution is worked for me.

The model class is not available in PlayFab Azure SDK v1.73.200602 or PlayFab Cloud Script Plugin v1.53.190627-alpha for Azure.

So I have downloaded the code from this GitHub Sample Project. and it works for me.

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.