# Player Groups

You may need to do certain things in your game that requires information on which players joined the game together. To make this process a bit easier, Kronos ships with a component that automatically assigns players into groups based on whether they joined the game together (as a party) or not.

{% hint style="info" %}
The term **Player Groups** just refer to players who are assigned to the same group index by the `KronosPlayerGrouperComponent`. They are not the same as parties.
{% endhint %}

## Player Grouper Component

The `KronosPlayerGrouperComponent` automatically assigns a **group index** to all players based on their reservation data. The group index is just a number that is unique to that group. You may be wondering what do reservations have to do with party information. When joining the game as a party, the party host requests a reservation for the entire party. So looking at the reservations we can tell which players belonged to the same party before they joined the game.

<figure><img src="/files/wNiWQL0z9WB7idV90Ddi" alt=""><figcaption></figcaption></figure>

Players who joined the game together (as a party) will have the same group index. Using this you can essentially get the list of players who were in the same party before they joined the game. The component is **fully replicated** so clients can easily access this data as well.

## How To Setup

Let's go over how to setup the `KronosPlayerGrouperComponent`.

### 1. Setting Up The Component

The component must be added to the `GameState`. Open up your game state blueprint (or class) and add the `KronosPlayerGrouperComponent` to it.

### 2. Assigning Players To Groups

Group indexes are assigned automatically for joining and leaving players if `bAutoAssignGroupsToPlayers` variable is enabled in the component. The exception to this is when the host used seamless travel to change maps (e.g. from lobby to game). Whether seamless traveling is used is set in the game mode.

{% hint style="warning" %}
When seamless traveling is used, the host must assign a group index to each seamless traveling player when they arrive on the new map.
{% endhint %}

For Blueprint projects, the game mode's `OnSwapPlayerControllers` event is a good place to handle group assignment for seamless traveling players. C++ projects can override the game mode's `InitSeamlessTravelPlayer` function directly.

{% tabs %}
{% tab title="Blueprint" %}

<figure><img src="/files/s1hlUyhBKvstZWNdc5Rk" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="C++" %}

```cpp
#include "Components/KronosPlayerGrouperComponent.h"
#include "GameFramework/GameStateBase.h"
#include "GameFramework/PlayerState.h"
```

```cpp
void AMyGameModeBase::InitSeamlessTravelPlayer(AController* NewController)
{
	Super::InitSeamlessTravelPlayer(NewController);

	// Make sure that the player state is valid.
	if (NewController->PlayerState)
	{
		// Get the player grouper component from the game state.
		UKronosPlayerGrouperComponent* PlayerGrouper = GameState->GetComponentByClass<UKronosPlayerGrouperComponent>();
		if (PlayerGrouper)
		{
			// Assign a group index to the player.
			const FUniqueNetIdRepl& PlayerId = NewController->PlayerState->GetUniqueId();
			PlayerGrouper->AssignGroupToPlayer(PlayerId);
		}
	}
}
```

{% endtab %}
{% endtabs %}

## Using Player Groups

Now that the component is set up, we can use the group index to get the list of players in a group. For example, lets print all player's names who are in the local player's group.

{% tabs %}
{% tab title="Blueprint" %}

<figure><img src="/files/g7GbICr0cbJ0BDJ5jd1o" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/sfMEpd4Sjs1GRzAPmxFO" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="C++" %}

```cpp
#include "Components/KronosPlayerGrouperComponent.h"
#include "KronosStatics.h"
#include "GameFramework/GameStateBase.h"
#include "GameFramework/PlayerState.h"
```

```cpp
// Get the game state.
AGameStateBase* GameState = GetWorld()->GetGameState();
if (GameState)
{
	// Get the player grouper component.
	UKronosPlayerGrouperComponent* PlayerGrouper = GameState->GetComponentByClass<UKronosPlayerGrouperComponent>();
	if (PlayerGrouper)
	{
		// Loop through all players who are in the local player's group.
		const int32 LocalPlayerGroupIndex = PlayerGrouper->GetLocalPlayerGroupIndex();
		for (const FUniqueNetIdRepl& PlayerId : PlayerGrouper->GetAllPlayersInGroup(LocalPlayerGroupIndex))
		{
			// Get the player state from unique id.
			APlayerState* PlayerState = UKronosStatics::GetPlayerStateFromUniqueId(this, PlayerId);
			
			// PlayerState->GetPlayerName();
		}
	}
}
```

{% endtab %}
{% endtabs %}

You can also use the `GetGroupIndexOfPlayer` node to access a player's group index via their `PlayerId`. You can get the player's `PlayerId` through their `PlayerState`.

## Player Group Events

The `KronosPlayerGrouperComponent` also contains Blueprint assignable events for when a player is added or removed from a group. These are the `OnPlayerAddedToGroup` and `OnPlayerRemovedFromGroup` events respectively.

## Player Group Replication

Group indexes are replicated to clients automatically. No setup work required. Please note that due to replication, group indexes should only ever be modified on server side!

## What If There Is No Reservation Data?

There may be cases when no reservation data is available, for example when starting a map directly in the editor with multiple clients in listen server mode (without going through matchmaking).

When no reservation data is available the component can either assign all players into the same group, or assign all players into separate groups. The `bUseSingleGroupIfNoReservationAvailable` variable of the component dictates which mode to use.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://horizongames.gitbook.io/kronos-matchmaking/advanced/player-groups.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
