server | v4 switch to v3  

오퍼레이션 추가하기

많은 경우에 있어서 이벤트를 전송하는 것만으로는 게임에 충분하지 않습니다. 인증, 저장 또는 게임의 특정한 오퍼레이션등을 제공하려면 이제 Lite(또는 LiteLobby)를 확장할 시간 입니다.

이 페이지에서는 새로운 오퍼레이션을 구현하고 어떻게 사용하는지에 대한 두가지 방식을 보여 줍니다. 샘플 오퍼레이션에서는 클라이언트로 부터 메시지가 오면 메시지를 체크하여 값을 리턴 합니다.

서버측, Server-Side, 간단한 변형

우선 Lite 어플리케이션의 서버측 부터 시작해 봅니다. 변경은 어렵지 않고 간단 합니다.

    
        //Server SDK, LitePeer.cs
        public void OnOperationRequest(OperationRequest request, SendParameters sendParameters)
        {
            // handle operation here (check request.OperationCode)
            switch (request.OperationCode)
            {
                case 1:
                    {
                        var message = (string)request.Parameters[100];
                        if (message == "Hello World")
                        {
                            // received hello world, send an answer!
                            var response = new OperationResponse
                            {
                                OperationCode = request.OperationCode,
                                ReturnCode = 0,
                                DebugMessage = "OK",
                                Parameters = new Dictionary<byte, object> { { 100, "Hello yourself!" } }
                            };

                            this.SendOperationResponse(response, sendParameters);
                        }
                        else
                        {
                            // received something else, send an error
                            var response = new OperationResponse
                                {
                                    OperationCode = request.OperationCode,
                                    ReturnCode = 1,
                                    DebugMessage = "Don't understand, what are you saying?"
                                }; 

                            this.SendOperationResponse(response, sendParameters);
                        }

                        return;
                    }
            }
        }

위의 코드는 처음에 호출된 OperationCode 를 검사 합니다. 이 경우의 OperationCode 는 1입니다. Photon에서 OperationCode는 오퍼레이션의 이름/타입을 짧게 줄인 것 입니다. 아래에서 클라이언트가 어떻게 이것을 호출하는지 살펴 볼 것 입니다.

만약 Operation 1이 호출 되면 요청 파라미터를 체크 합니다. 여기에서 파라미터 100 은 문자열로 예측하고 있습니다. 다시한번 말씀드리지만 Photon 은 바이트 형태의 파라미터만 사용하므로 전송시에 깔끔하게 유지하도록 하세요.

그리고 메시지 내용을 체크하고 응답을 준비합니다. 두 개 응답 모두 returnCode 와 디버그 메시지가 있습니다. returnCode 가 0 이면 에러가 없는 리턴이며 이외의 다른 숫자(여기에서는 1)는 오류 또는 클라이언트에 의해서 처리될 필요가 있다는 것을 의미 합니다.

긍정적인 응답은 또한 리턴값을 포함합니다. key-value 쌍을 더 추가할 수 있으나 여기에서는 문자열인 100을 고수 하고 있습니다.

이미 이것은 오퍼레이션을 완전하게 구현 했습니다. 새로운 오퍼레이션을 위한 우리의 규약이며 클라이언트가 사용할 수 있도록 전송 되어야만 합니다.

Back To Top

클라이언트 측

위 오퍼레이션에 대한 정의를 알았으니 클라이언트 측에서 호출 할 수 있습니다. 이 클라이언트 코드는 connect 시에 호출 합니다.

    
        public void OnStatusChanged(StatusCode status) 
        { 
            // handle peer status callback 
            switch (status) 
            { 
            case StatusCode.Connect: 
                // send hello world when connected         
                var parameter = new Dictionary<byte, object>();
                parameter.Add((byte)100, "Hello World");

                peer.OpCustom(1, parameter, true);
                break; 
                //[...]

위에서 정의 한대로 메시지는 파라미터 100 에 있을 것이라고 예측 합니다. 이것은 파라미터 딕셔너리로써 제공 됩니다. 파라미터 키는 바이트 이외의 것이 되어서는 안되며 바이트 이외이면 전송 되지 않을 것 입니다. 그리고 거기에 "Hello World" 로 넣었습니다.

PhotonPeer(그리고 LitePeer) 메소드 OpCustom 은 OperationCode가 첫 번째 파라미터일 것이라고 예상하고 있습니다. OperationCode 가 1 입니다. 파라미터들이 따라오고 오퍼레이션이 도착 했는지 확신하고 싶습니다(이것이 필 수 입니다).

이것과는 별도로 클라이언트는 일반적인 작업을 해야 합니다. 이 의미는 주기별로 PhotonPeer.Service 를 호출 해야 한다는 것 입니다.

결과를 사용할 수 있으면 다음과 같이 처리 할 수 있습니다:

    
        public void OperationResponse(OperationResponse operationResponse) 
        { 
            // handle response by code (action we called) 
            switch (operationResponse.OperationCode) 
            { 
                // out custom "hello world" operation's code is 1
                case 1: 
                    // OK 
                    if (operationResponse.ReturnCode == 0) 
                    { 
                        // show the complete content of the response
                        Console.WriteLine(operationResponse.ToStringFull()); 
                    } 
                    else 
                    { 
                        // show the error message
                        Console.WriteLine(operationResponse.DebugMessage); 
                    } 
                    break; 
            } 
        }

Back To Top

서버측, 고급 버전

오퍼레이션을 처리 할 때 선호하는 방식은 이것을 위해 클래스를 생성하는 것 입니다. 이 방식은 강한 타입형이고 파라미터가 누락되면 이슈가 되며 프레임워크에 의해서 처리가 됩니다.

이것이 오퍼레이션, 파라미터들, 파라미터의 타입과 리턴 값의 정의입니다:

    
//new Operation Class
namespace MyPhotonServer
{
    using Photon.SocketServer;
    using Photon.SocketServer.Rpc;

    public class MyCustomOperation : Operation
    {
        public MyCustomOperation(IRpcProtocol protocol, OperationRequest request)
            : base(protocol, request)
        {
        }

        [DataMember(Code = 100, IsOptional = false)]
        public string Message { get; set; }

        // GetOperationResponse could be implemented by this class, too
    }
}

위에서 정의된 오퍼레이션 클래스에서 요청에 대하여 강하게 타입된 방식으로 응답을 매핑 할 수 있습니다.

    
     public void OnOperationRequest(OperationRequest request, SendParameters sendParameters)
        {
            switch (request.OperationCode)
            {
                case 1:
                    {
                        var operation = new MyCustomOperation(this.Protocol, request);
                        if (operation.IsValid == false)
                        {
                            // received garbage, send an error
                            var response = new OperationResponse
                            {
                                OperationCode = request.OperationCode,
                                ReturnCode = 1, 
                                DebugMessage = "That's garbage!"
                            };

                            this.SendOperationResponse(response, sendParameters);
                            return;
                        }

                        if (operation.Message == "Hello World")
                        {
                            // received hello world, send an answer! 
                            operation.Message = "Hello yourself!";
                            OperationResponse response = new OperationResponse(request.OperationCode, operation); 
                            this.SendOperationResponse(response, sendParameters);
                        }
                        else
                        {
                            // received something else, send an error
                            var response = new OperationResponse
                            {
                                OperationCode = request.OperationCode,
                                ReturnCode = 1,
                                DebugMessage = "Don't understand, what are you saying?"
                            };

                            this.SendOperationResponse(response, sendParameters);
                        }
                        break;
                    }
            }
        }

기술문서 TOP으로 돌아가기