Commit 598357652e20e82a14325183b6d22e2c989a896c
1 parent
03a6166a
排行榜
Showing
11 changed files
with
233 additions
and
19 deletions
Show diff stats
src/GlobalVar.lua
src/ProtocolCode.lua
... | ... | @@ -90,12 +90,14 @@ actionCodes = { |
90 | 90 | Diner_addWantFoodRpc = 312, |
91 | 91 | Diner_initTaskRpc = 313, |
92 | 92 | Diner_handleTaskRpc = 314, |
93 | + Diner_rankRpc = 315, | |
93 | 94 | |
94 | 95 | Tower_roleFormatRpc = 350, |
95 | 96 | Tower_startBattleRpc = 351, |
96 | 97 | Tower_endBattleRpc = 352, |
97 | 98 | Tower_rankRpc = 353, |
98 | 99 | Tower_bugCountRpc = 354, |
100 | + Tower_rankInfoRpc = 355, | |
99 | 101 | |
100 | 102 | Car_makePotionRpc = 400, |
101 | 103 | Car_equipUpRpc = 401, | ... | ... |
src/RedisKeys.lua
... | ... | @@ -8,6 +8,13 @@ R_EQUIP_ROOT = "role:%d:equip*" -- 装备根目录 |
8 | 8 | R_RUNEIDS = "role:%d:runeIds" -- 玩家拥有符文自增id |
9 | 9 | R_RUNE = "role:%d:rune:%d" -- 符文详细信息 |
10 | 10 | |
11 | + | |
12 | +-- rank | |
13 | +RANK_TOWER = "rank:tower" | |
14 | +RANK_TOWER_INFO = "rank:tower:info" | |
15 | + | |
16 | +RANK_DINER = {"rank:diner1", "rank:diner2"} -- 餐厅排行榜 两个每天互换 | |
17 | +RANK_DINER_INFO = "rank:diner:info" | |
11 | 18 | -- -- role |
12 | 19 | -- R_FARM_KEY = "role:%d:farm" |
13 | 20 | -- R_TOWER_KEY = "role:%d:tower" | ... | ... |
src/actions/DinerAction.lua
... | ... | @@ -67,6 +67,7 @@ function _M.addSellRpc( agent, data ) |
67 | 67 | if not sells[slot] then |
68 | 68 | sells[slot] = { |
69 | 69 | reward = "", |
70 | + popular = 0, | |
70 | 71 | } |
71 | 72 | end |
72 | 73 | sells[slot].dish = dish |
... | ... | @@ -123,7 +124,7 @@ end |
123 | 124 | function _M.getSellRewardRpc( agent, data ) |
124 | 125 | local role = agent.role |
125 | 126 | local dirty = false |
126 | - local reward = "" | |
127 | + local reward, popular = "", 0 | |
127 | 128 | local sells = json.decode(role.dinerData:getProperty("sells")) |
128 | 129 | for slot, _ in pairs(sells) do |
129 | 130 | role.dinerData:updateSell(slot) |
... | ... | @@ -134,6 +135,7 @@ function _M.getSellRewardRpc( agent, data ) |
134 | 135 | for k,v in pairs(rewards) do |
135 | 136 | reward = reward:incrv(k, v) |
136 | 137 | end |
138 | + popular = popular + (sell.popular or 0) | |
137 | 139 | |
138 | 140 | if rewards[ItemId.Gold] and rewards[ItemId.Gold] > 0 then |
139 | 141 | if role.dinerData:checkDinerTask(DinerTask.DishWithGold, rewards[ItemId.Gold], sell.dish, nil, true) then |
... | ... | @@ -148,12 +150,15 @@ function _M.getSellRewardRpc( agent, data ) |
148 | 150 | end |
149 | 151 | end |
150 | 152 | sells[slot].reward = "" |
153 | + sells[slot].popular = 0 | |
151 | 154 | end |
152 | 155 | role.dinerData:updateProperty({field = "sells", value = json.encode(sells)}) |
153 | 156 | for k, v in pairs(reward:toNumMap()) do |
154 | 157 | role:addItem({itemId = k,count = v}) |
155 | 158 | end |
156 | 159 | |
160 | + role.dinerData:popularAdd(popular) | |
161 | + | |
157 | 162 | if dirty then |
158 | 163 | role.dinerData:notifyUpdateProperty("order", role.dinerData:getProperty("order")) |
159 | 164 | end |
... | ... | @@ -179,7 +184,7 @@ function _M.expediteSellRpc( agent, data ) |
179 | 184 | end |
180 | 185 | |
181 | 186 | local dirty = false |
182 | - local reward,popular = "",0 | |
187 | + local reward,popular = "", 0 | |
183 | 188 | local sells = json.decode(role.dinerData:getProperty("sells")) |
184 | 189 | for slot, _ in pairs(sells) do |
185 | 190 | role.dinerData:updateSell(slot) |
... | ... | @@ -216,6 +221,8 @@ function _M.expediteSellRpc( agent, data ) |
216 | 221 | role:addItem({itemId = k,count = v}) |
217 | 222 | end |
218 | 223 | |
224 | + role.dinerData:popularAdd(popular) | |
225 | + | |
219 | 226 | if dirty then |
220 | 227 | role.dinerData:notifyUpdateProperty("order", role.dinerData:getProperty("order")) |
221 | 228 | end |
... | ... | @@ -681,4 +688,13 @@ function _M.handleTaskRpc(agent, data) |
681 | 688 | return true |
682 | 689 | end |
683 | 690 | |
691 | +function _M.rankRpc(agent , data) | |
692 | + local role = agent.role | |
693 | + | |
694 | + local rankInfo = role.dinerData:getPopularRank() | |
695 | + SendPacket(actionCodes.Diner_rankRpc, MsgPack.pack(rankInfo)) | |
696 | + return true | |
697 | +end | |
698 | + | |
699 | + | |
684 | 700 | return _M |
685 | 701 | \ No newline at end of file | ... | ... |
src/actions/RoleAction.lua
src/actions/TowerAction.lua
... | ... | @@ -86,6 +86,9 @@ function _M.endBattleRpc(agent, data) |
86 | 86 | local reward |
87 | 87 | if msg.starNum and msg.starNum > 0 then --win |
88 | 88 | curCount = math.min(curCount + 1, globalCsv.tower_count_limit) -- 返还次数 |
89 | + --排行榜 | |
90 | + role:setTowerRank(towerInfo.l) | |
91 | + | |
89 | 92 | towerInfo.l = towerInfo.l + 1 |
90 | 93 | reward = role:award(curTower.reward) |
91 | 94 | end |
... | ... | @@ -122,9 +125,15 @@ end |
122 | 125 | |
123 | 126 | function _M.rankRpc(agent , data) |
124 | 127 | local role = agent.role |
128 | + SendPacket(actionCodes.Tower_rankRpc, MsgPack.pack(role:getTowerRank())) | |
129 | + return true | |
130 | +end | |
125 | 131 | |
126 | - local rankList = {} | |
127 | - SendPacket(actionCodes.Tower_rankRpc, MsgPack.pack({rankList = rankList})) | |
132 | +function _M.rankInfoRpc(agent , data) | |
133 | + local role = agent.role | |
134 | + local msg = MsgPack.unpack(data) | |
135 | + local roleId = msg.roleId | |
136 | + SendPacket(actionCodes.Tower_rankInfoRpc, MsgPack.pack({format = role:getTowerRankOneInfo(roleId)})) | |
128 | 137 | return true |
129 | 138 | end |
130 | 139 | ... | ... |
src/models/Diner.lua
... | ... | @@ -16,11 +16,14 @@ Diner.schema = { |
16 | 16 | task = {"table", {}}, -- 任务刷新 {et = 消失时间 id = 任务id, refuse = 0} |
17 | 17 | } |
18 | 18 | |
19 | +function Diner:rankResetData(notify) | |
20 | + self:updateProperty({field = "popular", value = 0, notNotify = not notify}) | |
21 | +end | |
22 | + | |
19 | 23 | function Diner:refreshDailyData(notify) |
20 | 24 | -- 每日加速次数 |
21 | 25 | self:updateProperty({field = "expedite", value = 1, notNotify = not notify}) |
22 | 26 | self:setProperty("expedite", 1) |
23 | - | |
24 | 27 | -- 特殊订单 |
25 | 28 | local orders = json.decode(self:getProperty("order")) |
26 | 29 | local hadTask = {} |
... | ... | @@ -170,8 +173,8 @@ function Diner:updateSell(slot, calOnly) |
170 | 173 | sells[slot].count = lastCount |
171 | 174 | sells[slot].level = self:getProperty("dishTree"):getv(sell.dish, 1) |
172 | 175 | sells[slot].reward = reward |
176 | + sells[slot].popular = (sells[slot].popular or 0) + popular | |
173 | 177 | self:setProperty("sells", json.encode(sells)) |
174 | - self:updateProperty({field = "popular", delta = popular}) | |
175 | 178 | self:checkDinerTask(DinerTask.SellDish, deltaCount, sell.dish) |
176 | 179 | self:checkDinerTask(DinerTask.SellDishType, deltaCount, math.ceil(sell.dish / 100)) |
177 | 180 | self:checkDinerTask(DinerTask.SellDishRare, deltaCount, dishData.rarity) |
... | ... | @@ -181,7 +184,6 @@ function Diner:updateSell(slot, calOnly) |
181 | 184 | deltaTime = deltaTime, |
182 | 185 | lastCount = lastCount, |
183 | 186 | reward = reward, |
184 | - popular = popular, | |
185 | 187 | } |
186 | 188 | end |
187 | 189 | |
... | ... | @@ -204,7 +206,6 @@ function Diner:expediteSell(slot) |
204 | 206 | sells[slot].time = sell.time - deltaTime |
205 | 207 | sells[slot].count = lastCount |
206 | 208 | self:setProperty("sells", json.encode(sells)) |
207 | - self:updateProperty({field = "popular", delta = popular}) | |
208 | 209 | self:checkDinerTask(DinerTask.SellDish, expediteCount, sell.dish) |
209 | 210 | self:checkDinerTask(DinerTask.SellDishType, expediteCount, math.ceil(sell.dish / 100)) |
210 | 211 | self:checkDinerTask(DinerTask.SellDishRare, expediteCount, dishData.rarity) |
... | ... | @@ -233,15 +234,61 @@ end |
233 | 234 | function Diner:getMaxDishs() |
234 | 235 | local dishCount = globalCsv.diner_sell_dish_init |
235 | 236 | |
236 | - local buildingCsv = csvdb["diner_buildingCsv"] | |
237 | - for id, level in pairs(self:getProperty("buildL"):toNumMap()) do | |
238 | - if buildingCsv[id][level].storage > 0 then | |
239 | - dishCount = dishCount + buildingCsv[id][level].storage | |
240 | - end | |
241 | - end | |
237 | + -- local buildingCsv = csvdb["diner_buildingCsv"] | |
238 | + -- for id, level in pairs(self:getProperty("buildL"):toNumMap()) do | |
239 | + -- if buildingCsv[id][level].storage > 0 then | |
240 | + -- dishCount = dishCount + buildingCsv[id][level].storage | |
241 | + -- end | |
242 | + -- end | |
242 | 243 | return dishCount |
243 | 244 | end |
244 | 245 | |
246 | +function Diner:popularAdd(popular) | |
247 | + if popular ~= 0 then | |
248 | + self:updateProperty({field = "popular", delta = popular}) | |
249 | + local dbKey = self.owner:getCurDinerRankKey() | |
250 | + local roleId = self.owner:getProperty("id") | |
251 | + -- 更新排行榜 | |
252 | + local curPopular = self:getProperty("popular") | |
253 | + redisproxy:pipelining(function (red) | |
254 | + red:zadd(dbKey, curPopular, roleId) --更新分数 | |
255 | + red:hset(RANK_DINER_INFO, roleId, MsgPack.pack({ | |
256 | + lv = self:getProperty("buildL"):getv(1, 0), | |
257 | + name = self.owner:getProperty("name"), | |
258 | + headId = self.owner:getProperty("headId") | |
259 | + })) | |
260 | + end) | |
261 | + end | |
262 | +end | |
263 | + | |
264 | +function Diner:getPopularRank() | |
265 | + local dbKey = self.owner:getCurDinerRankKey() | |
266 | + local list = {} | |
267 | + local ids = redisproxy:zrevrange(dbKey, 0 , 99, "WITHSCORES") | |
268 | + local redret = {} | |
269 | + if ids and next(ids) then | |
270 | + redret = redisproxy:pipelining(function (red) | |
271 | + for i = 1, #ids, 2 do | |
272 | + local roleId = ids[i] | |
273 | + local score = ids[i + 1] | |
274 | + list[#list + 1] = {score = tonumber(score), roleId = tonumber(roleId)} | |
275 | + red:hget(RANK_DINER_INFO, roleId) | |
276 | + end | |
277 | + end) | |
278 | + end | |
279 | + for i = 1, #redret do | |
280 | + local player = MsgPack.unpack(redret[i]) | |
281 | + list[i].player = player | |
282 | + end | |
283 | + local rank = redisproxy:ZREVRANK(dbKey, self.owner:getProperty("id")) | |
284 | + if not rank then | |
285 | + rank = -1 | |
286 | + else | |
287 | + rank = rank + 1 | |
288 | + end | |
289 | + return {list = list, rank = rank} | |
290 | +end | |
291 | + | |
245 | 292 | function Diner:data() |
246 | 293 | local properties = {"buildL", "order", "sells", "dishTree", "skillTree","popular","expedite","gfood", "task"} |
247 | 294 | local data = self:getProperties(properties) | ... | ... |
src/models/Role.lua
... | ... | @@ -22,6 +22,7 @@ Role.schema = { |
22 | 22 | id = {"number"}, |
23 | 23 | uid = {"string", ""}, |
24 | 24 | name = {"string", ""}, |
25 | + headId = {"number", 3201}, | |
25 | 26 | sid = {"number", 0}, |
26 | 27 | device = {"string", ""}, |
27 | 28 | banTime = {"number", 0}, |
... | ... | @@ -178,6 +179,7 @@ function Role:data() |
178 | 179 | return { |
179 | 180 | id = self:getProperty("id"), |
180 | 181 | name = self:getProperty("name"), |
182 | + headId = self:getProperty("headId"), | |
181 | 183 | level = self:getProperty("level"), |
182 | 184 | exp = self:getProperty("exp"), |
183 | 185 | items = self:getProperty("items"):toNumMap(), | ... | ... |
src/models/RolePlugin.lua
... | ... | @@ -31,9 +31,37 @@ function RolePlugin.bind(Role) |
31 | 31 | if notify then |
32 | 32 | self:notifyUpdateProperties(response) |
33 | 33 | end |
34 | + | |
35 | + if RESET_TIME == RESET_RANK_TIME then | |
36 | + self:onResetRank_raw(ltime, now, notify) | |
37 | + end | |
38 | + self:setProperty("ltime", now) | |
34 | 39 | return true |
35 | 40 | end |
36 | 41 | end |
42 | + | |
43 | + function Role:onResetRank(now, notify) | |
44 | + local ltime = self:getProperty("ltime") | |
45 | + if isCrossDay(ltime, now, RESET_RANK_TIME) then | |
46 | + local response = self:onResetRank_raw(ltime, now, notify) | |
47 | + | |
48 | + if notify and next(response) then | |
49 | + self:notifyUpdateProperties(response) | |
50 | + end | |
51 | + | |
52 | + self:setProperty("ltime", now) | |
53 | + return true | |
54 | + end | |
55 | + end | |
56 | + | |
57 | + function Role:onResetRank_raw(ltime, now, notify) | |
58 | + local response = {} | |
59 | + | |
60 | + self.dinerData:rankResetData(notify) | |
61 | + | |
62 | + return response | |
63 | + end | |
64 | + | |
37 | 65 | function Role:onOfflineEvent() |
38 | 66 | |
39 | 67 | end |
... | ... | @@ -613,7 +641,8 @@ function RolePlugin.bind(Role) |
613 | 641 | self:changeUpdates({{type = "funcOpen", field = unlockData.type, value = 1}}) |
614 | 642 | else |
615 | 643 | local oldV = self:getFuncLv(unlockData.type) |
616 | - self:changeUpdates({{type = "funcLv", field = unlockData.type, value = oldV + count}}) | |
644 | + local newLv = math.min(oldV + count, unlockData.value2) | |
645 | + self:changeUpdates({{type = "funcLv", field = unlockData.type, value = newLv}}) | |
617 | 646 | end |
618 | 647 | else |
619 | 648 | self:changeUpdates({{type = "funcOpen", field = func, value = 1}}) |
... | ... | @@ -661,6 +690,97 @@ function RolePlugin.bind(Role) |
661 | 690 | self:setProperty("advElS", globalCsv.adv_endless_season) |
662 | 691 | end |
663 | 692 | end |
693 | + | |
694 | + function Role:getTeamBattleValue(heros) | |
695 | + local battleV = 0 | |
696 | + for _, heroId in pairs(heros) do | |
697 | + local hero = self.heros[heroId] | |
698 | + battleV = battleV + hero:getProperty("battleV") | |
699 | + end | |
700 | + return battleV | |
701 | + end | |
702 | + | |
703 | + function Role:recordRankTeam(heroIds) | |
704 | + local heros = {} | |
705 | + for slot, heroId in pairs(heroIds) do | |
706 | + local hero = self.heros[heroId] | |
707 | + heros[slot] = { | |
708 | + htype = hero:getProperty("type"), | |
709 | + lv = hero:getProperty("level"), | |
710 | + breakL = hero:getProperty("breakL"), | |
711 | + } | |
712 | + end | |
713 | + return heros | |
714 | + end | |
715 | + | |
716 | + local StdDinerRankTime = toUnixtime("20190101"..string.format("%02x", RESET_RANK_TIME)) --跨天时间 | |
717 | + function Role:getCurDinerRankKey() | |
718 | + local now = skynet.timex() | |
719 | + local idx = 1 | |
720 | + if math.floor((now - StdDinerRankTime) / 86400) % 2 == 1 then | |
721 | + idx = 2 | |
722 | + end | |
723 | + return RANK_DINER[idx] | |
724 | + end | |
725 | + | |
726 | + local StdTowerRankTime = toUnixtime("2019010100") | |
727 | + function Role:setTowerRank(level) | |
728 | + local now = skynet.timex() | |
729 | + local ct = math.ceil((now - StdTowerRankTime) / 86400) --按天计算 365 * 27 < 10000 可以维持 27 年 | |
730 | + local ct = 10000 - ct -- 越早的排名越靠前 | |
731 | + local towerTeam = self:getProperty("towerF") | |
732 | + local battleV = self:getTeamBattleValue(towerTeam.heros) | |
733 | + local score = (level * 10000 + ct) * 10000000 + battleV | |
734 | + | |
735 | + local curInfo = { | |
736 | + name = self:getProperty("name"), | |
737 | + headId = self:getProperty("headId"), | |
738 | + lv = self:getProperty("level"), | |
739 | + batteV = battleV, | |
740 | + level = level, | |
741 | + format = self:recordRankTeam(towerTeam.heros), | |
742 | + } | |
743 | + local roleId = self:getProperty("id") | |
744 | + redisproxy:pipelining(function (red) | |
745 | + red:zadd(RANK_TOWER, score, roleId) --更新分数 | |
746 | + red:hset(RANK_TOWER_INFO, roleId, MsgPack.pack(curInfo)) | |
747 | + end) | |
748 | + end | |
749 | + | |
750 | + function Role:getTowerRank() | |
751 | + local list = {} | |
752 | + local ids = redisproxy:zrevrange(RANK_TOWER, 0 , 99) | |
753 | + local redret = {} | |
754 | + if ids and next(ids) then | |
755 | + redret = redisproxy:pipelining(function (red) | |
756 | + for i = 1, #ids do | |
757 | + local roleId = ids[i] | |
758 | + table.insert(list, {roleId = tonumber(roleId)}) | |
759 | + red:hget(RANK_TOWER_INFO, roleId) | |
760 | + end | |
761 | + end) | |
762 | + end | |
763 | + for i = 1, #redret do | |
764 | + local player = MsgPack.unpack(redret[i]) | |
765 | + player.format = nil | |
766 | + list[i].player = player | |
767 | + end | |
768 | + local rank = redisproxy:ZREVRANK(RANK_TOWER, self:getProperty("id")) | |
769 | + if not rank then | |
770 | + rank = -1 | |
771 | + else | |
772 | + rank = rank + 1 | |
773 | + end | |
774 | + return {list = list, rank = rank} | |
775 | + end | |
776 | + | |
777 | + function Role:getTowerRankOneInfo(roleId) | |
778 | + local data = redisproxy:hget(RANK_TOWER_INFO, roleId) | |
779 | + if data then | |
780 | + local player = MsgPack.unpack(data) | |
781 | + return player.format | |
782 | + end | |
783 | + end | |
664 | 784 | end |
665 | 785 | |
666 | 786 | return RolePlugin |
667 | 787 | \ No newline at end of file | ... | ... |
src/services/agent_util.lua
... | ... | @@ -41,6 +41,7 @@ end |
41 | 41 | |
42 | 42 | local PointDataMark = {} |
43 | 43 | local resetTimeStr = string.format("%02d00", RESET_TIME) |
44 | +local resetRankTimeStr = string.format("%02d00", RESET_RANK_TIME) | |
44 | 45 | |
45 | 46 | local function check_daily_reset(agent, now) |
46 | 47 | local date = os.date("*t", now) |
... | ... | @@ -66,6 +67,13 @@ local function check_daily_reset(agent, now) |
66 | 67 | role:onCrossDay(now, true) |
67 | 68 | end |
68 | 69 | end |
70 | + if resetTimeStr ~= resetRankTimeStr and timeEffect(resetRankTimeStr) then | |
71 | + -- 刷新排行榜需要重置的数据 | |
72 | + local role = agent.role | |
73 | + if role then | |
74 | + role:onResetRank(now, true) | |
75 | + end | |
76 | + end | |
69 | 77 | end |
70 | 78 | |
71 | 79 | function _M:update(agent) |
... | ... | @@ -76,7 +84,7 @@ function _M:update(agent) |
76 | 84 | nextCheckTime = now + HEART_TIMER_INTERVAL |
77 | 85 | end |
78 | 86 | pcall(check_daily_reset, agent, now) |
79 | - pcall(role.onRecoverTimer, role, now) | |
87 | + -- pcall(role.onRecoverTimer, role, now) | |
80 | 88 | end |
81 | 89 | |
82 | 90 | function _M:heart_beat(agent) | ... | ... |
src/utils/CommonFunc.lua
... | ... | @@ -109,11 +109,12 @@ function isCrossMonth(target, now) |
109 | 109 | end |
110 | 110 | end |
111 | 111 | |
112 | -function isCrossDay(lastTime, now) | |
112 | +function isCrossDay(lastTime, now, resetTime) | |
113 | + resetTime = resetTime or RESET_TIME | |
113 | 114 | if lastTime == 0 then return true end |
114 | 115 | now = now or skynet.timex() |
115 | - local today4h = specTime({hour = RESET_TIME}, now - RESET_TIME * 3600) | |
116 | - return lastTime < today4h and now >= today4h | |
116 | + local todayResetH = specTime({hour = resetTime}, now - resetTime * 3600) | |
117 | + return lastTime < todayResetH and now >= todayResetH | |
117 | 118 | end |
118 | 119 | |
119 | 120 | function crossDay(target, now) | ... | ... |