Table Of Contents

Previous topic

23.17. The GameProfileManager Object

Next topic

23.20. The NotificationsManager Object

This Page

23.18. The DataShareManager Object

The DataShareManager object is an API for creating and finding data share objects. Data shares are shared public key-value stores which allow games to share data with other users. For example, data shares could be used to store the game state of an asynchronous multiplayer game (allowing communication with users who are on-line or off-line) like Chess or Diplomacy.

For real-time multiplayer games requiring low latency (games with users all playing at the same time e.g. FPS) please use the MultiPlayerSessionManager.

Before using the DataShareManager make sure you understand the user data API and know which game data API to use. The DataShareManager is the most complex of the game data API’s and you should always consider the user data API or the game profiles API before using data shares.

Note

Guest users are not supported by the DataShareManager. This means that before using the DataShareManager games should check if the current user is a guest with the guest property on the UserProfile object.

Required scripts

The DataShareManager object requires:

/*{{ javascript("jslib/utilities.js") }}*/
/*{{ javascript("jslib/services/datasharemanager.js") }}*/
/*{{ javascript("jslib/services/turbulenzservices.js") }}*/

23.18.1. Data Shares

Data shares are public key-value stores which allow games to share data with other users. Please read the user data guide for using a key-value store for how to use a key-value store efficiently.

Multiple data share objects can be created per user, one for each multiplayer game they are playing.

Access

Each key in a data share has a public write access level. This can be set to either public read only or public read and write. All keys are read only when created with the set function and read and write when created with the compareAndSet function. Giving keys read only access protects save games from malicious users who could use the API to alter other user’s save games. Only the owner of a key (the first user to write to the key) can set the value for a public read only key.

For more information see the data share access example.

Testing with multiple users

To test with multiple users see this guide on multiple logins.

Manually viewing and removing the data store on the local server

You can find the data share key-value stores in the devserver/localdata/datashare/{game-slug}/{datashare-id}.yaml files of the SDK.

Each file contains a the meta information and key-value store of the items owned in the following example format:

created: 1361967918
owner: dave
store:
  apples: {access: 0, lastSet: 1361967918, modifiedBy: dave, token: d965512aac48e6451c32929a,
    value: '1'}
  bananas: {access: 0, lastSet: 1361967918, modifiedBy: dave, token: b29799338516ab0c091997de,
    value: '3'}
users: [dave, ben, bill]

To remove a data store remove this file and then refresh the page. To remove all data stores for a game remove the devserver/localdata/datashare/{game-slug} directory and then refresh the page.

23.18.2. Examples

Creating a data share

A data share can be created for the current user by calling the dataShareManager.createDataShare function. After creating the data share the game can write to its key-value store using the set (read only) and compareAndSet (read and write) functions.

var dataShareManager;

function dataShareCreated(dataShare) {
    function dataShareSetCallback(wasSet, reason)
    {
        // player can now stop playing or go offline
    }
    dataShare.set({
            key: 'gamestate',
            value: JSON.stringify(gameState),
            callback: dataShareSetCallback
        });
}

function sessionReadyFn(gameSession)
{
    dataShareManager = DataShareManager.create(requestHandler, gameSession);
    dataShareManager.createDataShare(dataShareCreated);
}
var gameSession = TurbulenzServices.createGameSession(requestHandler, sessionReadyFn);

Note that the user’s game can remain joined to a data share even while the user is off-line. When the game has finished using the data share it should call dataShare.leave to remove the current user from the data share. Once the dataShare.users array is empty it will be deleted.

Finding and joining data share objects

Data shares can be found using the dataShareManager.findDataShares function. This function returns an array of data share objects which match the find parameters. To use the data share getKeys, get, set or compareAndSet functions you first need to join the data share.

By joining a data share object the current user is added to the dataShare.users array property of the data share. Once the dataShare.users array is empty it will be deleted.

The following code will find the first data share object with the user “bob” joined and, if it can find it, will join it and get the key “gamestate”:

var dataShare;

