跳到主要内容

玩家 BlobData

1. 概述

PGOS提供玩家Blob数据服务,帮助开发者在游戏中使用二进制大对象。游戏开发者需要先在门户网站上自定义玩家Blob信息(Blob Key name、访问权限等),然后才能在游戏中上传/下载这些Blob。单个Blob的最大大小为100MB。 完成本教程后,您将了解以下内容:

  • 如何在网页门户上自定义玩家Blob数据模板并查看玩家Blob数据。
  • 如何在游戏中查询、下载和更新玩家Blob数据。

2. 自定义 Blob 数据模板

在访问玩家 Blob 数据之前,游戏必须在门户网站上自定义玩家 Blob 信息。登录门户网站,访问您的游戏区服,然后进入玩家 > Blob 数据模板

image-20221124112712026

上图展示了一个示例:该模板有两个key,这意味着游戏中的每个玩家都将独立拥有这两个 Blob 项。游戏可以根据其玩法需求自定义 Blob 项。

2.1 添加/删除 Blob Data 项

  • 使用"添加项"按钮创建新项,然后填写以下详细信息:
  • Key:数据项的键名,由字母、数字和下划线组成。必须以字母开头,且不能超过 128 个字符。
  • 访问权限:定义项的访问权限。
  • -使用"删除项"按钮删除所选数据项。数据项一旦被删除,将无法访问该项。请确保同时修改相关的代码逻辑。

2.2 Blob数据项访问权限

Blob数据的访问权限管理与key-value数据相同,详情请查看key-value数据访问权限

3. 查看玩家Blob数据

登录控制台,进入您的游戏区服,然后前往玩家 > 查询

image-20221116192538298

店家 Player ID查看玩家详情:

image-20221116192920640

4. 使用玩家 Blob 数据

4.1 游戏客户端

4.1.1 查询玩家 Blob

开发者可以通过指定 player_id 和 blob_key 来查询玩家的 blob 信息。玩家的游戏客户端只能查询自己的"非Server-Only"权限的 blob,以及其他玩家的"Client-Public"权限 的blob。 API 原型:

/**
* Get the player blob data information of the specified key.
*
* @param PlayerId The player to query.
* @param BlobKey The blob key to query.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void GetPBDInfo(
const FString& PlayerId,
const FString& BlobKey,
TFunction<void(const FPgosResult& Ret, const FPlayerBlobDataInfo* Data)> ResultCallback) const;

struct FPlayerBlobDataInfo
{
/**
* A downloadable blob url, valid for one hour after the information is obtained.
* To download it, you can use the download function provided by the PGOS Utility module or use the download function implemented by yourself.
*/
FString url;
/** The blob version number, an auto-incrementing number. */
int32 version = 0;
/** The UTC timestamp(in seconds) when the blob was updated. */
int64 last_modified_ts = 0;
/** Size of the blob (in bytes). */
int64 blob_size = 0;
/** MD5 of the blob. */
FString blob_md5;
};

