Webhooks

플레이어들이 게임에 재참여하고 플레이어와 게임 데이터를 유지할 수 있도록 어플리케이션을 확장하기 위해 Photon Cloud 에서 Webhooks를 사용하세요.

Photon webhooks는 특정 URL로 Photon Cloud가 전송하는 이벤트 기반의 HTTP POST 요청입니다. 각 Photon webhook는 트리거, 데이터와 목적 경로로 정의됩니다.

여기에서 webhooks 1.2의 새로운 내용을 읽어주십시오.

Content

설정

Photon Cloud에서 webhook를 설정하려면, 관리화면의 어플리케이션 목록의 관리 링크로 이동하세요. Webhooks 섹션에서 새로운 것을 추가하거나 기존의 것을 변경하십시오.

Webhooks 환경설정 페이지에서 드롭다운 리스트를 사용하여 사전에 정의된 프리셋중 하나를 선택할 수 있습니다. "데모" 프리셋은 개발에서만 사용되어야 합니다. 데모는 여러 설정에 대하여 빠른 미리보기와 사용방법에 대해 보여주는 목적을 위한 것 입니다.

환경설정은 문자열의 키/값 쌍을 정의하여 수행됩니다. 키의 최대 문자열 길이는 256 문자이며, 값은 1024 문자까지 허용됩니다.

기본 설정

  • BaseUrl (필수)
    WebRPC를 통해 호출되는 hook을 호스팅하는 서비스의 URL과 메소드. 슬래시로 끝나면 안됩니다. 아래에서 설정된 상대경로 URI로 콜백이 수신됩니다.
  • CustomHttpHeaders
    구성된 웹 서비스 요청에 HTTP 헤더로써 설정되어야 하는 키/값 쌍을 포함하고 있는 JSON 객체.

Paths

호스트에서 식별되는 URI에서 이벤트를 수신하도록 각 경로를 구성합니다. 비어있는 경로는 히트되지 않으며 해당 webhook의 콜백을 받지 않습니다.

  • PathCreate
    새로운 룸이 생성되었거나 룸의 상태가 외부 서비스에서 로드될 필요가 있을 때 호출됩니다.
  • PathClose
    Photon 서버 메모리에서 룸이 제거되었을 때 호출됩니다. IsPersistenttrue 설정되었다면 룸의 상태가 전송됩니다.
  • PathJoin
    Photon 서버 메모리내에 룸이 있을 때, 플레이어가 룸에 참여할 때 호출됩니다.
  • PathLeave
    플레이어가 룸에서 나갈 때 호출됩니다.
  • PathEvent
    web flag HttpForward 가 설정된 룸에서 클라이언트가 이벤트를 발생시켰을 때 호출됩니다.
  • PathGameProperties
    클라이언트가 룸 또는 플레이어 속성을 web flag HttpForward 로 설정했을 때 호출됩니다.

옵션

이러한 옵션을 사용하여 webhooks 구성의 동작을 조정하십시오. 설정되지 않았거나 값이 비어있는 경우 옵션은 구성되지 않은 것으로 간주됩니다. 각 옵션의 기본값은 false 이며, 각각 설정되지 않는것으로 적용됩니다.

  • HasErrorInfo
    true로 설정된 경우, 클라이언트들은 후크에 대한 호출이 실패했을 때 ErrorEvent 로 알림을 받게 될 것 입니다.
  • IsPersistent
    true로 설정되면, Photon Cloud 는 메모리에서 룸을 제거하기 전에 상태를 전송합니다. 이 옵션은 PathCreatePathClose 가 올바르게 구성되었을 경우에만 유효합니다. 상세 내용에 대해서는 GameCreateGameClose webhooks에 대하여 읽어 주십시오.
  • AsyncJoin
    이 옵션은 IsPersistenttrue 로 설정되었을 때만 유효합니다. 기본적으로 이 설정값은 true로 설정되며 참여 오퍼레이션이 서버에서 이름으로 룸을 찾지 못했을 때 webhook로써의 웹 서비스로 포워딩 될 것 입니다. 이 행위를 사용하지 못하도록 하려면 이 값을 false로 변경하십시오. 여기에서 더 읽으십시오.

