Webhooks

使用Photon Cloud的webhooks來擴展您的應用程序,允許玩家重新加入遊戲,並持久保存玩家和遊戲數據。

Photon webhooks是事件驅動的HTTP POST請求,由Photon Cloud發送至特定的URL。
每個Photon webhook都由自己的觸發器、數據和目標路徑定義。

Read what's new in webhooks 1.2 here.

設置

要設置Photon Cloud的Webhooks,請從您的介面上的應用列表中點擊Manage鏈接。
Webhooks部分添加新的或改變現有的。

從webhooks配置頁面,您可以使用下拉列表選擇一個預定義的預設。
演示 "預設應該只在開發中使用。
它的目的是讓您快速預覽不同的可用設置以及如何使用它們。

配置是通過定義字符串的鍵/值對完成的。
每個設置值允許的最大長度是1024個字符。

基本設置

  • BaseUrl (required)
    托管您的掛鉤的服務的URL,以及任何應該通過WebRPC調用的方法。
    它不能以正斜線。
    回調是在下面設置的相對路徑URI上接收的。
    如果您想配置的值將包含一個查詢字符串,請閱讀點此
  • CustomHttpHeaders
    由鍵/值對組成的JSON字符串(string:string),這些鍵/值對應該被設置為向所配置的Web服務發出的任何請求中的HTTP標頭信息。
    閱讀更多點此

路徑

配置每個路徑,以便在您的主機上的每個識別的URI上接收事件。
任何留空的路徑都不會點擊,您將不會在受影響的webhook上收到任何回調。

  • PathCreate
    當一個新的房間被創建或其狀態需要從外部服務加載時被調用。
  • PathClose
    當一個房間從Photon伺服器的內存中刪除時被調用。
    如果_IsPersistent_被設置為 true,房間的狀態將被發送。
  • PathJoin
    當玩家加入一個房間時,當它在Photon伺服器內存中時,會被調用。
  • PathLeave
    當玩家離開房間時被調用。
  • PathEvent
    當客戶端在房間裡提出一個設置了網絡標志HttpForward的事件時被調用。
  • PathGameProperties
    當客戶端設置了一個房間或玩家的屬性並設置了網絡標志HttpForward時被調用。

選項

用這些選項對您的webhooks配置的行為進行微調。
當沒有設置或其值為空時,一個選項被認為沒有配置。
每個選項的默認值是false,適用於每個未設置的選項。

  • HasErrorInfo
    如果設置為true,當對鉤子的調用失敗時,客戶端將被通知一個 ErrorEvent
  • IsPersistent
    如果設置為true,Photon Cloud會在從內存中刪除房間之前發送狀態。
    這個選項只有在_PathCreate_和_PathClose_都被正確配置後才有效。
    更多信息請閱讀GameCreateGameClosewebhooks的詳細信息。
  • AsyncJoin
    這個選項只有在_IsPersistent_被設置為true時才有效。
    默認情況下,該設置為 true,在伺服器上找不到房間名稱的加入操作將作為webhook轉發到網絡服務。
    要禁用這一行為,請將其設置為 false
    閱讀更多點此

Query String Handling

Query string parameters can be included in the BaseUrl.
If you do use them you should know the following:

  • Query string will be used as is. No URL encoding will be done. No duplicate keys check will be done.
  • You can use URL tags in query string parameters.
  • Do not add query string to Path settings.

Example:

  • Configuration:

    • BaseUrl:
      https://myawesomegame.com/chat/webhooks?clientver={AppVersion}&key=&keyA=valueA&keyA=valueB&keyB=valueB&=value
      
    • PathCreate: create
    • PathClose: close
  • Resulting URLs:

    • PathCreate:
      https://myawesomegame.com/realtime/webhooks/create?clientver=1.0&key=&keyA=valueA&keyA=valueB&keyB=valueB&=value
      
    • PathClose:
      https://myawesomegame.com/realtime/webhooks/close?clientver=1.1&key=&keyA=valueA&keyA=valueB&keyB=valueB&=value
      

HTTP Headers Considerations

