# matching\_and\_turn

## matching\_and\_turn サンプル

### 概要

MatchMaker モジュールを使用してマッチングを行った後、マッチしたユーザー達が別のサーバに接続してメッセージを送受信する複合的なサンプルです。 このサンプルは、マッチングを経て集まったユーザー同士が別のサーバに移動してゲームの本編部分をプレイする動線を模したものになっています。\
また、本サンプルではマッチング後、別サーバ上でのインゲームデータのやり取りに CSAR を使用しています。 CSAR を利用することによりマッチングしたユーザー同士が集まった場で唯一の Authority を決定しゲーム全体の進行管理役として扱ったり、Room と P2P の透過的な利用ができたりゲームを実装するうえで様々なメリットがあります。CSAR についての詳細は[こちら](/diarkis-client/csar-clustered-server-authoritative-ruler.md)を参照してください。

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

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

[1. Diarkis サーバーをローカル環境で起動する](/getting-started/tutorial/setup-local-server.md)

また、本サンプルではマッチングに使用する UDP サーバとインゲームでの通信用の UDP サーバの２つのサーバを用意する必要があります。チュートリアルでは UDP サーバを１台だけ起動する手順になっているため、`DIARKIS_SERVER_TYPE`  に `TURN` を指定してもう１台 UDP サーバを起動しておいてください。

**起動コマンド例**

`DIARKIS_SERVER_TYPE=TURN ./remote_bin/udp`

### サンプルの引数

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

`matching_and_turn.exe serverAddr UID clientKey`

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

#### 起動例：

`matching_and_turn.exe 192.168.1.123:7000 1111 AAAA`

### 起動方法

本サンプルは起動すると MatchMaker のチケットを発行してマッチング待ち状態に入ります。 サンプルプログラムを 2 つ起動するとチケットがマッチし別サーバ上で CSAR の GameInstance に入る処理に移行します。 GameInstance に接続後、それぞれのユーザーがメッセージを送受信しプログラムが終了します。

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

本サンプルはマッチメイキング部分とインゲーム部分に分けて実装されており、マッチメイキングとインゲームで別のサーバへ接続する想定の実装となっています。 タイミングや機能によって接続先サーバを切り替えるには、接続先のサーバ毎に `DiarkisInterfaceBase` を用意して使用する必要があります。 マッチメイキング部分では `DiarkisInterfaceBase` を直接利用していますが、インゲーム部分では CSAR が内部で管理してる `DiarkisInterfaceBase` を間接的に利用しています。\
また、本サンプルでは基礎的な Diarkis サーバへの接続方法等は説明していません。必要に応じて [room\_broadcast ](/diarkis-client/samples/cpp/room-broadcast.md)等の基礎的なサンプルを参照してください。

#### マッチメイキング処理

`MatchMaking` 関数に実装されています。

**DiarkisInterface について**

マッチメイキングではマッチメイキング用のサーバに接続するために専用の `DiarkisInterfaceBase` のインスタンスを用意して使用しています。

```
bool MatchMaking(const std::string& host, const std::string& uid, const std::string& clientKey, std::string& gameInstanceId)
{
    // DiarkisInterfaceインスタンスの作成
    std::shared_ptr<DiarkisInterface> diarkisMatch = Diarkis::DiarkisAllocShared<DiarkisInterface>(uid);
    ...

```

このインスタンスは `MatchMaking` 関数を抜ける際に破棄されており、このタイミングでマッチメイキング用サーバから切断しています。

**マッチメイキング**

本サンプルでは MatchMaker モジュールのチケットを使用してマッチングを行っています。

```
...
// サーバに MatchMaker IssueTicket を送信
diarkisMatch->GetMatchMakerBase()->SendIssueTicket(0);

while (!diarkisMatch->GetMatchMakerBase()->IsTicketComplete())
{
    ...
```

MatchMaker モジュールのチケットの使用方法については [matchmaker\_ticket](/diarkis-client/samples/cpp/matchmaker-ticket.md) サンプルに詳細が記載されていますのでそちらを参照してください。

**インゲーム用サーバへ接続する情報の共有**

マッチング完了後、マッチしたユーザー同士でインゲーム用サーバへ接続するために情報を共有しています。

```
// GameInstanceId をマッチングのオーナーから送信する
if (owner)  // matching owner
{
    // マッチングサーバのオーナーである場合、マッチングしたユーザに GameInstanceId を送信する
    // GameInstanceId は一般的にゲーム側で作成する必要がある。
    // 今回はテストのためにマッチングオーナーが作成する。
    gameInstanceId = "TestGameInstanceId";
    std::vector<uint8_t> gameInstanceIdVec(gameInstanceId.begin(), gameInstanceId.end());
    diarkisMatch->GetMatchMakerBase()->SendTicketBroadcast(0, gameInstanceIdVec);
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
else  // not matching owner (member)
{
    // マッチングのオーナーでない場合、マッチングのオーナーから GameInstanceId を待つ
    DiarkisUtils::Print("I am not owner. Receiving GameInstanceId from matching owner.");
    while (true)
    {
        ...
```

CSAR では任意の文字列を使用して同じ GameInstance に参加することができます。 本サンプルではマッチングオーナーとなったユーザーが決定した任意の文字列を他のユーザーに送信することで同じ GameInstance に参加するための情報を共有しています。 この時のメッセージの送信にはチケットでマッチしたユーザー全員にメッセージを送信することができる `DiarkisMatchMakerBase::SendTicketBroadcast` が使用されています。

ここまでのプロセスでマッチングが完了し、マッチしたユーザー間で同じ GameInstance に参加するための情報が共有されました。

#### インゲーム部分

`StartGameInstanceAndSendMessage` 関数に実装されています。 インゲーム部分では CSAR を使用し、同じ GameInstance に参加してメッセージのやり取りを行っています。

**同じ GameInstance に参加**

`StartGameInstanceAndSendMessage` では `MatchMaking` で共有された GameInstanceID を使用して CSAR の GameInstance に接続しています。

```
...
const int numClients = 2;
GameInstanceHostClientConfig config;
// MatchMaking 関数で共有された GameInstanceID を使用する
config.gameInstanceId = gameInstanceId.c_str();
config.networkType = GameInstNetworkType::ROOM_AND_P2P;
config.minMembers = 1;
config.maxMembers = numClients; // Game instance に参加するクライアント数 // Number of clients to join the game instance
manager->StartGameInstance(config);
...
```

各ユーザーが同じ GameInstanceID を使用しているため同じ GameInstance に参加することができます。

**メッセージの送受信**

CSAR の GameInstance に参加後は通常の CSAR の利用方法でメッセージの送受信を行うことができます。

```
...
// メッセージを送信
if (manager->IsAuthority())
{
    msg = "I am host. uid=" + std::string(uid);
    data = std::vector<uint8_t>(msg.begin(), msg.end());
    manager->SendToClients(data.data(), data.size(), reliability);
}

msg = "I am client. uid=" + std::string(uid);
data = std::vector<uint8_t>(msg.begin(), msg.end());
manager->SendToAuthority(data.data(), data.size(), reliability);
...
```

### 備考

本サンプルではサンプルとして試しやすくするために 1 つの Diarkis サーバに接続しています。 しかし、実際のアプリではマッチメイキング用とインゲーム用のサーバが別々に用意されることになります。 インゲーム用のサーバが別に用意された環境では接続先のアドレスが異なりますので、マッチメイキング後に GameInstanceID とともに接続先のインゲームサーバのアドレスを共有して接続先も切り替えてください。


---

# 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-client/samples/cpp/matching-and-turn.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.
