Skip to main content

Player KVData

1. Overview

The player key-value data is a collection of data associated with a player. To be exact, it's a series of key-value pairs defined in the web portal, generally associated with the gameplay and configured by the game itself, such as the player level and character ATK.

After completing this tutorial, you will understand the following content:

  • How to customize player kvdata template on the web portal and view player kvdata.
  • How to query and update player kvdata in code.

2. Customize KVData Template

Before accessing player data, the game must customize its own player data templates on the web portal.

Log in to the web portal, access your title region, and go to Players > KVData Template:

image-20231123174227746

The above screenshot shows an example. This data template has 4 keys, meaning each player in the game will have these 4 data items independently. The game can customize these data items based on its gameplay needs.

2.1 Add/Remove KVData Items

  • Use the Add Item button to create a new data item and then fill in the following details:

    • Key: The key name of the data item, composed of letters, numbers, and underscores. It must start with a letter and cannot exceed 128 characters. And the key name is case-sensitive, meaning that "KEY_NAME" and "key_name" will be considered as the same key.
    • Type: The type of the data item, which can be String, Integer (supports Int64), or Float (supports float64).
    • Default Value: The value of a player's data item before it is updated in-game.
  • Use the Remove Item button to remove the selected data item. Once a data item is removed, attempts to access the item will fail (through the PGOS SDK, matchmaking rule set, etc.). Make sure the relevant code logic is modified at the same time.

  • The upper limit for the number of KV Data Items that can be created is 1000.

2.2 KVData Item Access Permissions

Access permissions have three parallel attributes:

  • Server Only: When it is true, the data item can only be accessed by the game server.

  • Client Writable: When it is true, the data item can be updated by the data owner.

  • Client Public: When it is true, the data item can be viewed by other players.

    image-20210810115511084

Generally:

  • Game servers (dedicated servers or virtual servers) have permission to access all player data items.
  • The game client can update the client writable data items of the current player. It cannot update the data items of other players.

The example data template in the image below explains specific player data access permissions:

image-20231123174413832

  • Data Item experience:
    • Can be read and written by the game server.
    • Can be read, but not written by the player to whom the data belongs.
    • Not visible (cannot be read or written) to other players.
  • Data Item level:
    • Can be read and written by the game server.
    • Can be read, but not written by the player to whom the data belongs.
    • Can be read, but not written by other players.
  • Data Item mood:
    • Can be read and written by the game server.
    • Can be read and written by the player to whom the data belongs.
    • Can be read, but not written by other players.
  • Data Item mmr:
    • Can be read and written by the game server.
    • Not visible (cannot be read or written) to the player to whom the data belongs.
    • Not visible (cannot be read or written) to other players.

2.3 KVData Item Versioned

image-20231123205603837

The versioned attribute specifies whether a key requires strict version control. It is suitable for keys whose value require strict updates based on the latest original value. For example, in a game, the player's Buff is saved using player KVData. When the player meets certain conditions, the Buff will increase by 10% based on the current value, and triggering the increase may occur in multiple places (virtual server, dedicated server). To prevent potential data errors that may arise from updating the Buff simultaneously in multiple places, it is necessary to mark the Buff as versioned and call the Set*VersionedKVData APIs to update it. Each player has a version number for their player KVData versioned keys and the version number only increases when the values of versioned keys are updated. The versioned keys can only be updated using the Incr*KVData or Set*VersionedKVData APIs. Here is the availability of the relevant APIs for versioned key and non-versioned key:

SDKAPIVersioned KeyNon-versioned KeyVersioned Key + Non-versioned Key
Client SDKIncrOneOfMyKVDataAvailableAvailableNo multi-key support
Client SDKIncrMyKVDataAvailableAvailableAvailable
Client SDKSetMyVersionedKVDataAvailableNot availableAvailable
Client SDKGetMyVersionedKVDataAvailableNot availableAvailable
Server SDKIncrOneOfPlayerKVDataAvailableAvailableNo multi-key support
Server SDKBatchIncrOneOfPlayerKVDataAvailableAvailableAvailable
Server SDKIncrPlayerKVDataAvailableAvailableAvailable
Server SDKBatchIncrPlayerKVDataAvailableAvailableAvailable
Server SDKSetPlayerVersionedKVDataAvailableNot availableAvailable
Server SDKBatchSetPlayerVersionedKVDataAvailableNot availableAvailable
Server SDKGetPlayerVersionedKVDataAvailableNot availableAvailable
Server SDKBatchGetPlayerVersionedKVDataAvailableNot availableAvailable

In general, the Incr*KVData APIs are available for both versioned keys and non-versioned keys, The SetVersionedKVData APIs are only available for keys that contain at least one versioned key. The same rules apply to the `GetVersionedKVData` API.

tip

Generally, the get/set operations for non-versioned keys are faster, while versioned keys are relatively slower. Therefore, the game should only mark a key as versioned when necessary. In addition, before calling the Set*VersionedKVData APIs to update the value of versioned keys, you need to call Get*VersionedKVData APIs to obtain the version number of the player's versioned keys.

The behavior of the HTTP Backend APIs are the same as the behavior of the corresponding Server SDK APIs.

2.4 KVData Group

The game can directly manage and access all data items. However, when there are many data items, this method can be disorderly. To allow the game to better manage player data, we introduce the data group mechanism, as shown in the image below:

image-20210812194822621

As you can see, the game can use a group to associate several data items for collective management and access. Below, we will use a typical scenario to illustrate how to use the Group mechanism in a game.

Typical Group application scenario:

Assume you want to render a player's detailed information. Besides the name and avatar of the player (can be obtained from player info), you also want to involve the player level, experience, win count, and loss count, as shown in the image below:

image-20210812164150613

Obviously, it is better to store these data items in player data. Therefore, you defined them in a player data template and have the game server update the data at appropriate times, as shown in the image below:

image-20210812170420540