턴키 솔루션(Turnkey Solutions)

Microsoft Azure와 Heroku용 최신 턴키 설치는 당사 github 페이지에 있습니다. Java를 사용한 Photon Webhooks용 타사 솔루션은 bitbucket에 있습니다.

공통평가 기준

모든 Photon Webhook은 POST에 대한 기본 URL을 공유하며, 웹 서버에서 발생할 수 있는 최종 오류 및 각각 함께 전송되는 기준 데이터를 리턴합니다.

모든 Webhooks의 공통 인수

AppId: 게임 클라이언트에서 설정된 어플리케이션의 AppId이며 관리화면에서 확인할 수 있습니다.

AppVersion: 게임 클라이언트에서 설정된 어플리케이션의 버전.

Region: 게임 클라이언트가 연결된 지역과 해당 방이 속한 지역이 있습니다.

GameId: 룸의 ID 또는 이름.

Type: webhook의 유형, PathEvent webhook 내의 "Event" 이며 , PathJoin webhook 내의 "Join" 이고 다른 모든 webhooks에서 여러개의 값을 가질 수 있습니다.

PathClose를 제외한 모든 Webhooks의 공통 인

ActorNr: 후크를 트리거하는 액터 번호.

UserId: 후크를 트리거하는 액터의 UserId.

NickName: 클라이언트 SDK에서 설정된 후크를 트리거하는 액터의 이름.

리턴 값

예상되는 응답

webhooks를 전송할 때, Photon Cloud 는 대부분의 경우에 있어서 ResultCode 속성을 0으로 설정한 JSON 객체를 가지고 있는 응답만을 기대할 것 입니다. ResultCode 0은 웹 서버에서 성공적으로 처리된 webhook 요청 수신에 대한 응답입니다.

0 이외의 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>." }

Paths 상세내용

PathCreate

서버 레벨에서 룸이 생성되었을 때 매번 트리거되는 webhook 입니다. OpCreateRoom을 사용하여 룸이 생성된 경우, webhook의 Type 아규먼트는 Create 로 설정될 것 입니다. 룸을 생성 할 때 사용 된 TypedLobby 와 함께 RoomOptions 의 대부분은 CreateOptions 으로 보내집니다. ActorNr 값은 1이고 액터는 PathJoin의 발생 없이 자동으로 룸에 참여할 것 입니다.

액터가 이전에 생성되었으나 Photon Cloud에서 제거된 룸에 참여하거나 재참여를 시도한 경우, TypeLoad로 설정될 것 입니다. 웹 서버는 같은 룸의 직렬화된 State를 리턴해야합니다. 백엔드 로직은 이전에 저장된 직렬화된 방의 상태를 가져와야합니다.

상태를 찾을 경우, 웹 서버는 { "State" : state, "ResultCode" : 0 }로 JSON 객체를 리턴해야 합니다. 특정 이유로 상태가 발견되지 않으면 웹 서비스는 CreateIfNotExists의 값에 따라 새로운 상태로 룸 생성을 허용하거나 허용하지 않아야합니다. CreateIfNotExists 이 true이면, 클라이언트에서 제공된 옵션으로 룸 생성을 허용할 수 있도록 빈 룸 상태를 리턴할 수 있습니다.( 예, { "State" : "", "ResultCode" : 0 }) 이 값이 false인 경우 Photon Cloud는 ResultCode를 0 이외의 값으로 리턴하여 상태 로드에 실패했다고 웹 서버에게 알려주어야 합니다. 사람이 읽을 수 있는 원인이 포함된 오류 메시지를 추가하는 것을 고려하시기 바랍니다.

"IsPersistent" 가 true 로 설정되고 "PathCreate" 와 "PathClose" 가 구성되었다면, 룸 생성, 비동기 참여 또는 재참여가 다음일 때 실패할 것 입니다:
  • "PathCreate" 이 도달할 수 없거나 HTTP 에러를 리턴.
  • "PathCreate" 가 ResultCode0 이외의 값으로 리턴.
  • Photon Server 수신된 룸 상태를 해석하거나 설정하는 데 실패.

