local ipairs = ipairs local table = table local math = math local redisproxy = redisproxy local MsgPack = MsgPack local httpc = require("http.httpc") local remoteUrl = skynet.getenv("codeurl") local _M = {} local _pvpBattleInfoCacheC = {} --查询列表 缓存pvp战斗相关数据缓存 local _pvpBattleInfoCacheH = {} --查询列表 缓存pvp战斗相关数据缓存 local _pvpHeroInfoCacheH = {} --查询列表 缓存pvp 英雄相关数据缓存 local _pvpStartBattleCacheC = nil -- 当前战斗缓存 local _pvpStartBattleCacheH = nil -- 当前战斗缓存 local _pvpRecordInfoCacheC = {} -- 记录缓存 local _pvpRecordInfoCacheH = {} -- 记录缓存 local _pvpRecordBattleInfoCacheC = {} -- 记录战斗数据缓存 local _pvpRecordBattleInfoCacheH = {} -- 记录战斗数据缓存 local _pvpRecordHeroInfoCacheH = {} --查询列表 缓存pvp 英雄相关数据缓存 local _revengeRecord = {} -- 复仇对单人1分钟间隔 local RevengeWaitTime = 60 function _M.formatCommonRpc(agent , data) if true then return end local role = agent.role local roleId = role:getProperty("id") local msg = MsgPack.unpack(data) local pvpTC = role:getProperty("pvpTC") for slot, heroId in pairs(msg.heros or {}) do if not role.heros[heroId] then return end end if not msg.heros or not next(msg.heros) then return end local supports = {} for slot, support in pairs(msg.supports) do if slot ~= 1 and slot ~= 2 then return end local level = role.dinerData:getProperty("dishTree"):getv(support, 0) if level <= 0 then return end supports[slot] = support end table.clear(pvpTC) pvpTC.heros = {} for slot, heroId in pairs(msg.heros) do pvpTC.heros[slot] = heroId end pvpTC.leader = msg.leader pvpTC.supports = supports if msg.tactics and globalCsv.tactics_skill_passive_cell[msg.tactics] then pvpTC.tactics = msg.tactics end role:savePvpCTeam(pvpTC) SendPacket(actionCodes.Pvp_formatCommonRpc, '') return true end function _M.formatHighRpc(agent , data) local role = agent.role local roleId = role:getProperty("id") local msg = MsgPack.unpack(data) if not role:isCrossServerPvpPlayer() then return end local pvpTH = {} local had = {} -- 上阵的角色 local supportHad = {} for i = 1, 3 do local team = msg.teams[i] if not team then return end if not team.heros or not next(team.heros) then return end for slot, heroId in pairs(team.heros or {}) do if not role.heros[heroId] or had[heroId] then return end had[heroId] = 1 end local supports = {} for slot, support in pairs(team.supports) do if slot ~= 1 and slot ~= 2 then return end local level = role.dinerData:getProperty("dishTree"):getv(support, 0) if level <= 0 or supportHad[support] then return end supports[slot] = support supportHad[support] = 1 end local curTeam = {} curTeam.heros = team.heros curTeam.leader = team.leader curTeam.supports = supports if team.tactics and globalCsv.tactics_skill_passive_cell[team.tactics] then curTeam.tactics = team.tactics end table.insert(pvpTH, curTeam) end role:savePvpHTeam(pvpTH) role:changeCrossServerPvpSelfInfo("format") SendPacket(actionCodes.Pvp_formatHighRpc, '') return true end local function getMatchInfo(role, pvpList, battleCache, dbKey, infoFuncName, infoCache) table.clear(battleCache) local dbKey = role:getPvpDBKey(dbKey) local redret = redisproxy:pipelining(function(red) for _, info in ipairs(pvpList) do if info.t == 1 then red:zscore(dbKey, info.id) end end end) local matches = {} local curIdx = 1 for idx, info in ipairs(pvpList) do local curInfo = {idx = idx} if info.t == 1 then --玩家 curInfo.roleId = info.id curInfo.score = role:unpackPvpScore(redret[curIdx] or 0) curIdx = curIdx + 1 -- name, level, headId, battleV, heros local online, roleInfo = rpcRole(curInfo.roleId, infoFuncName) for k , v in pairs(roleInfo) do if k == "battleInfo" then battleCache[curInfo.roleId] = v else if (k == "team" or k == "battleV") and infoCache then infoCache[curInfo.roleId] = infoCache[curInfo.roleId] or {} infoCache[curInfo.roleId][k] = v end curInfo[k] = v end end elseif info.t == 2 then -- robot curInfo.robot = info.id end table.insert(matches, curInfo) end return matches end -- 获取pvp信息 function _M.infoRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") local msg = MsgPack.unpack(data) local ptype = msg.ptype or 1 if not role:isFuncUnlock(FuncUnlock.Pvp) then return end local response = {} if ptype == 1 then -- 普通pvp local dbKey = role:getPvpDBKey(RANK_PVP_COMMON) local redret = redisproxy:pipelining(function(red) red:zscore(dbKey, roleId) red:zrevrank(dbKey, roleId) end) local score = role:unpackPvpScore(redret[1]) local rank = tonumber(redret[2] or -2) + 1 --排名 1 - ... -1 未上榜 没打过pvp local pvpMC = role:getProperty("pvpMC") if not next(pvpMC) then --没有分配过对手 role:refreshPvpMatchC(score, -1) pvpMC = role:getProperty("pvpMC") end if not next(pvpMC) then return end response.rank = rank response.score = score response.matches = getMatchInfo(role, pvpMC, _pvpBattleInfoCacheC, RANK_PVP_COMMON, "pvpCInfo") elseif ptype == 2 then -- 高级pvp if not role:isTimeResetOpen(TimeReset.PvpHight) then return end local dbKey = role:getPvpDBKey(RANK_PVP_HIGHT) local redret = redisproxy:pipelining(function(red) red:zscore(dbKey, roleId) red:zrevrank(dbKey, roleId) end) local score = role:unpackPvpScore(redret[1]) local rank = tonumber(redret[2] or -2) + 1 --排名 1 - ... -1 未上榜 没打过pvp local pvpMH = role:getProperty("pvpMH") if not next(pvpMH) then --没有分配过对手 role:refreshPvpMatchH(score, -1) pvpMH = role:getProperty("pvpMH") end if not next(pvpMH) then return end response.rank = rank response.score = score response.matches = getMatchInfo(role, pvpMH, _pvpBattleInfoCacheH, RANK_PVP_HIGHT, "pvpHInfo", _pvpHeroInfoCacheH) else return end SendPacket(actionCodes.Pvp_infoRpc, MsgPack.pack(response)) return true end function _M.refreshMatchCRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) role:refreshPvpMatchC() local pvpMC = role:getProperty("pvpMC") local matches = getMatchInfo(role, pvpMC, _pvpBattleInfoCacheC, RANK_PVP_COMMON, "pvpCInfo") SendPacket(actionCodes.Pvp_refreshMatchCRpc, MsgPack.pack({matches = matches})) return true end function _M.refreshMatchHRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) if not role:isTimeResetOpen(TimeReset.PvpHight) then return end role:refreshPvpMatchH() local pvpMH = role:getProperty("pvpMH") local matches = getMatchInfo(role, pvpMH, _pvpBattleInfoCacheH, RANK_PVP_HIGHT, "pvpHInfo", _pvpHeroInfoCacheH) SendPacket(actionCodes.Pvp_refreshMatchHRpc, MsgPack.pack({matches = matches})) return true end function _M.buyCountRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local count = msg.count if math.illegalNum(count, 1, math.huge) then return 1 end local cost = {[ItemId.Diamond] = globalCsv.pvp_buy_cost * count} if not role:checkItemEnough(cost) then return 2 end role:costItems(cost, {log = {desc = "buyPvpKey"}}) role:award({[ItemId.PvpKey] = count}, {log = {desc = "buyPvpKey"}}) SendPacket(actionCodes.Pvp_buyCountRpc, '') return true end function _M.startBattleRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local idx = msg.idx local revenge = msg.revenge -- local pvpTC = role:getProperty("pvpTC") -- if not pvpTC.heros or not next(pvpTC.heros) then return 1 end local team = msg.team if not team then return end for slot, heroId in pairs(team.heros or {}) do if not role.heros[heroId] then return end end if not team.heros or not next(team.heros) then return end local supports = {} for slot, support in pairs(team.supports) do if slot ~= 1 and slot ~= 2 then return end local level = role.dinerData:getProperty("dishTree"):getv(support, 0) if level <= 0 then return end supports[slot] = support end local pvpTC = {} pvpTC.heros = {} for slot, heroId in pairs(team.heros) do pvpTC.heros[slot] = heroId end pvpTC.leader = team.leader pvpTC.supports = supports if team.tactics and globalCsv.tactics_skill_passive_cell[team.tactics] then pvpTC.tactics = team.tactics end local matchInfo, result, key, wait local now = skynet.timex() if revenge then --复仇 local temp = _pvpRecordInfoCacheC[idx] if not temp then return 2 end if not _revengeRecord[temp.id] or now >= _revengeRecord[temp.id] then if temp.t == 1 then matchInfo = _pvpRecordBattleInfoCacheC[temp.id] elseif temp.t == 2 then matchInfo = {robot = temp.id} end else result = 1 wait = _revengeRecord[temp.id] - now end else --打正常 local pvpMC = role:getProperty("pvpMC") if not pvpMC[idx] then return 3 end if pvpMC[idx].t == 1 then matchInfo = _pvpBattleInfoCacheC[pvpMC[idx].id] elseif pvpMC[idx].t == 2 then matchInfo = {robot = pvpMC[idx].id} end end if not result and not matchInfo then return 4 end if not result then -- 次数扣一波 local pvpFree = role.dailyData:getProperty("pvpFree") if pvpFree >= globalCsv.pvp_battle_free_count then local cost = {[ItemId.PvpKey] = 1} if not role:checkItemEnough(cost) then return 5 end role:costItems(cost, {log = {desc = "startPvp", int1 = 1}}) else role.dailyData:updateProperty({field = "pvpFree", delta = 1}) end key = tostring(math.random()) _pvpStartBattleCacheC = {idx = idx, key = key, revenge = revenge, pvpTC = pvpTC} role:checkTaskEnter("PvpBattle") role:mylog("pvp_action", {desc = "startBattle", short1 = 1, int1 = revenge and 1 or 0}) end SendPacket(actionCodes.Pvp_startBattleRpc, MsgPack.pack({matchInfo = matchInfo, key = key, result = result, wait = wait})) return true end function _M.endBattleRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") local msg = MsgPack.unpack(data) if not msg.key or not _pvpStartBattleCacheC or msg.key ~= _pvpStartBattleCacheC.key then SendPacket(actionCodes.Pvp_endBattleRpc, MsgPack.pack({errorCode = 1})) return true end if not msg.idx or msg.idx ~= _pvpStartBattleCacheC.idx then return 2 end local isWin = msg.starNum and msg.starNum > 0 local now = skynet.timex() local revenge = _pvpStartBattleCacheC.revenge local match if revenge then match = _pvpRecordInfoCacheC[msg.idx] _revengeRecord[match.id] = now + RevengeWaitTime -- 1分钟内不能再打 else local pvpMC = role:getProperty("pvpMC") match = pvpMC[msg.idx] end if not match then return end -- 防作弊 if not role:checkBattleCheat("pvpc", { isWin = isWin, info = msg.info, format = _pvpStartBattleCacheC.pvpTC, }) then SendPacket(actionCodes.Pvp_endBattleRpc, MsgPack.pack({errorCode = 1})) return true end local temp = string.randWeight(csvdb["player_expCsv"][role:getProperty("level")].pvpBonus, true) local reward, change = role:award({[temp[1]] = temp[2]}, {log = {desc = "pvpBattleC"}}) local myScore, matchScore, oldmyScore, oldMatchScore, myRank, oldMyRank = 0, 0, 0, 0, -1, -1 -- 失败了没再排行榜 不计入 if isWin or (not isWin and role:isInPvpRank(RANK_PVP_COMMON)) then myScore, matchScore, oldmyScore, oldMatchScore, myRank, oldMyRank= role:changePvpScoreCommon(match.t == 1 and match.id or -1, isWin) end if isWin then -- 记录编队 role:savePvpCTeam(_pvpStartBattleCacheC.pvpTC) end -- 请求上传录像 local params = { ["roleid"] = roleId, ["key"] = "zhaolugame20191016", ["time"] = now, } local status, body = httpc.get(remoteUrl, "/applyvideo?" .. httpGetFormatData(params), {}, {}) local video, headers = nil, nil if tonumber(status) == 200 then local result = json.decode(body) video = result.name headers = result.headers else skynet.error("applyvideo", "error", status, body) end -- 加入战斗记录 redisproxy:pipelining(function(red) local dbKey = string.format(RECORD_PVP_COMMON, roleId) red:lpush(dbKey, MsgPack.pack({ id = match.id, t = match.t, win = isWin, time = now, video = video, sdelta = myScore - oldmyScore, })) red:ltrim(dbKey, 0, 9) -- 对方加入战斗记录 if match.t == 1 then dbKey = string.format(RECORD_PVP_COMMON, match.id) red:lpush(dbKey, MsgPack.pack({ id = roleId, t = 1, win = not isWin, time = now, video = video, sdelta = matchScore - oldMatchScore, })) red:ltrim(dbKey, 0, 9) rpcRole(match.id, "redPTag", RedPointTags.PvpCR, now) end end) if isWin then role:checkTaskEnter("PvpWin", {score = myScore}) end role:checkBattle("pvpc", { isWin = isWin, info = msg.info, robotId = match.t == 2 and match.id or nil, enemy = match.t == 1 and _pvpBattleInfoCacheC[match.id] or nil, score = myScore, reward = reward, rank = myRank, }) role:mylog("pvp_action", {desc = "battleEnd", short1 = 1, int1 = isWin and 1 or 0, int2 = revenge and 1 or 0}) _pvpBattleInfoCacheC = {} --重新发阵容了 没毛病 _pvpRecordInfoCacheC = {} -- 记录刷新了 _pvpRecordBattleInfoCacheC = {} -- 取新纪录的时候搞 _pvpStartBattleCacheC = nil SendPacket(actionCodes.Pvp_endBattleRpc, MsgPack.pack({ reward = reward, change = change, myScore = myScore, matchScore = matchScore, oldmyScore = oldmyScore, oldMatchScore = oldMatchScore, myRank = myRank, oldMyRank = oldMyRank, video = video, headers = headers, })) return true end function _M.startBattleHRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local idx = msg.idx local revenge = msg.revenge if not role:isTimeResetOpen(TimeReset.PvpHight) then return end -- local pvpTH = role:getProperty("pvpTH") -- if not next(pvpTH) then return 1 end -- 检查并记录玩家队伍 local pvpTH = {} local had = {} -- 上阵的角色 local supportHad = {} for i = 1, 3 do local team = msg.teams[i] if not team then return end if not team.heros or not next(team.heros) then return end for slot, heroId in pairs(team.heros or {}) do if not role.heros[heroId] or had[heroId] then return end had[heroId] = 1 end local supports = {} for slot, support in pairs(team.supports) do if slot ~= 1 and slot ~= 2 then return end local level = role.dinerData:getProperty("dishTree"):getv(support, 0) if level <= 0 or supportHad[support] then return end supports[slot] = support supportHad[support] = 1 end local curTeam = {} curTeam.heros = team.heros curTeam.leader = team.leader curTeam.supports = supports if team.tactics and globalCsv.tactics_skill_passive_cell[team.tactics] then curTeam.tactics = team.tactics end table.insert(pvpTH, curTeam) end local enemyTeamRecord, result, key, wait, enemyT, matchInfo local now = skynet.timex() if revenge then --复仇 local temp = _pvpRecordInfoCacheH[idx] if not temp then return 2 end if not _revengeRecord[temp.id] or now >= _revengeRecord[temp.id] then if temp.t == 1 then enemyTeamRecord = _pvpRecordBattleInfoCacheH[temp.id] enemyT = _pvpRecordHeroInfoCacheH[temp.id] elseif temp.t == 2 then enemyTeamRecord = {robot = temp.id} end else result = 1 wait = _revengeRecord[temp.id] - now end else --打正常 local pvpMH = role:getProperty("pvpMH") if not pvpMH[idx] then return 3 end if pvpMH[idx].t == 1 then enemyTeamRecord = _pvpBattleInfoCacheH[pvpMH[idx].id] enemyT = _pvpHeroInfoCacheH[pvpMH[idx].id] elseif pvpMH[idx].t == 2 then enemyTeamRecord = {robot = pvpMH[idx].id} end end if not result and not enemyTeamRecord then return 4 end if not result then -- 次数扣一波 local pvpFreeH = role.dailyData:getProperty("pvpFreeH") if pvpFreeH >= globalCsv.pvp_battle_free_count_high then local cost = {[ItemId.PvpKey] = globalCsv.pvp_battle_high_cost} if not role:checkItemEnough(cost) then return 5 end role:costItems(cost, {log = {desc = "startPvp", int1 = 2}}) else role.dailyData:updateProperty({field = "pvpFreeH", delta = 1}) end -- 只发送指定的那个敌人 if enemyTeamRecord.robot then matchInfo = enemyTeamRecord else matchInfo = enemyTeamRecord[1] end key = tostring(math.random()) _pvpStartBattleCacheH = { idx = idx, -- 数据索引 key = key, -- 战斗校验 key revenge = revenge, -- 是否是复仇 result = {}, -- 战斗记录 pvpTH = pvpTH, -- 我方队伍缓存 enemyTB = enemyTeamRecord, --敌方战斗队伍缓存 enemyT = enemyT, } role:checkTaskEnter("PvpBattle") role:mylog("pvp_action", {desc = "startBattle", short1 = 2, int1 = revenge and 1 or 0}) end SendPacket(actionCodes.Pvp_startBattleHRpc, MsgPack.pack({ matchInfo = matchInfo, --敌方队伍 信息 key = key, --战斗校验 key round = 1, -- 战斗场数索引 result = result, -- 返回状态 wait = wait -- 等待复仇时间 })) return true end function _M.endBattleHRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") local msg = MsgPack.unpack(data) if not msg.key or not _pvpStartBattleCacheH or msg.key ~= _pvpStartBattleCacheH.key then SendPacket(actionCodes.Pvp_endBattleHRpc, MsgPack.pack({errorCode = 1})) return true end if not msg.idx or msg.idx ~= _pvpStartBattleCacheH.idx then return 2 end local isWin = msg.starNum and msg.starNum > 0 local now = skynet.timex() local revenge = _pvpStartBattleCacheH.revenge local match if revenge then match = _pvpRecordInfoCacheH[msg.idx] _revengeRecord[match.id] = now + RevengeWaitTime -- 1分钟内不能再打 else local pvpMH = role:getProperty("pvpMH") match = pvpMH[msg.idx] end if not match then return end -- 请求上传录像 local params = { ["roleid"] = roleId, ["key"] = "zhaolugame20191016", ["time"] = now, } local status, body = httpc.get(remoteUrl, "/applyvideo?" .. httpGetFormatData(params), {}, {}) local video, headers = nil, nil if tonumber(status) == 200 then local result = json.decode(body) video = result.name headers = result.headers else skynet.error("applyvideo", "error", status, body) end table.insert(_pvpStartBattleCacheH.result, { isWin = isWin, video = video, }) -- 检查是否结束战斗 local winCount, loseCount = 0, 0 for _, status in pairs(_pvpStartBattleCacheH.result) do if status.isWin then winCount = winCount + 1 else loseCount = loseCount + 1 end end -- 防作弊 if not role:checkBattleCheat("pvph", { isWin = isWin, info = msg.info, format = _pvpStartBattleCacheH.pvpTH[#_pvpStartBattleCacheH.result] }) then SendPacket(actionCodes.Pvp_endBattleHRpc, MsgPack.pack({errorCode = 1})) return true end if winCount >= 2 then isWin = true elseif loseCount >= 2 then isWin = false else -- 没结束 -- 返回继续战斗 local key = tostring(math.random()) _pvpStartBattleCacheH.key = key local round = #_pvpStartBattleCacheH.result + 1 local matchInfo = nil if _pvpStartBattleCacheH.enemyTB.robot then matchInfo = _pvpStartBattleCacheH.enemyTB else matchInfo = _pvpStartBattleCacheH.enemyTB[round] end -- 继续战斗 SendPacket(actionCodes.Pvp_endBattleHRpc, MsgPack.pack({ matchInfo = matchInfo, --敌方队伍 信息 key = key, --战斗校验 key round = round, -- 战斗场数索引 video = video, -- 返回让客户端上传录像 headers = headers, })) return true end -- 战斗结束了发奖 local temp = string.randWeight(csvdb["player_expCsv"][role:getProperty("level")].pvpgroupBonus, true) local reward, change = role:award({[temp[1]] = temp[2]}, {log = {desc = "pvpBattleH"}}) local myScore, matchScore, oldmyScore, oldMatchScore, myRank, oldMyRank = 0, 0, 0, 0, -1, -1 -- 失败了没再排行榜 不计入 if role:isTimeResetOpen(TimeReset.PvpHight) then if isWin or (not isWin and role:isInPvpRank(RANK_PVP_HIGHT)) then myScore, matchScore, oldmyScore, oldMatchScore, myRank, oldMyRank = role:changePvpScoreHigh(match.t == 1 and match.id or -1, isWin) end -- 记录编队 if isWin then role:savePvpHTeam(_pvpStartBattleCacheH.pvpTH) end end -- 加入战斗记录 local selfTeam = {} local enemyTeam = {} for _idx, info in ipairs(_pvpStartBattleCacheH.result) do info.winId = info.isWin and roleId or match.id info.isWin = nil selfTeam[_idx] = { team = role:getTeamHerosInfo(_pvpStartBattleCacheH.pvpTH[_idx]), battleV = role:getTeamBattleValue(_pvpStartBattleCacheH.pvpTH[_idx].heros) } if match.t == 1 and _pvpStartBattleCacheH.enemyT then enemyTeam[_idx] = { team = _pvpStartBattleCacheH.enemyT["team"][_idx], battleV = _pvpStartBattleCacheH.enemyT["battleV"][_idx] } end end local recordBattle = { result = _pvpStartBattleCacheH.result, [roleId] = selfTeam, [match.id] = enemyTeam } redisproxy:pipelining(function(red) local dbKey = string.format(RECORD_PVP_HIGH, roleId) red:lpush(dbKey, MsgPack.pack({ id = match.id, t = match.t, win = isWin, time = now, sdelta = myScore - oldmyScore, -- 队伍信息 record = recordBattle, })) red:ltrim(dbKey, 0, 9) -- 对方加入战斗记录 if match.t == 1 then dbKey = string.format(RECORD_PVP_HIGH, match.id) red:lpush(dbKey, MsgPack.pack({ id = roleId, t = 1, win = not isWin, time = now, sdelta = matchScore - oldMatchScore, -- 队伍信息 record = recordBattle, })) red:ltrim(dbKey, 0, 9) rpcRole(match.id, "redPTag", RedPointTags.PvpHR, now) end end) role:checkBattle("pvph", { isWin = isWin, info = msg.info, robotId = match.t == 2 and match.id or nil, enemy = match.t == 1 and (revenge and _pvpRecordBattleInfoCacheH[match.id] or _pvpBattleInfoCacheH[match.id]) or nil, score = myScore, reward = reward, rank = myRank, }) _pvpBattleInfoCacheH = {} --重新发阵容了 没毛病 _pvpRecordInfoCacheH = {} -- 记录刷新了 _pvpRecordBattleInfoCacheH = {} -- 取新纪录的时候搞 _pvpStartBattleCacheH = nil _pvpHeroInfoCacheH = {} _pvpRecordHeroInfoCacheH = {} if isWin then role:checkTaskEnter("PvpWin", {score = myScore}) end role:mylog("pvp_action", {desc = "battleEnd", short1 = 2, int1 = isWin and 1 or 0, int2 = revenge and 1 or 0}) SendPacket(actionCodes.Pvp_endBattleHRpc, MsgPack.pack({ reward = reward, change = change, myScore = myScore, matchScore = matchScore, oldmyScore = oldmyScore, oldMatchScore = oldMatchScore, myRank = myRank, oldMyRank = oldMyRank, video = video, headers = headers, isWin = isWin, })) return true end function _M.rankListRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") local msg = MsgPack.unpack(data) local ptype = msg.ptype or 1 local response = {} if ptype == 1 then -- 普通pvp local dbKey = role:getPvpDBKey(RANK_PVP_COMMON) local redret = redisproxy:pipelining(function(red) red:zscore(dbKey, roleId) red:zrevrank(dbKey, roleId) red:zrevrange(dbKey, 0, 99, "WITHSCORES") end) local score = role:unpackPvpScore(redret[1]) local rank = tonumber(redret[2] or -2) + 1 --排名 1 - ... -1 未上榜 没打过pvp local rankList = {} for i = 1, #redret[3], 2 do local roleId = tonumber(redret[3][i]) local score = role:unpackPvpScore(redret[3][i + 1]) local online, curInfo = rpcRole(roleId, "friendSInfo") curInfo.score = score curInfo.roleId = roleId table.insert(rankList, curInfo) end response.score = score response.rank = rank response.rankList = rankList elseif ptype == 2 then -- 高级pvp local dbKey = role:getPvpDBKey(RANK_PVP_HIGHT) local redret = redisproxy:pipelining(function(red) red:zscore(dbKey, roleId) red:zrevrank(dbKey, roleId) red:zrevrange(dbKey, 0, 99, "WITHSCORES") end) local score = role:unpackPvpScore(redret[1]) local rank = tonumber(redret[2] or -2) + 1 --排名 1 - ... -1 未上榜 没打过pvp local rankList = {} for i = 1, #redret[3], 2 do local roleId = tonumber(redret[3][i]) local score = role:unpackPvpScore(redret[3][i + 1]) local online, curInfo = rpcRole(roleId, "pvpHRankInfo") curInfo.score = score curInfo.roleId = roleId table.insert(rankList, curInfo) end response.score = score response.rank = rank response.rankList = rankList else return end SendPacket(actionCodes.Pvp_rankListRpc, MsgPack.pack(response)) return true end function _M.recordListRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") local msg = MsgPack.unpack(data) local ptype = msg.ptype or 1 local recordList = {} local now = skynet.timex() if ptype == 1 then -- 普通pvp local rlist = redisproxy:lrange(string.format(RECORD_PVP_COMMON, roleId), 0 , 9) local tempList = {} for _, temp in ipairs(rlist) do local one = MsgPack.unpack(temp) if now - one.time <= globalCsv.pvp_record_keep_time then -- 大于一天的弃之 table.insert(tempList, one) end end _pvpRecordInfoCacheC = tempList recordList = getMatchInfo(role, tempList, _pvpRecordBattleInfoCacheC, RANK_PVP_COMMON, "pvpCInfo") for idx, info in ipairs(recordList) do local temp = tempList[idx] info.win = temp.win info.time = temp.time info.video = temp.video info.sdelta = temp.sdelta end role:clearRedPTag(RedPointTags.PvpCR) elseif ptype == 2 then -- 高级pvp local rlist = redisproxy:lrange(string.format(RECORD_PVP_HIGH, roleId), 0 , 9) local tempList = {} for _, temp in ipairs(rlist) do local one = MsgPack.unpack(temp) if now - one.time <= globalCsv.pvp_record_keep_time then -- 大于一天的弃之 table.insert(tempList, one) end end _pvpRecordInfoCacheH = tempList recordList = getMatchInfo(role, tempList, _pvpRecordBattleInfoCacheH, RANK_PVP_HIGHT, "pvpHInfo", _pvpRecordHeroInfoCacheH) for idx, info in ipairs(recordList) do local temp = tempList[idx] info.win = temp.win info.time = temp.time info.sdelta = temp.sdelta info.record = temp.record end role:clearRedPTag(RedPointTags.PvpHR) else return end SendPacket(actionCodes.Pvp_recordListRpc, MsgPack.pack({list = recordList})) return true end function _M.highDivisionGiftRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") local pvpHGTime = role:getProperty("pvpHGTime") if pvpHGTime == 0 then return end local newTime, newReward = role:calculatePvpHGift(role:getPvpHDivision()) if not next(newReward) then return end role:updateProperties({ pvpHGTime = newTime, pvpHGift = {}, }) local reward, change = role:award(newReward, {log = {desc = "pvpDivisionH"}}) role:mylog("pvp_action", {desc = "pvpDivisionH"}) SendPacket(actionCodes.Pvp_highDivisionGiftRpc, MsgPack.pack(role:packReward(reward, change))) return true end function _M.shopBuyRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") local msg = MsgPack.unpack(data) local id = msg.id local count = msg.count or 1 local csvData = csvdb["shop_pvpCsv"][id] if not csvData then return end local pvpShop = role:getProperty("pvpShop") if csvData.limit > 0 then if math.illegalNum(count, 1, csvData.limit - (pvpShop[id] or 0)) then return end end if not role:checkItemEnough({[ItemId.PvpCoin] = csvData.cost * count}) then return end role:costItems({[ItemId.PvpCoin] = csvData.cost * count}, {log = {desc = "pvpShop", int1 = id, int2 = count}}) if csvData.limit > 0 then role:changeUpdates({{type = "pvpShop", field = id, value = (pvpShop[id] or 0) + count}}) end local gift = csvData.gift:toNumMap() for id, c in pairs(gift) do gift[id] = c * count end local reward, change = role:award(gift, {log = {desc = "pvpShop", int1 = id, int2 = count}}) role:mylog("pvp_action", {desc = "pvpShop", int1 = id, int2 = count}) SendPacket(actionCodes.Pvp_shopBuyRpc, MsgPack.pack(role:packReward(reward, change))) return true end ----------------------------跨服竞技场---------------------------------- function _M.crossInfoRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") if not role:isTimeResetOpen(TimeReset.PvpCross) then return end local result = role:getCrossServerPvpMatchInfo() if not result then return end SendPacket(actionCodes.Pvp_crossInfoRpc, MsgPack.pack(result)) return true end function _M.crossRoleInfoRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") if not role:isTimeResetOpen(TimeReset.PvpCross) then return end local result = role:getCrossServerPvpRoleInfo() if not result then return end SendPacket(actionCodes.Pvp_crossRoleInfoRpc, MsgPack.pack({roleInfo = result})) return true end function _M.crossRoleInfoDetailRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") if not role:isTimeResetOpen(TimeReset.PvpCross) then return end local msg = MsgPack.unpack(data) if not msg.ids or not next(msg.ids) then return end local result = role:getCrossServerPvpRoleInfoDeatil(msg.ids) if not result then return end SendPacket(actionCodes.Pvp_crossRoleInfoDetailRpc, MsgPack.pack(result)) return true end function _M.crossMatchRecordRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") if not role:isTimeResetOpen(TimeReset.PvpCross) then return 1 end local msg = MsgPack.unpack(data) if not msg.round then return 2 end if not msg.matchIdx then return 3 end local result = role:getCrossServerPvpMatchRecord(msg.round, msg.matchIdx) if not result then return 4 end SendPacket(actionCodes.Pvp_crossMatchRecordRpc, MsgPack.pack(result)) return true end function _M.crossBetInfoRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") if not role:isTimeResetOpen(TimeReset.PvpCross) then return end local result = role:getCrossServerPvpBetInfo() if not result then return end SendPacket(actionCodes.Pvp_crossBetInfoRpc, MsgPack.pack(result)) return true end function _M.crossBetRpc(agent, data) local role = agent.role local roleId = role:getProperty("id") local msg = MsgPack.unpack(data) if not role:isTimeResetOpen(TimeReset.PvpCross) then return 1 end if msg.idx ~= 1 and msg.idx ~= 2 then return 2 end local result, code = role:setCrossServerPvpBet(msg.idx) if not result then return 10 + code end role:mylog("pvp_action", {desc = "crossBet"}) SendPacket(actionCodes.Pvp_crossBetRpc, MsgPack.pack(result)) return true end return _M