根据ET5文档介绍,MailBoxComponent组件一般与Actor搭配使用,挂载该组件后,就可以通过Actor发送消息。
官方demo主要有两种使用方式:
session.AddComponent<MailBoxComponent, string>(MailboxType.GateSession);
await unit.AddComponent<MailBoxComponent>().AddLocation();
await unit.AddComponent<MailBoxComponent>()
1、这里拆分一下服务端的实体(客户端):
玩家在客户端有Player和Unit:Player有id,只有一个自己。Unit会有多个,自己和其他人。
玩家在服务端:
Realm:只负责注册,查询和验证等功能,不会有长链接的相关处理
Gate:在网关上有Player实体:有IId,Account和UnitId--关联Map服的Unit实体。Player绑定了Session。
Map:玩家在Map服务器上有Unit实体有唯一ID,挂载UnitGateComponent组件关联GateSessionId。
2、客户端,各服务器都是不同的端,都不在一台设备上。只是用相同的UnitID,分别在这些端创建Player和Unit实例,实例上存着需要的id号来识别谁是谁和找到连接session。
session就是在不同端建立的持续通信的连接。
Client与Gate通信,网关上存着Player绑定了session,有UnitID就能找到连接session进行通信。
服务端之间,你可以在每个服务端定义一个构建和获取与其它服务端的连接session的方法。
非网关服务器=》客户端,可以用ActorId,构建ActorMessageSender通信。
3、举例看看
在InnerMessageDispatcher中添加注释,方便查看内网中的Actor消息传递 HandleIActorMessage函数中:Log.Info("InnerMessageDispatcher内网消息转发:" + message.ActorId + "---" + entity);
3.1:Gate服务器不处理消息,直接转发消息:
注意:C2G_LoginGateHandler中 session.AddComponent<MailBoxComponent, string>(MailboxType.GateSession);当其他服务器消息发送到Gate的Session上时,消息会自动转发给前端,Gate服务器不会有相应的Handler处理该信息。
1、先注释寻路消息:G2M_CreateUnitHandler 中注释掉 await unit.AddComponent<MailBoxComponent>().AddLocation();
编译运行,
参考前端,有小人出现。说明创建小人消息发送到了前端,
3.2:Gate服务器处理消息--不直接转发。
1、调整代码 C2G_LoginGateHandler ,给Player添加个MailBox组件。
Player player = ComponentFactory.Create<Player, string>(account); player.AddComponent<MailBoxComponent>(); //新加入的代码 Game.Scene.GetComponent<PlayerComponent>().Add(player); session.AddComponent<SessionPlayerComponent>().Player = player; session.AddComponent<MailBoxComponent, string>(MailboxType.GateSession);
2、在Gate服务器中添加一个消息处理Handler
using System.Threading.Tasks; using ETModel; namespace ETHotfix { [ActorMessageHandler(AppType.Gate)] public class Actor_MatchSucess_NttHandler: AMActorHandler<Player, Actor_MatchSucess_Ntt> { protected override async ETTask Run(Player entity, Actor_MatchSucess_Ntt message) { Log.Info($"-------收到Map服务器发送的Actor消息---玩家{entity.Id}收到消息---:" + message.GamerID); await Task.CompletedTask; } } }
3、在内网中添加信息 InnerMessage.proto
在InnerMessage.proto中添加 message Actor_MatchSucess_Ntt // IActorMessage { int32 RpcId = 90; int64 ActorId = 94; int64 GamerID = 1; }
4、在Map中向Gate的Player中发送消息。G2M_CreateUnitHandler 中添加代码。
注意:这个添加的代码,ActorMessageSender 发送消息时往Player中发送,不是Session中。
await unit.AddComponent<MailBoxComponent>().AddLocation(); unit.AddComponent<UnitGateComponent, long>(request.GateSessionId); Game.Scene.GetComponent<UnitComponent>().Add(unit); response.UnitId = unit.Id; /**********添加测试代码 ********/ //测试给Gate服务器发送Actor消息 // 注意,Gate中Player必须 await player.AddComponent<MailBoxComponent>().AddLocation(); ActorMessageSenderComponent actorLocationSenderComponent = Game.Scene.GetComponent<ActorMessageSenderComponent>(); //这里是发送到Session实体,会直接转发到前端--需要调整Actor_MatchSucess_Ntt,OuterMessage.proto中添加消息体 // ActorMessageSender actorMessageSender = actorLocationSenderComponent.Get(request.GateSessionId); //这里是发送到Player,Gate有相关Handler处理,不会直接转发 ActorMessageSender actorMessageSender = actorLocationSenderComponent.Get(request.PlayerId); actorMessageSender.Send(new Actor_MatchSucess_Ntt(){GamerID = 32435}); /**********添加测试代码 ********/
5、编辑运行
4、总结
同样是Actor消息,有的是发送给Gate,有的是发送给前端。其实都是发送给了Gate,当信息发送给Session时,Gate会直接转发给前端,因为Session挂载MailBox时添加了MailBoxType.GateSession类型,使用会直接转发。Player挂载MailBox时,没有加类型,使用会转发到相关Handler里进行处理。
至于Player挂载MailBox两种方式 player.AddComponent<MailBoxComponent>(); 和 await player.AddComponent<MailBoxComponent>().AddLocation(); 个人理解:后面加AddLocation,会将实体加入到Location服务器中,方便发送 IActorLocationMessage 这种带 Location的消息--这种消息可能会在Location服务器中查询用户。
所以不论多少个端,Client,Gate,Map,Realm,只是在每个端都创建了同样UnitId的Player实例,和用同样UnitD创建的Unit实例,每一个玩家就像在每个端都有分身或影子,玩家的分身之间把消息传来传去,改变着玩家的状态。
另外,各类服务器(主要指map)也可以通过网关上客户端与网关的session连接,给一群玩家的本尊客户端广播消息。
注:Realm只需要认证账号,不需要分身
Demo中的这几大实例id,就是几种实体(Entity)的InstanceId
Player,Session,Unit
- actorsender在构建时,传入一个实体的实例id,就可以给这个实体的实例发消息,不论他在哪个服务器。--例子中player加MailBox
- 只要有session,player,unit 的实例id就能给他们发actor消息。
- 而通过session的实例id给用户的网关session发actor消息,session会给你转发给客户端(用户的网关sesion正是网关与客户端的连接session)。
参考内容:https://www.taikr.com/course/1053/task/30966/show
https://github.com/egametang/ET/blob/master/Book/5.4Actor%E6%A8%A1%E5%9E%8B.md
https://www.lfzxb.top/etbook/#54-actor%E6%A8%A1%E5%9E%8B