# Turn change notification patterns

> Learn how a Stateful Cloud Code module notifies players of turn changes based on their connection state.

When you build a turn-based game on [`MultiplayerSession`-scoped](/cloud-code/3.0.0/modules/stateful-cloud-code/state-scopes.md) Stateful Cloud Code, a module typically needs to keep three kinds of players up to date on state changes (such as a new turn starting), depending on each player's connection state at the time:

* The player who made the move learns the result directly, using [synchronous multiplayer](#synchronous-multiplayer) notification.
* Other players who are connected to the server at the same time also learn about it using synchronous notification, through a push message.
* Players who aren't connected at the time of the change learn about it later, using [asynchronous multiplayer](#asynchronous-multiplayer) notification, by fetching state themselves once they reconnect.

## Synchronous multiplayer

The player who calls the function that processes a move (for example, `MakeMove`) receives the result directly as that call's response, without needing a push message.

The same function can also notify any other players who are connected to the server at the same time, by looping through the session's remaining player IDs and calling `IPushClient.SendPlayerMessageAsync` for each one, instead of leaving their clients to poll.

Those other clients subscribe to player messages and react to a `TurnChanged` message type, rather than calling a module endpoint to check the game state on a timer. Refer to [Send push messages](/cloud-code/3.0.0/modules/how-to-guides/push-messages.md#subscribe-to-messages) for the full subscription example.

> **Tip:**
>
> Push notifications combine well with [turn timers](/cloud-code/3.0.0/modules/stateful-cloud-code/timers.md#turn-timer-implementation), letting `OnTurnTimeout` skip a player who doesn't act in time while still notifying the next player.

## Asynchronous multiplayer

A player who isn't connected to the server when another player moves won't receive a push message, so their client needs a way to catch up once they reconnect.

A function, for example `GetGameState`, returns whether the current turn belongs to the calling player. The client calls this function when the game launches or returns to the foreground, instead of depending on a push message it might have missed.

## Combine both techniques to cover every player

A single module typically combines both notification techniques, so it can handle players regardless of their connection state when a move happens. The following diagram shows all three outcomes for the same [`MakeMove`](/cloud-code/3.0.0/modules/stateful-cloud-code/timers.md#turn-timer-implementation) call, made by Player A while Player B is connected and Player C isn't:

```mermaid
flowchart TB
    A["<b>Player A</b><br/>Calls MakeMove"] --> DIRECT["Player A's client gets the result<br/>directly in the call's response"]
    A --> S["<b>MultiplayerSession state</b><br/>_currentPlayerIndex advances"]
    S --> SYNC["Server loops through remaining<br/>player IDs and calls<br/>IPushClient.SendPlayerMessageAsync"]
    SYNC --> BR["Player B's client is connected,<br/>so it reacts to the TurnChanged message"]
    S --> ASYNC["Player C isn't connected,<br/>so it doesn't receive the push message"]
    ASYNC --> BR2["Player C reconnects later<br/>and calls GetGameState to catch up"]
```

## Additional resources

* [Send push messages](/cloud-code/3.0.0/modules/how-to-guides/push-messages.md)
* [Turn-based games](/multiplayer/game-types/turn-based-games.md)
