Party
1. Overview
Party is a service for creating an instant team for players. The player can use it to build a "temporary virtual team" and then fire a battle. It includes party creation, player invitations, custom data, and party event dispatching. There is a leader and multiple members in a party. All players have permission to create a party. Once created, the creator is the leader by default, but the leadership can be transferred to other members if necessary. Since the party is an instant team, the player will be removed from the party once leaving the party manually or offline.
2. Architecture Diagram
Game accesses the party service through the PGOS client SDK, and includes two types of interaction. One is client invocation via the HTTPS protocol. The other is the client event, which is a message pushed by the push service in the PGOS backend and implemented through a WebSocket persistent connection that is automatically established and maintained by the PGOS client SDK after authentication. All events are triggered by the SDK as push messages, which also notifies the game.
3. Core Features and Rules
3.1 Create Party
Any player can create a party, but a player can only create/join one party concurrently.
Call CreateParty
from Party module as follows:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::CreateParty()
{
auto party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (party)
{
FClientCreatePartyParams Params;
Params.party_name = "A Name";
Params.max_player = 0;
Params.enable_chatting = false;
Params.join_strategy = EClientPartyJoinStrategy::Public;
Params.invite_strategy = EClientPartyInviteStrategy::AllMembersCanInvite;
party->CreateParty(Params, [](const FPgosResult& Ret, const FClientPartyInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnCreatePartySuccess: party_id=%s"), *Data->party_id);
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnCreatePartyFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientPartyAPI.h"
void SomeUObjectClass::CreateParty()
{
FClientCreatePartyParams Params;
Params.party_name = "A Name";
Params.max_player = 0;
Params.enable_chatting = false;
Params.join_strategy = EClientPartyJoinStrategy::Public;
Params.invite_strategy = EClientPartyInviteStrategy::AllMembersCanInvite;
PGOS_CALL_ASYNC_API(UPgosClientAPICreateParty::CreateParty,
this,
&SomeUObjectClass::OnCreatePartySuccess,
&SomeUObjectClass::OnCreatePartyFailed,
Params);
}
void SomeUObjectClass::OnCreatePartySuccess(
FPgosResult Result, FClientPartyInfo PartyInfo)
{
UE_LOG(LogTemp, Log, TEXT("OnCreatePartySuccess"));
}
void SomeUObjectClass::OnCreatePartyFailed(
FPgosResult Result, FClientPartyInfo PartyInfo)
{
UE_LOG(LogTemp, Error, TEXT("OnCreatePartyFailed: err_code=%d, err_msg=%s"), Result.err_code, *Result.msg);
}
3.2 Party Invite and Join Control
In the code mentioned above of CreateParty
, there are two parameters, join_strategy
and invite_strategy
, which are used to control how the party handles "joining" and "inviting."
join_strategy controls how other players join the party, there are four different strategies:
EClientPartyJoinStrategy | Description |
---|---|
Public | Any player can join the party, except for the player who is blocked by the leader. It's the default setting. |
OnlyFriendsOfLeader | Only friends of the leader are allowed to join the party. |
OnlyFriendsOfMembers | Only friends of any member who are not blocked by the leader are allowed to join the party. |
OnlyInvited | Only explicitly invited players who are not blocked by the leader are allowed to join the party. |
invite_strategy controls how the members of the party invite others.
EClientPartyInviteStrategy | Description |
---|---|
AllMembersCanInvite | All members of the party are allowed to invite other players to join the party. A player who is blocked by the leader or the inviting player can't be invited. It's the default setting. |
OnlyLeaderCanInvite | Only the leader is allowed to invite other players to join the party. A player who is blocked by the leader can't be invited. |
Only Leader
can change join_strategy
and invite_strategy
after the party created.
Call SetPartyStrategy
from Party module as follows:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
void SomeUObjectClass::SetPartyStrategy()
{
auto Party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (Party)
{
FClientSetPartyStrategyParams Params;
Params.party_id = PartyId;
Params.join_strategy = EClientPartyJoinStrategy::Public;
Params.invite_strategy = EClientPartyInviteStrategy::AllMembersCanInvite;
Party->SetPartyStrategy(Params, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SetPartyStrategy Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SetPartyStrategy Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientPartyAPI.h"
void SomeUObjectClass::SetPartyStrategy()
{
FClientSetPartyStrategyParams Params;
Params.party_id = PartyId;
Params.join_strategy = EClientPartyJoinStrategy::Public;
Params.invite_strategy = EClientPartyInviteStrategy::AllMembersCanInvite;
PGOS_CALL_ASYNC_API(UPgosClientAPISetPartyStrategy::SetPartyStrategy,
this,
&SomeUObjectClass::OnSetPartyStrategySuccess,
&SomeUObjectClass::OnSetPartyStrategyFailed,
Params);
}
void SomeUObjectClass::OnSetPartyStrategySuccess(
FPgosResult Result)
{
UE_LOG(LogTemp, Log, TEXT("OnSetPartyStrategySuccess"));
}
void SomeUObjectClass::OnSetPartyStrategyFailed(
FPgosResult Result)
{
UE_LOG(LogTemp, Error, TEXT("OnSetPartyStrategyFailed: err_code=%d, err_msg=%s"), Result.err_code, *Result.msg);
}
All members (except the leader) will receive a notification on the PartyStrategy
changed. Bind dynamic delegate to OnPartyStrategyChanged
as follows:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
// Observe the notification of party strategies changes somewhere
void SomeUObjectClass::SomeFunction()
{
auto party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (party)
{
party->OnPartyStrategyChanged().AddUObject(this, &SomeUObjectClass::OnPartyStrategyChanged);
}
}
// Handle the notification
void SomeUObjectClass::OnPartyStrategyChanged(const FClientPartyStrategyChangedEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnPartyStrategyChanged"));
// Party members cannot change `join_strategy` and `invite_strategy` actively.
}
#include "PgosClientEventDispatcher.h"
// Observe the notification of party invitation somewhere
void SomeUObjectClass::SomeFunction()
{
auto pDispatcher = UPgosClientEventDispatcher::GetPgosClientEventDispatcher();
if (pDispatcher)
{
pDispatcher->OnPartyStrategyChanged.Clear();
// add delegate callback
pDispatcher->OnPartyStrategyChanged.AddDynamic(
this,
&APluginTestGameModeBase::OnPartyStrategyChanged);
}
}
// Handle the invitation
void APluginTestGameModeBase::OnPartyStrategyChanged(const FClientPartyStrategyChangedEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnPartyStrategyChanged"));
// Party members cannot change `join_strategy` and `invite_strategy` actively.
}
3.3 Invite and Join
Leader and members can invite other players to join a party, and one player can only join one party concurrently.
3.3.1 Inviting
Call InvitePlayerToParty
from Party module as follows:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
void SomeUObjectClass::InvitePlayerToParty()
{
auto Party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (Party)
{
FString PartyId;
TArray<FString> InviteePlayerIds;
Party->InvitePlayerToParty(PartyId, InviteePlayerIds, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("InvitePlayerToParty Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("InvitePlayerToParty Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientPartyAPI.h"
void SomeUObjectClass::InvitePlayerToParty()
{
FString PartyId;
TArray<FString> InviteePlayerIds;
PGOS_CALL_ASYNC_API(UPgosClientAPIInvitePlayerToParty::InvitePlayerToParty,
this,
&SomeUObjectClass::OnInvitePlayerToPartySuccess,
&SomeUObjectClass::OnInvitePlayerToPartyFailed,
PartyId,
InviteePlayerIds);
}
void SomeUObjectClass::OnInvitePlayerToPartySuccess(
FPgosResult Result)
{
UE_LOG(LogTemp, Log, TEXT("OnInvitePlayerToPartySuccess"));
}
void SomeUObjectClass::OnInvitePlayerToPartyFailed(
FPgosResult Result)
{
UE_LOG(LogTemp, Error, TEXT("OnInvitePlayerToPartyFailed: err_code=%d, err_msg=%s"), Result.err_code, *Result.msg);
}
Bind dynamic delegate to OnReceivePartyInvitation
as follows:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
// Observe the notification of party invitation somewhere
void SomeUObjectClass::SomeFunction()
{
auto party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (party)
{
party->OnReceivePartyInvitation().AddUObject(this, &SomeUObjectClass::OnReceivePartyInvitation);
}
}
// Handle the invitation
void SomeUObjectClass::OnReceivePartyInvitation(const FClientReceivePartyInvitationEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnReceivePartyInvitation"));
// After receiving the invitation, it will generally be handled according to one of the following situations:
// 1. After receiving the invitation, the game will pop up a dialog box asking the player whether to join the party. After the player agrees, call the JoinParty API to join the party.
// 2. After receiving the invitation, the game can directly call the JoinParty API to join the party.
}
#include "PgosClientEventDispatcher.h"
// Observe the notification of party invitation somewhere
void SomeUObjectClass::SomeFunction()
{
auto pDispatcher = UPgosClientEventDispatcher::GetPgosClientEventDispatcher();
if (pDispatcher)
{
pDispatcher->OnReceivePartyInvitation.Clear();
// add delegate callback
pDispatcher->OnReceivePartyInvitation.AddDynamic(
this,
&APluginTestGameModeBase::OnReceivePartyInvitation);
}
}
// Handle the invitation
void APluginTestGameModeBase::OnReceivePartyInvitation(const FClientReceivePartyInvitationEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnReceivePartyInvitation"));
// After receiving the invitation, it will generally be handled according to one of the following situations:
// 1. After receiving the invitation, the game will pop up a dialog box asking the player whether to join the party. After the player agrees, call the JoinParty API to join the party.
// 2. After receiving the invitation, the game can directly call the JoinParty API to join the party.
}
3.3.2 Joining
Call JoinParty
from Party module as follows:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
void SomeUObjectClass::JoinParty()
{
auto Party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (Party)
{
FString PartyId;
Party->JoinParty(PartyId, [](const FPgosResult& Ret, const FClientPartyInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("JoinParty Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("JoinParty Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientPartyAPI.h"
void SomeUObjectClass::JoinParty()
{
FString PartyId;
PGOS_CALL_ASYNC_API(UPgosClientAPIJoinParty::JoinParty,
this,
&SomeUObjectClass::OnJoinPartySuccess,
&SomeUObjectClass::OnJoinPartyFailed,
PartyId);
}
void SomeUObjectClass::OnJoinPartySuccess(
FPgosResult Result, FClientPartyInfo PartyInfo)
{
UE_LOG(LogTemp, Log, TEXT("OnJoinPartySuccess"));
}
void SomeUObjectClass::OnJoinPartyFailed(
FPgosResult Result, FClientPartyInfo PartyInfo)
{
UE_LOG(LogTemp, Error, TEXT("OnJoinPartyFailed: err_code=%d, err_msg=%s"), Result.err_code, *Result.msg);
}
3.4 Leader’s Privileges
- Kick out members: a leader can kick out any member at any time.
- Dismiss the party.
- Transfer leadership to another member.
Call KickPartyMember/DismissParty/TransferPartyLeader
from Party module as follows:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
// Kick out members
void SomeUObjectClass::KickPartyMember()
{
auto party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (party)
{
FString PartyId = ObtainFromSomeWhere();
FString KickPlayerID = ObtainFromSomeWhere();
party->KickPartyMember(PartyId, KickPlayerID, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnKickMemberSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnKickMemberFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
// Dismiss the party
void SomeUObjectClass::DismissParty()
{
auto party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (party)
{
FString PartyId = ObtainFromSomeWhere();
party->DismissParty(PartyId, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnDismissPartySuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnDismissPartyFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
// Transfer leader privilege to another member
void SomeUObjectClass::TransferPartyLeader()
{
auto party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (party)
{
FString PartyId = ObtainFromSomeWhere();
FString NewLeaderPlayerId = ObtainFromSomeWhere();
party->TransferPartyLeader(PartyId, NewLeaderPlayerId, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnTransferLeaderSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnTransferLeaderFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientPartyAPI.h"
// Kick out members
void SomeUObjectClass::KickPartyMember()
{
FString PartyId = ObtainFromSomeWhere();
FString KickPlayerID = ObtainFromSomeWhere();
PGOS_CALL_ASYNC_API(UPgosClientAPIKickPartyMember::KickPartyMember,
this,
&APluginTestGameModeBase::OnKickMemberSuccess,
&APluginTestGameModeBase::OnKickMemberFailed,
PartyId,
KickPlayerID);
}
void SomeUObjectClass::OnKickMemberSuccess(FPgosResult Result)
{
UE_LOG(LogTemp, Log, TEXT("OnKickMemberSuccess"));
}
void SomeUObjectClass::OnCreatePartyFailed(FPgosResult Result)
{
UE_LOG(LogTemp, Error, TEXT("OnKickMemberFailed: err_code=%d, err_msg=%s"), Result.err_code, *Result.msg);
}
// Dismiss the party
void SomeUObjectClass::DismissParty()
{
FString PartyId = ObtainFromSomeWhere();
PGOS_CALL_ASYNC_API(UPgosClientAPIDismissParty::DismissParty,
this,
&APluginTestGameModeBase::OnDismissPartySuccess,
&APluginTestGameModeBase::OnDismissPartyFailed,
PartyId);
}
void SomeUObjectClass::OnDismissPartySuccess(FPgosResult Result)
{
UE_LOG(LogTemp, Log, TEXT("OnDismissPartySuccess"));
}
void SomeUObjectClass::OnDismissPartyFailed(FPgosResult Result)
{
UE_LOG(LogTemp, Error, TEXT("OnDismissPartyFailed: err_code=%d, err_msg=%s"), Result.err_code, *Result.msg);
}
// Transfer leader privilege to another member
void SomeUObjectClass::TransferPartyLeader()
{
FString PartyId = ObtainFromSomeWhere();
FString NewLeaderPlayerId = ObtainFromSomeWhere();
PGOS_CALL_ASYNC_API(UPgosClientAPITransferPartyLeader::TransferPartyLeader,
this,
&APluginTestGameModeBase::OnTransferLeaderSuccess,
&APluginTestGameModeBase::OnTransferLeaderFailed,
PartyId,
NewLeaderPlayerId);
}
void SomeUObjectClass::OnTransferLeaderSuccess(FPgosResult Result)
{
UE_LOG(LogTemp, Log, TEXT("OnTransferLeaderSuccess"));
}
void SomeUObjectClass::OnTransferLeaderFailed(FPgosResult Result)
{
UE_LOG(LogTemp, Error, TEXT("OnTransferLeaderFailed: err_code=%d, err_msg=%s"), Result.err_code, *Result.msg);
}
3.5 Dismiss Party
A party will be dismissed in the following cases:
Leader dismisses the party.
Party will be automatically dismissed after all members have left the party or have logged out.
sequenceDiagram PlayerA->>PartyService: dismiss PartyService-->>PlayerB: notify dismissed PartyService-->>PlayerC: notify dismissedCheck the previous section for sample codes.
3.6 Leave Party
Any player can leave the party. When the leader leaves the party, PGOS will automatically promote another member as the new leader.
A player will automatically leave the party after logging out.
sequenceDiagram PlayerA->>PartyService: leave party / transfer leader PartyService-->>PlayerB: notify PlayerA left / leader transfered PartyService-->>PlayerC: notify PlayerA left / leader transfered
Call LeaveParty
from Party module as follows:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
// Leave the party
void SomeUObjectClass::LeaveParty()
{
auto party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (party)
{
FString PartyId = ObtainFromSomeWhere();
party->LeaveParty(PartyId, [](const FPgosResult& Ret) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnLeavePartySuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnLeavePartyFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientPartyAPI.h"
// Leave the party
void SomeUObjectClass::LeaveParty()
{
FString PartyId = ObtainFromSomeWhere();
PGOS_CALL_ASYNC_API(UPgosClientAPILeaveParty::LeaveParty,
this,
&APluginTestGameModeBase::OnLeavePartySuccess,
&APluginTestGameModeBase::OnLeavePartyFailed,
PartyId);
}
void SomeUObjectClass::OnLeavePartySuccess(FPgosResult Result)
{
UE_LOG(LogTemp, Log, TEXT("OnLeavePartySuccess"));
}
void SomeUObjectClass::OnLeavePartyFailed(FPgosResult Result)
{
UE_LOG(LogTemp, Error, TEXT("OnLeavePartyFailed: err_code=%d, err_msg=%s"), Result.err_code, *Result.msg);
}
3.7 Custom Data Handling
Party Custom Data is used to help game to extend the party, such as "Party Ready Up", "Party Vote", etc. Every Party has two tiers of custom data: Global Custom Data
and Player Custom Data
. Game developers can store any data in there to implement the specific functionality.
Global Custom Data
is a string, that stores the data for the global scope. All members can visit it, but only party leader has permission to store and modify in the game client.
Player Custom Data
is a string->string (playerid -> data) map, that stores the data for every party members, the key is the playerid and the value is the data that is set by the owner member. All members can visit it, but the player only has permission to store and modify their own player custom data.
All members will receive the PartyCustomDataChangedEvt
event in the game client when any custom data was changed, including global custom data and player custom data.
Call GetPartyInfo
or CurrentParty
to obtain the PartyInfo that contains PartyCustomData.
Call SetGlobalCustomData
to set global custom data for a party. Please note that only party leader has permission to do it:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SetGlobalCustomData()
{
auto party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (party)
{
FString PartyId = ObtainFromSomeWhere();
party->SetGlobalCustomData(PartyId, GlobalCustomData, [](
const FPgosResult& Ret, const PartyCustomData * Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnSetGlobalCustomDataSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnSetGlobalCustomDataFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientPartyAPI.h"
void SomeUObjectClass::SetGlobalCustomData()
{
FString PartyId = ObtainFromSomeWhere();
PGOS_CALL_ASYNC_API(UPgosClientAPIGetCustomData::SetGlobalCustomData,
this,
&APluginTestGameModeBase::OnSetGlobalCustomDataSuccess,
&APluginTestGameModeBase::OnSetGlobalCustomDataFailed,
PartyId,
GlobalCustomData);
}
void SomeUObjectClass::OnGSetGlobalCustomDataSuccess(FPgosResult& Result, FPartyCustomData& Data)
{
UE_LOG(LogTemp, Log, TEXT("OnSetGlobalCustomDataSuccess"));
}
void SomeUObjectClass::OnSetGlobalCustomDataFailed(FPgosResult& Result, FPartyCustomData& Data)
{
UE_LOG(LogTemp, Error, TEXT("OnSetGlobalCustomDataFailed: err_code=%d, err_msg=%s"), Result.err_code, *Result.msg);
}
Call SetPlayerCustomData
toplayer owned custom data. Please note that the player only has permission to store and modify their own player custom data:
- UE C++
- UE BP
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SetPlayerCustomData()
{
auto party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (party)
{
FString PartyId = ObtainFromSomeWhere();
party->SetPlayerCustomData(PartyId, PlayerCustomData, [](
const FPgosResult& Ret, const PartyCustomData * Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("OnSetPlayerCustomDataSuccess"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("OnSetPlayerCustomDataFailed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
#include "PgosClientPartyAPI.h"
void SomeUObjectClass::SetPlayerCustomData()
{
FString PartyId = ObtainFromSomeWhere();
PGOS_CALL_ASYNC_API(UPgosClientAPIGetCustomData::SetPlayerCustomData,
this,
&APluginTestGameModeBase::OnSetPlayerCustomDataSuccess,
&APluginTestGameModeBase::OnSetPlayerCustomDataFailed,
PartyId,
PlayerCustomData);
}
void SomeUObjectClass::OnSetPlayerCustomDataSuccess(FPgosResult& Result, FPartyCustomData& Data)
{
UE_LOG(LogTemp, Log, TEXT("OnSetPlayerCustomDataSuccess"));
}
void SomeUObjectClass::OnSetPlayerCustomDataFailed(FPgosResult& Result, FPartyCustomData& Data)
{
UE_LOG(LogTemp, Error, TEXT("OnSetPlayerCustomDataFailed: err_code=%d, err_msg=%s"), Result.err_code, *Result.msg);
}
Key Error Codes
3.8 Start Matchmaking
Due to design considerations, parties are completely decoupled from matchmaking. We can use multi-player matchmaking requests to pass all player IDs as parameters into the matchmaking request interface. (refer to the detailed guide to Matchmaking)
The leader can start the matchmaking process via the process shown below:
Leader starts the matchmaking process through the game UI
The leader's client gets each member's player_id and generates a player_id list
The leader's client passes the player_id list as the core parameter and calls the StartMatchmaking interface in the Matchmaking service
The members' clients will immediately receive a push message indicating that the Leader has started the matchmaking process
The members' clients call the JoinMatchmaking interface
After matchmaking succeeds, all players will receive a push message, prompting that they can join the battle and connect to the dedicated server
3.9 Join Lobby
Due to design considerations, parties are completely decoupled from the Lobby. We can use the multi-player lobby joining request to pass all player IDs into the lobby interface.
3.10 Party Chat
Party service has built-in chat function and can be used directly: EnableChatting
is true when calling the interface UPgosClientAPICreateParty::CreateParty
.
- Any member in the party can send party chat messages
- Any member in the party can receive party chat messages
- Members will not receive party chat messages from themselves
Send party chat message
Call SendPartyChatTextMsg
/SendPartyChatCustomMsg
from Party module as follows:
#include "PgosSDKCpp.h"
void SomeUObjectClass::SendPartyChatTextMsg()
{
auto Party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (Party)
{
FClientSendPartyChatMsgParams Params;
Party->SendPartyChatTextMsg(Params, [](const FPgosResult& Ret, const FClientChatMsgInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SendPartyChatTextMsg Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SendPartyChatTextMsg Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
void SomeUObjectClass::SendPartyChatCustomMsg()
{
auto Party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (Party)
{
FClientSendPartyChatMsgParams Params;
Party->SendPartyChatCustomMsg(Params, [](const FPgosResult& Ret, const FClientChatMsgInfo* Data) {
if (Ret.err_code == (int32)Pgos::PgosErrCode::kSuccess)
{
UE_LOG(LogTemp, Log, TEXT("SendPartyChatCustomMsg Success"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("SendPartyChatCustomMsg Failed: err_code=%d, err_msg=%s"), Ret.err_code, *Ret.msg);
}
});
}
}
Receive party chat message
Bind dynamic delegate to OnReceivePartyChatMsg
as follows:
#include "PgosSDKCpp.h"
#include "Core/PgosErrorCode.h"
void SomeUObjectClass::SomeFunction()
{
auto party = IPgosSDKCpp::Get().GetClientPartyAPI();
if (party)
{
party->OnReceivePartyChatMsg().AddUObject(this, &SomeUObjectClass::OnReceiveChatMsg);
}
}
void SomeUObjectClass::OnReceiveChatMsg(const FClientReceivePartyChatMsgEvt& event)
{
UE_LOG(LogTemp, Log, TEXT("OnReceiveChatMsg"));
}
3.11 Party Query in Portal
You can query party records in the web portal. When a party is created, the PGOS backend automatically generates and stores a history record that contains the following information:
- Leader Player Id.
- Member Player Ids: members may change during the party's lifetime and the information of members will be recorded here.
- The creation and dismission time of the party (if dismissed).
- Party Id, Name.
- Max number of players allowed by the creator.
The query screen is shown below:
Party list:
Party details:
3.12 Party Events
Event Name | Event Description |
---|---|
OnPartyStrategyChanged | Sent when when party strategies changed. |
OnPartyMemberJoined | Sent when new players joined the party. |
OnPartyMemberLeft | Sent when players left the party. |
OnPartyDismissed | Sent when the party was dismissed. |
OnPartyLeaderTransferred | Sent when the leader status was transferred. |
OnReceivePartyInvitation | Sent when receive a party invitation. |
OnReceivePartyChatMsg | Sent when party chat message arrived. |
OnCustomDataChanged | Sent when party custom data changed. |
OnPartyInfoUpdated | Sent when party info updated. |
This section discusses a special event OnPartyInfoUpdated
, which is triggered when there is a change in party info.
Normally, more specific events occur when changes to party info happen. For example, the OnPartyStrategyChanged
event is triggered when party strategies change, and the OnPartyMemberJoined
event is triggered when new players join the party.
However, due to network issues or other reasons causing disruptions in the persistent connection, the server might be unable to notify the client of changes in party info (such as players entering or leaving the party) through this connection. If the client remains unaware of changes in party info for an extended period, it could lead to functional abnormalities in the game. To address this issue, the PGOS SDK periodically retrieves the latest party info (typically every 30 to 60 seconds) upon detecting a disruption in the persistent connection, and then notifies the game through the OnPartyInfoUpdated
event.
Therefore, it is recommended that games listen to the OnPartyInfoUpdated
event in addition to other events below that indicate changes in party info:
OnPartyStrategyChanged
OnPartyMemberJoined
OnPartyMemberLeft
OnPartyLeaderTransferred
OnCustomDataChanged
4. Key Fields and Data
Field | Notes | Remark |
---|---|---|
Party Id | Identity of party | Party Id is globally unique |
Name | Party's name | Optional and not unique |
Leader Player Id | Leader's player id | |
Max Player | Max player count | |
Created Time | Time of party creation | |
Dismissed Time | Time of party dismission | |
Members | Player Id list of all members | Including the leader |
5. Key Errors Handling
Error Code | Relevant API | Handling Suggestion |
---|---|---|
kBackendPartyDuplicated | CreateParty JoinParty | It means the player are already in other party since a player can only create/join one party concurrently. The game can prompt the player a message like "You should leave the current party and then try again" |
kBackendCreatePartyUic | CreateParty | It means the param party name contains profanity word. The game can prompt the player a message like "The party name contains profanity word, you should change it and then try again" |
kBackendIsNotPartyLeader | SetGlobalCustomData | It means the player has no ownership of the party try to set the global custom data of the lobby. Such action is not allowed |
kBackendJoinFailedDueToNotFriendOfLeader | JoinParty | It means the party join_strategy is set to OnlyFriendsOfLeader and the joining player is not a friend of the party leader. |
kBackendJoinFailedDueToNotFriendOfmembers | JoinParty | It means the party join_strategy is set to OnlyFriendsOfMembers and the joining player is not a friend of any member of the party. |
kBackendJoinFailedDueToNoInvitation | JoinParty | It means the party join_strategy is set to OnlyInvited and the joining player is not invited, or the last invitation has already expired.The expiration time is internally controlled by the PGOS backend. |
kBackendNoJoinPartyPermission | JoinParty | It usually means the joining player is blocked by the party leader. Or the joining player has blocked the party leader, it's a two-way relationship. |
kBackendPartyNotAllowJoin | JoinParty | It means the party join_strategy is set to NotAllowed , so this party is not allowed to join. |
kBackendInviteFailedDueToNotLeader | InvitePlayerToParty | It means the party invite_strategy is set to OnlyLeaderCanInvite and the inviting player is not the party leader. |
kBackendInviteFailedDueToNotAllowJoin | InvitePlayerToParty | It means the party join_strategy is set to NotAllowed , so you can't invite other players to this party. |