private async static ETTask RealmToGate(Session session, User user, R2C_Authentication response, bool isRefreshToken)
        {
            // 隨機分配GateServer
            StartConfig config = Game.Scene.GetComponent <RealmGateAddressComponent>().GetAddress();

            // Log.Debug($"gate address: {MongoHelper.ToJson(config)}");
            IPEndPoint innerAddress = config.GetComponent <InnerConfig>().IPEndPoint;
            Session    gateSession  = Game.Scene.GetComponent <NetInnerComponent>().Get(innerAddress);
            //Game.Scene.GetComponent<PingComponent>().RemoveSession(session.Id);

            // 向Gate請求一個Key,Client可以拿這個Key連接Gate
            G2R_GetLoginKey g2RGetLoginKey = (G2R_GetLoginKey)await gateSession.Call(new R2G_GetLoginKey()
            {
                Uid = user.Id
            });

            string outerAddress = config.GetComponent <OuterConfig>().Address2;

            // 創造權杖
            if (isRefreshToken)
            {
                SignInCryptographyHelper.Token tok = new SignInCryptographyHelper.Token
                {
                    uid = user.Id,
                    lastCreateTokenAt = user.lastCreateTokenAt,
                    salt = user.salt,
                };

                string token = SignInCryptographyHelper.EncodeToken(tok);
                response.Token = token;
            }

            PlayerRideTotalInfo playerRideTotalInfo = await UserDataHelper.QueryUserRideAllRecord(user);

            response.Error   = ErrorCode.ERR_Success;
            response.Address = outerAddress;
            response.Key     = g2RGetLoginKey.Key;
            response.Data    = new PlayerBaseInfo
            {
                Uid      = user.Id,
                Name     = user.name,
                Sex      = user.gender,
                Location = user.location,
                Height   = user.height,
                Weight   = user.weight,
                Birthday = user.birthday,
                CreateAt = user.createAt,
                // 校時用
                LastOnlineAt = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
                CharSetting  = user.playerCharSetting,
                TotalInfo    = playerRideTotalInfo,
                Language     = user.language,
            };
            response.LinkTypes.Clear();
            response.LinkTypes.AddRange(await GetAllLinkType(user.Id));
        }
        private static async void SaveUserAndBroadcastTarget(MapUnit mapUnit, User user, BsonDocument log)
        {
            await UserDataHelper.UpsertUser(user, DBLog.LogType.UpdateUserRideTotalRecord, log);

            // 如果玩家在線上 告知該玩家異動紀錄
            var    proxy      = Game.Scene.GetComponent <CacheProxyComponent>();
            var    playerSync = proxy.GetMemorySyncSolver <Player>();
            Player selfPlayer = playerSync.Get <Player>(mapUnit.Uid);

            if (selfPlayer != null)
            {
                PlayerRideTotalInfo playerRideTotalInfo = await UserDataHelper.QueryUserRideAllRecord(user);

                G2C_UpdatePlayerRideTotalInfo g2c_UpdatePlayerRideInfo = new G2C_UpdatePlayerRideTotalInfo()
                {
                    TotalInfo = playerRideTotalInfo,
                };
                GateMessageHelper.BroadcastTarget(g2c_UpdatePlayerRideInfo, mapUnit.Uid);
            }
        }