オブジェクトの遠隔操作
この場では、XML-RPCの実用例として、オブジェクトを遠隔操作するサンプルを作成してみたいと思います。通常、オブジェクトの編集にはセカンドライフを起動して、オブジェクトの配置されている場所までアバターを移動させる必要があります。しかし、XML-RPCを通じてスクリプトにオブジェクトの状態を変更するように命令できれば、セカンドライフを起動することなく、アプリケーションからオブジェクトを操作できます。
本稿の例では、XML-RPCで交換できる整数型と文字列型の2つのパラメータを用い、整数型から操作の種類を判定し、文字列型で設定内容を表す値を渡すという方法を用いています。例えば、idataが100であればオブジェクト名を変更するという意味であると解釈し、sdataには新しい名前が格納されている、という仕組みです。
integer CODE_ECHO = 0; //test message integer CODE_ERROR = -1; integer CODE_SUCCESSFUL = 1; integer CODE_RESULT = 10; //this message has result value integer CODE_SETNAME = 100; //change object name integer CODE_GETNAME = 150; //return object name integer CODE_SETDESC = 200; //change object description integer CODE_GETDESC = 250; //return object description integer CODE_SETTEXT = 300; //change object text integer CODE_GETTEXT = 350; //return object text key remoteKey = NULL_KEY; string objectText; default { state_entry() { llSetText("", <0, 0, 0>, 0); llOpenRemoteDataChannel(); } remote_data(integer event_type, key channel, key message_id, string sender, integer idata, string sdata) { if (event_type == REMOTE_DATA_CHANNEL) { remoteKey = channel; llOwnerSay("XML-RPC Channel:" + (string)channel); } else if (event_type == REMOTE_DATA_REQUEST) { llOwnerSay("Request received. int=" + (string)idata + ", str=" + sdata); if (idata == CODE_ECHO) { llRemoteDataReply(channel, message_id, llGetTimestamp(), CODE_SUCCESSFUL); } else if (idata == CODE_SETNAME) { llSetObjectName(sdata); llRemoteDataReply(channel, message_id, sdata, CODE_SUCCESSFUL); } else if (idata == CODE_GETNAME) { string name = llGetObjectName(); llRemoteDataReply(channel, message_id, name, CODE_RESULT); } else if (idata == CODE_SETDESC) { llSetObjectDesc(sdata); llRemoteDataReply(channel, message_id, sdata, CODE_SUCCESSFUL); } else if (idata == CODE_GETDESC) { string desc = llGetObjectDesc(); llRemoteDataReply(channel, message_id, desc, CODE_RESULT); } else if (idata == CODE_SETTEXT) { objectText = sdata; llSetText(sdata, <1,1,1>, 1.0); llRemoteDataReply(channel, message_id, sdata, CODE_SUCCESSFUL); } else if (idata == CODE_GETTEXT) { llRemoteDataReply(channel, message_id, objectText, CODE_RESULT); } else llRemoteDataReply(channel, message_id, "", CODE_ERROR); } } }
上記のコードをオブジェクトに設定し、開かれたチャネルを記録してクライアントから接続してください。この例では、オブジェクト名、オブジェクトの説明、オブジェクトのテキストの3つのプロパティを操作する機能を提供しています。
操作の種類を表す整数は、CODE_という名前で始まる整数型のグローバル変数でまとめています。スクリプトはSET系の操作が要求された場合は、オブジェクトの設定を渡された値で変更し、成功したことを表す結果をクライアントに返します。一方、GET系の操作が要求された場合は、オブジェクトの現在の値をクライアントに返します。
今回は、このスクリプトを設定しているオブジェクトを操作するプログラムをJavaで実装しました。もちろん、XML-RPCは抽象化されているサービスなので、接続するクライアントは制限されません。C/C++で開発されたアプリケーションでも、.NETアプリケーションからもアクセス可能です。もちろん、Webサービスからアクセスしてマッシュアップするといった可能性も考えられます。
「チャネルID」に接続先のチャネル番号を設定します。この値が設定されていなければ、接続することはできません。「名前」にはオブジェクト名、「説明」にはオブジェクトの説明、「テキスト」にはオブジェクトのテキストを表しています。
「設定」ボタンを押すと、テキストボックスに入力されている値でオブジェクトを更新します。「取得」ボタンを押すと、オブジェクトの現在の値を取得してテキストボックスに表示します。
例えば「テキスト」テキストボックスに何らかの文字列を入力して「設定」ボタンを押すとIntValueメンバにCODE_SETTEXT変数に対応する整数値300、StringValueメンバにテキストボックスに入力された文字列が指定されたXMLを送信します。

上の図はJavaアプリケーションからXML-RPCによる通信でオブジェクトのテキストを設定した状態です。セカンドライフのソフトを操作することなく、外部のアプリケーションからオブジェクトを操作することができました。このアプリケーションを拡張すれば、オブジェクトの色や座標などの設定を自由に遠隔操作することも可能です。
ただし、権限に関係なく外部からオブジェクトを編集させてしまうようなスクリプトを公開するのは危険です。実際の運用には、パスワードなどのセキュリティを考慮しなければなりません。
このようなオブジェクトの遠隔操作は、セカンドライフの経験がない利用者でも、セカンドライフ内の情報を更新する手助けになるでしょう。自分の土地に置いてあるオブジェクトを定型のフォームで編集することができれば、更新作業が容易になります。
最後に
セカンドライフの実行には、コンピュータにある程度のスペックが要求されるため、ゲーム専用機を持たないユーザーとっては大きな障壁になっています。セカンドライフとWebの接続は、こうしたスペック上の問題からセカンドライフを満足に実行できないユーザーを、セカンドライフの世界に間接的に参加させることができます。
また、セカンドライフへのアクセスを向上させるという意味でも、アプリケーションやWebサービスを通じて情報交換ができるというのは重要な意味を持ちます。セカンドライフを起動できる環境がなくても、あらゆる場所からセカンドライフ内の情報にアクセスできる仕組みを作ることで、外出中のモバイルからでもデータを得ることができます。
実用的かどうかという議論は別にして、Webサービスとマッシュアップするという道もあります。例えば、セカンドライフとWebで双方向の掲示板やチャットを実現するツールを作成することも可能です。セカンドライフからアップロードされた情報を用いれば、Webでオブジェクトの位置や状態を視覚化するといったサービスも考えられるでしょう。
HTTPリクエストやXML-RPCによってLSLの限界を突破し、Webの膨大な情報量と、セカンドライフの3次元空間のメリットを組み合わせることで、新しいコミュニケーションを発見できるかもしれません。

