-- 诸神圣域(跨服) -- A 先挑战B, C跟着挑战B, 挑战都胜利, C先于A把结果发到跨服上。处理方式: C先与B交换排名, A再与C交换排名 local InnerMsg = require("core.InnerMsg") local CombatVideo = require("combat.CombatVideo") local GodsAreaDB = require("godsArea.GodsAreaDB") local MiddleManager = require("middle.MiddleManager") local GodsAreaConfig = require("excel.godsArea") local Log = require("common.Log") local Timer = require("core.Timer") local Util = require("common.Util") -- 请求战斗到结束时间: 5s local MAX_CHALLENGE_TIME = 5 -- 每天发奖时间, 晚上23:00 local SEND_REWARD_HOUR = 23 -- 正在被挑战的排名列表 local challengeList = {} local function getSameIdx(heroList, targetUid) for k, v in pairs(heroList) do if v.heroUuid == targetUid then return k end end end -- 通过uid查找排名 local function getRankInfoByUid(rankList, uid) local finalRank = 0 for rank, rankData in ipairs(rankList) do if rankData.uid and rankData.uid == uid then return rank, rankData end end return finalRank end -- 获取某个服的在榜人数 local function getRankListBySrvId(rankList, targetSrvId) local rankTb = {} for rank, rankData in ipairs(rankList) do if rankData.serverId and rankData.serverId == targetSrvId then rankTb[rankData.uid] = rank end end return rankTb end -- 清理超时的挑战数据 local function clearChallengeList() if not next(challengeList) then return end local now = os.time() for k ,v in pairs(challengeList) do if v.startTime + MAX_CHALLENGE_TIME < now then challengeList[k] = nil end end end local function writeLog(logId ,logStr) -- Log.write(Log.LOGID_OSS_GODSAREA_CHALLENGE, logStr) Log.write(logId, logStr) end local function getAllSrvFd() local fdList = MiddleManager.MiddleManager_GetAllFD() local fdArray = {} local len = 0 for srvId, fd in pairs(fdList) do len = len + 1 fdArray[len] = {srvId, fd} end if len == 0 then return end return fdArray end --通知玩家 local function notifyPlayer(playerUid, serverId) local fd = MiddleManager.getFDBySvrIndex(serverId) local msgData = InnerMsg.wl.WL_GODSATREA_UPDATE_PLAYER_INFO msgData.playerUid = playerUid InnerMsg.sendMsg(fd, msgData) end -- 通知玩家更新数据。新需求,兼容老数据。 local function playerInfoCheck(rankList) for _, playerInfo in ipairs(rankList) do if playerInfo.uid and not playerInfo.power then notifyPlayer(playerInfo.uid, playerInfo.serverId) end end end -- 通知游戏服 function BrocastServer(srvTb, rankList) for _, srvInfo in ipairs(srvTb) do local rankTb = getRankListBySrvId(rankList, srvInfo[1]) CS_Send_Reward(srvInfo[2], rankTb) local logStr = string.format("跨服开始通知普通服, 普通服Id: %d", srvInfo[1]) writeLog(Log.LOGID_OSS_GODSAREA_MAIL ,logStr) end end -- 把连接到本跨服的普通服进行分批 function BatchServer() local cnt = 0 local maxNum = 10 local delay_sec = 0 local srvTb = {} local fdArray = getAllSrvFd() if not fdArray then local logStr = "跨服获取不到普通服的fd, 通知普通服失败" writeLog(Log.LOGID_OSS_GODSAREA_MAIL ,logStr) return end local rankList = GodsAreaDB.GetRankList() for _, v in ipairs(fdArray) do cnt = cnt + 1 srvTb[cnt] = v if cnt >= maxNum then delay_sec = delay_sec + 5 Timer.addLater(delay_sec, BrocastServer, srvTb, rankList) -- Timer.addLater(2, BrocastServer, srvTb, rankList) cnt = 0 srvTb = {} end end if cnt > 0 then Timer.addLater(2, BrocastServer, srvTb, rankList) end end function onHour(hour) if _G.is_middle ~= true then return end if hour == SEND_REWARD_HOUR then local delay_sec = math.random(1, 30) Timer.addLater(delay_sec, BatchServer) local logStr = string.format("[跨服]开始发奖, 当前时间: %s, 延迟: %d 秒通知", os.time(), delay_sec) writeLog(Log.LOGID_OSS_GODSAREA_MAIL ,logStr) end end -- 测试 function oneMin() -- local delay_sec = math.random(3, 5) -- Timer.addLater(delay_sec, BatchServer) -- local logStr = string.format("[跨服]开始发奖, 当前时间: %s, 延迟: %d 秒通知", os.time(), delay_sec) -- writeLog(Log.LOGID_OSS_GODSAREA_MAIL ,logStr) end -- 普通服请求排行榜数据 function CS_RankList_Query(sourceServerId, playerUid) local rankList = GodsAreaDB.GetRankList() local msgData = InnerMsg.wl.WL_GODSATREA_QUERY_RANKLIST msgData.myRank = 0 msgData.playerUid = playerUid msgData.rankList = {} local msgRankList = msgData.rankList for rank, playerInfo in ipairs(rankList) do msgRankList[rank] = { body = playerInfo.body or 0, name = playerInfo.name or "", uid = playerInfo.uid, power = playerInfo.power, serverId = playerInfo.serverId, head = playerInfo.head, headFrame = playerInfo.headFrame, } if playerInfo.uid and playerInfo.uid == playerUid then msgData.myRank = rank end end local fd = MiddleManager.getFDBySvrIndex(sourceServerId) InnerMsg.sendMsg(fd, msgData) playerInfoCheck(rankList) end -- 普通服请求某个排名的玩家数据 function CS_GetPlayerInfo(sourceServerId, targetRank, targetUid, playerUid) local fd = MiddleManager.getFDBySvrIndex(sourceServerId) local msgData = InnerMsg.wl.WL_GODSATREA_QUERY_PLAYER_INFO msgData.res = -1 msgData.playerInfo = {} msgData.playerUid = playerUid local rankList = GodsAreaDB.GetRankList() local rankData = rankList[targetRank] -- 数据异常 if not rankData then return InnerMsg.sendMsg(fd, msgData) end -- 客户端的数据不是最新数据 if rankData.uid and rankData.uid ~= targetUid then msgData.res = -2 return InnerMsg.sendMsg(fd, msgData) end msgData.res = 0 msgData.playerInfo.name = rankData.name msgData.playerInfo.lv = rankData.level msgData.playerInfo.head = rankData.head msgData.playerInfo.headFrame = rankData.headFrame msgData.playerInfo.rank = targetRank if rankData.uid then msgData.playerInfo.uid = rankData.uid msgData.playerInfo.defendObjList = rankData.heroList end InnerMsg.sendMsg(fd, msgData) end -- 普通服查询是否可以挑战某个排名 function CS_Challenge_Query(sourceServerId, defenseRank, defenseUid, attackerUid) local rankList = GodsAreaDB.GetRankList() local fd = MiddleManager.getFDBySvrIndex(sourceServerId) local msgData = InnerMsg.wl.WL_GODSATREA_CHALLENGE_QUERY msgData.res = 0 msgData.attackerUid = attackerUid msgData.defenseRank = defenseRank msgData.defenseUid = defenseUid msgData.defenseServerId = 0 local rankData = rankList[defenseRank] if not rankData then msgData.res = -1 return InnerMsg.sendMsg(fd, msgData) end -- 客户端的排行数据不是最新数据 if rankData.uid and defenseUid ~= rankData.uid then msgData.res = -2 return InnerMsg.sendMsg(fd, msgData) end -- 不能挑战比自己排名低的 local attackerRank = getRankInfoByUid(rankList, attackerUid) -- if attackerRank ~= 0 and attackerRank < defenseRank then -- msgData.res = -3 -- return InnerMsg.sendMsg(fd, msgData) -- end clearChallengeList() -- 如果有一方处于挑战/被挑战中, 则提醒 local now = os.time() local aChallengeInfo = challengeList[attackerRank] local dChallengeInfo = challengeList[defenseRank] if aChallengeInfo and (aChallengeInfo.startTime + MAX_CHALLENGE_TIME) > now then msgData.res = 1 end if dChallengeInfo and (dChallengeInfo.startTime + MAX_CHALLENGE_TIME) > now then msgData.res = 2 end -- 把被挑战方加入正在挑战列表 challengeList[defenseRank] = { startTime = now, attackerUid = attackerUid, attackerRank = attackerRank, defenseUid = defenseUid, } -- 如果挑战方在排行榜上, 也加入挑战列表 if attackerRank ~= 0 then challengeList[attackerRank] = { startTime = now, attackerUid = attackerUid, attackerRank = attackerRank, defenseUid = defenseUid, defenseRank = defenseRank, } end msgData.defenseServerId = rankData.serverId or 0 msgData.defenseName = rankData.name or "匿名玩家" InnerMsg.sendMsg(fd, msgData) end -- 普通服通知跨服挑战胜利 function CS_Challenge_Win(sourceServerId, defenseRank, defenseUid, attackerUid, attackInfo) local rankList = GodsAreaDB.GetRankList() local defenseRankData = rankList[defenseRank] local attackerRank, attackerRankData = getRankInfoByUid(rankList, attackerUid) local msgData = InnerMsg.wl.WL_GODSATREA_UPDATE_CHENGHAO local fd = MiddleManager.getFDBySvrIndex(defenseRankData.serverId) local attackData = attackInfo attackData._id = defenseRankData._id -- 挑战者在榜上则用榜上的展示数据 if attackerRank ~= 0 then attackData = attackerRankData end -- 挑战方排名高于防守方排名则不做其他操作 if attackData.rank and attackData.rank ~= 0 and attackData.rank < defenseRankData.rank then return end -- 防守方当前是玩家 if defenseRankData.uid then -- 通知失败方更新称号 msgData.targetUid = defenseRankData.uid msgData.newRank = attackerRank msgData.isWinner = 0 msgData.enemyName = attackData.name or "" InnerMsg.sendMsg(fd, msgData) end -- 挑战者是榜上玩家 if attackerRank ~= 0 then -- 失败方排名更新为胜利方原排名 defenseRankData.rank = attackerRank GodsAreaDB.UpdateRankData(attackerRank, defenseRankData) end -- 胜利方排名更新为失败方原排名 attackData.rank = defenseRank GodsAreaDB.UpdateRankData(defenseRank, attackData) -- 通知胜利方更新称号 fd = MiddleManager.getFDBySvrIndex(sourceServerId) msgData.targetUid = attackerUid msgData.newRank = defenseRank msgData.isWinner = 1 msgData.enemyName = defenseRankData.name or "" InnerMsg.sendMsg(fd, msgData) local logStr = string.format("挑战胜利, attackerUid: %s, attackerRank: %d, defenseRank: %d, defenseOldUid: %s, defenseNowUid: %s", attackerUid, attackerRank, defenseRank, defenseUid, defenseRankData.uid or defenseUid) writeLog(Log.LOGID_OSS_GODSAREA_CHALLENGE ,logStr) end local function getTargetVideo(videoArray, playerUid) local len = 0 local tbl = {} -- if not playerUid or not videoArray then -- return tbl -- end for _, videoData in ipairs(videoArray) do if videoData.combatInfo.defender.uuid == playerUid then len = len + 1 tbl[len] = videoData end end return tbl end -- 普通服请求战斗录像数据 function CS_Query_CombatVideo(sourceServerId, playerUid, targetRank) local videoArray = CombatVideo.getCombatVideosByType(CombatVideo.VIDEOTYPE_GODSAREA, targetRank) local fd = MiddleManager.getFDBySvrIndex(sourceServerId) local msgData = InnerMsg.wl.WL_GODSATREA_QUERY_RANK_VIDEO local rankList = GodsAreaDB.GetRankList() local rankData = rankList[targetRank] local targetUuid = rankData.uid or "" -- if not targetUuid then -- local rankCfg = GodsAreaConfig.rankList[targetRank] -- targetUuid = rankCfg.monsterOutID -- end local targetVideoArray = getTargetVideo(videoArray, targetUuid) msgData.playerUid = playerUid msgData.isFinish = 0 msgData.videoData = {} local videoCnt = #targetVideoArray if videoCnt <= 0 then msgData.isFinish = 1 InnerMsg.sendMsg(fd, msgData) return end for k,v in ipairs(targetVideoArray) do if k > CombatVideo.GODSAREA_RECORD_MAX_CNT then break end msgData.videoData = v if k == videoCnt or k == CombatVideo.GODSAREA_RECORD_MAX_CNT then msgData.isFinish = 1 end InnerMsg.sendMsg(fd, msgData) end end -- 更新玩家基础数据 function CS_Update_PlayerInfo(playerUid, newPlayerInfo) local rankList = GodsAreaDB.GetRankList() local rank, rankData = getRankInfoByUid(rankList, playerUid) if rank == 0 then return end for k,v in pairs(newPlayerInfo) do rankData[k] = v end GodsAreaDB.UpdateRankData(rank, rankData) end -- 更新英雄数据 function CS_Update_HeroInfo(playerUid, newHeroInfo) local rankList = GodsAreaDB.GetRankList() local rank, rankData = getRankInfoByUid(rankList, playerUid) if rank == 0 then return end local isChange = false if newHeroInfo.opType == 0 then local rmIdx = getSameIdx(rankData.heroList, newHeroInfo.removeHeroUuid) if rmIdx then isChange = true -- table.remove(rankData.heroList, rmIdx) rankData.heroList[rmIdx] = nil rankData.power = newHeroInfo.power end elseif newHeroInfo.opType == 1 then for _, v in pairs(newHeroInfo.heroList) do local targetIdx = getSameIdx(rankData.heroList, v.heroUuid) if targetIdx then isChange = true rankData.heroList[targetIdx] = v rankData.power = newHeroInfo.power break end end else if next(newHeroInfo.heroList) then rankData.heroList = newHeroInfo.heroList rankData.power = newHeroInfo.power isChange = true end end if isChange then GodsAreaDB.UpdateRankData(rank, rankData) end end -- 通知游戏服, 给玩家发奖 function CS_Send_Reward(fd, rankTb) local msgData = InnerMsg.wl.WL_GODSATREA_BROCAST_REWARD msgData.uid2RankTb = rankTb or {} InnerMsg.sendMsg(fd, msgData) end