パスワードが一致するルームを検出してマッチングをする

どうもnisokaです。
今回もモノビットエンジンの機能をいろいろ使ってみよう！ということで、
引き続きルームのマッチング機能を充実させていきます。([前回のリンク](https://qiita.com/nisoka/items/65ef73a8584220899d5b))

環境は以下の通りです
*win10 64bit, Unity2018.3.3f1, Monobit Unity Networking2.0 v2.6*

##やったこと
ルームにパスワードロック機能を実装して、入室制御をおこなう。
![image4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401086/c312dc84-8672-d93b-0979-0683cd3e9221.png)
1. RoomNameにルーム名、Passwordにパスワードを入力してCreateボタンを押す
2. 作成された部屋が一覧表示されるので入りたい部屋のPasswordを入力してJoinボタンを押す
3. パスワードの一致判定を行い、一致すれば入室できる

##ルームカスタムパラメータを使ってルーム作成
```C#:
// ルームカスタムパラメータ変数
private Hashtable customRoomParam = new Hashtable();

// パスワード入力
customRoomParam["Password"] = GUILayout.TextField(customRoomParam.ContainsKey("Password") ? customRoomParam["Password"].ToString() : "");

// ルーム設定
RoomSettings roomSetings = new RoomSettings()
{
    isVisible = true,
    isOpen = true,
    maxPlayers = maxPlayerCount,
    roomParameters = customRoomParam,
    lobbyParameters = new string[] {}
};
// ルーム作成
MonobitNetwork.CreateRoom(roomName, roomSetings, null);
```
MUNでは`isVisible`(ロビーでの公開/非公開) `isOpen`(入室可能かどうか) `maxPlayers`(入室可能人数)といった基本的なルーム設定のほかに、**ルームカスタムパラメータ**という任意のKeyにValueを指定してルーム条件を作成できます。
`customRoomParam["Password"]`というmapへパスワードを入力してルーム設定に反映します。([参考リンク](http://www.monobitengine.com/doc/mun/contents/FeatureClient/RoomCustomParameter.htm#MonobitEngine.RoomSettings.roomParameters%20%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3))
![image1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401086/12923613-db0b-9737-dd64-636f68beed75.png)


##パスワードを一致判定して入室制御
```C#:
private Hashtable joinRoomParam = new Hashtable();

// 全ルーム一覧表示
foreach (RoomData roomData in MonobitNetwork.GetRoomData())
{
    GUILayout.BeginHorizontal();
    
    // ルーム名ラベル表示
    GUILayout.Label("Room Name: " + roomData.name + "(" + roomData.playerCount + "/" + ((roomData.maxPlayers == 0) ? "-" : roomData.maxPlayers.ToString()) + ")");

	// パスワード入力
    GUILayout.Label("Password ");
    joinRoomParam[roomData.name] = GUILayout.TextField(joinRoomParam.ContainsKey(roomData.name) ? joinRoomParam[roomData.name].ToString() : "");

    if (GUILayout.Button("Join"))
    {
    	// 一致判定
        if(roomData.customParameters["Password"].Equals(joinRoomParam[roomData.name]))
        {
        	// ルームに入室
            MonobitNetwork.JoinRoom(roomData.name);
        }

        joinRoomParam[roomData.name] = "";
    }

    GUILayout.EndHorizontal();
}
```
`MonobitNetwork.GetRoomData()`で存在する全ルームの情報が取得できます。
まずforeachで`RoomData roomData`にひと部屋分の情報を格納します。
つぎに`RoomData.customParameters`からそのルームの設定情報を取得します。
最後にルーム設定に含まれるパスワードと入力したパスワードを一致判定して`MonobitNetwork.JoinRoom()`を呼んで終了です。
![image5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401086/b4fc4982-72cb-972c-8a04-628836794f1e.png)

##最後に
余談ですが、**JoinRandomRoom()という関数にハマりました。**
MUN公式サンプルの「MUNクライアントの主要機能＞マッチメイキング＞ルームフィルタ」には下記のようなコードがありました。

```C#:
// 該当するルームに入室する
if (GUILayout.Button("Join Room", GUILayout.Width(150)))
{
    // ルームカスタムパラメータへの登録
    this.customRoomParam["Password"] = this.joinRoomPassword[roomData.name];
                     
    MonobitNetwork.JoinRandomRoom(this.customRoomParam, 0);
                     
    this.customRoomParam["Password"] = "";
}
```
公式はすべて正しいですが、この解説とコードを読む限りだと、複数個の部屋を作ったことを想定していないようです。
サンプルのままJoinRandomRoom()をしてしまうと**「すべてのルームの中から入力したパスワードと一致する部屋に入室する」**という処理が行われます。つまり、どの部屋に対してパスワードの一致判定をおこなうのか指定が不可能のようでした。
ですので、今回クライアントの入力したパスワードと、ルームに設定されたパスワードを関数外で一致判定する必要がありました。
少しややこしかったです。

##参考リンク
- [Monobit Unity Networking2.0公式リンク](http://www.monobitengine.com/doc/mun/)
- [MUN-ルームカスタムパラメータについて](http://www.monobitengine.com/doc/mun/contents/FeatureClient/RoomCustomParameter.htm#MonobitEngine.RoomSettings.roomParameters%20%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3)
- [MUN-ルームフィルタサンプル](http://www.monobitengine.com/doc/mun/)