question

David Jones avatar image
David Jones asked

Cloudscript help

I've asked this question before, and got an answer but I'm going to try to articulate it better this time. I have a TitleData JSON object with about 20 nested keys. These are the first two out of twenty,

{
  "Settler": {
    "id": 0,
    "rating": 0,
    "ratingTop": 49,
    "nextClass": "Rebellious"
  },
  "Rebellious": {
    "id": 1,
    "rating": 50,
    "ratingTop": 99,
    "nextClass": "Fugative"
  },

}

Each player has a "Rating" statistic which has a rule in automation to call a cloudscript everytime the "Rating" statistic changes. My cloudscript function is below. It is messy... however its been changed a lot, trying to get different results.

handlers.UpdateSocialClass = function (args) {
    //Get current socialclass stored in currentSocialClass readonlydata
    var dataRequest = {
            PlayFabId: currentPlayerId, 
            Keys: ["SocialClass"]
    };
    var currentSocialClass = server.GetUserReadOnlyData(dataRequest);
    //get current rating stored in the var currentRating
    var statsRequest = {
        PlayFabId: currentPlayerId,
        StatisticName: "Rating",
    };
    var currentRating = server.GetPlayerStatistics(statsRequest);
    //Get the title data for SocialClasses, stored in jsonObject
    var getTitleDataRequest = "SocialClasses";
    var getTitleDataResponse = server.GetTitleData(getTitleDataRequest);
    //Access current class within the JSON object
    var yourSocialClassJson = getTitleDataResponse[currentSocialClass];
    //Access ratingtop within the current class jsonObject
    var ratingCap = yourSocialClassJson.ratingTop;
    
    //If they have enough rating level up
    if(currentRating > ratingCap) {
        var newClass = yourSocialClassJson.nextClass;
        //set userdata to new class
        dataPayload["SocialClass"] = newClass;
 
        var result = server.UpdateUserReadOnlyData({
            PlayFabId: currentPlayerId,
            Data: dataPayload
        });
    } else {
        // If they have less than required amount then DownGradeSocialClass


    }
}

In PlayStream it says my error is

"Error": "JavascriptException",
                        "Message": "JavascriptException",
                        "StackTrace": "TypeError: Cannot read property 'ratingTop' of undefined\n    at handlers.UpdateSocialClass (95E3-main.js:89:41)"

I know this is most likely an easy fix. I assume my syntax is wrong when I get the title data or when I try to access the different values in title data. Debugging on cloudscript is a little difficult for me. Is there an easier way rather than playstream?

CloudScriptPlayStream
10 |1200

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

v-humcin avatar image
v-humcin answered

The title data returned in the "GetTitleDataResult" is stored in an object called "Data" so based on your code the call should look something like this:

var yourSocialClassJson = getTitleDataResponse.Data[currentSocialClass];

If this does not fully fix the issue just let us know!

8 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.

David Jones avatar image David Jones commented ·

I changed the syntax the above line ^ and I still get the same error, Cannot read property 'ratingtop' of undefined.

0 Likes 0 ·
David Jones avatar image David Jones commented ·

In the playstream Event JSON it says i made 3 API calls so that would mean the title data request is fine, theres a problem with either of these lines from my understanding.

var yourSocialClassJson = getTitleDataResponse.Data[currentSocialClass];

var ratingCap = yourSocialClassJson.ratingTop;

0 Likes 0 ·
v-humcin avatar image v-humcin ♦ David Jones commented ·

Looking at it further there are a few other small adjustments that need to be made. "Data" does not directly contain the different social classes, you will have to access the "SocialClasses" value from "Data" before you can can access the other data. This is because GetTitleData will always return a dictionary of values even if you specify only one key.

Next you will need to make sure to parse the value obtained from "SocialClasses" as it is stored as a string in title data. After that that you should be able whichever class you need by name. I used "Rebellious" during testing but that's where you would use "currentSocialClass".

var getTitleDataRequest = "SocialClasses";
var getTitleDataResponse = server.GetTitleData(getTitleDataRequest);
//Access current class within the JSON object
var SocialClassJson = getTitleDataResponse.Data["SocialClasses"];
//Parse the result and then access current class within the JSON object
var parsed = JSON.parse(SocialClassJson);
var yourSocialClassJson = parsed[0]["Rebellious"];
0 Likes 0 ·
v-humcin avatar image v-humcin ♦ v-humcin ♦ commented ·

There was a quirk I noticed where your supplied JSON title data object is being returned as an array with one entry, so to actually access the classes it has to be accessed as "parsed[0]" as you can see in my example. I am doing more testing as to why this is happening as it does not seem to be intended, but for now this example should help you to understand the flow better.

0 Likes 0 ·
Show more comments
David Jones avatar image David Jones commented ·

My title ID is 95E3, thank you

0 Likes 0 ·
v-humcin avatar image v-humcin ♦ David Jones commented ·

Looking at the script again I noticed that you will need to make a small change to how you are accessing the GetUserReadOnlyData. Like with GetTitleDataResponse the data itself is stored within a "Data" object which in turn holds "UserDataRecord". You would then use the value field to get the desired value out. Looking through the documentation I linked can help you understand the exact relationship between the fields and how to access the value. Within your current setup, it would look something like this to get the final value out:

currentSocialClass.Data["SocialClass"].Value

As far as debugging in cloud script goes, using log.debug() statements is a good option. It would be helpful to add checks to api calls you make to determine their status. For instance you might have a check like this after calling GetTitleData:

if (getTitleDataResponse.error != null)
{
    log.debug(error.message);
}

You can read more about this here: https://docs.microsoft.com/en-us/gaming/playfab/features/automation/cloudscript/writing-custom-cloudscript#advanced-debugging-cloudscript

0 Likes 0 ·
David Jones avatar image
David Jones answered

An update - Everything works fine now although the only problem is the max API calls per cloudscript call. Unfortunately i have to abandon this feature because of the limitations but thank you, it made me understand better.

10 |1200

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

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.