There are few things you need to consider when using custom HTTP headers:

  • The value of CustomHttpHeaders configuration key needs to be a stringified JSON object that has properties with string values only.
    The JSON object's properties' names will be used as HTTP request header field names and the properties' values will be used as their respective values.
    Example:

    • CustomHttpHeaders value:
      {'X-Secret': 'YWxhZGRpbjpvcGVuc2VzYW1l', 'X-Origin': 'Photon'}
      
    • Webhooks HTTP request headers:
      X-Secret: YWxhZGRpbjpvcGVuc2VzYW1l
      X-Origin: Photon
      
  • Custom HTTP headers field names are case sensitive.

  • The supported formats for Date and If-Modified-Since can be found here.

  • Content-Type should not be used as as the webhooks plugin will set it to application/json.

  • The following HTTP headers are restricted and will be ignored if set from the "CustomHttpHeaders" configuration value.

    • Connection
    • Content-Length
    • Host
    • Range
    • Proxy-Connection

金鑰解決方案

我們的github頁面上找到最新的適用於Microsoft Azure和Heroku的統包安裝。

URL Tags

You can optionally set one or more "dynamic variables".
Those variables will be replaced with their respective values in our backend before sending out any requests.
Empty space characters will be removed.

URL tags come in handy if you want to handle user segments of your application differently, each.
Photon supports the following URL tags:

  • {AppVersion} will pass the application version as set by the client, e.g. "1.0".
  • {AppId} will pass the ID of your application, e.g. "2afda618-e64f-4a85-b2a2-74e05fdf0b65".
  • {Region} will pass the token for the cloud region the triggering client is connected to, e.g. "EU" or "USW".
  • {Cloud} will pass the name of the cloud the triggering client is connected to, e.g. "public" or "enigmaticenterprise".

Examples of URL Tags use cases

  1. https://{Region}.mydomain.com/{AppId}?version={AppVersion}&cloud={Cloud} to e.g. route each region to different hosts, version and cloud passed as query parameters.
  2. https://mydomain.com/{Cloud}/{Region}/{AppId}/{AppVersion} passes all tags as well structured URI.

通用標准

所有Photon webhooks都有一個基本的POST URL,能夠返回可能發生在網絡伺服器上的最終錯誤,以及每一個都要發送的基准數據。

所有Webhooks的通用參數

AppId
您的應用程序的AppId,由遊戲客戶端設置,在dashboard中找到。
{% endif }

AppVersion
您的應用程序的版本,由遊戲客戶端設置。

{% if PUN, Realtime %}
Region
擁有遊戲客戶端所連接的區域,以及相關房間所屬的區域。

GameId
房間的ID或名稱。

Type
webhook的類型,在PathEventwebhook中總是 "Event",在PathJoinwebhook中是 "Join",在所有其他的webhook中可以有多個值。

除PathClose外,所有Webhooks的通用參數

ActorNr
觸發掛鉤的actor編號。

UserId
觸發掛鉤的actor用戶名。

NickName
觸發掛鉤的actor名稱,由客戶SDK設置。

返回值

預期回應

當發送網絡掛鉤時,Photon Cloud在大多數情況下只期望得到一個JSON對象的回應,其ResultCode屬性設置為0。
0的ResultCode是對webhook請求的接收和web伺服器的成功處理的確認。

任何有ResultCode的返回對象的webhook調用都被認為是失敗的。
如果HasErrorInfo在配置中被設置為true;一個ErrorInfo事件將被廣播給仍然加入房間的客戶端。
除了PathCreate之外,伺服器會繼續正常執行,盡管如此。
該事件還包含ParameterCode.Info更多信息請參見您的SDK的API文檔

唯一讓Photon期望更多的情況是,當玩家試圖重新加入一個已經被Photon關閉的房間Cloud並已經從內存中刪除。
關於這一點的更多細節,請參考PathCreate部分

最佳實踐

始終檢查每個webhook中需要的參數。
如果缺少一個必要的參數,則返回一個錯誤代碼,以及一個可選的,但有用的可讀訊息。
一個webhook的JSON返回對象的建議格式是{ "ResultCode" : x, "Message" : "xxx" }

處理返回值的一個非常好的方法是在您的webhooks的後台邏輯中實現輔助程序。
下面是webhooks返回對象的一個非詳盡的例子。

  • 成功時的默認返回對象

    { "ResultCode" : 0 }
    { "ResultCode" : 0, "Message" : "OK" }

  • 協議層面錯誤,無論是在Photon方面還是在網絡伺服器方面

    { "ResultCode" : 1, "Message" : "Missing Webhook Argument: <argument name>." }

  • 應用程序特定錯誤

    { "ResultCode" : 2, "Message" : "Game with GameId=<gameId> already exists." }
    { "ResultCode" : 3, "Message" : "Could not load the State, Reason=<reason>." }

