question

brendan avatar image
brendan asked

Cloud Script and updating user data

We have a string we want to save to UserData but the ExecuteCloudScript only seems to allow us to pass one parameter so how does the cloud script know what key to use If we send the value (the string we want to save) but not the key? Do we have to make a separate cloud script function for each key we want to save values to? Also how do you assign the key,value pair in Server.UpdateUserData. This particular set of functions (both Update and GetUserData) are a bit confusing in comparison to the other server api calls.

Finally, I recall seeing that you guys were planning to add C# cloud script, is that still happening?

Player DataCloudScript
10 |1200

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

brendan avatar image
brendan answered

The FunctionParameter input to Cloud Script is an object, so it can be a complex set of info. The example in the doc page for ExecuteCloudScript shows an example of this: https://api.playfab.com/Documentation/Client/method/ExecuteCloudScript. The Key you use to pass a Value in doesn't have to have anything to do with the way you name Keys in your game, but without having some way to identify the Values you're passing in, you wouldn't have a good way to know which Value is which in your Cloud Script, so that would be the way to pass in multiple Values to write.

To use UpdateUserData in Cloud Script, I would recommend having a look at our samples: https://github.com/PlayFab/PlayFab-Samples. The Progressive Rewards sample is one that uses this API call, for example.

And yes, a C# implementation of Cloud Script is still in our backlog and we do want to add that in a future update, but it's not on our Q3 schedule right now, so I can't provide a solid date for when this will be added. I highly recommend voting up the Feature Request for this in our forums, to help with prioritization, if it's a key need for you: https://community.playfab.com/content/idea/425/206730247-Cloud-scripting-in-C-.html.

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

Tolin Simpson avatar image Tolin Simpson commented ·

What's the difference between PlayerData, ReadOnlyData and InternalData? What is the best way to include both the Key and Value in the Function Parameter in a way cloud script can understand it?

When getting user data do we have to parse it through Json again back to a regular value?

0 Likes 0 ·
brendan avatar image brendan Tolin Simpson commented ·
  • Player Data - read/write by the player via the Client API
  • Player Read Only Data - read-only by the player via the Client API

Note: For both of those, setting Permissions to Public allows any player to read the data, as well.

  • Player Internal Data - cannot be read by the player at all via the Client API

For all three, the Server API calls can read and write the data, allowing you to secure it via Cloud Script.

The example in the doc page specifically shows sending key/value pairs in the FunctionParameter. And yes, you would then use JSON.parse in the Cloud Script to turn the string into an object.

0 Likes 0 ·
Tolin Simpson avatar image Tolin Simpson brendan commented ·

How would you go about sending a Json object from the client as a function parameter?

The client api doesn't seem to have a Json.Parse ability and the following code doesn't work. Argument 1: Cannot convert string to System.Collection.Generic.KeyValuePair<string,Object>.

string value = "my string value";

PlayFab.Json.JsonObject data = new PlayFab.Json.JsonObject {"keyname", value};

updateUserData(data);


0 Likes 0 ·
Show more comments
Show more comments
brendan avatar image
brendan answered

@leatherboundgames@gmail.com - I'm moving to a new Answer, so that I have sufficient room to cover everything


There are a mix of issues with the snippet in question:

1. How are you calling ExecuteCloudScript, and how are you passing in the Key/Value pair you've created? Bear in mind that FunctionParameter is itself a JSON object, so you may need to pass them in as something like "keyName": string and "valueString": string, so that you can then parse them as individual elements from args.

2. SimpleJson isn't part of JavaScript - it's in our Unity SDK. In JavaScript, you can parse a string into a JSON object with JSON.parse(string), and you can turn an object into a string with JSON.stringify(object).

3. I'd recommend being very careful with how you form JavaScript calls, as the language tries to "help" a lot, which can result in it doing something utterly unlike what you intended. In this case, using a ...Request object (the way we do in the SDK) to create your call to the Server API is likely tripping you up.

For your call, I would actually do with something like the code from the post linked above (https://community.playfab.com/questions/3859/way-to-use-variables-to-set-kvp-data-in-cloud-scri.html). But here's the same code, modified to fit your specific use case. For this call, you need to pass in the Key and Value as described above.

handlers.UpdateUserData = function (args) {

    var dataPayload = {};

    dataPayload[args.keyName] = args.valueString;

    var result = server.UpdateUserReadOnlyData({
        PlayFabId: currentPlayerId,
        Data: dataPayload
    });
}
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.

Tolin Simpson avatar image Tolin Simpson commented ·

args in cloudscript should be the object created here:

object json = PlayFab.Json.JsonWrapper.SerializeObject("{\"key name\":\"" + valueString + "\"}");

Here is the ExecuteCloudScript function:

public void updateUserData(object value) //value = "json" defined above.

{
   ExecuteCloudScriptRequest request = new ExecuteCloudScriptRequest(){ Function = "UpdateUserData", GeneratePlayStreamEvent = true, FunctionParameter = value};

PlayFabClientAPI.ExecuteCloudScript(request, updateUserDataCallback, null);


}
0 Likes 0 ·
brendan avatar image brendan Tolin Simpson commented ·

As far as I can see, you're still not passing in the Key and Value strings so that you can then use them in your Cloud Script. Could you try simply defining your FunctionParameter directly in the call to create it for now, to see if that works? You can always work to make it more complex from there. Something like this:

ExecuteCloudScriptRequest request = new ExecuteCloudScriptRequest
{
  FunctionName = "UpdateUserData",
  FunctionParameter = new Dictionary<string, object> { { "keyName", keyNameString }, { "valueString", valueString } }
};
0 Likes 0 ·
Tolin Simpson avatar image
Tolin Simpson answered

I'm creating a new answer for anyone else to see summarizing what is going on.

To send a KeyValuePair to a CloudScript Function through the FunctionParameter of ExecuteCloudScriptRequest it has to be a Json object.

(Link to Json structure examples)

Sending a Json object to CloudScript however needs to have "keyName" and "valueString" there to define the object as a KeyValuePair with the strings for your key and value set to them respectively otherwise sending just your key and value in a Json object your Data in your CloudScript UpdateUserData function won't be able to be read.

Your Client-Side ExecuteCloudScript function can be set up like this to receive two variables. (C#)

public void updateUserData(string keyname, string value)

{
   ExecuteCloudScriptRequest request = new ExecuteCloudScriptRequest;
   {
       FunctionName = "UpdateUserData",
       GeneratePlayStreamEvent = true,
       FunctionParameter = new Dictionary<string,object> { {"keyName", keyname }, { "valueString", value } }
};

   PlayFabClientAPI.ExecuteCloudScript(request, yourCallBackFunction, null);
}

//Note: To access Dictionary you need to add using system.collections.generic; to the top of your script.

This should then call the following CloudScript function called "UpdateUserData":

handlers.UpdateUserData = function(args)

{

   var dataPayload = {};

   dataPayLoad[args.keyName] = args.valueString;

   var result = server.UpdateUserReadOnlyData({

   PlayFabId: currentPlayerId,

   Data: dataPayLoad

   });

Now if you go to your gameManager>Players>PlayerYouUpdatedDataFor you will see the keyname and value strings you sent from the client in the Key,Value pair boxes ready to be used in GetUserData().

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.

kennyroy avatar image kennyroy commented ·

Struggled with this for hours until I realized the L in PayLoad is wrong case.

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.