Photon Lessons 05 - Operation и Event

После 1, 2, 3 и 4 уроков настало время связать наш клиент и сервер с помощью Opertaion и Event. Вначале расскажу вам что такое Opertaion и Event, ибо на первый взгляд отличий не найдете:)

Operation — это грубо говоря «Запрос-ответ». Клиент посылает серверу например команду «выдай-ка мне список игроков в онлайне» и сервер затем отвечает клиенту, передавая этот самый список. Поэтому клиент может и отправлять операции, и принимать сообщения об операции.

Event — это «рассылка» сервером какого-то события. Т.е. допустим дядя Ваня убил мальчика Сашу и сервер выслал всем игрокам в радиусе видимости сообщение о том, что «дяда Ваня убил Сашу» — это сообщение и будет выслано в форме Event. Поэтому клиент не может отправлять событие на сервер, а значит сервер не может их принимать. Зато сервер может отсылать событие, а клиент может их принимать. Ну как, запутал еще больше?:) Ок, прочтите тогда еще раз и посмотрите видео + Злостный код из урока 4 + 5…



Скрипт UnityClient.cs(сервер):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Photon.SocketServer;
using ExitGames.Logging;
using PhotonHostRuntimeInterfaces;
namespace PhotonIntro
{
    public class UnityClient:PeerBase
    {
            private readonly ILogger Log = LogManager.GetCurrentClassLogger();
            public UnityClient(IRpcProtocol protocol, IPhotonPeer peer)
                    : base(protocol, peer)
            {
                    Log.Debug("Connection:" + peer.GetRemoteIP());
            }
            protected override void OnDisconnect()
            {
                    Log.Debug("Disconnected");
            }
            protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
            {
                    switch (operationRequest.OperationCode)
                    {
                            case 1:
                                    if (operationRequest.Parameters.ContainsKey(1))
                                    {
                                            Log.Debug("recv:" + operationRequest.Parameters[1]);
                                            OperationResponse response = new OperationResponse(operationRequest.OperationCode);
                                            response.Parameters = new Dictionary<byte, object> { { 1, "response message" } };
                                            SendOperationResponse(response, sendParameters);
                                    }
                                    break;
                            case 2:
                                    if (operationRequest.Parameters.ContainsKey(1))
                                    {
                                            Log.Debug("recv:" + operationRequest.Parameters[1]);
                                            EventData eventdata = new EventData(1);
                                            eventdata.Parameters = new Dictionary<byte, object> { { 1, "response for event" } };
                                            SendEvent(eventdata, sendParameters);
                                    }
                                    break;
                            default:
                                    Log.Debug("Unknown OperationRequest received!:" + operationRequest.OperationCode);
                                    break;
                    }
            }
    }
}


Скрипт Login.cs(клиент):
using UnityEngine;
using System.Collections;
using System;
using ExitGames.Client.Photon;
public class Login : MonoBehaviour {
    PhotonServer _photonServer;
    bool _isConnected;
// Use this for initialization
void Start () {
            Application.runInBackground = true;
            _photonServer = new PhotonServer();
}

// Update is called once per frame
void Update () {
            try
            {
                    if (_isConnected)
                    {
                            _photonServer.Update();
                    }
            }
            catch(Exception ex)
            {
                    Debug.Log(ex);
            }
}
    void OnApplicationQuit()
    {
            try
            {
                    _photonServer.Disconnect();
            }
            catch (Exception ex)
            {
                    Debug.Log(ex);
            }
    }
    void OnGUI()
    {
            if (GUI.Button(new Rect(5, 5, 100, 20), "Connect"))
            {
                    PhotonPeer peer = new PhotonPeer(_photonServer, false);
                    _photonServer.Init(peer, "localhost:5055", "PhotonIntro",this);
                    _isConnected = true;
            }
            if (GUI.Button(new Rect(110, 5, 100, 20), "Send") && _photonServer.Status.Equals("Connected"))
            {
                    _photonServer.SendOperation2();
            }
            GUI.Label(new Rect(5, 30, 100, 20), _photonServer.Status);
    }
    public void DebugMessage(string message)
    {
            Debug.Log(message);
    }
}