路徑的細節

PathCreate

If a room is created as a result of a JoinOrCreateRoom call, "PathCreate" webhook will be triggered only if:
  • "IsPersistent" is set to "true".
  • "PathCreate" is configured.
  • "PathClose" is configured.
Otherwise, the room is created and no webhook will be fired.

每次在伺服器上創建一個房間時,都會觸發這個webhook。
如果房間是用OpCreateRoom創建的,webhook將把它的 Type參數設置為 Create
大多數RoomOptions連同創建房間時使用的TypedLobby將作為CreateOptions發送。
ActorNr的值將是1,actor將自動加入房間而不觸發PathJoinwebhooks。

若actor試圖加入或重新加入一個以前創建的房間,但從Photon Cloud中刪除,Type將被設置為Load
網絡伺服器應該返回同一個房間的序列化的State
後台邏輯將需要獲取先前保存的、序列化的房間狀態版本。

如果狀態被找到,網絡伺服器應該返回一個JSON對象作為{ "State" : state, "ResultCode" : 0 }
如果由於某種原因無法找到狀態,網絡服務應該檢查CreateIfNotExists的值,以允許或不允許用新狀態創建房間。
如果CreateIfNotExists為真,您可以返回一個空的房間狀態(例如{ "State" : "", "ResultCode" : 0 })來允許創建一個由客戶提供的房間選項。
由於其值為false,Photon Cloud應被告知網絡伺服器未能通過返回0以外的ResultCode來加載狀態。
考慮添加一個可讀的錯誤信息,並說明原因。

If "IsPersistent" is set to true and both "PathCreate" and "PathClose" are configured, room creation, asynchronous join or rejoin will fail when:
  • "PathCreate" is unreachable or returns HTTP error.
  • "PathCreate" returns ResultCode other than 0.
  • Photon Server fails to parse or set received room state.

AsyncJoin選項

Photon應用程序支持異步操作,比如在遊戲創建數小時後接受邀請加入遊戲,以方便與朋友一起玩。
IsPersistentIsPersistent同時啟用時,任何在Photon伺服器內存中找不到房間的加入操作都會觸發 PathCreateType=”Load”)webhook。
目標是嘗試從您的網絡服務中加載房間狀態,假設它是先前創建和保存的。

IsPersistent true 時,AsyncJoin 被默認啟用。
要禁用AsyncJoin,如果webhooks設置中沒有,請添加其鍵值,並將其值設為false

該表顯示了當IsPersistent被啟用時,所有可能觸發PathCreatewebhook的Type="Load"的客戶端操作(以防在Photon伺服器內存中找不到房間)。

Client Operation JoinMode AsyncJoin = false AsyncJoin = true AsyncJoin = N/A
OpJoinRoom Default (Join)
OpRejoinRoom RejoinOnly
OpJoinOrCreateRoom CreateIfNotExists

Specific Arguments

PathCreate, Type "Create"

CreateOptions
創建房間時使用的選項。
它包含了從客戶端設置的RoomOptions類的信息,以及關於使用的TypedLobby的細節。
它的所有屬性可以在以後從State中獲取,因為它將被原樣復制到那裡。

下表是CreateOptionsRoomOptions之間的比較:

Property or Field CreateOptions RoomOptions Notes
IsVisible Can be retrieved later from room State.
IsOpen Can be retrieved later from room State.
MaxPlayers
PlayerTtl
EmptyRoomTtl
CheckUserOnJoin This should be set to true if you have unique ID per player.
SuppressRoomEvents If set to true, no room events are sent to the clients on join and leave. Default is false and sent.
DeleteCacheOnLeave This is called CleanupCacheOnLeave in RoomOptions.
LobbyType The type of the room's lobby as set by game client in TypedLobby.Type. See the API doc for your SDK for additional info.
LobbyId The name of the room's lobby as set by game client in TypedLobby.Name. See the API doc for your SDK for additional info.
CustomProperties Contains only the initial custom properties of the room that should be public, i.e. visible to the lobby.
CustomRoomProperties Contains all initial custom properties of the room.
CustomRoomPropertiesForLobby Contains the keys of the custom properties of the room that should be public, i.e. visible to the lobby.
PublishUserId Defines if the UserIDs of players get "published" in the room.
Can be retrieved later from room State.
Read more about it here.