AsyncJoin 옵션

Photon 어플리케이션은 친구들과 더 쉽게 플레이 하기위해, 게임이 생성되고 몇 시간 후에 게임 참여를 위한 초대를 수락하는 것과 같은 비동기 오퍼레이션을 지원합니다. IsPersistentAsyncJoin 이 사용되도록 되어있으면, Photon 서버 메모리에서 찾을 수 없는 룸이 있는 모든 참여 오퍼레이션은 PathCreate (Type="Load") webhook을 트리거할 것 입니다.
이 목적은 룸이 이전에 생성되고 저장되었다고 가정하여 웹 서비스로부터 룸의 상태를 로드하는 것 입니다.

AsyncJoinIsPersistenttrue로 설정되어있으면 기본적으로 사용됩니다. AsyncJoin을 사용하지 않기 위해서는, webhooks 설정에 없으면 키를 추가하고 값을false 로 설정하십시오.

아래 테이블은 IsPersistent가 사용하도록 설정되어 있을 때(Photon 서버 메모리에서 룸이 없는 경우), Type="Load"PathCreate webhook을 트리거하는 모든 클라이언트 오퍼레이션을 나타냅니다.

클라이언트 오퍼레이션 JoinMode AsyncJoin = false AsyncJoin = true AsyncJoin = N/A
OpJoinRoom 기본 (Join) x
OpRejoinRoom RejoinOnly
OpJoinOrCreateRoom CreateIfNotExists

특별한 인수

PathCreate, Type "Create"

CreateOptions: 이 옵션은 룸 생성시에 사용됩니다. 여기에는 TypedLobby에 관한 세부 사항이 담긴RoomOptions 클래스의 정보가 들어 있습니다. 이것의 모든 속성들은 현재 값으로 복사 될 것이므로 State에서 나중에 불러올 수 있습니다.

다음 테이블은 CreateOptionsRoomOptions의 비교표입니다.

속성 또는 필드 CreateOptions RoomOptions Notes
IsVisible x 나중에 룸 상태에서 불러 올 수 있습니다.
IsOpen x 나중에 룸 상태에서 불러 올 수 있습니다.
MaxPlayers
PlayerTtl
EmptyRoomTtl
CheckUserOnJoin 플레이어마다 유일한 ID를 가지고 있으면 반드시 true 로 설정되어야 합니다.
SuppressRoomEvents true로 설정되면, 참여하고 떠날때 모든 이벤트들이 클라이언트들에게 전송되지 않습니다. 기본값은 false이며 전송됩니다.
DeleteCacheOnLeave 이것은 RoomOptions에서 CleanupCacheOnLeave 라고 합니다.
LobbyType x TypedLobby.Type 에서 게임 클라이언트가 설정하는 룸의 로비 유형. 추가적인 정보는 SDK의 API 문서 참조하십시오.
LobbyId x TypedLobby.Name에서 게임 클라이언트가 설정한 룸의 로비 이름. 추가적인 정보는SDK의 API 문서 참조하십시오.
CustomProperties x 공개되어야하는, 즉 로비에 표시되어야 하는 룸의 초기 사용자정의 속성만이 들어있습니다.
CustomRoomProperties x 룸의 모든 초기 사용자정의 속성들이 들어 있습니다.
CustomRoomPropertiesForLobby x 공개되어야하는, 즉 로비에 표시되어야 하는 룸의 초기 사용자정의 속성의 키가 들어있습니다.
PublishUserId x 플레이어의 사용자 ID가 룸에 "게시"되었는지 여부를 정의합니다.
나중에 룸 상태에 값을 가져올 수 있습니다.
이에 대해서는 여기를 읽어 보십시오.

PathCreate, Type "Load"

CreateIfNotExists: 웹 서비스에서 룸 상태를 찾을 수 없는 경우 새 룸을 생성할지를 나타내는 데 사용되는 플래그입니다.

