using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace vnxbqy.UI { public class RankModel : Model, IBeforePlayerDataInitialize, IPlayerLoginOk { //后续不再使用,旧逻辑依然有在用不要删除 C1001_tagCWatchBillboard, H1001_tagBillboard接收排行榜信息 //改用 HA9A2_tagPYBillboardData 和 HC007_tagGCCrossBillboardInfo; 参考m_RankPageDatas public Dictionary> m_RankDatas = new Dictionary>(); public Dictionary> displaySubRanks = new Dictionary>(); public Dictionary subRankSpreads = new Dictionary(); public List displayRanks = new List(); int m_SelectRankId = 0; public int selectRankId { get { return m_SelectRankId; } set { if (m_SelectRankId != value) { m_SelectSubRankId = 0; m_SelectRankId = value; if (selectRankIdRefresh != null) { selectRankIdRefresh(); } } } } int m_SelectSubRankId = 0; public int selectSubRankId { get { return m_SelectSubRankId; } set { if (m_SelectSubRankId != value) { m_SelectSubRankId = value; if (selectSubRankIdRefresh != null) { selectSubRankIdRefresh(); } } } } public int selectRankType { get { if (displaySubRanks.ContainsKey(selectRankId)) { var config = RankListConfig.Get(selectSubRankId); return config == null ? 0 : config.type; } else { var config = RankListConfig.Get(selectRankId); return config == null ? 0 : config.type; } } } public int displayRankCount { get; private set; } public int jumpRankType { get; set; } public readonly ObjectPool m_RankDataPool = new ObjectPool(OnGetRankData, OnReleaseRankData); public event Action selectRankIdRefresh; public event Action selectSubRankIdRefresh; public event Action onRankRefresh; public event Action onMyRankRefresh; public override void Init() { jumpRankType = -1; ParseConfig(); } public void OnBeforePlayerDataInitialize() { foreach (var rankDatas in m_RankDatas.Values) { foreach (var item in rankDatas) { m_RankDataPool.Release(item); } } m_RankDatas.Clear(); m_RankPageDatas.Clear(); m_RankIDToIndex.Clear(); queryRankCD.Clear(); } public void OnPlayerLoginOk() { //SendBegRank(RankType.JadeDynastyTower); } public override void UnInit() { } void ParseConfig() { { var config = FuncConfigConfig.Get("RankListCnt"); displayRankCount = int.Parse(config.Numerical1); } { var configs = RankListConfig.GetValues(); foreach (var config in configs) { if (config.ID >= 100) { var rankId = config.ID / 100; List subRanks = null; if (!displaySubRanks.TryGetValue(rankId, out subRanks)) { subRanks = new List(); displaySubRanks.Add(rankId, subRanks); } subRanks.Add(config.ID); } else { displayRanks.Add(config.ID); } } } } public bool TryGetRanks(int type, out List ranks) { return m_RankDatas.TryGetValue(type, out ranks); } public bool TryGetMyRank(int type, out int rank) { rank = 0; var playerId = PlayerDatas.Instance.baseData.PlayerID; List rankDatas = null; if (TryGetRanks(type, out rankDatas)) { for (int i = 0; i < rankDatas.Count; i++) { if (rankDatas[i].id == playerId) { rank = i + 1; return true; } } } return false; } public bool TryGetMyRankByID(int type, int queryID, out int rank) { rank = 0; List rankDatas = null; if (TryGetRanks(type, out rankDatas)) { for (int i = 0; i < rankDatas.Count; i++) { if (rankDatas[i].id == queryID) { rank = i + 1; return true; } } } return false; } public void SendBegRank(RankType rankType) { C1001_tagCWatchBillboard rankPack = new C1001_tagCWatchBillboard(); rankPack.Type = (byte)rankType; GameNetSystem.Instance.SendInfo(rankPack); } public void ReceivePackage(H1001_tagBillboard package) { List rankDatas = null; if (!m_RankDatas.TryGetValue(package.Type, out rankDatas)) { rankDatas = new List(); m_RankDatas.Add(package.Type, rankDatas); } for (int i = 0; i < package.BillboardCount; i++) { if (i < rankDatas.Count) { rankDatas[i].type = package.Type; ReSetRankData(rankDatas[i], package.Billboard[i]); } else { var rankData = m_RankDataPool.inactivedCount > 0 ? m_RankDataPool.Get() : new RankData(); rankData.type = package.Type; ReSetRankData(rankData, package.Billboard[i]); rankDatas.Add(rankData); } } var start = package.BillboardCount; var end = rankDatas.Count; for (int i = end - 1; i >= start; i--) { RankData data = rankDatas[i]; rankDatas.RemoveAt(i); m_RankDataPool.Release(data); } if (onRankRefresh != null) { onRankRefresh(package.Type); } } void ReSetRankData(RankData data, H1001_tagBillboard.tagBillboardList serverData) { data.id = serverData.ID; 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; } void ReSetRankDataEx(RankData data, HA9A2_tagPYBillboardData.tagPYBillboardInfo 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.index = (int)serverData.OrderIndex; data.type = type; } static void OnGetRankData(RankData data) { } static void OnReleaseRankData(RankData data) { } #region 分页查询 Dictionary queryRankCD = new Dictionary(); //查询CD Dictionary> m_RankPageDatas = new Dictionary>(); //分页查询 排名索引按字段存储 0代表第一名 //类型:ID -排名索引,通过ID进行排重删除 不同名次 同ID的数据 Dictionary> m_RankIDToIndex = new Dictionary>(); //本服分页查询使用说明 //1. QueryRankByPage:先查询第一页,startIndex = 0, count = 30, 在第一页查询前可以选择初始化ResetQueryParam //2. ListenRankPage:一般在滚动条OnRefreshCell监听排行榜显示名次,用于分页查询 // WatchID; //查看指定ID名次前后,其他参数无效 public void QueryRankByPage(int type, int startIndex = 0, int count = 30, int watchID = 0, bool forceQuery = false) { if (queryRankCD.ContainsKey(type) && !forceQuery) { if (Time.time - queryRankCD[type] < 2f) { return; } } var pak = new CA9A2_tagCPYWatchBillboard(); pak.Type = (byte)type; pak.StartIndex = (uint)startIndex; //排名从0开始 pak.WatchCnt = (byte)count; pak.WatchID = (uint)watchID; GameNetSystem.Instance.SendInfo(pak); queryRankCD[type] = (int)Time.time; } //监听排行榜显示名次,用于分页查询,第一页查询由外部触发 //使用场景 如界面排行榜滚动的时候每次查询30个排名名额,在显示大于m*30 +20名时,监听下一页,查询m+1页 int pageCnt = 30; //每页查询条数 int queryPointNum = 20; //查询点 int queryPageCD = 60; //查询点CD 避免不断上下滑动的时候过于频繁查询,外部使用重新打开的时候可以重置CD Dictionary queryPageTimes = new Dictionary(); //查询页CD public void ListenRankPage(int type, int index) { int page = index / pageCnt; if (index > page * pageCnt + queryPointNum) { if (queryPageTimes.ContainsKey(page) && Time.realtimeSinceStartup - queryPageTimes[page] < queryPageCD) return; Debug.LogFormat("分页查询:{0} - {1}", index, page); QueryRankByPage(type, pageCnt * (page + 1), pageCnt, forceQuery:true); queryPageTimes[page] = Time.realtimeSinceStartup; } } public void ResetQueryParam() { pageCnt = 30; queryPointNum = 20; queryPageCD = 60; queryPageTimes.Clear(); } public void SetQueryParm(int pageCnt, int queryPointNum, int queryPageCD) { this.pageCnt = pageCnt; this.queryPointNum = queryPointNum; this.queryPageCD = queryPageCD; queryPageTimes.Clear(); } //分页查询使用说明 //1. QueryCrossRank:先查询第一页,startIndex = 0, count = 30, 在第一页查询前可以选择初始化ResetQueryParam //2. ListenCrossRankPage:一般在滚动条OnRefreshCell监听排行榜显示名次,用于分页查询 // WatchID; //查看指定ID名次前后,其他参数无效 //查询跨服排行榜,排行榜类型可能因跨服功能不同 由分组分赛季等情况组合 /// 查看条数,服务端默认20,最大不超过100 public void QueryCrossRank(int type, int groupID, int startIndex = 0, int count = 30, int watchID = 0, int cd = 2, bool forceQuery = false, int groupValue2 = 0) { if (queryRankCD.ContainsKey(type) && !forceQuery) { if (Time.time - queryRankCD[type] < cd) { return; } } var pak = new CC004_tagCGViewCrossBillboard(); pak.Type = (byte)type; pak.GroupValue1 = (byte)groupID; pak.GroupValue2 = (uint)groupValue2; pak.StartIndex = (uint)startIndex; pak.WatchCnt = (byte)count; pak.WatchID = (uint)watchID; GameNetSystem.Instance.SendInfo(pak); queryRankCD[type] = (int)Time.time; } //groupVaule2 用于分组分赛季等情况 public void ListenCrossRankPage(int type, int groupID, int index, int groupVaule2 = 0) { int page = index / pageCnt; if (index > page * pageCnt + queryPointNum) { if (queryPageTimes.ContainsKey(page) && Time.realtimeSinceStartup - queryPageTimes[page] < queryPageCD) return; Debug.LogFormat("跨服分页查询:{0} - {1}", index, page); QueryCrossRank(type, groupID, pageCnt * (page + 1), pageCnt, forceQuery: true, groupValue2: groupVaule2); queryPageTimes[page] = Time.realtimeSinceStartup; } } //跨服排行榜信息 public void UpdateCSBillboardInfo(HC007_tagGCCrossBillboardInfo package) { if (package.Type == 150) { //已在 CSRechargeModel 处理,此处过滤 return; } ReceivePackageCross(package); } //跨服排行榜信息 public void ReceivePackageCross(HC007_tagGCCrossBillboardInfo package) { int rankType = package.Type; //部分跨服排行榜同一个榜存在分组分区的情况 //赛区3位+赛季3位+排行榜类型3位 if (rankType == 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()); } for (int i = 0; i < package.BillboardCount; i++) { int id = (int)package.CrossBillboardDataList[i].ID; int orderIndex = (int)package.CrossBillboardDataList[i].OrderIndex; 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.BillboardCount; i++) { int orderIndex = (int)package.CrossBillboardDataList[i].OrderIndex; if (!m_RankPageDatas[rankType].ContainsKey(orderIndex)) { m_RankPageDatas[rankType][orderIndex] = new RankData(); } ReSetRankData(m_RankPageDatas[rankType][orderIndex], package.CrossBillboardDataList[i], package.Type); } if (package.WatchID != 0) { onMyRankRefresh?.Invoke(rankType); } else { onRankRefresh?.Invoke(rankType); } } //跨服排行榜信息 void ReSetRankData(RankData data, HC007_tagGCCrossBillboardInfo.tagGCCrossBillboardData 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.index = serverData.OrderIndex; data.type = type; //与服务端一致的跨服排行榜类型,外部自行处理不同分组分赛季等情况 } //查询本服排行榜 public void ReceiveRankPagePackage(HA9A2_tagPYBillboardData package) { if (package.Type == 28) //本服竞技场排行榜,已在 ArenaRankModel 处理,此处过滤 return; if (!m_RankPageDatas.ContainsKey(package.Type)) { m_RankPageDatas.Add(package.Type, new Dictionary()); } //同ID排重删除 if (!m_RankIDToIndex.ContainsKey(package.Type)) { m_RankIDToIndex.Add(package.Type, new Dictionary()); } for (int i = 0; i < package.BillboardCount; i++) { int id = (int)package.Billboard[i].ID; int orderIndex = (int)package.Billboard[i].OrderIndex; if (!m_RankIDToIndex[package.Type].ContainsKey(id)) { m_RankIDToIndex[package.Type][id] = orderIndex; } else if (m_RankIDToIndex[package.Type][id] != orderIndex) { m_RankPageDatas[package.Type].Remove(m_RankIDToIndex[package.Type][id]); m_RankIDToIndex[package.Type][id] = orderIndex; } } for (int i = 0; i < package.BillboardCount; i++) { int orderIndex = (int)package.Billboard[i].OrderIndex; if (!m_RankPageDatas[package.Type].ContainsKey(orderIndex)) { m_RankPageDatas[package.Type][orderIndex] = new RankData(); } ReSetRankDataEx(m_RankPageDatas[package.Type][orderIndex], package.Billboard[i], package.Type); } if (package.WatchID != 0) { onMyRankRefresh?.Invoke(package.Type); } else { onRankRefresh?.Invoke(package.Type); } } //排名从0 开始 //如果是跨服排行榜 类型可能因跨服功能不同 由分组分赛季等情况组合 public Dictionary GetRankPageDatas(int type) { Dictionary datas = null; if (m_RankPageDatas.TryGetValue(type, out datas)) { return datas; } return null; } ////如果是跨服排行榜 类型可能因跨服功能不同 由分组分赛季等情况组合 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 GetMyRankByID(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 } 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 index; //分页查询会用到 排名 } }