PathCreate, Type "Load"

CreateIfNotExists: 一個標志,用於指示如果不能從網絡服務中找到一個新房間的狀態,是否應該創建。

除了在CreateOptions中找到的房間State的屬性。

  • ActorCounter:最後加入的actor的actor編號。
  • ActorList:一個數組,包含了房間內每個actor的信息條目(活躍或不活躍)。
    每個條目都有以下屬性。
    • ActorNr:房間裡actor的編號。
    • UserId:actor的用戶ID。
    • NickName:actor的昵稱。
    • IsActive:表示該actor是否加入了房間。它不在PathCloseState參數中發送。
    • DeactivationTime:房間離開事件的時間戳。只在PathCloseState參數中發送。
    • Binary*:Base64編碼的行為者屬性。
    • DEBUG_BINARY**:actor屬性的可讀形式。
  • Slice:緩存的索引。
  • Binary *:Base64編碼的房間屬性和緩存事件。
  • DebugInfo **:二進制數據的可讀形式。
    • DEBUG_PROPERTIES_18**:房間屬性的可讀形式。
    • DEBUG_EVENTS_19**:緩存事件的可讀形式。
    • DEBUG_GROUPS_20**:興趣小組的可讀形式。
  • ExpectedUsers:預期加入房間的玩家的UserID的數組。閱讀更多關於 Slot Reservation

* :Binary屬性的存在是由於[Photon使用協議]的性質(~/realtime/current/reference/binary-protocol)。
**:對於生產環境中的應用,Debug屬性應該被禁用。請確保只在調試時使用這些屬性。

Sample Call

JSON

{
    "ActorNr": 1,
    "AppVersion": "client-x.y.z",
    "AppId": "00000000-0000-0000-0000-000000000000",
    "CreateOptions": {
        "MaxPlayers": 4,
        "LobbyId": null,
        "LobbyType": 0,
        "CustomProperties": {
            "lobby3Key": "lobby3Val",
            "lobby4Key": "lobby4Val"
        },
        "EmptyRoomTTL": 0,
        "PlayerTTL": 2147483647,
        "CheckUserOnJoin": true,
        "DeleteCacheOnLeave": false,
        "SuppressRoomEvents": false
    },
    "GameId": "MyRoom",
    "Region": "EU",
    "Type": "Create",
    "UserId": "MyUserId1",
    "NickName": "MyPlayer1"
}

PathJoin

如果一個actor加入或重新加入一個沒有從Photon Cloud中移除的房間,這個webhook將被觸發。
Type參數被設置為 Join

特定參數

PathJoin沒有額外的參數。

Sample Call

JSON

{
    "ActorNr": 2,
    "AppVersion": "client-x.y.z",
    "AppId": "00000000-0000-0000-0000-000000000000",
    "GameId": "MyRoom",
    "Region": "EU",
    "Type": "Join",
    "UserId": "MyUserId0",
    "NickName": "MyPlayer0"
}

PathGameProperties

每次用戶從客戶端設置房間或玩家的自定義屬性時,如果使用正確的重載方法並設置了HttpForward網絡標志,就會觸發這個webhook。
與webhook一起發送的Type參數將被相應地設置為GameActor

具體參數

Properties:一組從SDK客戶端發送的更新屬性。
State:一個房間完整狀態的序列化紀錄。
隻有在調用 OpSetCustomProperties 時設置了 SendState webflag並且 IsPersistent 設置為 true 時才會發送。
AuthCookie:客戶端不可見的加密對象,在成功的自定義認証后,網絡服務可選擇返回。
隻有在調用 OpSetCustomProperties 時設置了 SendAuthCookie 網路標志,它才會被發送。

PathGameProperties, Type="Actor"
TargetActor:屬性被更新的角色的編號。

Sample Call

JSON

