question

My Game Studio avatar image
My Game Studio asked

Cloudscript API

Hello,

I'm trying to figure out why some API calls (serverside server object) return a fully qualified json object (with .code, .status, .Data) and some only return a subset of data?

 

Example server.GrantCharacterToUser returns just the CharacterId, nothing else of the normal REST API - This seems mix/matched as some calls do return full objects that can be used for error handling

 

Any tips on how to find what objects are what?

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

For error handling, you should always get back a standard PlayFabError object, containing all the info needed to determine what the issue was.

For the non-error results, the different API methods return results specific to the request, while trying to minimize the packet requirement. So, for example, GetPhotonAuthenticationToken only returns the PhotonCustomAuthenticationToken, since that's the only thing needed. GetUserCombinedInfo, on the other hand, requests a wide variety of data objects, making its response far more complex.

10 |1200

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

My Game Studio avatar image
My Game Studio answered

Would it not make sense to have every object have its associated return code? The API itself returns this data regardless but its being hidden from cloudscript.

 

For error handling then would this be acceptable?

if (typeof(requestPacket) !== 'PlayFabError'

 

Thank you

 

10 |1200

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

My Game Studio avatar image
My Game Studio answered

Additional, Is there any API docs for the javascript objects? (PlayFabError for example).

 

10 |1200

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

Hamza Lazaar avatar image
Hamza Lazaar answered

paultech, thank you for posting this question. You beat me to it.

The BasicClan CloudScript sample from github contains this snippet:

 

 

```

var serverData = server.CreateSharedGroup ({

  "SharedGroupId": clanNameId
  });
 

if (serverData.code != 200 )return("Clan already exist");

```

 

This is wrong and does not work as expected. When the call is not successful, it does not return anything and it throws strange undocumented various different errors.

I have tried all the SharedGroup "server" functions from CloudScript (Create, Get, Update, Delete) and I can confirm that it does not give you any clue when something is wrong.

I wrapped all calls inside try/catch blocks and I found myself catching 'undefined' errors (undefined name, message and stack)!! Yes CloudScript is driving me crazy. I have white hair already.

Here are some helper functions I'm using (source):

```

function createSharedGroup(id) {

'use strict';
try { return server.CreateSharedGroup({SharedGroupId : id});
} catch (e) { /*logException(getISOTimestamp(), 'createSharedGroup:' + id, String(e.stack));*/ throw e; }
}

function updateSharedGroupData(id, data) {
'use strict';
try {
var key;
for (key in data) {
if (data.hasOwnProperty(key) && !undefinedOrNull(data[key]) && !isString(data[key])) {
data[key] = JSON.stringify(data[key]);
}
}
return server.UpdateSharedGroupData({ SharedGroupId: id, Data: data });
} catch (e) { logException(getISOTimestamp(), 'updateSharedGroupData(' + id + ', ' + JSON.stringify(data) + ')', String(e.stack)); throw e; }
}

function getSharedGroupData(id, keys) {
'use strict';
try {
var data = {}, key;
if (undefinedOrNull(keys)) {
data = server.GetSharedGroupData({ SharedGroupId: id }).Data;
} else {
data = server.GetSharedGroupData({ SharedGroupId: id, Keys: keys }).Data;
}
for (key in data) {
if (data.hasOwnProperty(key)) {
data[key] = JSON.parse(data[key].Value); // 'LastUpdated' and 'Permission' properties are overwritten
}
}
return data;
} catch (e) { logException(getISOTimestamp(), 'getSharedGroupData:' + id + ',' + JSON.stringify(keys), String(e.stack)); throw e; }
}

function deleteSharedGroup(id) {
'use strict';
try { return server.DeleteSharedGroup({SharedGroupId : id}); } catch (e) { logException(getISOTimestamp(), 'deleteSharedGroup:' + id, String(e.stack)); throw e; }
}

```

 

EDIT: to better understand the situation: CloudScript is messed up more than the ZenDesk forums.

10 |1200

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

My Game Studio avatar image
My Game Studio answered

Hamza,

That is terrible! I hope that is not the solution we will be using. Testing so far and 

    if (typeof(return)  == 'PlayFabError')

Seems to be working, I'm testing different conditions now. If that's the case I'll debug the object to see what variables and methods are available (API docs please!) and that will give us a workable error handling solution.

 

The samples show multiple errors and some layouts are still strange without docs (IE, In clan sample it shows accessing .Data but in most cases, the object has the variable directly assigned and not in the Data array.  I love the possibilities with CloudScript, I'd just like way more documentation

 

 

10 |1200

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

My Game Studio avatar image
My Game Studio answered

I also don't believe you need to have 'use strict' - The script we submit to PlayFab is preprocessed into CloudScript.js that adds additional wrapper code.

 

 

10 |1200

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

Hamza Lazaar avatar image
Hamza Lazaar answered

I don't have a big experience with JavaScript before CloudScript. 

I always like to do things properly. I'm trying to follow some guidelines and get rid of all JSLint / JSHint warnings.

I invite you to take a look at this CloudScript repository and give me all your feedback. It will be released for public one day to give PlayFab customers that use Photon a baseline to work on and save them the headaches and sweat.

 

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.

Ion avatar image Ion commented ·

Hey @Hamza Lazaar, i have checked your repository, and looks very complete, although it is a bit old. Do you have some up-to-date advanced examples of managing Photon webhooks within Playfab?

I am starting to code some logic in the webhooks, also using Shared Group Data to store some room properties, specifically those ones which are necessary for calculating the result of a game match.

The way i am doing, is just for example, if a player kills other player, the killer raises an event (the best is that the killer raises the event because the killed could be inactive) so he can update the shared group in the raise event webhook. After a second, the killed player will try to get the match result executing cloud script from playfab client api. If this way a proper one, or what would you recommend?

Also, i am not using authoritative server.

Any help is very appreciated.

0 Likes 0 ·
My Game Studio avatar image
My Game Studio answered

Using a automated javascript linter may fail as it's not seeing the complete context as PlayFab wraps the script.

 

Have you looked at https://github.com/PlayFab/Photon-Cloud-Integration/tree/master/CloudScript ?

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

Ah, I see - your question is specific to Cloud Script, then? With Cloud Script, if the script produces an error in a call to a Server API method, that generates an exception, which you would need to catch if you want to do error handling on this. We do also return the error to the calling Client, so that you can handle it at that stage. But the expected return otherwise for a Server call in Cloud Script is the given return structure for the call in question.

Since JavaScript is a duck typed language, you won't find the same Class definitions in our SDK that you would for other languages. What you should do is use our Web API documentation (our main API doc pages) to see all the contents of each response.

Specific to errors, in addition to the response code ("code"), along with the status, error, errorCode, and errorMessage. For some API methods, there will also be an errorDetails which provides extra response info which can be used to debug the issue. For example, calls from PlayFab to third-party services, like Facebook or Steam, often use the errorDetails to pass along extra info from those services, when the error occurred on their side.

Here's a simple example of a Web API call error response:

{

  "code": 400,
  "status": "BadRequest",
  "error": "InvalidParams",
  "errorCode": 1000,
  "errorMessage": "Invalid input parameters",
  "errorDetails": {
    "Password": [
      "The Password field is required."
    ]
  }
}

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

Great conversation (now that I'm caught up on the additional exchanges). I do see that there's a problem in the BasicClans example that was posted - I'll work with Mark to get that updated. Thanks for calling it out!

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.