zoukankan      html  css  js  c++  java
  • ET5 MailBoxComponent 简单介绍

    根据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

                

     

     
  • 相关阅读:
    【云计算奇妙学习之旅】第一期:初识云计算
    手撸平衡二叉树!保证讲懂平衡过程!
    复习一下各种排序算法
    CSAPP实验——DataLab
    信息的表示和处理(整数部分)
    实现一个简单的解释器(6)
    实现一个简单的解释器(5)
    实现一个简单的解释器(4)
    实现一个简单的解释器(3)
    实现一个简单的解释器(2)
  • 原文地址:https://www.cnblogs.com/cj8988/p/14487463.html
Copyright © 2011-2022 走看看