跳到主要内容

Friends

1. 概述

好友服务允许开发者管理玩家的好友列表。玩家可以邀请好友加入组队进行匹配或聊天。

完成本教程后,开发者将了解:

  • 如何管理好友列表
  • 如何处理好友请求
  • 如何处理好友备注
  • 如何监控好友事件
  • 如何搜索玩家
  • 如何获取推荐玩家
  • 如何将平台好友添加为PGOS好友

您可以在Web门户上查询好友列表,如下所示。

friend_list_webportal

##2. 功能

  • 管理好友列表

    • 查询:获取玩家的好友列表。
    • 添加:当玩家A向玩家B发送好友请求 ,玩家B接受请求后,两人成为共同好友。
    • 移除:玩家可以从好友列表中移除玩家,这将取消双方的友谊。
  • 处理好友请求

    • 获取已收到的请求:获取已收到的好友请求列表,每个请求均包含请求玩家的信息、附加的请求消息。
    • 获取已发送的请求:获取已发送的好友请求列表。
    • 接受请求:接受其他玩家的好友请求 。
    • 拒绝请求:拒绝其他玩家的好友请求 。
    • 删除已发送请求:删除发送给其他玩家的好友请求 。
  • 监控好友事件 当以下事件发生时,玩家将收到包含相关信息的推送通知:

    • 添加好友请求 :其他玩家向此玩家发送好友请求 。
    • 添加好友回应:另一个玩家接受了该玩家的好友请求 。
    • 好友已移除:该玩家已从另一个玩家的好友列表中移除。
    • 好友请求徽章数量:当收到的好友请求列表发生变化时。
  • 玩家搜索 根据玩家id和玩家名称搜索玩家。

  • 获取推荐玩家

    • 获取推荐的陌生人:获取一群组陌生人。
    • 获取潜在好友:获取一群组潜在好友。
    • 获取最近的玩家:获取一群组最近一起玩过的玩家。
  • 将OpenID转换为平台PlayerInfos:帮助玩家在PGOS中找到自己平台好友的身份信息。

  • 将AccountID转换为PlayerID:帮助玩家在PGOS中找到自己平台黑名单的身份信息。

3.交互图

添加或删除好友时PGOS Client SDK与Server交互的整个流程: 添加好友:

friend request

移除好友:

friend delete

将账号 openID 转换为玩家信息并批量添加好友:

1621318474845

4. 使用好友服务

4.1 获取好友列表

获取玩家的好友列表。

