Game Manager API

The Google Cast Game Manager API (hereafter, the game manager) lets you quickly write Google Cast-enabled games. With the API, you can build sender applications that connect with a receiver application to communicate and synchronize player and game states. The API supports Android, iOS, and Chrome Cast sender applications as well as Cast receiver applications.

Setup

To set up your game for Cast:

  1. Get the following from API libraries:
    • For v2 on iOS and Android, obtain both the Cast SDK and the Game Manager API for the appropriate platform.
    • For v3 on iOS, obtain only the Cast SDK, as the Game Manager API is now part of the core Cast SDK.
  2. Develop your sender application according to the Cast SDK v2 developer guides for Android, iOS, and Chrome. For iOS, you can instead choose the developer guide for iOS for Cast SDK v3.
  3. Develop your receiver application according to the Custom Receiver developer guide.
  4. Follow the instructions in this guide to implement the game manager APIs.

You do not have to configure a specific namespace, protocol, or media type. Instead, use the appropriate main class, calling the initialization method described in the following table.

API Cast Main class Initialization
Android sender v2 android.gms.cast.games.GameManagerClient
  1. Launch Android sender v2
  2. Call GameManagerClient.getInstanceFor
iOS Sender v2 GCKGameManagerChannel
  1. Launch iOS sender
  2. Call initWithSessionID:
  3. Call addChannel:
  4. Wait for gameManagerChannelDidConnect:
iOS Sender v3 GCKCastSession
  1. Launch iOS sender
  2. Create the GCKGameManagerChannel instance using its initWithSessionID: initializer.
  3. Implement the GCKSessionManagerListener protocol in some class X.
  4. Call [[GCKCastContext sharedInstance].sessionManager addListener:] with X to register that as the session listener.
  5. When a Cast session is started, X's
    -[sessionManager:didStartCastSession:] callback will be invoked with the GCKCastSession instance.
  6. Call addChannel: on that GCKCastSession instance to register the GCKGameManagerChannel with the session.
Chrome Sender v2 chrome.cast.games.GameManagerClient
  1. Launch Chrome sender
  2. Call GameManagerClient.getInstanceFor
Receiver v2 cast.receiver.games.GameManager
  1. Instantiate cast.receiver.games.GameManager
  2. Start custom receiver

This document further describes how to use the API, and provides some examples.

Communication model

The game manager handles connection, reconnection, and communication between senders and receivers, and manages player state, gameplay, and lobby information for a Cast-enabled game. It utilizes the Cast sender-receiver communication model, with request and update messages in the Cast namespace and message bus. However, the game manager provides you with abstractions of this communication model, defining the namespace and protocol for you. This means you don't have to write lots of code to keep the players and the game synchronized; the game manager does it for you.

The abstractions are divided between the GameManager and the GameManagerClient. The messages sent between them are preformatted strings; you do not have to format or parse the messages.

GameManager

The receiver uses the GameManager to communicate with connected senders. Internally, the GameManager uses the CastMessageBus to send and receive messages defined in an internal namespace.

The game running on the receiver should add callbacks to the GameManager to make game-related decisions based on input from the senders, update the game displayed on the TV, and notify the senders of the results of these decisions.

To notify senders about changes, the game running on the receiver can tell the GameManager to send update messages. For example, the game might want to let senders know that the game is finished loading on the receiver. Update messages may include a field for custom information specific to your game. There are two types of updates: responses to a request from a sender, which can be sent to individual or multiple senders, and updates triggered by the receiver application, which can be sent to individual or multiple senders. The receiver application can register callbacks for GameManager events and can also update information managed by the GameManager in these callbacks. The senders can be notified of these changes through event callbacks triggered by the GameManagerClient.

