跳到主要内容

集成PGOS C++ SDK

本文介绍使用 PGOS C++ SDK 的一般步骤,以 Visual Studio + PGOS Windows SDK 为例进行说明,您可以下载 C++ SDK 示例 作为参考。

1. Sample 结构介绍

image-20240905145934316

C++ SDK 示例包含两个子项目,用于演示 PGOS 客户端/服务器 SDK。所有项目均通过 CMake 管理:

  • ClientSample:用于演示 PGOS 客户端 SDK 的子项目。

  • ServerSample:用于演示 PGOS 服务器 SDK 的子项目。

  • deps:包含 PGOS SDK 和一些通用代码。在下面的截图中,我们将 PGOS SDK 包中的 windows 目录重命名为 ./deps 中的 pgos_sdk_windows

image-20231127201511216

  • Script: Contains a batch script for generating a Visual Studio solution and completing the build process.

2. PGOS SDK的附加包含目录

  • 对于客户端示例CMakeLists文件:

image-20240905151538838

/deps/pgos_sdk_windows/include/pgos_core/raw

/deps/pgos_sdk_windows/include/pgos_core

/deps/pgos_sdk_windows/include/pgos_client/raw

/deps/pgos_sdk_windows/include/pgos_client

  • 服务器示例 CMakeLists 文件:

    image-20240905151811146

    /deps/pgos_sdk_windows/include/pgos_core/raw

    /deps/pgos_sdk_windows/include/pgos_core

    /deps/pgos_sdk_windows/include/pgos_server/raw

    /deps/pgos_sdk_windows/include/pgos_server

3. 更改 Build 配置

PGOS SDK 目前仅提供 Windows 的 x64 Release 版本。

image-20231026162843297

4. 客户端编码

4.1 基本步骤

  • 添加头文件引用

    #include "pgos_client_sdk.h"
  • 创建和销毁 PGOS

    void CreatePGOS() {
    auto sdk = pgos::client::ClientSDK();
    if (sdk) {
    auto root_dir = GetRootDir();
    sdk->InitSdk(root_dir.append("/pgos/"), root_dir.append("/pgos_res/"));

    // the original secret key can be obtained from the developer portal,
    // it is recommended not to hardcode the original secret key in the code.
    const char* encrypted_secret_key = "the ciphertext of the original secret key";
    auto secret_key = SimpleDecrypt(encrypted_secret_key);

    pgos::pmap<pgos::pstring, pgos::pstring> cfgs;
    cfgs["title_id"] = "your title id"; // obtain from the developer portal
    cfgs["secret_key"] = secret_key;
    sdk->InitConfig(cfgs);
    }
    }

    void DestoryPGOS() {
    auto sdk = pgos::client::ClientSDK();
    if (sdk) {
    sdk->Destroy();
    }
    }

    int main()
    {
    CreatePGOS();

    // other business code...

    DestoryPGOS();
    return 0;
    }
  • 如何获取PGOS模块**

    所有模块都可以通过pgos_client_sdk.h中的帮助函数找到并获取对象指针,然后您就可以调用模块的API。

    // get module object pointers.
    auto sdk = pgos::client::ClientSDK();
    auto fas = pgos::client::FakeAccount();
    auto auth = pgos::client::PlayerAuth();
    // ...

    // call module APIs.
    auto my_player_id = auth->MyPlayerID();
    // ...

    在实际调用 PGOS 服务之前,您必须先成功登录 PGOS(调用 IPlayerAuth::LoginPGOS API)。

  • 如何监听模块事件

    通过模块的 SetOn*() API 绑定处理函数或 lambda 表达式到事件:

    auto auth = pgos::client::PlayerAuth();
    if (!auth) {
    return;
    }

    auth->SetOnPlayerBanned(OnPlayerBanned);
    auth->SetOnPlayerSessionChanged(
    [](const PlayerSessionChangedEvt& event) {
    // todo
    });
  • 重要说明

    • 在PGOS C++ SDK中,所有API回调和事件回调都在子线程中执行,因此在回调中访问数据时需要考虑线程安全问题。
    • 在访问PGOS服务时,无论使用C++ SDK还是Unreal插件,整体流程和方法都是相同的。因此,关于PGOS SDK的更多使用细节,您也可以参考服务手册

4.2 客户端示例工作流程

