23.17. The GameProfileManager Object
23.20. The NotificationsManager Object
Enter search terms or a module, class or function name.
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") }}*/
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.
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.
Summary
Creates a DataShareManager object.
Syntax
var dataShareManager = DataShareManager.create(requestHandler, gameSession, defaultErrorCallbackFn);
Returns a DataShareManager object or if the Turbulenz Services are unavailable returns null.
Summary
Create a DataShare object.
Syntax
function dataShareCreated(dataShare) {}
dataShareManager.createDataShare(dataShareCreated, errorCallback);
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.
Summary
Create a DataShare object.
Syntax
function dataSharesFound(dataShares) {}
var dataShare = dataShareManager.findDataShares({
user: 'bob',
callback: dataSharesFound,
errorCallback: errorCallback
});
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.
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.
Summary
Join the DataShare.
Syntax
function dataShareJoined(success) {}
dataShare.join(dataShareJoined, errorCallback);
A JavaScript function. Callback function, called asynchronously once the joined to the dataShare object. Called with the following properties:
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.
Summary
Leave the DataShare.
Syntax
function dataShareLeaveCallback() {}
dataShare.leave(dataShareLeaveCallback, errorCallback);
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.
Summary
Allow other players to join the data share.
Syntax
function setJoinableCallback() {}
dataShare.setJoinable(joinable, setJoinableCallback, errorCallback);
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.
Summary
Find all of the keys set for the DataShare key-value store.
Syntax
function dataShareGetKeysCallback(stores) {}
dataShare.getKeys(dataShareGetKeysCallback, errorCallback);
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:
Note that, to save bandwidth and memory, it does not contain value for any of the keys.
errorCallback (Optional)
Summary
Get a value from the DataShare key-value store.
Syntax
function dataShareGetCallback(store) {}
dataShare.get(key, dataShareGetCallback, errorCallback);
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:
errorCallback (Optional)
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
});
A JavaScript function. Callback function, called asynchronously with:
errorCallback (Optional)
Note
DataShare.compareAndSet can only be used on keys with public read only access values. For more information see the datashare access example.
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
}
}
A JavaScript function. Callback function, called asynchronously with:
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.
Summary
Check if a user is joined to the data share.
Syntax
dataShare.isJoined(username);
Returns a JavaScript boolean. Useful to filter out data shares that the current user is already joined to. See the finding data shares example.
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.
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.
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.
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:
The key could not be set as it is read only. When publicReadOnly access is set:
Note
This property is read only.
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.
Summary
The username of the creator of the data share.
Syntax
var owner = dataShare.owner;
A JavaScript string.
Note
This property is read only.
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.
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.
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) {}