/// <summary>
        /// 加入房间
        /// </summary>
        /// <param name="self"></param>
        /// <param name="room"></param>
        /// <param name="matcher"></param>
        public static async void JoinRoom(this MatchComponent self, Room room, Matcher matcher)
        {
            //玩家加入房间,移除匹配队列
            self.Playing[matcher.UserID] = room.Id;
            self.MatchSuccessQueue.Enqueue(matcher);

            //向房间服务器发送玩家进入请求
            ActorProxy actorProxy = Game.Scene.GetComponent <ActorProxyComponent>().Get(room.Id);
            Actor_PlayerEnterRoom_Ack actor_PlayerEnterRoom_Ack = await actorProxy.Call(new Actor_PlayerEnterRoom_Req()
            {
                PlayerID  = matcher.PlayerID,
                UserID    = matcher.UserID,
                SessionID = matcher.GateSessionID
            }) as Actor_PlayerEnterRoom_Ack;

            Gamer gamer = GamerFactory.Create(matcher.PlayerID, matcher.UserID, actor_PlayerEnterRoom_Ack.GamerID);

            room.Add(gamer);

            //向玩家发送匹配成功消息
            ActorProxyComponent actorProxyComponent = Game.Scene.GetComponent <ActorProxyComponent>();
            ActorProxy          gamerActorProxy     = actorProxyComponent.Get(gamer.PlayerID);

            gamerActorProxy.Send(new Actor_MatchSucess_Ntt()
            {
                GamerID = gamer.Id
            });
        }
        public static void Broadcast(AActorMessage message, Unit[] units)
        {
            ActorProxyComponent actorProxyComponent = Game.Scene.GetComponent <ActorProxyComponent>();

            foreach (Unit unit in units)
            {
                long gateSessionId = unit.GetComponent <UnitGateComponent>().GateSessionId;
                actorProxyComponent.Get(gateSessionId).Send(message);
            }
        }
        protected override async void Run(Session session, G2M_PlayerEnterMatch message, Action <M2G_PlayerEnterMatch> reply)
        {
            M2G_PlayerEnterMatch response = new M2G_PlayerEnterMatch();

            try
            {
                MatchComponent      matchComponent      = Game.Scene.GetComponent <MatchComponent>();
                ActorProxyComponent actorProxyComponent = Game.Scene.GetComponent <ActorProxyComponent>();

                if (matchComponent.Playing.ContainsKey(message.UserID))
                {
                    //todo 重连逻辑
                    MatchRoomComponent matchRoomComponent = Game.Scene.GetComponent <MatchRoomComponent>();
                    long  roomId = matchComponent.Playing[message.UserID];
                    Room  room   = matchRoomComponent.Get(roomId);
                    Gamer gamer  = room.Get(message.UserID);

                    //重置GateActorID
                    gamer.PlayerID = message.PlayerID;

                    //重连房间
                    ActorProxy actorProxy = actorProxyComponent.Get(roomId);
                    await actorProxy.Call(new MH2MP_PlayerEnterRoom()
                    {
                        PlayerID  = message.PlayerID,
                        UserID    = message.UserID,
                        SessionID = message.SessionID
                    });

                    //向玩家发送匹配成功消息
                    ActorProxy gamerActorProxy = actorProxyComponent.Get(gamer.PlayerID);
                    gamerActorProxy.Send(new M2G_MatchSucess()
                    {
                        GamerID = gamer.Id
                    });
                }
                else
                {
                    //创建匹配玩家
                    Matcher matcher = MatcherFactory.Create(message.PlayerID, message.UserID, message.SessionID);
                }

                reply(response);
            }
            catch (Exception e)
            {
                ReplyError(response, e, reply);
            }
        }
        public override async void Destroy(SessionUserComponent self)
        {
            try
            {
                //释放User对象时将User对象从管理组件中移除
                Game.Scene.GetComponent <UserComponent>()?.Remove(self.User.UserID);

                StartConfigComponent config = Game.Scene.GetComponent <StartConfigComponent>();
                ActorProxyComponent  actorProxyComponent = Game.Scene.GetComponent <ActorProxyComponent>();

                //正在匹配中发送玩家退出匹配请求
                if (self.User.IsMatching)
                {
                    IPEndPoint matchIPEndPoint = config.MatchConfig.GetComponent <InnerConfig>().IPEndPoint;
                    Session    matchSession    = Game.Scene.GetComponent <NetInnerComponent>().Get(matchIPEndPoint);
                    await matchSession.Call(new G2M_PlayerExitMatch_Req()
                    {
                        UserID = self.User.UserID
                    });
                }

                //正在游戏中发送玩家退出房间请求
                if (self.User.ActorID != 0)
                {
                    ActorProxy actorProxy = actorProxyComponent.Get(self.User.ActorID);
                    await actorProxy.Call(new Actor_PlayerExitRoom_Req()
                    {
                        UserID = self.User.UserID
                    });
                }

                //向登录服务器发送玩家下线消息
                IPEndPoint realmIPEndPoint = config.RealmConfig.GetComponent <InnerConfig>().IPEndPoint;
                Session    realmSession    = Game.Scene.GetComponent <NetInnerComponent>().Get(realmIPEndPoint);
                await realmSession.Call(new G2R_PlayerOffline_Req()
                {
                    UserID = self.User.UserID
                });

                self.User.Dispose();
                self.User = null;
            }
            catch (System.Exception e)
            {
                Log.Trace(e.ToString());
            }
        }
        protected override async void Run(Session session, C2G_ReturnLobby_Ntt message)
        {
            //验证Session
            if (!GateHelper.SignSession(session))
            {
                return;
            }

            User user = session.GetComponent <SessionUserComponent>().User;
            StartConfigComponent config = Game.Scene.GetComponent <StartConfigComponent>();
            ActorProxyComponent  actorProxyComponent = Game.Scene.GetComponent <ActorProxyComponent>();

            //正在匹配中发送玩家退出匹配请求
            if (user.IsMatching)
            {
                IPEndPoint matchIPEndPoint = config.MatchConfig.GetComponent <InnerConfig>().IPEndPoint;
                Session    matchSession    = Game.Scene.GetComponent <NetInnerComponent>().Get(matchIPEndPoint);
                await matchSession.Call(new G2M_PlayerExitMatch_Req()
                {
                    UserID = user.UserID
                });

                user.IsMatching = false;
            }

            //正在游戏中发送玩家退出房间请求
            if (user.ActorID != 0)
            {
                ActorProxy actorProxy = actorProxyComponent.Get(user.ActorID);
                await actorProxy.Call(new Actor_PlayerExitRoom_Req()
                {
                    UserID = user.UserID
                });

                user.ActorID = 0;
            }
        }