function joined() {
    Utilities.log('Joined game');
    dataShare.get('gamestate', function stateLoaded(store)
        {
            gameState = JSON.parse(store.value);
        });
};

dataShareManager.findDataShares({
    user: 'bob',
    callback: function callback(dataShares)
    {
        if (dataShares.length > 0)
        {
            dataShare = dataShare[0];
            dataShare.join(joined);
        }
        else
        {
            Utilities.log('Bob is not in a multiplayer game');
        }
    }
});

...
// sometime later the multiplayer game ends
function leave() {
    Utilities.log('Multiplayer game left');
};
dataShare.leave(leave);

Note that the user’s game can remain joined to a data share even while the user is off-line. Once the user leaves a multiplayer game or it is complete, the game must call leave so that the data share can be deleted.

To find any joinable data share object remove the user filter:

dataShareManager.findDataShares({
    callback: function callback(dataShares)
    {
        if (dataShares.length > 0)
        {
            dataShare = dataShare[0];
            dataShare.join(joined);
        }
        else
        {
            Utilities.log('No available multiplayer games');
        }
    }
});

To filter out the data shares with the current user already joined use the dataShare.isJoined function:

dataShareManager.findDataShares({
    callback: function callback(dataShares)
    {
        var dataSharesLength = dataShares.length;
        var dataSharesIndex;

        for (dataSharesIndex = 0; dataSharesIndex < dataSharesLength; dataSharesIndex += 1)
        {
            dataShare = dataShare[dataSharesIndex];
            if (!dataShare.isJoined(currentUsername))
            {
                dataShare.join(joined);
                return;
            }
        }
        Utilities.log('No available multiplayer games');
    }
});

Note

The username of the current user can be found with the TurbulenzServices.createUserProfile function.

Public read only and public read and write keys

Keys can be created as read only by the key creator to stop malicious users from overwriting data:

dataShare.set({
        key: 'gamestate',
        value: JSON.stringify(gameState),
        callback: dataShareSetCallback
    });

The dataShare.set function will create the key with public read only access. Once a key has been created using dataShare.set the dataShare.compareAndSet function cannot be used on that key until it is deleted.

To allow any user who can join to the data share write access to the key:

dataShare.compareAndSet({
        key: 'gamestate',
        value: JSON.stringify(gameState),
        callback: dataShareSetCallback
    });

Once a key has been set using dataShare.compareAndSet the dataShare.set function cannot be used on that key until it is deleted. Compare and set operations will fail if another user has written to the key value since it was last read using dataShare.get.

Limiting the number of players

Currently, the number of players that can join a data share has to be limited client-side. This can be achieved by using the dataShare.users property.

function joinedDataShare(success)
{
    if (success)
    {
        currentDataShare = dataShare;
        if (currentDataShare.users.length > maxUsers)
        {
            // only maxUsers players should join a game
            // this is possible if 2 (or more) people click to join a game at the same time
            leaveGame();
            currentDataShare.setJoinable(false);
        }
        ...
    }
}
dataShare.join(joinedDataShare);

Since dataShare.users is only updated when join is called only the last user to join will leave (as the first user to join will not see the last user int the users list and so will see the correct amount of users).

It is also a good idea to check the number of players when starting a game (in-case a player joins and then closes their browser before checking the number of joined players). For a more detailed example see the Tic-tac-toe app.

Tic-tac-toe

The SDK contains a Tic-tac-toe app which shows how to use data share objects combined with instant notifications with some simple game and lobby logic. This includes code for limiting the number of players that can join the game. Read the instructions for logging in multiple accounts in order to play.

23.18.3. Constructor

23.18.3.1. create

Summary

Creates a DataShareManager object.

Syntax

var dataShareManager = DataShareManager.create(requestHandler, gameSession, defaultErrorCallbackFn);
requestHandler
A RequestHandler object.
gameSession
A GameSession object.
defaultErrorCallbackFn (Optional)
The default error callback function that is called for any DataShareManager functions that do not specify their own error callback function.

