> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qwacks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sessions

> One game: a host, its players and a join code.

A **session** is one game. One player **hosts** it and the others hold **seats**, up to 16 in all.
A player hosts a session and reads out its **join code**, or a [match](/guides/matchmaking.md) makes
one. A player holds one seat at a time: hosting or joining another session gives up the one held.
When the host leaves, the player seated longest becomes the host.

> [!NOTE]
>
> **Scope:** sessions belong to one **game**; a seat belongs to a player.

**Dashboard**

**Multiplayer → Sessions** lists the **Live Sessions** and the **Session History**. Each
session's details show its host and **Host changes**, its **Connection**, **Join code**,
**Participants**, and the **Relay credentials drawn** by its players. **Multiplayer settings**
on the same page set the seat count, timeouts and maximum age; see
[Multiplayer](/guides/multiplayer.md#setting-up).

**Unity**

Host a session, and show its code.

```csharp theme={null}
FlockMultiplayerProvider multiplayer = FlockClient.Instance.Multiplayer;

// 2 to 16 seats (the game's setting when not given), and the game's own data, set once.
FlockMultiplayerSession session = await multiplayer.HostSessionAsync(
    4, new Dictionary<string, object> { ["map"] = "crypt" });
joinCodeLabel.text = session.JoinCode;
```

A friend's game joins with the code; letter case does not matter.

```csharp theme={null}
FlockMultiplayerSession joined = await multiplayer.JoinSessionAsync(typedCode);
joined.TryGetData("map", out string map);
```

Follow the session, and leave it.

```csharp theme={null}
session.PlayersChanged += () => ShowPlayers(session.Players);   // seated longest first
session.HostChanged += OnHostChanged;   // start the netcode again: see Connecting players
session.Ended += reason => BackToLobby(reason);

await session.LeaveAsync();                // anyone
await session.EndAsync();                  // the host only: ends it for everyone
await session.MakeHostAsync(otherPlayer);  // the host only: hands hosting over
```

After the game restarts, find the seat the player still holds:

```csharp theme={null}
FlockMultiplayerSession held = await multiplayer.GetMySessionAsync();   // null when seated nowhere
```

To connect the players, see [Connecting players](/guides/connecting-players.md).

**Unreal**

Host a session, and show its code. The examples run in your game instance, which outlives the
level changes that bring the players together.

```cpp theme={null}
#include "FlockSubsystem.h"
#include "Multiplayer/FlockMultiplayerSession.h"

FFlockMultiplayerProvider* Multiplayer = GetSubsystem<UFlockSubsystem>()->GetMultiplayerProvider();

// 2 to 16 seats (the game's setting when unset), the game's own data, set once, and only players on this build.
Multiplayer->HostSession(4, FFlockCommandData().Set(TEXT("map"), TEXT("crypt")), /*bSameVersionOnly*/ true,
    [this](TFlockResult<UFlockMultiplayerSession*> Hosted)
    {
        if (Hosted.IsSuccess())
        {
            Session = Hosted.Value;   // a UPROPERTY
            ShowJoinCode(Session->GetJoinCode());
        }
    });
```

A friend's game joins with the code; letter case does not matter.

```cpp theme={null}
Multiplayer->JoinSession(TypedCode, [this](TFlockResult<UFlockMultiplayerSession*> Joined)
{
    FString Map;
    if (Joined.IsSuccess() && Joined.Value->GetData().TryGetString(TEXT("map"), Map))
    {
        ShowMap(Map);
    }
});
```

Follow the session, and leave it.

```cpp theme={null}
Session->OnPlayersChanged.AddDynamic(this, &UMyGameInstance::ShowPlayers);   // GetPlayers(): seated longest first
Session->OnHostChanged.AddDynamic(this, &UMyGameInstance::PlayAgain);         // travel again: see Connecting players
Session->OnEnded.AddDynamic(this, &UMyGameInstance::BackToLobby);             // BackToLobby(const FString& Reason)

Session->Leave(nullptr);                     // anyone
Session->End(nullptr);                       // the host only: ends it for everyone
Session->MakeHost(OtherPlayerId, nullptr);   // the host only: hands hosting over
```

After the game restarts, find the seat the player still holds:

```cpp theme={null}
Multiplayer->GetMySession([this](TFlockResult<UFlockMultiplayerSession*> Held) { /* Held.Value is null when seated nowhere */ });
```

Every call returns an `FFlockRequestHandle`; its `Cancel()` stops the request on its way. A
call on a session that has ended is refused (`Validation`) without a request.

In Blueprint, the calls are nodes under **Flock | Multiplayer**: **Flock Host Session**,
**Flock Join Session** and **Flock Get Session** (On Success with the session, On Failure with
the error), **Flock Get My Session** (On Session, On No Session, On Failure), and **Flock Leave
Session**, **Flock End Session** and **Flock Make Session Host**. Max Players left at 0 takes
the game's setting. Bind the session's **On Players Changed**, **On Host Changed** and **On
Ended** events on the session object.

To connect the players, see [Connecting players](/guides/connecting-players.md).

## Game versions

A session takes only players on the host's **Game Version** unless the host passes
`sameVersionOnly: false` (Unreal: `bSameVersionOnly` false). A player on another build is refused
with `MultiplayerVersionMismatch`; ask them to update.

## When a player goes quiet

The SDK sends a heartbeat every 20 seconds while the game runs, so a playing player never times
out. What happens when the game stops running (where a cell gives two names, the first is Unity's
and the second Unreal's):

| What happened | What Flock does | What players see |
| - | - | - |
| A player quits the game | Gives the seat up at once | `PlayersChanged` / `OnPlayersChanged` |
| A player's game crashes or loses its network | Gives the seat up after the **Participant timeout** (90 s) | `PlayersChanged` / `OnPlayersChanged` |
| A phone goes to the home screen | The game stops, so its heartbeats stop; after the **Participant timeout** the seat is given up | Back in the game, the session ends as `dropped` |
| The host leaves | Makes the player seated longest the host at once | `HostChanged` / `OnHostChanged` |
| The host's game crashes | Replaces the host after the **Host timeout** (60 s) | `HostChanged` / `OnHostChanged`, about a minute later |
| The game restarts within the timeout | Keeps the seat | `GetMySessionAsync` / `GetMySession` finds it |

## When a session ends

`Ended` (`OnEnded` on Unreal) is raised once with the reason. On Unity the reason is a
`FlockMultiplayerSessionEndReason`; on Unreal it is a string, compared with the constants of
`FlockMultiplayerSessionEndReasons`, which carry the same names (`FlockMultiplayerSessionEndReasons::EndedByHost`
is `ended_by_host`). The server can add reasons, so keep a default:

| Unity | Unreal | When |
| - | - | - |
| `EndedByHost` | `ended_by_host` | The host ended it. |
| `HostLeft` | `host_left` | The host left and nobody was seated to take over. |
| `Empty` | `empty` | Everyone left. |
| `Expired` | `expired` | It reached the **Session max age** (4 hours by default). |
| `Left` | `left` | The player left it. |
| `Dropped` | `dropped` | The player's seat timed out. |
| `MovedToAnotherSession` | `moved_to_another_session` | The player hosted or joined another session. |
| `SignedOut` | `signed_out` | The player signed out, or another player signed in. |

`Ended` (`OnEnded`) is not raised when the game quits.

## Errors

Each code is a `FlockErrorCode` on Unity and an `EFlockErrorCode` on Unreal, with the same name,
and the error carries a hint naming the fix.

| `ErrorCode` | When | What to do |
| - | - | - |
| `MultiplayerInvalidJoinCode` | No open session has that code. | Ask the host for the code again; a code stops working when its session ends. |
| `MultiplayerSessionFull` | Every seat is taken. | Join another session, or host one with more seats. |
| `MultiplayerSessionNotFound` | No session the player holds or held has that id, or the player's seat was given up. | Join again with the session's join code. |
| `MultiplayerVersionMismatch` | The player's build differs from the host's. | Update the game, or host with `sameVersionOnly: false` (Unreal: `bSameVersionOnly` false) to let any build join. |
| `MultiplayerNotHost` | A call only the host can make. | Read the session again to see who hosts now. |
| `MultiplayerTargetNotAParticipant` | That player holds no seat in the session. | Hand hosting to one of the session's players. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.