{
    "ActorNr": 1,
    "AppVersion": "client-x.y.z",
    "AppId": "00000000-0000-0000-0000-000000000000",
    "Properties": {
        "turn": 1,
        "lobby3Key": "test1a",
        "lobby4Key": "test1b"
    },
    "GameId": "MyRoom",
    "Region": "EU",
    "State": {
        "ActorCounter": 2,
        "ActorList": [
            {
                "ActorNr": 1,
                "UserId": "MyUserId1",
                "NickName": "MyPlayer1",
                "IsActive": true,
                "Binary": "RGIAAAEBRAAAAAJzAAlz...",
                "DEBUG_BINARY": {
                    "1": {
                        "255": "MyPlayer1",
                        "player_id": "12345"
                    }
                }
            },
            {
                "ActorNr": 2,
                "UserId": "MyUserId0",
                "NickName": "MyPlayer0",
                "IsActive": true,
                "Binary": "RGIAAEBRAAAAAFi/3M15...",
                "DEBUG_BINARY": {
                    "1": {
                        "255": "MyPlayer0"
                    }
                }
            }
        ],
        "Binary": {
            "18": "RAAAAAdzAAhwcm9wMUtl..."
        },
        "CheckUserOnJoin": true,
        "CustomProperties": {
            "lobby4Key": "test1b",
            "lobby3Key": "test1a"
        },
        "DeleteCacheOnLeave": false,
        "EmptyRoomTTL": 0,
        "IsOpen": true,
        "IsVisible": true,
        "LobbyType": 0,
        "LobbyProperties": [
            "lobby3Key",
            "lobby4Key"
        ],
        "MaxPlayers": 4,
        "PlayerTTL": 2147483647,
        "SuppressRoomEvents": false,
        "Slice": 0,
        "DebugInfo": {
            "DEBUG_PROPERTIES_18": {
                "250": [
                    "lobby3Key",
                    "lobby4Key"
                ],
                "prop1Key": "prop1Val",
                "prop2Key": "prop2Val",
                "lobby4Key": "test1b",
                "lobby3Key": "test1a",
                "map_name": "mymap",
                "turn": 1
            }
        }
    },
    "Type": "Game",
    "UserId": "MyUserId1",
    "NickName": "MyPlayer1"
}

PathEvent

如果使用正確的重載方法並設置HttpForward網絡標志,每次用戶從客戶端引發自定義事件時都會觸發。
自定義事件代碼和事件數據將與webhook一起發送。

具體參數

EvCode:自定義事件代碼。
Data:客戶端SDK發送的自定義事件數據。
State:房間完整狀態的序列化快照。
隻有在調用 OpRaiseEvent 時設置了 SendState webflag並且 IsPersistent 設置為 true 時才會發送。
AuthCookie:客戶端不可見的加密對象,在成功的自定義認証后,網絡服務可選擇返回。
隻有在調用 OpRaiseEvent 時設置了 SendAuthCookie webflag才會發送。

Sample Call

JSON

{
    "ActorNr": 3,
    "AppVersion": "client-x.y.z",
    "AppId": "00000000-0000-0000-0000-000000000000",
    "Data": "data",
    "GameId": "MyRoom",
    "Region": "EU",
    "State": {
        "ActorCounter": 3,
        "ActorList": [
            {
                "ActorNr": 1,
                "UserId": "MyUserId1",
                "NickName": "MyPlayer1",
                "Binary": "RGIAAAEBRAAAAAJzAAlw...",
                "DEBUG_BINARY": {
                    "1": {
                        "255": "MyPlayer1",
                        "player_id": "12345"
                    }
                }
            },
            {
                "ActorNr": 3,
                "UserId": "MyUserId0",
                "NickName": "MyPlayer0",
                "IsActive": true,
                "Binary": "RGIAAAEBRAAAAAFi/3MAC...",
                "DEBUG_BINARY": {
                    "1": {
                        "255": "MyPlayer0"
                    }
                }
            }
        ],
        "Binary": {
            "18": "RAAAAAdzAAhwcm9wMUtl...",
            "19": "RGl6AAEAAAAAAAN6AANp..."
        },
        "CheckUserOnJoin": true,
        "CustomProperties": {
            "lobby4Key": "test1b",
            "lobby3Key": "test1a"
        },
        "DeleteCacheOnLeave": false,
        "EmptyRoomTTL": 0,
        "IsOpen": true,
        "IsVisible": true,
        "LobbyType": 0,
        "LobbyProperties": [
            "lobby3Key",
            "lobby4Key"
        ],
        "MaxPlayers": 4,
        "PlayerTTL": 2147483647,
        "SuppressRoomEvents": false,
        "Slice": 0,
        "DebugInfo": {
            "DEBUG_PROPERTIES_18": {
                "250": [
                    "lobby3Key",
                    "lobby4Key"
                ],
                "prop1Key": "prop1Val",
                "prop2Key": "prop2Val",
                "lobby4Key": "test1b",
                "lobby3Key": "test1a",
                "map_name": "mymap",
                "turn": 1
            },
            "DEBUG_EVENTS_19": {
                "0": [
                    [
                        3,
                        0,
                        "data"
                    ],
                    [
                        3,
                        0,
                        "data"
                    ],
                    [
                        3,
                        0,
                        "data"
                    ]
                ]
            }
        }
    },
    "Type": "Event",
    "UserId": "MyUserId0",
    "NickName": "MyPlayer0",
    "EvCode": 0
}

