Photon服务器进阶&一个新游戏的出产(二)

继续上个文章说~

接收其他人发过来的广播,在OnEvent中进行响应

比如说接收过来加入的消息

    public void OnEvent(EventData eventData)
    {
        Debug.Log("触发了事件:" + eventData.ToStringFull());
        //处理服务器转发回来的事件
        switch (eventData.Code)
        {
            case LiteEventCode.Join:
                int actorNr = (int)eventData.Parameters[LiteEventKey.ActorNr];
                Debug.Log("玩家的编号为:" + actorNr);
                break;
        }
    }

这个消息是系统给的所以能用在LiteEventKey中的Code,而我们要传自定义的数据要怎么弄呢

case (byte)OpCodeEnum.getTag:
        Hashtable Message = (Hashtable)eventData.Parameters[LiteEventKey.Data];
        int tag = (int)Message[(byte)OpKeyEnum.tag];
        break;

OpCodeEnum和OpKeyEnum都是我自定义的枚举,而我们自定义的数据就存在LiteEventKey.Data中,这还没玩,这只是我们传输的哈希表,而真正的数据放在这个哈希表里。

而OnOperationResponse中的数据处理,和以前的还是一样的。这里就不进行讲解了。

说一下一个比较困扰的问题吧,对于指定群发。这回我们不用Lite方式,自己写一个指定群发。

博主这里有两种方法供参考,如有更牛逼的方法请多多指教。同时也是第二种Peer的进阶使用

先说第一种比较容易理解的。

当一个玩家连入服务器的时候就会在Application中新建一个Peer,这样看来,Application是掌管全局的。这样我们就可以用一个字典将每个Peer记录,来进行简单的群发操作。代码如下加在Application中

        public Dictionary<int, MyPeer> Peer = new Dictionary<int, MyPeer>();

        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            //建立连线并回传给Photon Server

            MyPeer mypeer = new MyPeer(initRequest.Protocol, initRequest.PhotonPeer);
            Peer.Add(mypeer.ConnectionId, mypeer);
            return mypeer;
        }

        public void radioEvent()
        {
            OperationResponse or = new OperationResponse();
            foreach (MyPeer mypeer in Peer.Values)
            {
                or.ReturnCode = 0; 
                or.DebugMessage = ""; //返回消息
                or.OperationCode = (byte)OpCodeEnum.Login; //编码
                mypeer.SendOperationResponse(or, new SendParameters());
            }
        }

现在我们来看看第二种方法,在用第一种方法的时候会发现一个问题,我们怎么向Lite一样,分房间。指定广播(如果有人能解决这个问题谢谢分享),还有怎客户端发送消息给服务器的时候是在Peer端进行处理的,然而怎么调用Application端的群发也是个问题。

我用下面的方法来解决:

namespace Chat
{
    public class ChatPeer : PeerBase
    {
        private static readonly object syncRoot = new object();

        public ChatPeer(IRpcProtocol protocol,IPhotonPeer unmanagedPeer) : base(protocol, unmanagedPeer)
        {
            lock (syncRoot)
            {
                BroadcastMessage += this.OnBroadcastMessage;
            }
        }

        private static event Action<ChatPeer, EventData, SendParameters> BroadcastMessage;

        protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
        {
            lock (syncRoot)
            {
                BroadcastMessage -= this.OnBroadcastMessage;
            }
        }

        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            var @event = new EventData(1) { Parameters = operationRequest.Parameters };
            lock (syncRoot)
            {
                BroadcastMessage(this, @event, sendParameters);
            }

            var response = new OperationResponse(operationRequest.OperationCode);
            this.SendOperationResponse(response, sendParameters);
            
        }

        private void OnBroadcastMessage(ChatPeer peer, EventData @event, SendParameters sendParameters)
        {
            if (peer != this)
            {
                this.SendEvent(@event, sendParameters);
            }
        }

    }
}

首先是一个Action委托(不知道委托是什么意思的可以百度一下)

private static event Action<ChatPeer, EventData, SendParameters> BroadcastMessage; // 静态让他常驻内存

Peer被创建的同时将一个OnBriadcastMessage的委托给BrioadcastMessage

当服务器收到客户端发来的群发消息时,启用委托

BroadcastMessage(this, @event, sendParameters);

将在BroadcastMessage中的委托都执行一遍,通过

if (peer != this) { this.SendEvent(@event, sendParameters); }

来控制给谁群发。很强大的方法。貌似是官方的Demo。

原文地址:https://www.cnblogs.com/SHOR/p/5400766.html