跳到主要内容

玩家 KV 数据

1. 概述

玩家key-value数据是与玩家关联的一组数据。具体来说,它是一系列在网页控制台中定义的key-value键值对,通常与游戏玩法相关并由游戏本身配置,例如玩家等级和角色攻击力。

完成本教程后,您将了解以下内容:

  • 如何在控制台中自定义玩家kv data模板并查看玩家kv data。
  • 如何在代码中查询和更新玩家kv data。

2. 自定义 KVData 模板

在访问玩家数据之前,游戏必须在网页控制台上自定义其专属的玩家数据模板。

登录网页控制台,进入您的游戏区服,然后前往玩家 > KVData 模板

image-20231123174227746

上述截图展示了一个示例。该数据模板包含4个键值,意味着游戏中的每个玩家都将独立拥有这4个数据项。游戏可以根据其玩法需求自定义这些数据项。

2.1 添加/删除 KV 数据项

  • 使用"添加项目"按钮创建新的数据项,然后填写以下详细信息:

  • 键名:数据项的键名,由字母、数字和下划线组成。必须以字母开头,且不能超过128个字符。键名区分大小写,这意味着"KEY_NAME"和"key_name"将被视为相同的键。

  • 类型:数据项的类型,可以是字符串、整数(支持Int64)或浮点数(支持float64)。

  • 默认值:在游戏中更新之前,玩家数据项的值。

  • 使用"删除项目"按钮删除选定的数据项。一旦数据项被删除,通过PGOS SDK、匹配规则集等方式访问该项目将会失败。请确保同时修改相关的代码逻辑。

  • 可创建的KV数据项数量上限为1000个。

2.2 KV Data 数据项访问权限

访问权限具有三个并行属性:

  • 仅服务器:当为 true 时,该数据项只能由游戏服务器访问。

  • 客户端可写:当为 true 时,该数据项可以由数据所有者更新。

  • 客户端公开:当为 true 时,该数据项可以被其他玩家查看。

image-20210810115511084

通常情况下:

  • 游戏服务器(DS或VS)有权限访问所有玩家的数据项。
  • 游戏客户端可以更新当前玩家的客户端可写数据项。它无法更新其他玩家的数据项。

下图中的数据模板示例说明了具体的玩家数据访问权限:

image-20231123174413832

  • 数据项 experience
  • 游戏服务器可读写。
  • 数据所属玩家可读但不可写。
  • 其他玩家不可见(不可读写)。
  • 数据项 level
  • 游戏服务器可读写。
  • 数据所属玩家可读但不可写。
  • 其他玩家可读但不可写。
  • 数据项 mood
  • 游戏服务器可读写。
  • 数据所属玩家可读写。
  • 其他玩家可读但不可写。
  • 数据项 mmr
  • 游戏服务器可读写。
  • 数据所属玩家不可见(不可读写)。
  • 其他玩家不可见(不可读写)。

2.3 KVData Item 版本控制

image-20231123205603837

versioned 属性指定键是否需要严格的版本控制。它适用于需要基于最新原始值进行严格更新的键值。例如,在游戏中,玩家的 Buff 通过玩家 KV Data 保存。当玩家满足特定条件时,Buff 会在当前值的基础上增加 10%,而这种增加可能会在多个地方(云函数、DS)触发。为了防止在多个地方同时更新 Buff 可能导致的数据错误,需要将 Buff 标记为 versioned,并调用 Set*VersionedKVData API 来更新它。每个玩家的 KV Data versioned key都有一个版本号,该版本号仅在 versioned key更新时才会增加。versioned key只能使用 Incr*KVDataSet*VersionedKVData API 进行更新。以下是 versioned key和非 versioned key相关 API 的可用性:

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

通常情况下,Incr*KVData API 既适用于带版本的key也适用于不带版本的键。SetVersionedKVData API 仅适用于至少包含一个带版本key的情况。GetVersionedKVData API 也遵循相同的规则。

提示

一般来说,不带版本key的读写操作速度较快,而带版本key的操作相对较慢。因此,游戏应该只在必要时才将key标记为带版本。此外,在调用 Set*VersionedKVData API 更新带版本key的值之前,需要先调用 Get*VersionedKVData API 获取玩家带版本key的版本号。