客户端示例的工作流程由状态机管理。以下是示例在每个状态下执行的任务说明。

  • Idle: 等待状态转换。
  • ToLoginAccountSystem: 正在登录账号系统。在客户端示例中使用PGOS临时账号系统完成此操作。
  • ToLoginPGOS: 登录账号系统后需要登录PGOS。
  • ToChooseTask: 选择要执行的任务。提供以下选项:
  • 发起单人匹配,用户需要输入匹配配置名称。
  • 直接连接到服务器示例,用户需要输入DS端口。
  • ToConnectDS: 直接连接到DS。用户需要输入DS端口。
  • ToMatchmaking: 发起单人匹配。用户需要输入匹配配置ID。
  • ToStop: 终止示例。
// ClientSample.cpp
enum class ClientState {
Idle, // do nothing and wait state change.
ToLoginAccountSystem, // login account system.
ToLoginPGOS, // login PGOS.
ToChooseTask, // choose to start matchmaking or connect DS directly.
ToMatchmaking, // start matchmaking and wait till complete.
ToConnectDS, // connect to DS when matchmaking complete.
ToStop, // client stop.
};

注意:要使用ToMatchmaking功能,您必须先将服务器示例部署到PGOS DS托管服务。有关相关功能的更多信息,请参阅以下文档:

5. 服务器编程

5.1 基本步骤

  • 添加头文件引用

    #include "pgos_server_sdk.h"
  • 创建和销毁 PGOS

    void CreatePGOS() {
    auto sdk = pgos::server::ServerSDK();
    if (sdk) {
    auto root_dir = GetRootDir();
    sdk->InitSdk(root_dir.append("/pgos/"), root_dir.append("/pgos_res/"));

    pgos::pmap<pgos::pstring, pgos::pstring> cfgs;
    cfgs["title_id"] = "your title id"; // obtain from the developer portal
    sdk->InitConfig(cfgs);
    }
    }

    void DestoryPGOS() {
    auto sdk = pgos::server::ServerSDK();
    if (sdk) {
    sdk->Destroy();
    }
    }

    int main()
    {
    CreatePGOS();

    // other business code...

    DestoryPGOS();
    return 0;
    }
  • 如何获取PGOS模块

    所有模块都可以通过pgos_server_sdk.h中的帮助函数找到并获取对象指针,然后您就可以调用模块API。

    // get module object pointers.
    auto sdk = pgos::server::ServerSDK();
    auto hosting = pgos::server::Hosting();
    auto player_profile = pgos::server::PlayerProfile();
    // ...

    // call module APIs.
    player_profile->GetPlayerInfo(...);
    // ...
  • 如何监听模块事件

    通过模块的 SetOn*() API 将处理函数或 lambda 表达式绑定到事件:

    auto hosting = pgos::server::Hosting();
    if (!hosting) {
    return;
    }

    hosting->SetOnHealthCheck(OnHealthCheck);
    hosting->SetOnStartBattleSession(
    [](const pgos::server::BattleSession & battle_session) {
    // todo
    });

    重要说明

    • 在PGOS C++ SDK中,所有API回调和事件回调都在子线程中执行,因此在回调中访问数据时需要考虑线程安全问题。
    • 在访问PGOS服务时,无论使用C++ SDK还是Unreal插件,整体流程和方法都是相同的。因此,关于PGOS SDK的更多使用细节,您也可以参考服务手册

5.2 服务器示例的工作流程

服务器示例在本地运行时会将自身注册为本地 DS。您也可以将服务器示例部署到 Fleet 中作为在线 DS。

运行后,服务器示例会启动一个 TCP 服务器来处理客户端连接请求,并在 WorkLoop 线程中管理进程声明周期。

// server life cycle control 
std::thread workerThread(WorkLoop);

// will block until the g_server stops.
g_server.Run();

if (workerThread.joinable()) {
workerThread.join();
}

以下回调函数用于处理战斗会话放置请求和玩家事件。有关管理战斗会话的更多详细信息,请参阅战斗会话

// monitor hosting events
hosting->SetOnHealthCheck(OnHealthCheck);
hosting->SetOnStartBattleSession(OnStartBattleSession);
hosting->SetOnProcessTerminate(OnProcessTerminate);
hosting->SetOnPlayerBattleSessionsTerminated(OnPlayerSessionTerminated);
hosting->SetOnBattleSessionUpdated(OnBattleSessionUpdated);
hosting->SetOnBattlePlayerBanned(OnBattlePlayerBanned);
hosting->SetOnBattlePlayerOffline(OnBattlePlayerOffline);

6. 运行工程

构建工程并获取可执行文件,将 pgos_client/pgos_server 二进制文件复制到可执行文件所在的目录,然后即可运行或调试程序。

二进制文件位于 SDK 的 bin 目录中。