pvpd.lua 7.63 KB
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.call, "center", pvpd, "updateRoleInfo", change)
	end
end

local function getDayAndTime()
	local startTime = getStartTime()
	local now = skynet.timex()

	local crossTime = now - startTime
	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__)