These data items are scattered throughout the data template, so it is difficult to find and manage them. Therefore, it is a good idea to place them in a single group.

Click on the Add Group button on the left to add a group named profile_view, as shown in the image below:

image-20210812172227809

The upper limit for the number of KV Data Groups that can be created is 100.

Add level, experience, win_cnt, and lost_cnt to the profile_view group, as shown in the image below:

image-20210812173816583

Then, you can use the group name to find the group on the portal, as shown in the following image:

image-20210812174920793

After completing the above operations, when you render the player detail info, you can use the group name to easily find the data items in profile_view:

/**
* Query the specified group kvdata of the specified player.
*
* @param PlayerId Player to query.
* @param GroupName Name of the specified group.
*/
void GetPlayerGroupKVData(
const FString& PlayerId,
const FString& GroupName,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroup* Data)> Callback) const;

Some information for you to pay attention to:

  • On the portal, you can create and delete data groups, but cannot create more than 100 groups.

  • The group name consists of letters and numbers only. It must start with a letter and cannot exceed 64 characters.

  • A single data item can be placed in multiple groups.

  • When the game client requests for the data items in groups, the PGOS back-end will only return the data items for which the requester has permission.

  • Dedicated servers and virtual servers can access all data items in groups.

2.5 Public KVData

We call the set of data items that is visible to all other players (Client Public = true) "public data".

image-20210812205135005

This is a special set, which is frequently accessed in the game's player profile view. Therefore, we provide APIs in the PGOS Client SDK that can directly access it:

  • Obtain public data for one player: UPgosPlayerProfileAPI::GetPlayerPublicKVData

    /**
    * Query all public kvdata of the specified player.
    *
    * @param PlayerId Player to query.
    */
    void GetPlayerPublicKVData(
    const FString& PlayerId,
    TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroup* Data)> Callback) const;

    struct FPlayerKVDataGroup
    {
    /** Player to query. */
    FString player_id;
    /** KVData items, key: item key, value: item value. */
    TMap<FString, FKVDataValue> kvdata;
    };
  • Obtain public data for multiple players: UPgosPlayerProfileAPI::BatchGetPlayerPublicKVData

    /**
    * Query multiple players' public kvdata.
    *
    * @param PlayerIds Players to query.
    */
    void BatchGetPlayerPublicKVData(
    const TArray<FString>& PlayerIds,
    TFunction<void(const FPgosResult& Ret, const FBatchGetPlayerGroupKVDataRsp* Data)> Callback) const;

    struct FBatchGetPlayerGroupKVDataRsp
    {
    /** KVData of the players, key: player_id, value: the player's public kvdata. */
    TMap<FString, FKVDataGroup> data;
    /** Players who totally failed, key: player_id, value: failed reason. */
    TMap<FString, FString> fail_players;
    };

3. View Player KVData

Log in to the web portal, access your title region, and go to Players > Query:

image-20210809163842712

Click on the ID of a player to view the player details:

image-20210811180415078

4. Using Player KVData

4.1 KVData Structure

The values of data items are categorized into different types (String, Integer, or Float) and are inevitably used in the input and output of the PlayerData APIs. To make it easier for developers to reference and set these values, we abstract them into the FKVDataValue structure:

struct FKVDataValue
{
/** Value data: Please access with operators or As* functions. */
FString value;
/** Value type: String/Integer/Float. */
EKVDataType type;

public:
FKVDataValue() : type(EKVDataType::String){};
FKVDataValue(const FKVDataValue& o) : value(o.value), type(o.type){};
FKVDataValue(const TCHAR* vl) { Set(vl ? (vl):TEXT("")); }; // FKVDataValue v = TEXT("abc");
FKVDataValue(const FString& vl) { Set(vl); }; // FKVDataValue v = FString(TEXT("abc"));
FKVDataValue(int32 vl) { Set(vl); }; // FKVDataValue v = 123;
FKVDataValue(int64 vl) { Set(vl); }; // FKVDataValue v = (int64)123;
FKVDataValue(float vl) { Set(vl); }; // FKVDataValue v = (float)1.23;
FKVDataValue(double vl) { Set(vl); }; // FKVDataValue v = 1.23;

operator const TCHAR*() { return AsStr().GetCharArray().GetData(); }; // const TCHAR* v = FKVDataValue(TEXT("abc"));
operator FString() { return AsStr(); }; // FString v = FKVDataValue(TEXT("abc"));
operator int32() { return AsInt32(); }; // int32 v = FKVDataValue(123);
operator int64() { return AsInt64(); }; // int64 v = FKVDataValue((int64_t)123);
operator float() { return AsFloat(); }; // float v = FKVDataValue((float)1.23);
operator double() { return AsDouble(); }; // double v = FKVDataValue(1.23);

void Set(const FString& vl) { value = vl; type = EKVDataType::String; };
void Set(int32 vl) { value = FString::FromInt(vl); type = EKVDataType::Integer; };
void Set(int64 vl) { value = FString::Printf(TEXT("%lld"), vl); type = EKVDataType::Integer; };
void Set(float vl) { value = FString::SanitizeFloat(vl); type = EKVDataType::Float; };
void Set(double vl) { value = FString::Printf(TEXT("%f"), vl); type = EKVDataType::Float; };

FString AsStr() const { return value; };
int32 AsInt32() const { return FCString::Atoi(*value); };
int64 AsInt64() const { return FCString::Atoi64(*value); };
float AsFloat() const { return FCString::Atof(*value); };
double AsDouble() const { return FCString::Atod(*value); };
};

As you can see, FKVDataValue implements multiple constructors and overloaded operators so that developers can directly set values of other data types (TCHAR*/FString/int32/int64/float/double) to FKVDataValue instances. Likewise, developers can also use FKVDataValue instances to directly set values of other data types (TCHAR*/FString/int32/int64/float/double). Sample code is shown below:

