/// <summary>
        /// 查詢使用者的所有關係,包含User的基礎資料
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public static async ETTask <List <RelationshipSimpleInfo> > GetUserRelationshipSimpleInfoList(long uid)
        {
            var relations = await GetUserRelationshipList(uid);

            var relationDict = relations.ToDictionary(e => e.targetUid, e => e);
            var users        = await UserDataHelper.FindUsers(relations.Select(e => e.targetUid).ToArray());

            return(users.Select(user =>
            {
                Relationship rel = null;
                RelationshipSimpleInfo info = new RelationshipSimpleInfo();
                info.Name = user.name;
                info.Location = user.location;
                info.Mileage = user.playerRideTotalInfo.Mileage;
                info.Uid = user.Id;
                info.DisconnectTime = 0;
                if (relationDict.TryGetValue(user.Id, out rel))
                {
                    info.RelationshipType = rel.relationshipType;
                }
                else
                {
                    info.RelationshipType = (int)Relationship.RelationType.Stranger;
                }
                return info;
            }).ToList());
        }
        /// <summary>
        /// 用name做模糊查詢非好友的清單
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="queringUids"></param>
        /// <returns></returns>
        public static async ETTask <RepeatedField <RelationshipSimpleInfo> > QueryLikeName(long uid, string userName, int count = 100)
        {
            if (string.IsNullOrEmpty(userName))
            {
                return(new RepeatedField <RelationshipSimpleInfo>());
            }

            // 先查詢自己的關係
            var relations = await GetUserRelationshipList(uid);

            var excludes = relations.Select(e => e.targetUid).ToList();

            // 排除自己
            excludes.Add(uid);

            // 排除已申請的玩家
            var relationApplyInfSenders = await GetRelationshipApplyInfoBySenderUid(uid);

            for (int i = 0; i < relationApplyInfSenders.Count; i++)
            {
                excludes.Add(relationApplyInfSenders[i].ReceiverUid);
            }

            // 排除向自己申請的玩家
            var relationApplyInfoReceivers = await GetRelationshipApplyInfoByReceiverUid(uid);

            for (int i = 0; i < relationApplyInfoReceivers.Count; i++)
            {
                excludes.Add(relationApplyInfoReceivers[i].SenderUid);
            }

            // (?i)表示忽略大小寫
            List <User> users = await UserDataHelper.FindUsers(e =>
                                                               !excludes.Contains(e.Id) && Regex.IsMatch(e.name, $"(?i){userName}")
                                                               , 0, count);

            return(users.Aggregate(new RepeatedField <RelationshipSimpleInfo>(), (list, user) =>
            {
                RelationshipSimpleInfo info = new RelationshipSimpleInfo();
                info.Name = user.name;
                info.Location = user.location;
                info.Mileage = user.playerRideTotalInfo.Mileage;
                info.Uid = user.Id;
                info.DisconnectTime = 0;
                info.RelationshipType = (int)Relationship.RelationType.Stranger;
                list.Add(info);
                return list;
            }));
        }
        /// <summary>
        /// 用uids查詢非好友的清單
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="queringUids"></param>
        /// <returns></returns>
        public static async ETTask <RepeatedField <RelationshipSimpleInfo> > QueryByUids(long uid, params long[] queringUids)
        {
            // 先查詢自己的關係
            var relations = await GetUserRelationshipList(uid);

            var excludes = relations.Select(e => e.targetUid).ToList();

            // 排除自己
            excludes.Add(uid);

            // 排除已申請的玩家
            var relationApplyInfSenders = await GetRelationshipApplyInfoBySenderUid(uid);

            for (int i = 0; i < relationApplyInfSenders.Count; i++)
            {
                excludes.Add(relationApplyInfSenders[i].ReceiverUid);
            }

            // 排除向自己申請的玩家
            var relationApplyInfoReceivers = await GetRelationshipApplyInfoByReceiverUid(uid);

            for (int i = 0; i < relationApplyInfoReceivers.Count; i++)
            {
                excludes.Add(relationApplyInfoReceivers[i].SenderUid);
            }

            // 用差集過濾下
            var finds = queringUids.Except(excludes);

            List <User> users = await UserDataHelper.FindUsers(finds.ToArray());

            return(users.Aggregate(new RepeatedField <RelationshipSimpleInfo>(), (list, user) =>
            {
                RelationshipSimpleInfo info = new RelationshipSimpleInfo();
                info.Name = user.name;
                info.Location = user.location;
                info.Mileage = user.playerRideTotalInfo.Mileage;
                info.Uid = user.Id;
                info.DisconnectTime = 0;
                info.RelationshipType = (int)Relationship.RelationType.Stranger;
                list.Add(info);
                return list;
            }));
        }
        /// <summary>
        /// 根據筆數跟偏移,尋找跟自己沒有關係的人們
        /// 回傳資料集合跟DB表的總長度
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="skip"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public static async ETTask <Tuple <List <RelationshipSimpleInfo>, long> > GetStrangers(long uid, long skip = 0L, long limit = getStrangerLimitCount)
        {
            var relations = await GetUserRelationshipList(uid);

            var excludes = relations.Select(e => e.targetUid).ToList();

            // 排除自己
            excludes.Add(uid);

            // 排除已申請的玩家
            var relationApplyInfSenders = await GetRelationshipApplyInfoBySenderUid(uid);

            for (int i = 0; i < relationApplyInfSenders.Count; i++)
            {
                excludes.Add(relationApplyInfSenders[i].ReceiverUid);
            }

            // 排除向自己申請的玩家
            var relationApplyInfoReceivers = await GetRelationshipApplyInfoByReceiverUid(uid);

            for (int i = 0; i < relationApplyInfoReceivers.Count; i++)
            {
                excludes.Add(relationApplyInfoReceivers[i].SenderUid);
            }

            List <User> users = await UserDataHelper.FindUsers(entity => !excludes.Contains(entity.Id), skip, limit);

            long totalCount = await dbProxy.QueryCount <User>(entity => !excludes.Contains(entity.Id));

            List <RelationshipSimpleInfo> list = users.Select(user =>
            {
                RelationshipSimpleInfo info = new RelationshipSimpleInfo();
                info.Name             = user.name;
                info.Location         = user.location;
                info.Mileage          = user.playerRideTotalInfo.Mileage;
                info.Uid              = user.Id;
                info.DisconnectTime   = 0;
                info.RelationshipType = (int)Relationship.RelationType.Stranger;
                return(info);
            }).ToList();

            return(new Tuple <List <RelationshipSimpleInfo>, long>(list, totalCount));
        }
        private async ETTask RunAsync(Player player, C2L_RemoveRelationship message, Action <L2C_RemoveRelationship> reply)
        {
            L2C_RemoveRelationship response = new L2C_RemoveRelationship();

            try
            {
                long uid = player.uid;
                await RelationshipDataHelper.RemoveRelationship(uid, message.Uid);

                response.Error = ErrorCode.ERR_Success;
                reply(response);
                L2C_NotifyRelationshipState notifyRelationshipState = new L2C_NotifyRelationshipState();
                RelationshipSimpleInfo      info = new RelationshipSimpleInfo();
                {
                    info.Uid = uid;
                }
                notifyRelationshipState.Info = info;
                GateMessageHelper.BroadcastTarget(notifyRelationshipState, message.Uid);
            }
            catch (Exception e)
            {
                ReplyError(response, e, reply);
            }
        }