diff --git a/.gitignore b/.gitignore index 0dd15c7..df4d3f9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ dump.rdb .DS_Store src/.idea +*.pyc diff --git a/src/ProtocolCode.lua b/src/ProtocolCode.lua index 9c56494..ce7662a 100644 --- a/src/ProtocolCode.lua +++ b/src/ProtocolCode.lua @@ -61,6 +61,7 @@ actionCodes = { Adv_wearArtifactRpc = 166, Adv_upArtifactRpc = 167, Adv_repayWheelSurfRpc = 168, + Adv_rankRpc = 169, Hero_loadInfos = 201, Hero_updateProperty = 202, diff --git a/src/RedisKeys.lua b/src/RedisKeys.lua index 83a3be7..f18b255 100644 --- a/src/RedisKeys.lua +++ b/src/RedisKeys.lua @@ -16,38 +16,18 @@ R_EMAIL_ITEM = "email:%d:%d" --邮件 RANK_TOWER = "rank:tower" RANK_TOWER_INFO = "rank:tower:info" +-- adv +RANK_ADV = "rank:adv" +RANK_ADV_INFO = "rank:adv:info" + RANK_DINER = {"rank:diner1", "rank:diner2"} -- 餐厅排行榜 两个每天互换 RANK_DINER_INFO = "rank:diner:info" RANK_PVP_COMMON = "rank:pvpc" RECORD_PVP_COMMON = "record:pvpc:%d" RANK_PVP_HIGHT = "rank:pvph" --- -- role --- R_FARM_KEY = "role:%d:farm" --- R_TOWER_KEY = "role:%d:tower" --- R_COOKLOG_KEY = "role:%d:cooklog" --- R_TRADELOG_KEY = "role:%d:tradelog" --- R_PVP_KEY = "role:%d:pvp" --- R_DINER_KEY = "role:%d:diner" --- -- rank --- RANK_PVP = "rank:pvp" --- RANK_TRADE = "rank:trade" --- RANK_TOWER = "rank:tower" --- RANK_BOX = "rank:box" -- 盒子舒适度排行榜 --- MAP_LIKE = "map:box:like" --点赞个数 --- RANK_LEVEL = "rank:level" --等级排名 --- RANK_ITEM = "rank:item" --活动物品排行 --- -- 日志 --- NOTE_COOK_KEY = "note:cook:%d" - --- TRADE_KEY = "trade:%d" --- TRADE_ID_KEY = "tradeIDs" --- TASK_ACTIVE = "task:%d:active" -- 记录激活的任务 --- TASK_FINISH = "task:%d:finish" -- 记录完成的任务 --- BOSS_SET = "boss:%d:%d" --- BOSS_INFO = "boss:battle" FRIEND_KEY = "role:%d:friend" --哈希表 好友 FRIEND_APPLY_KEY = "role:%d:apply" -- sort set 申请列表 diff --git a/src/actions/AdvAction.lua b/src/actions/AdvAction.lua index 543f8a7..62d3916 100644 --- a/src/actions/AdvAction.lua +++ b/src/actions/AdvAction.lua @@ -18,6 +18,23 @@ local AdvCommon = require "adv.AdvCommon" local _M = {} +-- 无尽模式是否开放 +local function isOpenEndless(role) + if role.advOverTime ~= 0 and skynet.timex() >= role.advOverTime then + return false + end + return true +end +-- 冒险内的操作是否可以继续 +local function isCanContinue(role) + local adv = role:getAdvData() + if not adv:isRunning() then return false end + if adv:isEndless() then + if not isOpenEndless(role) then return false end + end + return true +end + local function checkFormat(role, format, checkAdvTeam) local advHang = role:getProperty("advHang") @@ -69,7 +86,7 @@ function _M.startAdvRpc( agent, data ) local format = msg.format --编队 --上一个关卡结束才可以开始新的关卡 - if next(role:getProperty("advInfo")) then return 8 end + if role:getAdvData():isRunning() then return 8 end local chapterData = csvdb["adv_chapterCsv"][chapterId] if not chapterData or layer < 1 then return 1 end @@ -79,6 +96,8 @@ function _M.startAdvRpc( agent, data ) local advPass = role:getProperty("advPass") if AdvCommon.isEndless(chapterId) then + if chapterId ~= role.advElChapter then return end -- 不是当前进行的章节 + if not isOpenEndless(role) then return end if role.dailyData:getProperty("advElC") >= role:getAdvElLimit() then return 2 end -- 是否有体力 if not role:isFuncOpen(FuncOpenType.AdvEndless) or not role:isFuncOpen(FuncOpenType.AdvRelay) then return 11 end -- 开放了中继模式 和 无尽模式 才可以玩儿无尽模式 local maxl = math.floor(role:getProperty("advElM") / 10) * 10 @@ -147,7 +166,7 @@ function _M.startHangRpc(agent, data) if role.dailyData:getProperty("advC") >= role:getAdvHangLimit() then return end -- 是否有体力 - if not checkFormat(role, format, next(role:getProperty("advInfo"))) then return end --编队是否正确 + if not checkFormat(role, format, role:getAdvData():isRunning()) then return end --编队是否正确 local battleV = 0 for _, heroId in pairs(format.heros) do @@ -167,7 +186,7 @@ function _M.startHangRpc(agent, data) info.time = skynet.timex() + chapterData.idleTime --挂机时间 -- 没有在战斗 用team来挂机了 把team清掉 - if not next(role:getProperty("advInfo")) then + if not role:getAdvData():isRunning() then role:updateProperty({field = "advTeam", value = {}}) end @@ -248,6 +267,7 @@ function _M.finishTaskRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) + if not isCanContinue(role) then return end local adv = role:getAdvData() local taskId = msg.taskId -- -1 则是主线任务 local status, reward @@ -270,7 +290,9 @@ function _M.clickBlockRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) + if not isCanContinue(role) then return end local adv = role:getAdvData() + if adv:isWaitChooseArtifact() then return end local status, errorCode = adv:clickBlock(msg.roomId, msg.blockId, msg) if not status then return errorCode end @@ -290,6 +312,7 @@ function _M.useItemRpc(agent, data) local itemData = csvdb["adv_itemCsv"][itemId] if not itemData then return end + if not isCanContinue(role) then return end local adv = role:getAdvData() if adv:isWaitChooseArtifact() then return end --重置数量 @@ -337,7 +360,8 @@ function _M.usePotionRpc(agent, data) local potionBag = role:getProperty("potionBag") local own = potionBag[potionId] or 0 if own <= 0 then return 4 end - + + if not isCanContinue(role) then return end local adv = role:getAdvData() if adv:isWaitChooseArtifact() then return end @@ -359,8 +383,10 @@ end function _M.chooseArtifactRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) - local adv = role:getAdvData() + if not isCanContinue(role) then return end + + local adv = role:getAdvData() if not msg.idx then return end if not adv:isWaitChooseArtifact() then return end local status = adv:chooseArtifact(msg.idx) @@ -378,6 +404,8 @@ function _M.wearArtifactRpc(agent, data) local slot = msg.slot local id = msg.id + if not isCanContinue(role) then return end + local adv = role:getAdvData() if math.illegalNum(slot, 1, 5) then return 1 end @@ -398,6 +426,8 @@ function _M.upArtifactRpc(agent, data) local msg = MsgPack.unpack(data) local id = msg.id + if not isCanContinue(role) then return end + local adv = role:getAdvData() if adv:isWaitChooseArtifact() then return 1 end local curLevel = adv:isHaveArtifact(id) @@ -421,6 +451,8 @@ end function _M.exitAdvRpc(agent, data) local role = agent.role -- local msg = MsgPack.unpack(data) + if not isCanContinue(role) then return end + local adv = role:getAdvData() local status = adv:exit() -- target {roomId = 1, blockId = 1} 选择的目标 SendPacket(actionCodes.Adv_exitAdvRpc, MsgPack.pack({events = adv:popBackEvents()})) @@ -438,8 +470,10 @@ function _M.startBattleRpc(agent, data) local monsterId = msg.monsterId local enemyId = msg.enemyId if not enemyId then return end + if not isCanContinue(role) then return end local adv = role:getAdvData() + if adv:isWaitChooseArtifact() then return end local enemy = adv.battle:getEnemyById(enemyId) @@ -467,6 +501,8 @@ function _M.endBattleRpc(agent, data) local bySkill = msg.bySkill --死于 技能 if not player or not player.hp or not player.sp or not enemyId or not key then return end + if not isCanContinue(role) then return end + local adv = role:getAdvData() if adv:isWaitChooseArtifact() then return end -- 校验 @@ -597,7 +633,7 @@ function _M.finishAchievRpc(agent, data) local taskId = msg.taskId -- 领取id local adv = role:getAdvData() - + local status, reward -- if ctype == 1 then -- status = adv:finishAchievement(chapterId, taskId) @@ -610,5 +646,40 @@ function _M.finishAchievRpc(agent, data) return true end +function _M.rankRpc(agent, data) + local role = agent.role + + local list = {} + local ids = redisproxy:zrevrange(RANK_ADV, 0 , 99) + local redret = {} + if ids and next(ids) then + redret = redisproxy:pipelining(function (red) + for i = 1, #ids do + local roleId = ids[i] + table.insert(list, {roleId = tonumber(roleId)}) + red:hget(RANK_ADV_INFO, roleId) + end + end) + end + for i = 1, #redret do + local player = MsgPack.unpack(redret[i]) + player.format = nil + list[i].player = player + end + local redret = redisproxy:pipelining(function(red) + red:ZREVRANK(RANK_ADV, role:getProperty("id")) + red:zscore(RANK_ADV, role:getProperty("id")) + end) + local rank = redret[1] + if not rank then + rank = -1 + else + rank = redret[1] + 1 + end + local score = tonum(redret[2], 0) + + SendPacket(actionCodes.Adv_rankRpc, MsgPack.pack({list = list, rank = rank, score = score})) + return true +end return _M \ No newline at end of file diff --git a/src/actions/GmAction.lua b/src/actions/GmAction.lua index b62055a..b633579 100644 --- a/src/actions/GmAction.lua +++ b/src/actions/GmAction.lua @@ -204,13 +204,7 @@ end table.insert(helpDes, {"冒险清除" , "advc"}) function _M.advc(role, pms) - role:updateProperty({field = "advInfo", value = {}}) - role:updateProperty({field = "advTask", value = {}}) - role:updateProperty({field = "advItems", value = ""}) - role:updateProperty({field = "advTeam", value = {}}) - role:updateProperty({field = "advAFGet", value = {}}) - role:updateProperty({field = "advAFWear", value = {}}) - role.advData = nil + role:getAdvData():forceOver() return "成功" end diff --git a/src/actions/RoleAction.lua b/src/actions/RoleAction.lua index b9a2efb..af28413 100644 --- a/src/actions/RoleAction.lua +++ b/src/actions/RoleAction.lua @@ -116,7 +116,7 @@ function _M.loginRpc( agent, data ) SERV_OPEN = redisproxy:hget("autoincrement_set", "server_start") role:changeStructVersion() -- 数据结构 版本更新 - role:advEndlessSeasonCheck() -- 冒险赛季更新检查 + role:advEndlessSeasonCheck(true) -- 冒险赛季更新检查 -- 跨天登陆事件 role:onCrossDay(now) diff --git a/src/adv/Adv.lua b/src/adv/Adv.lua index 963fe45..dd6c5a0 100644 --- a/src/adv/Adv.lua +++ b/src/adv/Adv.lua @@ -99,9 +99,30 @@ function Adv:clear() self.shopStatus = {} end +function Adv:isRunning() + if self.chapterId then return true end + return false +end + +-- 强制结束 +function Adv:forceOver(notNotify) + if self:isRunning() then + self:clear() + local advTeam = self.owner:getProperty("advTeam") + advTeam.player = nil + self.owner:updateProperties({ + advInfo = {}, + advTeam = advTeam, + advItems = "", + advAFGet = {}, + advAFWear = {}, + }, notNotify) + end +end + function Adv:saveDB(notNotify) local advInfo, advTeam = {}, self.owner:getProperty("advTeam") - if self.chapterId then + if self:isRunning() then advInfo.chapterId = self.chapterId advInfo.level = self.level @@ -401,14 +422,33 @@ function Adv:over(success, isAllPass) self.owner:checkTaskEnter("AdvAllPass", {id = self.chapterId}) end + local roleId = self.owner:getProperty("id") + local oldMaxScore = tonum(redisproxy:zscore(RANK_ADV, roleId)) + if score > oldMaxScore then + local team = self.owner:getProperty("advTeam") + local curInfo = { + name = self.owner:getProperty("name"), + headId = self.owner:getProperty("headId"), + lv = self.owner:getProperty("level"), + batteV = self:getTeamBattleValue(team.heros), + chapter = self.chapterId, + format = self.owner:getTeamHerosInfo(team.heros), + } + redisproxy:pipelining(function (red) + red:zadd(RANK_ADV, score, roleId) --更新分数 + red:hset(RANK_ADV_INFO, roleId, MsgPack.pack(curInfo)) + end) + end end self:clearAdvUnlockCache() self:clear() self.owner:checkTaskEnter("AdvScore", {score = score}) - self.owner:updateProperty({field = "advItems", value = ""}) - self.owner:updateProperty({field = "advAFGet", value = {}}) - self.owner:updateProperty({field = "advAFWear", value = {}}) + self.owner:updateProperties({ + advItems = "", + advAFGet = {}, + advAFWear = {}, + }) self:backEnd(success, score, scoreInfo, reward) end diff --git a/src/models/Role.lua b/src/models/Role.lua index 8ff7168..ce4903e 100644 --- a/src/models/Role.lua +++ b/src/models/Role.lua @@ -21,6 +21,9 @@ function Role:ctor( properties ) self.heros = {} self.runeBag = {} self.advData = nil + + self.advElChapter = tonum(redisproxy:hget("adv_season", "chapter"), globalCsv.adv_endless_default_chapter) -- 无尽模式记录的赛季对应章节 + self.advOverTime = tonum(redisproxy:hget("adv_season", "overTime")) -- 无尽模式关闭时间戳 end Role.schema = { @@ -64,7 +67,7 @@ Role.schema = { advAchiev = {"table", {}}, -- 冒险成就 {chapterId = {achievId = status, -1 = pt, pts = {}}, } advL = {"table", {0, 0}}, -- 冒险队等级 {lv, exp} advElM = {"number", 0}, -- 无尽模式通关的最高层数 endless max layer - advElS = {"number", globalCsv.adv_endless_season}, -- 无尽模式记录的赛季 endless season + advElS = {"number", 0}, -- 无尽模式记录的赛季 endless season advAFOpen = {"table", {}}, -- 解锁的神器 {[id] = 1} advAFGet = {"table", {}}, -- 当前拥有的神器 {[id] = 等级} advAFWear = {"table", {}}, -- 当前拥有的神器 {[slot] = id} @@ -254,6 +257,8 @@ function Role:data() advAchiev = self:getProperty("advAchiev"), advL = self:getProperty("advL"), advElM = self:getProperty("advElM"), + advElChapter = self.advElChapter, + advOverTime = self.advOverTime, advAFGet = self:getProperty("advAFGet"), advAFWear = self:getProperty("advAFWear"), advDrawB = self:getProperty("advDrawB"), diff --git a/src/models/RolePlugin.lua b/src/models/RolePlugin.lua index 7683a35..59f5cfa 100644 --- a/src/models/RolePlugin.lua +++ b/src/models/RolePlugin.lua @@ -772,12 +772,36 @@ function RolePlugin.bind(Role) end -- 赛季检查 - function Role:advEndlessSeasonCheck() - if self:getProperty("advElS") ~= globalCsv.adv_endless_season then + function Role:advEndlessSeasonCheck(notNotify) + -- 重置一下冒险 + local nowSeason = tonum(redisproxy:hget("adv_season", "idx")) + if self:getProperty("advElS") ~= nowSeason then local ml = self:getProperty("advElM") + local nl = math.max(0, ml - (math.floor(ml / 50) + 2) * 10) self:setProperty("advElM", math.floor(nl / 10) * 10) - self:setProperty("advElS", globalCsv.adv_endless_season) + self:setProperty("advElS", nowSeason) + + -- 正在无尽冒险清掉 + local adv = self:getAdvData() + if adv:isRunning() and adv:isEndless() then + adv:forceOver() + end + + -- 重新设定冒险章节和冒险结束时间 + self.advElChapter = tonum(redisproxy:hget("adv_season", "chapter"), globalCsv.adv_endless_default_chapter) + self.advOverTime = tonum(redisproxy:hget("adv_season", "overTime")) + + if not notNotify then + SendPacket(actionCodes.Role_updateProperties, MsgPack.pack({ + advElChapter = self.advElChapter, + advOverTime = self.advOverTime, + })) + end + -- 清掉冒险手册 + self:updateProperties({ + advEAchiev = {}, + }, notNotify) end end diff --git a/src/python/adv_season.py b/src/python/adv_season.py new file mode 100644 index 0000000..234c060 --- /dev/null +++ b/src/python/adv_season.py @@ -0,0 +1,12 @@ + +from redisCommon import redis, pipe, decode, encode + +import time, datetime + + +lastOverTime = int(time.mktime(datetime.date.today().timetuple())) + 3600 * 24 * 14 #取当天0点 + + + + + diff --git a/src/python/redisCommon.py b/src/python/redisCommon.py new file mode 100644 index 0000000..16b58a5 --- /dev/null +++ b/src/python/redisCommon.py @@ -0,0 +1,78 @@ +from redis import Redis +import msgpack + +redisConf = { + "host" : "127.0.0.1", + "port" : 6100, + "db" : 1, + "password" : None, +} + + +def numberUnpack(n) : + if isinstance(n, bytes) : + try: + return int(n) + except ValueError: + try: + return float(n) + except ValueError: + pass + return n.decode() + else : + return n + +def stringUnpack(s) : + if isinstance(s, bytes) : + return n.decode() + else : + return s + +def tableUnpack(t) : + if isinstance(t, bytes) : + return msgpack.unpackb(t, raw = False) #解包 + else : + return t + +redisUnpack = { + "number" : numberUnpack, + "string" : stringUnpack, + "table" : tableUnpack, + "default" : numberUnpack, +} +def commonPack(w) : + return w + +def tablePack(t): + return msgpack.packb(t, use_bin_type = True) + +redisPack = { + "default" : commonPack, + "table" : tablePack, +} + + + + +redis = Redis( + host = redisConf["host"], + port = redisConf["port"], + db = redisConf["db"], + password = redisConf["password"] +) + +pipe = redis.pipeline() + +def decode(w, t = "default"): + return redisUnpack[t](w) + +def encode(w, t = "default") : + return redisPack[t](w) + + + + + + + + diff --git a/src/python/requirements.txt b/src/python/requirements.txt new file mode 100644 index 0000000..e10f065 --- /dev/null +++ b/src/python/requirements.txt @@ -0,0 +1,2 @@ +redis +msgpack \ No newline at end of file diff --git a/src/services/dbseed.lua b/src/services/dbseed.lua index 3a889e8..ee212aa 100644 --- a/src/services/dbseed.lua +++ b/src/services/dbseed.lua @@ -23,6 +23,9 @@ local function initRedisDb( ... ) redisproxy:hsetnx("autoincrement_set", "email", 0) redisproxy:hsetnx("autoincrement_set", "emailTimestamp", 0) redisproxy:hsetnx("autoincrement_set", "delay_email", 0) + redisproxy:hsetnx("adv_season", "idx", 0) + redisproxy:hsetnx("adv_season", "chapter", globalCsv.adv_endless_default_chapter) + redisproxy:hsetnx("adv_season", "overTime", 0) end end -- libgit2 0.21.2