PathLeave

當一個角色與Photon遊戲伺服器斷開連接時,這個掛鉤就會被觸發。
斷開可能有幾個原因。
webhook本身在其Type中以可讀的形式告訴你這個原因,並以編碼的方式告訴你,見Reason

具體參數

Type:原因的可讀形式,可以是以下值之一:

  • ClientDisconnect:表示客戶端調用了OpLeaveRoom()Disconnect()
  • ClientTimeoutDisconnect:表明客戶端已經 timed-out 伺服器。
    這只在使用UDP/ENET時有效。
  • ManagedDisconnect:表示客戶端太慢,無法處理發送的數據。
  • ServerDisconnect:表示低級別的協議錯誤,可能由數據損壞引起。
  • TimeoutDisconnect:表明伺服器已經 timed-out 客戶端。
    doc on analyzing disconnects .中找到額外的信息。
  • LeaveRequest:表示客戶端通過調用 OpLeaveRoom() OpLeaveRoom(false) 明確地放棄了這個房間。
  • PlayerTtlTimedOut:表示不活動的actor_time-out_,意味著房間的PlayerTtL對該actor來說已經到期。
    更多信息請參考您的SDK的API文檔。
  • PeerLastTouchTimedOut:表示一個非常不尋常的情況,actor在5分鐘內沒有向Photon伺服器發送任何東西。
    通常情況下,對象在這之前早就超時了,但是Photon每5分鐘檢查一次每個連接的對象與伺服器最後一次交換的時間戳(稱為 LastTouch)。
  • PluginRequest:表明actor被插件從actor列表中移除。
  • PluginFailedJoin:表示Photon Cloudwebhooks執行中的一個內部錯誤。

IsInactive:指actor離開房間前的狀態。如果設置為 true,那麼actor可以重新加入遊戲。如果設置為false,則actor永遠離開,並從actor名單中刪除,不能重新加入遊戲。

Reason:原因代碼

下面的表格將每種類型與它的代碼相匹配,並解釋了webhook是如何產生的,以及玩家在房間裡的存在是如何被影響的。

RoomOptions.PlayerTTL在房間創建時設置為0

RoomOptions.PlayerTTL == 0 的房間的actor永遠不能處於不活動狀態,一旦他們離開,就會從actor列表中刪除。
IsPersistent選項將被忽略,因為根據設計,只有當房間包含至少一個不活動的actor時,房間狀態才會被保存。

任何觸發PathLeave網絡掛鉤的事件都將導致從房間中移除相應的actor。
不要試圖檢查這些actor是否處於活動狀態;)
OpLeaveRoom(true)將不再有用,PlayerTtlTimedOut類型的PathLeave在這種情況下不會發生。

Type Reason Trigger Inactive
ClientDisconnect 0 a call to Disconnect() false
ClientTimeoutDisconnect 1 called by Photon server false
ManagedDisconnect 2 called by Photon server false
ServerDisconnect 3 called by Photon server false
TimeoutDisconnect 4 called by Photon server false
LeaveRequest 101 a call to OpLeaveRoom() false
PlayerTtlTimedOut 102 N/A N/A
PeerLastTouchTimedout 103 called by Photon server false
PluginRequest 104 called by plugin false
PluginFailedJoin 105 called by Photon server false
RoomOptions.PlayerTTL !=0在創建房間時
Type Reason Trigger IsInactive
ClientDisconnect 0 a call to Disconnect() true
ClientTimeoutDisconnect 1 called by Photon server true
ManagedDisconnect 2 called by Photon server true
ServerDisconnect 3 called by Photon server true
TimeoutDisconnect 4 called by Photon server true
LeaveRequest 101 a call to OpLeaveRoom() false
PlayerTtlTimedOut 102 called by Photon server false
PeerLastTouchTimedout 103 called by Photon server false
PluginRequest 104 called by plugin false
PluginFailedJoin 105 called by Photon server false

