yyl
8 天以前 871594462e82d6bc1341918d39e11ab036d59563
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
using System;
using System.Collections.Generic;
using UnityEngine;
 
// 支持分页查询排行榜, 本服/跨服统一使用 参考QueryRankByPage  新封包 DTCA130_tagMCViewBillboardRet
public class RankModel : GameSystemManager<RankModel>
{
    public event Action<int> onRankRefresh;
    //public event Action<int> onMyRankRefresh;
    
    //排行榜滚动显示的最大数量 类型
    Dictionary<int, int> ranksShowMaxCnt = new Dictionary<int, int>();
 
    //分页查询
    Dictionary<int, int> queryRankCD = new Dictionary<int, int>(); //首次查询CD,不影响后续的分页查询
    //分页查询 排名索引按字段存储 1代表第一名
    Dictionary<int, Dictionary<int, RankData>> m_RankPageDatas = new Dictionary<int, Dictionary<int, RankData>>();  
    //类型:ID -排名索引,通过ID进行排重删除 不同名次 同ID的数据
    Dictionary<int, Dictionary<int, int>> m_RankIDToIndex = new Dictionary<int, Dictionary<int, int>>();
 
    //监听排行榜显示名次,用于分页查询,第一页查询由外部触发
    //使用场景 如界面排行榜滚动的时候每次查询30个排名名额,在显示大于m*30 +20名时,监听下一页,查询m+1页
    int pageCnt = 20; //每页查询条数
    int queryPointNum = 12;  //查询点
    int queryPageCD = 60; //内部查询点CD 避免不断上下滑动的时候过于频繁查询,外部使用重新打开的时候可以重置CD
    Dictionary<int, float> queryPageTimes = new Dictionary<int, float>(); //查询页CD
    Dictionary<int, int> ranksServerMaxCnt = new Dictionary<int, int>();    //服务器排行榜当前总数量(动态变化),分页查询的时候过滤用
 
 
 
    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<int, RankData>());
        }
 
        //同ID排重删除
        if (!m_RankIDToIndex.ContainsKey(rankType))
        {
            m_RankIDToIndex.Add(rankType, new Dictionary<int, int>());
        }
 
        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<int, RankData> GetRankPageDatas(int type)
    {
        Dictionary<int, RankData> datas = null;
        if (m_RankPageDatas.TryGetValue(type, out datas))
        {
            return datas;
        }
        return null;
    }
 
    //查询指定目标排名的数据
    public RankData GetRankDataByRank(int type, int rank)
    {
        Dictionary<int, RankData> 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<int, RankData> 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<int, RankData> 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开始 非排名 分页查询会用到 
}