# session\_simple

## session\_simple サンプル

### 概要

4 人のユーザーが Session モジュールを使用してメッセージのやり取りを行います。 Session モジュールの特徴については[こちらのページ](https://help.diarkis.io/diarkis-modules/session)を参照してください。

### ローカル環境でサーバーを起動する

サンプルで使用するサーバーを起動するためのチュートリアルを実施して、ローカル環境で Diarkis サーバーを起動します。

[setup-local-server](https://help.diarkis.io/getting-started/tutorial/setup-local-server "mention")

### サンプルの引数

サンプルの起動時には以下の３つのパラメータを指定してください。

`session_simple.exe serverAddr UID clientKey`

| 引数         | 説明                            |
| ---------- | ----------------------------- |
| serverAddr | Diarkis サーバのエンドポイントを指定してください  |
| UID        | 接続するユーザーの ID を任意の文字列で指定してください |
| clientKey  | クライアントキーを任意の文字列で指定してください      |

#### 起動例：

`session_simple.exe 192.168.1.123:7000 1111 AAAA`

### 起動方法

本サンプルは 4 クライアントが既定の UID で接続する前提の実装となっています。起動時は "1111", "2222", "3333", "4444" の UID でサンプルを起動してください。\
起動後、"1111" は他のユーザーを招待して Session に参加する形でサンプルが動作しますので "1111" 以外のユーザーを起動後、最後に "1111" を起動してください。

### サンプルコード説明

#### Session を使用する全体的な流れ

1. Diarkis ランタイムおよび Diarkis Module を初期化し、Diarkis サーバーへ接続します。\
   詳細については [Diarkis モジュール利用の全体的な流れ](https://help.diarkis.io/diarkis-module#diarkis-モジュール利用の全体的な流れ) を参照してください。
2. セットアップ\
   Session モジュールを初期化します。

   ```
   diarkis = Diarkis::DiarkisAllocShared<DiarkisInterfaceSessionSimple>(uid);
   ...
   // DiarkisInterface 内で管理されている Session モジュールを初期化します。
   // Session モジュールのインスタンスを確保して、通信に使用する UDP モジュールと関連付けます。
   // 以降、Session モジュールのポインタを DiarkisInterface から取得して Session の機能にアクセスします。
   diarkis->SetupSession();
   ```
3. Session の作成\
   `DiarkisSessionBase::SendCreate` を使用して Session の作成をサーバへリクエストします。`DiarkisSessionBase::HasSession` を使用して、特定の Session が作成済みかをチェックすることができます。

   ```
   session->SendCreate(SessionSimple::SessionType::Global, 3, 60);
   while (!session->HasSession(SessionSimple::SessionType::Global))
   {
       std::this_thread::sleep_for(std::chrono::milliseconds(100));
   }
   ```
4. Session への招待\
   `DiarkisSessionBase::SendInvite` を使用して他のユーザーを Session へ招待します。招待するにはユーザーの UID を知っている必要があるため Session 以外の方法で UID を事前に共有する必要があります。本サンプルではすでに共有済みの状態を想定して実装されています。

   ```
   const char* inviteMembers[2] =
   {
       "2222",
       "4444"
   };
   session->SendInvite(SessionSimple::SessionType::Global, &inviteMembers[0], 2, "Do you want to join us?");
   ```
5. Session への参加\
   他のユーザーから招待を受けると `DiarkisSessionBase::OnSessionInvite` が発火します。 `DiarkisSessionBase::OnSessionInvite` では引数の `DiarkisSessionInviteEventArgs` で Session ID と SendInvite に渡されたメッセージを取得することができます。 本サンプルでは `DiarkisSessionInviteEventArgs` で取得した Session ID を使用して `DiarkisSessionBase::SendJoin` を実行することで Session に参加しています。\
   また、Session モジュールでは複数の Session に参加することが可能です。 本サンプルでも全体 Session とチーム Session に見立てて複数の Session に参加しています。

   ```
   void OnSessionInvite(const DiarkisSessionInviteEventArgs& e) override
   {
       // Invite されたときの session type をチェックして join しています。
       switch (e.GetSessionType())
       {
       case SessionType::Global:
           if (ownUID_ == "2222" || ownUID_ == "4444")
           {
               DiarkisUtils::Print("SendJoin(%d, %s) is called in %s", e.GetSessionType(), e.GetSessionID().c_str(), ownUID_.c_str());
               SendJoin(e.GetSessionType(), e.GetSessionID().c_str());
           }
           break;
       ...
   ```
6. メッセージの送信\
   Session に参加後、`DiarkisSessionBase::SendBroadcast` 等メッセージ送信系の API を使用して Session に参加しているメンバーにメッセージを送ることができます。

   ```
   const char* GlobalBroadcastMessage = "Message to the Global session type";
   session->SendBroadcast(SessionSimple::SessionType::Global, GlobalBroadcastMessage);
   ```
7. メッセージの受信\
   他のユーザーからメッセージを受信すると `DiarkisSessionBase::OnSessionBroadcast` や `DiarkisSessionBase::OnSessionMessageTo` が発火します。ユーザーは `DiarkisSessionBase` のこれらのメソッドをオーバーライドすることで受信したデータに対してアプリ固有の処理を実装することができます。

   ```
   void OnSessionBroadcast(const DiarkisSessionNotificationEventArgs& e) override
   {
       DiarkisSessionBase::OnSessionBroadcast(e);
       DiarkisUtils::Print("SessionSimple::OnSessionBroadcast(%d, %s) is called in %s", e.GetSessionType(), e.GetContent().c_str(), ownUID_.c_str());
   }

   void OnSessionMessageTo(const DiarkisSessionNotificationEventArgs& e) override
   {
       DiarkisSessionBase::OnSessionMessageTo(e);
       DiarkisUtils::Print("SessionSimple::OnSessionMessageTo(%d, %s) is called in %s", e.GetSessionType(), e.GetContent().c_str(), ownUID_.c_str());
   }
   ```
8. ユーザーのキック\
   `DiarkisSessionBase::SendKick` を使用することで特定のユーザーを Session から強制的に追い出すことができます。

   ```
   // "4444" をキックして SessionType::Global(0) から除外します。
   session->SendKick(SessionSimple::SessionType::Global, "4444");
   ```
9. 切断処理\
   `DiarkisSessionBase::SendLeave` を使用することで Session から退出することができます。

   ```
   session->SendLeave(SessionSimple::SessionType::Global);
   ```
10. 終了処理\
    詳細については [Diarkis モジュール利用の全体的な流れ](https://help.diarkis.io/diarkis-module#diarkis-モジュール利用の全体的な流れ) を参照してください。
