ET框架---ClientDispatcher学习笔记
2018-04-07 23:11
302 查看
ClientDispatcher学习笔记
请大家关注我的微博:@NormanLin_BadPixel坏像素public class ClientDispatcher: IMessageDispatcher { // 热更层消息回调 public Action<Session, PacketInfo> HotfixCallback; public void Dispatch(Session session, PacketInfo packetInfo) { if (OpcodeHelper.IsClientHotfixMessage(packetInfo.Opcode)) { HotfixCallback.Invoke(session, packetInfo); return; } Type messageType = Game.Scene.GetComponent<OpcodeTypeComponent>().GetType(packetInfo.Opcode); IMessage message = (IMessage)session.Network.MessagePacker.DeserializeFrom(messageType, packetInfo.Bytes, packetInfo.Index, packetInfo.Length); // 如果是帧同步消息,交给ClientFrameComponent处理 FrameMessage frameMessage = message as FrameMessage; if (frameMessage != null) { Game.Scene.GetComponent<ClientFrameComponent>().Add(session, frameMessage); return; } // 普通消息或者是Rpc请求消息 MessageInfo messageInfo = new MessageInfo(packetInfo.RpcId, packetInfo.Opcode, message); Game.Scene.GetComponent<MessageDispatherComponent>().Handle(session, messageInfo); } }
我们先看看普通的消息是怎么处理的。传入的参数是Session跟PacketInfo,这在我们之前都讲过了。在Seesion学习笔记里有。
我们知道,通过网络传过来的消息在接收过来后会被封装成PacketInfo,这里,我们需要对PacketInfo进行解析,获取到里面的消息。之前怎么打包的,我们也就怎么解包。先是通过Opcode获取到消息的类型,根据类型再反序列换为IMessage相对应的派生类,所有的消息都会继承这个类。
// 如果是帧同步消息,交给ClientFrameComponent处理
因为如果是帧同步消息,则需要根据帧同步决定它什么时候被处理,所以我们把它传给ClientFrameComponent,这个我们之前也讲过哦。
而如果是普通消息或者是Rpc请求消息,我们需要立马对其进行处理。先是根据消息内容创建MessageInfo,然后直接交给MessageDispatherComponent处理。这里我们也知道为什么在3.0里把MessageDispatherComponent移除了热更新消息的调度,因为热更的消息在3.0根本就不会传入MessageDispatherComponent,而是在HotfixCallback里调用。而热更新的消息则会传入HotfixMessageDispatcher,因为热更的消息有自己的一套OpcodeTypeComponent和MessageDispatherComponent。
HotFix的OpcodeTypeComponent
HotFix的OpcodeTypeComponent跟Model的相差无几,但是在储存Opcode的时候,把有MEssageAttribute特性的类存入了ProtoBuf.PType。这个类,在原生Protobuf-net中是没有的。它用自己的CreateInstance取代了原生Protobuf-net中的RuntimeTypeModel和TypeSerializer中的Activator.CreateInstance。为什么要这么做呢?为什么呢?我也很疑惑,所以去问了,不过大概是周末,大家都不在,没有人为我解惑。所以我就不断的去看,看这些代码的源头在哪,又是在什么地方被调用的。终于,功夫不负有心人,终于给我找着了,这里我就给大家解惑一下。(可花了我半个多小时!)
如上面介绍的,我们的消息会分为热更新消息和普通消息,但是不管是什么消息,我们都需要在Unity主程序层通过Protobuf-net反序列化成对应的类。反序列化其实就是根据一定结构的数据实例化一个类。但是,我们知道,在ILRuntime中的反射,是不允许我们直接实例化热更层的类的,而是要调用AppDomain来创建实例。这里是说明。所以为了区分需要反序列化的类是热更层dll中的还是Unity主程序的,引入了这个PType。
public static object CreateInstance(Type type){ if (Type.GetType (type.FullName) == null) { if (CreateInstanceFunc != null) { return CreateInstanceFunc.Invoke(type.FullName); } } return Activator.CreateInstance (type #if !(CF || SILVERLIGHT || WINRT || PORTABLE || NETSTANDARD1_3 || NETSTANDARD1_4) , nonPublic: true #endif ); }
通过这个方法创建实例,会判断是否属于热更层的类,如果是,则通过特殊的方法实例化,这里是ILRuntime的appDomain.Instantiate方法。否则,则通过普通的Activator.CreateInstance。
HotFix的MessageDispatherComponent
热更层的消息调度器跟Model层的差不多,也是获取热更层的程序集,找到里面有MessageHandlerAttribute特性的类,然后根据opcode注册里面的处理器。但是这里多了一个步骤,它会尝试注册到mono层。为什么还要注册到mono层呢?我的理解是,有些消息,可能需要mono层和热更层同时处理。瞎编个例子,一个移动的消息,我的位置变化可能写在mono层,是不变的,但是我的动画播放写在热更层,可能会变。而注册到mono层,则要通过中间层MessageProxy,这个其实就是用委托代理的方法让mono层调用热更层中的方法。相关文章推荐
- ET框架---ClientComponent学习笔记
- ET框架---HotFix.HotFix学习笔记
- ET框架---BundleDownloaderComponent学习笔记
- ET---TBuffer学习笔记
- Android 学习笔记之AndBase框架学习(二) 使用封装好的进度框,Toast框,弹出框,确认框...
- 基于SSH实现员工管理系统之框架整合篇 学习笔记
- xUtils3.0框架学习笔记分享
- C# Hadoop学习笔记(七)—C#的云计算框架借鉴(下)
- MyBatis 学习笔记之Logging -【使用日志框架是有根据顺序选择的】
- 学习ASP.NET MVC5框架揭秘笔记-ASP.NET MVC是如何运行的(三)
- ALSA声卡08_从零编写之框架_学习笔记
- php学习笔记(三十四)smarty框架的初步使用和注意事项
- 【应用篇】WCF学习笔记(一):Host、Client、MetadataExchage
- React Native学习笔记之--常用App框架的搭建(标签栏+导航栏)
- java安全框架-Shiro学习笔记(一)-入门小案例
- Python框架之Django学习笔记(十)
- Python爬虫框架Scrapy 学习笔记 10.3 -------【实战】 抓取天猫某网店所有宝贝详情
- yii框架学习笔记2
- hibernate框架学习笔记9:多对多关系案例
- jq框架封装学习笔记4-DOM操作模块