按如下方式调用 Friend 模块中的 GetFriendList 方法:

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::GetFriendList()
{
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->GetFriendList([](const FPgosResult& Ret, const FClientFriendListInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnGetFriendListSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnGetFriendListFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

如果成功,您将获得玩家的好友列表。

如果失败,请检查错误代码和错误信息以了解发生了什么。

4.2 添加好友

要将其他玩家添加到玩家的好友列表中,您需要获取目标玩家的玩家ID并调用AddFriend函数。

如果您不想接收来自其他玩家的好友请求,可以更新您的隐私设置。点击这里)了解详情。

Friend模块调用AddFriend,如下所示:

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::AddFriend()
{
FClientAddFriendParams Params; // player_id and message.
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->AddFriend(Params, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnAddFriendSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnAddFriendFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

如果成功,目标玩家将收到请求。如果游戏监听了OnAddFriendRequest事件,该事件会在目标玩家一方被触发。目标玩家也可以在其收到的请求列表中看到该请求。

4.3 批量添加好友

4.4 获取好友请求

玩家有两个请求列表:已接收和已发送。

按以下方式调用 Friend 模块中的 GetReceivedFriendRequests

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::GetReceivedFriendRequests()
{
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->GetReceivedFriendRequests([](const FPgosResult& Ret, const FClientFriendReqListInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnGetReceivedFriendRequestsSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnGetReceivedFriendRequestsFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.5 接受好友请求

如果玩家通过AcceptFriendRequest函数接受来自其他玩家的请求,他们将成为互相的好友。

按照以下方式从Friend模块调用AcceptFriendRequest

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::AcceptFriendRequest()
{
FString PlayerId; // The id for target player.
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->AcceptFriendRequest(PlayerId, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnAcceptFriendRequestSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnAcceptFriendRequestFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

如果成功,目标玩家将出现在玩家的好友列表中。如果游戏监听了OnAddFriendResponse事件,该事件将在目标玩家一方被触发。

4.6 拒绝好友请求

玩家可以通过RejectFriendRequest函数拒绝来自其他玩家的好友请求。

请按以下方式从Friend模块调用RejectFriendRequest

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::RejectFriendRequest()
{
FString PlayerId; // The id for target player.
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->RejectFriendRequest(PlayerId, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnRejectFriendRequestSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnRejectFriendRequestFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.7 删除已发送的好友请求

玩家可以从已发送请求列表中删除发送给其他玩家的好友请求。

Friend模块调用DelSentFriendRequest,如下所示:

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::DelSentFriendRequest()
{
FString PlayerId; // The id for target player.
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->DelSentFriendRequest(PlayerId, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnDelSentFriendRequestSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnDelSentFriendRequestFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.8 删除好友

开发者可以使用RemoveFriend函数从好友列表中删除玩家。

Friend模块调用RemoveFriend函数的方法如下:

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::RemoveFriend()
{
FString PlayerId; // The id for target player.
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->RemoveFriend(PlayerId, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnRemoveFriendSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnRemoveFriendFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

如果成功,该玩家将从好友列表中移除。如果游戏监听了OnFriendRemoved事件,双方都会触发该事件。

4.9 搜索玩家

根据指定关键词搜索玩家,关键词将用于对玩家ID和玩家显示名称进行模糊匹配。匹配到的玩家将以数组形式返回。如果关键词完全匹配黑名单中某个玩家的ID,该玩家也会出现在结果中。

如果您不希望被其他玩家搜索到,可以更新您的隐私设置。点击这里)了解详情。

Friend模块调用SearchPlayers/SearchPlayersWithFilter,示例如下:

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::SearchPlayers()
{
FClientSearchPlayersParams Params;
Params.search_key = TEXT("John");
Params.offset = 0;
Params.count = 30;
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->SearchPlayers(Params, [](const FPgosResult& Ret, const FClientPlayerSearchInfoList* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnSearchPlayersSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnSearchPlayersFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

void SomeUObjectClass::SearchPlayersWithFilter()
{
SearchPlayersWithFilter Params;
Params.search_key = TEXT("John");
Params.offset = 0;
Params.count = 30;
Params.search_filter.os.Add(EClientOS::Windows);
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->SearchPlayersWithFilter(Params, [](const FPgosResult& Ret, const FClientPlayerSearchInfoList* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnSearchPlayersSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnSearchPlayersFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.10 获取最近玩家

获取与该玩家最近一起游戏的玩家群组。黑名单中的玩家不会出现在结果中。

Friend模块调用GetRecentPlayers,如下所示:

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::GetRecentPlayers()
{
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->GetRecentPlayers([](const FPgosResult& Ret, const FClientPlayerSearchInfoList* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnGetRecentPlayersSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnGetRecentPlayersFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.11 获取推荐玩家

获取一组随机玩家。黑名单中的玩家不会出现在结果中。

按以下方式调用 Friend 模块中的 GetRecommendedPlayers

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::GetRecommendedPlayers()
{
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->GetRecommendedPlayers([](const FPgosResult& Ret, const FClientPlayerSearchInfoList* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnGetRecommendedPlayersSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnGetRecommendedPlayersFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.12 获取潜在好友

获取系统发现的一组潜在好友。黑名单中的玩家不会出现在结果中。

Friend模块调用GetPotentialPlayers,如下所示:

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::GetPotentialPlayers()
{
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->GetPotentialPlayers([](const FPgosResult& Ret, const FClientPlayerSearchInfoList* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnGetPotentialPlayersSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnGetPotentialPlayersFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.13 订阅好友在线状态

游戏客户端订阅好友在线状态后,后端会向游戏客户端推送 OnFriendPresenceChanged 事件,以便游戏可以更新UI。主要规则如下:

  • 登录后,默认不会向客户端推送好友的在线状态。
  • 订阅后,如果好友的在线状态发生变化(包括在线/离线状态变化和自定义在线状态变化),后台会向客户端推送事件消息。取消订阅后,推送将停止。
  • 默认不推送好友在线状态,主要是出于性能和游戏体验的考虑,尽量减少不必要的推送,以免占用游戏带宽并影响游戏体验(例如,在战斗中推送好友在线状态是没有意义的)。
  • 建议游戏客户端由UI驱动,即在需要查看好友在线状态时(如打开好友列表UI)发起订阅,关闭UI后取消订阅。

Friend 模块调用 SubscribeFriendPresence/UnsubscribeFriendPresence 方法,如下所示:

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

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

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

4.14 好友数量限制

开发者可以在 PGOS 门户网站上通过以下策略配置玩家的最大好友数量:

  • 全局限制:开发者可以设置一个特定值作为所有玩家的最大好友数量。
  • 玩家个人限制:开发者可以使用服务器 API BatchSetPlayerFriendsLimit 为每个玩家设置个人最大好友数量限制。

img

❗ 注意:

无论选择何种策略,玩家的好友数量上限不能超过500。

4.14.1 GetMyFriendsLimit Client API

查询您可以拥有的好友数量上限。

接口原型:

/**
* Query the maximum limit of friends you can have.
*/
void GetMyFriendsLimit(TFunction<void(const FPgosResult& Ret, const FClientGetMyFriendsLimitResult* Data)> Callback) const;

示例代码:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (Friend)
{

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

4.14.2 BatchSetPlayerFriendsLimit Server API

批量设置玩家可拥有的好友数量上限。

仅当PGOS门户配置的策略为"玩家个人限制"时才可调用。

接口原型

/**
* Batch set the maximum limit of friends players can have. (max 100 players, max 500 friends per player)
*
* @param Params Request struct for set friend remark.
*/
void BatchSetPlayerFriendsLimit(
const FServerBatchSetPlayerFriendsLimitParams& Params,
TFunction<void(const FPgosResult& Ret)> Callback) const;

示例代码:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Friend = IPgosSDKCpp::Get().GetServerFriendAPI();
if (Friend)
{
FServerBatchSetPlayerFriendsLimitParams Params;
// Fill Params
Friend->BatchSetPlayerFriendsLimit(Params, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchSetPlayerFriendsLimit Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchSetPlayerFriendsLimit Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.14.3 BatchGetPlayerFriendsLimit Server API

批量查询玩家可拥有的好友数量上限。

接口原型:

/**
* Batch query the maximum limit of friends players can have. (max 100 players)
*
* @param Params Request struct for set friend remark.
*/
void BatchGetPlayerFriendsLimit(
const FServerBatchGetPlayerFriendsLimitParams& Params,
TFunction<void(const FPgosResult& Ret, const FServerBatchGetPlayerFriendsLimitResult* Data)> Callback) const;

示例代码:

#include "PgosSDKCpp.h"

void SomeUObjectClass::SomeFunction()
{
auto Friend = IPgosSDKCpp::Get().GetServerFriendAPI();
if (Friend)
{
FServerBatchGetPlayerFriendsLimitParams Params;
// Fill Params
Friend->BatchGetPlayerFriendsLimit(Params, [](const FPgosResult& Ret, const FServerBatchGetPlayerFriendsLimitResult* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerFriendsLimit Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("BatchGetPlayerFriendsLimit Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}

4.15 监听好友事件

使用好友服务时会触发一些事件。开发者需要监听这些事件并适当处理。

  • OnAddFriendRequest: 收到好友请求。
  • OnAddFriendResponse: 好友请求被接受。
  • OnFriendRemoved: 玩家从好友列表中被移除。
  • OnBadgeNumOfFriendReq: 当玩家登录 PGOS 或收到的好友请求列表发生变化时。
  • OnFriendPresenceChanged: 在订阅好友在线状态,后,当好友的在线状态发生变化时(包括在线/离线状态的变化以及自定义在线状态字符串的变化)。

要监听好友事件:

将动态委托绑定到 OnAddFriendRequest/OnAddFriendResponse/OnFriendRemoved,如下所示:

#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"

void SomeUObjectClass::MonitorFriendEvents()
{
auto friend = IPgosSDKCpp::Get().GetClientFriendAPI();
if (friend)
{
friend->OnAddFriendRequest().AddUObject(this, &SomeUObjectClass::OnAddFriendRequest);
friend->OnAddFriendResponse().AddUObject(this, &SomeUObjectClass::OnAddFriendResponse);
friend->OnFriendRemoved().AddUObject(this, &SomeUObjectClass::OnFriendRemoved);
friend->OnBadgeNumOfFriendReq().AddUObject(this, &SomeUObjectClass::OnBadgeNumOfFriendReq);
friend->OnFriendPresenceChanged().AddUObject(this, &SomeUObjectClass::OnFriendPresenceChanged);
}
}

void SomeUObjectClass::OnAddFriendRequest(const FClientAddFriendRequestEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnAddFriendRequest"));
}

void SomeUObjectClass::OnAddFriendResponse(const FClientAddFriendResponseEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnAddFriendResponse"));
}

void SomeUObjectClass::OnFriendRemoved(const FClientFriendRemovedEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnFriendRemoved"));
}

void SomeUObjectClass::OnBadgeNumOfFriendReq(const FClientBadgeNumOfFriendReqEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnBadgeNumOfFriendReq"));
}

void SomeUObjectClass::OnFriendPresenceChanged(const FClientFriendPresenceChangedEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnFriendPresenceChanged"));
}

5. 关键错误处理

Error Code相关 API处理建议
kBackendErrPlayerIsPunishedAddFriend
BatchAddFriends
AcceptFriendRequest
SearchPlayers
SearchPlayersWithFilter
玩家受到惩罚。msg是一个JSON序列化字符串,包含截止时间(惩罚结束时的Unix时间戳(以秒为单位),小于等于0表示永久惩罚)和原因。