Sample Call

JSON

{
    "ActorNr": 1,
    "AppVersion": "client-x.y.z",
    "AppId": "00000000-0000-0000-0000-000000000000",
    "GameId": "MyRoom",
    "IsInactive": true,
    "Reason": "0",
    "Region": "EU",
    "Type": "ClientDisconnect",
    "UserId": "MyUserId1",
    "NickName": "MyPlayer1"
}

PathClose

這個掛鉤在從Photon Cloud的內存中刪除房間事件之前觸發。
這只發生在EmptyRoomTTL過期時。
EmptyRoomTTL是在創建房間時設置的,它是一個 timer,當房間變空時就開始計時。
當房間裡最後一個活動角色離開時,房間就被認為是空。

如果 IsPersistent 被設置為 true,Photon Cloud將發送 State,這是房間的序列化snapshot,包含其屬性、角色信息和緩存的事件。
在這種情況下,webhook的Type 將有Save值。

如果IsPersistent被設置為false,這是默認狀態,TypeCloseState不被發送,房間將永遠消失。

具體參數

ActorCount:不活動的actor的數量。如果是0,那麼Type 應該是 "關閉"。

PathClose, Type: "Save"

State:房間完整狀態的序列化快照

Sample Call

JSON

{
    "ActorCount": 2,
    "AppVersion": "client-x.y.z",
    "AppId": "00000000-0000-0000-0000-000000000000",
    "GameId": "MyRoom",
    "Region": "EU",
    "State": {
        "ActorCounter": 3,
        "ActorList": [
            {
                "ActorNr": 1,
                "UserId": "MyUserId1",
                "NickName": "MyPlayer1",
                "Binary": "RGIAAAEBRAAAAAJzAAlw...",
                "DEBUG_BINARY": {
                    "1": {
                        "255": "MyPlayer1",
                        "player_id": "12345"
                    }
                }
            },
            {
                "ActorNr": 3,
                "UserId": "MyUserId0",
                "NickName": "MyPlayer0",
                "Binary": "RGIAAAEBRAAAAAFi/3MA...",
                "DEBUG_BINARY": {
                    "1": {
                        "255": "MyPlayer0"
                    }
                }
            }
        ],
        "Binary": {
            "18": "RAAAAAdzAAhwcm9wMUtl...",
            "19": "RGl6AAEAAAAAAAN6AANp..."
        },
        "CheckUserOnJoin": true,
        "CustomProperties": {
            "lobby4Key": "test1b",
            "lobby3Key": "test1a"
        },
        "DeleteCacheOnLeave": false,
        "EmptyRoomTTL": 0,
        "IsOpen": true,
        "IsVisible": true,
        "LobbyType": 0,
        "LobbyProperties": [
            "lobby3Key",
            "lobby4Key"
        ],
        "MaxPlayers": 4,
        "PlayerTTL": 2147483647,
        "SuppressRoomEvents": false,
        "Slice": 0,
        "DebugInfo": {
            "DEBUG_PROPERTIES_18": {
                "250": [
                    "lobby3Key",
                    "lobby4Key"
                ],
                "prop1Key": "prop1Val",
                "prop2Key": "prop2Val",
                "lobby4Key": "test1b",
                "lobby3Key": "test1a",
                "map_name": "mymap",
                "turn": 1
            },
            "DEBUG_EVENTS_19": {
                "0": [
                    [
                        3,
                        0,
                        "data"
                    ],
                    [
                        3,
                        0,
                        "data"
                    ],
                    [
                        3,
                        0,
                        "data"
                    ]
                ]
            }
        }
    },
    "Type": "Save"
}

剝離房間狀態

