오퍼레이션 추가하기
많은 경우에 있어서 이벤트를 전송하는 것만으로는 게임에 충분하지 않습니다. 인증, 저장 또는 게임의 특정한 오퍼레이션등을 제공하려면 이제 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