CreateOptions에서 있는 것 이외의 룸의 State 속성:

  • ActorCounter: 최근에 참여한 액터의 ActorNr.
  • ActorList: 룸에 있는 각 액터에 대한 정보 항목의 배열 (활성 또는 비활성). 각 항목은 다음 속성들을 가지고 있습니다:
    • ActorNr: 룸에 있는 액터의 번호.
    • UserId: 액터의 UserID.
    • NickName: 액터의 NickName.
    • IsActive: 액터가 룸에 참여하고 있는지를 나타냅니다. PathCloseState 인수내로는 전송되지 않습니다.
    • DeactivationTime: 룸 이벤트의 타임스탬프. PathCloseState 인수로만 전송됩니다.
    • Binary*: Base64 로 인코딩된 액터 속성들.
    • DEBUG_BINARY**: 액터 속성들의 읽을 수 있는 형태.
  • Slice: 캐시 슬라이스 인덱스.
  • Binary *: Base64 인코딩된 룸 속성 및 캐시된 이벤트들.
  • DebugInfo **: 바이너리 데이터의 읽을 수 있는 형식.
    • DEBUG_PROPERTIES_18**: 룸 속성들의 읽을 수 있는 형식.
    • DEBUG_EVENTS_19**: 캐시된 이벤트들의 읽을 수 있는 형식.
    • DEBUG_GROUPS_20**: 관심 그룹들의 읽을 수 있는 형식.
  • ExpectedUsers: 룸에 참여할 것으로 예상되는 플레이어들의 UserId의 배열. 슬롯 예약에 대해서 더 읽어보십시오.

* : Binary 속성들은 Photon에서 사용되는 프로토콜의 특성때문에 존재합니다.
* : Debug 속성들은 제품 출시 환경에서는 사용되어서는 안됩니다. 이러한 속성들이 디버그 할 때만 사용되는지 확인해주십시오.

샘플 호출