HTTP Backend API 的行为与相应的 Server SDK API 的行为是一致的。

2.4 KV Data 分组

游戏可以直接管理和访问所有数据项。但是,当数据项较多时,这种方式会显得杂乱无序。为了让游戏能更好地管理玩家数据,我们引入了数据分组机制,如下图所示:

image-20210812194822621

如您所见,游戏可以使用分组来关联多个数据项以进行统一管理和访问。下面,我们将通过一个典型场景来说明如何在游戏中使用分组机制。

分组应用的典型场景:

假设您想要渲染玩家的详细信息。除了玩家的名称和头像(可以从玩家信息中获取)之外,您还想包含玩家等级、经验值、胜场数和负场数,如下图所示:

image-20210812164150613

显然,最好将这些数据项存储在玩家数据中。因此,您需要在玩家数据模板中定义这些数据,并让游戏服务器在适当的时候更新数据,如下图所示:

image-20210812170420540

这些数据项分散在数据模板的各个位置,因此很难找到和管理。所以,将它们放在一个分组中是个不错的主意。

点击左侧的"Add Group"按钮添加一个名为"profile_view"的分组,如下图所示:

image-20210812172227809

可创建的 KV 数据群组数量上限为 100。

如下图所示,将 levelexperiencewin_cntlost_cnt 添加到 profile_view 分组中:

image-20210812173816583

然后,您可以使用分组名称在门户网站上找到该分组,如下图所示:

image-20210812174920793

完成上述操作后,当您渲染玩家详细信息时,可以使用分组名称轻松在 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;

需要您注意的一些信息:

  • 在门户网站上,您可以创建和删除数据分组,但创建的分组数量不能超过100个。

  • 分组名称只能由字母和数字组成,必须以字母开头,且不能超过64个字符。

  • 单个数据项可以放置在多个分组中。

  • 当游戏客户端请求分组中的数据项时,PGOS后端只会返回请求者有权限访问的数据项。

  • DS和云函数可以访问分组中的所有数据项。

2.5 公共 KVData

我们将对所有其他玩家可见的数据项集合(Client Public = true)称为"公共数据"。

image-20210812205135005

这是一个特殊的数据集,在游戏的玩家资料界面中经常被访问。因此,我们在 PGOS Client SDK 中提供了可以直接访问它的 API:

  • 获取单个玩家的公开数据: 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;
};
  • 获取多个玩家的公开数据: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. 查看玩家 KVData

登录网页门户,进入您的游戏区服,然后前往玩家 > 查询

image-20210809163842712

点击玩家的ID以查看玩家详细信息:

image-20210811180415078

4. 使用玩家 KVData

4.1 KVData 结构

数据项的值被分类为不同的类型(字符串、整数或浮点数),这些值在 PlayerData API 的输入和输出中必然会用到。为了让开发者更容易引用和设置这些值,我们将它们抽象为 FKVDataValue 结构:

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); };
};

如您所见,FKVDataValue 实现了多个构造函数和重载运算符,使开发者可以直接将其他数据类型(TCHAR*/FString/int32/int64/float/double)的值设置给 FKVDataValue 实例。同样地,开发者也可以使用 FKVDataValue 实例直接设置其他数据类型(TCHAR*/FString/int32/int64/float/double)的值。示例代码如下:

// (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 游戏客户端

4.2.1 查询玩家 KVData

获取当前玩家的数据:

APIDescription
GetOneOfMyKVData获取当前玩家的指定 KV Data。
GetMyKVData获取当前玩家的特定 KV Data。
GetAllOfMyKVData获取当前玩家所有可访问的 KV Data。
GetMyPublicKVData获取当前玩家的所有公开 KV Data。
GetMyGroupKVData获取当前玩家指定群组的 KV Data。
GetMyVersionedKVData获取当前玩家的特定版本的KV Data。

获取其他玩家的玩家数据:

