save data (safely) with logic checking on server side
u
urseg ames
started a topic
about 8 years ago
Hello, I'm beginner on GameSparks. I have a few questions:
I need to save some data from my game and get them (I use Unity3D) and how can I do it safely (cheaters protecting).
Where I can create a Collection in the Runtime area or Metadata area?
How can I add value from collection A with value from collection B (from Cloud Code) and save it all to collection C.
How can I (from Unity) safely and correctly do Insert, Update, Delete any data in right collection?
Thanks!
Best Answer
C
Customer Support
said
about 8 years ago
Hello!
So to store information in a collection, you do so in an event in Cloud Code. In all cases we should use the playerId which is unique to each player and therefore should only return one document when queried. I'll run through the entire flow and add an example bit about adding from multiple documents into another document at the bottom.
On RegistrationResponse you can create a document for each player:
//Creates or finds a collection
var playerSavesCollection = Spark.runtimeCollection("playerSaves");
//A Javascript Object containing player information, we'll use this information to search for and update a player's save
var entry = {"playerId" : Spark.getPlayer().getPlayerId()};
//Inserts a document into a collection and returns true or false if the document insertion worked or not
var success = playerSavesCollection.insert(entry);
Then when we want to update the player's information we can create a custom event that accepts a JSON attribute, in this example we'll name it "JSONData" and in it's cloud code we can write:
//Finds our "playerSaves" collection
var playerSavesCollection = Spark.runtimeCollection("playerSaves");
//Finds the document with our player's Id
var playerSave = playerSavesCollection.findOne({"playerId" : Spark.getPlayer().getPlayerId()});
//This gets the JSONData attribute we are passing in
var JSONData = Spark.data.JSONData;
//Overwrite our playerSave with the data we are sending
playerSave = JSONData;
//Re-apply our user's I'd (it just got overwritten)
playerSave.playerId = Spark.getPlayer().getPlayerId();
// Update the document in our collection that contains our playerId with the current playerState
var success = playerSavesCollection.update({"playerId" : Spark.getPlayer().getPlayerId()}, playerSave);
//This will print the information in the response on the TestHarness and send it in the response in Unity.
Spark.setScriptData("playerState", playerSavesCollection.findOne({"playerId" : Spark.getPlayer().getPlayerId()}));
Then to update that information from Unity you need to do a few things:
using GameSparks.Core;
using GameSparks.Api.Requests:;
//We create a GSRequestData variable
//by using jsonDataToSend.Add() we can add in any variable we choose
//and they will be converted to JSON
GSRequestData jsonDataToSend = new GSRequestData();
jsonDataToSend.Add("health", playerHealth);
jsonDataToSend.Add("strength", playerStrength);
jsonDataToSend.AddString("name", playerName);
jsonDataToSend.Add("playerPos", transform.position);
//We then send our LogEventRequest with the event shortcode and the event attrirbute
new LogEventRequest().SetEventKey("setPlayerDataJSON")
.SetEventAttribute("JSONData", jsonDataToSend)
.Send((response) =>
{
});
This should send the data to GameSparks, the Cloud Code will interpret the data and save it to the document of the player stored in our collection.
To get that data back again, we need to create another custom event, we'll have this event take an attribute of "playerId":
//You use this to get any other player's current state
//This finds the runtimeCollection in which all the playerState documents are stored
var playerSavesCollection = Spark.runtimeCollection("playerSaves");
//This will find a particular user's state via the player Id we pass in
var playerSaves= playerSavesCollection .findOne({"playerId" : Spark.data.userId});
//This will set the information to ScriptData so it's easily readable in Unity or the Test Harness
Spark.setScriptData("playerState", playerSaves);
If you run that in the test harness it should come back with the user's save.
Do retrieve it in Unity use the following:
//Send our logEventRequest to retrive information from the collection
new LogEventRequest().SetEventKey("getPlayerData").SetEventAttribute("userId", userId).Send((getPlayerStateResponse) =>
{
if (getPlayerStateResponse.HasErrors)
{
Debug.Log(getPlayerStateResponse.Errors);
}
else
{
//Assign the variables from our document to our instance
playerHealth = getPlayerStateResponse.ScriptData.GetObject("playerState").GetNumber("health").ToString();
playerStrength = getPlayerStateResponse.ScriptData.GetObject("playerState").GetNumber("strength").ToString();
playerName = getPlayerStateResponse.ScriptData.GetObject("playerState").GetString("name");
playerPos = getPlayerStateResponse.ScriptData.GetObject("playerState").GetString("playerPos");
}
});
To get values from multiple collections and save them to another you could do something like:
var player1Save = playerSavesCollection.findOne({"player1Id" : Spark.data.userId});
var player2Save = playerSavesCollection.findOne({"player2Id" : Spark.data.userId});
var playerGroup = playerGroupsCollection.findOne({"playerGroupId" : Spark.data.groupId});
var combinedPlayersStrength = player1Save.strength + player2Save.strength;
playerGroup.strength = combinedPlayersStrength;
var success = playerGroupCollection.update({"groupId" : Spark.data.groupId}, playerGroup);
So to store information in a collection, you do so in an event in Cloud Code. In all cases we should use the playerId which is unique to each player and therefore should only return one document when queried. I'll run through the entire flow and add an example bit about adding from multiple documents into another document at the bottom.
On RegistrationResponse you can create a document for each player:
//Creates or finds a collection
var playerSavesCollection = Spark.runtimeCollection("playerSaves");
//A Javascript Object containing player information, we'll use this information to search for and update a player's save
var entry = {"playerId" : Spark.getPlayer().getPlayerId()};
//Inserts a document into a collection and returns true or false if the document insertion worked or not
var success = playerSavesCollection.insert(entry);
Then when we want to update the player's information we can create a custom event that accepts a JSON attribute, in this example we'll name it "JSONData" and in it's cloud code we can write:
//Finds our "playerSaves" collection
var playerSavesCollection = Spark.runtimeCollection("playerSaves");
//Finds the document with our player's Id
var playerSave = playerSavesCollection.findOne({"playerId" : Spark.getPlayer().getPlayerId()});
//This gets the JSONData attribute we are passing in
var JSONData = Spark.data.JSONData;
//Overwrite our playerSave with the data we are sending
playerSave = JSONData;
//Re-apply our user's I'd (it just got overwritten)
playerSave.playerId = Spark.getPlayer().getPlayerId();
// Update the document in our collection that contains our playerId with the current playerState
var success = playerSavesCollection.update({"playerId" : Spark.getPlayer().getPlayerId()}, playerSave);
//This will print the information in the response on the TestHarness and send it in the response in Unity.
Spark.setScriptData("playerState", playerSavesCollection.findOne({"playerId" : Spark.getPlayer().getPlayerId()}));
Then to update that information from Unity you need to do a few things:
using GameSparks.Core;
using GameSparks.Api.Requests:;
//We create a GSRequestData variable
//by using jsonDataToSend.Add() we can add in any variable we choose
//and they will be converted to JSON
GSRequestData jsonDataToSend = new GSRequestData();
jsonDataToSend.Add("health", playerHealth);
jsonDataToSend.Add("strength", playerStrength);
jsonDataToSend.AddString("name", playerName);
jsonDataToSend.Add("playerPos", transform.position);
//We then send our LogEventRequest with the event shortcode and the event attrirbute
new LogEventRequest().SetEventKey("setPlayerDataJSON")
.SetEventAttribute("JSONData", jsonDataToSend)
.Send((response) =>
{
});
This should send the data to GameSparks, the Cloud Code will interpret the data and save it to the document of the player stored in our collection.
To get that data back again, we need to create another custom event, we'll have this event take an attribute of "playerId":
//You use this to get any other player's current state
//This finds the runtimeCollection in which all the playerState documents are stored
var playerSavesCollection = Spark.runtimeCollection("playerSaves");
//This will find a particular user's state via the player Id we pass in
var playerSaves= playerSavesCollection .findOne({"playerId" : Spark.data.userId});
//This will set the information to ScriptData so it's easily readable in Unity or the Test Harness
Spark.setScriptData("playerState", playerSaves);
If you run that in the test harness it should come back with the user's save.
Do retrieve it in Unity use the following:
//Send our logEventRequest to retrive information from the collection
new LogEventRequest().SetEventKey("getPlayerData").SetEventAttribute("userId", userId).Send((getPlayerStateResponse) =>
{
if (getPlayerStateResponse.HasErrors)
{
Debug.Log(getPlayerStateResponse.Errors);
}
else
{
//Assign the variables from our document to our instance
playerHealth = getPlayerStateResponse.ScriptData.GetObject("playerState").GetNumber("health").ToString();
playerStrength = getPlayerStateResponse.ScriptData.GetObject("playerState").GetNumber("strength").ToString();
playerName = getPlayerStateResponse.ScriptData.GetObject("playerState").GetString("name");
playerPos = getPlayerStateResponse.ScriptData.GetObject("playerState").GetString("playerPos");
}
});
To get values from multiple collections and save them to another you could do something like:
var player1Save = playerSavesCollection.findOne({"player1Id" : Spark.data.userId});
var player2Save = playerSavesCollection.findOne({"player2Id" : Spark.data.userId});
var playerGroup = playerGroupsCollection.findOne({"playerGroupId" : Spark.data.groupId});
var combinedPlayersStrength = player1Save.strength + player2Save.strength;
playerGroup.strength = combinedPlayersStrength;
var success = playerGroupCollection.update({"groupId" : Spark.data.groupId}, playerGroup);
...if you want to retrieve playerHealth from a received array of player?
Customer Support
said
about 8 years ago
Hi Gabriel,
If you are getting playerHealth from an array on the player you need to get a bit more specific and use GetDoubleList, GetIntList or GetFloatList. So if you were storing playerHealth, playerStrength, playerDefense etc in an array called "playerStats" = [100, 15, 12] respectively it would be:
If you have any more questions please fire away, if you have any examples of what you're trying to do, please post them as well, it helps us a lot.
Shane
K
Khen Prel
said
about 8 years ago
Hello I follow this tutorial as best as I could and I am unable to get a working result. Was wondering what I could have done wrong.
In Unity I send a ReqistrationRequest to create a new player. In my cloud code on RegistrationResponse I included the code you provided. I check my NoSQL and I was not able to find the document "playerSaves". I even tried to move the code to ReistrationRequest since I thought it should fired that event automatically since I am sending a RegistrationRequest but unfortunately that didn't work either.
Customer Support
said
about 8 years ago
Hi Khen,
Try using
var success = playerSavesCollection.save(entry);
and if that doesn't work can you paste your code? If it would help you could add me to your GameSparks game as a collaborator from the overview panel, this will allow me to check your code from the Portal.
Let me know how it goes,
Shane
K
Khen Prel
said
about 8 years ago
Hi Shane thank you for the reply. I eventually solve this on my own by simply ticking of debug mode in unity. I always get a "unkown" event key response back from gamespark even when working of the test harness. Then I tried working on the preview snap shot it works as intended. I don't know if I'm doing things correctly or not but nothing work for me on LIVE configuration.
G
Gonçalo Abreu
said
over 6 years ago
Sorry for the dig up, but I found this topic really useful!
I'm getting an error thought, here is the output
WebSocket onMessage: {"@class":".GameSparksErrorResponse","error":{"message":"TypeError: Cannot set property \"playerId\" of undefined to \"573874891474e704c7c68562\" (298828-event-GSAV#20)"},"message":"TypeError: Cannot set property \"playerId\" of undefined to \"573874891474e704c7c68562\" (298828-event-GSAV#20)","requestId":"1463317640768_2"}
S
Saad Anees
said
about 6 years ago
Hello,
I have followed the tutorial but couldn't update my runtime collection. I tested it in testharness. I am just modifying playerID. Need help.
urseg ames
Hello, I'm beginner on GameSparks.
I have a few questions:
I need to save some data from my game and get them (I use Unity3D) and how can I do it safely (cheaters protecting).
Where I can create a Collection in the Runtime area or Metadata area?
How can I add value from collection A with value from collection B (from Cloud Code) and save it all to collection C.
How can I (from Unity) safely and correctly do Insert, Update, Delete any data in right collection?
Thanks!
Hello!
So to store information in a collection, you do so in an event in Cloud Code. In all cases we should use the playerId which is unique to each player and therefore should only return one document when queried. I'll run through the entire flow and add an example bit about adding from multiple documents into another document at the bottom.
On RegistrationResponse you can create a document for each player:
Then when we want to update the player's information we can create a custom event that accepts a JSON attribute, in this example we'll name it "JSONData" and in it's cloud code we can write:
Then to update that information from Unity you need to do a few things:
This should send the data to GameSparks, the Cloud Code will interpret the data and save it to the document of the player stored in our collection.
To get that data back again, we need to create another custom event, we'll have this event take an attribute of "playerId":
If you run that in the test harness it should come back with the user's save.
Do retrieve it in Unity use the following:
To get values from multiple collections and save them to another you could do something like:
Hope this helps!
Shane
2 people have this question
- Oldest First
- Popular
- Newest First
Sorted by Oldest FirstCustomer Support
Hello!
So to store information in a collection, you do so in an event in Cloud Code. In all cases we should use the playerId which is unique to each player and therefore should only return one document when queried. I'll run through the entire flow and add an example bit about adding from multiple documents into another document at the bottom.
On RegistrationResponse you can create a document for each player:
Then when we want to update the player's information we can create a custom event that accepts a JSON attribute, in this example we'll name it "JSONData" and in it's cloud code we can write:
Then to update that information from Unity you need to do a few things:
This should send the data to GameSparks, the Cloud Code will interpret the data and save it to the document of the player stored in our collection.
To get that data back again, we need to create another custom event, we'll have this event take an attribute of "playerId":
If you run that in the test harness it should come back with the user's save.
Do retrieve it in Unity use the following:
To get values from multiple collections and save them to another you could do something like:
Hope this helps!
Shane
Gabriel Sauve
How would you do ...
...if you want to retrieve playerHealth from a received array of player?
Customer Support
Hi Gabriel,
If you are getting playerHealth from an array on the player you need to get a bit more specific and use GetDoubleList, GetIntList or GetFloatList. So if you were storing playerHealth, playerStrength, playerDefense etc in an array called "playerStats" = [100, 15, 12] respectively it would be:
playerHealth = getPlayerStateResponse.ScriptData.GetObject("players").GetDoubleList("playerStats")[0];
If you are receiving an array of playerObjects it would be:
playerHealth = getPlayerStateResponse.ScriptData.GetObjectList("playerState")[0].GetNumber("health").ToString();
If you have any more questions please fire away, if you have any examples of what you're trying to do, please post them as well, it helps us a lot.
Shane
Khen Prel
Hello I follow this tutorial as best as I could and I am unable to get a working result. Was wondering what I could have done wrong.
In Unity I send a ReqistrationRequest to create a new player. In my cloud code on RegistrationResponse I included the code you provided. I check my NoSQL and I was not able to find the document "playerSaves". I even tried to move the code to ReistrationRequest since I thought it should fired that event automatically since I am sending a RegistrationRequest but unfortunately that didn't work either.
Customer Support
Hi Khen,
Try using
and if that doesn't work can you paste your code? If it would help you could add me to your GameSparks game as a collaborator from the overview panel, this will allow me to check your code from the Portal.
Let me know how it goes,
Shane
Khen Prel
Gonçalo Abreu
Sorry for the dig up, but I found this topic really useful!
I'm getting an error thought, here is the output
Saad Anees
Hello,
I have followed the tutorial but couldn't update my runtime collection. I tested it in testharness. I am just modifying playerID. Need help.
Thanks.
-
Documentation Notes
-
Design issues with user events
-
Using NoSQL
-
Runtime Collections vs Metadata Collections
-
Anonymous authentication from browser app
-
Modules
-
Movement With Unity
-
Problem with url parameters for downloadables
-
Querying NoSql GameSparks database
-
Challenge accesType
See all 2487 topics