8-登录流程
在AppStartInitFinish_CreateLoginUI.初始化后,执行Login界面的初始化
登录面板逻辑:UILoginComponentSystem,针对组件UILoginComponent创建的System
登录面板逻辑:UILoginComponent
逻辑层: LoginHelper中的clientSenderComponent.LoginAsync()是整个连接的过程。
网络层:ClientSenderComponentSystem使用Call(xxx)发送网络消息 Main2NetClient_Login()
找到消息的处理类,一般为(网络消息名字)_Handler,如Main2NetClient_LoginHandler,需要继承
MessageHandler(网络消息处理基类),并且带有请求的网络消息与回复的网络消息,并且带有
[MessageHandler(SceneType.NetClient)],在Run()函数中,做了如下事情:
1-移除并添加与初始化RouterAddressComponent(路由地址组件),在ConstValue中设置的连接ip与端口,并通过路由地址组件获取realm地址,
2-添加NetComponent(网络组件),并创建session,通过session.Call()发送网络消息,它的返回值就是回复的网络消息(异步)
3-创建gateSession,连接网关服务器,后续与游戏服务器通讯的时候,都是使用这个GateSession,使用gateSession的Call(),来向网关服务器请求登录。
这里只配置了一台Realm服务器,在正式部署时,为了分散性能压力,会配置多台,获取Reaml地址时,就会有多个地址。
服务端如何处理gateSession的Call()呢?还是通过找网络消息名字_handler,有C2R_Login则找C2R_LoginHandler,在Run(xxx)中,做了如下的事情
1-随机分配一个Gate
2-向gate请求一个key,客户端可以拿着这个key连接gate
3-将拿到的key写在回复的消息R2C_Login中
4-释放session
C2R_LoginHandler : MessageSessionHandler<C2R_Login, R2C_Login>,游戏客户端session与服务端的session是两个session。
MessageSessionHandler与MessageHandler如何区分使用?
跟消息是不是使用了ISessionRequest接口有关,如果使用了,则要使用MessageSessionHandler。
FiberInit_Realm文件中,有一个分发逻辑(类似虚函数),Invoke()类似与时间发布,但是不同的是,
1- Invoke类似函数,必须有被调用方,否则异常,调用者跟被调用者属于同一模块,比如MoveComponent中的Timer计时器,调用跟被调用的代码均属于移动模块
2- 既然Invoke跟函数一样,那么为什么不使用函数呢? 因为有时候不方便直接调用,比如Config加载,在客户端跟服务端加载方式不一样。比如TimerComponent需要根据Id分发
3- 注意,不要把Invoke当函数使用,这样会造成代码可读性降低,能用函数不要用Invoke
4- publish是事件,抛出去可以没人订阅,调用者跟被调用者属于两个模块,比如任务系统需要知道道具使用的信息,则订阅道具使用事件
在C2R_LoginHandler来判定账号与密码的合法性,然后获取数据库组件:
DBComponent dbComponent = session.Root().GetComponent().GetZoneDB(session.Zone);
在FiberInit_Realm中添加数据库管理组件
root.AddComponent();然后调用语句开始查询,访问其他属性的变量需要使用FriendOf(xxx )
在Config/StartZoneConfig中,配置的是有关区(zone)的信息,在session.Zone()取到的值也是这里填的区ID,配置中也有关于数据库的配置,一个区一个数据库,
使用协程锁避免同个账号的写入问题。
// 挂上这个组件,5秒就会删除session,所以客户端验证完成要删除这个组件。该组件的作用就是防止外挂一直连接不发消息也不进行权限验证
session.AddComponent();
PlayerComponent 用于管理player实体,
MailBoxComponent 增加后就拥有处理网络消息的能力,根据增加时候设定的参数,就能处理参数类型的网络消息,并不是所有的消息都能处理。
SessionPlayerComponent 与PlaySessionComponent 区别与关系,相互记录,完成一一映射的关系,可以通过Player找到session,也可以通过session找到Player:
session.GetComponent().Player.
session有过期的情况,所以经常会出现覆盖的情况。
EnterMapHelper里面有进入到另一个地图的步骤 1- 发送进入地图请求 2- 等待场景切换完成 3-发布进入地图的事件
处理进入地图的方法:C2G_EnterMapHandler,模拟地图传送的逻辑,先创建一个虚拟地图,登录后传送过去。
步骤:1-在player上加一个GateMapComponent,创建临时MapScene并赋值给GateMapComponent上的Scene上。2-从DB中加载数据,创建Unit映射对象实体到刚才创建的GateScene中 3- 传送到登录的场景中去。TransferHelper.TransferAtFrameFinish()。也就是说在player身上加了一个GateMapComponent组件,在该组件上创建了一个gateMap场景,然后在这个场景上添加Unit映射对象,然后传送过去。
传送会等待一帧在执行,在当前这帧,会回到EnterMapHelper中,等待场景切换完成(就是等待传送的这一帧执行完毕-使用objectWait类),
传送前需要锁定,Unit实体如果在传送的状态,无法就行其他的操纵。
传送函数的步骤(Transfer(xxx)):1-获取需要传送单元当前的场景 2-创建一个传送的消息并赋上对应的参数(位置id-ActoriId,对象序列化数据,以及它身上所有的实现了ITrandfer接口的组件的序列化数据).3-原单元对象释放,4-锁住改单元并且发送请求,锁住是为了避免在传送过程中再对对象进行操作。
ActorId是位置id,由进程id,场景id,实体id生成一个对应的id,
M2M_UnitTransferRequestHandler类是处理接收对象的类(M2M是mapToMap的意思),步骤如下:
1-重新创建Unit对象。从request中的数据反序列化一个对象,同时反序列化这个单元实现了ITransfer接口的组件,给这个unit添加移动与寻路组件,并设置它的初始位置,同时添加MailBoxComponent组件用来通讯,
2-在场景中获取一个单位组件(UnitComponent)并将反序列化的单元加载该组件上。
3-发送一个场景已经改变的网络消息M2C_StartSceneChange (M2C是MapToClient的意思)
4-加入AOI组件,用来处理多人同屏的相关逻辑。
5-通知Locaition定位服务器,解锁发送时的锁。
如果Unit没有附加在组件上进行管理,那么就会造成内存泄漏永远不能回收,
M2C_StartSceneChangeHandler处理场景切换消息。
M2C_CreateMyUnitHandler 刚才发送消息的处理类。
AfterUnitCreate_CreateUnitView中是创建View层Unit的相关逻辑。