# v1.1.1

本ドキュメントは CSAR モジュール に関するドキュメントです。\
CSAR モジュール は [Diarkis ランタイム・ライブラリ](https://help.diarkis.io/diarkis-client/runtime-library) と [Diarkis-Module](https://help.diarkis.io/diarkis-client/diarkis-module) の上位レイヤーにあたり、Diarkis の低レイヤーの機能を組み合わせて一般的なゲームやアプリの実装モデルを想定した機能を提供し、より使いやすくしたライブラリです。

## 通信モデル

CSAR では通信モデルとして Single Authority （スター型）と No Authority（メッシュ型）をサポートしており、このどちらかもしくは混在させて使用することができます。

#### Single Authority (スター型)

通信トポロジーのスター型のように、オーソリティとなるホスト役が存在しそのホスト役に対して各クライアントが接続するタイプになります。クライアントはホスト役のみと送受信する事が可能で、ホスト役は全クライアントから受け取ったデータをもとにゲームサーバの処理を行い結果をクライアントに返すようなモデルを想定しています。Single Authority には、Client-Hosted タイプと DGS タイプがあります。\
DGS タイプは、ホスト役はクライアントではなく Dedicated Game Server (専用ゲームサーバー) がオーソリティを担います。クライアントプログラムは CSAR を通して Diarkis クラスタ内に配置した DGS サーバーに接続することができます。\
Client-Hosted タイプは、クライアントの中の１つがホスト役も担います。ネットワークに参加したコンピュータの中から CSAR が自動的にオーソリティとなるホスト役のユーザーを指定します。

#### No Authority (メッシュ型)

オーソリティとなるホスト役が存在せず、各クライアントが対等な関係で接続するタイプです。ネットワークに参加している各コンピュータがそれぞれ全員とデータの送受信をすることが可能です。

## 通信経路の抽象化

[Diarkis ランタイム・ライブラリ](https://help.diarkis.io/diarkis-client/runtime-library) には Room を使用したリレー通信、P2P 通信など様々な経路の通信方法が存在します。 クライアントライブラリを直接使用する場合、目的に応じてユーザーが API を使い分ける必要がありますが、CSAR では初期化時に使用したい通信経路を指定するとその経路の中で利用可能なものを使用してデータの送受信を行います。 たとえば初期化時に Room と P2P を有効にすると P2P を優先して使用しつつ、ホールパンチングに失敗したユーザーに対しては Room でデータを送信するといった動作をします。

## CSAR に接続する流れ

CSAR に接続し、他のユーザーと通信を行うための手順について説明します。

#### 初期化処理

`ConnectionManager` のインスタンスを作成します。`ConnectionManager` は CSAR の機能にアクセスするためのインターフェイスです。内部に `DiarkisInterface` をもっており、この機能を使用して CSAR の機能を提供します。`DiarkisInterface` は `ConnectionManager` の初期化時に外部から渡すインターフェイスもあり、ユーザーが作成したものを使用することも可能です。

#### Diarkis サーバへ接続

`ConnectionManager::ConnectDiarkisServer` で Diarkis サーバへ接続します。本 API の初期化時にコンフィグとして接続先のサーバのアドレスなどを設定します。接続処理の結果は `DiarkisConnectionEvent` で受け取ることができ `ConnectionManager::AddServerConnectCallback` で呼び出されるコールバックを設定することができます。

#### ゲームインスタンスの開始

Diarkis サーバへ接続完了後、`ConnectionManager::StartGameInstance` でゲームインスタンスを開始することができます。 ゲームインスタンスはデータの送受信を行うグループを表す概念で CSAR を使用して通信を行うユーザーは同じゲームインスタンスに参加する必要があります。 ゲームインスタンスはゲームインスタンス ID によって識別され、それぞれのユーザーが同じ ID に対して `ConnectionManager::StartGameInstance` を実行することにより同じゲームインスタンスに参加することができます。

#### **ConnectionMode**

ゲームのタイプによって Authority となるホスト役が必要になるかで指定することができます。

<table><thead><tr><th width="185">Mode</th><th></th></tr></thead><tbody><tr><td>Single Authority</td><td>Authority となるホスト役が存在し、そのホスト役で当たり判定などを行ってゲームが進行するタイプになります。Host-Cliented タイプや DGS タイプのゲームで利用頂けます。</td></tr><tr><td>No Authority</td><td>Authority となるホスト役が存在せず、各クライアントが対等な関係で接続するタイプです。格闘ゲームなどのゲームで利用を想定したモードになります。</td></tr><tr><td>Shared Authority</td><td>全クライアントで Authority を共有して、ホスト役とクライアント役を担います。 ※1</td></tr></tbody></table>

※1 :  Shared Authority モードは、今後削除を予定しています。ご利用を予定されている場合ご相談ください。

#### **NetworkType**

以下の通信タイプから選択することができます。

<table><thead><tr><th width="145.333251953125"></th><th></th></tr></thead><tbody><tr><td>Room &#x26; P2P</td><td>内部的に Room に入室して、 Room 経由の Relay 通信 と P2P を利用して通信します。P2P で通信できる時 P2P で通信し、P2P で通信できにないときは Room 経由で通信します。どの経路で通信しているか意識しないで使用することができます。</td></tr><tr><td>Room</td><td>内部的に Room に入室して、 Room 経由の Relay 通信のみを利用して通信します。</td></tr><tr><td>DGS</td><td>内部的に Room に入室して、別途起動している DGS サーバーに接続して通信します。DGS では、必ず ConnectionMode は Single Authority を選択して頂く必要があります。※2</td></tr><tr><td>OFFLINE</td><td>Diarkis サーバーに接続せず OFFLINE でゲームを動作させるためのモードになります。OFFLINE では、必ずConnectionMode は Single Authority を選択して頂く必要があります。</td></tr></tbody></table>

※2 : DGS を使用する際は、別途 アプリケーションを DGS サーバーで起動しておく必要があります。

#### **MaxMembers**

ゲームインスタンスに参加するクライアントの数を指定します。

## インゲームセッション中のユーザー管理とデータ送受信

#### ゲームインスタンスの開始処理

ゲームインスタンス開始処理の結果は `GameInstStartEvent` で受け取ることができ `ConnectionManager::AddGameInstStartCallback` で呼び出されるコールバックを設定することができます。\
ゲームインスタンス開始が成功すれば自分自身は CSAR への接続が完了した事になります。\
また、ゲームインスタンスに参加した結果、自分がゲームのホスト役となった場合、ゲームサーバの処理の開始を要求する `LaunchHostProcess` イベントが発生します。 このイベントはゲームサーバの処理を新たに開始する必要がある、ゲームインスタンスの開始時と後述するホストマイグレーション時に発生します。 ユーザはこのイベントのコールバックをトリガーとしてゲームサーバの開始処理を行うことができます。 `LaunchHostProcess` イベントは `ConnectionManager::AddLaunchHostProcessCallback` で呼び出されるコールバックを設定することができます。

#### 参加ユーザーの情報取得

ゲームインスタンスに自分以外のユーザーが接続すると `UserConnect` イベントが発生します。`UserConnect` イベントは `ConnectionManager::AddUserConnectCallback` で呼び出されるコールバックを設定することができます。 ゲームインスタンスから自分以外のユーザーが離脱すると `UserDisconnect` イベントが発生します。`UserDisconnect` イベントは `ConnectionManager::AddUserDisconnectCallback` で呼び出されるコールバックを設定することができます。 ゲームインスタンスに参加しているユーザーは `ConnectionManager::GetConnectedClients` もしくは `ConnectionManager::GetConnectedUsers` で取得することが可能です。詳細は API ドキュメントをご参照ください。

#### データの送受信

Single Authority を使用している場合、データの送信には Single Authority 専用の `SendToHost/SendToClient` を使用します。この API で送信したデータは `DataToHost/DataToClient` イベントで受け取ることができ、`ConnectionManager::AddDataToHost/AddDataToClient` で呼び出されるコールバックを設定することができます。

No Authority を使用している場合、データの送信には No Authority 専用の `SendBroadcast/SendMulticast/SendUnicast` を使用します。この API で送信したデータは `DataToUser` イベントで受け取ることができ、`ConnectionManager::AddDataToUserCallback` で呼び出されるコールバックを設定することができます。

#### 終了処理

ゲームインスタンスから離脱するには `ConnectionManager::ExitFromGameInstance` を使用します。  ゲームインスタンスから離脱すると `ConnectionManager::ExitFromGameInstance` を実行したユーザーは `GameInstExit` イベントで離脱したことを受け取ることができ、`ConnectionManager::AddGameInstExitCallback` で呼び出されるコールバックを設定することができます。 Single Authority のクライアントを除くその他のユーザーは `OnUserDisconnect` を受け取ります。

ゲームインスタンスから離脱後、`ConnectionManager::DisconnectDiarkisServer` を使用して Diarkis サーバから切断します。

#### ホスト役かどうかの判断

`ConnectionManager::IsHost` で自身がホスト役になっているかどうかを確認することができます。

## ホストマイグレーションのフロー

CSAR は既存のホスト役が不在となった場合でも新たなホスト役を選任してホスト役を切り替える事 (ホストマイグレーション) でゲームを継続することができます。ホストマイグレーションは CSAR が Single Authority でかつ Host-Cliented タイプで動作している場合にのみ有効です。No Authority や DGS を用いたゲームでは機能しません。ホストマイグレーションは、主に次のような状況で発生します：

* ホストがゲームインスタンスから退出した場合や、アプリのクラッシュなどによりネットワークから切断された場合
* `ConnectionManager::TransferHost` の実行により、ホストの役割が他のクライアントに委譲された場合

&#x20;ホストマイグレーションは以下のフローで実行されます。

#### ホストの状態の保存

ホストマイグレーションに備えて、ホスト役だけが持っているマスターデータの情報を Diarkis サーバー 上に保存することが可能です。 `ConnectionManager::StoreGameState` を呼び出すことで任意のバイト列を 10 KiB まで保存することができます。

#### クライアントの場合

ホスト役が認識できなくなった場合、`HostOffline` イベントが発生します。 `HostOffline` 通知後、CSAR は 自動的に新たなホスト役に接続する処理を開始します。その後、新たなホスト役が決定し、通信の準備が完了すると `HostMigrationComplete` イベントが発生します。

`HostOffline` イベントは `ConnectionManager::AddHostOfflineCallback` で、`HostMigrationComplete` イベントは `ConnectionManager::AddHostMigrationCompleteCallback` でそれぞれ呼び出されるコールバックを設定することができます。

#### 新しいホストの場合

新しくホスト役として選出された場合、クライアントの側のイベントに加えて `LaunchHostProcess` イベントが発生します。 このイベントでは新たにホスト役として選出されたことの通知とともに前任のホスト役が `ConnectionManager::StoreGameState` で保存したデータがあればそのデータを取得することが可能です。このデータをもとにアプリ側でホスト役の状態を復元することで、ホストが他のコンピュータに移動しても保存時の状態を復帰することできます。`ConnectionManager::GetConnectedClients` で取得できるホスト役から見たクライアントのリストも、この時点で接続しているクライアントが返るようになります。

## ゲームインスタンスのライブマイグレーション

Diarkis サーバーがスケールインなどによってシャットダウンされる際に稼働中のゲームインスタンスがある場合、ゲームインスタンスを別な Diarkis サーバーにマイグレートすることでゲームを継続することが可能です。

#### GameInstanceOffline イベント

Diarkis サーバーのプロセスがシャットダウンされる際にサーバーはクライアントに offline になる旨を通知します。クライアント側では `GameInstanceOffline` イベントがトリガーされます。`GameInstanceOffline` イベントはゲームインスタンスを構成するクライアントのうち1人だけにトリガーされます。ホストクライアント型のゲームであればホスト役で、メッシュ型のゲームであれば誰か1人が自動で選ばれそのクライアントでトリガーされます。

`GameInstanceOffline` イベントを受信したクライアントは `ConnectionManager::MigrateGameInstance` を実行することでマイグレーションを開始することができます。マイグレーションが開始されるとゲームインスタンス内の全てのクライアントが自動で新しい Diarkis サーバーに再接続します。

以下は `GameInstanceOffline` イベントのコールバック実装の例です。

```
void OnGameInstanceOffline(const GameInstanceOfflineEventArgs& args)
{
    // Call MigrateGameInstance at the appropriate timing according to the app-side implementation to migrate the GameInstance.
    // アプリ側の実装に合わせて、適したタイミングで MigrateGameInstance を呼び出して GameInstance の移動を行ってください。
    DiarkisUtils::Print("Start migrate game instance...");
    gManager->MigrateGameInstance();
}

```

なお、`ConnectionManager::MigrateGameInstance` を実行して再接続処理が開始すると現在接続しているサーバーと切断されるため一時的に通信できなくなります。 切断が発生するタイミングは `ConnectionManager::MigrateGameInstance` を実行するタイミングでコントロールすることができますので、アプリケーションの都合に合わせて調整してください。

#### GameInstanceMigrationStart イベント

ゲームインスタンスのマイグレーションが開始されると `GameInstanceMigrationStart` イベントが全てのクライアントでトリガーされます。`GameInstanceMigrationComplete` イベントがトリガーされるまで他のクライアントと通信することはできません。

#### GameInstanceMigrationComplete イベント

新しいサーバーに接続しゲームインスタンスのマイグレーションが完了すると `GameInstanceMigrationComplete` イベントが全てのクライアントでトリガーされます。このイベントが成功した場合、他のクライアントとの通信が可能になります。

\* 現在ゲームインスタンスのマイグレーションは Room ベースのゲームでのみ使用可能で、DGS のときは動作しません。

## その他の機能

#### Single Authority と メッシュ型 の共存

ゲームインスタンスをSingle Authority で初期化後に `ConnectionManager::AllowSendDataBetweenClients` を使用することで同時にメッシュ型の通信を使用することができるようになります。 この機能はデフォルトでは無効になっており、明示的に有効化する必要があります。ゲームインスタンスが開始された後に`ConnectionManager::AllowSendDataBetweenClients` を `true` で呼び出すと `SendBroadcast`, `SendMulticast`, `SendUnicast` を実行してクライアント間でデータをやり取りすることができるようになります。これらのデータは`DataToUserCallback` で受信することができます。また、`ConnectionManager::GetConnectedUsers` で他のクライアントの UID を取得することが可能になります。
