902 lines
36 KiB
Lua
902 lines
36 KiB
Lua
|
|
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 playerFields = require "PlayerFields"
|
|||
|
|
local errorInfo = require "ErrorInfo"
|
|||
|
|
local serverId = tonumber(skynet.getenv "serverId")
|
|||
|
|
local redisKeyUrl = require "RedisKeyUrl"
|
|||
|
|
local pb = require "pb"
|
|||
|
|
local dbData = require "DBData"
|
|||
|
|
local player = require "Player"
|
|||
|
|
local dataType = require "DataType"
|
|||
|
|
local queue = require "Queue"
|
|||
|
|
|
|||
|
|
local AccountCenter = oo.class()
|
|||
|
|
AccountCenter.Platform_local = "Local"
|
|||
|
|
AccountCenter.Platform_WeChat = "WeChat"
|
|||
|
|
AccountCenter.PerSaveMaxCount = 50 --每次保存最多个数
|
|||
|
|
AccountCenter.SaveMysqlDBFailedMaxCount = 3 --保存mysql失败最大次数
|
|||
|
|
|
|||
|
|
--处理老IOS用户
|
|||
|
|
function AccountCenter:IosOldPlayer( mobile )
|
|||
|
|
if skynet.GetTime() >= 1719849600 then --超过这个时间 2024-07-02 00:00:00 不再处理
|
|||
|
|
return false , "" , 0 , 0
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local redisKey = redisKeyUrl.AccountServerOldIOSPlayerSet
|
|||
|
|
if not skynet.server.redis:sismember( redisKey , mobile ) then
|
|||
|
|
return false , "" , 0 , 0
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local sql = string.format(sqlUrl.queryAccountFromOldIosPlayer , mobile )
|
|||
|
|
local queryData = skynet.server.db:Query("account" , sql )
|
|||
|
|
if queryData and queryData[1] then
|
|||
|
|
--从redis删除标记
|
|||
|
|
skynet.server.redis:srem( redisKey , mobile )
|
|||
|
|
|
|||
|
|
--数据库里更新状态
|
|||
|
|
sql = string.format(sqlUrl.updateAccountToOldIosPlayer , 1 , mobile )
|
|||
|
|
skynet.server.db:Query("account" , sql )
|
|||
|
|
return true, queryData[1].ArchiveData , queryData[1].PayCount , queryData[1].InviteCount --获取存档数据
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return false , "" , 0 , 0
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--初始化
|
|||
|
|
function AccountCenter:Init()
|
|||
|
|
--初始化默认DB索引(千成不能删除,非常重要 开始)!!!!!!!!!!!!!!!
|
|||
|
|
--[[
|
|||
|
|
local key = nil
|
|||
|
|
for i = 1, skynet.server.gameConfig.DBInfoConfig.playerTableCount, 1 do
|
|||
|
|
key = string.format(redisKeyUrl.AccountServerUserDBID , i )
|
|||
|
|
if not skynet.server.redis:exists( key) then
|
|||
|
|
skynet.server.redis:set( key , 10000000 * i )
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--设置游戏服的版本号
|
|||
|
|
if not skynet.server.redis:exists( key) then
|
|||
|
|
skynet.server.redis:set( redisKeyUrl.GameServerVersion , 1 )
|
|||
|
|
end
|
|||
|
|
]]
|
|||
|
|
|
|||
|
|
--!!!!!!!!!!!!重要结束!!!!!!!!!!!!!!!!!!!!!
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--跨天
|
|||
|
|
function AccountCenter:OnNewDay()
|
|||
|
|
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--1秒Timer
|
|||
|
|
function AccountCenter:On1SecTimer()
|
|||
|
|
if not self:IsAccountCenter( serverId ) then
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
|
|||
|
|
--检查玩家是否符合普通保存策略
|
|||
|
|
function AccountCenter:CheckNormalToMongo()
|
|||
|
|
local playerList = skynet.server.playerCenter:GetPlayerList()
|
|||
|
|
local saveCount = 0
|
|||
|
|
local saveUserMaxTime = 600 --玩家数据有变动最长3分钟保存1次 180
|
|||
|
|
local saveUserMaxCount = 15 --一次保存10个
|
|||
|
|
local nowTime = skynet.GetTime()
|
|||
|
|
|
|||
|
|
for userId, value in pairs( playerList ) do
|
|||
|
|
if saveCount >= saveUserMaxCount then --一次保存200个
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--游戏进行中 时间超过十分钟
|
|||
|
|
if dataType.SaveLevel_Normal == value.player.tmpData.saveLevel and nowTime - value.lastSaveTime >= saveUserMaxTime then
|
|||
|
|
value.lastSaveTime = nowTime --保存了,刷新一下间隔保存时间
|
|||
|
|
|
|||
|
|
if self:SavePlayerToMongo( value.player ) then
|
|||
|
|
saveCount = saveCount +1
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if saveCount > 0 then
|
|||
|
|
log.info(string.format("间隔保存 一般策略 保存数量 %d 耗时 %d" , saveCount , skynet.GetTime() - nowTime ))
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--检查玩家是否有充值
|
|||
|
|
function AccountCenter:CheckPayToMongo()
|
|||
|
|
local playerList = skynet.server.playerCenter:GetPlayerList()
|
|||
|
|
local saveCount = 0 --落地玩家数量
|
|||
|
|
local nowTime = skynet.GetTime()
|
|||
|
|
for userId, value in pairs( playerList ) do
|
|||
|
|
--玩家充过值,优先数据落地
|
|||
|
|
if dataType.SaveLevel_Pay == value.player.tmpData.saveLevel then
|
|||
|
|
value.lastSaveTime = nowTime --优先保存了,刷新一下间隔保存时间
|
|||
|
|
if self:SavePlayerToMongo( value.player ) then
|
|||
|
|
saveCount = saveCount +1
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if saveCount >= 10 then
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if saveCount > 0 then
|
|||
|
|
log.info(string.format("间隔保存 充值优先 保存数量 %d 耗时 %d" , saveCount , skynet.GetTime() - nowTime ))
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--检查关键数据变化保存到mongo
|
|||
|
|
function AccountCenter:CheckKeyDataChangeToMongo()
|
|||
|
|
local playerList = skynet.server.playerCenter:GetPlayerList()
|
|||
|
|
local saveCount = 0
|
|||
|
|
local saveUserMaxTime =60 --背包变化最长1分钟保存1次
|
|||
|
|
local saveUserMaxCount = 20 --一次保存20个
|
|||
|
|
local nowTime = skynet.GetTime()
|
|||
|
|
|
|||
|
|
for userId, value in pairs( playerList ) do
|
|||
|
|
if saveCount >= saveUserMaxCount then --一次保存20个
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--游戏进行中 时间超过十分钟
|
|||
|
|
if dataType.SaveLevel_KeyDataChange == value.player.tmpData.saveLevel and nowTime - value.lastSaveTime >= saveUserMaxTime then
|
|||
|
|
value.lastSaveTime = nowTime --优先保存了,刷新一下间隔保存时间
|
|||
|
|
|
|||
|
|
if self:SavePlayerToMongo( value.player ) then
|
|||
|
|
saveCount = saveCount +1
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if saveCount > 0 then
|
|||
|
|
log.info(string.format("间隔保存 关键数据变化 保存数量 %d 耗时 %d" , saveCount , skynet.GetTime() - nowTime ))
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--间隔保存用户信息
|
|||
|
|
function AccountCenter:CheckSaveMongoDB()
|
|||
|
|
--[[
|
|||
|
|
if skynet.server.gameServer.isStopServerSaveAccount then
|
|||
|
|
log.info("AccountCenter:CheckSaveMongoDB 停服保存数据中,暂时不执行该Timer")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
]]
|
|||
|
|
|
|||
|
|
--优先保存充值用户数据
|
|||
|
|
self:CheckPayToMongo()
|
|||
|
|
|
|||
|
|
--优先关键数据变化保存
|
|||
|
|
self:CheckKeyDataChangeToMongo()
|
|||
|
|
|
|||
|
|
--一般策略保存
|
|||
|
|
self:CheckNormalToMongo()
|
|||
|
|
|
|||
|
|
log.info("成功执行 CheckSaveMongoDB")
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--检查玩家是否超时未游戏
|
|||
|
|
function AccountCenter:CheckSaveMysqlDB()
|
|||
|
|
function Do()
|
|||
|
|
--[[
|
|||
|
|
if skynet.server.gameServer.isStopServerSaveAccount then
|
|||
|
|
log.info("AccountCenter:CheckSaveMysqlDB 停服保存数据中,暂时不执行该Timer")
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
]]
|
|||
|
|
|
|||
|
|
local playerList = skynet.server.playerCenter:GetPlayerList()
|
|||
|
|
|
|||
|
|
local offlineCount = 0 --下线玩家数量
|
|||
|
|
local saveCount = 0 --落地玩家数量
|
|||
|
|
local curTime = skynet.GetTime()
|
|||
|
|
|
|||
|
|
local checkPingTimeout = 180 --正常情况下3分钟断线
|
|||
|
|
local checkOfflineUserTime = 1200 --下线后20分钟未登陆就数据落地
|
|||
|
|
self.PerSaveMaxCount = 50 --每次保存10个
|
|||
|
|
|
|||
|
|
--测试数据,测试时可以打开
|
|||
|
|
--checkPingTimeout = 30
|
|||
|
|
--checkOfflineUserTime = 10
|
|||
|
|
|
|||
|
|
--如果服务器停止了,就尽快让玩家数据落地
|
|||
|
|
if skynet.server.clusterServer and skynet.server.clusterServer.isForceDisconnectCenter then
|
|||
|
|
checkPingTimeout = 60 --服务器停止,ping超时时间设为60秒
|
|||
|
|
checkOfflineUserTime = 90 --服务器停止,离线时间设为90秒
|
|||
|
|
self.PerSaveMaxCount = 20 --服务器停止,大量服务器都会开始保存数据,一次最多写2个玩家数据,以免把数据库搞崩
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
for userId, value in pairs( playerList ) do
|
|||
|
|
if value then
|
|||
|
|
local dbIndex = value.player.basicInfo.dbIndex
|
|||
|
|
local account = value.player.basicInfo.accountName
|
|||
|
|
|
|||
|
|
--玩家游戏状态中,已经ping超时,就设为掉线状态
|
|||
|
|
if 0 == skynet.AddTime and skynet.server.playerCenter.Status_Playing == value.status and curTime - value.pingTime >= checkPingTimeout then
|
|||
|
|
skynet.server.playerCenter:UserOffline( userId )
|
|||
|
|
skynet.server.playerCenter:CloseSocket( value.netType , value.socketId , value.agentId )
|
|||
|
|
offlineCount = offlineCount + 1
|
|||
|
|
log.info(string.format("玩家 %d netType %d Ping超时 %d 秒 强制让玩家掉线" , userId , value.netType , curTime - value.pingTime))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--玩家离线状态中,掉线超过指定时间,就进行数据落地
|
|||
|
|
if skynet.server.playerCenter.Status_Offline == value.status and curTime - value.offlineTime >= checkOfflineUserTime then
|
|||
|
|
|
|||
|
|
if self:SavePlayerToMysql( value.player ) then
|
|||
|
|
saveCount = saveCount +1
|
|||
|
|
self:OfflineProcess( value.player )
|
|||
|
|
log.info(string.format("玩家 %d 数据库索引 %d 保存数据到MysqlDB成功", userId , dbIndex ))
|
|||
|
|
else
|
|||
|
|
value.saveMysqlCount = value.saveMysqlCount + 1
|
|||
|
|
value.offlineTime = value.offlineTime + 300 --离线时间延长5分钟,后面再次尝试保存数据
|
|||
|
|
log.info(string.format("玩家 %d 数据库索引 %d 保存数据到MysqlDB失败%d次", userId , dbIndex , value.saveMysqlCount ))
|
|||
|
|
|
|||
|
|
--失败保存次数达到最大次数,将玩家数据强制写到文件当中
|
|||
|
|
if value.saveMysqlCount >=self.SaveMysqlDBFailedMaxCount then
|
|||
|
|
local basicInfo = value.player.basicInfo
|
|||
|
|
local gameData = value.player.gameData
|
|||
|
|
|
|||
|
|
--组装下玩家数据,写到文件中,方便恢复
|
|||
|
|
self:SaveFailedPlayerDataToFile( value.player )
|
|||
|
|
|
|||
|
|
self:OfflineProcess( value.player )
|
|||
|
|
|
|||
|
|
local errorText = string.format("玩家 %d 数据库索引 %d 保存数据到MysqlDB失败%d次 已达最大次数5次 ", userId , dbIndex , value.saveMysqlCount or 0 )
|
|||
|
|
skynet.server.clusterServer:SendErrorInfoToCenter( account , errorInfo.ErrorCode.SaveUserDataFailed , errorText )
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if saveCount >= self.PerSaveMaxCount then
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
log.info(string.format("成功执行 CheckSaveMysqlDB 下线数量 %d 落地保存数量 %d" , offlineCount , saveCount ))
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local ret,err = pcall(Do)
|
|||
|
|
if not ret or not err then
|
|||
|
|
log.info("内部错误信息 AccountCenter:CheckSaveMysqlDB 检查玩家是否超时未游戏",ret ,err)
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--下线后一些处理
|
|||
|
|
function AccountCenter:OfflineProcess( player )
|
|||
|
|
function Do()
|
|||
|
|
local account = player.basicInfo.accountName
|
|||
|
|
local userId = player.basicInfo.userID
|
|||
|
|
|
|||
|
|
--让玩家从在线列表中删除
|
|||
|
|
local redisKey = string.format( redisKeyUrl.RouteServerLoginInfoHash , account )
|
|||
|
|
skynet.server.redis:del( redisKey )
|
|||
|
|
|
|||
|
|
--触发离线订阅
|
|||
|
|
skynet.server.subscribe:UpdateOfflineTime( player ,1)
|
|||
|
|
skynet.server.playerCenter:UserExit( userId )
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local ret,err = pcall(Do)
|
|||
|
|
if not ret or not err then
|
|||
|
|
--保存玩家数据报错了,有可能是数据有问题,无法转成json,所以直接打到文件中,方便查看
|
|||
|
|
log.info("内部错误信息 AccountCenter:OfflineProcess 下线后一些处理失败", ret ,err)
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--用户登陆游戏
|
|||
|
|
function AccountCenter:UserLoginGame( c2sData , s2cData )
|
|||
|
|
local platform = c2sData.data.platform
|
|||
|
|
local account = c2sData.data.loginAccount
|
|||
|
|
|
|||
|
|
--迁移redis相关
|
|||
|
|
skynet.server.migrateData:AccountData( account )
|
|||
|
|
|
|||
|
|
--检查是创建还是登陆
|
|||
|
|
local userDBInfo = skynet.server.redisCenter:GetRedisDBInfo( account )
|
|||
|
|
local redisUserListKey = string.format( redisKeyUrl.AccountServerUserList , account )
|
|||
|
|
|
|||
|
|
if not userDBInfo and not skynet.server.redis:exists( redisUserListKey ) then
|
|||
|
|
--不存在帐号,创建帐号
|
|||
|
|
self:UserCreateToDB( c2sData , s2cData )
|
|||
|
|
else
|
|||
|
|
--这里肯定是存在玩家帐号的
|
|||
|
|
local dbIndex = userDBInfo.DBIndex
|
|||
|
|
local userId = userDBInfo.UserID --从REDIS中取出来的数据会变成字符串
|
|||
|
|
log.info("玩家登陆游戏" , dbIndex , userId , platform , account )
|
|||
|
|
|
|||
|
|
--根据玩家是否在线来决定从哪里去取数据
|
|||
|
|
local isExistOnlinePlayer = skynet.server.playerCenter:IsExistPlayer( account )
|
|||
|
|
if isExistOnlinePlayer then
|
|||
|
|
--直接从内存中加载数据
|
|||
|
|
self:LoadUserFromMem( account , userId , s2cData )
|
|||
|
|
else
|
|||
|
|
--玩家数据不在内存中,从DB中加载
|
|||
|
|
self:LoadUserFromDB( c2sData , s2cData , userDBInfo )
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if errorInfo.Suc == s2cData.code then
|
|||
|
|
--更新下登陆IP地址
|
|||
|
|
s2cData.data.playerData.basicInfo.lastLoginIP = c2sData.addr
|
|||
|
|
|
|||
|
|
--将该玩家的ID放入在线玩家列表中
|
|||
|
|
local redisKey = string.format( redisKeyUrl.RouteServerLoginInfoHash , account )
|
|||
|
|
skynet.server.redis:hset( redisKey , "Status" , dataType.LoginStatus_IntoGame ) --修改登录状态
|
|||
|
|
skynet.server.redis:persist( redisKey ) --不删除玩家的登录信息
|
|||
|
|
|
|||
|
|
s2cData.data.playerData = json:encode(s2cData.data.playerData)
|
|||
|
|
log.info("将玩家UserID 加入到在线列表成功 ",account )
|
|||
|
|
else
|
|||
|
|
log.info("将玩家UserID 加入到在线列表失败 ",account , s2cData.code)
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--创建用户数据到DB中
|
|||
|
|
function AccountCenter:UserCreateToDB( c2sData , s2cData )
|
|||
|
|
local platform = c2sData.data.platform
|
|||
|
|
local account = c2sData.data.loginAccount
|
|||
|
|
local version = c2sData.data.version
|
|||
|
|
local configType = c2sData.data.configType
|
|||
|
|
local mobile = c2sData.data.mobile
|
|||
|
|
|
|||
|
|
s2cData.code = errorInfo.Suc
|
|||
|
|
s2cData.data = {}
|
|||
|
|
|
|||
|
|
--检查服务器是否能注册
|
|||
|
|
if not skynet.server.gameServer.curServerConfig.IsCanReg then
|
|||
|
|
s2cData.code = errorInfo.ErrorCode.ForbidUserReg
|
|||
|
|
return s2cData
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local rand = 0
|
|||
|
|
local token = ""
|
|||
|
|
local sql = nil
|
|||
|
|
local queryData = nil
|
|||
|
|
local curId = nil
|
|||
|
|
|
|||
|
|
--分配DB索引
|
|||
|
|
local redisKey = string.format(redisKeyUrl.AccountServerCurDBIndex )
|
|||
|
|
local dbIndex = skynet.server.redis:incr(redisKey)
|
|||
|
|
|
|||
|
|
if dbIndex > skynet.server.gameConfig.DBInfoConfig.playerTableCount then
|
|||
|
|
skynet.server.redis:set(redisKey , 1)
|
|||
|
|
dbIndex = 1
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--获取最新DBID
|
|||
|
|
redisKey = string.format(redisKeyUrl.AccountServerUserDBID , dbIndex )
|
|||
|
|
local curId = skynet.server.redis:incr(redisKey)
|
|||
|
|
|
|||
|
|
--创建玩家的redis数据
|
|||
|
|
skynet.server.redisCenter:SetRedisDBInfo( account , "DBIndex" , dbIndex , "UserID" , curId )
|
|||
|
|
|
|||
|
|
local cacheCount = 0 --skynet.server.gameServer.curServerConfig.PerSaveCacheCreateAccount or 0
|
|||
|
|
local cacheAccountInfo = {} --缓存帐号信息
|
|||
|
|
|
|||
|
|
if 0 == cacheCount then
|
|||
|
|
--所有玩家列表到DB
|
|||
|
|
sql = string.format(sqlUrl.insertUserDBIndexToUser , curId , platform , account , dbIndex )
|
|||
|
|
queryData = skynet.server.db:Query( "account" , sql )
|
|||
|
|
if 1 ~= queryData.affected_rows then
|
|||
|
|
log.info("插入DBIndex失败",skynet.server.common:TableToString(queryData) ,sql)
|
|||
|
|
s2cData.code = errorInfo.ErrorCode.AlreadyCreateAccount
|
|||
|
|
local keyUserList = string.format(redisKeyUrl.AccountServerUserList , account )
|
|||
|
|
log.info("创建user数据失败,删除redis中的key ",keyUserList)
|
|||
|
|
skynet.server.redis:del(keyUserList)
|
|||
|
|
return s2cData
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
--将创建的帐号信息进入队列
|
|||
|
|
cacheAccountInfo.curId = curId
|
|||
|
|
cacheAccountInfo.platform = platform
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--组装玩家的游戏数据
|
|||
|
|
local newPlayer = {}
|
|||
|
|
newPlayer.basicInfo = {}
|
|||
|
|
dbData:Traversal( newPlayer.basicInfo , playerFields.InitBasicInfo )
|
|||
|
|
newPlayer.basicInfo.dbIndex = dbIndex
|
|||
|
|
newPlayer.basicInfo.userID = tonumber(curId)
|
|||
|
|
newPlayer.basicInfo.platform = platform
|
|||
|
|
newPlayer.basicInfo.accountName = account
|
|||
|
|
newPlayer.basicInfo.appVersion = c2sData.data.version
|
|||
|
|
newPlayer.basicInfo.channel = c2sData.data.channel
|
|||
|
|
newPlayer.basicInfo.regTime = skynet.GetTime()
|
|||
|
|
newPlayer.basicInfo.regIP = c2sData.addr
|
|||
|
|
newPlayer.basicInfo.lastLoginIP = c2sData.addr
|
|||
|
|
newPlayer.basicInfo.lastExitTime = 0
|
|||
|
|
newPlayer.basicInfo.mobile = mobile
|
|||
|
|
|
|||
|
|
--根据XX来定配置
|
|||
|
|
newPlayer.basicInfo.configType = skynet.server.gameConfig:GetConfigType( configType , 1 )
|
|||
|
|
|
|||
|
|
--游戏数据
|
|||
|
|
newPlayer.gameData = {}
|
|||
|
|
|
|||
|
|
--非存档用户可以初始化线上数据
|
|||
|
|
dbData:Traversal( newPlayer.gameData , playerFields.InitGameData )
|
|||
|
|
|
|||
|
|
local isExistUser , oldData , oldPayCount , inviteCount = self:IosOldPlayer( mobile )
|
|||
|
|
if isExistUser then
|
|||
|
|
--把老苹果用户的存档数据保存在该玩家身上
|
|||
|
|
newPlayer.basicInfo.isOldIOS = true
|
|||
|
|
newPlayer.gameData.oldData = json:decode(oldData)
|
|||
|
|
newPlayer.gameData.oldPayCount = oldPayCount
|
|||
|
|
newPlayer.gameData.inviteCount = inviteCount
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--在player表中创建玩家的数据
|
|||
|
|
sql = string.format(sqlUrl.insertAccountToPlayer ,curId , account , platform , json:encode( newPlayer.basicInfo ) , json:encode( newPlayer.gameData ))
|
|||
|
|
queryData = skynet.server.db:QueryPlayer( dbIndex , sql )
|
|||
|
|
if 1 ~= queryData.affected_rows then
|
|||
|
|
log.info("未成功创建用户ID信息 ",account)
|
|||
|
|
log.info("失败SQL ",sql)
|
|||
|
|
log.info("创建player数据失败,删除user中的玩家ID",curId)
|
|||
|
|
sql = string.format(sqlUrl.deleteUserDBIndexToUser , curId)
|
|||
|
|
skynet.server.db:Query( "account" , sql )
|
|||
|
|
local keyUserList = string.format(redisKeyUrl.AccountServerUserList , account )
|
|||
|
|
log.info("创建player数据失败,删除redis中的key",keyUserList)
|
|||
|
|
skynet.server.redis:del(keyUserList)
|
|||
|
|
s2cData.code = errorInfo.ErrorCode.AlreadyCreateAccount
|
|||
|
|
return s2cData
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--处理邀请注册信息
|
|||
|
|
if c2sData.data.invitePartnerId ~= nil and c2sData.data.invitePartnerId ~= "" then
|
|||
|
|
skynet.server.gameClubTask:BeInviteInfoHandle(newPlayer,c2sData.data.invitePartnerId)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--创建后再进入游戏
|
|||
|
|
log.info("创建帐号并登陆成功 用户ID",curId,account )
|
|||
|
|
|
|||
|
|
local userData = {}
|
|||
|
|
userData.userId = curId
|
|||
|
|
userData.account = account
|
|||
|
|
userData.playerData = newPlayer
|
|||
|
|
userData.announce = ""
|
|||
|
|
s2cData.data = userData
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--从内存中加载玩家数据
|
|||
|
|
function AccountCenter:LoadUserFromMem( account , userId , s2cData )
|
|||
|
|
local player = skynet.server.playerCenter:GetPlayer( userId )
|
|||
|
|
if not player then
|
|||
|
|
log.info(string.format("玩家 %d 从内存中加载失败",userId ))
|
|||
|
|
s2cData.code = errorInfo.ErrorCode.NoExistUser
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local playerData = {}
|
|||
|
|
playerData.basicInfo = player.basicInfo
|
|||
|
|
playerData.gameData = player.gameData
|
|||
|
|
|
|||
|
|
--用户数据
|
|||
|
|
local userData = {}
|
|||
|
|
userData.userId = userId
|
|||
|
|
userData.account = account
|
|||
|
|
userData.playerData = playerData
|
|||
|
|
userData.announce = ""
|
|||
|
|
s2cData.data = userData
|
|||
|
|
log.info(string.format("玩家 %d 从内存中加载数据",userId))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--从DB中加载玩家数据
|
|||
|
|
function AccountCenter:LoadUserFromDB( c2sData , s2cData , userDBInfo )
|
|||
|
|
local dbIndex = userDBInfo.DBIndex
|
|||
|
|
local userId = userDBInfo.UserID
|
|||
|
|
local saveMySqlTime = userDBInfo.saveMySqlTime or 0
|
|||
|
|
local saveMongoTime = userDBInfo.saveMongoTime or 0
|
|||
|
|
|
|||
|
|
local platform = c2sData.data.platform
|
|||
|
|
local account = c2sData.data.loginAccount
|
|||
|
|
local queryData = nil
|
|||
|
|
local basicInfo = nil
|
|||
|
|
local gameData = nil
|
|||
|
|
log.info(string.format("玩家 %d DB相关信息 MysqlTime %d MongoTime %d" , userId , saveMySqlTime , saveMongoTime ))
|
|||
|
|
|
|||
|
|
if ( 0 == saveMySqlTime and 0 == saveMongoTime ) or saveMySqlTime > saveMongoTime then
|
|||
|
|
--mysql保存时间大于mongo保存时间,则从mysql中加载数据
|
|||
|
|
local sql = string.format(sqlUrl.queryAccountFromPlayer , userId )
|
|||
|
|
queryData = skynet.server.db:QueryPlayer( dbIndex , sql )
|
|||
|
|
|
|||
|
|
if not queryData then
|
|||
|
|
--这种报错一般是因为mysql的连接失败
|
|||
|
|
s2cData.code = errorInfo.ErrorCode.NoGetUserDataFromDB
|
|||
|
|
log.info(string.format("玩家 %d 从MysqlDB中加载数据失败",userId))
|
|||
|
|
return s2cData
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
queryData = queryData[1]
|
|||
|
|
log.info(string.format("玩家 %d 从MysqlDB中加载数据成功",userId))
|
|||
|
|
else
|
|||
|
|
--从MongoDB中加载数据
|
|||
|
|
function Do()
|
|||
|
|
queryData = skynet.server.mongo[ "player".. dbIndex]:findOne({ _id = userId })
|
|||
|
|
return queryData
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local isDo, res = pcall( Do )
|
|||
|
|
if not isDo then
|
|||
|
|
--这种报错一般是因为mongo的连接失败
|
|||
|
|
s2cData.code = errorInfo.ErrorCode.NoGetUserDataFromDB
|
|||
|
|
log.info(string.format("玩家 %d 从MongoDB中加载数据失败",userId))
|
|||
|
|
return s2cData
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
queryData = res
|
|||
|
|
log.info(string.format("玩家 %d 从MongoDB中加载数据成功",userId))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--解析数据
|
|||
|
|
basicInfo = json:decode(queryData.BasicInfo)
|
|||
|
|
gameData = json:decode(queryData.GameData)
|
|||
|
|
|
|||
|
|
--检查是否有新字段,有新字段进行处理
|
|||
|
|
dbData:CheckNewFields( basicInfo , playerFields.InitBasicInfo)
|
|||
|
|
dbData:CheckNewFields( gameData , playerFields.InitGameData)
|
|||
|
|
|
|||
|
|
if not userDBInfo.PartnerId then
|
|||
|
|
--由于之前未到账号下保存好友ID,这里做个检测,如果没有就加入进来
|
|||
|
|
skynet.server.redisCenter:SetRedisDBInfo( account , "PartnerId" , gameData.partner.id )
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local playerData = {}
|
|||
|
|
playerData.basicInfo = basicInfo
|
|||
|
|
playerData.gameData = gameData
|
|||
|
|
|
|||
|
|
--处理一下邮件的转义问题
|
|||
|
|
for k ,v in pairs(playerData.gameData.mail.mailList) do
|
|||
|
|
v.content = string.gsub(v.content,"\n","\\n")
|
|||
|
|
v.content = string.gsub(v.content,"\r","\\r")
|
|||
|
|
v.content = string.gsub(v.content,"\t","\\t")
|
|||
|
|
v.content = string.gsub(v.content,"\"","")
|
|||
|
|
v.content = string.gsub(v.content,'"',"")
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--用户数据
|
|||
|
|
local userData = {}
|
|||
|
|
userData.userId = userId
|
|||
|
|
userData.account = account
|
|||
|
|
userData.playerData = playerData
|
|||
|
|
userData.announce = ""
|
|||
|
|
s2cData.data = userData
|
|||
|
|
log.info(string.format("玩家 %d 结束从DB中加载数据",userId))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--同步玩家数据到Redis
|
|||
|
|
function AccountCenter:SyncPlayerDataToRedis( playerData , redisKey )
|
|||
|
|
local basickey = ""
|
|||
|
|
if not redisKey then
|
|||
|
|
basickey = string.format(redisKeyUrl.AccountServerOnlinePlayer , playerData.basicInfo.platform , playerData.basicInfo.userID )
|
|||
|
|
else
|
|||
|
|
basickey = string.format("%s" , redisKey)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
for k, v in pairs( playerData ) do
|
|||
|
|
if "table" == type( v ) then
|
|||
|
|
self:SyncPlayerDataToRedis( v , string.format("%s:%s" , basickey , k ))
|
|||
|
|
else
|
|||
|
|
skynet.server.redis:hset(basickey,k,v)
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--从Redis获取玩家数据
|
|||
|
|
function AccountCenter:GetPlayerFromRedis( id , redisKeyUrl , initData ,data )
|
|||
|
|
if -1 == id then
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
for k, v in pairs( initData ) do
|
|||
|
|
if "table" == type(v[2]) then
|
|||
|
|
redisKeyUrl = string.format("%s:%s" , redisKeyUrl , v[1] )
|
|||
|
|
data[ v[1] ] = {}
|
|||
|
|
self:GetPlayerFromRedis( id , redisKeyUrl , v[2] , data[ v[1] ] )
|
|||
|
|
else
|
|||
|
|
data[ v[1] ] = skynet.server.redis:hget(redisKeyUrl, v[1] )
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--从Redis中删除玩家数据
|
|||
|
|
function AccountCenter:DeletePlayerDataFromRedis( userId , redisKeyUrl , initData )
|
|||
|
|
for k, v in pairs( initData ) do
|
|||
|
|
if "table" == type(v[2]) then
|
|||
|
|
redisKeyUrl = string.format("%s:%s" , redisKeyUrl , v[1] )
|
|||
|
|
self:DeletePlayerDataFromRedis( userId , redisKeyUrl , v[2] )
|
|||
|
|
else
|
|||
|
|
local fields = skynet.server.redis:hkeys(redisKeyUrl)
|
|||
|
|
for k, v in pairs(fields) do
|
|||
|
|
skynet.server.redis:hdel(redisKeyUrl , v)
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--玩家关键数据保存到MongoDB(暂时不用)
|
|||
|
|
function AccountCenter:SaveKeyDataChangeToMongo( player )
|
|||
|
|
function Do()
|
|||
|
|
local account = player.basicInfo.accountName
|
|||
|
|
local userId = player.userId
|
|||
|
|
local dbIndex = player.basicInfo.dbIndex
|
|||
|
|
local bag = json:encode(player.gameData.bag)
|
|||
|
|
local nowTime = skynet.GetTime()
|
|||
|
|
|
|||
|
|
local ok , err , r = skynet.server.mongo[ "player".. dbIndex ]:safe_update({ _id = userId } , { BasicInfo = "nimei" } , true)
|
|||
|
|
if not ok then
|
|||
|
|
log.info("Mongo执行异常 SaveKeyDataChangeToMongo", userId , err , skynet.server.common:TableToString(r))
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local ret,err = pcall(Do)
|
|||
|
|
if not ret or not err then
|
|||
|
|
local account = player.basicInfo.accountName
|
|||
|
|
local userId = player.userId
|
|||
|
|
log.info("内部错误信息 SaveKeyDataChangeToMongo 保存当前玩家失败", account ,userId ,ret ,err )
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--玩家数据保存到MongoDB
|
|||
|
|
function AccountCenter:SavePlayerToMongo( player )
|
|||
|
|
function Do()
|
|||
|
|
player:AddSaveLevel( dataType.SaveLevel_No , true )
|
|||
|
|
|
|||
|
|
local account = player.basicInfo.accountName
|
|||
|
|
local userId = player.userId
|
|||
|
|
local dbIndex = player.basicInfo.dbIndex
|
|||
|
|
local basicInfo = json:encode(player.basicInfo)
|
|||
|
|
local gameData = json:encode(player.gameData)
|
|||
|
|
local nowTime = skynet.GetTime()
|
|||
|
|
local ok , err , r = skynet.server.mongo[ "player".. dbIndex ]:safe_update({ _id = userId} , { BasicInfo = basicInfo , GameData = gameData , SaveTime = nowTime } , true)
|
|||
|
|
if not ok then
|
|||
|
|
log.info("Mongo执行异常 SavePlayerToMongo", userId , err , skynet.server.common:TableToString(r))
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
skynet.server.redisCenter:SetRedisDBInfo( account , "saveMongoTime" , nowTime )
|
|||
|
|
log.info(string.format("玩家 %d 保存数据到MongoDB成功", userId ))
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local ret,err = pcall(Do)
|
|||
|
|
if not ret or not err then
|
|||
|
|
local account = player.basicInfo.accountName
|
|||
|
|
local userId = player.userId
|
|||
|
|
log.info("内部错误信息 SavePlayerToMongo 保存当前玩家失败", account ,userId ,ret ,err )
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--保存玩家数据到DB isIntervalSave非间隔保存
|
|||
|
|
function AccountCenter:SavePlayerToMysql( player )
|
|||
|
|
function Do()
|
|||
|
|
local platform = player.basicInfo.platform
|
|||
|
|
local account = player.basicInfo.accountName
|
|||
|
|
local userId = player.basicInfo.userID
|
|||
|
|
|
|||
|
|
local basicInfo = player.basicInfo
|
|||
|
|
local gameData = player.gameData
|
|||
|
|
local nowTime = skynet.GetTime()
|
|||
|
|
|
|||
|
|
--计算在线时间
|
|||
|
|
player:CalcGameTime( nowTime )
|
|||
|
|
|
|||
|
|
--如果是同一天 则增加当天登录时间
|
|||
|
|
if skynet.server.common:IsSameDay(player.basicInfo.lastGameTime , nowTime ) then
|
|||
|
|
--判断是否可以触发相关礼包
|
|||
|
|
local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue")
|
|||
|
|
local packInfo = cfgSValue.triggerUpgradePack
|
|||
|
|
--如果本日登录时长到达并且等级没有变化 则触发相关礼包
|
|||
|
|
if player.gameData.todayGain.todayGameTime >= packInfo[1]*60*60
|
|||
|
|
and nowTime - player.gameData.upTime >= packInfo[1]*60*60
|
|||
|
|
and player.gameData.level < player.maxLevelLimt
|
|||
|
|
and player.gameData.level >= cfgSValue.storeUnlockLvl then
|
|||
|
|
skynet.server.store:TriggerPack(player , skynet.server.store.TriggerPack_UpGrade)
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--获取数据库索引
|
|||
|
|
local dbIndex = basicInfo.dbIndex
|
|||
|
|
|
|||
|
|
--更新玩家所有数据到数据库
|
|||
|
|
local sql = string.format(sqlUrl.saveAccountToPlayer , json:encode(basicInfo) , json:encode(gameData) , userId )
|
|||
|
|
local queryData = skynet.server.db:QueryPlayer( dbIndex , sql )
|
|||
|
|
if queryData and queryData.errno then
|
|||
|
|
log.info("DB执行异常 SavePlayerToDB", dbIndex , skynet.server.common:TableToString(queryData))
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
player:AddSaveLevel( dataType.SaveLevel_No , true )
|
|||
|
|
|
|||
|
|
skynet.server.redisCenter:SetRedisDBInfo( account , "saveMySqlTime" , skynet.GetTime() )
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local ret,err = pcall(Do)
|
|||
|
|
if not ret or not err then
|
|||
|
|
local account = player.basicInfo.accountName
|
|||
|
|
local userId = player.userId
|
|||
|
|
|
|||
|
|
--保存玩家数据报错了,有可能是数据有问题,无法转成json,所以直接打到文件中,方便查看
|
|||
|
|
log.info("内部错误信息 SavePlayerToDB 保存当前玩家失败", account , userId ,ret ,err)
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--保存Mysql数据库失败的玩家数据写文件
|
|||
|
|
function AccountCenter:SaveFailedPlayerDataToFile( player )
|
|||
|
|
|
|||
|
|
local basicInfo = player.basicInfo
|
|||
|
|
local gameData = player.gameData
|
|||
|
|
local dbIndex = basicInfo.dbIndex
|
|||
|
|
local userId = basicInfo.userID
|
|||
|
|
local account = basicInfo.accountName
|
|||
|
|
local fileName = string.format("SaveFailedPlayerDataToFile_%d_%d.txt", serverId , dbIndex )
|
|||
|
|
local saveFile = io.open( fileName , "a+")
|
|||
|
|
local nowTime = skynet.GetTime()
|
|||
|
|
|
|||
|
|
--有可能玩家JSON数据有问题,无法转,所以这里打印成文本,方便排查问题
|
|||
|
|
function Do1()
|
|||
|
|
log.info("玩家数据写入失败" , account , userId , skynet.server.common:TableToString(basicInfo) , skynet.server.common:TableToString(gameData))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local isDo1,callData1 = pcall( Do1 )
|
|||
|
|
if not isDo1 then
|
|||
|
|
local errorText = "保存玩家数据到文件失败 , 只有打印相关数据,方便排查问题1"
|
|||
|
|
log.warning( errorText , callData1)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--转成sql,方便直接恢复玩家数据
|
|||
|
|
function Do2()
|
|||
|
|
local sql = string.format(sqlUrl.saveAccountToPlayer , json:encode(basicInfo) , json:encode(gameData) , userId )
|
|||
|
|
sql = string.format("%s|%s|%d|%s \r\n" , skynet.server.common:GetStrTime( nowTime ) , account, userId , sql)
|
|||
|
|
saveFile:write( sql )
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local isDo2,callData2 = pcall( Do2 )
|
|||
|
|
if not isDo2 then
|
|||
|
|
local errorText = "保存玩家数据到文件失败 , 只有打印相关数据,方便排查问题2"
|
|||
|
|
if userId then
|
|||
|
|
log.warning(errorText , userId , callData2 , skynet.server.common:TableToString(basicInfo) , skynet.server.common:TableToString(gameData) )
|
|||
|
|
else
|
|||
|
|
log.warning( errorText , callData2 , skynet.server.common:TableToString(basicInfo) , skynet.server.common:TableToString(gameData))
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
saveFile:close()
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--检查参数是否有效
|
|||
|
|
function AccountCenter:CheckParam( key , value)
|
|||
|
|
if nil == key or nil == value then
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local suc = true
|
|||
|
|
local paramLen = 0 --参数长度,字符串会取长度,其余参数为0
|
|||
|
|
if "string" == type(value) then
|
|||
|
|
paramLen = #value
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if "platform" == key and paramLen > 32 then
|
|||
|
|
suc = false
|
|||
|
|
elseif "loginAccount" == key and paramLen > 20 then
|
|||
|
|
suc = false
|
|||
|
|
elseif "loginToken" == key and 8 ~= paramLen then
|
|||
|
|
suc = false
|
|||
|
|
elseif "hardwareCode" == key and paramLen > 64 then
|
|||
|
|
suc = false
|
|||
|
|
elseif "channel" == key and paramLen > 32 then
|
|||
|
|
suc = false
|
|||
|
|
elseif "gameCgi" == key and paramLen > 32 then
|
|||
|
|
suc = false
|
|||
|
|
elseif "configType" == key and ( paramLen > 16 or nil == skynet.server.gameConfig:GetConfigType( value , 1 ) ) then
|
|||
|
|
suc = false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if not suc then
|
|||
|
|
log.warning(string.format("参数 %s 值 %s 异常 长度 %d" , key , value, paramLen ))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return suc
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--保存缓存账号到DB(废弃)
|
|||
|
|
function AccountCenter:SaveCacheCreateAccountToDB()
|
|||
|
|
local userPararm = nil
|
|||
|
|
local playerPararm = nil
|
|||
|
|
|
|||
|
|
local cacheCount = skynet.server.gameServer.curServerConfig.PerSaveCacheCreateAccount or 0
|
|||
|
|
if 0 == cacheCount then
|
|||
|
|
return false
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
for dbIndex = 1, skynet.server.gameConfig.DBInfoConfig.playerTableCount, 1 do
|
|||
|
|
local sqlUser = sqlUrl.insertUserDBIndexToUser1
|
|||
|
|
local sqlPlayer = sqlUrl.insertAccountToPlayer1
|
|||
|
|
local saveCount = 0 --当前保存的数量
|
|||
|
|
local account = nil
|
|||
|
|
local accountInfo = nil
|
|||
|
|
local queueCount = self.queueAccount[ dbIndex ].Count --当前队列中的缓存数量
|
|||
|
|
local curSaveList = {}
|
|||
|
|
log.info(string.format("目前缓存账号信息 DB %d 数量 %d" , dbIndex , queueCount ))
|
|||
|
|
|
|||
|
|
function Do()
|
|||
|
|
for i = 1, queueCount , 1 do
|
|||
|
|
--从队列中取出数据
|
|||
|
|
local item = self.queueAccount[ dbIndex ]:DeQueue()
|
|||
|
|
if not item or not item.key or "" == item.key or not item.value then
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
account = item.key
|
|||
|
|
accountInfo = item.value
|
|||
|
|
saveCount = saveCount + 1
|
|||
|
|
table.insert( curSaveList , account )
|
|||
|
|
|
|||
|
|
--组装SQL
|
|||
|
|
userPararm = string.format(sqlUrl.insertUserDBIndexToUser2 , accountInfo.curId , accountInfo.platform , account , dbIndex )
|
|||
|
|
sqlUser = sqlUser .. userPararm
|
|||
|
|
|
|||
|
|
playerPararm = string.format(sqlUrl.insertAccountToPlayer2 , accountInfo.curId , account , accountInfo.platform , json:encode( accountInfo.basicInfo ) , json:encode( accountInfo.gameData ) )
|
|||
|
|
sqlPlayer = sqlPlayer .. playerPararm
|
|||
|
|
|
|||
|
|
if saveCount >= cacheCount then
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if saveCount >0 then
|
|||
|
|
--超过最大保存次数
|
|||
|
|
local curTime = skynet.GetTime()
|
|||
|
|
sqlUser = string.sub(sqlUser , 1, -2 ) --去掉最后一个逗号
|
|||
|
|
local queryData = skynet.server.db:Query( "account" , sqlUser )
|
|||
|
|
if saveCount ~= queryData.affected_rows then
|
|||
|
|
log.info("user 插入数据失败", sqlUser , skynet.server.common:TableToString(queryData))
|
|||
|
|
skynet.server.clusterServer:SendErrorInfoToCenter( account , errorInfo.ErrorCode.CacheCreateAccountError , string.format("user 插入数据失败 %d %d", saveCount or 0 , queryData.affected_rows or 0 ))
|
|||
|
|
end
|
|||
|
|
log.info(string.format("user 保存缓存创建玩家数据 数据库索引 %d 应保存人数 %d 实际保存人数 %d 保存用时 %d 秒", dbIndex , saveCount , queryData.affected_rows , curTime - skynet.GetTime()))
|
|||
|
|
|
|||
|
|
sqlPlayer = string.sub(sqlPlayer , 1, -2 ) --去掉最后一个逗号
|
|||
|
|
queryData = skynet.server.db:QueryPlayer( dbIndex , sqlPlayer )
|
|||
|
|
if saveCount ~= queryData.affected_rows then
|
|||
|
|
log.info("player 插入数据失败", sqlUser , skynet.server.common:TableToString(queryData))
|
|||
|
|
skynet.server.clusterServer:SendErrorInfoToCenter( account , errorInfo.ErrorCode.CacheCreateAccountError , string.format("player 插入数据失败 %d %d", saveCount or 0 , queryData.affected_rows or 0 ))
|
|||
|
|
end
|
|||
|
|
log.info(string.format("player 保存缓存创建玩家数据 数据库索引 %d 应保存人数 %d 实际保存人数 %d 保存用时 %d 秒", dbIndex , saveCount , queryData.affected_rows , curTime - skynet.GetTime() ))
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local ret,err = pcall(Do)
|
|||
|
|
if not ret then
|
|||
|
|
log.info("内部错误信息 缓存保存当前玩家失败1", ret ,err , account , sqlUser , sqlPlayer)
|
|||
|
|
log.info("内部错误信息 缓存保存当前玩家失败2", skynet.server.common:TableToString(curSaveList))
|
|||
|
|
return
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
return true
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
skynet.server.accountCenter = AccountCenter
|
|||
|
|
return AccountCenter
|