Returns a DataShareManager object or if the Turbulenz Services are unavailable returns null.

23.18.4. Methods

23.18.4.1. createDataShare

Summary

Create a DataShare object.

Syntax

function dataShareCreated(dataShare) {}
dataShareManager.createDataShare(dataShareCreated, errorCallback);
dataShareCreated
A JavaScript function. A callback function called asynchronously with the created DataShare object.

errorCallback (Optional)

The current user owns the returned dataShare object and is automatically joined to it. Note that the user’s game can remain joined to a data share even while the user is off-line. The game should still call dataShare.leave once it has stopped using the data share object.

For an example using this function see creating datashares.

23.18.4.2. findDataShares

Summary

Create a DataShare object.

Syntax

function dataSharesFound(dataShares) {}
var dataShare = dataShareManager.findDataShares({
        user: 'bob',
        callback: dataSharesFound,
        errorCallback: errorCallback
    });
user (Optional)
A JavaScript string. Find only data shares with the username user joined.
friendsOnly (Optional)
A JavaScript boolean. Find only data shares with the current user’s friends joined. This flag is ignored if the user property is also set. This flag is currently ignored (so returns all users) on the Local and Hub as they do not yet support friends.
callback
A JavaScript function. Returns a list of the first 64 joinable DataShare objects matching the search sorted by most recently created. This list can contain data shares that the current user has already joined. Joined data shares can be filtered out with the dataShare.isJoined function.

errorCallback (Optional)

The user must be joined to the data share before calling getKeys, get, set or compareAndSet functions. When calling createDataShare the current user is joined automatically.

For examples using this function see finding and joining data shares.

23.19. The DataShare Object

A data share object can be created with a call to DataShareManager.createDataShare. Other users data share objects can be retrieved with a call to DataShareManager.findDataShares.

23.19.1. Methods

23.19.1.1. join

Summary

Join the DataShare.

Syntax

function dataShareJoined(success) {}
dataShare.join(dataShareJoined, errorCallback);
dataShareJoined (Optional)

A JavaScript function. Callback function, called asynchronously once the joined to the dataShare object. Called with the following properties:

success
A JavaScript boolean. True, if the current player successfully joined the data share. False, if the data share is not joinable.

errorCallback (Optional)

The user must be joined to the data share before calling getKeys, get, set or compareAndSet functions. Once the game has finished using a dataShare object it must call dataShare.leave.

The dataShare.users property is updated on a successful join operation.

Note

Calling dataShareManager.createDataShare automatically joins the user to the created data share.

Note

The dataShare.users property is updated atomically. This means that the users property always lists the users in the order that they joined and that any other users who join after the current user will not be listed.

23.19.1.2. leave

Summary

Leave the DataShare.

Syntax

function dataShareLeaveCallback() {}
dataShare.leave(dataShareLeaveCallback, errorCallback);
dataShareLeaveCallback (Optional)
A JavaScript function. Callback function, called asynchronously once the user is removed from the dataShare object.

errorCallback (Optional)

Once the game has finished using a dataShare object it must call dataShare.leave. Once all joined players leave a dataShare object it will be deleted (so there is no need to manually delete the keys).

After calling dataShare.leave the dataShare object should not be used again.

Note

The owner of the dataShare object is joined automatically when they call DataShareManager.createDataShare but dataShare.leave should still be called once the owner has finished with the dataShare.

23.19.1.3. setJoinable

Summary

Allow other players to join the data share.

Syntax

function setJoinableCallback() {}
dataShare.setJoinable(joinable, setJoinableCallback, errorCallback);
joinable
A JavaScript boolean. Set the joinable flag to this value.
setJoinableCallback (Optional)
A JavaScript function. Callback function, called asynchronously once the user is removed from the dataShare object.

errorCallback (Optional)

Allow other players to join the data share. On creation of the data share this flag is set to true.

When this flag is set to false, other users will not be able to find this data share (with the exception of users who are already joined to this data share). This can be used, for example, to stop new players from joining after the maximum number of players have joined.

