# Room モジュールをクライアントから利用する

## はじめに

本ページでは C++ クライアント・ランタイムから **Diarkis Module** を使用して Room モジュールを使用する際の流れについて説明します。\
Room モジュールを使用する前に Diarkis サーバーとの接続が完了している必要がありますので、（link to Diarkis モジュール利用の全体的な流れ）を参照して Diarkis サーバーと接続してください。 Room モジュールは TCP/UDP どちらでも使用可能です。

## 基本的な使い方

### Diarkis Module の Room をセットアップする

まず初めに `DiarkisInterfaceBase::SetupRoom()` を呼び出して **Diarkis Module** の **DiarkisRoomBase** をセットアップします。\
`SetupRoom` では **DiarkisRoomBase** を初期化しロギングやイベント・コールバックの設定が行われます。 セットアップ完了後、各種 Room の機能ができるようになります。

### Room を作成する

`DiarkisRoomBase::SendCreateRoom()` を使用して Room をサーバー上に作成することができます。\
Room 作成時は参加可能人数、空の Room を残すかどうか、作成と同時に部屋へ参加するか、Room のサーバー上での生存時間、データ送信の間隔等を指定可能です。\
詳細については `DiarkisRoomBase::SendCreateRoom()` のドキュメントを参照してください。

また、サーバー上で Room の作成が完了すると `DiarkisRoomBase::OnRoomCreation()` がイベントとして通知されます。\
ユーザーはこのイベントの引数で作成された Room の ID を取得することができます。 **Diarkis Module** を使用している場合、内部でこの ID を保存しており、`DiarkisRoomBase::GetRoomID()` 等のメソッドで Room ID を取得することができます。

### Room に参加する

`DiarkisRoomBase::SendJoinRoom()` で Room ID を指定して Room に参加することができます。Room ID は DM 等、何らかの通信を使用して Room を作成したユーザーから通知してもらう必要があります。\
また、`DiarkisRoomBase::SendRandomJoinRoom()` を使用して参加可能な Room にランダムで参加する機能もあります。 この機能では参加可能な Room が無かった場合、新たに Room を作成します。

サーバー上で Room へユーザーが参加した場合、参加したユーザーには `DiarkisRoomBase::OnRoomJoin()`が、すでに Room に入っているユーザーには `DiarkisRoomBase::OnRoomMemberJoin()` がイベントとして通知されます。

### Room に参加しているユーザーにメッセージを送る

Room に参加している状態で以下のメソッドを使用することで任意のデータを他のユーザーに送信することができます。送信したデータはサーバー上で処理され、サーバーから他のユーザーへ送信されます。

* `DiarkisRoomBase::SendBroadcastToRoom()`
  * 部屋に参加しているユーザー全員にデータを送信します。
* `DiarkisRoomBase::SendMessageToRoom()`
  * 引数で指定したユーザーだけにデータを送信します。
* `DiarkisRoomBase::SendRelay()`
  * 部屋に参加している自分以外のユーザーにデータを送信しますが BroadcastToRoomと異なりサーバーから可能な限り早くデータを送信します。
* `DiarkisRoomBase::SendRelayTo()`
  * 引数で指定したユーザーだけにデータを送信しますが MessageTo と異なりサーバーから可能な限り早くデータを送信します。

これらのメソッドで送信されてたメッセージを受信した場合、以下のイベントが発生し受信したデータを受け取ることができます。

* `DiarkisRoomBase::OnRoomMemberBroadcast()`
  * `DiarkisRoomBase::SendBroadcastToRoom()` で送信したデータの受信イベント
* `DiarkisRoomBase::OnRoomMemberMessage()`
  * `DiarkisRoomBase::SendMessageToRoom()` で送信したデータの受信イベント
* `DiarkisRoomBase::OnRoomRelay()`
  * `DiarkisRoomBase::SendRelay()` で送信したデータの受信イベント
* `DiarkisRoomBase::OnRoomRelayTo()`
  * `DiarkisRoomBase::SendRelayTo()` で送信したデータの受信イベント

### Room から離脱する

`DiarkisRoomBase::SendLeave()` を実行することで現在参加している Room から離脱することができます。 離脱処理がサーバー上で実行されると `DiarkisRoomBase::OnRoomLeave()` イベントが発火して処理結果を通知します。また、離脱したユーザー以外のユーザーでは `DiarkisRoomBase::OnRoomMemberLeave()` が発火してユーザーが部屋から離脱したことが通知されます。離脱した結果、Room のオーナーが変わった場合は `DiarkisRoomBase::OnRoomOwnerChange()` が発火します。

