using System; using System.Collections.Generic; using UnityEngine; // 支持分页查询排行榜, 本服/跨服统一使用 参考QueryRankByPage 新封包 DTCA130_tagMCViewBillboardRet public class RankModel : GameSystemManager { public event Action onRankRefresh; //public event Action onMyRankRefresh; //排行榜滚动显示的最大数量 类型 Dictionary ranksShowMaxCnt = new Dictionary(); //分页查询 Dictionary queryRankCD = new Dictionary(); //首次查询CD,不影响后续的分页查询 //分页查询 排名索引按字段存储 1代表第一名 Dictionary> m_RankPageDatas = new Dictionary>(); //类型:ID -排名索引,通过ID进行排重删除 不同名次 同ID的数据 Dictionary> m_RankIDToIndex = new Dictionary>(); //监听排行榜显示名次,用于分页查询,第一页查询由外部触发 //使用场景 如界面排行榜滚动的时候每次查询30个排名名额,在显示大于m*30 +20名时,监听下一页,查询m+1页 int pageCnt = 20; //每页查询条数 int queryPointNum = 12; //查询点 int queryPageCD = 60; //内部查询点CD 避免不断上下滑动的时候过于频繁查询,外部使用重新打开的时候可以重置CD Dictionary queryPageTimes = new Dictionary(); //查询页CD Dictionary ranksServerMaxCnt = new Dictionary(); //服务器排行榜当前总数量(动态变化),分页查询的时候过滤用 public override void Init() { DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize; ParseConfig(); } public void OnBeforePlayerDataInitialize() { m_RankPageDatas.Clear(); m_RankIDToIndex.Clear(); queryRankCD.Clear(); } void ParseConfig() { var config = FuncConfigConfig.Get("BillboardSet"); ranksShowMaxCnt = ConfigParse.ParseIntDict(config.Numerical3); } public int GetRankShowMaxCnt(int type) { if (ranksShowMaxCnt.ContainsKey(type)) { return ranksShowMaxCnt[type]; } return 100; } public override void Release() { DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitialize; } void ReSetRankDataEx(RankData data, HA130_tagMCViewBillboardRet.tagMCViewBillboardData serverData, int type) { data.id = serverData.ID; data.id2 = (int)serverData.ID2; data.name1 = serverData.Name1.Trim().Replace("\0", ""); data.name2 = serverData.Name2.Trim().Replace("\0", ""); data.subType = serverData.Type2; data.value1 = serverData.Value1; data.value2 = serverData.Value2; data.value3 = serverData.Value3; data.value4 = serverData.Value4; data.value5 = serverData.Value5; data.value6 = serverData.Value6; data.value7 = serverData.Value7; data.value8 = serverData.Value8; data.cmpValue = serverData.CmpValue; data.cmpValue2 = serverData.CmpValue2; data.cmpValue3 = serverData.CmpValue3; data.userData = serverData.UserData; data.rank = serverData.Rank; data.type = type; data.index = serverData.Index; } #region 分页查询 //!!!本服分页查询使用说明 //1. QueryRankByPage:先查询第一页,startIndex = 0, count = 30, 在第一页查询前可以选择初始化ResetQueryParam //2. ListenRankPage:一般在滚动条OnRefreshCell监听排行榜显示名次,用于分页查询 // // startIndex 和 count 配对,与watchID无关联 // watchID; //查看指定ID名次前后,查询范围服务端已固定,如果只要查指定目标,count可以设置1减少附加信息 public void QueryRankByPage(int type, int startIndex = 0, int count = 20, int watchID = 0, bool forceQuery = false, int groupValue1 = 0, int groupValue2 = 0) { if (queryRankCD.ContainsKey(type) && !forceQuery) { if (Time.time - queryRankCD[type] < 2f) { return; } } var pak = new CA130_tagCMViewBillboard(); pak.Type = (byte)type; pak.GroupValue1 = (byte)groupValue1; pak.GroupValue2 = (uint)groupValue2; pak.StartIndex = (ushort)startIndex; //排名从0开始 pak.ViewCnt = (byte)count; pak.ViewID = (uint)watchID; GameNetSystem.Instance.SendInfo(pak); queryRankCD[type] = (int)Time.time; } public void ListenRankPage(int type, int index, int groupValue1 = 0, int groupValue2 = 0) { int page = index / pageCnt; if (index > page * pageCnt + queryPointNum) { if (queryPageTimes.ContainsKey(page) && Time.realtimeSinceStartup - queryPageTimes[page] < queryPageCD) return; if (ranksServerMaxCnt.ContainsKey(type)) { if(index >= ranksServerMaxCnt[type]) { //超过服务器已上榜的总数量,比如总榜单是100名,当前只有8名玩家上榜,往下滚动就不再查询 return; } } Debug.LogFormat("分页查询:{0} - {1}", index, page); QueryRankByPage(type, pageCnt * (page + 1), pageCnt, 0, true, groupValue1, groupValue2); queryPageTimes[page] = Time.realtimeSinceStartup; } } public void ResetQueryParam() { pageCnt = 20; queryPointNum = 12; queryPageCD = 60; queryPageTimes.Clear(); } public void SetQueryParm(int pageCnt, int queryPointNum, int queryPageCD) { this.pageCnt = pageCnt; this.queryPointNum = queryPointNum; this.queryPageCD = queryPageCD; queryPageTimes.Clear(); } //跨服排行榜信息 void ReSetRankData(RankData data, HA130_tagMCViewBillboardRet.tagMCViewBillboardData serverData, int type) { data.id = serverData.ID; data.id2 = (int)serverData.ID2; data.name1 = serverData.Name1.Replace("\0", ""); data.name2 = serverData.Name2.Replace("\0", ""); data.subType = serverData.Type2; data.value1 = serverData.Value1; data.value2 = serverData.Value2; data.value3 = serverData.Value3; data.value4 = serverData.Value4; data.value5 = serverData.Value5; data.value6 = serverData.Value6; data.value7 = serverData.Value7; data.value8 = serverData.Value8; data.cmpValue = serverData.CmpValue; data.cmpValue2 = serverData.CmpValue2; data.cmpValue3 = serverData.CmpValue3; data.userData = serverData.UserData; data.rank = serverData.Rank; data.index = serverData.Index; data.type = type; //与服务端一致的跨服排行榜类型,外部自行处理不同分组分赛季等情况 } //查询本服/跨服排行榜 public void ReceiveRankPagePackage(HA130_tagMCViewBillboardRet package) { int rankType = package.Type; //部分跨服排行榜同一个榜存在分组分区的情况 //赛区3位+赛季3位+排行榜类型3位 if (rankType == 165) //CrossServerOneVsOneRewardModel.rankType { rankType = (int)package.GroupValue1 * 1000000 + (int)package.GroupValue2 * 1000 + rankType; } if (!m_RankPageDatas.ContainsKey(rankType)) { m_RankPageDatas.Add(rankType, new Dictionary()); } //同ID排重删除 if (!m_RankIDToIndex.ContainsKey(rankType)) { m_RankIDToIndex.Add(rankType, new Dictionary()); } if (!ranksServerMaxCnt.ContainsKey(rankType)) { ranksServerMaxCnt.Add(rankType, package.DataTotal); } ranksServerMaxCnt[rankType] = package.DataTotal; for (int i = 0; i < package.PageDataCnt; i++) { int id = (int)package.PageDataList[i].ID; int orderIndex = (int)package.PageDataList[i].Rank; if (!m_RankIDToIndex[rankType].ContainsKey(id)) { m_RankIDToIndex[rankType][id] = orderIndex; } else if (m_RankIDToIndex[rankType][id] != orderIndex) { m_RankPageDatas[rankType].Remove(m_RankIDToIndex[rankType][id]); m_RankIDToIndex[rankType][id] = orderIndex; } } for (int i = 0; i < package.PageDataCnt; i++) { int orderIndex = (int)package.PageDataList[i].Rank; if (!m_RankPageDatas[rankType].ContainsKey(orderIndex)) { m_RankPageDatas[rankType][orderIndex] = new RankData(); } ReSetRankDataEx(m_RankPageDatas[rankType][orderIndex], package.PageDataList[i], rankType); } if (package.ViewID != 0) { //查询指定目标排名 for (int i = 0; i < package.ViewIDDataCnt; i++) { int id = (int)package.ViewIDDataList[i].ID; int orderIndex = (int)package.ViewIDDataList[i].Rank; if (!m_RankIDToIndex[rankType].ContainsKey(id)) { m_RankIDToIndex[rankType][id] = orderIndex; } else if (m_RankIDToIndex[rankType][id] != orderIndex) { m_RankPageDatas[rankType].Remove(m_RankIDToIndex[rankType][id]); m_RankIDToIndex[rankType][id] = orderIndex; } } for (int i = 0; i < package.ViewIDDataCnt; i++) { int orderIndex = (int)package.ViewIDDataList[i].Rank; if (!m_RankPageDatas[rankType].ContainsKey(orderIndex)) { m_RankPageDatas[rankType][orderIndex] = new RankData(); } ReSetRankData(m_RankPageDatas[rankType][orderIndex], package.ViewIDDataList[i], package.Type); } //onMyRankRefresh?.Invoke(package.Type); 同时查询没有单独返回数据,暂时不要这个事件 } onRankRefresh?.Invoke(package.Type); } //排名从1 开始 //如果是跨服排行榜 类型可能因跨服功能不同 由分组分赛季等情况组合 public Dictionary GetRankPageDatas(int type) { Dictionary datas = null; if (m_RankPageDatas.TryGetValue(type, out datas)) { return datas; } return null; } //查询指定目标排名的数据 public RankData GetRankDataByRank(int type, int rank) { Dictionary rankDatas = null; RankData rankData = null; if (m_RankPageDatas.TryGetValue(type, out rankDatas)) { rankDatas.TryGetValue(rank, out rankData); } return rankData; } ////如果是跨服排行榜 类型可能因跨服功能不同 由分组分赛季等情况组合 public RankData GetMyRank(int type) { var playerId = PlayerDatas.Instance.baseData.PlayerID; Dictionary rankDatas = null; if (m_RankPageDatas.TryGetValue(type, out rankDatas)) { foreach (var item in rankDatas.Values) { if (item.id == playerId) { return item; } } } return null; } public RankData GetRankByID(int type, int queryID) { Dictionary rankDatas = null; if (m_RankPageDatas.TryGetValue(type, out rankDatas)) { foreach (var item in rankDatas.Values) { if (item.id == queryID) { return item; } } } return null; } #endregion } // 默认情况,各个榜可能有所变化 // 玩家个人榜 // ID - 玩家ID // Name1 - 玩家名 // Name2 - 游戏账号 // Type2 - 职业 // Value1 - 官职 // Value2 - 称号ID // Value3 - 头像 // Value4 - 头像框 // Value5 - 主角形象 // cmpValue 比较值亿 // cmpValue2 比较值小于亿 // cmpValue3 时间戳 // --------------------------------------- // 仙盟榜 // ID - 仙盟ID // ID2 - 盟主ID // Name1 - 仙盟名 // Name2 - 盟主名 // Value1 - 总战力,整除亿部分 // Value2 - 总战力,求余亿部分 // Value3 - 徽章 // Value4 - 仙盟等级 // Value5 - 仙盟ServerID public class RankData { public int type; //排行榜类型 public int subType; public uint id; public int id2; public string name1; public string name2; public uint value1; public uint value2; public uint value3; public uint value4; public uint value5; public uint value6; public uint value7; public uint value8; public uint cmpValue; public uint cmpValue2; public uint cmpValue3; public string userData; public int rank; // 排名从1开始,代表第1名 public int index; //数据在榜单列表中的索引,从0开始 非排名 分页查询会用到 }