// (TCHAR*/FString/int32/int64/float/double) to FKVDataValue
FKVDataValue v1 = TEXT("abc");
FKVDataValue v2 = FString(TEXT("abc"));
FKVDataValue v3 = 123;
FKVDataValue v4 = (int64)123;
FKVDataValue v5 = (float)1.23;
FKVDataValue v6 = 1.23;

// FKVDataValue to (TCHAR*/FString/int32/int64/float/double)
const TCHAR* str1 = FKVDataValue(TEXT("abc"));
FString str2 = FKVDataValue(TEXT("abc"));
int32 i1 = FKVDataValue(123);
int64 i2 = FKVDataValue((int64_t)123);
float f1 = FKVDataValue((float)1.23);
double f2 = FKVDataValue(1.23);

4.2 For Game Client

4.2.1 Query Player KVData

Obtain player data of current player:

APIDescription
GetOneOfMyKVDataQuery the specified KVData of the current player.
GetMyKVDataQuery certain KVData of the current player.
GetAllOfMyKVDataQuery all accessible KVData of the current player.
GetMyPublicKVDataQuery all public KVData of the current player.
GetMyGroupKVDataQuery the specified group KVData of the current player.
GetMyVersionedKVDataQuery certain versioned KVData of the current player.

Obtain player data of another player:

APIDescription
GetOneOfPlayerKVDataQuery the specified KVData of the specified player.
GetPlayerKVDataQuery certain KVData of the specified player.
BatchGetPlayerKVDataPerform a batch query of KVData for multiple players.
GetPlayerPublicKVDataQuery all public KVData of the specified player.
BatchGetPlayerPublicKVDataPerform a batch query of public KVData for multiple players.
GetPlayerGroupKVDataQuery the specified group KVData of the specified player.
BatchGetPlayerGroupKVDataPerform a batch query of the specified group KVData for multiple players.

API details:

4.2.1.1 GetOneOfMyKVData Client API

Interface prototype:

