Party #
The Party service allows players to create a party with their friends, and configure their game and other selections before entering matchmaking. Extension data and the Party plugin can be used to create custom party configuration and workflows.
Architecture #
The Party service coordinates invites and shared player state in real time. This requires sending out player broadcasts to each individual player when states change and managing a careful multithreaded implementation.
The Pragma Engine architecture uses its deterministic routing capability to send broadcasts directly to each player without extra network hops that can create load bottlenecks. Each party is synchronized to maintain integrity of the party state, while the service itself is massively parallel to support thousands of parties per box and scale horizontally to any number of Party service instances.
Party Plugin #
Pragma Engine handles running all basic party operations and provides access to a plugin to add custom behavior. The Party plugin supports defining and updating extension data at points of change for the party lifecycle–creating a party, joining a party, updating ready state, leaving a party, updating any selections on the party, starting matchmaking, and recreating the party after players leave matchmaking or finish their match.
Custom Party behavior #
Custom ext
logic can be defined for endpoints within the Party plugin.
To customize plugin behavior with ext
fields, use the appropriate function to take client-supplied data in RequestExt
objects and translate it to the relevant ext
selections object within a party.
Pragma Engine provides several of theseRequestExt
objects that are sent on the payloads of RPC calls, such asCreate
,Join
,UpdatePlayerSelections
, andUpdatePartySelections
.
Send custom data to the game server #
To allow the game server to take advantage of any Party plugin ext
fields, implement a custom MatchFoundPlugin
with a prepareMatchInfo
function.
prepareMatchInfo
has two important capabilities:
- provides the plugin access to
MatchLifecycleRpc.CreateMatchV2Request
- includes a builder called
MatchCapacityRpc.StartMatchV1Request.Builder
The CreateMatchV2Request
is called after matchmaking to create a match, and includes complete party payloads for all individual parties. Use this to retrieve any ext
data from the original party payloads, and then embed them into the StartMatchV1Request
request.
The builder can be used to customize payloads sent to the game server:
- to modify global game settings, update the
ExtCreateMatchV1Request
on the builder - to modify individual player settings, locate the correct player within the prepopulated list of
pragma.matchlifecycle.PlayerInfoV2
, then update theExtPlayerInfo
field
Extension Data #
There are three kinds of party data: public player selections, private player selections, and public party selections.
Type | Visibility | Examples |
---|---|---|
public party selections | party | current mode or map, active mutations |
public player selections | party | selected hero or skin, preferred map or mode to play |
private player selections | player | selected deck in a CCG not visible to opponent until match start |
Quick Guides #
Creating a party #
Send CreateV1
to create a party based on the active player:
{
"requestId": 1,
"type": "PartyRpc.CreateV1Request",
"payload": {
"createRequestExt":{},
"playerJoinRequestExt":{},
"gameClientVersion":"gameClientVersion1"
}
}
The party’s creator is added to the party as the leader. The PartyPlugin
plugin functions initializeParty
and onAddPlayer
are invoked during creation.
When using the Pragma SDK, gameClientVersion
is automatically managed and sent via configuration.
Sample response contains data about the generated party, including the display name, party state, and an invite code:
{
"sequenceNumber": 0,
"response": {
"requestId": 1,
"type": "PartyRpc.CreateV1Response",
"payload": {
"party": {
"extPartySelections": {},
"extPrivatePlayerSelections": {},
"partyId": "41b6a903-bd3a-4317-b7cb-db996021087d",
"partyMembers": [
{
"ext": {},
"playerId": "d560eb9b-4f34-4350-b733-5f6df678dab0",
"displayName": {
"displayName": "test01",
"discriminator": "0001"
},
"isReady": false,
"isLeader": true
}
],
"inviteCode": "CDCLGP"
}
}
}
}
Sending a party invite #
Use SendPartyInviteV1
with the invited player’s ID:
{
"requestId": 1,
"type": "PartyRpc.SendInviteV1Request",
"payload": {
"inviteePlayerId": "f9525239-cd99-425d-9f14-1ff948c02553"
}
}
Receiving and responding to a party invite #
The invited player’s client is sent an PartyRpc.InviteReceivedV1Notification
.
Within the Party service in each SDK, there are OnInviteReceived
events that can be leveraged for wiring up any UI and responding to the invite.
To respond to an invite, use RespondToInviteV1
with the invite ID provided in the InviteReceivedV1Notification
.
{
"requestId": 2,
"type": "PartyRpc.RespondToInviteV1Request",
"payload": {
"requestExt":{},
"inviteId":"89962f84-7edd-45b9-97c0-b6fd49fc8497",
"accepted":true,
"gameClientVersion":"gameClientVersion1"
}
}
The PartyPlugin
plugin function onAddPlayer
is invoked as a player joins.
When using the Pragma SDK, gameClientVersion
is automatically managed and sent via configuration.
Joining a party with an invite code #
For playtesting purposes, we provide an invite code system of 6-character strings that can be used to quickly join games.
To join with an invite code, use JoinWithInviteCodeV1
with the invite code from the party you wish to join.
{
"requestId": 3,
"type": "PartyRpc.JoinWithInviteCodeV1Request",
"payload": {
"requestExt":{},
"inviteCode":"CDCLGP",
"gameClientVersion":"gameClientVersion1"
}
}
The PartyPlugin
plugin function onAddPlayer
is invoked as the player joins.
When using the Pragma SDK, gameClientVersion
is automatically managed and sent via configuration.
Joining a party with a party ID #
Players can join existing parties by using the party ID as a key.
To join with a party ID, use JoinWithPartyIdV1
with the party ID from the party you wish to join.
{
"requestId": 4,
"type": "PartyRpc.JoinWithPartyIdV1Request",
"payload": {
"requestExt":{},
"partyId":"5e359a34-8112-4a84-81d5-86f11f261f67",
"gameClientVersion":"gameClientVersion1"
}
}
The PartyPlugin
plugin function onAddPlayer
is invoked as the player joins.
When using the Pragma SDK, gameClientVersion
is automatically managed and sent via configuration.
Leaving a party #
To leave a party, use LeaveV1
.
{
"requestId": 4,
"type": "PartyRpc.LeaveV1Request",
"payload": {
}
}
Pragma Engine invokes the PartyPlugin
function onRemovePlayer
after a player leaves a party.
Updating player and party selections #
When called, Pragma Engine invokes the PartyPlugin
function updateParty
with the request ext
, allowing for custom-built updates to selections.
To update player selections, use UpdatePlayerSelectionsV1
.
{
"requestId": 6,
"type": "PartyRpc.UpdatePlayerSelectionsV1Request",
"payload": {
"requestExt": {}
}
}
To update party selections, use UpdatePartySelectionsV1
.
{
"requestId": 7,
"type": "PartyRpc.UpdatePartySelectionsV1Request",
"payload": {
"requestExt": {}
}
}
Receiving party updates #
When a party member calls the Party service to change the state of the party, they receive an up-to-date payload of the new party state. All party members are automatically notified of any changes to the party state (that they did not directly invoke) via an PartyDetailsV1Notification
.
The Unity and Unreal SDKs have behavior built in to automatically listen to these updates and manage latest party state appropriately.
Setting ready state #
Party members may toggle their ready state using SetReadyStateV1
.
{
"requestId": 5,
"type": "PartyRpc.SetReadyStateV1Request",
"payload": {
"ready": "true"
}
}
Matchmaking is blocked from starting if not all players are ready. When called, Pragma Engine invokes the PartyPlugin
function canChangeReady
to determine whether to accept or reject the player’s new ready state.
Starting matchmaking #
To start matchmaking, use StartMatchmakingV1
.
{
"requestId": 8,
"type": "PartyRpc.StartMatchmakingV1",
"payload": {
}
}
When called, Pragma Engine invokes both PartyPlugin
functions buildMatchmakingKey
and buildExtEnterMatchmakingV2Request
to allow for customization of matchmaking keys and any other custom matchmaking context.
You can only enter matchmaking when when all party members are marked ready and StartMatchmaking
is called by a party leader.
Sending custom data to a match #
To allow the game server to take advantage of any Party plugin ext
fields, you can implement a custom MatchFoundPlugin
.
The prepareMatchInfo
function provides the plugin access to the complete MatchLifecycleRpc.CreateMatchV2Request
. The complete party payloads for all individual parties in the match are embedded within this request.
The plugin’s function signature also contains a builder for the MatchCapacityRpc.StartMatchV1Request
that defines the payload that the game server receives. Use this to retrieve any ext
data from the original party payloads, and then embed them into the StartMatchV1Request
request.