Did you find this helpful?

Using Cloud Script Actions with PlayStream

When a Cloud Script handler is launched from a PlayStream action, that handler has access to additional data on why it is being run - the context - which you can use to drive your server-side logic. This tutorial walks you through what all is available in the context and how to make use of it in your Cloud Script handlers.

Cloud Script Basics

The key to getting the most out of Cloud Script is knowing how to work with the inputs you have available – namely, the args and context for your handler. For example, here’s the helloWorld example from the starter Cloud Script loaded as revision 1 in all newly created titles (also available in our GitHub, here):

// This is a Cloud Script function. "args" is set to the value of the "FunctionParameter"
// parameter of the ExecuteCloudScript API.
// (
// "context" contains additional information when the Cloud Script function is called from a PlayStream action.
handlers.helloWorld = function (args, context) {
    // The pre-defined "currentPlayerId" variable is initialized to the PlayFab ID of the player logged-in on the game client.
    // Cloud Script handles authenticating the player automatically.
    var message = "Hello " + currentPlayerId + "!";
    // You can use the "log" object to write out debugging statements. It has
    // three functions corresponding to logging level: debug, info, and error. These functions
    // take a message string and an optional object.;
    var inputValue = null;
    if (args != null && args != undefined)
        inputValue = args.inputValue;
    log.debug("helloWorld:", { input: inputValue });
    // The value you return from a Cloud Script function is passed back
    // to the game client in the ExecuteCloudScript API response, along with any log statements
    // and additional diagnostic information, such as any errors returned by API calls or external HTTP
    // requests. They are also included in the optional player_executed_cloudscript PlayStream event
    // generated by the function execution.
    // (
    return { messageValue: message };

This example demonstrates the common use case of calling Cloud Script from a client via ExecuteCloudScript. It checks for an argument passed in with the key “inputValue”, and uses the value for that key as part of the text returned in the debug log info for the execution.

The Context Input Parameter

However, it’s also possible to call a Cloud Script as a result of an event in PlayStream, via a Rule (Automation->Rules), a Segment Enter/Exit Action (Players->Segments), or the Task service (Automation->Tasks). When you do, the context passed in to the function provides all the information you’ll need to take the appropriate action.

To see this, have a look at the handlePlayStreamEventAndProfile handler from the same sample Cloud Script:

// This is a simple example of a function that is called from a
// PlayStream event action. (
handlers.handlePlayStreamEventAndProfile = function (args, context) {
    // The event that triggered the action
    // (
    var psEvent = context.playStreamEvent;
    // The profile data of the player associated with the event
    // (
    var profile = context.playerProfile;
    // Post data about the event to an external API
    var content = JSON.stringify({user: profile.PlayerId, event: psEvent.EventName});
    var response = http.request('', 'post', content, 'application/json', null, true);
    return { externalAPIResponse: response };

In the case of a PlayStream-triggered Cloud Script call, the context contains three elements that can be used to drive your server-authoritative handler’s logic.

First, there’s the playStreamEvent, which you can see in the example code above. The playStreamEvent contains the complete event which triggered the handler as a JSON object, with all the parameters you see in the PlayStream event documentation. So for example, if you set up a Rule in your title that called handlePlayStreamEventAndProfile on any player_logged_in event, playStreamEvent.EventName would be “player_logged_in”, etc. (here’s the complete set of parameters for that event).

Next, there’s the playerProfile, also shown above. This contains information about the player that triggered the event. You can find all the details of the profile parameters here, but among other things, it contains the complete set of Statistics for the player in your title, as well as any custom Tags you have assigned to the player, so that you can use that data for very rich decision-making.

Now, the last element of context is triggeredByTask. Unlike the first two, which are set when using Rules and Segment Enter/Exit triggers, triggeredByTask is only applicable when the handler is running as a result of a Task, whether manual or on a timer. It contains only two parameters:

  • Name – The unique name you gave your Task when you created it
  • Id – The unique identifier automatically generated by PlayFab for your Task

For a Task run against a user Segment, you’ll also have the playerProfile, but you won’t have a playStreamEvent. And for a Task that’s simply run against your game but without any Segment, there won’t be a playerProfile, since the intent is to run something more general, like setting some Title Data for an event. So Name is the element you’ll want to use to use in your handler’s code flow, to determine the appropriate action to take.

PlayStream Plus Cloud Script

In many ways, Cloud Script handlers triggered by PlayStream actions have even more potential functionality than those triggered directly through calls to ExecuteCloudScript, since there’s a rich set of data made available via the context. This gives you the ability to update your handlers post-launch with additional logic that makes use of elements of the event or player profile that you hadn’t originally anticipated, without needing to update your client code in any way. In addition, we’ll continue to make additions to the player profile in future updates of the PlayFab service which will provide even more options for server-side logic.

Did you find this helpful?