/**
* Query the specified kvdata of the current player.
*
* @param QueryKey Key to query
*/
void GetOneOfMyKVData(
const FString& QueryKey,
TFunction<void(const FPgosResult& Ret, const FOnePlayerKVData* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (playerprofile)
{
FString QueryKey = TEXT("level");
PlayerProfile->GetOneOfMyKVData(QueryKey, [](const FPgosResult& Ret, const FOnePlayerKVData* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetOneOfMyKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetOneOfMyKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.2 GetMyKVData Client API

Interface prototype:

/**
* Query certain kvdata of the current player.
*
* @param QueryKeys Keys to query
*/
void GetMyKVData(
const TArray<FString>& QueryKeys,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroupWithFails* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
TArray<FString> QueryKeys = {TEXT("level"), TEXT("experience")};
PlayerProfile->GetMyKVData(QueryKeys, [](const FPgosResult& Ret, const FPlayerKVDataGroupWithFails* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetMyKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetMyKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.3 GetAllOfMyKVData Client API

Interface prototype:

/**
* Query all accessible kvdata of the current player.
*/
void GetAllOfMyKVData(TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
PlayerProfile->GetAllOfMyKVData([](const FPgosResult& Ret, const FPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetAllOfMyKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetAllOfMyKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.4 GetMyPublicKVData Client API

Interface prototype:

/**
* Query all public kvdata of the current player.
*/
void GetMyPublicKVData(TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
PlayerProfile->GetMyPublicKVData([](const FPgosResult& Ret, const FPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetMyPublicKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetMyPublicKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.5 GetMyGroupKVData Client API

Interface prototype:

/**
* Query the specified group kvdata of the current player.
* Keys in the group that are not accessible to the current player will be ignored.
*
* @param GroupName Name of the specified group.
*/
void GetMyGroupKVData(
const FString& GroupName,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
FString GroupName = TEXT("profile_view");
PlayerProfile->GetMyGroupKVData(GroupName, [](const FPgosResult& Ret, const FPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetMyGroupKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetMyGroupKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.6 GetOneOfPlayerKVData Client API

Interface prototype:

/**
* Query the specified kvdata of the specified player.
*
* @param PlayerId Player to query.
* @param QueryKey Key to query.
*/
void GetOneOfPlayerKVData(
const FString& PlayerId,
const FString& QueryKey,
TFunction<void(const FPgosResult& Ret, const FOnePlayerKVData* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{

FString PlayerId = TEXT("197177");
FString QueryKey = TEXT("level");;
PlayerProfile->GetOneOfPlayerKVData(PlayerId, QueryKey, [](const FPgosResult& Ret, const FOnePlayerKVData* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetOneOfPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetOneOfPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.7 GetPlayerKVData Client API

Interface prototype:

/**
* Query certain kvdata of the specified player.
*
* @param PlayerId Player to query.
* @param QueryKeys Keys to query.
*/
void GetPlayerKVData(
const FString& PlayerId,
const TArray<FString>& QueryKeys,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroupWithFails* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{

FString PlayerId = TEXT("197177");
TArray<FString> QueryKeys = {TEXT("level"), TEXT("experience")};
PlayerProfile->GetPlayerKVData(PlayerId, QueryKeys, [](const FPgosResult& Ret, const FPlayerKVDataGroupWithFails* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.8 BatchGetPlayerKVData Client API

Interface prototype:

/**
* Perform a batch query of KVData for multiple players.
* If all player operations are successful, the callback result is success.
* If some player operations succeed while others fail, the callback result is success, and the reasons for the failed players can be obtained from the callback data.
* If all player operations fail, the callback result is failure (kBackendAllFailed), and the reasons for the failed players can be obtained from the callback data.
*
* @param PlayerIds Players to query.
* @param QueryKeys Keys to query.
*/
void BatchGetPlayerKVData(
const TArray<FString>& PlayerIds,
const TArray<FString>& QueryKeys,
TFunction<void(const FPgosResult& Ret, const FBatchPlayerKVDataGroupWithFails* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{

TArray<FString> PlayerIds = {TEXT("197177"), TEXT("197178")};
TArray<FString> QueryKeys = {TEXT("level"), TEXT("experience")};
PlayerProfile->BatchGetPlayerKVData(PlayerIds, QueryKeys, [](const FPgosResult& Ret, const FBatchPlayerKVDataGroupWithFails* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.9 GetPlayerPublicKVData Client API

Interface prototype:

/**
* Query all public kvdata of the specified player.
*
* @param PlayerId Player to query.
*/
void GetPlayerPublicKVData(
const FString& PlayerId,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
FString PlayerId = TEXT("197177");
PlayerProfile->GetPlayerPublicKVData(PlayerId, [](const FPgosResult& Ret, const FPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerPublicKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerPublicKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.10 BatchGetPlayerPublicKVData Client API

Interface prototype:

/**
* Perform a batch query of public KVData for multiple players.
* If all player operations are successful, the callback result is success.
* If some player operations succeed while others fail, the callback result is success, and the reasons for the failed players can be obtained from the callback data.
* If all player operations fail, the callback result is failure (kBackendAllFailed), and the reasons for the failed players can be obtained from the callback data.
*
* @param PlayerIds Players to query.
*/
void BatchGetPlayerPublicKVData(
const TArray<FString>& PlayerIds,
TFunction<void(const FPgosResult& Ret, const FBatchPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
TArray<FString> PlayerIds = {TEXT("197177"), TEXT("197178")};
PlayerProfile->BatchGetPlayerPublicKVData(PlayerIds, [](const FPgosResult& Ret, const FBatchPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerPublicKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerPublicKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.11 GetPlayerGroupKVData Client API

Interface prototype:

/**
* Query the specified group kvdata of the specified player.
* Keys in the group that are not accessible to the current player will be ignored.
*
* @param PlayerId Player to query.
* @param GroupName Name of the specified group.
*/
void GetPlayerGroupKVData(
const FString& PlayerId,
const FString& GroupName,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{

FString PlayerId = TEXT("197177");
FString GroupName = TEXT("profile_view");
PlayerProfile->GetPlayerGroupKVData(PlayerId, GroupName, [](const FPgosResult& Ret, const FPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerGroupKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerGroupKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.12 BatchGetPlayerGroupKVData Client API

Interface prototype:

/**
* Perform a batch query of the specified group KVData for multiple players.
* Keys in the group that are not accessible to the current player will be ignored.
* If all player operations are successful, the callback result is success.
* If some player operations succeed while others fail, the callback result is success, and the reasons for the failed players can be obtained from the callback data.
* If all player operations fail, the callback result is failure (kBackendAllFailed), and the reasons for the failed players can be obtained from the callback data.
*
* @param PlayerIds Players to query.
* @param GroupName Name of the specified group.
*/
void BatchGetPlayerGroupKVData(
const TArray<FString>& PlayerIds,
const FString& GroupName,
TFunction<void(const FPgosResult& Ret, const FBatchPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{

TArray<FString> PlayerIds = {TEXT("197177"), TEXT("197178")};
FString GroupName = TEXT("profile_view");
PlayerProfile->BatchGetPlayerGroupKVData(PlayerIds, GroupName, [](const FPgosResult& Ret, const FBatchPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerGroupKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerGroupKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.1.13 GetMyVersionedKVData Client API

Interface prototype:

/**
* Query certain versioned kvdata of the current player.
* The keys to be queried must contain at least one versioned key.
* Call 'GetMyKVData' or 'GetPlayerKVData' instead if you don't need to get the 'version' field, which is only needed when updating versioned KVData.
*
* @param QueryKeys Keys to query.
*/
void GetMyVersionedKVData(
const TArray<FString>& QueryKeys,
TFunction<void(const FPgosResult& Ret, const FKVDataGroupWithVerAndFails* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
TArray<FString> QueryKeys = {TEXT("buff"), TEXT("experience")};
PlayerProfile->GetMyVersionedKVData(QueryKeys, [](const FPgosResult& Ret, const FKVDataGroupWithVerAndFails* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetMyVersionedKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetMyVersionedKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.2.2 Update Player KVData

Update player data of current player:

APIDescription
SetOneOfMyKVDataUpdate the specified KVData of the current player.
SetMyKVDataUpdate KVData of the current player.
IncrOneOfMyKVDataPerform atomic increment operation on a specific KVData item for the current player.
IncrMyKVDataPerform atomic increment operation on multiple KVData items for the current player.
SetMyVersionedKVDataUpdate versioned KVData for the current player.

API details:

4.2.2.1 SetOneOfMyKVData Client API

Interface prototype:

/**
* Update the specified kvdata of the current player.
*
* @param Key Key to update
* @param Value The new value can be set to string/int32/int64/float/double.
*/
void SetOneOfMyKVData(
const FString& Key,
const FKVDataValue& Value,
TFunction<void(const FPgosResult& Ret)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{

FString Key = TEXT("my_lucky_num");
FKVDataValue Value = 777;
PlayerProfile->SetOneOfMyKVData(Key, Value, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetOneOfMyKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetOneOfMyKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.2.2 SetMyKVData Client API

Interface prototype:

/**
* Update kvdata of the current player.
* The update operation for a player's KVData will either succeed as a whole or fail as a whole.
*
* @param Kvdata KVData to update.
*/
void SetMyKVData(
const TMap<FString, FKVDataValue>& Kvdata,
TFunction<void(const FPgosResult& Ret)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
TMap<FString, FKVDataValue> Kvdata;
Kvdata.Add(TEXT("num_key"), 100);
Kvdata.Add(TEXT("string_key"), TEXT("abc"));
PlayerProfile->SetMyKVData(Kvdata, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetMyKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetMyKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.2.3 IncrOneOfMyKVData Client API

Interface prototype:

/**
* Perform atomic increment operation on a specific kvdata item for the current player. [Only works on Integer/Float type keys]
* If the operation is successful, the callback will return the updated data.
*
* @param Key Key to operate.
* @param Increment The increment value can be set to int32/int64/float/double.
*/
void IncrOneOfMyKVData(
const FString& Key,
const FKVDataValue& Increment,
TFunction<void(const FPgosResult& Ret, const FOnePlayerKVData* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{

FString Key = TEXT("my_lucky_day_cnt");
FKVDataValue Increment = 1;
PlayerProfile->IncrOneOfMyKVData(Key, Increment, [](const FPgosResult& Ret, const FOnePlayerKVData* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("IncrOneOfMyKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("IncrOneOfMyKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.2.4 IncrMyKVData Client API

Interface prototype:

/**
* Perform atomic increment operation on multiple kvdata items for the current player. [Only works on Integer/Float type keys]
* If the operation is successful, the callback will return the updated data.
*
* @param Increments Increments to update, key: kvdata key, value: increment of the value.
*/
void IncrMyKVData(
const TMap<FString, FKVDataValue>& Increments,
TFunction<void(const FPgosResult& Ret, const FKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
TMap<FString, FKVDataValue> Increments;
Increments.Add(TEXT("win_cnt"), 1);
Increments.Add(TEXT("defeated_players_cnt"), 5);
PlayerProfile->IncrMyKVData(Increments, [](const FPgosResult& Ret, const FKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("IncrMyKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("IncrMyKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.2.2.5 SetMyVersionedKVData Client API

Interface prototype:

/**
* Update versioned kvdata for the current player.
* The KVData of the player to be updated must contain at least one versioned key.
* The 'version' needs to pass in can be obtained from the 'GetMyVersionedKVData' API call.
* If the 'version' passed in is the latest, the callback will return success along with the updated data.
* If the 'version' passed in is not the latest, the callback will return failure(err_code=11108, kBackendKVDataVersionMismatched) along with the current latest data, you may try again with the latest version.
* For other errors, please refer to the error message and the developer manual on the portal, and the callback data is invalid.
*
* @param Data Versioned kvdata items that need to update. Please set the 'version' field to the latest value you got for the player.
*/
void SetMyVersionedKVData(
const FKVDataGroupWithVer& Data,
TFunction<void(const FPgosResult& Ret, const FKVDataGroupWithVer* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction(int32 latest_ver)
{
auto PlayerProfile = IPgosSDKCpp::Get().GetClientPlayerProfileAPI();
if (PlayerProfile)
{
FKVDataGroupWithVer Data;
Data.version = latest_ver;
Data.kvdata.Add(TEXT("num_key"), 100);
Data.kvdata.Add(TEXT("string_key"), TEXT("abc"));
PlayerProfile->SetMyVersionedKVData(Data, [](const FPgosResult& Ret, const FKVDataGroupWithVer* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetMyVersionedKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetMyVersionedKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.3 For Game Server

4.3.1 Query Player KVData

Obtain player data:

APIDescription
GetOneOfPlayerKVDataQuery the specified KVData of the specified player.
GetPlayerKVDataQuery certain KVData of the specified player.
BatchGetPlayerKVDataPerform a batch query of KVData for multiple players.
GetPlayerGroupKVDataQuery the specified group KVData of the specified player.
BatchGetPlayerGroupKVDataPerform a batch query of the specified group KVData for multiple players.
GetPlayerVersionedKVDataQuery certain versioned kvdata of the specified player.
BatchGetPlayerVersionedKVDataPerform a batch query of versioned KVData for multiple players.

API details:

4.3.1.1 GetOneOfPlayerKVData Server API

Interface prototype:

/**
* Query the specified kvdata of the specified player.
*
* @param PlayerId The player to query.
* @param QueryKey The key to query.
*/
void GetOneOfPlayerKVData(
const FString& PlayerId,
const FString& QueryKey,
TFunction<void(const FPgosResult& Ret, const FOnePlayerKVData* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
FString PlayerId = TEXT("197177");
FString QueryKey = TEXT("level");
PlayerProfile->GetOneOfPlayerKVData(PlayerId, QueryKey, [](const FPgosResult& Ret, const FOnePlayerKVData* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetOneOfPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetOneOfPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.1.2 GetPlayerKVData Server API

Interface prototype:

/**
* Query certain kvdata of the specified player.
*
* @param PlayerId The player to query.
* @param QueryKeys Keys to query.
*/
void GetPlayerKVData(
const FString& PlayerId,
const TArray<FString>& QueryKeys,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroupWithFails* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{

FString PlayerId = TEXT("197177");
TArray<FString> QueryKeys = {TEXT("level"), TEXT("experience")};
PlayerProfile->GetPlayerKVData(PlayerId, QueryKeys, [](const FPgosResult& Ret, const FPlayerKVDataGroupWithFails* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.1.3 BatchGetPlayerKVData Server API

Interface prototype:

/**
* Perform a batch query of KVData for multiple players.
* If all player operations are successful, the callback result is success.
* If some player operations succeed while others fail, the callback result is success, and the reasons for the failed players can be obtained from the callback data.
* If all player operations fail, the callback result is failure (kBackendAllFailed), and the reasons for the failed players can be obtained from the callback data.
*
* @param PlayerIds Players to query.
* @param QueryKeys Keys to query.
*/
void BatchGetPlayerKVData(
const TArray<FString>& PlayerIds,
const TArray<FString>& QueryKeys,
TFunction<void(const FPgosResult& Ret, const FBatchPlayerKVDataGroupWithFails* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
TArray<FString> PlayerIds = {TEXT("197177"), TEXT("197178")};
TArray<FString> QueryKeys = {TEXT("level"), TEXT("experience")};
PlayerProfile->BatchGetPlayerKVData(PlayerIds, QueryKeys, [](const FPgosResult& Ret, const FBatchPlayerKVDataGroupWithFails* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.1.4 GetPlayerGroupKVData Server API

Interface prototype:

/**
* Query the specified group kvdata of the specified player.
*
* @param PlayerId Player to query.
* @param GroupName Name of the specified group.
*/
void GetPlayerGroupKVData(
const FString& PlayerId,
const FString& GroupName,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
FString PlayerId = TEXT("197177");
FString GroupName = TEXT("profile_view");
PlayerProfile->GetPlayerGroupKVData(PlayerId, GroupName, [](const FPgosResult& Ret, const FPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerGroupKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerGroupKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.1.5 BatchGetPlayerGroupKVData Server API

Interface prototype:

/**
* Perform a batch query of the specified group KVData for multiple players.
* If all player operations are successful, the callback result is success.
* If some player operations succeed while others fail, the callback result is success, and the reasons for the failed players can be obtained from the callback data.
* If all player operations fail, the callback result is failure (kBackendAllFailed), and the reasons for the failed players can be obtained from the callback data.
*
* @param PlayerIds Players to query.
* @param GroupName Name of the specified group.
*/
void BatchGetPlayerGroupKVData(
const TArray<FString>& PlayerIds,
const FString& GroupName,
TFunction<void(const FPgosResult& Ret, const FBatchPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
TArray<FString> PlayerIds = {TEXT("197177"), TEXT("197178")};
FString GroupName = TEXT("profile_view");
PlayerProfile->BatchGetPlayerGroupKVData(PlayerIds, GroupName, [](const FPgosResult& Ret, const FBatchPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerGroupKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerGroupKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.1.6 GetPlayerVersionedKVData Server API

Interface prototype:

/**
* Query certain versioned kvdata of the specified player.
* The keys to be queried must contain at least one versioned key.
* Call 'GetMyKVData' or 'GetPlayerKVData' instead if you don't need to get the 'version' field, which is only needed when updating versioned KVData.
*
* @param PlayerId The player to query.
* @param QueryKeys Keys to query.
*/
void GetPlayerVersionedKVData(
const FString& PlayerId,
const TArray<FString>& QueryKeys,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroupWithVerAndFails* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
FString PlayerId = TEXT("197177");
TArray<FString> QueryKeys = {TEXT("buff"), TEXT("experience")};
PlayerProfile->GetPlayerVersionedKVData(PlayerId, QueryKeys, [](const FPgosResult& Ret, const FPlayerKVDataGroupWithVerAndFails* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerVersionedKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPlayerVersionedKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.1.7 BatchGetPlayerVersionedKVData Server API

Interface prototype:

/**
* Perform a batch query of versioned KVData for multiple players.
* The keys to be queried must contain at least one versioned key.
* Call 'BatchGetPlayerKVData' instead if you don't need to get 'version', which is only needed when updating versioned KVData.
*
* @param PlayerIds Players to query.
* @param QueryKeys Keys to query.
*/
void BatchGetPlayerVersionedKVData(
const TArray<FString>& PlayerIds,
const TArray<FString>& QueryKeys,
TFunction<void(const FPgosResult& Ret, const FBatchPlayerKVDataGroupWithVerAndFails* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
TArray<FString> PlayerIds = {TEXT("197177"), TEXT("197178")};
TArray<FString> QueryKeys = {TEXT("level"), TEXT("experience")};
PlayerProfile->BatchGetPlayerVersionedKVData(PlayerIds, QueryKeys, [](const FPgosResult& Ret, const FBatchPlayerKVDataGroupWithVerAndFails* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerVersionedKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerVersionedKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.3.2 Update Player KVData

Update player data:

APIDescription
SetOneOfPlayerKVDataUpdate the specified kvdata of the specified player.
SetPlayerKVDataUpdate kvdata of the specified player.
BatchSetPlayerKVDataPerform a batch update of KVData for multiple players.
IncrOneOfPlayerKVDataPerform atomic increment operation on a specified kvdata item for a specified player.
BatchIncrOneOfPlayerKVDataPerform a batch atomic increment operation on a specified kvdata item for multiple players.
IncrPlayerKVDataPerform atomic increment operation on multiple kvdata items for a specified player.
BatchIncrPlayerKVDataPerform a batch atomic increment operation on multiple kvdata items for multiple players.
SetPlayerVersionedKVDataUpdate versioned kvdata for the specified player., The KVData of the player to be updated must contain at least one versioned key.
BatchIncrPlayerKVDataIdempotentIdempotent version of BatchIncrPlayerKVData. Idempotency token could be set for each player.
BatchSetPlayerVersionedKVDataPerform a batch update of versioned KVData for multiple players.

API details:

4.3.2.1 SetOneOfPlayerKVData Server API

Interface prototype:

/**
* Update the specified kvdata of the specified player.
*
* @param PlayerId Player to query.
* @param Key Key to update
* @param Value The new value can be set to string/int32/int64/float/double.
*/
void SetOneOfPlayerKVData(
const FString& PlayerId,
const FString& Key,
const FKVDataValue& Value,
TFunction<void(const FPgosResult& Ret)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{

FString PlayerId = TEXT("197177");
FString Key = TEXT("my_lucky_num");
FKVDataValue Value = 777;
PlayerProfile->SetOneOfPlayerKVData(PlayerId, Key, Value, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetOneOfPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetOneOfPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.2.2 SetPlayerKVData Server API

Interface prototype:

/**
* Update kvdata of the specified player.
* The update operation for a player's KVData will either succeed as a whole or fail as a whole.
*
* @param PlayerId Player to update kvdata.
* @param Kvdata KVData to update.
*/
void SetPlayerKVData(
const FString& PlayerId,
const TMap<FString, FKVDataValue>& Kvdata,
TFunction<void(const FPgosResult& Ret)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{

FString PlayerId = TEXT("197177");
TMap<FString, FKVDataValue> Kvdata;
Kvdata.Add(TEXT("num_key"), 100);
Kvdata.Add(TEXT("string_key"), TEXT("abc"));
PlayerProfile->SetPlayerKVData(PlayerId, Kvdata, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.2.3 BatchSetPlayerKVData Server API

Interface prototype:

/**
* Perform a batch update of KVData for multiple players.
* If all player operations are successful, the callback result is success.
* If some player operations succeed while others fail, the callback result is success, and the reasons for the failed players can be obtained from the callback data.
* If all player operations fail, the callback result is failure (kBackendAllFailed), and the reasons for the failed players can be obtained from the callback data.
* The update operation for a player's KVData will either succeed as a whole or fail as a whole.
*/
void BatchSetPlayerKVData(
const TArray<FPlayerKVDataGroup>& Kvdatas,
TFunction<void(const FPgosResult& Ret, const FBatchPlayerOperationResult* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
FPlayerKVDataGroup op1;
op1.player_id = TEXT("197177");
op1.kvdata.Add(TEXT("level"), 30);
op1.kvdata.Add(TEXT("experience"), 5000);

FPlayerKVDataGroup op2;
op2.player_id = TEXT("197178");
op2.kvdata.Add(TEXT("level"), 40);
op2.kvdata.Add(TEXT("experience"), 7000);

TArray<FPlayerKVDataGroup> Kvdatas = { op1, op2};
PlayerProfile->BatchSetPlayerKVData(Kvdatas, [](const FPgosResult& Ret, const FBatchPlayerOperationResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchSetPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchSetPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.2.4 IncrOneOfPlayerKVData Server API

Interface prototype:

/**
* Perform atomic increment operation on a specified kvdata item for a specified player. [Only works on Integer/Float type keys]
* If the operation is successful, the callback will return the updated data.
*
* @param PlayerId Player to operate.
* @param Key Key to operate.
* @param Increment The increment value can be set to int32/int64/float/double.
*/
void IncrOneOfPlayerKVData(
const FString& PlayerId,
const FString& Key,
const FKVDataValue& Increment,
TFunction<void(const FPgosResult& Ret, const FOnePlayerKVData* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{

FString PlayerId = TEXT("197177");
FString Key = TEXT("level");
FKVDataValue Increment = 1;
PlayerProfile->IncrOneOfPlayerKVData(PlayerId, Key, Increment, [](const FPgosResult& Ret, const FOnePlayerKVData* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("IncrOneOfPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("IncrOneOfPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.2.5 BatchIncrOneOfPlayerKVData Server API

Interface prototype:

/**
* Perform a batch atomic increment operation on a specified kvdata item for multiple players. [Only works on Integer/Float type keys]
* If all player operations are successful, the callback result is success.
* If some player operations succeed while others fail, the callback result is success, and the reasons for the failed players can be obtained from the callback data.
* If all player operations fail, the callback result is failure (kBackendAllFailed), and the reasons for the failed players can be obtained from the callback data.
* For the players whose operations are successful, the callback data will contain the new value of their updated kvdata item.
* The update operation for a player's KVData will either succeed as a whole or fail as a whole.
*
* @param PlayerIds Players to operate.
* @param Key Key to operate.
* @param Increment The increment value can be set to int32/int64/float/double.
*/
void BatchIncrOneOfPlayerKVData(
const TArray<FString>& PlayerIds,
const FString& Key,
const FKVDataValue& Increment,
TFunction<void(const FPgosResult& Ret, const FServerBatchIncrOneOfPlayerKVDataRsp* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{

TArray<FString> PlayerIds = {TEXT("197177"), TEXT("197178"), TEXT("197179")};
FString Key = TEXT("experience");
FKVDataValue Increment = 60;
PlayerProfile->BatchIncrOneOfPlayerKVData(PlayerIds, Key, Increment, [](const FPgosResult& Ret, const FServerBatchIncrOneOfPlayerKVDataRsp* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchIncrOneOfPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchIncrOneOfPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.2.6 IncrPlayerKVData Server API

Interface prototype:

/**
* Perform atomic increment operation on multiple kvdata items for a specified player. [Only works on Integer/Float type keys]
* If the operation is successful, the callback will return the updated data.
*
* @param PlayerId Player to operate.
* @param Increments Increments to update, key: kvdata key, value: increment of the value.
*/
void IncrPlayerKVData(
const FString& PlayerId,
const TMap<FString, FKVDataValue>& Increments,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{

FString PlayerId = TEXT("197177");
TMap<FString, FKVDataValue> Increments;
Increments.Add(TEXT("level"), 1);
Increments.Add(TEXT("experience"), 60);
PlayerProfile->IncrPlayerKVData(PlayerId, Increments, [](const FPgosResult& Ret, const FPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("IncrPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("IncrPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.2.7 BatchIncrPlayerKVData Server API

Interface prototype:

/**
* Perform a batch atomic increment operation on multiple kvdata items for multiple players. [Only works on Integer/Float type keys]
* If all player operations are successful, the callback result is success.
* If some player operations succeed while others fail, the callback result is success, and the reasons for the failed players can be obtained from the callback data.
* If all player operations fail, the callback result is failure (kBackendAllFailed), and the reasons for the failed players can be obtained from the callback data.
* For the players whose operations are successful, the callback data will contain the new value of their updated kvdata item.
* The update operation for a player's KVData will either succeed as a whole or fail as a whole.
*
* @param Increments Player kvdata increments list.
*/
void BatchIncrPlayerKVData(
const TArray<FPlayerKVDataGroup>& Increments,
TFunction<void(const FPgosResult& Ret, const FBatchPlayerKVDataGroup* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
FPlayerKVDataGroup op1;
op1.player_id = TEXT("197177");
op1.kvdata.Add(TEXT("level"), 1);
op1.kvdata.Add(TEXT("experience"), 60);

FPlayerKVDataGroup op2;
op2.player_id = TEXT("197178");
op2.kvdata.Add(TEXT("level"), 2);
op2.kvdata.Add(TEXT("experience"), 120);

TArray<FPlayerKVDataGroup> Increments = {op1, op2};
PlayerProfile->BatchIncrPlayerKVData(Increments, [](const FPgosResult& Ret, const FBatchPlayerKVDataGroup* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchIncrPlayerKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchIncrPlayerKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.2.8 SetPlayerVersionedKVData Server API

Interface prototype:

/**
* Update versioned kvdata for the specified player.
* The KVData of the player to be updated must contain at least one versioned key.
* The 'version' needs to pass in can be obtained from the 'GetPlayerVersionedKVData' or 'BatchGetPlayerVersionedKVData' API call.
* If the 'version' passed in is the latest, the callback will return success along with the updated data.
* If the 'version' passed in is not the latest, the callback will return failure(err_code=11108, kBackendKVDataVersionMismatched) along with the current latest data, you may try again with the latest version.
* For other errors, please refer to the error message and the developer manual on the portal, and the callback data is invalid.
*
* @param Data Versioned kvdata items that need to update. Please set version to the latest value you got for the player.
*/
void SetPlayerVersionedKVData(
const FPlayerKVDataGroupWithVer& Data,
TFunction<void(const FPgosResult& Ret, const FPlayerKVDataGroupWithVer* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction(int32 latest_ver)
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
FPlayerKVDataGroupWithVer Data;
Data.player_id = TEXT("197177");
Data.version = latest_ver;
Data.kvdata.Add(TEXT("num_key"), 100);
Data.kvdata.Add(TEXT("string_key"), TEXT("abc"));
PlayerProfile->SetPlayerVersionedKVData(Data, [](const FPgosResult& Ret, const FPlayerKVDataGroupWithVer* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetPlayerVersionedKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetPlayerVersionedKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.2.9 BatchIncrPlayerKVDataIdempotent Server API

Interface prototype:

/**
* Idempotent version of BatchIncrPlayerKVData. Idempotency token could be set for each player.
*
* @param Params Params of BatchIncrPlayerKVDataIdempotent.
*/
void BatchIncrPlayerKVDataIdempotent(
const FServerBatchIncrPlayerKVDataIdempotentParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerBatchIncrPlayerKVDataIdempotentResult* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
FServerBatchIncrPlayerKVDataIdempotentParams Params;
PlayerProfile->BatchIncrPlayerKVDataIdempotent(Params, [](const FPgosResult& Ret, const FServerBatchIncrPlayerKVDataIdempotentResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchIncrPlayerKVDataIdempotent Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchIncrPlayerKVDataIdempotent Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
4.3.2.10 BatchSetPlayerVersionedKVData Server API

Interface prototype:

/**
* Perform a batch update of versioned KVData for multiple players.
* The KVData of the player to be updated must contain at least one versioned key.
* The 'version' needs to pass in can be obtained from the 'GetPlayerVersionedKVData' or 'BatchGetPlayerVersionedKVData' API call.
* If all player operations are successful, the callback result is success.
* If some player operations succeed while others fail, the callback result is success, and the reasons for the failed players can be obtained from the callback data.
* If all player operations fail, the callback result is failure (kBackendAllFailed), and the reasons for the failed players can be obtained from the callback data.
* The update operation for a player's KVData will either succeed as a whole or fail as a whole.
*
* @param Data Versioned kvdata items that need to update. Please set version to the latest value you got for the player.
*/
void BatchSetPlayerVersionedKVData(
const TArray<FPlayerKVDataGroupWithVer>& Data,
TFunction<void(const FPgosResult& Ret, const FServerBatchSetPlayerVersionedKVDataRsp* Data)> Callback) const;

Example Code:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction(int32 latest_ver1, int32 latest_ver2)
{
auto PlayerProfile = IPgosSDKCpp::Get().GetServerPlayerProfileAPI();
if (PlayerProfile)
{
FPlayerKVDataGroupWithVer PlayerData1;
PlayerData1.player_id = TEXT("197177");
PlayerData1.version = latest_ver1;
PlayerData1.kvdata.Add(TEXT("num_key"), 100);
PlayerData1.kvdata.Add(TEXT("string_key"), TEXT("abc"));

FPlayerKVDataGroupWithVer PlayerData2;
PlayerData2.player_id = TEXT("197177");
PlayerData2.version = latest_ver2;
PlayerData2.kvdata.Add(TEXT("num_key"), 100);
PlayerData2.kvdata.Add(TEXT("string_key"), TEXT("abc"));

TArray<FPlayerKVDataGroupWithVer> Data = {PlayerData1, PlayerData2};
PlayerProfile->BatchSetPlayerVersionedKVData(Data, [](const FPgosResult& Ret, const FServerBatchSetPlayerVersionedKVDataRsp* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchSetPlayerVersionedKVData Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchSetPlayerVersionedKVData Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

5. Key Errors Handling

Error CodeRelevant APIHandling Suggestion
kBackendKeyNotExistQuery KVData (Client)

Update KVData (Client)

Query KVData (Server)

Update KVData (Server)
blob key not exist. Check the key whether it's defined on the portal.
kBackendReqPlayerIDIsInvalidQuery KVData (Client)

Query KVData (Server)

Update KVData (Server)
request player_id is invalid.
kBackendClientInaccessibleKeyQuery KVData (Client)key is inaccessible by client. This means that the access permission of the key is server-only or the key you specified is a non-client-public key belonging to other players. Check the key access permission on the portal.
kBackendClientUnwritableKeyUpdate KVData (Client)key is un-writable by client. Check the key access permission on the portal.
kBackendKeyNeedVersionedAPIUpdate KVData (Client)
Update KVData (Server)
failed to update due to the API is only available for non-versioned keys, but the key is versioned.
kBackendNeedVersionedKeyQuery KVData (Client)

Update KVData (Client)

Query KVData (Server)

Update KVData (Server)
failed to update due to the API requires at least one versioned key.
kBackendKVDataVersionMismatchedUpdate KVData (Client)
Update KVData (Server)
failed to update due to version did not matched, and you can get the latest data from response to retry.
kSdkNetworkErrorAll Network APInetwork error, check error msg for detail.