APIDescription
GetOneOfPlayerKVData获取指定玩家的指定 KV Data。
GetPlayerKVData获取指定玩家的KV Data。
BatchGetPlayerKVData批量获取多个玩家的 KV Data
GetPlayerPublicKVData批量指定玩家的所有公开 KV Data。
BatchGetPlayerPublicKVData批量查询多个玩家的公开 KV Data 。
GetPlayerGroupKVData获取指定玩家的指定分组的KV Data
BatchGetPlayerGroupKVData批量查询多个玩家的指定分组的 KV Data。

API details:

4.2.1.1 GetOneOfMyKVData Client API

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

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

示例代码:

#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

接口原型:

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

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口代码:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

更新当前玩家的玩家数据:

APIDescription
SetOneOfMyKVData更新当前玩家的指定 KVData。
SetMyKVData更新当前玩家的KVData。
IncrOneOfMyKVData对当前玩家的特定 KVData 项执行原子递增操作。
IncrMyKVData对当前玩家的多个KVData项执行原子递增操作。
SetMyVersionedKVData更新当前玩家的versioned KV Data。

API details:

4.2.2.1 SetOneOfMyKVData Client API

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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 查询 Player KVData

获取玩家数据:

APIDescription
GetOneOfPlayerKVData查询指定玩家的指定KV Data
GetPlayerKVData查询指定玩家的KV Data
BatchGetPlayerKVData批量查询多个玩家的KV Data。
GetPlayerGroupKVData查询指定玩家的指定分组的KV Data。
BatchGetPlayerGroupKVData批量查询多个玩家的指定分组的KV Data。
GetPlayerVersionedKVData查询指定玩家的特定versioned KV Data
BatchGetPlayerVersionedKVData批量查询多个玩家的versioned KV Data

API details:

4.3.1.1 GetOneOfPlayerKVData Server API

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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 更新玩家 KV Data

更新玩家数据:

APIDescription
SetOneOfPlayerKVData更新指定玩家的指定KV Data
SetPlayerKVData更新指定玩家的KV Data
BatchSetPlayerKVData批量更新多个玩家的 KV Data。
IncrOneOfPlayerKVData对指定玩家的指定 KV Data 项执行原子递增操作。
BatchIncrOneOfPlayerKVData对多个玩家的指定 KV Data项执行批量原子递增操作。
IncrPlayerKVData对指定玩家的多个 KV Data项执行原子递增操作。
BatchIncrPlayerKVData对多个玩家的多个KV Data项执行批量原子递增操作。
SetPlayerVersionedKVData更新指定玩家的 versioned KV Data。玩家的KV Data必须至少包含一个带版本号的Key。
BatchIncrPlayerKVDataIdempotentBatchIncrPlayerKVData的幂等版本。每个玩家都可以设置幂等token。
BatchSetPlayerVersionedKVData批量更新多个玩家的versioned KV Data

API details:

4.3.2.1 SetOneOfPlayerKVData Server API

接口原型:

/**
* 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;

示例:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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

接口原型:

/**
* 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;

示例代码:

#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 密钥不存在。请检查是否已在门户网站中定义该密钥。
kBackendReqPlayerIDIsInvalidQuery KVData (Client)

Query KVData (Server)

Update KVData (Server)
请求的玩家ID无效。
kBackendClientInaccessibleKeyQuery KVData (Client)客户端无法访问该密钥。这意味着该密钥的访问权限为仅服务器可用,或者您指定的密钥是属于其他玩家的非客户端公开密钥。请在门户网站上检查密钥的访问权限。
kBackendClientUnwritableKeyUpdate KVData (Client)客户端无法写入密钥。请在门户网站上检查密钥的访问权限。
kBackendKeyNeedVersionedAPIUpdate KVData (Client)
Update KVData (Server)
更新失败,因为该API仅适用于非版本化密钥,但当前密钥已启用版本控制。
kBackendNeedVersionedKeyQuery KVData (Client)

Update KVData (Client)

Query KVData (Server)

Update KVData (Server)
更新失败,因为 API 至少需要一个带版本的密钥。
kBackendKVDataVersionMismatchedUpdate KVData (Client)
Update KVData (Server)
由于版本不匹配导致更新失败,您可以从响应中获取最新数据重试。
kSdkNetworkErrorAll Network API网络错误,请查看错误信息了解详情。