---
metadata:
  - name: generator
    content: Diplodoc Platform v5.54.4
alternate:
  - https://yandex.com/dev/games/doc/en/sdk/sdk-multiplayer-sessions.md
  - https://yandex.com/dev/games/doc/hi/sdk/sdk-multiplayer-sessions.md
  - https://yandex.com/dev/games/doc/ko/sdk/sdk-multiplayer-sessions.md
  - https://yandex.com/dev/games/doc/ru/sdk/sdk-multiplayer-sessions.md
  - https://yandex.com/dev/games/doc/tr/sdk/sdk-multiplayer-sessions.md
  - https://yandex.com/dev/games/doc/vi/sdk/sdk-multiplayer-sessions.md
  - https://yandex.com/dev/games/doc/zh/sdk/sdk-multiplayer-sessions.md
  - href: en/sdk/sdk-multiplayer-sessions.md
    type: text/markdown
    title: Markdown version
  - href: ../llms.txt
    type: text/markdown
    title: llms.txt
---
> **Documentation Index:** Fetch the complete configuration index at https://yandex.com/dev/games/doc/en/llms.txt

# Asynchronous multiplayer

<!-- source: en/_includes/script-common.md -->
<!-- source: en/_includes/script/index-js.md -->

<!-- endsource: en/_includes/script/index-js.md -->

<!-- source: en/_includes/script/requirements-js.md -->

<!-- endsource: en/_includes/script/requirements-js.md -->

<!-- source: en/_includes/script/image-modal-js.md -->

<!-- endsource: en/_includes/script/image-modal-js.md -->
<!-- endsource: en/_includes/script-common.md -->

With the `ysdk.multiplayer` module, you can create a competitive mode similar to online multiplayer. This means you don't need to:

- write and maintain your own server solution;
- have a critical mass of players necessary for fast opponent matching.

Examples of genres whose core mechanics can be implemented via the SDK:

