Player Authentication
1. Overview
This document breaks down the use of player authentication which is the prerequisite of accessing PGOS services. You need to use the player authentication service when the game needs to identify the player and manage the player session status of the player.
After completing this tutorial, developers will know the following:
- The general sequence to create a player session.
- How to monitor player session events.
- How to handle player session exceptions.
- How to start a new player session with a new account (switch account).
2. General Sequence
2.1 Sequence Diagram
The player authentication service includes two parts:
- Verification of player identity
- Management of player session status
Before using the PGOS services, you need to use the account service to log in to an identity, and then use the open_id & token returned by the account provider to log in PGOS (create a PGOS player session). After that, you can access all PGOS services. The general sequence is shown in the following diagram:
2.2 Keyword Definition
- account provider: The third-party account provider that supports player login and authentication. Common account providers include PlayFab, INTL, Steam, etc. The game generally needs to integrate its http APIs or SDK to use its account service. There are two types of account providers:
- Type 1: Supports only one account platform. Take account provider Steam as an example, it only supports its own account platform, that is, only Steam accounts are supported when using account provider Steam.
- Type 2: Supports multiple account platforms. Take account provider PlayFab as an example, it supports account platforms such as Steam, Google, PSN, etc.
- account platform: The platform system for managing user accounts and identity authentication. Common account platforms include Steam, Google, Apple, etc. An account platform can simultaneously be an account provider, such as Steam. And an account provider may support multiple account platforms, for example, the account provider INTL supports account platforms such as Steam, Google, and XBoxLive, etc.
- fake account service: Fake account service (FAS) provider is provided to help go through all the PGOS services before integrating the game with a real account service. You can use FAS to temporarily replace the real account service during the game development stage.
- open id: The User identity provided by the account-service provider.
- token: The valid ticket corresponding to the open_id provided by the account service provider.
- player id: The unique player ID in the title region provided by the PGOS.
- player session: Session between game client and PGOS backend. Once the player session expires, the game client will not be able to access the PGOS services.
3. Using Player Auth
3.1 Log in PGOS
Before logging in to PGOS with an identity using account service, you need to make sure that the corresponding Auth add-on has been enabled. After that, you can call PlayerAuth::LoginPGOS
API to log in PGOS and create a player session. If the login result is success, then you can access all PGOS services, if the login result is failed, check the error code and error message to see what happened.
3.1.1 Login Param
The FClientLoginPGOSParams
structure parameter serves as the input for the login process.
struct FClientLoginPGOSParams: public FBaseBackendEventParams
{
int32 account_provider = -1;
FString account_open_id;
FString account_token;
FString title_region_id;
TMap<FString, FString> extra_param;
};
struct FBaseBackendEventParams
{
/**
* [Optional] A game-defined custom value pass to PGOS backend event.
* If you need to get a custom value in the event, pass it in, otherwise, ignore this field.
* The API parameter structures inherited from this structure all support passing a custom data to the related events.
* The size is limited to 4096 bytes in a narrow-character string, if it is a wide-character string, it should be converted to a utf-8 narrow-character string before calculating its length.
* Detail for PGOS backend event: https://pgos.intlgame.com/pgosdoc/manual/service_manual/extensions/event.html.
* Detail for how to reference the 'event_custom_data':https://pgos.intlgame.com/pgosdoc/manual/service_manual/extensions/virtual_server_v2.html#43-the-request-and-response-protocol.
*/
FString event_custom_data;
};
Fields in FClientLoginPGOSParams
structure:
account_provider: Account service provider, the game client uses its sdk/api for account login. The default value is -1 (not set), at which point
PgosSDK
will try to read it from the configuration: account_provider.const int32 FAS = 0; /** Fake account service provided by PGOS. */
const int32 INTL = 1; /** Account service provided by Proxima for overseas games. */
const int32 MSDK = 2; /** Account service provided by Tencent for China mainland games. */
const int32 WeGame = 3; /** Account service provided by WeGame. */
const int32 PlayFab = 4; /** Account service provided by PlayFab. */
const int32 Steam = 5; /** Account service provided by Steam. */
const int32 Epic = 6; /** Account service provided by Epic(EOS), only epicgames identity is supported. */
const int32 XboxLive = 7; /** Account service provided by XboxLive. */
const int32 PlayStationNetwork = 8; /** Account service provided by PlayStationNetwork. */
const int32 Nintendo = 9; /** Account service provided by Nintendo. */account_open_id: Open id of the logged-in account service. Obtained from a successful account service login. Player user IDs.
account_token: Token of the account open id. Obtained from a successful account service login.
title_region_id: Title region id that the player wants to login, can be obtained from PGOS portal console.
extra_param: [Optional] Extra parameter for the account service, Its value depends on the account service used to log in.
event_custom_data: [Optional] A game-defined custom value pass to PGOS backend event:
event_player_login_pgos
. If you need to get a custom value in the event, pass it in, otherwise, ignore this field. The size is limited to 4096 bytes (after converting the string to utf8 format). Click here to view how to reference theevent_custom_data
in the virtual server.
In the following chapters, we will give a more detailed introduction on how to log in to PGOS with these account providers.
3.1.2 Login with FAS
In the development stage of the game, developers can use FAS to go through all the PGOS services before integrating the game with a real account service. Here is the sample code:
#include "PgosSDKCpp.h"
// call after a successful FAS login
// and the FASAuthRet is obtained from FAS Login
void SomeUObjectClass::LoginPGOS(const FClientFasLoginInfo& FASAuthRet)
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
FClientLoginPGOSParams Params;
Params.account_provider = (int32)EAccountProvider::FAS;
Params.account_open_id = FASAuthRet.open_id;
Params.account_token = FASAuthRet.token;
Params.title_region_id = TEXT("region_id_to_login"); // Obtained from PGOS portal console.
playerAuth->LoginPGOS(Params, [](const FPgosResult& Ret, const FClientAuthenticationInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSSuccess: player_id=%s"), *Data->player_id);
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
The following are tips about the FClientLoginPGOSParams fields when logging in with FAS:
- extra_param: Ignore this filed when login with FAS.
- event_custom_data: If you need to get a custom value in PGOS Event: event_player_login_pgos, pass it in, if not, ignore this field.
3.1.3 Login with INTLSDK (Player Network)
To login PGOS with INTLSDK (Player Network), you must install the INTLSDK Addon on the portal console first, then you can start your coding work, here is the sample code:
#include "PgosSDKCpp.h"
// call after a successful INTLSDK login
// and the INTLAuthRet is obtained from INTLSDK Login
void SomeUObjectClass::LoginPGOS(const FINTLAuthResult& INTLAuthRet)
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
FClientLoginPGOSParams Params;
Params.account_provider = (int32)EAccountProvider::INTL;
Params.account_open_id = INTLAuthRet.OpenID;
Params.account_token = INTLAuthRet.Token;
Params.title_region_id = TEXT("region_id_to_login"); // Obtained from PGOS portal console.
Params.extra_param.Add(TEXT("account_channel"), INTLAuthRet.ChannelID);
playerAuth->LoginPGOS(Params, [](const FPgosResult& Ret, const FClientAuthenticationInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSSuccess: player_id=%s"), *Data->player_id);
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
The following are tips about the ClientLoginPGOSParams fields when logging in with INTL SDK:
extra_param: Add a key
"account_channel"
and set the value with theChannelID
obtained from the INTL SDK authentication result.Params.extra_param.Add(TEXT("account_channel"), INTLAuthRet.ChannelID);
event_custom_data: If you need to get a custom value in PGOS Event: event_player_login_pgos, pass it in, if not, ignore this field.
3.1.4 Login with WeGame
To login PGOS with WeGame, you must install the WeGame Addon on the portal console first, then you can start your coding work, here is the sample code:
#include "PgosSDKCpp.h"
// call after a successful WeGame login
// and the RailId and SessionTicket are obtained from the Rail API 'AsyncAcquireSessionTicket' response
void SomeUObjectClass::LoginPGOS(const FString& RailId, const FString& SessionTicket)
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
FClientLoginPGOSParams Params;
Params.account_provider = (int32)EAccountProvider::WeGame;
Params.account_open_id = RailId;
Params.account_token = SessionTicket;
Params.title_region_id = TEXT("region_id_to_login"); // Obtained from PGOS portal console.
playerAuth->LoginPGOS(Params, [](const FPgosResult& Ret, const FClientAuthenticationInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSSuccess: player_id=%s"), *Data->player_id);
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
The following are tips about the ClientLoginPGOSParams fields when logging in with WeGame:
- extra_param: Ignore this filed when login with WeGame.
- event_custom_data: If you need to get a custom value in PGOS Event: event_player_login_pgos, pass it in, if not, ignore this field.
3.1.5 Login with PlayFab
To login PGOS with PlayFab, you must install the PlayFab Addon on the portal console first, then you can start your coding work, here is the sample code:
#include "PgosSDKCpp.h"
// call after a successful PlayFab login
// and the PlayFabId and SessionTicket are obtained from PlayFab Login
void SomeUObjectClass::LoginPGOS(const FString& PlayFabId, const FString& SessionTicket)
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
FClientLoginPGOSParams Params;
Params.account_provider = (int32)EAccountProvider::PlayFab;
Params.account_open_id = PlayFabId;
Params.account_token = SessionTicket;
Params.title_region_id = TEXT("region_id_to_login"); // Obtained from PGOS portal console.
playerAuth->LoginPGOS(Params, [](const FPgosResult& Ret, const FClientAuthenticationInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSSuccess: player_id=%s"), *Data->player_id);
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
The following are tips about the ClientLoginPGOSParams fields when logging in with PlayFab:
- extra_param: Ignore this filed when login with PlayFab.
- event_custom_data: If you need to get a custom value in PGOS Event: event_player_login_pgos, pass it in, if not, ignore this field.
3.1.6 Login with Steam
To login PGOS with Steam, you must install the Steam Addon on the portal console first, then you can start your coding work, here is the sample code:
#include "PgosSDKCpp.h"
// call after a successful Steam login
// and the SteamId and SessionTicket are obtained from the steamworks API 'ISteamUser::GetAuthSessionTicket'
void SomeUObjectClass::LoginPGOS(const FString& SteamId, const FString& SessionTicket)
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
FClientLoginPGOSParams Params;
Params.account_provider = (int32)EAccountProvider::Steam;
Params.account_open_id = SteamId;
Params.account_token = SessionTicket;
Params.title_region_id = TEXT("region_id_to_login"); // Obtained from PGOS portal console.
playerAuth->LoginPGOS(Params, [](const FPgosResult& Ret, const FClientAuthenticationInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSSuccess: player_id=%s"), *Data->player_id);
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
The following are tips about the ClientLoginPGOSParams fields when logging in with Steam:
- extra_param: Ignore this filed when login with Steam.
- event_custom_data: If you need to get a custom value in PGOS Event: event_player_login_pgos, pass it in, if not, ignore this field.
3.1.7 Login with Epic
Currently, PGOS only supports epicgames identity and does not support other identity providers on EOS. And to login PGOS with Epic, you must install the Epic Addon on the portal console first, then you can start your coding work, here is the sample code:
#include "PgosSDKCpp.h"
// call after login to Epic
void SomeUObjectClass::LoginPGOS(const FString& EpicAccountId, const FString& JWT_IDToken)
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
FClientLoginPGOSParams Params;
Params.account_provider = (int32)EAccountProvider::Epic;
Params.account_open_id = EpicAccountId;
Params.account_token = JWT_IDToken;
Params.title_region_id = TEXT("region_id_to_login"); // Obtained from PGOS portal console.
playerAuth->LoginPGOS(Params, [](const FPgosResult& Ret, const FClientAuthenticationInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSSuccess: player_id=%s"), *Data->player_id);
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
The following are tips about the ClientLoginPGOSParams fields when logging in with Epic:
- extra_param: Ignore this filed when login with Steam.
- event_custom_data: If you need to get a custom value in PGOS Event: event_player_login_pgos, pass it in, if not, ignore this field.
3.1.8 Login with XboxLive
To login PGOS with XboxLive, you must install the XboxLive Addon on the portal console first, then you can start your coding work, here is the sample code:
#include "PgosSDKCpp.h"
// call after login to XboxLive
// The endpoint URL should be "https://xboxlive.com/" when obtaining an XSTSToken by calling `XUserGetTokenAndSignatureAsync`.
void SomeUObjectClass::LoginPGOS(const FString& Xuid, const FString& XSTSToken)
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
FClientLoginPGOSParams Params;
Params.account_provider = (int32)EAccountProvider::XboxLive;
Params.account_open_id = Xuid;
Params.account_token = XSTSToken;
Params.title_region_id = TEXT("region_id_to_login"); // Obtained from PGOS portal console.
playerAuth->LoginPGOS(Params, [](const FPgosResult& Ret, const FClientAuthenticationInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSSuccess: player_id=%s"), *Data->player_id);
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
The following are tips about the ClientLoginPGOSParams fields when logging in with XboxLive:
- extra_param: Ignore this filed when login with XboxLive.
- event_custom_data: If you need to get a custom value in PGOS Event: event_player_login_pgos, pass it in, if not, ignore this field.
3.1.9 Login with PlayStationNetwork
To login PGOS with PlayStationNetwork, you must install the PlayStationNetwork Addon on the portal console first, then you can start your coding work, here is the sample code:
#include "PgosSDKCpp.h"
// call after login to PlayStationNetwork
void SomeUObjectClass::LoginPGOS(const FString& UserId, const FString& AuthorizationCode)
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
FClientLoginPGOSParams Params;
Params.account_provider = (int32)EAccountProvider::PlayStationNetwork;
Params.account_open_id = UserId;
Params.account_token = AuthorizationCode;
Params.title_region_id = TEXT("region_id_to_login"); // Obtained from PGOS portal console.
playerAuth->LoginPGOS(Params, [](const FPgosResult& Ret, const FClientAuthenticationInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSSuccess: player_id=%s"), *Data->player_id);
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
The following are tips about the ClientLoginPGOSParams fields when logging in with PlayStationNetwork:
- extra_param: Ignore this filed when login with PlayStationNetwork.
- event_custom_data: If you need to get a custom value in PGOS Event: event_player_login_pgos, pass it in, if not, ignore this field.
3.1.10 Login with Nintendo
To login PGOS with Nintendo, you must install the Nintendo Addon on the portal console first, then you can start your coding work, here is the sample code:
#include "PgosSDKCpp.h"
// call after login to Nintendo
void SomeUObjectClass::LoginPGOS(const FString& Naid, const FString& NsaIdToken)
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
FClientLoginPGOSParams Params;
Params.account_provider = (int32)EAccountProvider::Nintendo;
Params.account_open_id = Naid;
Params.account_token = NsaIdToken;
Params.title_region_id = TEXT("region_id_to_login"); // Obtained from PGOS portal console.
playerAuth->LoginPGOS(Params, [](const FPgosResult& Ret, const FClientAuthenticationInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSSuccess: player_id=%s"), *Data->player_id);
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnLoginPGOSFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
The following are tips about the ClientLoginPGOSParams fields when logging in with Nintendo:
- extra_param: Ignore this filed when login with Nintendo.
- event_custom_data: If you need to get a custom value in PGOS Event: event_player_login_pgos, pass it in, if not, ignore this field.
LoginPGOS Key Error Codes
- PgosErrCode::kBackendYouAreBanned
- PgosErrCode::kBackendAuthClientSecretIsNull
- PgosErrCode::kBackendAddonAuthCfgIsNull
- PgosErrCode::kBackendFasNotAllowedLoginProd
- PgosErrCode::kBackendTitleRegionIsClosed
- PgosErrCode::kBackendGeoRestricted
- PgosErrCode::kBackendAccountIDCanNotChangeAfterSet
- PgosErrCode::kBackendOtherPlayerHasOccupiedTheAccountID
- PgosErrCode::kCltSdkPlayerAlreadyLoginPgos
- PgosErrCode::kSdkLastOperationNotCompleted
- PgosErrCode::kSdkNetworkError
3.2 Log out PGOS
When the game client wants to exit or no longer needs to access the PGOS services, the developer should call LogoutPGOS
to end the player session.
The FClientLogoutPGOSParams
structure parameter serves as the input for the login process.
struct FClientLogoutPGOSParams
{
FString event_custom_data;
};
Fields in FClientLogoutPGOSParams
structure:
- event_custom_data: [Optional] A game-defined custom value pass to PGOS backend event:
event_player_logout_pgos
. If you need to get a custom value in the event, pass it in, otherwise, ignore this field. The size is limited to 4096 bytes (after converting the string to utf8 format). Click here to view how to reference theevent_custom_data
in the virtual server.
Here is the sample code for logging out PGOS:
#include "PgosSDKCpp.h"
void SomeUObjectClass::LogoutPGOS()
{
auto PlayerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (PlayerAuth) {
FClientLogoutPGOSParams Params;
PlayerAuth->LogoutPGOS(Params, [](const FPgosResult &Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess) {
UE_LOG(LogTemp, Log, TEXT("LogoutPGOS Success"));
} else {
UE_LOG(LogTemp, Log, TEXT("LogoutPGOS Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
3.3 Switch Account
If the player wants to switch and log in to a new account, follow the process:
- Call the
LogoutPGOS
function to terminate the current player session.. - Switch to the new account through account service.
- Call the
LoginPGOS
function to create a new player session.
3.4 Monitor Player Session Changed Event
Some events may be triggered during the lifetime of a player session. Developers need to be aware of these events and handle them properly. To monitor player session events, bind dynamic delegate to OnPlayerSessionChanged
as follows:
#include "PgosSDKCpp.h"
void SomeUObjectClass::MonitorPlayerSessionEvent()
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
playerAuth->OnPlayerSessionChanged().AddUObject(this, &SomeUObjectClass::OnPlayerSessionChanged);
}
}
void SomeUObjectClass::OnPlayerSessionChanged(const FClientPlayerSessionChangedEvt& event)
{
/*
struct FClientPlayerSessionChangedEvt{
EClientPlayerSessionEvt evt;
FString msg;
}
*/
UE_LOG(LogTemp, Log, TEXT("OnPlayerSessionChanged"));
}
There are 6 player session events defined in the PGOS, which will be triggered when the player session status changed:
enum class EClientPlayerSessionEvt : uint8
{
Dummy = 0,
SessionExpired_NetworkAbnormal = 1,
SessionExpired_TokenExpired = 2,
SessionExpired_KickoutByGame = 3,
SessionExpired_KickoutByBan = 4,
SessionExpired_KickoutByAnotherLogin = 5,
SessionExpired_KickoutByTitleRegionClosed = 6,
SessionExpired_KickoutByAccountCanceled = 7,
SessionStart = 8,
SessionEnd = 9,
};
Type: SessionStart
It will be triggered when a player session starts successfully after
LoginPGOS
is called.Type: SessionExpired_NetworkAbnormal
It will be triggered when the network is abnormal.
It is recommended that game clients silently call ReLoginPGOS API to create a new player session to regain access to PGOS services. If the result of ReLoginPGOS API still fails, then notify the player to check the local network environment.
Type: SessionExpired_TokenExpired
It will be triggered when the PGOS PLAYER TOKEN expired. This usually happens when:
the game client loses the network for a long time (for example, the app enters the background mode on the mobile device), and then regains the network (the app enters the foreground mode) and reconnects with PGOS. It is recommended that game clients silently call ReLoginPGOS API to create a new player session to regain access to PGOS services. If the result of ReLoginPGOS API still fails, then notify the player to re-login using the account service.
Type: SessionExpired_KickoutByGame
It will be triggered when the player is kicked out by the backend HTTP API: KickOutPlayer. When this happens, it is recommended to notify the player to check the account status. There are suggestions at the end of this paragraph on how to handle situations when a player is kicked out.
Type: SessionExpired_KickoutByBan
It will be triggered when the player is banned by the backend HTTP API: BanPlayer (kickout=true). When this happens, it is recommended to notify the player to check the account status. There are suggestions at the end of this paragraph on how to handle situations when a player is kicked out. Click to View Ban Event.
Type: SessionExpired_KickoutByAnotherLogin
It will be triggered when the account performed another login (maybe on another device). When this happens, it is recommended to notify the player to check the account status. There are suggestions at the end of this paragraph on how to handle situations when a player is kicked out.
Type: SessionExpired_KickoutByTitleRegionClosed
In the workflow of Closing Title Region, if it is set to kick players offline, then at the specified time, players will be offline and receive this event.
When this happens, it is recommended to notify the player the title region is closed, and the player can find an accessible title region to log in or just exit the game.
Type: SessionExpired_KickoutByAccountCanceled
It will be triggered when the login account is cancelled. When this happens, it is recommended to notify the player to check the account status. There are suggestions at the end of this paragraph on how to handle situations when a player is kicked out.
Type: SessionEnd
It will be triggered when the player session ends.
Once the player session expires, the game client will not be able to access the PGOS services.
There are two typical ways to handle situations when a player is kicked out:
- Exit the game immediately: Since the game client can't access the PGOS services, the game client may not be able to provide complete game features, so the game can exit the game client after notifying the player.
- If the player is playing the battle, wait for the battle to end before exiting the game: Although the current game client can't access the PGOS services, the DS where the battle session is placed is not affected, so the current player can still finish the current battle, wait and then exit the game would be a pretty friendly way. (Note: features that rely on PGOS services, such as text chat, will no longer work in the current game client.)
3.5 Monitor Player Ban Event
Player ban event may be triggered during the lifetime of a player session, developers can trigger a ban event by calling the backend HTTP API BanPlayer, and if the field kickout
is set to true, a PlayerSessionChangedEvt (SessionExpired_KickoutByBan)
event will be triggered too. Developers need to be aware of the event and handle it properly. To monitor the player ban event, bind dynamic delegate to OnPlayerBanned
as follows:
#include "PgosSDKCpp.h"
void SomeUObjectClass::MonitorPlayerBannedEvent()
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
playerAuth->OnPlayerBanned().AddUObject(this, &SomeUObjectClass::OnPlayerBanned);
}
}
void SomeUObjectClass::OnPlayerBanned(const FClientPlayerBannedEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnPlayerBanned"));
}
Developers can get banned details through FClientPlayerBannedEvt
:
struct FClientPlayerBannedEvt{
/** Reason for ban. */
FString ban_reason;
/** Ban creation time. */
int64 ban_created_time;
/** Ban duration */
int64 ban_duration;
/** Ban expiration time, 0 means forever */
int64 ban_expired_time;
}
ban_expired_time means the time when the ban ends, if it is 0, it means a forever ban.
ban_duration indicates the duration of the ban. If it is a forever ban, its value is 0.
After being banned, FClientAuthBanInfo
will be returned in the callback when LoginPGOS
, similar to FClientPlayerBannedEvt
.
struct FClientAuthBanInfo{
/** Whether the player is banned. */
bool is_banned = false;
/** Reason for ban. */
FString ban_reason;
/** Ban creation time. */
int64 ban_created_time;
/** Ban duration */
int64 ban_duration;
/** Ban expiration time, 0 means forever */
int64 ban_expired_time;
}
3.6 Monitor Title Region Closed Event
The game can close the title region as needed, you can read more about Title Region Open & Close here. When the title region is closed, players can no longer access new logins, new matchmaking, or new battle session placements. Developers can bind dynamic delegate to OnTitleRegionClosed
to monitor the event:
#include "PgosSDKCpp.h"
void SomeUObjectClass::MonitorRegionClosedEvent()
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
playerAuth->OnTitleRegionClosed().AddUObject(this, &SomeUObjectClass::OnRegionClosed);
}
}
void SomeUObjectClass::OnRegionClosed(const FClientTitleRegionClosedEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnRegionClosed"));
}
The accompanying information of the event is as follows:
struct FClientTitleRegionClosedEvt
{
/** The current UTC timestamp of the backend server. (in seconds) */
int64 current_time = 0;
/**
* The approximate Unix timestamp at which the player will be kicked offline. (in seconds)
* If the value is 0, the PGOS backend will kick the player offline soon.
* If the value is -1, the PGOS backend will still allow the current player to remain online, and battle sessions the player is in will not be affected.
*/
int64 kicked_offline_time = 0;
};
Since the OnTitleRegionClosed
event is an event for all online players, for performance reasons, it is notified to the player client through a persistent connection heartbeat, and the heartbeat interval is once every 30 seconds. It is important to note that the push behavior of the OnTitleRegionClosed
event will be different depending on the Close Title Region
operation.
There are 3 scenarios:
Select the
DO NOT kick off
option:The player client will receive the
OnTitleRegionClosed
event in the next persistent connection heartbeat, and thekicked_offline_time
field value of theFClientTitleRegionClosedEvt
will be-1
.Select the
Kick off
option:With
0
minutes after the closing start:Setting 0 makes the PGOS backend kick the player offline immediately, so the persistent connection will be disconnected, and the player client may not have the opportunity to receive the
OnTitleRegionClosed
event through the heartbeat. If fortunate enough to receive the event, thekicked_offline_time
field value will be0
.With
n
minutes after the closing start (n
> 0):The player client will receive the
OnTitleRegionClosed
event in the next persistent connection heartbeat.
Anyway, when the player is kicked offline, a
PlayerSessionChangedEvt
event with reasonSessionExpired_KickoutByTitleRegionClosed
will be triggered.
3.7 Monitor Event Channel Status Changed Event
The Event Channel serves as a data pipeline for the PGOS backend to send event notifications (e.g., chat_messages/friend_requests) to the client. And the event will be triggered when the event channel status has been changed. The event channel status can be influenced by factors such as API calls (e.g., login/logout) and fluctuations in the network environment. In certain scenarios, the event helps the game/player understand the possible reasons for PGOS/game service degradation. For instance, when the event channel is unavailable, the game client can present a message to the player in an appropriate location, such as: "Chat temporarily unavailable, undergoing reconstruction...".
Developers can bind dynamic delegate to OnEventChannelStatusChanged
to monitor the event:
#include "PgosSDKCpp.h"
void SomeUObjectClass::MonitorEventChannelStatusChanged()
{
auto playerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (playerAuth)
{
playerAuth->OnEventChannelStatusChanged().AddUObject(this, &SomeUObjectClass::OnEventChannelStatusChanged);
}
}
void SomeUObjectClass::OnEventChannelStatusChanged(const FClientEventChannelStatusChangedEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnEventChannelStatusChanged"));
}
Developers can get event details through FClientEventChannelStatusChangedEvt
:
struct FClientEventChannelStatusChangedEvt
{
/** Indicate the current status of the event channel. */
EClientPgosEventChannelStatus current_status = EClientPgosEventChannelStatus::Dummy;
/** Indicate the status of the event channel in the previous StatusChanged event. If there is no previous event (meaning it is the first event), its value is set to 'Dummy'. */
EClientPgosEventChannelStatus last_status = EClientPgosEventChannelStatus::Dummy;
};
enum class EClientPgosEventChannelStatus : uint8
{
/** Invalid status. */
Dummy = 0,
/** When the client is connecting or reconnecting to the backend in order to establish the channel, the status is set to 'Creating'. */
Creating = 1,
/** When the channel is successfully established, the status is set to 'Available', indicating that the event notification service is functioning properly. */
Available = 2,
/**
* When the client expectedly(logout) or unexpectedly(network exception) disconnects from the backend, the status is set to 'Unavailable', and the event notification service stops working.*/
Unavailable = 3
};
When the status of the Event Channel changes to Unavailable
, the PGOS event notification service will stop working. This means that the game client will be unable to receive chat messages, friend requests, and other events that rely on backend push notifications. If this is not an expected status (for example, if the player has logged out), the PgosSDK will automatically attempt to rebuild the channel until it succeeds, with a gradually slowing frequency. It starts by trying to rebuild every 3 seconds and eventually reduces the frequency to once every 5 minutes.
3.8 ReLogin PGOS
The ReLoginPGOS
API will try re-login to PGOS using the LoginPGOSParams
cached in memory, this will create a new player session and trigger a PlayerSessionEvt::SessionStart
if it runs successfully. It is generally recommended to call this API when the PlayerSessionEvt::SessionExpired_NetworkAbnormal
or PlayerSessionEvt::SessionExpired_TokenExpired
event occurs.
Here is the sample code:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SomeFunction()
{
auto PlayerAuth = IPgosSDKCpp::Get().GetClientPlayerAuthAPI();
if (PlayerAuth)
{
PlayerAuth->ReLoginPGOS([](const FPgosResult& Ret, const FClientAuthenticationInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("ReLoginPGOS Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("ReLoginPGOS Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
3.9 Player Verification on the Game Server
In some scenarios, the game server may need to verify the identity of the player connecting from the game client. PGOS provides the following method to help the game complete the work:
Related APIs:
Related Client SDK API:
FPgosPlayerAuthAPI::MyAuthTicket
/**
* Get the current player's PGOS authenticated ticket which can be used to authenticate the player via the HTTP Backed API.
* The ticket has a reliable validity period of 60 seconds. Please retrieve it from SDK when needed and avoid caching it.
* If the player is not logged in, an empty string will be returned.
*
* @return The current player's ticket, valid after a successful LoginPGOS.
*/
FString MyAuthTicket() const;Related PGOS HTTP Backend API: VerifyAuthTicket
ReLogin Key Error Codes
- PgosErrCode::kBackendYouAreBanned
- PgosErrCode::kBackendAuthClientSecretIsNull
- PgosErrCode::kBackendAddonAuthCfgIsNull
- PgosErrCode::kBackendFasNotAllowedLoginProd
- PgosErrCode::kBackendTitleRegionIsClosed
- PgosErrCode::kBackendGeoRestricted
- PgosErrCode::kCltSdkPlayerNotLoginPgos
- PgosErrCode::kCltSdkPlayerAlreadyLoginPgos
- PgosErrCode::kSdkLastOperationNotCompleted
- PgosErrCode::kSdkNetworkError
4. Using FAS
We provide fake account service (FAS) to help go through all the PGOS services before integrating the game with a real account service. The real account service will have lots of functions, while the PGOS FAS only provides some simple key functions:
API | Description |
---|---|
Login | Log in with the specified account. |
AutoLogin | Log in with a local historical account (if there is no historical account, one will be created automatically). |
4.1 Login Client API
Players can log in with the specified FAS account, and the FAS account does not need to be registered in advance, it can be any string without line breaks ('\r', '\n'). The FAS accounts can be managed by the game studio. Here is the sample code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto FakeAccount = IPgosSDKCpp::Get().GetClientFakeAccountAPI();
if (FakeAccount)
{
FString Account = TEXT("any_string_as_account"); // account can be any string without line breaks ('\r', '\n').
FakeAccount->Login(Account, [](const FPgosResult& Ret, const FClientFasLoginInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("Login Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("Login Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2 AutoLogin Client API
The generated fake account will be saved locally and can be used automatically when you log in. The file (/fas/account) is where the fake account is saved in, you can distribute or replace it if you want to use this fake account to log in to other devices. Here is the sample code:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto FakeAccount = IPgosSDKCpp::Get().GetClientFakeAccountAPI();
if (FakeAccount)
{
FakeAccount->AutoLogin([](const FPgosResult& Ret, const FClientFasLoginInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("AutoLogin Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("AutoLogin Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
5. Key Error Handling
Error Code | Relevant API | Handling Suggestion |
---|---|---|
kBackendYouAreBanned | LoginPGOS ReLoginPGOS | It means the player is banned. The game can prompt the player a message like "You are banned, expired time is xxxx" |
kBackendAuthClientSecretIsNull | LoginPGOS ReLoginPGOS | It means client secret configuration does not exist. you should use portal create a client secret(if client secret configuration does exist, you should contact with pgos team). |
kBackendAddonAuthCfgIsNull | LoginPGOS ReLoginPGOS | It means the current account authentication method is not supported. you need to make sure that the corresponding Auth add-on has been enabled. |
kBackendFasNotAllowedLoginProd | LoginPGOS ReLoginPGOS | FAS is not allowed to use in Production Region. |
kBackendTitleRegionIsClosed | LoginPGOS ReLoginPGOS | The title region to log in is closed, please check the status of the title region on portal. |
kBackendGeoRestricted | LoginPGOS ReLoginPGOS | Failed to login due to GEO restriction. Check the GEO restriction setting on the portal. |
kCltSdkPlayerNotLoginPgos | ReLoginPGOS | The current player has not logged in to PGOS, so 're-login' won't work. |
kCltSdkPlayerAlreadyLoginPgos | LoginPGOS ReLoginPGOS | The current player has already logged in to PGOS, so the operation is not appropriate. |
kSdkLastOperationNotCompleted | LoginPGOS ReLoginPGOS | The last login operation is still in progress, please wait for the last login operation to complete. |
kSdkNetworkError | All Network API | network error, check error msg for detail. |