HomeServer/Server/AllServer/GameServer/ServerManage.lua
2024-11-20 15:41:37 +08:00

365 lines
14 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local skynet = require "skynet"
local oo = require "Class"
local log = require "Log"
local json =require "json"
local sqlUrl = require "SqlUrl"
local curServerId = tonumber(skynet.getenv "serverId")
local manageCmd = require "ManageCmd"
local clusterServer = require "ClusterServer"
local errorInfo = require "ErrorInfo"
local redisKeyUrl = require "RedisKeyUrl"
local ServerManage = oo.class()
function ServerManage:Init()
end
--获取服务器
function ServerManage:GetServer()
local server = nil --找出对应的服务器信息
if curServerId == clusterServer.centerServerID then
server = skynet.server.centerServer
elseif curServerId == clusterServer.multiServerID then
server = skynet.server.multiServer
elseif curServerId == clusterServer.payServerID then
server = skynet.server.payServer
elseif curServerId >= clusterServer.routeServerMinID and curServerId <= clusterServer.routeServerMaxID then
server = skynet.server.routeServer
elseif curServerId >= clusterServer.gameServerMinID and curServerId <= clusterServer.gameServerMaxID then
server = skynet.server.gameServer
end
return server
end
--执行服务器命令
function ServerManage:DoManageCmd( c2sData , s2cData)
local cmd = c2sData.cmd
local userId = c2sData.userId or nil
local value = c2sData.value or nil
s2cData.data = {}
s2cData.data.serverId = curServerId
s2cData.data.isSuc = true
log.info("执行服务器命令" ,cmd ,userId ,value)
if cmd > manageCmd.AllServerStart and cmd < manageCmd.AllServerEnd then --所有服务器
local server = self:GetServer()
if manageCmd.ReloadClusterConfig == cmd then
self:ReloadClusterConfig( server )
elseif manageCmd.Reg == cmd then
self:Reg( server )
elseif manageCmd.UnReg == cmd then
self:UnReg( server )
elseif manageCmd.ReConnectDB == cmd then
self:ReConnectDB( server )
elseif manageCmd.ShutDown == cmd then
self:ShutDown( server , c2sData , s2cData )
end
elseif curServerId == clusterServer.centerServerID then --中心服
if manageCmd.QueryPlayerDBInfo == cmd then
self:QueryPlayerDBInfo( c2sData , s2cData )
elseif manageCmd.QueryPlayerOnlineInfo == cmd then
self:QueryPlayerOnlineInfo( c2sData , s2cData )
elseif manageCmd.RestartGameServer == cmd then
self:RestartGameServer( c2sData , s2cData )
end
elseif curServerId >= clusterServer.routeServerMinID and curServerId <= clusterServer.routeServerMaxID and cmd > manageCmd.RouteServerStart and cmd < manageCmd.RouteServerEnd then --路由服务器
if manageCmd.RouteSyncWhiteList == cmd then
self:RouteSyncWhiteList( c2sData , s2cData )
elseif manageCmd.RouteSyncBlackList == cmd then
self:RouteSyncBlackList( c2sData , s2cData )
end
elseif curServerId >= clusterServer.gameServerMinID and curServerId <= clusterServer.gameServerMaxID and cmd > manageCmd.GameServerStart and cmd < manageCmd.GameServerEnd then --游戏服务器
if manageCmd.NeedPlayerCount == cmd then
self:NeedPlayerCount( c2sData , s2cData)
elseif manageCmd.SaveUserToDB == cmd then
self:SaveUserToDB( c2sData , s2cData)
elseif manageCmd.SaveUserToTxt == cmd then
self:SaveUserToTxt( c2sData , s2cData )
elseif manageCmd.ForceUserOffline == cmd then
self:ForceUserOffline( c2sData , s2cData )
elseif manageCmd.QueryPlayerInServer == cmd then
self:QueryPlayerInServer( c2sData , s2cData )
elseif manageCmd.UpdateGameVersion == cmd then
self:UpdateGameVersion( s2cData )
elseif manageCmd.UpdateUserData == cmd then
self:UpdateUserData( c2sData , s2cData )
elseif manageCmd.SaveAllUserDataToFile == cmd then
self:SaveAllUserDataToFile( c2sData , s2cData )
elseif manageCmd.ReStartTimer == cmd then
self:ReStartTimer( c2sData , s2cData )
end
else
s2cData.code = errorInfo.ErrorCode.ErrRequestParam
end
if errorInfo.Suc ~= s2cData.code then
s2cData.data.isSuc = false
end
return s2cData
end
--注册服务器
function ServerManage:Reg( server )
skynet.server.clusterServer:Reg()
log.info("成功注册服务")
end
--注销服务器
function ServerManage:UnReg( server )
skynet.server.clusterServer:UnReg()
log.info("成功注销服务")
end
--重连数据库
function ServerManage:ReConnectDB( server )
log.info("开始 重新连接数据库")
skynet.InitDB( true )
log.info("结束 重新连接数据库")
end
--关闭服务器
function ServerManage:ShutDown( server , c2sData , s2cData )
skynet.server.clusterServer:UnReg()
if server:StopServer( c2sData , s2cData ) then
log.info("强制关闭服务器成功")
else
log.info("强制关闭服务器失败")
end
end
--关闭服务器
function ServerManage:ReloadClusterConfig( server )
server:ReloadClusterNode()
log.info("成功载入集群配置")
end
--查询玩家DB信息
function ServerManage:QueryPlayerDBInfo( c2sData , s2cData)
local account = c2sData.account
local userDBInfo = skynet.server.redisCenter:GetRedisDBInfo( account )
s2cData.data.userDBInfo = userDBInfo
end
--查询玩家在线信息
function ServerManage:QueryPlayerOnlineInfo( c2sData , s2cData)
local account = c2sData.account
local redisKey = string.format( redisKeyUrl.RouteServerLoginInfoHash , account )
local queryData = skynet.server.redis:hgetall( redisKey )
queryData = redisKeyUrl:CovertTable(queryData)
s2cData.data.onlineInfo = queryData
end
--重启游戏服
function ServerManage:RestartGameServer( c2sData , s2cData)
local startServerId = c2sData.startServerId --游戏服起始ID
local endServerId = c2sData.endServerId --游戏服结束ID
local opTime = c2sData.opTime --操作时间
if nil == endServerId then
endServerId = startServerId
end
if nil == opTime or "" == opTime then
s2cData.code = errorInfo.ErrorCode.ErrRequestParam
return s2cData
end
--将时间格式 2022-02-22 22:22:22 转为时间戳
local tmpOpTime = opTime
opTime = skynet.server.common:GetTime( opTime )
--将执行计划写入redis
local planInfo = {}
planInfo.startServerId = startServerId
planInfo.endServerId = endServerId
planInfo.opTime = opTime
for k, v in pairs( skynet.server.clusterServer.clusterInfo ) do
if v.serverId >= skynet.server.clusterServer.routeServerMinID and v.serverId <= skynet.server.clusterServer.routeServerMaxID then
skynet.server.redis:hset( redisKeyUrl.RestartPlanHSet , v.serverId , json:encode( planInfo ) )
end
end
log.info(string.format("成功写入重启计划 游戏服ID 起始 %d 结束 %d 开始时间 %s", startServerId , endServerId, tmpOpTime))
end
--路由服加入白名单
function ServerManage:RouteSyncWhiteList( c2sData , s2cData )
skynet.server.routeServer:SyncWhiteList()
s2cData.data.isSuc = true
end
--路由服加入黑名单
function ServerManage:RouteSyncBlackList( c2sData , s2cData )
skynet.server.routeServer:SyncBlackList()
s2cData.data.isSuc = true
end
--需要玩家数量
function ServerManage:NeedPlayerCount( c2sData , s2cData)
local param = c2sData.param
skynet.server.gameServer.serverInfo.needPlayerCount = tonumber( param.needCount )
log.info(string.format("游戏服需要 %d 个玩家", skynet.server.gameServer.serverInfo.needPlayerCount))
end
--保存用户数据到DB
function ServerManage:SaveUserToDB( c2sData , s2cData)
local account = c2sData.account
local player = skynet.server.playerCenter:GetPlayerForAccount( account )
if not player then
s2cData.code = errorInfo.ErrorCode.NoExistUser
else
local sucSave = skynet.server.accountCenter:SavePlayerToMysql( player )
if sucSave then
log.info(string.format("玩家 %s 强制将玩家数据保存到Mysql成功", account ))
else
--强制失败先存玩家的sql如果无法组装数据只能打印成文本
s2cData.code = errorInfo.ErrorCode.OpFailed
log.info(string.format("玩家 %s 强制将玩家数据保存到Mysql失败", account ))
skynet.server.accountCenter:SaveFailedPlayerDataToFile( player )
end
end
end
--保存用户数据到Txt
function ServerManage:SaveUserToTxt( c2sData , s2cData )
local account = c2sData.account
local param = c2sData.param
local player = skynet.server.playerCenter:GetPlayerForAccount( account )
if not player then
s2cData.code = errorInfo.ErrorCode.NoExistUser
else
local basicInfo = player.basicInfo
local gameData = player.gameData
local file = io.open("UserData.txt", "a+")
file:write( account )
if param.isJson then
file:write( json:encode( basicInfo ))
file:write("\r\n")
file:write( json:encode( gameData ))
file:write("\r\n")
log.info(string.format("玩家 %s 强制将玩家数据以Json格式保存到Txt ", account ))
else
file:write( skynet.server.common:TableToString( basicInfo ))
file:write("\r\n")
file:write( skynet.server.common:TableToString( gameData ))
file:write("\r\n")
log.info(string.format("玩家 %s 强制将玩家数据以文本格式保存到Txt ", account ))
end
file:close()
end
end
--强制玩家下线
function ServerManage:ForceUserOffline( c2sData , s2cData)
local account = c2sData.account
local player = skynet.server.playerCenter:GetPlayerForAccount( account )
if not player then
s2cData.code = errorInfo.ErrorCode.NoExistUser
else
local sucSave = skynet.server.accountCenter:SavePlayerToMysql( player )
if sucSave then
log.info(string.format("玩家 %s 强制玩家下线并保存到Mysql成功", account ))
else
--强制失败先存玩家的sql如果无法组装数据只能打印成文本
s2cData.code = errorInfo.ErrorCode.OpFailed
log.info(string.format("玩家 %s 强制玩家下线并保存到Mysql失败", account ))
skynet.server.accountCenter:SaveFailedPlayerDataToFile( player )
end
skynet.server.accountCenter:OfflineProcess( player )
end
end
--查询玩家在哪个游戏服
function ServerManage:QueryPlayerInServer( c2sData , s2cData )
local playerList = skynet.server.playerCenter:GetPlayerList()
for curUseId, value in pairs( playerList ) do
if curUseId == userId then
s2cData.data.isSuc = true
break
end
end
end
--更新游戏版本号
function ServerManage:UpdateGameVersion( s2cData )
skynet.server.redis:incr( redisKeyUrl.GameServerVersion )
end
--更新玩家数据(玩家可能在线,某种数据,导致无法数据落地,我们将进行修复)
function ServerManage:UpdateUserData( c2sData , s2cData )
local playerList = skynet.server.playerCenter:GetPlayerList()
for curUseId, v in pairs( playerList ) do
if curUseId == userId then
local resetKey = c2sData.resetKey
local resetValue = c2sData.resetValue
local listResetKey = skynet.server.common:Split( resetKey , ".")
local gameData = v.player[ c2sData.dataType ]
--s2cData.data.isSuc = true
break
end
end
end
--保存所有玩家数据到文件
function ServerManage:SaveAllUserDataToFile( c2sData , s2cData )
--保存玩家数据的文件列表
local fileList = {}
for i = 1, 5, 1 do
local fileName = string.format("ForceSaveUserDataToFile_%d_%d.txt", curServerId , i)
fileList[ i ] = io.open( fileName , "w+")
end
local playerList = skynet.server.playerCenter:GetPlayerList()
for curUseId, v in pairs( playerList ) do
function Do()
local basicInfo = v.player.basicInfo
local gameData = v.player.gameData
local dbIndex = basicInfo.dbIndex
local userId = basicInfo.userID
local account = basicInfo.accountName
local sql = string.format(sqlUrl.saveAccountToPlayer , json:encode(basicInfo) , json:encode(gameData) , userId )
sql = string.format("%s|%d|%s \r\n" , account, userId , sql)
fileList[ dbIndex ]:write( sql )
log.info(string.format("玩家 %d 成功保存玩家数据sql到文件", userId ))
end
local isDo,callData = pcall( Do )
if not isDo then
local errorText = "保存所有玩家数据到文件 失败"
if curUseId then
log.warning(errorText , curUseId , callData )
else
log.warning( errorText , callData)
end
end
end
for i = 1, 5, 1 do
fileList[ i ]:close()
end
end
--重启Timer
function ServerManage:ReStartTimer( c2sData , s2cData )
local timerType = c2sData.timerType
if 1 == timerType then
skynet.fork(skynet.SaveMongoDBTimer,500) --500
elseif 2 == timerType then
skynet.fork(skynet.SaveMysqlDBTimer,500) --500
end
log.info("重启Timer成功 TimerType" , timerType)
end
skynet.server.serverManage = ServerManage
return ServerManage