This document is about: SERVER 4
SWITCH TO

오퍼레이션 추가하기

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

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

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

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

C#

//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을 고수 하고 있습니다.

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

클라이언트 측

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

C#

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 를 호출 해야 한다는 것 입니다.

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

C#

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;
    }
}

서버측, 고급 버전

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

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

C#

//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
    }
}

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

C#

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;
               }
       }
   }
Back to top