skynet = require "skynet" local json = require("shared.json") redisproxy = require("shared.redisproxy") local cluster = require "skynet.cluster" local serverId = tonumber(skynet.getenv("servId")) datacenter = require "skynet.datacenter" csvdb = require "shared.csvdata" require "shared.init" require "utils.init" require "RedisKeys" require "skynet.manager" require "GlobalVar" local MatchCache = {} -- 比赛记录 缓存 { [roundIdx] = {{rolesId, rolesId, winId = roleId}, {rolesId, rolesId}}, ... } local RoleInfo = {} -- 角色信息缓存 {[rolesId] = info} local pvpInfo = nil local ROBOT_SERV_ID = 999 local function packRoleId(servId, roleId) return roleId * 1000 + servId end local function unpackRoleId(tempId) local servId = tempId % 1000 local roleId = math.floor(tempId / 1000) return servId, roleId end skynet.register_protocol { name = "role", id = 101, pack = skynet.pack, unpack = skynet.unpack, dispatch = function(session, address, submethod, ...) end, } local function rpcRole(roleId, funcName, ...) local fields = ... local agent = datacenter.get("agent", roleId) if agent and agent.serv then if funcName == "getProperties" then return skynet.call(agent.serv, "role", funcName, fields) else return skynet.call(agent.serv, "role", funcName, ...) end else local roleCross = require("models.RoleCross") if funcName == "getProperties" then return roleCross.handle(funcName, roleId, fields) else return roleCross.handle(funcName, roleId, ...) end end end local function getDBKey() local resetData = csvdb["time_resetCsv"][TimeReset.PvpCross] local curRound = math.floor((skynet.timex() - START_RESET_TIME - resetData.start) / resetData.interval) local idx = 1 if curRound % 2 == 1 then idx = 2 end return RANK_PVP_HIGHT_KEY[idx] end local function getStartTime() local resetData = csvdb["time_resetCsv"][TimeReset.PvpCross] local curRound = math.floor((skynet.timex() - START_RESET_TIME - resetData.start) / resetData.interval) local startTime = START_RESET_TIME + curRound * resetData.interval + resetData.start return startTime end local CMD = {} ------------------- 角色调用 -------------------------- function CMD.updateRoleInfo(change) CMD.refreshRoleInfo(change) local pvpd = cluster.query("center", "pvpd") if pvpd then pcall(cluster.send, "center", pvpd, "updateRoleInfo", change) end end local function getDayAndTime() local startTime = getStartTime() local now = skynet.timex() local crossTime = now - startTime + RESET_TIME * 3600 local aday = 3600 * 24 local day = math.ceil(crossTime / aday) -- 当前是第几个比赛日 local ctime = crossTime % aday -- 当前在本天 经过多少时间 return day, ctime end local function hideMatchInfo() local day, ctime = getDayAndTime() local tempMatchCache = {} for round, tempData in pairs(MatchCache) do if round == day and ctime < globalCsv.pvp_cross_server_show_result - 1 then tempMatchCache[round] = {} for idx, match in pairs(tempData) do tempMatchCache[round][idx] = { [1] = match[1], [2] = match[2], } end elseif round <= day then tempMatchCache[round] = {} for idx, match in pairs(tempData) do tempMatchCache[round][idx] = { [1] = match[1], [2] = match[2], win = match.win, battleV = { [match[1]] = (match.teams[match[1]] or {}).battleV, [match[2]] = (match.teams[match[2]] or {}).battleV, } } end end end return tempMatchCache end local function hideRoleInfo() local day, ctime = getDayAndTime() local needInfo = {} local tempRoleInfo = {} for pId, roleInfo in pairs(RoleInfo) do tempRoleInfo[pId] = { name = roleInfo.name, level = roleInfo.level, headId = roleInfo.headId, } end return tempRoleInfo end function CMD.getMatchInfo() if not next(MatchCache) then local pvpd = cluster.query("center", "pvpd") if pvpd then local status, result = pcall(cluster.call, "center", pvpd, "getMatchInfo", {serverId = serverId}) MatchCache = result.matchInfo or {} RoleInfo = result.roleInfo or {} end end return {matchInfo = hideMatchInfo(), roleInfo = hideRoleInfo()} end function CMD.getRoleInfo() if not next(MatchCache) then CMD.getMatchInfo() end return hideRoleInfo() end function CMD.getRoleDetail(pIds) if not next(MatchCache) then CMD.getMatchInfo() end local result = {} for _, pId in ipairs(pIds) do result[pId] = RoleInfo[pId] end return result end function CMD.getMatchRecord(round, matchIdx) if not next(MatchCache) then CMD.getMatchInfo() end local day, ctime = getDayAndTime() if round > day or (round == day and ctime < globalCsv.pvp_cross_server_show_result) then return end -- 还么结算 if not (MatchCache[round] or {})[matchIdx] then return end return { videos = MatchCache[round][matchIdx].video, teams = MatchCache[round][matchIdx].teams, } end function CMD.getBetInfo() if not next(MatchCache) then CMD.getMatchInfo() end local day, ctime = getDayAndTime() local change = false local lastDay = math.min(day, globalCsv.pvp_cross_server_day) local betInfo = pvpInfo:getProperty("betInfo") local betNum = pvpInfo:getProperty("betNum") for cday = 1, lastDay do if not betInfo[cday] then change = true betInfo[cday] = math.randomInt(1, #(MatchCache[cday] or {1})) if cday == lastDay then betNum = {} redisproxy:del("cross:pvpInfo:bet:" .. cday) end end end if change then pvpInfo:setProperties({ betInfo = betInfo, betNum = betNum }) end return pvpInfo:getProperties({"betInfo", "betNum"}) end function CMD.setBet(idx, roleId, costNum) local day, ctime = getDayAndTime() if day > globalCsv.pvp_cross_server_day or ctime >= globalCsv.pvp_cross_server_stop_stake then return end local betInfo = pvpInfo:getProperty("betInfo") if not betInfo[day] then return end local betNum = pvpInfo:getProperty("betNum") betNum[idx] = (betNum[idx] or 0) + 1 pvpInfo:setProperty("betNum", betNum) redisproxy:hset("cross:pvpInfo:bet:" .. day, roleId, costNum * 10 + idx) return {betNum = betNum} end -------------------中心服务器 调用---------------------- function CMD.loadRoles(roleIds) roleIds = roleIds or {} local infos = {} RoleInfo[serverId] = RoleInfo[serverId] or {} for _, roleId in ipairs(roleIds) do infos[roleId] = rpcRole(roleId, "pvpHInfo") local temp = {} for _field, _v in pairs(infos[roleId]) do if _field ~= "battleInfo" then temp[_field] = _v end end RoleInfo[packRoleId(serverId, roleId)] = temp end return infos end -- 新赛季了 清掉缓存 function CMD.loadTeams() local dbKey = getDBKey() local redret = redisproxy:zrevrange(dbKey, 0, 15) local roleIds = {} for _, roleId in ipairs(redret) do table.insert(roleIds, tonumber(roleId)) end MatchCache = {} RoleInfo = {} local infos = CMD.loadRoles(roleIds) pvpInfo:setProperties({ betInfo = {}, betNum = {}, }) return {roleIds = roleIds, infos = infos} end -- 刷新缓存 function CMD.refreshMatchCache(info) MatchCache = info.matchInfo RoleInfo = info.roleInfo end -- 刷新 玩家数据 function CMD.refreshRoleInfo(change) if not next(RoleInfo) then return end if RoleInfo[change.id] then for field, value in pairs(change) do if field ~= "id" then RoleInfo[change.id][field] = value end end end end ------------------------------------------------------ function CMD.start() globalCsv = csvdb["GlobalDefineCsv"] pvpInfo = require("models.Pvpd").new({key = "cross:pvpInfo"}) pvpInfo:load() end --------------------------------------------------------- local function __init__() skynet.dispatch("lua", function(_, _, command, ...) local f = CMD[command] if f then skynet.ret(skynet.pack(f(...))) end end) skynet.register(".pvpcross") end skynet.start(__init__)