The GameManager manages the following types of information and reports it in updates to senders:

  • PlayerInfo: a struct representing the following player information:
    • playerId: a unique string identifier
    • playerState: an enum describing the state of a player in the game (ready, playing, etc.)
    • playerData: a JSON serializable object with game-specific player information (player name, avatar, character stats, etc.) shared between senders and receiver that persists in memory while the receiver application is running
  • GameplayState: an enum describing whether the game is loading, running, paused, or showing an information screen; informs other non-game Cast applications about the state of the receiver application
  • GameData: a JSON serializable object with game-specific information shared between senders and receiver (game difficulty level, overall score, etc.) that persists in memory while the receiver application is running
  • LobbyState: an enum describing whether the game lobby is open or closed

The GameManager only synchronizes the information about a game. The application must do something with the player and game information. For example, changing something like gameplayState to "loading" with the GameManager on the receiver does not automatically load the game; it is up to the application to implement loading the game. But the GameManager does notify all of the senders that the game is loading.

The receiver may control one or more virtual players, which are not associated with any sender. You can also use virtual players to integrate the receiver with other non-Cast game services. See Virtual players for information about creating virtual players.

GameManagerClient

Senders use the GameManagerClient to communicate with the GameManager on the receiver. The GameManagerClient uses a session internally to send and receive messages defined in an internal namespace. Note, the GameManagerClient class in iOS is called GameManagerChannel.

The sender application should call GameManagerClient methods to let the GameManager on the receiver know about player actions in the game. The game running on the receiver should then make a decision based on input from all of the senders, update the game on the TV, and notify senders.

To ask the game running on the receiver about player-related changes, senders send request messages to the GameManager on the receiver. For example, the sender might want to let the receiver know that a player is ready to play the game. When the GameManager receives a request, an event is triggered for which the receiver can implement a callback to provide game functionality such as setting up a lobby, starting a game, or sending custom updates back to senders. The sender can include custom information specific to the game in a request. On the receiver, the event triggered by the request includes this custom information.

Senders use the GameManagerClient to send the following types of requests to the GameManager:

  • Changes to the playerState field of the PlayerInfo object
  • Custom messages for the receiver application (for example, firing a bullet)

Senders can only request to change player state. Only the receiver can actually change gameplay state, game data, and lobby state. A sender can send a custom message to cause the receiver to change gameplay state.

Senders may have one or more players, created and managed by the GameManagerClient. For example, a sender application on a laptop could map WASD keys for one player, and arrow keys for another. The sender can send discrete requests for each player on the device, and a callback is triggered for each player request.

Sender API

The Cast sender gaming APIs expose the GameManagerClient and related objects to Cast senders for the following platforms:

This guide assumes you already understand how to build a Cast application. Refer to the following documentation for information about building a sender for Cast:

This section provides some examples for Android. The APIs for iOS and Chrome follow a similar pattern.

Creating the GameManagerClient

Create the GameManagerClient once your app has established a Cast session.

In Android, use the getInstanceFor method in the callback that launches the application. For example:

private final class LaunchReceiverApplicationResultCallback implements
        ResultCallback {
    @Override
    public void onResult(ApplicationConnectionResult result) {
        Status status = result.getStatus();
        ApplicationMetadata appMetaData = result.getApplicationMetadata();
        if (status.isSuccess()) {
            Log.d(TAG, "Launching game: " + appMetaData.getName());
            mCastSessionId = result.getSessionId();
            GameManagerClient.getInstanceFor(mApiClient, mCastSessionId)
              .setResultCallback(new ResultCallback() {
                @Override
                onResult(GameManagerInstanceResult result) {
                  mGameManagerClient = result.getGameManagerClient();
                }
            });
        } else {
            Log.d(TAG, "Unable to launch the the game. statusCode: " + result);
            setSelectedDevice(null);
        }
    }
}

Accessing game information

Once you have a GameManagerClient instance, you may retrieve the GameManagerState object that holds lobby, gameplay, and player information. See the following API references for lists of methods.

The following example for Android sets up the basic game information:

