local skynet = require "skynet" local oo = require "Class" local gameCmd = require "GameCmd" local json =require "json" local log = require "Log" local sqlUrl = require "SqlUrl" local defense = require "Defense" local playerFields = require "PlayerFields" local errorInfo = require "ErrorInfo" local serverId = tonumber(skynet.getenv "serverId") local redisKeyUrl = require "RedisKeyUrl" local clusterServer = require "ClusterServer" local RankServer = oo.class(clusterServer) --初始化 RankServer.SaveDataToDBHour = 3 --凌晨3点保存数据到DB RankServer.PerSaveUserCount = 100 --每次保存用户数量 RankServer.RankType_Personal = 1 --个人排行榜 RankServer.RankType_Prestige = 2 --国家排行榜(家国情怀) RankServer.RankType_Country = 3 --声望排行榜(广招贤士) RankServer.CountryType_Start = 0 RankServer.CountryType_Wei = 1 --魏 RankServer.CountryType_Shu = 2 --蜀 RankServer.CountryType_Wu = 3 --吴 RankServer.CountryType_Wu = 4 --汉 RankServer.CountryType_Wu = 5 --群 RankServer.CountryType_End = 6 RankServer.MaxScoreCount = 5 --最大分数数量 function RankServer:Init() self:GetAllRankData( nil , {}) end --跨天 function RankServer:OnNewDay() if not self:IsRankServer( serverId ) then return end end --1秒Timer function RankServer:On1SecTimer() if not self:IsRankServer( serverId ) then return end end --5秒Timer function RankServer:On5SecTimer() if not self:IsRankServer( serverId ) then return end local time = os.date("*t", skynet.GetTime()) if self.SaveDataToDBHour == time.hour then --指定时间到了就写数据库 self:SaveDataToDB() end end --接收集群数据 function RankServer:ClusterRecv(...) local cmd , c2sData = ... local s2cData = {} s2cData.code = errorInfo.Suc if self.Center2All_ServerManageCmd == cmd then elseif self.GateToRank_UpdateScore == cmd then self:UpdateScore( c2sData , s2cData ) elseif self.GateToRank_GetAllRankData == cmd then self:GetAllRankData( c2sData , s2cData ) elseif self.GateToRank_GetUserRankData == cmd then self:GetUserRankData( c2sData , s2cData ) else log.info(string.format("集群服务器 消息接口 %d 不存在", cmd)) s2cData.code = 2 end log.info("集群服务器 消息接口", cmd , "返回信息",s2cData.code) return s2cData end --更新分数 function RankServer:UpdateScore( c2sData , s2cData ) local userId = c2sData.userId local score = c2sData.score local countryType = c2sData.countryType --更新一些玩家排行榜需要的基本信息 skynet.server.redis:hset( redisKeyUrl.RankUserInfo , userId , json:encode( c2sData )) --同步玩家数据到Redis skynet.server.redis:zincrby( redisKeyUrl.PersonalRankKey , score , userId ) skynet.server.redis:zincrby( redisKeyUrl.CountryRankKey..countryType , score , userId ) skynet.server.redis:zincrby( redisKeyUrl.PrestigeRankKey , score , userId ) skynet.server.redis:sadd( redisKeyUrl.RankUpdateUser , userId ) end --获取所有排行榜数据 function RankServer:GetAllRankData( c2sData , s2cData ) s2cData.personalRank = skynet.server.redis:zrevrange( redisKeyUrl.PersonalRankKey , 0 , self.MaxScoreCount - 1 ) s2cData.prestigeRank = skynet.server.redis:zrevrange( redisKeyUrl.PrestigeRankKey , 0 , self.MaxScoreCount - 1 ) for i = self.CountryType_Start + 1, self.CountryType_End - 1, 1 do s2cData[ "countryRank"..i ] = skynet.server.redis:zrevrange( redisKeyUrl.CountryRankKey..i , 0 , self.MaxScoreCount - 1 ) end end --获取用户排行榜数据 function RankServer:GetUserRankData( c2sData , s2cData ) local userId = c2sData.userId end --保存数据落地 function RankServer:SaveDataToDB() local userCount = skynet.server.redis:scard( redisKeyUrl.RankUpdateUser ) if userCount < self.PerSaveUserCount then --小于指定数量就不保存数据库 return end local score = 0 local userCount = 0 local sqlPersonal = "" local sqlPrestige = "" local sqlCountry = "" local t = skynet.GetTime() local allUser = skynet.server.redis:smembers( redisKeyUrl.RankUpdateUser ) for k, v in pairs(allUser) do score = skynet.server.redis:zscore( redisKeyUrl.PersonalRankKey , v) sqlPersonal = sqlPersonal .. string.format(sqlUrl.updateScoreToPersonalRank , v , score , score ) .. ";" score = skynet.server.redis:zscore( redisKeyUrl.PrestigeRankKey , v) sqlPrestige = sqlPrestige .. string.format(sqlUrl.updateScoreToPrestigeRank , v , score , score ) .. ";" score = skynet.server.redis:zscore( redisKeyUrl.CountryRankKey..1 , v) for i = self.CountryType_Start + 1, self.CountryType_End - 1, 1 do score = skynet.server.redis:zscore( redisKeyUrl.CountryRankKey..i , v) if score then sqlCountry = sqlCountry .. string.format(sqlUrl.updateScoreToCountryRank, v , i , score , score ) .. ";" end end userCount = userCount + 1 skynet.server.redis:srem(redisKeyUrl.RankUpdateUser , v) --有1000条数据就写一次数据库 if userCount >= self.PerSaveUserCount then break end end --有数据时才写数据库 if userCount > 0 then sqlPersonal = string.sub(sqlPersonal , 1,-2 ) --去掉最后一个逗号 sqlPrestige = string.sub(sqlPrestige , 1,-2 ) --去掉最后一个逗号 sqlCountry = string.sub(sqlCountry , 1,-2 ) --去掉最后一个逗号 skynet.server.db:Query(sqlPersonal) skynet.server.db:Query(sqlPrestige) skynet.server.db:Query(sqlCountry) --清除保存的玩家 end --os.execute("sleep 1") end --如果是当前服务器ID,那么就加入进来 if serverId == clusterServer.rankServerID then skynet.server.rankServer = RankServer end return RankServer