{
    "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

액터가 Photon Cloud 에서 제거되지 않은 룸에 참여하거나 재참여하면, 이 webhook이 발생할것입니다. Type 인수는 Join 으로 설정됩니다.

특별한 인수

PathJoin 은 추가 인수가 없습니다.

샘플 호출

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

PathGameProperties

이 webhook은 HttpForward 웹 플래그가 설정된 적절한 오버로드 메소드가 사용되고 클라이언트 측에서 룸 또는 플레이어의 사용자정의 속성을 사용자가 설정하면 매번 발생됩니다. webhook 과 함께 Type 인수는 Game 또는 Actor 에 따라 설정될 것 입니다.

특별한 인수

Properties: 클라이언트 SDK에서 전송된 일련의 업데이트 된 속성.
State: 룸의 전체 상태의 직렬화된 스냅샷. SendState가 설정된 경우에, OpSetCustomProperties 을 호출시 "IsPersistent" 설정이 true 로 되어 있는 경우에만 전송됩니다. AuthCookie: 암호화된 객체로 클라이언트에게는 보이지 않으며, 성공적인 사용자정의 인증시 웹 서비스로부터 선택적으로 리턴됩니다. OpSetCustomProperties 호출시에 SendAuthCookie 웹 플래그가 설정된 경우에만 전송됩니다.

PathGameProperties, Type="Actor"
TargetActor: 속성이 갱신된 액터 번호

샘플 호출

{
    "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: 룸의 전체 상태의 직렬화된 스냅샷. SendState가 설정된 경우에, OpRaiseEvent 를 호출시 "IsPersistent" 설정이 true 로 되어 있는 경우에만 전송됩니다.

AuthCookie: 암호화된 객체로 클라이언트에게는 보이지 않으며, 성공적인 사용자정의 인증시 웹 서비스로부터 선택적으로 리턴됩니다. OpRaiseEvent 호출시에 SendAuthCookie 웹 플래그가 설정된 경우에만 전송됩니다.

샘플 호출

{
    "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: 클라이언트가 서버에서 타임아웃 되었다는 것을 나타냅니다. UDP/ENET 를 사용할 때만 유효합니다.
  • ManagedDisconnect: 전송된 데이터를 처리하기에 클라이언트가 너무 느리다는 것을 나타냅니다.
  • ServerDisconnect: 저수준 프로토콜 에러로 데이터 변질에 의한 것이라는 것을 나타냅니다.
  • TimeoutDisconnect: 서버가 타임아웃된 클라이언트를 가지고 있다는 것을 나타냅니다. 추가적인 정보는 클라이언트 연결 처리 페이지 또는 연결해제 분석 문서를 참고하십시오.

  • LeaveRequest: 클라이언트가 명시적으로 OpLeaveRoom() OpLeaveRoom(false) 를 호출하여 룸을 나갔다는 것을 나타냅니다.

  • PlayerTtlTimedOut: 활동중이지 않은 액터가 타임아웃 되었다는 것을 나타내며, 해당 액터의 룸 PlayerTtL 만료되었다는 것입니다. 추가정보에 대해서는 SDK의 API 문서를 참고하십시오.
  • PeerLastTouchTimedOut: 액터가 Photon Servers에 5분 동안 아무 것도 보내지 않은 아주 특별한 시나리오를 나타냅니다. 일반적으로 피어들은 이것보다 전에 타임아웃 되지만 Photon은 5분마다 서버와 마지막으로 교환한 모든 연결된 피어의 타임스탬프 (LastTouch라고 함)를 확인합니다.
  • PluginRequest: 액터가 플러그인에 의해서 ActorList로 부터 제거되었는지를 나타냅니다.
  • PluginFailedJoin: Photon Cloud webhooks 구현의 내부 오류가 있다는 것을 나타냅니다.

IsInactive: 룸을 나가기 전에 액터의 상태를 나타냅니다. true로 설정하면 액터가 게임에 다시 참여할 수 있습니다. false로 설정하면, 액터는 영원히 떠난 것이므로, ActorList에서 제거되고 게임에 다시 참여할 수 없습니다.

Reason: 사유의 코드

아래 표는 각 유형을 해당 코드와 일치시키고 웹 훅이 어떻게 생성되는지, 그리고 룸에서 플레이어의 존재가 어떻게 영향을 받는지를 설명합니다.

RoomOptions.PlayerTTL set to 0 upon Room Creation

RoomOptions.PlayerTTL == 0 으로 되어 있는 룸의 액터들은 비활성 상태로 절대 될 수 없으며 룸에서 떠나면 즉시 ActorList에서 제거될 것 입니다. IsPersistent 옵션은 방에 적어도 하나의 비활성 액터가 있는 경우에만 디자인 룸 상태를 저장해야 하므로 무시될 것 입니다.

PathLeave webhook로 트리거된 모든 이벤트들은 룸에서 액터를 제거하는 결과가 될 것 입니다. 이러한 액터가 활성인지 여부를 확인하려고 하지는 마십시오, ;) OpLeaveRoom (true)는 더 이상 사용되지 않으며 PathLeavePlayerTtlTimedOut 유형의 이 상황에서 발생할 수 없습니다.

Type Reason Trigger ActorList 내의 액터
ClientDisconnect 0 Disconnect() 또는 OpLeaveRoom(true) 호출 false
ClientTimeoutDisconnect 1 Photon server에 의해 호출 false
ManagedDisconnect 2 Photon server에 의해 호출 false
ServerDisconnect 3 Photon server에 의해 호출 false
TimeoutDisconnect 4 Photon server에 의해 호출 false
LeaveRequest 101 OpLeaveRoom() 또는 OpLeaveRoom(false) 호출 false
PlayerTtlTimedOut 102 N/A N/A
PeerLastTouchTimedout 103 Photon server에 의해 호출 false
PluginRequest 104 플러그인에 의해 호출 false
PluginFailedJoin 105 Photon server에 의해 호출 false
RoomOptions.PlayerTTL != 0 upon Room Creation
Type Reason Trigger IsComingBack 또는 IsInactive ActorList 내의 액터
ClientDisconnect 0 Disconnect() 또는 OpLeaveRoom(true) 호출 true true
ClientTimeoutDisconnect 1 Photon server에 의해 호출 true true
ManagedDisconnect 2 Photon server에 의해 호출 true true
ServerDisconnect 3 Photon server에 의해 호출 true true
TimeoutDisconnect 4 Photon server에 의해 호출 true true
LeaveRequest 101 OpLeaveRoom() 또는 OpLeaveRoom(false) 호출 false false
PlayerTtlTimedOut 102 a call to false false
PeerLastTouchTimedout 103 a call to false false
PluginRequest 104 플러그인에 의해 호출 false false
PluginFailedJoin 105 Photon server에 의해 호출 false false

샘플 호출

{
    "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 은 룸 생성시에 설정되며 룸이 비기 시작할 때부터 시작되는 타이머 입니다. 룸은 최종 활성 액터가 룸을 떠났을 때부터 비어 있는 것으로 간주됩니다.

IsPersistenttrue로 설정된 경우, Photon Cloud 는 액터와 캐시된 이벤트에 대한 속성과 정보를 담고 있는 룸의 직렬화된 스냅샷State를 전송할 것 입니다. 이 경우에 있어서, webhook의 TypeSave 값을 가지고 있을 것 입니다.

IsPersistent 가 기본값인 false 로 설정된 경우에, TypeClose이며 State는 전송되지 않으며 룸은 영원히 없어지게 될 것 입니다.

특별한 인수

ActorCount: 비활성화인 액터의 번호. 0이면 Type은 "Close"가 되어야 합니다.

PathClose, Type: "Save"

State: 룸 전체 상태의 직렬화된 스냅샷

샘플 호출

{
    "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"
}

URL 태그

대시보드에서 Webhooks 또는 WebRpc 의 기준 URL을 설정 할 때 하나 이상의 "동적 변수"를 설정 할 수 있습니다. 이러한 변수들은 요청을 전송하기 전에 백엔드에서 상응하는 값들로 교체 되게 됩니다.

어플리케이션에서 사용자들을 서로 다르게 분리하여 처리를 원할 때 URL 태그는 매우 간편합니다. Photon 은 다음의 URL 태그들을 지원합니다:

  • {AppVersion} 은 클라이언트에서 설정된 어플리케이션 버전을 전달 합니다.
  • {AppId} 는 어플리케이션의 ID 를 전달 합니다.
  • {Region} 은 클라이언트가 접속된 클라우드 지역에 대한 토큰을 전달 합니다. 예, "eu".
  • {Cloud} 는 클라이언트가 연결된 클라우드의 이름을 전달 합니다. 예, "public" 또는 "enigmaticenterprise".

URL 태그 유즈케이스의 예제

  1. https://{Region}.mydomain.com/{AppId}?version={AppVersion}&cloud={Cloud}
  2. https://mydomain.com/{Cloud}/{Region}/{AppId}/{AppVersion}

룸 상태 분리하기

룸 상태의 크기가 걱정된다면, 데이터의 누락없이 크기 축소를 위한 몇 가지 트릭을 수행 할 수 있습니다. 웹 서비스에서 룸 상태를 저장하면 다음과 같이 크기를 줄일 수 있습니다:

  1. 디버그 목적으로 만들어진 일부 읽기 전용 필드와 룸을 로드 할 때 방 상태를 재구성하는 동안 사용되지 않는 필드를 제거합니다. 이러한 필드는 다음과 같습니다: CustomProperties, DebugInfo 그리고 모든 DEBUG_BINARYActorList 내의 각 액터의 NickName. 이런 필드들은 룸 상태를 비직렬화 할때 무시되므로 제거해도 안전합니다.

다음은 PathCreate, Type="Load" webhook로 리턴되는 모든 룸 상태 입니다:

{
    "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"
                    ]
                ]
            }
        }
    }
}

다음은 동일한 webhook에서 리턴 될 수 있는 분리된 버전의 방의 상태입니다:

{
    "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 서버로 상태를 리턴하기 전에 원래 값으로 다시 추가해야합니다. 그렇지 않으면 상태가 깨질 수 있습니다.

이러한 필드들은 다음과 같습니다:

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

 기술문서 TOP으로 돌아가기