代码示例:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerBlobData = IPgosSDKCpp::Get().GetClientPlayerBlobDataAPI();
if (PlayerBlobData)
{

FString PlayerId = TEXT("33816459");
FString BlobKey = TEXT("GameSave");
PlayerBlobData->GetPBDInfo(PlayerId, BlobKey, [](const FPgosResult& Ret, const FPlayerBlobDataInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPBDInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPBDInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.1.2 下载 Player Blob

4.1.2 下载玩家 Blob

当您从 GetPBDInfo API 获取到 blob 下载链接后,您可以使用自己的 http 下载器进行下载,或使用 PGOS Utility 提供的 http 下载器 API。以下是使用 PGOS Utility API 下载 blob 的示例代码。

❗ 注意:从 GetPBDInfo API 获取的 blob URL 仅在大约一小时内有效。

接口原型:

/**
* Download the specified URL using the http protocol.
*
* @param Url The url to download.
* @param SaveCallback This callback function gets called by PGOS as soon as there is data received that needs to be saved, and it may be called with zero bytes data if the transferred file is empty. It will be called in an ASYNCHRONOUS CHILD THREAD.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void HttpDownloadBuff(
const FString& Url,
TFunction<void(const FPgosBuffer* data)> SaveCallback,
TFunction<void(const FPgosResult& Ret)> ResultCallback) const;

/**
* Download the specified URL to local file using the http protocol.
*
* @param Url The url to download.
* @param SavePath File path to write the data to.
* @param ProgressCallback Data transfer progress callback, which will be called in an ASYNCHRONOUS CHILD THREAD.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void HttpDownloadFile(
const FString& Url,
const FString& SavePath,
TFunction<void(const FHttpDownloadProgressInfo* data)> ProgressCallback,
TFunction<void(const FPgosResult& Ret)> ResultCallback) const;

示例代码:

  • HttpDownloadBuff

    #include "PgosSDKCpp.h"

    void SomeUObjectClass::SomeFunction()
    {
    auto PlayerBlobData = IPgosSDKCpp::Get().GetClientPlayerBlobDataAPI();
    if (PlayerBlobData)
    {
    FString PlayerId = TEXT("33816459");
    FString BlobKey = TEXT("GameSave");
    PlayerBlobData->GetPBDInfo(PlayerId, BlobKey, [this](const FPgosResult& Ret, const FPlayerBlobDataInfo* Data) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("GetPBDInfo Success"));
    DownloadBlobBuffer(Data->url);
    }
    });
    }
    }

    void SomeUObjectClass::DownloadBlobBuffer(const FString& URL)
    {
    auto spBufferHolder = std::make_shared<std::string>();

    auto SaveCallback = [spBufferHolder](const FPgosBuffer* data) {
    spBufferHolder->append(data->buffer_ptr, (size_t)data->buffer_len);
    UE_LOG(LogTemp, Log, TEXT("Http Download SaveCallback: %llu bytes."), data->buffer_len);
    };

    auto Utility = IPgosSDKCpp::Get().GetClientUtilityAPI();
    if (Utility)
    {
    Utility->HttpDownloadBuff(URL, SaveCallback, [](const FPgosResult& Ret) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("HttpDownloadBuff Success"));
    // Process the data in spBufferHolder ...
    }
    else
    {
    UE_LOG(LogTemp, Log, TEXT("HttpDownloadBuff Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
    }
    });
    }
    }
  • DownloadBlobFile

    #include "PgosSDKCpp.h"

    void SomeUObjectClass::SomeFunction()
    {
    auto PlayerBlobData = IPgosSDKCpp::Get().GetClientPlayerBlobDataAPI();
    if (PlayerBlobData)
    {
    FString PlayerId = TEXT("33816459");
    FString BlobKey = TEXT("GameSave");
    PlayerBlobData->GetPBDInfo(PlayerId, BlobKey, [this](const FPgosResult& Ret, const FPlayerBlobDataInfo* Data) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("GetPBDInfo Success"));
    DownloadBlobFile(Data->url);
    }
    });
    }
    }

    void SomeUObjectClass::DownloadBlobFile(const FString& URL)
    {
    FString ProjectSavedPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectSavedDir());
    FString SavePath = ProjectSavedPath + "/GameSave.blob";

    auto ProgressCallback = [](const FHttpDownloadProgressInfo* data) {
    UE_LOG(LogTemp, Log, TEXT("Http Download ProgressCallback: %llu bytes."), data->transfered_size);
    };

    auto Utility = IPgosSDKCpp::Get().GetClientUtilityAPI();
    if (Utility)
    {
    Utility->HttpDownloadFile(URL, SavePath, ProgressCallback, [](const FPgosResult& Ret) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("HttpDownloadFile Success"));
    }
    else
    {
    UE_LOG(LogTemp, Log, TEXT("HttpDownloadFile Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
    }
    });
    }
    }

❗ 注意:SaveCallbackProgressCallback 是在异步子线程中被调用的回调函数。

4.1.3 更新我的玩家 Blob

开发者可以通过内存缓冲区(UpdateMyPBDFromBuff)或本地文件(UpdateMyPBDFromFile)更新玩家 Blob。需要注意的是,使用UpdateMyPBDFromBuff API 会在内部创建 blob 数据的副本,如果缓冲区很大,可能会导致内存使用率过高。因此对于大型 blob 缓冲区,建议使用UpdateMyPBDFromFile API。在更新过程中,开发者可以监控更新进度。玩家的游戏客户端只能更新具有客户端可写权限的 blob。

接口原型:

/**
* Update blob data of the current player from a memory buffer.
* The function will create a copy of blob data internally, if the buffer is very large, this may lead to high memory usage.
* So for the blob buffer with large size, consider using the UpdateMyPBDFromFile API instead.
*
* @param BlobKey The blob key to update.
* @param BlobBuff Blob data buffer to set. If the buffer address pointer is nullptr, the blob data will be reset to 0 bytes.
* @param ProgressCallback Data transfer progress callback, which will be called in an ASYNCHRONOUS CHILD THREAD.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void UpdateMyPBDFromBuff(
const FString& BlobKey,
const FPgosBuffer& BlobBuff,
TFunction<void(const FUpdatePBDProgressInfo* data)> ProgressCallback,
TFunction<void(const FPgosResult& Ret)> ResultCallback) const;

/**
* Update blob data of the current player from a local file.
*
* @param BlobKey The blob key to update.
* @param FilePath The full path to the file to upload. If it is not a UE project (FString), please pass in a full local path (not in utf8 format).
* @param ProgressCallback Data transfer progress callback, which will be called in an ASYNCHRONOUS CHILD THREAD.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void UpdateMyPBDFromFile(
const FString& BlobKey,
const FString& FilePath,
TFunction<void(const FUpdatePBDProgressInfo* data)> ProgressCallback,
TFunction<void(const FPgosResult& Ret)> ResultCallback) const;

示例代码:

  • UpdateMyPBDFromBuff

    #include "PgosSDKCpp.h"

    void SomeUObjectClass::SomeFunction()
    {
    auto PlayerBlobData = IPgosSDKCpp::Get().GetClientPlayerBlobDataAPI();
    if (PlayerBlobData)
    {
    FString BlobKey = TEXT("GameSave");
    std::string buffer("game save content...");
    FPgosBuffer GameSaveBuffer;
    GameSaveBuffer.buffer_ptr = (const char*)buffer.c_str();
    GameSaveBuffer.buffer_len = (int64)buffer.size();

    auto ProgressCallback = [](const FUpdatePBDProgressInfo* data) {
    UE_LOG(LogTemp, Log, TEXT("UpdateMyPBDFromBuff ProgressCallback: player_id=%s, blob_key=%s, transfered_size=%llu, new_blob_size=%llu."), *data->player_id, *data->blob_key, data->transfered_size, data->new_blob_size);
    };

    PlayerBlobData->UpdateMyPBDFromBuff(BlobKey, GameSaveBuffer, ProgressCallback, [](const FPgosResult& Ret) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("UpdateMyPBDFromBuff Success"));
    }
    else
    {
    UE_LOG(LogTemp, Log, TEXT("UpdateMyPBDFromBuff Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
    }
    });
    }
    }
  • UpdateMyPBDFromFile

    #include "PgosSDKCpp.h"

    void SomeUObjectClass::SomeFunction()
    {
    auto PlayerBlobData = IPgosSDKCpp::Get().GetClientPlayerBlobDataAPI();
    if (PlayerBlobData)
    {
    FString BlobKey = TEXT("GameSave");
    FString ProjectSavedPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectSavedDir());
    FString FilePath = ProjectSavedPath + "/GameSave.blob";

    auto ProgressCallback = [](const FUpdatePBDProgressInfo* data) {
    UE_LOG(LogTemp, Log, TEXT("UpdatePBDFromFile ProgressCallback: player_id=%s, blob_key=%s, transfered_size=%llu, new_blob_size=%llu."), *data->player_id, *data->blob_key, data->transfered_size, data->new_blob_size);
    };

    PlayerBlobData->UpdateMyPBDFromFile(BlobKey, FilePath, ProgressCallback, [](const FPgosResult& Ret) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("UpdateMyPBDFromFile Success"));
    }
    else
    {
    UE_LOG(LogTemp, Log, TEXT("UpdateMyPBDFromFile Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
    }
    });
    }
    }

4.1.4 取消更新

开发人员可以在需要时取消正在进行的 Blob 更新。

接口原型:

/**
* Cancel the blob data update operation of the current player.
*
* @param BlobKey The blob key to cancel the update.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void CancelMyPBDUpdate(
const FString& BlobKey,
TFunction<void(const FPgosResult& Ret)> ResultCallback) const;

示例代码:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerBlobData = IPgosSDKCpp::Get().GetClientPlayerBlobDataAPI();
if (PlayerBlobData)
{
FString BlobKey = TEXT("GameSave");
PlayerBlobData->CancelMyPBDUpdate(BlobKey, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("CancelMyPBDUpdate Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("CancelMyPBDUpdate Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

当取消操作完成后,ResultCallback将在游戏线程中运行。

注意:即使指定的更新任务不存在,取消操作也会返回成功。

4.2 游戏服务器

4.2.1 查询玩家 Blob

开发者可以指定 player_id 和 blob_key 来查询玩家的 blob 信息。游戏服务器对所有玩家的 blob 都具有访问权限。当取消操作完成后,ResultCallback 将在游戏线程中运行。

注意:即使指定的更新任务不存在,取消操作也会返回成功。

接口原型:

/**
* Get the player blob data information of the specified key.
*
* @param PlayerId The player to query.
* @param BlobKey The blob key to query.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void GetPBDInfo(
const FString& PlayerId,
const FString& BlobKey,
TFunction<void(const FPgosResult& Ret, const FPlayerBlobDataInfo* Data)> ResultCallback) const;

struct FPlayerBlobDataInfo
{
/**
* A downloadable blob url, valid for one hour after the information is obtained.
* To download it, you can use the download function provided by the PGOS Utility module or use the download function implemented by yourself.
*/
FString url;
/** The blob version number, an auto-incrementing number. */
int32 version = 0;
/** The UTC timestamp(in seconds) when the blob was updated. */
int64 last_modified_ts = 0;
/** Size of the blob (in bytes). */
int64 blob_size = 0;
/** MD5 of the blob. */
FString blob_md5;
};

示例代码:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerBlobData = IPgosSDKCpp::Get().GetServerPlayerBlobDataAPI();
if (PlayerBlobData)
{

FString PlayerId = TEXT("33816459");
FString BlobKey = TEXT("GameSave");
PlayerBlobData->GetPBDInfo(PlayerId, BlobKey, [](const FPgosResult& Ret, const FPlayerBlobDataInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("GetPBDInfo Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("GetPBDInfo Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.2.2 下载玩家 Blob

当您从 GetPBDInfo API 获取到 blob 下载链接后,您可以使用自己的 http 下载器进行下载,或者使用 PGOS Utility 提供的 http 下载器 API。以下是使用 PGOS Utility API 下载 blob 的示例代码。

❗ 注意:从 GetPBDInfo API 获取的 blob 链接仅在大约一小时内有效。

接口原型:

/**
* Download the specified URL using the http protocol.
*
* @param Url The url to download.
* @param SaveCallback This callback function gets called by PGOS as soon as there is data received that needs to be saved, and it may be called with zero bytes data if the transferred file is empty. It will be called in an ASYNCHRONOUS CHILD THREAD.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void HttpDownloadBuff(
const FString& Url,
TFunction<void(const FPgosBuffer* data)> SaveCallback,
TFunction<void(const FPgosResult& Ret)> ResultCallback) const;

/**
* Download the specified URL to local file using the http protocol.
*
* @param Url The url to download.
* @param SavePath File path to write the data to.
* @param ProgressCallback Data transfer progress callback, which will be called in an ASYNCHRONOUS CHILD THREAD.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void HttpDownloadFile(
const FString& Url,
const FString& SavePath,
TFunction<void(const FHttpDownloadProgressInfo* data)> ProgressCallback,
TFunction<void(const FPgosResult& Ret)> ResultCallback) const;

示例代码:

  • HttpDownloadBuff

    #include "PgosSDKCpp.h"

    void SomeUObjectClass::SomeFunction()
    {
    auto PlayerBlobData = IPgosSDKCpp::Get().GetServerPlayerBlobDataAPI();
    if (PlayerBlobData)
    {
    FString PlayerId = TEXT("33816459");
    FString BlobKey = TEXT("GameSave");
    PlayerBlobData->GetPBDInfo(PlayerId, BlobKey, [this](const FPgosResult& Ret, const FPlayerBlobDataInfo* Data) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("GetPBDInfo Success"));
    DownloadBlobBuffer(Data->url);
    }
    });
    }
    }

    void SomeUObjectClass::DownloadBlobBuffer(const FString& URL)
    {
    auto spBufferHolder = std::make_shared<std::string>();

    auto SaveCallback = [spBufferHolder](const FPgosBuffer* data) {
    spBufferHolder->append(data->buffer_ptr, (size_t)data->buffer_len);
    UE_LOG(LogTemp, Log, TEXT("Http Download SaveCallback: %llu bytes."), data->buffer_len);
    };

    auto Utility = IPgosSDKCpp::Get().GetServerUtilityAPI();
    if (Utility)
    {
    Utility->HttpDownloadBuff(URL, SaveCallback, [](const FPgosResult& Ret) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("HttpDownloadBuff Success"));
    // Process the data in spBufferHolder ...
    }
    else
    {
    UE_LOG(LogTemp, Log, TEXT("HttpDownloadBuff Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
    }
    });
    }
    }
  • DownloadBlobFile

    #include "PgosSDKCpp.h"

    void SomeUObjectClass::SomeFunction()
    {
    auto PlayerBlobData = IPgosSDKCpp::Get().GetServerPlayerBlobDataAPI();
    if (PlayerBlobData)
    {
    FString PlayerId = TEXT("33816459");
    FString BlobKey = TEXT("GameSave");
    PlayerBlobData->GetPBDInfo(PlayerId, BlobKey, [this](const FPgosResult& Ret, const FPlayerBlobDataInfo* Data) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("GetPBDInfo Success"));
    DownloadBlobFile(Data->url);
    }
    });
    }
    }

    void SomeUObjectClass::DownloadBlobFile(const FString& URL)
    {
    FString ProjectSavedPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectSavedDir());
    FString SavePath = ProjectSavedPath + "/GameSave.blob";

    auto ProgressCallback = [](const FHttpDownloadProgressInfo* data) {
    UE_LOG(LogTemp, Log, TEXT("Http Download ProgressCallback: %llu bytes."), data->transfered_size);
    };

    auto Utility = IPgosSDKCpp::Get().GetServerUtilityAPI();
    if (Utility)
    {
    Utility->HttpDownloadFile(URL, SavePath, ProgressCallback, [](const FPgosResult& Ret) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("HttpDownloadFile Success"));
    }
    else
    {
    UE_LOG(LogTemp, Log, TEXT("HttpDownloadFile Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
    }
    });
    }
    }

❗ 注意:SaveCallbackProgressCallback 是在异步子线程中被调用的回调函数。 :::tip

4.2.3 更新玩家 Blob

开发者可以通过内存缓冲区(UpdatePBDFromBuff)或本地文件(UpdatePBDFromFile)更新玩家 Blob。需要注意的是,使用 UpdatePBDFromBuff API 会在内部创建 blob 数据的副本,如果缓冲区很大,可能会导致内存使用率过高。因此对于大型 blob 缓冲区,建议使用 UpdatePBDFromFile API。在更新过程中,开发者可以监控更新进度。游戏服务器对所有玩家 Blob 都具有更新权限。

接口原型:

/**
* Update the player blob data from a memory buffer.
* The function will create a copy of blob data internally, if the buffer is very large, this may lead to high memory usage.
* So for the blob buffer with large size, consider using the UpdatePBDFromFile API instead.
*
* @param PlayerId The player to update blob data.
* @param BlobKey The blob key to update.
* @param BlobBuff Blob data buffer to set. If the buffer address pointer is nullptr, the blob data will be reset to 0 bytes.
* @param ProgressCallback Data transfer progress callback, which will be called in an ASYNCHRONOUS CHILD THREAD.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void UpdatePBDFromBuff(
const FString& PlayerId,
const FString& BlobKey,
const FPgosBuffer& BlobBuff,
TFunction<void(const FUpdatePBDProgressInfo* data)> ProgressCallback,
TFunction<void(const FPgosResult& Ret)> ResultCallback) const;

/**
* Update the player blob data from a local file.
*
* @param PlayerId The player to update blob data.
* @param BlobKey The blob key to update.
* @param FilePath The full path to the file to upload. If it is not a UE project (FString), please pass in a full local path (not in utf8 format).
* @param ProgressCallback Data transfer progress callback, which will be called in an ASYNCHRONOUS CHILD THREAD.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void UpdatePBDFromFile(
const FString& PlayerId,
const FString& BlobKey,
const FString& FilePath,
TFunction<void(const FUpdatePBDProgressInfo* data)> ProgressCallback,
TFunction<void(const FPgosResult& Ret)> ResultCallback) const;

示例代码:

  • UpdatePBDFromBuff

    #include "PgosSDKCpp.h"

    void SomeUObjectClass::SomeFunction()
    {
    auto PlayerBlobData = IPgosSDKCpp::Get().GetServerPlayerBlobDataAPI();
    if (PlayerBlobData)
    {
    FString PlayerId = TEXT("33816459");
    FString BlobKey = TEXT("GameSave");
    std::string buffer("game save content...");
    FPgosBuffer GameSaveBuffer;
    GameSaveBuffer.buffer_ptr = (const char*)buffer.c_str();
    GameSaveBuffer.buffer_len = (int64)buffer.size();

    auto ProgressCallback = [](const FUpdatePBDProgressInfo* data) {
    UE_LOG(LogTemp, Log, TEXT("UpdatePBDFromBuff ProgressCallback: player_id=%s, blob_key=%s, transfered_size=%llu, new_blob_size=%llu."), *data->player_id, *data->blob_key, data->transfered_size, data->new_blob_size);
    };

    PlayerBlobData->UpdatePBDFromBuff(PlayerId, BlobKey, GameSaveBuffer, ProgressCallback, [](const FPgosResult& Ret) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("UpdatePBDFromBuff Success"));
    }
    else
    {
    UE_LOG(LogTemp, Log, TEXT("UpdatePBDFromBuff Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
    }
    });
    }
    }
  • UpdatePBDFromFile

    #include "PgosSDKCpp.h"

    void SomeUObjectClass::SomeFunction()
    {
    auto PlayerBlobData = IPgosSDKCpp::Get().GetServerPlayerBlobDataAPI();
    if (PlayerBlobData)
    {
    FString PlayerId = TEXT("33816459");
    FString BlobKey = TEXT("GameSave");
    FString ProjectSavedPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectSavedDir());
    FString FilePath = ProjectSavedPath + "/GameSave.blob";
    auto ProgressCallback = [](const FUpdatePBDProgressInfo* data) {
    UE_LOG(LogTemp, Log, TEXT("UpdatePBDFromFile ProgressCallback: player_id=%s, blob_key=%s, transfered_size=%llu, new_blob_size=%llu."), *data->player_id, *data->blob_key, data->transfered_size, data->new_blob_size);
    };

    PlayerBlobData->UpdatePBDFromFile(PlayerId, BlobKey, FilePath, ProgressCallback, [](const FPgosResult& Ret) {
    if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
    {
    UE_LOG(LogTemp, Log, TEXT("UpdatePBDFromFile Success"));
    }
    else
    {
    UE_LOG(LogTemp, Log, TEXT("UpdatePBDFromFile Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
    }
    });
    }
    }

4.2.4 取消更新

开发人员可以在需要时取消正在进行的 Blob 更新。

接口原型:

/**
* Cancel the update operation of the player blob data.
*
* @param PlayerId The player to be cancelled from updating blob data.
* @param BlobKey The blob key to cancel the update.
* @param ResultCallback The result callback after the API execution ends, and it will be called in the GAME THREAD.
*/
void CancelPBDUpdate(
const FString& PlayerId,
const FString& BlobKey,
TFunction<void(const FPgosResult& Ret)> ResultCallback) const;

示例代码:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto PlayerBlobData = IPgosSDKCpp::Get().GetServerPlayerBlobDataAPI();
if (PlayerBlobData)
{
FString PlayerId = TEXT("33816459");
FString BlobKey = TEXT("GameSave");
PlayerBlobData->CancelPBDUpdate(PlayerId, BlobKey, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("CancelPBDUpdate Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("CancelPBDUpdate Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

取消操作完成后,ResultCallback将在游戏线程中运行。

注意:即使指定的更新任务不存在,取消操作也会返回成功。When the cancel operation is completed, the ResultCallback

5. Key Error Handling

Error CodeRelevant APIHandling Suggestion
kBackendKeyNotExistGetPBDInfo (Client)
GetPBDInfo (Server)
UpdateMyPBDFromBuff
UpdateMyPBDFromFile
UpdatePBDFromBuff
UpdatePBDFromFile
Blob key 不存在。请检查是否已在门户网站中定义该 key 。
kBackendReqPlayerIDIsInvalidGetPBDInfo (Client)
GetPBDInfo (Server)
UpdatePBDFromBuff
UpdatePBDFromFile
请求的玩家ID无效。
kBackendBlobItemNotExistGetPBDInfo (Client)
GetPBDInfo (Server)
Blob 数据未初始化。这表示该 Blob 从未被更新过。
kBackendClientInaccessibleKeyGetPBDInfo (Client)客户端无法访问该密钥。这意味着该密钥的访问权限为仅服务器可用,或者您指定的密钥是属于其他玩家的非客户端公开密钥。请在门户网站上检查密钥的访问权限。
kBackendBlobNotOwnerGetPBDInfo (Client)
密钥只能由其所有者访问。这意味着您指定的密钥是属于其他玩家的非客户端公开密钥。请在门户网站上检查密钥的访问权限。
kSdkCreateFileFailedHttpDownloadFile (Client)
HttpDownloadFile (Server)
无法创建文件,请确保路径正确且您具有相应的权限。
kSdkOpenTheUploadFileFailedUpdateMyPBDFromFile
UpdatePBDFromFile
无法打开要上传的文件,请检查文件是否可读。
kSdkUploadCanceledByAnotherCallUpdateMyPBDFromBuff
UpdateMyPBDFromFile
UpdatePBDFromBuff
UpdatePBDFromFile
上传被另一个API调用取消。
kSdkLastOperationNotCompletedUpdateMyPBDFromBuff
UpdateMyPBDFromFile
UpdatePBDFromBuff
UpdatePBDFromFile
上一个同类型操作(相同玩家ID和密钥)尚未完成。要执行当前操作,请等待或取消上一个操作。
kBackendClientUnwritableKeyUpdateMyPBDFromBuff
UpdateMyPBDFromFile
客户端无法写入密钥。请在门户网站上检查密钥的访问权限。
kSdkNetworkErrorAll Network API网络错误,请查看错误信息了解详情。