Skip to main content

Friends

1. Overview

The Friends service allows developers to manage the player's friend list. The player can invite friends to join a party for matchmaking or to chat.

After completing this tutorial, developers will know:

  • How to manage friend lists.
  • How to handle friend requests.
  • How to handle friend remark.
  • How to monitor friend events.
  • How to search for players.
  • How to get recommend players.
  • How to add platform friend as PGOS friend.

You can query a friend list on Web Portal as shown below.

friend_list_webportal

2. Features

  • Manage a Friend List

    • Query: Get the player's friend list.
    • Add: When player A sends a friend request to player B and player B accepts the request, they become mutual friends.
    • Remove: A player can remove players from their friend list, which will cancel the friendship on both sides.
  • Handle Friend Requests

    • Get Received Requests: Get a list of received friend requests. Each request contains the requesting player's information, attached request message.

    • Get Sent Requests: Get a list of sent friend requests.

    • Accept Request: Accept a friend request from another player.

    • Reject Request: Reject a friend request from another player.

    • Delete Sent Request: Delete a friend request sent to another player.

  • Monitor Friend Events

    A player will receive a push notification with relevant information when the following events happen:

    • Add Friend Request: Another player sends a friend request to this player.
    • Add Friend Response: Another player has accepted this player's friend request.
    • Friend Removed: This player is removed from another player's friend list.
    • Badge Num Of Friend Requests: When the list of received friend requests changes.
  • Player Searching

    Search players base on player id and player name.

  • Get Recommend Players

    • Get recommended strangers: Get a group of stranger.
    • Get potential friends: Get a group of potential friends.
    • Get recent players: Get a group of players who played together recently.
  • Convert OpenIDs to Platform PlayerInfos: Help players find their platform friends' identity information in PGOS.

  • Convert AccountIDs to PlayerIDs: Help players find their platform blocklist' identity information in PGOS.

3. Interaction Diagram

The whole process of interaction between the PGOS Client SDK and Server when adding or removing a friend:

Add Friend :

friend request

Remove Friend :

friend delete

Convert account openIDs to player infos and batch adding friends:

1621318474845

4. Using the Friends Service

4.1 Get Friend List

Get the player's friend list.

Call GetFriendList from Friend module as follows:

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

If successful, you will get the player's friend list.

If fail, check the error code and error message to see what happened.

4.2 Add a Friend

To add another player to the player's friend list, you need to get the player ID of target player and call the AddFriend function.

If you don't want to receive add-friend requests from other players, you can update your privacy settings. Click here for details.

Call AddFriend from Friend module as follows:

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

If successful, the target player will receive the request. If the game monitors the OnAddFriendRequest event, it will be triggered on the target player's side. The target player can also see the request in their received request list.

4.3 Batch Add Friends

4.4 Get Friend Requests

A player has two request lists, received and sent.

Call GetReceivedFriendRequests from Friend module as follows:

#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 Accept Friend Request

If the player accepts a request from another player through the AcceptFriendRequest function, they will become mutual friends.

Call AcceptFriendRequest from Friend module as follows:

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

If successful, the target player will appear in the player's friend list. If the game monitors the OnAddFriendResponse event, it will be triggered on the target player's side.

4.6 Reject Friend Request

A player can reject a friend request from another player through RejectFriendRequest function.

Call RejectFriendRequest from Friend module as follows:

#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 Delete Sent Friend Request

A player can delete a friend request that is sent to another player from its sent request lsit.

Call DelSentFriendRequest from Friend module as follows:

#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 Remove Friends

Developers can remove players from a friend list using the RemoveFriend function.

Call RemoveFriend from Friend module as follows:

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

If successful, the player will be removed from friend list. If the game monitors the OnFriendRemoved event, it will be triggered on both sides.

4.9 Search For Players

Search for players with specified keywords, the keywords will be used for fuzzy matching based on player ID and player display name. Matched players will be returned as a vector. If the keywords completely hits the ID of a player in the blocklist, the player will appear in the result.

If you don't want to be searched by other players, you can update your privacy settings. Click here for details.

Call SearchPlayers/SearchPlayersWithFilter from Friend module as follows:

#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 Get Recent Players

Get a group of players who recently played with the player. Players in the blocklist will not appear in the result.

Call GetRecentPlayers from Friend module as follows:

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

Get a group of random players. Players in the blocklist will not appear in the result.

Call GetRecommendedPlayers from Friend module as follows:

#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 Get Potential Players

Get a group of potential friends discovered by the system. Players in the blocklist will not appear in the result.

Call GetPotentialPlayers from Friend module as follows:

#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 Subscribe to Friends' Presence

After the game client subscribes to the friend's presence status, the backend will push the OnFriendPresenceChanged event to the game client, so that the game can update the UI. The main rules are as follows:

  • After logging in, the presence status of friends will not be pushed to the client by default.
  • After subscribing, if the friend's presence status changes (including the change of online/offline and custom presence), the background will push the event message to the client. After unsubscribing, the push will stop.
  • Why not push friend presence status by default, mainly for performance and game experience considerations, to minimize unnecessary push, so as not to occupy the game bandwidth and affect the game experience (for example, in a battle, pushing friend presence status is meaningless).
  • It is recommended that the game client be driven by the UI, that is, initiate a subscription when you need to view the presence status of friends (such as opening the UI of friend list), and cancel the subscription after closing the UI.

Call SubscribeFriendPresence/UnsubscribeFriendPresence from Friend module as follows:

#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 Friends Limit

Developers can configure the maximum number of friends for players on the PGOS Portal using the following strategies:

  • Global Limit: Developers can set a specific value as the maximum number of friends for all players.
  • Player Individual Limit: Developers can use the Server API BatchSetPlayerFriendsLimit to set individual limits for each player's maximum number of friends.

img

❗ Note:

Regardless of the strategy chosen, the maximum number of friends for players cannot exceed 500.

4.14.1 GetMyFriendsLimit Client API

Query the maximum limit of friends you can have.

Interface prototype:

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

Example Code:

#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

Batch set the maximum limit of friends players can have.

It can only be called when the strategy configured on the PGOS Portal is "Player Individual Limit".

Interface prototype:

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

Example Code:

#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.

Interface prototype:

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

Example Code:

#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 Monitor Friend Events

Some events will be triggered when using the Friends service. Developers need to monitor these events and deal with them appropriately.

  • OnAddFriendRequest: A friend request is received.
  • OnAddFriendResponse: A friend request is accepted.
  • OnFriendRemoved: A player was removed from the friend list.
  • OnBadgeNumOfFriendReq: When the player login PGOS or the list of received friend requests changes.
  • OnFriendPresenceChanged: After subscribing to friends' presence, when a friend's presence status changed (including the change of online/offline status and the custom presence string).

To monitor friend events:

Bind dynamic delegate to OnAddFriendRequest/OnAddFriendResponse/OnFriendRemoved as follows:

#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. Key Error Handling

Error CodeRelevant APIHandling Suggestion
kBackendErrPlayerIsPunishedAddFriend
BatchAddFriends
AcceptFriendRequest
SearchPlayers
SearchPlayersWithFilter
The player is punished. msg is the json serialized string of deadline(unix timestamp (in seconds) at the end of the punishment, <= 0 means permanent punishment) and reason.