Using CloudScript actions with PlayStream

When a CloudScript 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 CloudScript handlers.

CloudScript basics

The key to getting the most out of CloudScript 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 CloudScript, loaded as Revision 1 in all newly created titles (also available in our GitHub, shown below).

// This is a CloudScript function.
// "args" is set to the value of the "FunctionParameter" parameter of the ExecuteCloudScript API.
// "context" contains additional information when the CloudScript 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.
    // CloudScript 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.
    log.info(message);
    var inputValue = null;
    if (args != null && args != undefined)
    {
        inputValue = args.inputValue;
    }
    log.debug("helloWorld:", { input: inputValue });

    // The value you return from a CloudScript 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 CloudScript 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 CloudScript 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 read about the basics of how PlayStream events work, see our blog Introducing PlayStream, and for a list of PlayStream event types and their properties, see our PlayFab API Reference.

To view this action, have a look at the handlePlayStreamEventAndProfile handler from the same sample CloudScript.

// This is a simple example of a function that is called from a
handlers.handlePlayStreamEventAndProfile = function (args, context) {

    // The event that triggered the action.
    // For a list of event types, see our PlayFab API documentation.
    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('https://httpbin.org/status/200', 'post', content, 'application/json', null, true);

    return { externalAPIResponse: response };
}

In the case of a PlayStream-triggered CloudScript call, the context contains 3 elements that can be used to drive your server-authoritative handler's logic.

  1. 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).

  2. Next, there’s the playerProfile, also shown in the previous example. 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.

  3. 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 CloudScript

In many ways, CloudScript 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.