GameManagerClient gameManagerClient = mCastConnectionManager.getGameManagerClient();
if (mCastConnectionManager.isConnectedToReceiver()) {
    GameManagerState state = gameManagerClient.getCurrentState();
    mTextViewApplicationName.setText(state.getApplicationName());
    mTextViewMaxPlayers.setText(Integer.toString(state.getMaxPlayers()));
    mTextViewLobbyState.setText(getLobbyStateName(state.getLobbyState()));
    mTextViewGameplayState.setText(getGameplayStateName(state.getGameplayState()));
    mTextViewGameStatusText.setText(state.getGameStatusText());

    JSONObject gameData = state.getGameData();
    String gameDataText = gameData != null ? gameData.toString() : "";
    mTextViewGameData.setText(gameDataText);
}

Using state information

Don't store, cache, or otherwise persist game and player state information across functions. For each function that executes more than one change against the current state, always get a fresh state and use the same state information for all changes against that state. Don't count on a state variable to be updated automatially.

DON'T repeat state updates between changes:
statusTextField.setText(client.getCurrentState().getGameStatusText());
maxPlayersTextField.setText(client.getCurrentState().getMaxPlayers());
DO use one state update for all changes:
GameManagerState state = client.getCurrentState();
statusTextField.setText(state.getGameStatusText());
maxPlayersTextField.setText(state.getMaxPlayers());

Handling game state changes

To respond to changes in the GameManagerState members, implement a GameManagerClient.Listener and use the GameManagerState "hasChanged" methods. For example, in Android, the GameManagerClient.Listener.onStateChanged listener method could check if the lobby state, gameplay state, and game data have changed, as follows:

private class DebuggerListener implements GameManagerClient.Listener {

