WebRPC
WebRPCを使用すれば、Photon serverに柔軟に外部サービスを統合することができます。 たとえば、WebRPCによってPhotonクライアントが外部Webサービスからデータをフェッチするようサーバーにリクエストすることができます。
Webサービスの基礎
Photon Serverは、クライアントとWebサーバー間で プロキシ または リレー の役割を果たします。
WebRPCはWebhookの拡張、またはクライアント主導のWebhookと考えることができます。
開発の際には、以下のヒントを参照してください:
- WebRPCにサービスを実装するには、あらゆる言語、フレームワーク、Webサーバーを使用することができます。
- すべての場合において、送信するデータは最小化し、プレイヤーへの負荷を抑えてください。
設定
Photon Serverでは、以下でWebRPC設定をおこなうことができます:
- マスターサーバー向けには
"deploy\Loadbalancing\Master\bin\Photon.LoadBalancing.dll.config" - ゲームサーバー向けには"deploy\Loadbalancing\GameServer\bin\Photon.LoadBalancing.dll.config"
これにはBaseURL
値が必要で、無効化することができます。設定例は以下のとおりです:
XML
<WebRpcSettings Enabled="true">
<BaseUrl Value="https://example.com/WebRPC" />
</WebRpcSettings>
リクエスト
Photon WebRPCはマスターサーバーまたはゲームサーバーに接続した際に、クライアント側から許可されるPhotonオペレーションです。 Photon WebRPCにはURIパス文字列(別名:WebRPCメソッド名)が必要です。また、オプションでWebサービスに送信されるデータを含む2番目の引数が必要となります(別名:WebRPCパラメータ)。 これら2つの引数は LoadBalancingClient.OpWebRpc
メソッドに渡すことが可能です。
UriPath
はWebRPCの相対パスで、リモートプロシージャ名と合致する必要があります。
URL自体でパラメータを送信することも可能です。 この場合、クエリ文字列 はプロシージャ名に含め、相対パスに加える必要があります。
リクエストがPhoton Serverに受信されると、プロシージャ名はBaseURLに連結されて、同一のURLのWebサービスに送信される前にWebRPCのURLの絶対パスが生成されます。
使用されるHTPPリクエストメソッドがPOSTであるため、クライアントによって送信されるパラメータがある場合、PhotonはこれらのパラメータをデフォルトのプロパティとともにJSON POSTデータとして渡します:
AppVersion
: ゲームクライアントで設定される、アプリケーションのバージョン。UserId
: WebRPCを作成するアクターのID。
その他のプロパティは、クライアントから送信されるパラメータの一部です。
クライアントで使用されるWebRpcParameters
型がDictionary<string, object>
の場合、すべてのキー/値のセットはポストデータのルートオブジェクトに送信されます。
もし、その他のJSON有効型の場合には、その型は新たなプロパティRpcParams
の値として含まれます。
例 1
BaseURLはhttps://my.service.org
で、クライアントはWebRPC("method?id=1", parameters)
を呼びます。
パラメータは、{{"key1": 1}, {"key2": "yx"}, {"key3": true}}
をコンテンツとして持つDictionary<string, object>
です。
この場合、Photonはhttps://my.service.org/method?id=1
を呼び、さらにJSONをPOSTします:
JSON
{
"AppId": "00000000-0000-0000-0000-000000000000",
"AppVersion": "client-x.y.z",
"Region": "EU",
"UserId": "userXYZ",
"key1": 1,
"key2": "yx",
"key3": true
}
例 2
BaseURLはhttps://my.service.org
で、クライアントはWebRPC("method?id=1", parameters)
を呼びます。
パラメータはオブジェクトの配列です:object[] { 0, "xy", false }
。
この場合、Photonはhttps://my.service.org/method?id=1
を呼び、さらにJSONをPOSTします:
JSON
{
"AppId": "00000000-0000-0000-0000-000000000000",
"AppVersion": "client-x.y.z",
"Region": "EU",
"UserId": "userXYZ",
"RpcParams": [0, "xy", false]
}
例 3
BaseURLはhttps://my.service.org
で、クライアントはWebRPC("method?id=1", parameters)
を呼びます。
パラメータは初歩的で単純な型です。文字列は「test」としましょう。
この場合、Photonはhttps://my.service.org/method?id=1
を呼び、さらにJSONをPOSTします:
JSON
{
"AppId": "00000000-0000-0000-0000-000000000000",
"AppVersion": "client-x.y.z",
"Region": "EU",
"UserId": "userXYZ",
"RpcParams": "test"
}
安全なデータを送信
WebRPCには利用可能な場合に、暗号化されたオブジェクトAuthCookieをWebサービスに安全に送信するオプションがあります。
これは、クライアントコードからWebRPCオペレーションメソッドを呼び出す際、適切なWebフラグ (SendAuthCookie = 0x02)を設定することで実行できます。
AuthCookie
は、カスタム認証プロバイダに対する認証が成功した後に取得できます。
詳細は、
カスタム認証のドキュメントページ
を参照してください。
レスポンス
WebRPCのためのWebサービスは、Photonがクライアントに結果を返送できるようにJSONオブジェクトでレスポンスする必要があります。
予期されるレスポンスにはResultCode
、Data
、または任意でMessage
.を含める必要があります。
ResultCode
はOKの場合は0、エラーの場合はその他のコードにしてください。 クライアントがエラーを処理できるよう、設定してください。
また、読み取り可能な文字列メッセージを追加することがベストプラクティスです。
Data
は空にすることが可能ですが、何かを送信する場合は有効なJSONオブジェクトでなければなりません。
例 1<!--
JSON
{
"ResultCode": "0"
}
例 2<!--
JSON
{
"ResultCode": "1",
"Message": "Self-explanatory error message"
}
例 3<!--
JSON
{
"ResultCode": "1",
"Data": {
"Key1": "V",
"Key2": 1,
"Key3": true
}
}
WebRPCを選択する理由
HTTPリクエストの送信は、Photonなしでも実行できます。
HTTPクライアントは自分で記述することができ、またはSDKやライブラリから利用することも可能です。
ただし、Photon WebRPCの機能はそれだけにとどまりません。
以下が、Photon WebRPCを利用する利点です:
すべてのロジックを単独の接続されたクライアント内に保持して、単独の「ライフサイクル」と「ステートマシン」を処理することを推奨します。Photonクライアントならば、これらをすべて実現できます。
WebRPCオペレーションは、2つの方法でJSON直列化を考慮します。
AuthCookie
を使用してWebRPCに送信するか、またはさらに機密性の高いデータをサーバー間で送受信して、クライアントの正当性を確認できます。この機能の詳細についてはこちらを参照してください。
トラブルシューティング
以下に、WebRPCコールを作成した際に発生する可能性があるエラーコードと、その対処法を記載します。
OperationInvalid
(-2)
通常、このエラーはアプリケーションにサーバー側でWebRPCが設定されていないか、または有効化されていないことを示しています。
HttpLimitReached
(32745)
このエラーは、1秒間に作成するWebRPCリクエストが多すぎることを示しています。
エラーメッセージを確認し、上限数を確認してください。
ExternalHttpCallFailed
(32744)
このエラーは、設定された外部ウェブサービスと通信する際に問題が発生していることを示しています。
エラーメッセージで詳細を確認し、対処してください。
GetGameList
私達のGitHubページで提供されているサンプルの1つを使用する場合は、リモート・プロシージャ名のスペルに注意してください。
または、任意の名前、あるいは任意のWebRPC実装を自由に選択できます。
GetGameList
は、PhotonのWebRPC機能を実証するための「メモリデモ」で紹介した通り、特殊なWebRPCです。
ほとんどすべてのゲームは、以前に保存したゲームの一覧を取得する必要があるため、とても重要です。
その基本的な方法は、ウェブサービスにリクエストを送信し、発信ユーザが再参加し、プレイを継続するためのゲームリストを取得することです。
これは、アプリケーションが適切にダッシュボードから構成されることを前提としています。
BaseUrl
はWebサービスを指し、ゲームデータを維持するためにはisPersistent
をtrue
に設定し、
PathClose Webhookを有効化する必要があります。
ウェブサービスに返されるべきゲームデータはPhotonの直列化されたルーム状態に依存しているので、後者は重要です。
一方、ウェブサービスは保存されたゲームデータへのアクセス権を持つべきであり、WebRPCのパスに送信されたプロセスHTTP POSTリクエストを受信および処理する準備ができている必要があります (ここではGetGameList
)。
PhotonはすべてのWebRPCリクエストデータにUserID
を送信しているので、カスタムパラメータを追加する必要はありません。リクエストは、追加の引数なしで送信されます。
ウェブサービスは、JSONオブジェクトとしてData
に保存されたゲームのリストを返すべきです。保存された各ゲームのGameIdはキーを持ちます。それぞれの値は、2つのプロパティで構成されるJSONオブジェクトです。
ActorNr
:WebRPCを呼び出すアクターが最初にそのルームに参加したときに割り当てられものと全く同じActorNr。これは、以前、意図的に個別で保存された場合、簡単に読み込むことができます。また、ActorListにループしてUserIdを比較することにより、それぞれのルームの保存されたState
オブジェクトから取得できます。Properties
:それぞれのルームの保存されたState
に含まれるCustomPropertiesプロパティから取得可能なロビーに表示されるCustomRoomProperties
のキー:値ペア。
JavaScript
{
"ResultCode":0,
"Message":"",
"Data":{
"RoomA":{
"ActorNr":3,
"Properties":{
"Map":"USA",
"Mode":"FFA",
"Respawn":true
}
},
"RoomB":{
"ActorNr":5,
"Properties":{
"Map":"Germany",
"Mode":"TDM",
"TeamA":1,
"TeamB":5
}
},
"RoomC":{
"ActorNr":1,
"Properties":{
"Map":"Russia",
"Mode":"CTF",
"TeamA":1,
"TeamB":5,
"Flag":20
}
}
}
}
WebRPCの呼び出しはマスターとゲームサーバーの両方に許可されますが、ルームに参加していない場合はGetGameList
を呼び出す方がより理にかなっています。例:Masterサーバから。
ウェブサービスへのデータの受け渡し
WebRPCは、クライアントからウェブサービスににデータを渡す3つの異なる方法を提供します。3つの異なるタイプを別々に使用するか、組み合わせることができます。
例えば、GetGameList
を拡張し、特定の相手に基づいて保存したゲームのフィルタリングされたリストを取得する場合、3つの異なる方法で行うことができます:
RESTfulの方法:
相対 URI:
/GetGameList/{opponentId}
POSTデータ:
相対 URI:
/GetGameList
Request data:
Plain Old Text
{ "AppId": "00000000-0000-0000-0000-000000000000", "AppVersion": "client-x.y.z", "Region": "EU", "UserId": "userXYZ", "OpponentId": "opponentId" }
Query string (a.k.a. GET parameters):
相対 URI:
/GetGameList?opponentId={opponentId}
もちろん、ウェブサービスは、選択された方法に従って更新する必要があります。
データ型の変換
ここでは、Photon ServerとWebサービス間で通信するデータ型のみを説明します。
クライアントとPhoton Server間で通信するデータ型の詳細は、Photonのシリアライゼーションをご覧ください。
Photon Server -> Webサービス
C# / .NET (Photon supported types) | JavaScript / JSON |
---|---|
byte
|
number |
short
|
|
int
|
|
long
|
|
double | |
bool
|
bool |
string
|
string |
byte[] (byte array length < short.MaxValue )
|
string (Base64 encoded) |
T[] (array of supported type T, length < short.MaxValue )
|
array |
Hashtable (of supported types, count < short.MaxValue , preferably Photon implementation)
|
object
|
Dictionary (keys and values of supported types, count < short.MaxValue )
|
object
|
null
|
null
|
リクエストデータ(型を連結済み)のサンプル
Photon Serverからの送信
JSON
{
"(Dictionary<String,Object>)Dictionary":{
"(Int32)dk_int":"1",
"(String)dk_str":"dv2",
"(Boolean)dk_bool":"True"
},
"(Hashtable)Hashtable":{
"(Byte)hk_byte":"255",
"(Object[])hk_array":[
"(Int32)0",
"(String)xy",
"(Boolean)False"
],
"hk_null":"null"
},
"null":"null",
"(String[])string[]":[
"PUN",
"TB",
"RT",
"Bolt",
"Chat"
],
"(Byte[])byte[]":[
"255",
"0"
],
"(Int16[])short[]":[
"-32768",
"32767"
],
"(Int32[])int[]":[
"-2147483648",
"2147483647"
],
"(Int64[])long[]":[
"-9223372036854775808",
"9223372036854775807"
],
"(Single[])float[]":[
"-3.402823E+38",
"3.402823E+38"
],
"(Double[])double[]":[
"-1.79769313486232E+308",
"1.79769313486232E+308"
],
"(Boolean[])bool[]":[
"True",
"False"
]
}
Webサービスでの読み込み
JSON
{
"(object)Dictionary":{
"dk_int":"(number)1",
"dk_str":"(string)dv2",
"dk_bool":"(boolean)true"
},
"(object)Hashtable":{
"(number)hk_byte":"255",
"(array)hk_array":[
"(number)0",
"(string)xy",
"(boolean)false"
],
"hk_null":null
},
"null":null,
"(array)string[]":[
"(string)PUN",
"(string)TB",
"(string)RT",
"(string)Bolt",
"(string)Chat"
],
"byte[]":"(string)/wA=",
"(array)short[]":[
"(number)-32768",
"(number)32767"
],
"(array)int[]":[
"(number)-2147483648",
"(number)2147483647"
],
"(array)long[]":[
"(number)-9223372036854776000",
"(number)9223372036854776000"
],
"(array)float[]":[
"(number)-3.40282347e+38",
"(number)3.40282347e+38"
],
"(array)double[]":[
"(number)-1.7976931348623157e+308",
"(number)1.7976931348623157e+308"
],
"(array)bool[]":[
"(boolean)true",
"(boolean)false"
]
}
Webサービス -> Photon Server
JavaScript/JSONの型と、C#/.Netの型との対応表は、以下の通りです。
JavaScript / JSON | C# / .Net |
---|---|
object |
Dictionary
|
array |
object[] (array of objects)
|
number (integral) |
long
|
number (floating) |
double
|
string |
string
|
boolean |
bool
|
null (not a type)
|
null
|
undefined (when sent)
|
null
|
レスポンスデータ(型を連結済み)のサンプル
Webサービスからの送信
JSON
{
"(object)number": {
"(number)MAX_VALUE": "1.7976931348623157e+308",
"(number)MIN_VALUE": "5e-324"
},
"(object)object": {
"(string)string": "xyz",
"null": null,
"(boolean)bool": "false",
"(undefined)undefined": "undefined",
"(number)float": "-3.14",
"(number)integer": "123456"
},
"(array)array": [
"(string)xyz",
"(number)0",
"(boolean)true",
null,
"(undefined)undefined"
]
}
Photon Serverでの読み込み
JSON
{
"(Dictionary<String,Object>)number":{
"(Double)MAX_VALUE":"1.79769313486232E+308",
"(Double)MIN_VALUE":"4.94065645841247E-324"
},
"(Dictionary<String,Object>)object":{
"(String)string":"xyz",
"null":"null",
"(Boolean)bool":"False",
"(Double)float":"-3.14",
"(Int64)integer":"123456"
},
"(Object[])array":[
"(String)xyz",
"(Int64)0",
"(Boolean)True",
"null",
"null"
]
}
Back to top