如果房間狀態的大小對您來說是個問題,您可以做一些小技巧來縮小它而不丟失任何數據。
當在您的網絡服務中保存房間狀態時,您可以通過以下方式減少其大小。

  1. 刪除一些字段,這些字段是為只讀調試目的而設的,在加載房間時不會被用於重建房間狀態。
    這些字段是:CustomProperties, DebugInfo和每個DEBUG_BINARY以及ActorList中每個角色的NickName
    這些字段可以安全地刪除,因為在反序列化房間狀態時它們會被忽略。

    Here is a full room state returned in PathCreate, Type="Load" webhook:

    JSON

    {
        "ResultCode": 0,
        "Message": "Room State successfully loaded",
        "State": {
            "ActorCounter": 3,
            "ActorList": [
                {
                    "ActorNr": 1,
                    "UserId": "MyUserId1",
                    "NickName": "MyPlayer1",
                    "Binary": "RGIAAAEBRAAAAAJzAAlw...",
                    "DEBUG_BINARY": {
                        "1": {
                            "255": "MyPlayer1",
                            "player_id": "12345"
                        }
                    }
                },
                {
                    "ActorNr": 3,
                    "UserId": "MyUserId0",
                    "NickName": "MyPlayer0",
                    "Binary": "RGIAAAEBRAAAAAFi/3MA...",
                    "DEBUG_BINARY": {
                        "1": {
                            "255": "MyPlayer0"
                        }
                    }
                }
            ],
            "Binary": {
                "18": "RAAAAAdzAAhwcm9wMUtl...",
                "19": "RGl6AAEAAAAAAAN6AANp..."
            },
            "CheckUserOnJoin": true,
            "CustomProperties": {
                "lobby4Key": "test1b",
                "lobby3Key": "test1a"
            },
            "DeleteCacheOnLeave": false,
            "EmptyRoomTTL": 0,
            "IsOpen": true,
            "IsVisible": true,
            "LobbyType": 0,
            "LobbyProperties": [
                "lobby3Key",
                "lobby4Key"
            ],
            "MaxPlayers": 4,
            "PlayerTTL": 2147483647,
            "SuppressRoomEvents": false,
            "Slice": 0,
            "DebugInfo": {
                "DEBUG_PROPERTIES_18": {
                    "250": [
                        "lobby3Key",
                        "lobby4Key"
                    ],
                    "prop1Key": "prop1Val",
                    "prop2Key": "prop2Val",
                    "lobby4Key": "test1b",
                    "lobby3Key": "test1a",
                    "map_name": "mymap",
                    "turn": 1
                },
                "DEBUG_EVENTS_19": {
                    "0": [
                        [
                            3,
                            0,
                            "data"
                        ],
                        [
                            3,
                            0,
                            "data"
                        ],
                        [
                            3,
                            0,
                            "data"
                        ]
                    ]
                }
            }
        }
    }
    

    Here is a stripped version of the room state that could be returned in the same webhook:

    JSON

    {
        "ResultCode": 0,
        "Message": "Room State successfully loaded",
        "State": {
            "ActorCounter": 3,
            "ActorList": [
                {
                    "ActorNr": 1,
                    "UserId": "MyUserId1",
                    "Binary": "RGIAAAEBRAAAAAJzAAlw..."
                },
                {
                    "ActorNr": 3,
                    "UserId": "MyUserId0",
                    "Binary": "RGIAAAEBRAAAAAFi/3MA..."
                }
            ],
            "Binary": {
                "18": "RAAAAAdzAAhwcm9wMUtl...",
                "19": "RGl6AAEAAAAAAAN6AANp..."
            },
            "CheckUserOnJoin": true,
            "DeleteCacheOnLeave": false,
            "EmptyRoomTTL": 0,
            "IsOpen": true,
            "IsVisible": true,
            "LobbyType": 0,
            "LobbyProperties": [
                "lobby3Key",
                "lobby4Key"
            ],
            "MaxPlayers": 4,
            "PlayerTTL": 2147483647,
            "SuppressRoomEvents": false,
            "Slice": 0
        }
    }
    
    1. 刪除一些字段,這些字段在您的應用邏輯中被認為是常量,在房間使用期間不應該被改變,或者可以在加載房間時將狀態返回給Photon伺服器之前被代碼注入。
      這些字段應該在將狀態返回給Photon Servers之前被添加回它們的原始值。否則,狀態可能會被破壞。

      這些字段可以是以下的任何一個:

    • ActorCounter
    • CheckUserOnJoin
    • DeleteCacheOnLeave
    • EmptyRoomTTL
    • IsOpen
    • IsVisible
    • MaxPlayers
    • LobbyId
    • LobbyType
    • LobbyProperties
    • PlayerTTL
    • SuppressRoomEvents
    • Slice

Securing Webhooks

Other than using HTTPS and newer TLS version, you can enforce webhooks security using custom HTTP request headers or query string parameters.
The idea is that you set up one or more "secrets" ("token", "key", etc.) from Photon dashboard that can help you make sure that the incoming HTTP requests are originating from Photon servers.

Back to top