23.19.1.4. getKeys

Summary

Find all of the keys set for the DataShare key-value store.

Syntax

function dataShareGetKeysCallback(stores) {}
dataShare.getKeys(dataShareGetKeysCallback, errorCallback);
dataShareGetKeysCallback

A JavaScript function. Callback function, called asynchronously with the key summary data from the dataShare object. Called with the first 64 key stores which an list of summary data objects with the following properties:

ownedBy
A JavaScript string. The username of the first user to set the data for key key. This is reset when the key is removed.
access
Either DataShare.publicReadOnly or DataShare.publicReadAndWrite. The write access for key key.

Note that, to save bandwidth and memory, it does not contain value for any of the keys.

errorCallback (Optional)

Note

The user must be joined to the data share before calling getKeys.

23.19.1.5. get

Summary

Get a value from the DataShare key-value store.

Syntax

function dataShareGetCallback(store) {}
dataShare.get(key, dataShareGetCallback, errorCallback);
key
A JavaScript string. The key to get in the data share key-value store.
dataShareGetCallback

A JavaScript function. Callback function, called asynchronously with the data from the dataShare object. Called with store which is either null if no value has been set or an object with the following properties:

ownedBy
A JavaScript string. The username of the first user to set the data for key key. This is reset when the key is removed.
value
A JavaScript string. The value stored for key key see set and compareAndSet functions.
access
Either DataShare.publicReadOnly or DataShare.publicReadAndWrite. The write access for key key.

errorCallback (Optional)

Note

The user must be joined to the data share before calling get.

23.19.1.6. set

Summary

Set a public read only value in the DataShare key-value store.

Syntax

function dataShareSetCallback(wasSet, reason) {}
dataShare.set({
        key: 'apples',
        value: '3',
        callback: dataShareSetCallback,
        errorCallback: errorCallback
    });
key
A JavaScript string. The key to set in the data share key-value store.
value
A JavaScript string. The value to set for key key. Setting value to an empty string will delete the key-value.
dataShareSetCallback (Optional)

A JavaScript function. Callback function, called asynchronously with:

wasSet
A JavaScript boolean. True, if the data was successfully set. False otherwise, the reason it could not be set is specified in reason.
reason
A reason string from DataShare.notSetReason or undefined if wasSet is true.

errorCallback (Optional)

Note

The user must be joined to the data share before calling set.

Note

DataShare.compareAndSet can only be used on keys with public read only access values. For more information see the datashare access example.

23.19.1.7. compareAndSet

Summary

Set a public read and write value in the DataShare key-value store if it has not been set by another user since the last dataShare.get request for the same key.

Syntax

function dataShareSetCallback(wasSet, reason) {}
dataShare.compareAndSet({
        key: 'apples',
        value: '3',
        callback: dataShareSetCallback,
        errorCallback: errorCallback
    });

// example callback usage:
function dataShareSetCallback(wasSet, reason)
{
    if (!wasSet && reason === DataShare.notSetReason.changed)
    {
        // unable to set key because it has changed since the last dataShare.get('apples') request
    }
}
key
A JavaScript string. The key to set in the data share key-value store.
value
A JavaScript string. The value to set for key key. Setting value to an empty string will delete the key-value.
dataShareSetCallback (Optional)

A JavaScript function. Callback function, called asynchronously with:

wasSet
A JavaScript boolean. True, if the data was successfully set. False otherwise, the reason it could not be set is specified in reason.
reason
A reason string from DataShare.notSetReason or undefined if wasSet is true.

errorCallback (Optional)

The reason argument will return DataShare.notSetReason.changed if the key has been set by another user since the key was last read with dataShare.get.

Note

The user must be joined to the data share before calling DataShare.compareAndSet.

Note

DataShare.compareAndSet can only be used on keys with public read and write access values. For more information see the datashare access example.

23.19.1.8. isJoined

Summary

Check if a user is joined to the data share.

Syntax