    @Override
    public void onStateChanged(GameManagerState currentState, GameManagerState previousState) {
        if (currentState.hasLobbyStateChanged(previousState)) {
            Log.d(TAG, "onLobbyStateChange: " + currentState);
            mTextViewLobbyState.setText(getLobbyStateName(currentState.getLobbyState()));
        }
        if (currentState.hasGameplayStateChanged(previousState)) {
            Log.d(TAG, "onGameplayStateChanged: " + currentState);
            mTextViewGameplayState.setText(getGameplayStateName(
                    currentState.getGameplayState()));
        }
        if (currentState.hasGameDataChanged(previousState)) {
            String text = currentState.getGameData() != null
                    ? currentState.getGameData().toString() : "";
            Log.d(TAG, "onGameDataChanged: " + text);
            mTextViewGameData.setText(text);
        }
        ...

Affecting game state changes

To cause a change in the game, you send a GameManagerClient request to the GameManager. It is up to the game running on the receiver to decide what to do with this request. The request includes an extraMessageData parameter that holds a JSON object with data for the game; for example, in a chess game, the coordinates to where the player wants to move a piece; the GameManager can encode whether the chess move was valid or not. The sendGameRequest methods of the GameManagerClient return a GameManagerClient.GameManagerResult with information from the GameManager also encoded as a JSON object.

For example, in Android, to use the sendGameRequest GameManagerClient method:

JSONObject chessMove = new JSONObject();
chessMove.put("moveFrom", "b3");
chessMove.put("moveTo", "b4");
gameManagerClient.sendGameRequest(playerId, yourGameSpecificInformation).setResultCallback(
  new ResultCallback<GameManagerResult> {
    @Override
    public void onResult(GameManagerResult gameManagerResult) {
       JSONObject chessResult = gameManagerResult.getExtraMessageData();
       // implement logic to read chessResult
   }
});

On iOS, extraMessageData is called extraData, and a request ID is returned instead of a GameManagerResult. The result from the GameManager is provided via GCKGameManagerChannelDelegate#gameManagerChannel:requestDidSucceedWithID:result: delegate callback method.

You can also send a GameManagerClient message to the GameManager. As with requests, it is up to the game running on the receiver to decide what to do with this message. The message does not return a result. Messages may be used, for example, in a fast-paced game to move a player when dropping one movement message out of 50 does not really impact gameplay and receiving a failure response for a movement message isn’t really actionable on the sender, especially if the player is focused on what is happening on the TV.

For example, in Android, use the sendGameMessage GameManagerClient method:

JSONObject fireMessage = new JSONObject();
fireMessage.put("fire", true);
gameManagerClient.sendGameMessage(playerId, fireMessage);

GameManagerClient requests and messages have two signatures: one with a playerId parameter and one without. If the playerId is not specified, the game manager uses an internally stored lastUsedPlayerId. This makes it easier for a game with only one player per sender as it does not have to keep passing in the playerId.

Requesting player changes

Game players are represented by PlayerInfo objects. The PlayerInfo class has methods to get player data and player state information. For example, in Android, PlayerInfo.getPlayerData retrieves the JSON object from the GameManager that holds player-specific data. To set this data, you send an updatePlayerData request to the GameManager.

For example, in Android, use the sendPlayerReadyRequest GameManagerClient method to change the player state to READY:

JSONObject extraMessageData = new JSONObject();
extraMessageData.put("playerName", playerName);
extraMessageData.put("avatar", avatar);
gameManagerClient.sendPlayerReadyRequest(playerId, extraMessageData);

Player state information may be returned from the PlayerInfo object, but it is maintained in constants of the GameManagerCient. The game player states within the context of Cast are: AVAILABLE, DROPPED, IDLE, PLAYING, QUIT, READY, and UNKNOWN. The GameManagerClient only maintains state information for players which the receiver knows about, created when the sender issues a player available request; for example, in Android, GameManagerClient.sendPlayerAvailableRequest.

Adding a player to the game

A sender can add a player to the game by sending a request for a player to become AVAILABLE. You can provide a unique player ID for the new player or let the game manager assign one automatically. For example, to add a player to the game with your own player ID:

String newPlayerID = ...;
JSONObject extraMessageData = ...;  // this can be null
gameManagerClient.sendPlayerAvailableRequest(newPlayerID, extraMessageData);

To add a player to the game and let the game manager assign the player ID automatically, set the player ID parameter to null:

gameManagerClient.sendPlayerAvailableRequest(null, extraMessageData);

The result object returned by the sendPlayerAvailableRequest has the assigned player ID. If the sender only manages one player, you don't need to maintain a player ID. The GameManagerClient keeps track of the last used player ID (in this case, from creating a new player), and you can call GameManagerClient methods that do not have a player ID parameter.

Receiver API

The Cast GameManager and related receiver API classes manage game setup, handle requests from senders as well as receiver-only requests, and manage the information shared with senders. These classes are part of the Cast Receiver API.

First, implement a custom receiver acccording to the Custom Receiver Application guide.

Configuring game manager

GameManager is the main class for the game receiver SDK. It must be instantiated before CastReceiverManager.start is called. The constructor for GameManager requires a GameManagerConfig object, a struct in which you specify the name of the game and the maximum number of players.

Following is an example that sets up CastReceiverManager, GameManagerConfig, and GameManager.

var gameManager;

window.onload = function() {
  var castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
  var appConfig = new cast.receiver.CastReceiverManager.Config();
  appConfig.statusText = 'My Game is getting ready';
  appConfig.maxInactivity = 6000;  // 100 minutes for testing only.

  var gameConfig = new cast.receiver.games.GameManagerConfig();
  gameConfig.applicationName = 'My Game';
  gameConfig.maxPlayers = 2;
  gameManager = new cast.receiver.games.GameManager(gameConfig);

  castReceiverManager.start(appConfig);
};

Handling requests

The GameManager handles all requests to change game, gameplay, and player states for the game. In your GameManager instance, you implement callbacks to respond to events generated by requests and updates.

Events

All game manager API requests trigger a GameManager Event. These events are of the EventType for games. All of these event types describe events that may be triggered by an update from the game running on the receiver; a subset of these event types describe events triggered by a request from the sender.

Player events, like PLAYER_READY, can be triggered by a request from the sender or an update to the game manager from the game running on the receiver. For example, a sender calls sendPlayerReadyRequest to change the player state, or the game on the receiver calls updatePlayerState to change the player state.

Game events, like GAME_PAUSED, can be triggered only by an update to the game manager from the game running on the receiver. For example, the game calls updateGameplayState to change gameplay state. Note, the GAME_MESSAGE event is the one game event that may fire for a request from the sender as well as an update from the receiver.

The Event fields hold the event type, playerInfo, error data, error description, and requestExtraMessageData for the extraMessageData field available in all requests, plus a resultExtraMessageData field with data to be set in the callback for the event.

Callbacks

There are three ways to set up request event callbacks with GameManager.

  • Call the addEventListener method for a specific request.

    gameManager.addEventListener(cast.receiver.games.EventType.PLAYER_AVAILABLE,
        function(event) {
            console.log('Player ' + event.playerInfo.playerId + ' is available');
        });
    
  • Implement a callback for the defined GameManager property.

    gameManager.onPlayerAvailable = function(event) {
        console.log('Player ' + event.playerInfo.playerId + ' is available');
    };
    
  • Call the addGameManagerListener method to provide one object (that implements GameManagerListener) to handle all requests.

Here is an example of using addGameManagerListener with an object that handles the PLAYER_AVAILABLE request. This is useful for writing a single game class that handles all requests. When a callback is triggered, this is scoped to the object (in this example, this is scoped to MyGame).

MyGame = function() {
};

MyGame.prototype.onPlayerAvailable = function(event) {
    console.log('Player ' + event.playerInfo.playerId + ' is available');
};

MyGame.prototype.onPlayerReady = function() {};
MyGame.prototype.onPlayerIdle = function() {};
MyGame.prototype.onPlayerPlaying = function() {};
MyGame.prototype.onPlayerDropped = function() {};
MyGame.prototype.onPlayerQuit = function() {};
MyGame.prototype.onPlayerDataChanged = function() {};
MyGame.prototype.onGameStatusTextChanged = function() {};
MyGame.prototype.onGameMessageReceived = function() {};
MyGame.prototype.onGameDataChanged = function() {};
MyGame.prototype.onGameLoading = function() {};
MyGame.prototype.onGameRunning = function() {};
MyGame.prototype.onGamePaused = function() {};
MyGame.prototype.onGameShowingInfoScreen = function() {};
MyGame.prototype.onLobbyOpen = function() {};
MyGame.prototype.onLobbyClosed = function() {};

myGame = new MyGame();
gameManager.addGameManagerListener(myGame);

Responding to sender requests with extraMessageData

A callback can use the resultExtraMessageData field of the Event object passed to the callback respond to sender requests with game-specific information. The extra information is used only when the request automatically triggers a response. For example, the game manager sends a response to sendGameRequest, but sendGameMessage does not. Here is an example of responding to a GAME_REQUEST request with extraMessageData:

gameManager.addEventListener(cast.receiver.games.EventType.GAME_MESSAGE_RECEIVED,
    function(event) {
        if (event.requestExtraMessageData == 'attack') {
            if (Math.random() < 0.5) {
                 event.resultExtraMessageData = { result : 'hit' };
            } else {
                 event.resultExtraMessageData = { result : 'miss' };
            }
        }
    });

Manually sending game-specific information

The receiver application might want to notify one or more players about game-specific information that does not involve changing game or player state. For example, the receiver might want to send a private notification message or alert a sender about a special transient event. Use the sendGameMessageToPlayer and sendGameMessageToPlayers methods to manually send a game-specific message object to one or more players. For example:

var playerId = gameManager.getPlayers()[0].playerId;
var message = { result: 'damaged' };
gameManager.sendGameMessageToPlayer(playerId, message);

Senders receiving the message triggers a callback for the game-specific message:

gameManagerClient.addEventListener(
    chrome.cast.games.GameManagerEventType.GAME_MESSAGE_RECEIVED, function(event) {
         console.log(‘Received message: ‘);
         console.dir(requestExtraMessageData);
    });

Handling multiple players from the same sender

A sender can have one or more players. For example, a laptop could map WASD keys for player 1, and arrow keys for player 2. In this scenario, a sender sends a request for each player on the device. Thus, the request callback is triggered for each player.

Use the getSenderIdWithPlayerId method to look up the sender ID associated with a player ID, and the getPlayerIdsWithSenderId method to look up all the players associated with a sender ID. In the example of the laptop with two players, the laptop is represented by one sender ID, and the two players are represented by two different player IDs. Both player IDs are associated with the same sender ID (for the laptop).

Here is an example that displays player and sender information for a PLAYER_AVAILABLE request:

gameManager.addEventListener(cast.receiver.games.EventType.PLAYER_AVAILABLE,
    function(event) {
       var playerId = event.playerInfo.playerId;
       var senderId = gameManager.getSenderIdWithPlayerId(playerId);
       var playerIds = gameManager.getPlayerIdsWithSenderId(senderId);
       console.log('Player ' + playerId + ' available from sender ' + senderId);
       console.log('All players on sender ' + senderId + ':');
       console.dir(playerIds);
    });

Keeping track of players

Often a game wants to know the list of all players that are connected to the game manager. A player is connected to the game manager if the player's state is not DROPPED or QUIT. Instead of calling getPlayersInState multiple times, you can use the getConnectedPlayers method. Here is an example that lists all players connected to the game, and prints their PlayerInfo information to the console:

var connectedPlayers = gameManager.getConnectedPlayers();
for (var i = 0; i < players.length; i++) {
  var playerInfo = players[i];
  console.log('PlayerInfo for connected player ' + playerInfo.playerId);
  console.dir(playerInfo);
}

Managing information

GameManager manages player information, gameplay state, game data, and lobby state.

Player information

GameManager represents each player with a PlayerInfo struct, which includes the PlayerId field that uniquely identifies each player. The Event object passed to request callbacks also has a PlayerInfo field that is set with information from the request or update. GameManager also has several methods for getting player information.

Here is an example that lists all players that are playing the game, and prints their PlayerInfo information to the console:

var players = gameManager.getPlayersInState(
    cast.receiver.games.PlayerState.PLAYING);
for (var i = 0; i < players.length; i++) {
    var playerInfo = players[i];
    console.log('PlayerInfo for player ' + playerInfo.playerId);
    console.dir(playerInfo);
}

Player data

The PlayerInfo struct includes a playerData field; this field's data persists in memory while the game is running on the receiver.

Here is an example where a GAME_MESSAGE_RECEIVED callback changes player data. The opt_noBroadcastUpdate parameter is false to allow the update to be sent since a GAME_MESSAGE_RECEIVED event does not automatically generate a response:

gameManager.addEventListener(cast.receiver.games.EventType.GAME_MESSAGE_RECEIVED,
    function(event) {
        ...
        gameManager.updatePlayerData(playerId, { 'travel': 'fly' },
            false);
    });

Player data can be obtained using getPlayers or getPlayerInState methods. Both return the PlayerInfo struct that includes the player data. These methods allow for updating all senders immediately (when the opt_noBroadcastUpdate parameter is false), or suppressing sending updates until calling the game manager’s broadcastGameManagerStatus method (when the opt_noBroadcastUpdate parameter is true). This is useful if the game needs to do multiple updates and then broadcast a single update to all senders.

Here is an example that manually changes all player data for players in the PLAYING state, and broadcasts a response to all senders:

var players = gameManager.getPlayersInState(
    cast.receiver.games.PlayerState.PLAYING);
var travel = { travel: 'fly' };
for (var i = 0; i < players.length; i++) {
    var playerInfo = players[i];
    gameManager.updatePlayerData(playerInfo.playerId, status,
        true);
}
gameManager.broadcastGameManagerStatus();

Player state

There are two ways to update player state. Both of these methods triggers an event callback from the game manager, as described in Handling requests.

  • Senders can send game manager requests to change the player state of their players, as described in Requesting player changes.
  • The game running on the receiver can update the player state of any player by calling GameManager.updatePlayerState method. This method allows for updating all senders immediately (when the opt_noBroadcastUpdate parameter is false), or suppressing sending updates until calling the game manager’s broadcastGameManagerStatus method (when the opt_noBroadcastUpdate parameter is true). This is useful if the game needs to do multiple updates and then broadcast a single update to all senders.

Here is an example that updates state information and then broadcasts the final state information via GameManager:

var readyPlayers = gameManager.getPlayersInState(
    cast.receiver.games.PlayerState.READY, true);
for (var i = 0; i <h; readyPlayers.length; i++) {
    gameManager.updatePlayerState(readyPlayers.playerId,
        cast.receiver.games.PlayerState.PLAYING, true);
}

gameManager.broadcastGameManagerStatus();

Virtual players

Virtual players are players that are completely controlled by the receiver application and have no sender associated with them. This is useful for tests, bots, and integrating a receiver application with other non-Cast game services.

All of the earlier sections about getting player information, changing player state, and changing player data apply to virtual players. However, the receiver application is responsible for notifying senders about changes to virtual players (e.g. using broadcastGameManagerStatus).

Use the GameManager.updatePlayerState method as follows to create a virtual player:

gameManager.updatePlayerState(null, cast.receiver.games.PlayerState.AVAILABLE);

In the example above, the null passed to the playerId field indicates the game requests to create a virtual player. This triggers a PLAYER_AVAILABLE event that includes the player ID of the virtual player.

Gameplay state

Use GameManager’s updateGameplayState method to update gameplay state. This method allows for updating all senders immediately (when the opt_noBroadcastUpdate parameter is false), or suppressing sending updates until calling the game manager’s broadcastGameManagerStatus method (when the opt_noBroadcastUpdate parameter is true). This is useful if the game needs to do multiple updates and then broadcast a single update to all senders.

Here is an example that updates gameplay state information and then broadcasts the final state information via GameManager:

gameManager.updateGameplayState(
    cast.receiver.games.GameplayState.RUNNING, true);

gameManager.broadcastGameManagerStatus();

Game data

GameManager manages a game-specific game data object shared between senders and the receiver. This information persists in memory while the receiver application is running.

Use GameManager’s updateGameData method to update game data. This method allows for updating all senders immediately (when the opt_noBroadcastUpdate parameter is false), or suppressing sending updates until calling the game manager’s broadcastGameManagerStatus method (when the opt_noBroadcastUpdate parameter is true).

Here is an example where a GAME_MESSAGE_RECEIVED callback changes game data. The opt_noBroadcastUpdate parameter is false to allow the update to be sent since a GAME_MESSAGE_RECEIVED event does not automatically generate a response:

gameManager.addEventListener(cast.receiver.games.EventType.GAME_MESSAGE_RECEIVED,
    function(event) {
        ...
        gameManager.updateGameData({ enemyStatus: ‘dead’ }, false);
    });

Conversely, this example changes game data, then broadcasts the change to all senders.

gameManager.updateGameData({ enemyStatus: ‘dead’ }, false);
gameManager.broadcastGameManagerStatus();

Lobby state

Use GameManager’s updateLobbyState method to update the lobby state. This method allows for updating all senders immediately (when the opt_noBroadcastUpdate parameter is false), or suppressing sending updates until calling the game manager’s broadcastGameManagerStatus method (when the opt_noBroadcastUpdate parameter is true).

Here is an example that updates gameplay state information and then broadcasts the final state information via GameManager:

gameManager.updateLobbyState(
    cast.receiver.games.LobbyState.CLOSED, true);

gameManager.broadcastGameManagerStatus();