Скрипт PhotonServer.cs(клиент):
using ExitGames.Client.Photon;
using System.Collections.Generic;
public class PhotonServer :IPhotonPeerListener{
    public string Status { get; set; }
    PhotonPeer _peer;
    Login _login;
    public PhotonServer()
    {
            Status = "Disconnected";
    }
    public void DebugReturn(DebugLevel level, string message)
    {
           
    }
    public void OnEvent(EventData eventData)
    {
            switch (eventData.Code)
            {
                    case 1:
                            if (eventData.Parameters.ContainsKey(1))
                            {
                                    _login.DebugMessage("recv event:" + eventData.Parameters[1]);
                            }
                            break;
                    default:
                            _login.DebugMessage("Unknown Event:" + eventData.Code);
                            break;
            }
    }
    public void OnOperationResponse(OperationResponse operationResponse)
    {
            switch (operationResponse.OperationCode)
            {
                    case 1:
                            if (operationResponse.Parameters.ContainsKey(1))
                            {
                                    _login.DebugMessage("recv:" + operationResponse.Parameters[1]);
                            }
                            break;
                    default:
                            _login.DebugMessage("Unknown OperationResponse:" + operationResponse.OperationCode);
                            break;
            }
    }
    public void OnStatusChanged(StatusCode statusCode)
    {
            switch (statusCode)
            {
                    case StatusCode.Connect:
                            Status = "Connected";
                            break;
                    case StatusCode.Disconnect:
                    case StatusCode.DisconnectByServer:
                    case StatusCode.DisconnectByServerLogic:
                    case StatusCode.DisconnectByServerUserLimit:
                    case StatusCode.TimeoutDisconnect:
                            Status = "Disconnected";
                            break;
                    default:
                            Status = "Unknown";
                            break;
            }
    }
    public void Init(PhotonPeer peer, string serverAddress, string applicationName,Login login)
    {
            _peer = peer;
            _peer.Connect(serverAddress, applicationName);
            _login = login;
    }
    public void Disconnect()
    {
            _peer.Disconnect();
    }
    public void Update()
    {
            _peer.Service();
    }
    public void SendOperation()
    {
            _peer.OpCustom(1, new Dictionary<byte, object> { { 1, "send message" } }, false);
    }
    public void SendOperation2()
    {
            _peer.OpCustom(2, new Dictionary<byte, object> { { 1, "send message for event" } }, false);
    }
}


А дальше только гемор, бессонные ночибезопасность в уроке 6.

8 комментариев

avatar
Как можно подружить этот сервер и приложение unity3d?
Допустим клиент просто отсылает нажатия клавиш, серверу надо проверить можно ли дяде Васе сделать шаг или перед ним стена.
Писать в файл, а в unity читать?) Бред.
avatar
public void SendOperation()
    {
            _peer.OpCustom(1, new Dictionary<byte, object> { { 1, "send message" } }, false);
    }

Делаешь вот такие операции, отправляешь на сервер. На сервере обрабатываешь… Что тут не понятно?
avatar
Про обмен я давно понял, обработка проблемы вызывает.
Откуда сервер узнает, что дяде Васе нельзя сделать шаг?
Доверять пользователю не вариант.
avatar
Это уже называется серверный обсчет: проверка коллизий, ГЕО проверка(проверка местности, напрмиер, может ли игрок находится в текущих координатах), обсчет ИИ(Искусственный интелект) NPC…
avatar
Очень понравилось!!!
Жаль что только 5 уроков
Ждем продолжения, спасибо автору.
avatar
упс… нашел 6 ой урок
avatar
Как можно отправить event только некоторым подключившимся, а не всем?
avatar
Насколько я помню, есть перегрузка метода SendEvent, в которой один из параметров принимает список получателей…
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.