- **Puzzles**: asynchronous sessions can be played on adjacent game boards, and you can add competition based on time or scores. Examples of suitable games: [Solitaire Online!](https://yandex.com/games/app/211144){.external} (by KosmosGames), [Match Arena - Match 3!](https://yandex.com/games/app/96787){.external} (by PecPoc Piggy).
- **Runners and races**: opponents' sessions can be displayed as "ghosts" moving along the level simultaneously with the player (ghost driver mechanic). Examples of suitable games: [Wild Racing 2](https://yandex.com/games/app/374739){.external} (by JL studio) in "Fast Race" mode, [Wild Bikes](https://yandex.com/games/app/233231){.external} (by haoda games).
- **Strategy and auto-battlers**: you can create battles against other players' tactics. Examples of suitable games: [Ludus](https://yandex.com/games/app/376147){.external} (by Positron Dynamics), [Like a King](https://yandex.com/games/app/140656){.external} (by Vladimir Saponenko), [TOYS: Crash Arena](https://yandex.com/games/app/291515){.external} (by Mad Pixel).



## Concept {#concept}

1. User A plays, SDK records key events (key presses, state changes) and timestamps them.
2. These events are stored on the server as a timeline (a list of transactions).
3. When User B starts the game, opponents from the already saved timelines are loaded into their session.
4. The SDK reproduces the opponents' actions in real time, creating the impression of simultaneous play.



## Initialization and Session Loading {#init}

To start working with asynchronous multiplayer, call the `ysdk.multiplayer.sessions.init()` method. This handles initial initialization and loading of the opponents' game sessions.

The method returns an [array of loaded sessions](#response-format).

Accepts parameters:

#|
|| **Parameter** | **Type** | **Description** ||
|| `count` | `number` | Determines the number of sessions to load. The maximum number of sessions in the response is 10. ||
|| `isEventBased` | `boolean` | Flag for [initializing](#use) via events. ||
|| `maxOpponentTurnTime` | `number` | Limits the opponent's turn time and sets the maximum interval between sending `multiplayer-sessions-transaction` events in milliseconds. If specified, each opponent's turn that lasts longer than `maxOpponentTurnTime` will be shortened to the specified value. By default, the opponent's turn time is unlimited.

{% cut "Example of `maxOpponentTurnTime` in action" %}

The opponent in a recorded session made moves with intervals of 2−10 seconds, and the `maxOpponentTurnTime` parameter value is 5000 ms. In this case, all actions of this opponent, regardless of the original turn duration, will occur no later than 5 seconds.

{% endcut %} ||
|| `meta` | `object` | The custom parameters `meta1`, `meta2`, `meta3` are used for selection. They are objects in the form `{ min: %number%, max: %number% }` and are set when [saving a session](#push). For example, if `meta1` stores the game score and `meta2` stores the player's level, you can load saved sessions that are close to these parameters of the current user. ||
|#

{% note warning %}

To load sessions, you need to set at least one of the three `meta` parameters and ensure the `count` value is greater than zero. Otherwise, multiplayer will be initialized only for recording.

{% endnote %}

{% list tabs %}

- Request example

  ```javascript showLineNumbers
  ysdk.multiplayer.sessions.init({
    count: 2, // Number of opponent sessions to load (up to 10).
    isEventBased: true, // Flag to initialize work through events.
    maxOpponentTurnTime: 200, // Opponent's turn time limit (ms).
    [meta](*meta): {
      meta1: {
        min: 0,
        max: 6000,
      },
      meta2: {
        min: 2,
        max: 10,
      },
    },
  }).then(opponents => console.log(opponents));
  ```

- Request example using ES2017 async/await

  ```javascript showLineNumbers
  const work = async () => {
    const opponents = await ysdk.multiplayer.sessions.init({
      count: 2, // Number of opponent sessions to load (up to 10).
      isEventBased: true, // Flag to initialize work through events.
      maxOpponentTurnTime: 200, // Opponent's turn time limit (ms).
      [meta](*meta): {
        meta1: {
          min: 0,
          max: 6000,
        },
        meta2: {
          min: 2,
          max: 10,
        },
      },
    });

    console.log(opponents);
  }

  work();
  ```

{% endlist %}

#### Response format {#response-format}

```javascript showLineNumbers
[
  {
    [id](*id): string;
    [meta](*meta): {
      meta1: number;
      meta2: number;
      meta3: number;
    };
    [player](*player): {
      avatar: string;
      name: string;
    };
    [timeline](*timeline): [
      {
        [id](*timeline_id): string;
        [payload](*payload): object | string | undefined;
        [time](*time): number;
      },
      ...
    ];
  },
  ...
]
```

#|
|| **Parameter** | **Type** | **Description** ||
|| `id` | `string` | Session identifier. ||
|| `meta` | `object` | Custom parameters `meta1`, `meta2`, `meta3`. For example, game score or player level. ||
|| `player` | `object` | Information about the opponent player:
- `avatar: string` — URL of the user's avatar;
- `name: string` — player's name.
||
|| `timeline` | `array` | Array of events with timing information describing the game session:
- `id: string` — unique event identifier;
- `payload` — event data: information that reflects the essence or cause of changes in the game world (e.g., new character coordinates or mouse click);
- `time: number` — time from the start of the game adjusted for pauses (ms).
||
|#



## Recording Game Session {#record}

{% note alert %}

The maximum size of a single recorded session is 200 KB.

{% endnote %}

Use the SDK to record user game sessions (a sequence of events with timestamps). Events can include moving pieces on a board in puzzles or pressing keyboard or mouse buttons in runners.

In games where user input is continuous, such as runners, events may be artificially generated at set time intervals, capturing character state metrics — coordinates, energy levels, etc. They may also include random events in the game, such as rewards or earthquakes.

Events occurring in the game are saved as transactions. Each transaction includes:

#|
|| **Parameter** | **Type** | **Description** ||
|| `id` | `number` | A unique event identifier. ||
|| `payload` | `object` | Event data: information reflecting the essence or reason for changes in the game world (e.g., new character coordinates or a mouse button press). An object with key-value pairs. ||
|| `time` | `number` | Time elapsed since the start of the game, adjusted for pauses.. ||
|#

During the game, save the `payload` using the [commit()](#commit) method. This will form a list of transactions—a timeline of the game session (`timeline`).

At the end of the game, save the session on a server using the [push()](#push) method. Once saved, the session can be loaded and replayed in a subsequent game.


### ysdk.multiplayer.sessions.commit() {#commit}

The method finalizes transactions of the current game session. It takes event data ([payload](*payload)) as an argument.

{% note warning %}

Other transaction parameters — identifier (`id`) and time since the start of the game (`time`) — are computed in the SDK, so it's important to send the `payload` in a timely manner.

{% endnote %}

#### Example {#commit-ex}

```javascript showLineNumbers
// The first transaction.
ysdk.multiplayer.sessions.commit({ x: 1, y: 2, z: 3, health: 67 });

// .......

// The next transaction.
ysdk.multiplayer.sessions.commit({ x: 4, y: -2, z: 19, health: 15 });

// .......
```


### ysdk.multiplayer.sessions.push() {#push}

The method is used to save the timeline on a remote server. It is called at the end of the game.

The values for `meta1`, `meta2`, `meta3` are set when saving the session. At least one of the [meta-parameters](*meta) must be defined.

#### Usage example {#push-ex}

```javascript
ysdk.multiplayer.sessions.push({ meta1: 12, meta2: -2 });
```


## Working with Sessions {#use}

To choose how to work with loaded opponent sessions, pass the desired value of the `isEventBased` flag to the [init()](#init) method:

#|
|| **Value** | **Description** ||
|| `isEventBased: true` | Event-based operation. ||
|| `isEventBased: false` | Manual processing. ||
|#

{% list tabs %}

- Event-based

  The client subscribes to the `multiplayer-sessions-transaction` and `multiplayer-sessions-finish` events using `ysdk.on()`, and the SDK independently loads the general session and issues events at the time stamps indicated in it:

  - During the game, opponent transactions arrive at the `multiplayer-sessions-transaction` handler at the recorded moment from the start of the session, considering the opponent's turn time limit (`maxOpponentTurnTime`, a parameter of the [init()](#init) method).

  - When the session ends, the `multiplayer-sessions-finish` handler is called with the identifier of the opponent whose game has finished.

  ```javascript showLineNumbers
  ysdk.multiplayer.sessions.init({
    count: 2, // Number of opponent sessions to load (up to 10).
    isEventBased: true, // Flag to initialize work through events.
    maxOpponentTurnTime: 200, // Opponent's turn time limit (ms).
    [meta](*meta): {
      meta1: {
        min: 0,
        max: 6000,
      },
      meta2: {
        min: 2,
        max: 10,
      },
    },
  });

  // Here's an array of transactions to be executed at the current time:
  // the current transaction, as well as transactions delayed due to possible game freezes.
  ysdk.on('multiplayer-sessions-transaction', ({ opponentId, transactions }) = > {
    console.log(opponentId, transactions);
    // Applying transaction.payload data to the game field.
  });

  ysdk.on('multiplayer-sessions-finish', (opponentId) => console.log(opponentId));
  ```

  The start and pause of multiplayer are controlled by [gameplay markup](sdk-game-events.md/#gameplay) methods:

  ```javascript showLineNumbers
  // Start multiplayer.
  ysdk.features.GameplayAPI.start();

  // Pause multiplayer.
  ysdk.features.GameplayAPI.stop();
  ```

- Your own solution

  The multiplayer initialization method [init()](#init) returns an array of loaded opponent sessions that contain timelines with transactions.

  Retrieve the data and process it yourself:

  ```javascript showLineNumbers
  const start = (opponent) => {
    console.log('player', opponent.player);
    console.log('timeline', opponent.timeline);

    // Implementation of the mechanism for using timeline and player data.
  }

  const work = async () => {
    const opponents = await ysdk.multiplayer.sessions.init({
      count: 2, // Number of opponent sessions to load (up to 10).
      isEventBased: false, // Flag to initialize work through events.
      maxOpponentTurnTime: 200, // Opponent's turn time limit (ms).
      [meta](*meta): {
        meta1: {
          min: 0,
          max: 6000,
        },
        meta2: {
          min: 2,
          max: 10,
        },
      },
    });

    console.log('opponents', opponents);

    for (let i = 0; i < opponents.length; i++) {
      start(opponents[i]);
    }
  }

  work();
  ```

{% endlist %}


---

<!-- source: en/_includes/sdk-support.md -->
{% note info %}

Our support team can help publish finished games on Yandex Games. If you have any questions about development or testing, ask them in the [Discord channel](https://discord.com/invite/wU4p3whr4T){.external}.

{% endnote %}

If you are facing an issue or have a question regarding the use of Yandex Games SDK, please contact support:

<!-- source: en/_includes/button-chat.md -->
<a href="https://yandex.com/chat/#/user/a4fa5c06-75db-9b38-6eea-b1673785f7d5">
  <span class="button">Write to chat</span>
</a>
<!-- endsource: en/_includes/button-chat.md -->
<!-- endsource: en/_includes/sdk-support.md -->

[*id]: Session identifier.

[*meta]: Custom parameters `meta1`, `meta2`, `meta3`, set when saving the session. For example, the game score or player level.

[*player]: Information about the opposing player:
- `avatar: string` — URL of the user's avatar;
- `name: string` — the player's name.

[*timeline]: Array of timed events describing the game session:
- `id: string` — unique event identifier;
- `payload` — event data: information reflecting the essence, reason for changes in the game world (e.g., new character coordinates or mouse button press);
- `time: number` — time from the beginning of the game adjusted for pauses (ms).

[*timeline_id]: Unique event identifier.

[*payload]: Event data: information reflecting the essence, reason for changes in the game world (e.g., new character coordinates or mouse button press).

[*time]: Time from the beginning of the game adjusted for pauses.