## Room の情報を取得する

Room に関する情報をサーバーに問い合わせて取得することが可能です。

### Room のオーナーを取得する

`DiarkisRoomBase::SendGetOwnerID()` を実行することで現在の Room のオーナー ID をサーバーに問い合わせることができます。\
問い合わせた結果は `DiarkisRoomBase::OnRoomGetOwnerID()` が発火することで通知され結果が `DiarkisRoomBase` 内に保存されます。\
保存されている ID は `DiarkisRoomBase::GetOwnerUID()` で取得することができます。

### Room の参加メンバーを取得する

`DiarkisRoomBase::SendGetMemberIDs()` を実行することで現在 Room に参加しているユーザーの ID のリストをサーバーに問い合わせることができます。\
問い合わせた結果は `DiarkisRoomBase::OnRoomMemberIDs()` が発火することで通知され結果が `DiarkisRoomBase` 内に保存されます。\
保存されているユーザー ID のリストは `DiarkisRoomBase::GetRoomMembers()` で取得することができます。

### Room の参加メンバー数を取得する

`DiarkisRoomBase::SendGetNumberOfMembers()` を実行することで現在 Room に参加しているユーザーの数をサーバーに問い合わせることができます。\
問い合わせた結果は `DiarkisRoomBase::OnRoomNumberOfMembers()` が発火することで通知されます。

## Room で情報を共有する

サーバー上の Room を使用して Room に参加しているユーザー間でデータを共有することができます。

### プロパティを使用してデータを共有する

Coming Soon

### オブジェクトを使用してデータを共有する

Coming Soon

### Room 内でメッセージをやり取りする

Coming Soon

## 特殊な機能

### Room の参加者で P2P 接続をする

Room に参加しているユーザー同士で P2P 接続を行うことができます。\
Room に参加しているユーザーが `DiarkisRoomBase::SendStartP2PSync()` を呼び出すことで P2P 接続プロセスが開始されます。このリクエストを受信したサーバーは Room に参加しているユーザーに対して接続先のアドレスのリストを送信します。クライアント側では `DiarkisRoomBase::OnStartP2PSync()` が発火してこの通知を受け取り、送信されてきた接続先のアドレスのリストに対してホールパンチ・プロセスを開始します。ホールパンチングが完了すると、接続したピア同士で直接通信することが可能となります。

### Room の予約

Coming Soon

### Room を検索する

Coming Soon

### Room のマイグレーション

Room を使用中にマイグレーションが発生した場合、Room 専用のマイグレーション処理を実行する必要があります。

Room モジュールの特性上同じ Room に参加しているメンバーは同じサーバーに接続している状態となります。Room が作成されている Diarkis サーバーがスケールインする場合、Room に参加している全メンバーのサーバーの再接続と、同じ Room への移動が必要となります。Room のオーナーが マイグレートを呼び出すだけで、自動でマイグレーション処理が実行されます。

マイグレーションの詳細については [マイグレーション](/diarkis-client/diarkis-module/migration.md) を参照してください。

Room に参加しているときにマイグレーション発生する場合、`DiarkisTcpBase/DiarkisUdpBase` の `OnOffline()` ではなく、`DiarkisRoomBase::OnOffline()` が呼び出され、接続中のサーバーのスケールインと Room のマイグレーション処理が必要なことが通知されます。

SDK 付属のサンプルコードでは以下のように実装されています。

```
void DiarkisRoom::OnOffline()
{
    DiarkisRoomBase::OnOffline();

    // サーバのスケールインにより、入室している Room があるサーバが offline になります。
    // アプリ側の実装に合わせて、適したタイミングで SendMigrateRoom を呼び出して Room（サーバ）の移動を行ってください。
    if (GetOwnUID() == GetOwnerUID())
    {
        // Room のオーナーが Migrate を呼ぶ
        this->SendMigrateRoom();
    }

}
```

ただ、Room の場合はサンプルのコメントにもあるように Room のオーナだけが `DiarkisRoomBase::SendMigrateRoom()` を呼び出す必要があります。\
また、`DiarkisTcpBase/DiarkisUdpBase` 同様、呼び出し後、Room から一時的に切断されるため `DiarkisRoomBase::SendMigrateRoom()` を呼び出すタイミングはアプリの都合に合わせて調整してください。

サーバー側も含めた詳細なフローについては、以下の API ドキュメントを参照してください。

<https://docs.diarkis.io/docs/server/v1.0.0/diarkis/room/index.html#MigrateRoom>


---

# 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://help.diarkis.io/diarkis-modules/room/setup-client.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.
