I have made a custom collection of players and I use that for most of the operations within my game. All the stats are stored in the custom collection, though I still the system collection for turns and other things automatically managed by GameSparks.
Now it may happen that a user, registered by device, wants to connect Facebook. The user doesn't want to loose all the progress up to that point when switching to Facebook.
I insert a new instance into the custom player list collection in the AuthenticationResponse code. What I am trying to do is to look if the new player is from Facebook and if so copying the statistics from the device registered ID. But I can't see any field in the system collection that links the new Facebook player to the old device registered player.
How can I retrieve informations about the previous user when it's connecting to Facebook?
Best Answer
A
Andrea Marchetti
said
over 5 years ago
I sent a ticket to the support and we found out the problem was that I was deleting the players manually from the noSQL database when I should have used deletePlayer from the Cloud Code. The remedy was to delete all the entries in the externalAuthentication collection so that now when I connect Facebook, the account is merged and linked.
If a user connected by device wants to connect with facebook, your game code will call FacebookConnectRequest. This will automatically link the current "player" with facebook authentication. So there's nothing else to do on your part. You custom collection of players will be linked to the same player.
If you want FacebookConnectRequest to create a new player you'll have to set doNotLinkToCurrentPlayer to true but this is what you want.
The problem is that I can't know what was the old device registered account of the new Facebook player... I needed because the custom collection is not linked. Why do you say that is linked even in the custom collection?
This is my code in the AuthenticationResponse for inserting a new player into my custom collection:
I need a way to figure out if the new player is coming from a device registered account. If so, then I can upload the player data as 'Facebook connected' instead to insert a new player into the runtime collection.
C
Christian Gauthier
said
over 5 years ago
Here's what you can do if you don't mind hitting the db each time a user is connecting.
var player = Spark.getPlayer();
var playerId = player.getPlayerId();
var fbID = player.getExternalIds().FB;
//Only fetching the customPlayer.facebookId to make it as ligthweight as possible
var customPlayer = Spark.runtimeCollection("playersList").findOne({"playerId":playerId}, {"facebookId":true});
if (customPlayer !== null) {
if (fbID !== undefined && customPlayer.facebookId !== fbID){
Spark.runtimeCollection("playersList").update({"playerId": playerId},
{$set:{"isFacebookConnected":true, "facebookId":fbID, "playerName":player.getDisplayName()}},
false, false);
}
}
else {
var isFB = fbID != undefined;
var name = isFB ? player.getDisplayName() : randomNames[Math.floor(Math.random()*randomNames.length)];
Spark.runtimeCollection("playersList").insert( {
"playerId" : playerId,
"isFacebookConnected" : isFB,
"facebookId" : fbID,
"playerName" : name,
"bio" : randomBios[Math.floor(Math.random()*randomBios.length)],
"avatarIndex" : 0 ,
"level" : 0,
"totalSquarcuits" : 0,
"totalWon" : 0,
"totalLost" : 0
} );
If you mind hitting the DB each time, i'll tell you how but it's less elegant :)
A
Andrea Marchetti
said
over 5 years ago
I have some problems understanding your code.
The point is that with a new Facebook authentication the system will provide a different 'playerId' than the previous device registered user. So this will always fall into the 'else' code for a new player and it will insert the user normally.
It will fall in the 'if' code only when the player is not new, but in that case there would be nothing to update.
Am I wrong?
PS: Thanks for the Javascript syntax lesson.
C
Christian Gauthier
said
over 5 years ago
That's were you are wrong, if the user is already authenticated (in your case by device id) and your game code calls FacebookConnectRequest GS will simply link the currently authenticated player to facebook then your cloud code will be called and you will be able to update the facebook info into playersList.
As for the JS code your welcome :)
but I made a small mistake:
var isFB = fbID != undefined;
should have been
var isFB = fbID !== undefined;
doc:
If the current player has previously created an account using either DeviceAuthenticationRequest or RegistrationRequest AND the Facebook user is not already registered with the game, the Facebook user will be linked to the current player.
A
Andrea Marchetti
said
over 5 years ago
But in the system collection the ID is different from the device registered user.
This is what I tried:
1- Registered with DeviceAuthenticationRequest a new player.
2- Connected to Facebook using FacebookConnectRequest from the device registered player.
maybe doNotLinkToCurrentPlayer default is not false as specified in the doc, set it explicitly to false
I don't know
1 person likes this
A
Andrea Marchetti
said
over 5 years ago
I did set it explicitly to false and it still doesn't work. I think I'm going to submit a ticket for this.
What should be the correct behaviour? There should be two entries in the system collection, one for the device and one for Facebook, but they both should have the same external ID?
A
Andrea Marchetti
said
over 5 years ago
Answer
I sent a ticket to the support and we found out the problem was that I was deleting the players manually from the noSQL database when I should have used deletePlayer from the Cloud Code. The remedy was to delete all the entries in the externalAuthentication collection so that now when I connect Facebook, the account is merged and linked.
Now I can use your code, Christian. Thanks.
A
Andrea Marchetti
said
over 5 years ago
I did use your code but I think this code is correct *, because otherwise you would look only for those players who are already connected to Facebook. And most of the times the users are trying to connect for the first time to Facebook from their Device Account.
//Only fetching the customPlayer.facebookId to make it as ligthweight as possible
var customPlayer = Spark.runtimeCollection("playersList").findOne({"playerId":playerId}, {"isFacebookConnected": true); // WRONG.
// CORRECT.
var customPlayer = Spark.runtimeCollection("playersList").findOne({"playerId":playerId});
C
Christian Gauthier
said
over 5 years ago
Hi Andrea,
Happy to see that's its working fine now.
As for the wrong code you misinterpreted the parameters, The second parameter of the findOne function is to specify the projected fields not the query.
so this code is correct:
var customPlayer = Spark.runtimeCollection("playersList").findOne({"playerId":playerId}, {"facebookId":true});
like I said in my comment, by specifying the projected field, mongodb will return an object with only two fields (oid and facebookId) instead of the full object. This is what we want because we only use customPlayer .facebookId in the code. But don't worry about that, it's an optimization that will maybe be usefull once you have 100000 users :)
Andrea Marchetti
I have made a custom collection of players and I use that for most of the operations within my game. All the stats are stored in the custom collection, though I still the system collection for turns and other things automatically managed by GameSparks.
Now it may happen that a user, registered by device, wants to connect Facebook. The user doesn't want to loose all the progress up to that point when switching to Facebook.
I insert a new instance into the custom player list collection in the AuthenticationResponse code. What I am trying to do is to look if the new player is from Facebook and if so copying the statistics from the device registered ID. But I can't see any field in the system collection that links the new Facebook player to the old device registered player.
How can I retrieve informations about the previous user when it's connecting to Facebook?
I sent a ticket to the support and we found out the problem was that I was deleting the players manually from the noSQL database when I should have used deletePlayer from the Cloud Code. The remedy was to delete all the entries in the externalAuthentication collection so that now when I connect Facebook, the account is merged and linked.
Now I can use your code, Christian. Thanks.
- Oldest First
- Popular
- Newest First
Sorted by Oldest FirstChristian Gauthier
Hi Andrea,
If a user connected by device wants to connect with facebook, your game code will call FacebookConnectRequest. This will automatically link the current "player" with facebook authentication. So there's nothing else to do on your part. You custom collection of players will be linked to the same player.
If you want FacebookConnectRequest to create a new player you'll have to set doNotLinkToCurrentPlayer to true but this is what you want.
The doc:
https://docs.gamesparks.com/api-documentation/request-api/authentication/facebookconnectrequest.html
Andrea Marchetti
The problem is that I can't know what was the old device registered account of the new Facebook player... I needed because the custom collection is not linked. Why do you say that is linked even in the custom collection?
This is my code in the AuthenticationResponse for inserting a new player into my custom collection:
I need a way to figure out if the new player is coming from a device registered account. If so, then I can upload the player data as 'Facebook connected' instead to insert a new player into the runtime collection.
Christian Gauthier
Here's what you can do if you don't mind hitting the db each time a user is connecting.
If you mind hitting the DB each time, i'll tell you how but it's less elegant :)
Andrea Marchetti
I have some problems understanding your code.
The point is that with a new Facebook authentication the system will provide a different 'playerId' than the previous device registered user. So this will always fall into the 'else' code for a new player and it will insert the user normally.
It will fall in the 'if' code only when the player is not new, but in that case there would be nothing to update.
Am I wrong?
PS: Thanks for the Javascript syntax lesson.
Christian Gauthier
That's were you are wrong, if the user is already authenticated (in your case by device id) and your game code calls FacebookConnectRequest GS will simply link the currently authenticated player to facebook then your cloud code will be called and you will be able to update the facebook info into playersList.
As for the JS code your welcome :)
but I made a small mistake:
var isFB = fbID != undefined;
should have been
var isFB = fbID !== undefined;
doc:
If the current player has previously created an account using either DeviceAuthenticationRequest or RegistrationRequest AND the Facebook user is not already registered with the game, the Facebook user will be linked to the current player.
Andrea Marchetti
But in the system collection the ID is different from the device registered user.
This is what I tried:
1- Registered with DeviceAuthenticationRequest a new player.
2- Connected to Facebook using FacebookConnectRequest from the device registered player.
This is what I have in the database:
- DEVICE ACCOUNT ID: $oid: "595398e92d91abaf5d1644ef"
- FACEBOOK ACCOUNT ID: $oid: "59567e2038c31604f5e2b2b5"
They're different and there are two separate entries, only the field list is different...
Why shouldn't be one entry for both if they are linked? Or a field showing the link?
Christian Gauthier
maybe related to the problem reported here
https://support.gamesparks.net/support/discussions/topics/1000074942
maybe doNotLinkToCurrentPlayer default is not false as specified in the doc, set it explicitly to false
I don't know
1 person likes this
Andrea Marchetti
I did set it explicitly to false and it still doesn't work. I think I'm going to submit a ticket for this.
What should be the correct behaviour? There should be two entries in the system collection, one for the device and one for Facebook, but they both should have the same external ID?
Andrea Marchetti
I sent a ticket to the support and we found out the problem was that I was deleting the players manually from the noSQL database when I should have used deletePlayer from the Cloud Code. The remedy was to delete all the entries in the externalAuthentication collection so that now when I connect Facebook, the account is merged and linked.
Now I can use your code, Christian. Thanks.
Andrea Marchetti
I did use your code but I think this code is correct *, because otherwise you would look only for those players who are already connected to Facebook. And most of the times the users are trying to connect for the first time to Facebook from their Device Account.
Christian Gauthier
Hi Andrea,
Happy to see that's its working fine now.
As for the wrong code you misinterpreted the parameters, The second parameter of the findOne function is to specify the projected fields not the query.
so this code is correct:
var customPlayer = Spark.runtimeCollection("playersList").findOne({"playerId":playerId}, {"facebookId":true});
like I said in my comment, by specifying the projected field, mongodb will return an object with only two fields (oid and facebookId) instead of the full object. This is what we want because we only use customPlayer .facebookId in the code. But don't worry about that, it's an optimization that will maybe be usefull once you have 100000 users :)
-
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