dataShare.isJoined(username);
username
A JavaScript string. The username to check.

Returns a JavaScript boolean. Useful to filter out data shares that the current user is already joined to. See the finding data shares example.

23.19.2. Properties

23.19.2.1. id

Summary

A globally unique id for this data share (this is the same for all users).

Syntax

var id = dataShare.id;

A JavaScript string. Useful when sending notifications (see NotificationsManager) so the receiving user knows which data share the notification is about.

Note

This property is read only.

23.19.2.2. publicReadOnly

Summary

Public read only flag returned by dataShare.get and dataShare.getKeys functions.

Syntax

var publicReadOnly = DataShare.publicReadOnly;

To set a key with DataShare.publicReadOnly access use the dataShare.set function. The dataShare.compareAndSet function cannot be used on DataShare.publicReadOnly keys.

A JavaScript number.

Note

This property is read only.

23.19.2.3. publicReadAndWrite

Summary

Public read and write flag returned by dataShare.get and dataShare.getKeys functions.

Syntax

var publicReadAndWrite = DataShare.publicReadAndWrite;

To set a key with DataShare.publicReadAndWrite access use the dataShare.compareAndSet function. The dataShare.set function cannot be used on DataShare.publicReadAndWrite keys.

A JavaScript number.

Note

This property is read only.

23.19.2.4. notSetReason

Summary

A dictionary of reasons why a set or compareAndSet operation could not be achieved.

Syntax

var notSetReason = DataShare.notSetReason;

// example usage:
function dataShareSetCallback(wasSet, reason)
{
    if (!wasSet && reason === DataShare.notSetReason.changed)
    {
        // unable to set key because it has changed since the last dataShare.get('apples') request
    }
}
dataShare.compareAndSet({
        key: 'apples',
        value: '3',
        callback: dataShareSetCallback,
        errorCallback: errorCallback
    });
// or
dataShare.set({
        key: 'apples',
        value: '3',
        callback: dataShareSetCallback,
        errorCallback: errorCallback
    });

The notSetReason properties are:

changed
The key could not be set for the compareAndSet function because it has changed since the last get request for the same key.
readOnly

The key could not be set as it is read only. When publicReadOnly access is set:

readAndWrite
When publicReadAndWrite access is set only the dataShare.compareAndSet function can be used to set the key value (dataShare.set cannot be used).

Note

This property is read only.

23.19.2.5. created

Summary

The UTC time since epoch in seconds that the data share was created.

Syntax

var created = dataShare.created;

A JavaScript number.

Note

This property is read only.

23.19.2.6. owner

Summary

The username of the creator of the data share.

Syntax

var owner = dataShare.owner;

A JavaScript string.

Note

This property is read only.

23.19.2.7. users

Summary

A list of user’s usernames joined to the data share.

Syntax

var users = dataShare.users;
var username = users[0];

A JavaScript array of strings. This list is in order of joining with the first to join the datashare (normally the owner if they have not left the datashare) at index 0 and the last user to join the datashare at the end.

Note

This property is only updated on calls to dataShareManager.createDataShare, dataShareManager.findDataShares and dataShare.join.

Note

This property is read only.

23.19.2.8. joinable

Summary

True, if a data share can be joined. False, otherwise.

Syntax

var joinable = dataShare.joinable;

A JavaScript boolean. See setJoinable to set this property. If false, then the dataShare object will not be returned by DataShareManager.findDataShares if the current user is not joined to the data share.

Note

This property is read only.

23.19.3. Error callback

If no error callback is given then the DataShareManager.create errorCallbackFn is used.

Summary

A JavaScript function. Returns an error message and its HTTP status.

Syntax

function errorCallbackFn(errorMsg, httpStatus, calledByFn, calledByParams) {}
errorMsg
A JavaScript string. The error message.
httpStatus
A JavaScript number. You can find a list of common status codes here - http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
calledByFn
A JavaScript function. The function that threw the error.
calledByParams
A JavaScript array of the parameters given to the function that threw the error.