After sign-in, display the sync status of PlayerID that user currently use and provide the function to be able to link with other ID Providers (“IdP”).
Display the sync status of IdP in the game settings menu, and configure the UI so that the user can connect and disconnect with the IdP.
- Checking the Information of IdP Sync status
- IdP Sync
- Handling Account Conflicts with IdP Sync
- IdP Disconnection
Checking the Information of IdP Sync Status
You can use getPlayerInfo()
method of AuthV4 class to see the IdP list synced with the currently logged-in PlayerID. In the game settings screen, make sure to configure the UI to see which IdP is synced, and expose the Phrases to suggest IdP sync.
In the game setting screen, PlayerID of each user should be displayed along with the IdP sync information. Display the PlayerID with the format of CS Code, and with the value of currently logged in user.
Followings are sample codes to get the IdP list synced with the current PlayerID to display the current status.
API Reference: hive.AuthV4.getPlayerInfo
1 2 3 4 5 |
AuthV4.PlayerInfo playerInfo = AuthV4.getPlayerInfo(); foreach (AuthV4.ProviderInfo providerInfo in playerInfo.providerInfoData) { // Synced-Provider data } |
API Reference: AuthV4::getPlayerInfo
1 2 3 4 5 |
// Request the sync status of HIVE SDK AuthV4 for( auto providerInfo : AuthV4::getPlayerInfo().providerInfoData ) { cout<<"ProviderType : "<<ProviderInfo::stringProviderType(providerInfo.second.providerType)<<endl; cout<<"ProviderUserId : "<<providerInfo.second.providerUserId<<endl; } |
API Reference: com.hive.AuthV4.getPlayerInfo
1 2 |
//Search the verified user data AuthV4.PlayerInfo playerInfo = AuthV4.getPlayerInfo(); |
API Reference: HIVEAuthV4:getPlayerInfo
1 2 3 4 5 6 |
HIVEPlayerInfo *playerInfo = [HIVEAuthV4 getPlayerInfo]; for (NSString *providerTypeStr in [playerInfo.providerInfoData allKeys]) { // Synced Provider data HIVEProviderInfo *providerInfo = playerInfo.providerInfoData[providerTypeStr]; } |
Phrases to suggest IdP sync
Language | Text |
---|---|
Korean | 계정 연동을 통해 플레이 데이터를 안전하게 지키세요! |
English | Sync your account to protect your game data! |
Japanese | アカウントを連動してプレイデータを守りましょう! |
Chinese (Simplified) | 绑定账号,保护游戏数据安全吧! |
Chinese (Traditional) | 綁定帳號,保護帳號資料安全! |
French | Synchronise ton compte afin de protéger tes données de jeu ! |
German | Synchronisiere dein Konto, um deine Spieldaten zu schützen! |
Russian | Синхронизируйте аккаунт, чтобы обезопасить игровые данные. |
Spanish | ¡Sincronicen su cuenta para proteger sus datos del juego! |
Portuguese | Sincronize sua conta para proteger seus dados de jogo! |
Indonesian | Hubungkan akunmu untuk mengamankan data game milikmu! |
Malay | Segerakkan akaun kamu untuk melindungi data permainanmu! |
Vietnamese | Vui lòng liên kết tài khoản để bảo vệ an toàn cho dữ liệu game của bạn! |
Thai | ซิงค์บัญชีเพื่อปกป้องข้อมูลเกมของคุณ! |
Italian | Sincronizza il tuo account per proteggere i tuoi dati di gioco. |
Turkish | Oyun verilerini korumak için hesabınızı senkronize ediniz. |
Arabic | زامن حسابك لحماية بيانات اللعبة الخاصة بك! |
IdP Sync
The currently logged-in PlayerID can sync with new IdPs. But when user attempts to sync with the IdP linked with different a PlayerID, an error is occurred. If the sync is successful, check the sync status information and update the sync info UI.
When the IdP that you want to add in the IdP connection is linked to another PlayerID, this is called Account conflict situation. To solve this conflict situation, see Handling account conflicts when working with an IdP.
For IdP integration, call the connect () method with the ProviderType you want to work with as parameters. Followings are sample codes to implement the IdP sync.
API Reference: hive.AuthV4.connect
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// HIVE SDK AuthV4 Connect (Sync) callback handler public void onAuthV4Connect(ResultAPI result, AuthV4.PlayerInfo conflictPlayer) { if (result.isSuccess() == true) { // Success to sync } else if (result.errorCode == ResultAPI.CONFLICT_PLAYER) { // Account conflict // showConflictSelection or selectConflict } else { // Failed to sync } } // HIVE SDK AuthV4 Connect (Sync) callback handler AuthV4.connect(AuthV4.ProviderType.HIVE, onAuthV4Connect); |
API Reference: AuthV4::connect
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Request to sync with HIVE SDK AuthV4 AuthV4::connect(ProviderType::HIVE, [=](ResultAPI const & result, PlayerInfo const & conflictPlayer) { // Result callback if (result.isSuccess()) { // Success to sync } else if (result.getErrorCode() == ResultAPI::CONFLICT_PLAYER && conflictPlayer.playerId > 0) { // Account conflict // TODO : Let user select one based on the PlayerId of conflicted account } else { // Failed to sync // TODO : Error Handling } }); |
API Reference: com.hive.AuthV4.connect
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
AuthV4.connect(providerType, new AuthV4.AuthV4ConnectListener() { @Override public void onAuthV4Connect(ResultAPI result, AuthV4.PlayerInfo conflictPlayer) { if (result.isSuccess) { //Success to sync } else if(result.errorCode == ResultAPI.CONFLICT_PLAYER && conflictPlayer != null) { //Account conflict //currentPlayerInfo = AuthV4.getPlayerInfo(); //conflictPlayerInfo = conflictPlayer; //showConflictSelection() or selectConflict() } else { //Failed to sync } } }); |
API Reference: HIVEAuthV4:connect
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Request to sync with HIVE SDK AuthV4 [HIVEAuthV4 connect:kHIVEProviderTypeHIVE handler:^(HIVEResultAPI *result, HIVEPlayerInfo *conflictPlayer) { Loggerd(@"HIVEAuthV4.connect:handler:\nresult = %@\nconflictPlayer = %@", result, conflictPlayer); if (result.isSuccess) { // Success to sync } else if (result.errorCode == kHIVEResultAPITypeCONFLICT_PLAYER) { // Account conflict // showConflictSelection or selectConflict } else { // Failed to sync } }]; |
Handling Account Conflicts with IdP Sync
If the IdP account which the user tries to sync with is already connected to another PlayerID when calling connect()
method, an account conflict occurs and returns the playerID of the account that conflicted with a conflict error. In the following description, the currently logged-in account is called CurrentPlayer, and the account with the conflict is called ConflictPlayer.
When the account conflict occurs, you need to expose the ConflictPlayer’s game information to the user and provide a UI to select ConflictPlayer. You can use the UI provided by HIVE SDK or customize it in game for the account selection UI. If you customize the UI, see Customizing for IdP Conflicts.
To use the UI provided by HIVE SDK, configure the information of ConflictPlayer to match with the game and call the showConflictSelection()
method with ConflictPlayer data as a parameter. User can change the account with ConflictPlayer or cancel the sync without data change to keep playing the game.
Notes on Account Selection
Composition of Game Data
ConflictPlayer data is composed of two essential keys, player_id
and game_data
.
-
player_id
: PlayerID of ConflictPlayergame_data
: Organize the game data such as character name, the amount of game money, and level asMap<String, Object >
format
Following is a sample code to compose the data of ConflictPlayer.
1 |
{"player_id":123, "game_data":{"Name":"ConflictPlayer", "Level":52}} |
Implementing Account-selecting UI from HIVE SDK
Once you completed to configure the ConflictPlayer data, the showConflictSelection () method is called to expose the UI provided by the SDK and the user’s choice will be returned as a result. If the result is successful and the user selects the ConflictPlayer, then you need to load the game data again. The result returns failure when user cancels or fails to select an account, and in this case, make sure to continue the game play as is.
Followings are sample codes to implement the UI which HIVE SDK provides by configuring game data of the conflicted PlayerID.
API Reference: hive.AuthV4.showConflictSelection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// HIVE SDK AuthV4 account selection UI callback handler public void onAuthV4ShowConflictSelection(ResultAPI result, AuthV4.PlayerInfo playerInfo) { if (result.isSuccess() == true) { // Success to select an account } else { // Failed to select an account } } // _conflictPlayer : conflict player info JSONObject conflictPlayerData = new JSONObject(); conflictPlayerData.AddField("player_id", _conflictPlayer.playerId); JSONObject usedPlayerIDGameData = new JSONObject(); usedPlayerIDGameData .AddField("playerId", _conflictPlayer.playerId); usedPlayerIDGameData .AddField("Name", "usedName"); usedPlayerIDGameData .AddField("Level", 11); conflictPlayerData.AddField("game_data", usedPlayerIDGameData); // Request account selection UI from HIVE SDK AuthV4 AuthV4.showConflictSelection(NULL, conflictPlayerData, onAuthV4ShowConflictSelection); |
API Reference: AuthV4::showConflictSelection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Game data of conflicted PlayerID ConflictViewInfo viewInfo = ConflictViewInfo(123456789); viewInfo.SetValue("playerId", 123456789); viewInfo.SetValue("Name", "conflitUserName"); viewInfo.SetValue("Level", "20"); // Request account selection UI from HIVE SDK AuthV4 AuthV4::showConflictSelection(viewInfo, [=](ResultAPI const & result, PlayerInfo const & playerInfo) { // Result callback if (result.isSuccess()) { // Selected user cout<<"PlayerName : "<<playerInfo.playerName<<endl; cout<<"PlayerId : "<<playerInfo.playerId<<endl; } else { // TODO : Error Handling } }); |
API Reference: com.hive.AuthV4.showConflictSelection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Conflict Player Map<String, Object> conflictPlayerData = new HashMap<>(); conflictPlayerData.put("player_id", conflictPlayerInfo.playerId); Map<String, Object> conflictPlayerGameData = new HashMap<>(); conflictPlayerGameData.put("Name", "ConflictPlayer-" + conflictPlayerInfo.playerId); conflictPlayerGameData.put("Level", 10); conflictPlayerData.put("game_data", conflictPlayerGameData); AuthV4.showConflictSelection(NULL, conflictPlayerData, new AuthV4.AuthV4SignInListener() { @Override public void onAuthV4SignIn(ResultAPI result, AuthV4.PlayerInfo playerInfo) { if(result.isSuccess()) { } } }); |
API Reference: HIVEAuthV4:showConflictSelection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
// _playerInfo : current player info // _conflictPlayerInfo : conflict player info NSDictionary *currentPlayerData = @{ @"player_id" : @(_playerInfo.playerId), @"game_data" : @{ @"playerId" : @(_playerInfo.playerId), @"Name" : @"Current Player Name", @"Level" : @(10) } }; NSDictionary *conflictPlayerData = @{ @"player_id" : @(_conflictPlayerInfo.playerId), @"game_data" : @{ @"playerId" : @(_conflictPlayerInfo.playerId), @"Name" : @"Conflict Player Name", @"Level" : @(11) } }; // Request account selection UI from HIVE SDK AuthV4 [HIVEAuthV4 showConflictSelection:currentPlayerData conflictPlayerData:conflictPlayerData handler:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) { Loggerd(@"HIVEAuthV4.showConflictSelection:conflictPlayerData:handler:\nresult = %@\nplayerInfo = %@", result, playerInfo); if (result.isSuccess) { // Success to select the account } else { // Failed to select the account } }]; |
IdP Disconnection
You can have users disconnect from the synced list. To disconnect the IdP, call disconnect()
method with the ProviderType
as a parameter you want to disconnect. If you successfully disconnect the IdP by using the disconnect()
method, make sure to check the connection status of users and then update the synced IdP list on the UI.
Followings are sample codes to implement IdP disconnection.
API Reference: hive.AuthV4.disonnect
1 2 3 4 5 6 7 8 9 10 11 12 |
// Callback handler of disconnecting HIVE SDK AuthV4 public void onAuthV4Disconnect(ResultAPI result) { if (result.isSuccess() == true) { // Success to disconnect } else { // Failed to disconnect } } // Request to disconnect HIVE SDK AuthV4 AuthV4.disonnect(AuthV4.ProviderType.HIVE, onAuthV4Disconnect); |
API Reference: AuthV4::disonnect
1 2 3 4 5 6 7 8 9 10 |
// Request to disconnect HIVE SDK AuthV4 AuthV4::disconnect(ProviderType::HIVE, [=](ResultAPI const & result) { // Callback the result if (result.isSuccess()) { // Success to disconnect } else { // Failed to disconnect // TODO : Error Handling } }); |
API Reference: com.hive.AuthV4.disonnect
1 2 3 4 5 6 7 8 9 10 |
AuthV4.disconnect(providerType, new AuthV4.AuthV4DisconnectListener() { @Override public void onAuthV4Disconnect(ResultAPI result) { if (result.isSuccess) { // Success to disconnect } else { // Failed to disconnect } } }); |
API Reference: HIVEAuthV4:disonnect
1 2 3 4 5 6 7 8 9 10 11 12 |
// Request to disconnect HIVE SDK AuthV4 [HIVEAuthV4 disconnect:kHIVEProviderTypeHIVE handler:^(HIVEResultAPI *result) { Loggerd(@"HIVEAuthV4.disconnect:handler:\nresult = %@", result); if (result.isSuccess) { // Success to disconnect } else { // Failed to disconnect } }]; |
Notification phrases in accordance with the situation
Expose the appropriate alerts in accordance with the situation when users disconnect IdP.
- If a user tries to disconnect the only account synced
Language | Phrase |
---|---|
Korean | 최소 1개의 계정 연동을 유지해야 합니다. |
English | You must keep at least 1 of your accounts synced. |
Japanese | 少なくとも1つのアカウントを連動しなければなりません。 |
Chinese (Simplified) | 需要绑定至少1个账号。 |
Chinese (Traditional) | 至少要有1個帳號是綁定的! |
French | Tu dois garder au moins l’un de tes comptes synchronisés. |
German | Du musst mindestens 1 deiner Konten synchronisieren. |
Russian | Хотя бы 1 из аккаунтов должен быть синхронизирован. |
Spanish | Debe de mantener al menos 1 de sus cuentas sincronizada. |
Portuguese | É necessário sincronizar pelo menos 1 das suas contas. |
Indonesian | Kamu harus punya paling tidak satu akun yang terhubung. |
Malay | sekurang-kurangnya kamu harus simpan 1 akaun yang segerak. |
Vietnamese | Bạn cần phải duy trì ít nhất 1 liên kết tài khoản. |
Thai | ต้องซิงค์บัญชีอย่างหน่อย 1 บัญชี |
Italian | Devi mantenere almeno 1 dei tuoi account sincronizzato. |
Turkish | En az 1 hesabınızı senkronize etmeniz gerekmektedir. |
Arabic | يجب أن تحتفظ على الأقل بحساب واحد متزامن من بين حساباتك. |
- If game limits IdP disconnection
Language | Phrase |
---|---|
Korean | 계정 연동은 해제할 수 없습니다. |
English | Account sync can’t be disabled. |
Japanese | アカウント連動は解除できません。 |
Chinese (Simplified) | 无法解除账号绑定。 |
Chinese (Traditional) | 無法解除綁定。 |
French | La synchronisation de compte ne peut pas être désactivée. |
German | Konto-Sychronisierung kann nicht deaktiviert werden. |
Russian | Невозможно отменить синхронизацию аккаунта. |
Spanish | Una sincronización de cuenta no puede ser desactivada. |
Portuguese | A sincronização de conta não pode ser desativada. |
Indonesian | Penghubungan akun tidak bisa dihapus. |
Malay | Penyegerakan akaun tidak dapat dihapus. |
Vietnamese | Liên kết tài khoản không thể được gỡ bỏ. |
Thai | ไม่สามารถปิดการซิงค์บัญชีได้ |
Italian | La sincronizzazione account non può essere disattivata. |
Turkish | Hesap senkronizasyonu devre dışı bırakılamaz. |
Arabic | لا يمكن تعطيل مزامنة الحساب. |
- If login status becomes guest after IdP disconnection
Language | Presentation |
---|---|
Korean | 계정 연동이 없어 게스트 상태로 전환되었습니다. 게스트 상태에서 게임 삭제 시 데이터가 삭제됩니다. |
English | You have been transferred to a Guest Account because you don’t have any account synced. Your game data will be deleted if you delete the game while playing as a guest. |
Japanese | アカウントが連動されていないため、ゲストアカウントに切り替えられました。ゲストアカウントの場合、ゲームを削除するとデータも消えてしまいます。 |
Chinese (Simplified) | 未绑定账号,已转换为游客状态。游客状态下删除游戏客户端时,数据也会消失。 |
Chinese (Traditional) | 因為沒有綁定,目前將以訪客帳號登入。訪客帳號登入時,當遊戲刪除或變更設備時, 遊戲資料將無法保留。 |
French | Tu a été transféré vers un compte invité car tu n’as pas de compte synchronisé. Tes données de jeu vont être supprimées si tu supprimes le jeu en jouant en invité. |
German | Du wurdest auf ein Gastkonto übertragen, weil Du kein Konto synchronisiert hast. Deine Spieldaten werden gelöscht, wenn Du als Gast das Spiel deinstallierst. |
Russian | Аккаунт не синхронизирован: вы были переведены на гостевой аккаунт. |
Spanish | Has sido transferido a una Cuenta de Invitado porque no tiene ninguna cuenta sincronizada. Sus datos del juego serán borrados mientras juegue como invitado. |
Portuguese | Você foi transferido para uma Conta de Visitante porque não há nenhuma conta sincronizada. Seus dados de jogo serão perdidos se o jogo for deletado caso esteja jogando com uma Conta de Visitante. |
Indonesian | Kamu akan ditransfer ke akun Guest karena kamu tidak punya akun terhubung. Data game akan terhapus jika kamu menghapus game selama bermain sebagain Guest. |
Malay | Kamu telah dipindah ke akaun tetamu kerana tidak mempunyai akaun yang disegerakkan. Data permainan akan terhapus jika kamu bermain dan menghapuskan permainan sebagai tetamu. |
Vietnamese | Tài khoản của bạn đã được chuyển sang Tài Khoản Khách do bạn đã không liên kết tài khoản. Dữ liệu game của bạn sẽ bị xóa nếu bạn xóa game khi đang chơi ở tài khoản khách. |
Thai | กลับมาใช้บัญชี Guest เนื่องจากคุณไม่ได้ซิงค์บัญชีใด ๆ ไว้ หากคุณเล่นโดยใช้บัญชี Guest และลบเกม ข้อมูลเกมจะสูญหายทั้งหมด |
Italian | Sei stato trasferito a un Account Ospite perché non hai alcun account sincronizzato. I tuoi dati di gioco verranno persi se elimini il gioco mentre sei ancora in modalità Ospite. |
Turkish | Senkrone edilmiş bir hesabınız olmadığı için Misafir Hesabına transfer edildiniz. Misafir hesabıyla oynarken oyunu silerseniz oyun verileri de silinecektir. |
Arabic | لقد تم نقلك إلى حساب ضيف لأنك لا تمتلك أي حساب مزامن. سيتم حذف بيانات اللعبة الخاصة بك إذا قمت بحذف اللعبة أثناء اللعب كضيف. |