mrs_ws は、 MRSのWebSocket版クライアント mrs.js と、
MRS RoomのWebSocket版クライアント room.js 、
それらを使用するサンプルコード、
テスト用のスクリプトなどを含んでいます。
MRSは Monobit Realtime Server の略で、TCPとUDPに対応した通信ライブラリです。
詳細は、MRSのパッケージに含まれるドキュメントを参照してください。
上記2つで検証していますが、Node.jsをインストールできるLinuxで、
またMRSライブラリが動作する環境であれば問題なく動作するはずです。
任意の場所に任意の名前のディレクトリを作成してください。
仮にwork という名前を付けます。
workの直下に、以下のように必要なものが配置されているようにしてください。
MRSライブラリ: work/mrs
MRS Room: work/mrs_room
mrs_ws: work/mrs_ws
MRSライブラリは、ライブラリのサンプルプログラムが格納されている
ディレクトリにアクセスできることが必要です。具体的には次のとおりです。
work/mrs/sample/cpp/mac (MacOSの場合)
work/mrs/sample/cpp/linux (Linuxの場合)
MRS Roomについては、配布パッケージに含まれているサンプルプログラムが必要です。具体的には次の通りです。
work/mrs_room/sample/cpp/mac (MacOSの場合)
work/mrs_room/sample/cpp/linux (Linuxの場合)
これらのサンプルプログラムを用いて動作確認ができます。
2つのパターンでアプリケーションを作ることができます。
まず一つ目の単純なパターンは、mrs.jsのみを使って、
MRSのバイナリレコードを送信してMRSのサーバーと通信して、
アプリケーションを作成する方法です。
このパターンを「MRSアプリケーション」と呼びます。
このパターンのサンプルアプリケーションが cli.html です。
MRSの詳細については、MRSの配布パッケージに含まれる MRS_API_Overview.mdを参照してください。
もうひとつのパターンは、mrs.jsとroom.jsの両方を使って、
MRS Roomのサーバと通信する方法です。
このパターンは「MRS Roomアプリケーション」と呼びます。
ルームサーバーは、サーバー側にゲーム処理を持たないタイプの
マルチプレイゲームを簡単に作るための、ゲームデータの同期用サーバーです。
このパターンのサンプルアプリケーションが、 cli_room.htmlです。
MRS Roomについての詳しい説明は、 MRS Roomの配布パッケージに含まれる ROOM_API_Overview.mdを参照してください。
MRSアプリケーションの動作するサンプルは cli.html にあります。
ここでは、cli.htmlがどのように実装されているかを解説します。
まず、HTMLで mrs.jsを読み込みます。
HTMLに次のようなタグを追加してください。
<script type="text/javascript" src="mrs.js"> </script>
次に、 createMRSClient
関数を使ってMRSのクライアントを作成します。
この関数は内部でWebSocketを作成し、バイナリモードの通信を設定します。
var cli = createMRSClient("ws://localhost:8888/");
localhost以外でサーバを動作させたい場合は、このURLを直接変更してください。
次にデータを受信したときにアプリケーションが処理を行うために、
コールバック関数を設定します。
cli.onReadRecord = function(payload_type,u8ary,msg) {
switch(payload_type) {
case 0x01: // アプリケーションが自由に定義する
....
}
};
payload_typeはMRSのレコードにおけるpayload_typeと同じ意味で、
アプリケーションが処理を分岐するために自由に定義できる値です。
u8aryは Uint8Arrayで渡される生データ、
msgは u8aryをUTF-8の文字列と解釈してstringに変換した値です。
次の例では、文字列をデータとして含むレコードを1個送信しています。
payload_typeは0x01で、文字列の内容が "hello" です。
cli.writeStringRecord( 0x01, "hello" );
次の例では、バイナリデータをUint8Arrayを用いて渡してレコードを1個送信しています。 payload_typeは0x01で、送るデータの内容は 4バイトで、
中身は 0x01,0x02,0x03,0x04 です。
cli.writeRecord( 0x01, new Uint8Array([1,2,3,4]));
HTMLのボタンを押したときになにか送信したい場合は、
以下のようにsend関数を呼ぶように定義し、
<button onclick="send();">send</button>
send関数では次のようにします。
function send() {
cli.writeStringRecord( 0x01, "hello" );
}
これを試すには、MRSパッケージに含まれるエコーサーバーのプログラムが使えます。
MacOSならば、 mrs/sample/cpp/mac/10.11/echo_server
を、
Amazon LinuxやCentOSならば、 mrs/sample/cpp/linux/centos6_4.4.7/echo_serever
が実行バイナリです。MacOS 10.12や、CentOS7などについてもビルド済みのバイナリが含まれています。
echo_serverをコマンドラインから起動すると次のようになります。
bash$ ./echo_server
sleep_msec=1 server_addr=0.0.0.0 server_port=22222 backlog=10
TCP listening on 0.0.0.0 22222
UDP waiting on 0.0.0.0 22222
WS listening on 0.0.0.0 22223
WSS listening on 0.0.0.0 22224
上からそれぞれ、TCP、UDP、WebSocket、セキュアなWebSocketです。
ポート番号が利用できないなどのエラーの場合は次のように表示されエラー終了します。
TCP mrs_server_create: MRS_EADDRINUSE: Address already in use
cli.htmlをダブルクリックしてブラウザで開くと、次の図のような画面になります。
その際はデバッガコンソールを開くと便利でしょう。
画面の上から、テキスト入力の "Payload_type"で数値を指定すると、送信するレコードのpayload_typeを設定できます。1を指定するとエコーサーバーはエコーしてきますが、1以外だとエコーしません。
"Message"は任意の文字列を指定します。
Repeatは繰り返しの回数を指定します。100を設定すると、同じレコードを100回送信します。
sendボタンをクリックするとレコード送信を実行します。
エコーサーバーが反応を返してきたら、Response:のDOM要素のところに、
次のようなログが表示されます。
payload_type:1 Data:hello_11:0 RTT:4ms
RTTをみると、送信してから受信までに4msの時間がかかったことがわかります。
MRS Roomアプリケーションの実装も、MRSアプリケーションと基本的には同じで、
クライアントを作成し、コールバック関数を定義し、
送信関数を呼び出すだけです。ただし、
コールバックが2種類になり、送信関数も種類が増えています。
動作するサンプルは cli_room.html です。
ルームやプレイヤーの概念については、MRS Roomのドキュメントを参照してください。
まず、HTMLで mrs.jsとroom.jsを読み込みます。
HTMLに次のようなタグを追加してください。
<script type="text/javascript" src="mrs.js"> </script>
<script type="text/javascript" src="room.js"> </script>
次に、 createMRSClient
関数とcreateMRSRoom関数を使って
MRS Roomのクライアントを作成します。
var cli = createMRSClient("ws://localhost:8888/");
var room = createMRSRoomClient(cli);
以降はここで作成したroomを使ってすべての操作を行います。
データを受信したときにアプリケーションが処理を行うためには、
roomにコールバック関数を設定します。
room.onReadRecord = function(room_id,owner_player_id,member_ids,sender_player_id, payload_type, payload ) {
// ルームに送信されたレコードを受信した。
}
コールバックの引数に渡される値は次の通りです。
room_id は参加しているルームのID
owner_player_id はルームの所有者のプレイヤーID
member_ids はルームに参加しているプレイヤーIDの配列
sender_player_id は送信したプレイヤーのID
payload_type はアプリケーションが自由に設定するペイロードタイプ
payload は Uint8Arrayの配列で、アプリケーションが送信した生のデータです。
Roomサーバーとの通信においては、 onReadRecordコールバックで受信できる
ゲームデータの同期用のレコードだけではなく、
ルームの参加者が増減したりなどのルームの状態自体に関するイベントもコールバック関数で受信することができます。
そのためには次のように onRoomEvent コールバック関数を登録します。
room.onRoomEvent = function(evt,room_id,player_id,result,members) {
};
コールバック関数の引数は以下の値が渡されます。
evt はイベントの種別で、次のものが定義されています。詳細については、MRS Roomのリファレンスを参照してください。
var MRS_ROOM_EVENT_NONE = 0;
var MRS_ROOM_EVENT_CREATE_ROOM = 1;
var MRS_ROOM_EVENT_CREATE_ROOM_ERROR = 2;
var MRS_ROOM_EVENT_JOIN_ROOM = 3;
var MRS_ROOM_EVENT_JOIN_ROOM_ERROR = 4;
var MRS_ROOM_EVENT_JOIN_ROOM_OTHER_PLAYER = 5;
var MRS_ROOM_EVENT_LEAVE_ROOM = 6;
var MRS_ROOM_EVENT_LEAVE_ROOM_OTHER_PLAYER = 7;
var MRS_ROOM_EVENT_SET_OWNER_PLAYER = 8;
room_idはルームのID
player_idは事象を引き起こしたプレイヤーのID
resultは次の値のいずれかです。
var MRS_ROOM_RESULT_SUCCESS = 0;
var MRS_ROOM_RESULT_FAILURE = -1;
var MRS_ROOM_RESULT_CANNOT_CREATE_ROOM = -100;
var MRS_ROOM_RESULT_ROOM_NOT_FOUND = -101;
var MRS_ROOM_RESULT_PLAYER_ALREADY_JOINED = -102;
membersはルームに参加しているプレイヤーのIDの配列です。
room.sendCreateRoom(room_id,player_id);
作成時のエラーはonRoomEventで通知されます。
room.sendJoinRoom(room_id,player_id);
参加時のエラーはonRoomEventで通知されます。
room.sendLeaveRoom();
room.sendSetOwner(player_id);
room.broadcastString(payload_type,payload);
room.broadcast(payload_type,payload);
broadcastStringは文字列を、broadcastはUint8Arrayを送信します。
room.othercastString(payload_type,payload);
othercastStringは文字列を、othercastはUint8Arrayを送信します。
room.unicastString(payload_type,payload,player_id);
unicastStringは文字列を、unicastはUint8Arrayを送信します。
room.multicastString(payload_type,payload,[player_id]);
最後の引数はプレイヤーIDの配列を指定します。
multicastStringは文字列を、multicastはUint8Arrayを送信します。
room.ownercastString(payload_type,payload);
ownercastStringは文字列を、ownercastはUint8Arrayを送信します。
Roomクライアントの動作確認をするためには、
MRS Roomパッケージに含まれるルームサーバーのサンプルコードが使えます。
Roomサーバーをコマンドラインから起動すると次のようになります。
以下、MacOSでの例ですが、Linuxでもバイナリが用意されています。
bash$ cd mrs_room/sample/cpp/mac/10.11
bash$ ./room_server
sleep_msec=1 server_addr=0.0.0.0 server_port=33333 backlog=10
TCP listening on 0.0.0.0 33333
UDP ready on 0.0.0.0 33333
WebSocket ready on 0.0.0.0 33334
エコーサーバーと異なり、TCP33333番がデフォルトとなっています。
UDPとWebSocketのサーバも同時に起動します。
ブラウザでcli_room.htmlを開きます。
画面の上から、テキスト入力の "Player_id"で数値を指定すると、
これから呼び出すコマンドのplayer_id引数の値として渡されます。
WritePlayerIdを指定すると、broadcastなどのcast系の関数の送信プレイヤーを示すプレイヤーのIDを渡します。
RoomIdに数値を入力すると、room_idの値となり、
PayloadTypeに数値を入れると、 payload_typeとなり、
Payload:に文字列を入れると、ペイロードのデータとしてこの値が使われます。
送信ボタンはいくつもあり、
CreateRoom, JoinRoom, SetOwner, Broadcast, Othercast, Unicast, Multicast, Ownercast をそれぞれ試すことができます。
ページ末尾のResponse: には、受信したイベントとレコードの内容が表示されます。