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 errorInfo = require "ErrorInfo" local serverId = tonumber(skynet.getenv "serverId") local redisKeyUrl = require "RedisKeyUrl" local serverManage = require "ServerManage" local dataServer = require "DataService" local chatManage = require "ChatManage" local dataCopyService = require "DataCopyService" local personal = require "Personal" local mail =require "Mail" local playerLand = require "PlayerLand" local payServer = require "PayServer" local clusterServer = require "ClusterServer" local MultiServer = oo.class(clusterServer) --初始化 function MultiServer:Init() self.WXOrderList = {} --微信通知 end --跨天 function MultiServer:OnNewDay() end --1秒Timer function MultiServer:On1SecTimer() end MultiServer.qq = false --5秒Timer function MultiServer:On5SecTimer() if not self.qq then self.qq = true --self:Test() end end function MultiServer:Test() local readFile= assert(io.open("异常加速名单.txt")) local writeFile= assert(io.open("未处理的名单.txt","w")) local errorFile = assert(io.open("错误的名单.txt","w")) local guangFile = assert(io.open("光子的名单.txt","w")) --删除背包 local function RemoveBag( account , myBag , goodsType , goodsId , count ) for k, v in pairs( myBag ) do if goodsType == v.type and goodsId == v.id then --背包减去数量 local tmpCount = v.count - count if tmpCount <= 0 then table.remove( myBag , k) else v.count = v.count - count end log.debug(string.format("玩家 %s 背包删除 商品类型 %d 商品ID %d 数量 %d 最新数量 %d" , account , goodsType , goodsId , count, v.count)) break end end end while true do local userInfo = readFile:read() if nil == userInfo then break end local rewardInfo = skynet.server.common:Split(userInfo, "|") local account = rewardInfo[1] local reduceVolueCount = math.floor(tonumber(rewardInfo[2])) --需要减去家具数量 local reduceCoinCount = math.floor(tonumber(rewardInfo[3])) --需要减去的碎片数量 log.info("11111111a") local redisKey = string.format(redisKeyUrl.RouteServerLoginInfoHash , account ) if skynet.server.redis:exists( redisKey) then --玩家在线,就不写 writeFile:write(userInfo) log.info("11111111b1") else log.info("11111111b2") local userDBInfo = skynet.server.redisCenter:GetRedisDBInfo( account ) if userDBInfo then local dbIndex = userDBInfo.DBIndex local userId = userDBInfo.UserID --从REDIS中取出来的数据会变成字符串 log.info("11111111c" , dbIndex , userId) --从玩家表中获取数据 --local sql = string.format("select GameData->'$.coin' as myCoin ,GameData->'$.clovers' as myClovers,GameData->'$.volute' as myVolue \ --,GameData->'$.bag' as myBag from player where UserID = %d" , userId ) local sql = string.format(sqlUrl.queryAccountFromPlayer , userId ) local queryData = skynet.server.db:QueryPlayer( dbIndex , sql ) if queryData then queryData = queryData[1] local basicInfo = json:decode( queryData.BasicInfo) local gameData = json:decode(queryData.GameData) --local queryData = skynet.server.db:QueryPlayer( dbIndex , sql ) if gameData then --log.info("222222222222222",skynet.server.common:TableToString(gameData)) --处理一下邮件的转义问题 for k ,v in pairs(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 log.info("11111111d") --local myCoin = tonumber(gameData.coin) --local myClovers = tonumber(gameData.clovers) --local myVolue = tonumber(gameData.volute) local fragmentNum = tonumber(gameData.design.fragmentNum) log.info(string.format("玩家 %s 家具数量 %d 碎片数量 %d 背包数量 %d " , account , reduceVolueCount , fragmentNum , #gameData.bag)) RemoveBag( account , gameData.bag , 11 , 1362 , reduceVolueCount) --嫩黄潮装冰箱 if account == "6028822114510006784" then RemoveBag( account , gameData.bag , 11 , 2048 , 1) --星际生态椅 RemoveBag( account , gameData.bag , 11 , 2049 , 1) --智温绿护舱 RemoveBag( account , gameData.bag , 11 , 2050 , 1) --生态育培柱 RemoveBag( account , gameData.bag , 11 , 2051 , 1) --星河碎星灯 RemoveBag( account , gameData.bag , 11 , 2052 , 1) --璀璨星河窗 RemoveBag( account , gameData.bag , 11 , 2053 , 1) --内嵌绿植窗 RemoveBag( account , gameData.bag , 11 , 2054 , 1) --悬浮智械管家 RemoveBag( account , gameData.bag , 11 , 2055 , 1) --智航机械臂 RemoveBag( account , gameData.bag , 11 , 2056 , 1) --生态智能桌 RemoveBag( account , gameData.bag , 11 , 2057 , 1) --智航全息电脑 RemoveBag( account , gameData.bag , 11 , 2058 , 1) --宠物休眠仓 RemoveBag( account , gameData.bag , 11 , 2059 , 1) --全息星球仪 RemoveBag( account , gameData.bag , 11 , 2060 , 1) --星舰气密门 RemoveBag( account , gameData.bag , 11 , 2061 , 1) --智航全息屏 RemoveBag( account , gameData.bag , 11 , 2062 , 1) --登月地灯 RemoveBag( account , gameData.bag , 11 , 2063 , 1) --登月地灯 elseif account == "6028726715199328000" then RemoveBag( account , gameData.bag , 11 , 2048 , 1) -- RemoveBag( account , gameData.bag , 11 , 2049 , 1) -- RemoveBag( account , gameData.bag , 11 , 2055 , 1) -- RemoveBag( account , gameData.bag , 11 , 2057 , 1) -- RemoveBag( account , gameData.bag , 11 , 2059 , 1) -- RemoveBag( account , gameData.bag , 11 , 2060 , 1) -- RemoveBag( account , gameData.bag , 11 , 2062 , 1) -- end --RemoveBag( account , gameData.bag , 21 , 6 , reduceGoods6Count ) --加速券 --[[ myVolue = myVolue - reduceVolueCount myCoin = myCoin - reduceCoinCount if myVolue < 0 then myVolue = 0 end if myCoin < 0 then myCoin = 0 end gameData.coin = myCoin gameData.volute = myVolue log.info("11111111e" , myVolue , myCoin) ]] gameData.design.fragmentNum = gameData.design.fragmentNum - reduceCoinCount if gameData.design.fragmentNum < 0 then gameData.design.fragmentNum = 0 end --sql = string.format("update player set GameData = JSON_SET(GameData , '$.volute', %d , '$.coin', %d , '$.bag' , %s ) where UserID = %d" , myVolue , myCoin , json:encode(myBag) , userId ) local sql = string.format(sqlUrl.saveAccountToPlayer , json:encode(basicInfo) , json:encode(gameData) , userId ) --log.info("44444444", sql) 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 errorFile:write(userInfo) end log.info(string.format("玩家 %s 处理完成 背包数量 %d" , account , #gameData.bag )) skynet.sleep(200) --break else errorFile:write(userInfo) log.info("11111111f") end else errorFile:write(userInfo) log.info("11111111f1") end else guangFile:write(userInfo) log.info("11111111g") end end end log.info("11111111h") readFile:close() writeFile:close() errorFile:close() guangFile:close() end --接收集群数据 function MultiServer:ClusterRecv(...) local cmd , c2sData = ... local s2cData = {} s2cData.code = errorInfo.Suc if self.Center2All_ServerManageCmd == cmd then --中心服集群消息 serverManage:DoManageCmd( c2sData , s2cData ) elseif self.Center2All_SyncClusterInfo == cmd then self:RecvSyncClusterInfo( c2sData ) elseif self.Center2All_SyncServerConfig == cmd then --同步服务器配置 self:RecvSyncServerConfig( c2sData ) else log.info(string.format("集群服务器 消息接口 %d 不存在", cmd)) s2cData.code = errorInfo.ErrorCode.NoExistInterface end log.info("集群服务器 消息接口", cmd , "返回信息",s2cData.code) return s2cData end --接收HTTP数据 function MultiServer:HttpRecv( c2sData , url , addr ) c2sData.addr = addr local s2cData = {} s2cData.state = {} s2cData.code = errorInfo.Suc --组装签名参数{post方式可用,目前只有微信游戏圈发货采用} local signParam = {} if c2sData.bodyStr ~=nil and c2sData.bodyStr ~= "" then signParam["_body"]=c2sData.bodyStr:gsub("%s+", "") --删除多余参数{影响签名} c2sData.bodyStr = nil end if c2sData.getData ~= nil and type(c2sData.getData) == "string" then local getData = skynet.server.httpServer:Translate(c2sData.getData) if next(getData) then --合并参数 for key, value in pairs(getData) do c2sData[key]=value signParam[key]=value end end --删除多余参数{影响签名} c2sData.getData = nil end -- if not self.isConnectCenterServer then -- --断开了就不允许接收后台的邮件请请求 -- s2cData.code = errorInfo.ErrorCode.ServiceOffline -- return s2cData -- end --验证管理员 --[[ if not self:CheckAdmin( c2sData , s2cData , url ) then return s2cData end ]] if "QueryGoodsRecord" == url then skynet.server.dataService:QueryGoodsRecord( c2sData , s2cData ) elseif "QueryGoodsLocation" == url then skynet.server.dataService:QueryGoodsLocation( c2sData , s2cData ) elseif "QueryUserInfo" == url then skynet.server.dataService:QueryUserInfo( c2sData , s2cData ) elseif "QueryDecoWeek" == url then skynet.server.dataService:QueryDecoWeek( c2sData , s2cData ) elseif "QueryDecoWeekReward" == url then skynet.server.dataService:QueryDecoWeekReward( c2sData , s2cData ) elseif "SendDecoWeekReward" == url then skynet.server.dataService:SendDecoWeekReward( c2sData , s2cData ) elseif "ChatBan" == url then skynet.server.chatManage:Ban( c2sData , s2cData ) elseif "ChatClear" == url then skynet.server.chatManage:Clear( c2sData , s2cData ) elseif "GMCopyData" == url then skynet.server.dataCopyService:DataCopy( c2sData , s2cData ) elseif "GMCopyDataTo" == url then skynet.server.dataCopyService:DataCopyTo( c2sData , s2cData ) elseif "AddWXNotify" == url then self:AddWXNotify( c2sData , s2cData,signParam ) else log.info(string.format("Http服务器 消息接口 %s 不存在", url)) s2cData.code = errorInfo.ErrorCode.NoExistInterface end log.info("Http服务器 消息接口 ",url ,"返回信息",s2cData.code) return s2cData end --新增微信发货-sdk转发 function MultiServer:AddWXNotify( c2sData , s2cData ,signParam) --测试代码注意取消注释 if not c2sData.MiniGame or self.WXOrderList[ c2sData.MiniGame.OrderId ] then s2cData.state.code = 1 --重复订单 return end --参数 --local serverId = c2sData.serverId local account = tostring(c2sData.gameAccountId) --判断配置是否为空 if not next(c2sData.MiniGame.GoodsList) then log.debug("微信通知 c2sData.MiniGame.GoodsList is nil") s2cData.state.code = 2 --参数错误 s2cData.ErrCode = 2 --参数错误 return end --道具id,这里用第一个道具id作为邮件id local mailId = c2sData.MiniGame.GoodsList[1].Id --查找邮件配置 local mailCfg = mail:FindMailByMailId(mailId) if mailCfg == nil then log.info("微信通知 邮件不存在,mailId:",mailId) s2cData.state.code = 2 --参数错误 s2cData.ErrCode = 2 --参数错误 return end --验证签名 local sign = payServer:GenerateSign( signParam ) log.info(string.format("微信通知 玩家 %s 生成的Sign %s 收到的Sign %s", account , sign , c2sData.sign)) if sign ~= c2sData.sign then s2cData.state.code = 2 --发货失败 s2cData.ErrCode = 2 --参数错误 log.info(string.format("微信通知 玩家 %s Sign不一致" , account )) return end s2cData.state.code = 1 --进这里面都能表示成功 s2cData.ErrCode = 0 --进这里面都能表示成功 s2cData.ErrMsg ="Success" --充值信息 local sendData = {} sendData.account = account sendData.mailId = mailId --缓存失败的充值 local function OfficialPayFailedAccount() --将失败数据插入到redis中去 local redisKey = redisKeyUrl.PayServerWXNotifyFailedAccountSet skynet.server.redis:sadd( redisKey , account ) redisKey = string.format( redisKeyUrl.PayServerWXNotifyFailedAccountList , account ) skynet.server.redis:rpush( redisKey , json:encode(sendData) ) -- --通知道其它游戏服 -- local tmpData = {} -- tmpData.account = account -- self:SendMsgToGameServer( self.Pay2Game_WXNotifyPayFailedAccount , tmpData , s2cData ) end local redisKey = string.format( redisKeyUrl.RouteServerLoginInfoHash , account ) local isExistLogin = skynet.server.redis:exists( redisKey ) if isExistLogin then --存在玩家的登录信息 local gameServerId = tonumber(skynet.server.redis:hget( redisKey , "GameServerID")) if not gameServerId or not self.clusterInfo[ gameServerId ] then OfficialPayFailedAccount() else local callData = {} local isSuc = self:SendMsgToOneGameServer( self.Pay2Game_WXNotifyAddPayInfo , gameServerId , sendData , callData ) if not isSuc then if errorInfo.ErrorCode.NoExistUser == callData.code then log.info(string.format("微信通知 玩家 %s 玩家未在线1", account )) OfficialPayFailedAccount() else s2cData.state.code = 2 --发货失败 end end end else log.info(string.format("微信通知 玩家 %s 玩家未在线2", account )) OfficialPayFailedAccount() end --将充值数据保存到DB local sql = string.format(sqlUrl.insertPayRecord , json:encode( c2sData )) local insertData = skynet.server.db:Query("game" , sql ) if 1 ~= insertData.affected_rows then log.info(string.format("微信通知 玩家 %s 插入服务器配置失败 %s", account , sql )) end --保存订单,{重复订单验证} self.WXOrderList[ c2sData.MiniGame.OrderId ] = skynet.GetTime() end --发送消息到GS function MultiServer:SendMsgToOneGameServer( cmd , gameServerId , sendData , callData ) local clusterReturn = {} local account = tostring(sendData.account) for k, v in pairs(self.clusterInfo) do if self:IsGameServer( v.serverId ) and gameServerId == v.serverId and (v.status == self.Status_Running or v.status == self.Status_Stop) then log.info(string.format("充值 玩家 %s 充值服向游戏服 %d 发送消息 %d 开始" , account , v.serverId , cmd )) clusterReturn = self:CallMsgToServer(v.serverId , cmd , sendData ) if clusterReturn and errorInfo.Suc == clusterReturn.code then log.info(string.format("充值 玩家 %s 充值服向游戏服 %d 发送消息 %d 成功" , account , v.serverId , cmd )) callData.code = clusterReturn.code return true else log.info(string.format("充值 玩家 %s 充值服向游戏服 %d 发送消息 %d 失败" , account , v.serverId , cmd )) callData.code = clusterReturn and clusterReturn.code or errorInfo.ErrorCode.NoExistUser return false end end end return false end --测试数据 function MultiServer:TestData() --异常加币玩家数据修复 --[[ local readFile= assert(io.open("5000个.txt")) while true do local account = readFile:read() if nil == account then break end account = string.sub(account , 1,-2 ) local redisKey = string.format(redisKeyUrl.GameServerMailMyNewForAccountZSet, account) if skynet.server.redis:exists( redisKey ) then log.info("1111111111",account) skynet.server.redis:del(redisKey ) else log.info("2222222222",account) end end ]] --local readFile1= assert(io.open("157服登陆玩家.txt")) --local readFile2= assert(io.open("157服已保存的.txt")) --local writeFile= assert(io.open("补偿玩家.txt","w")) --[[ --获取最新的周赛 local curActivityId = 10 local redisKey = string.format(redisKeyUrl.GameServerActivityDecoWeekHumanVoteScoreZSet , curActivityId ) local rankList = skynet.server.redis:zrevrange(redisKey, 0, 100 , "withscores") rankList = redisKeyUrl:CovertTable(rankList) local newRankList = {} for k, v in pairs(rankList) do local partnerId = k local score = v table.insert(newRankList, { partnerId = partnerId, score = score }) end table.sort(newRankList, function(a, b) return a.score > b.score end) for k, v in pairs( newRankList ) do log.info(string.format("https://myres.myfreetime.casdk.cn/serverres/home/Images/ActivityDecoWeek/%d/%s_%d.jpg 分数 %d" , curActivityId , v.partnerId , curActivityId , v.score)) end --异常加币玩家数据修复 local readFile= assert(io.open("异常加速名单.txt")) local writeFile= assert(io.open("未处理的名单.txt","w")) while true do local errorData = readFile:read() if nil == errorData then break end local rewardInfo = skynet.server.common:Split(errorData, "|") local account = rewardInfo[1] local payCount = math.floor(tonumber(rewardInfo[2])) --需要减去的沃克币 local redisKey = string.format(redisKeyUrl.RouteServerLoginInfoHash , account ) if skynet.server.redis:exists( redisKey) then --玩家在线,就不写 writeFile:write(errorData) else local redisKey = string.format(redisKeyUrl.AccountServerUserList , account ) --不用改 if skynet.server.redis:exists( redisKey) then local dbIndex = skynet.server.redis:hget( redisKey , "DBIndex") local userId = tonumber(skynet.server.redis:hget( redisKey , "UserID")) --从REDIS中取出来的数据会变成字符串 --从玩家表中获取数据 local sql = string.format("select GameData->'$.coin' as myCoin ,GameData->'$.clovers' as myClovers,GameData->'$.volute' as myVolue from player where UserID = %d" , userId ) local queryData = skynet.server.db:QueryPlayer( dbIndex , sql ) log.info(string.format("玩家 %s 充值金额 %d 异常 金币数量 %d 三叶草数量 %d 蜗壳币数量 %d " , account , payCount , tonumber(queryData[1].myCoin), tonumber(queryData[1].myClovers), tonumber(queryData[1].myVolue) )) if queryData[1] and tonumber(queryData[1].myVolue) and tonumber(queryData[1].myVolue) > (payCount * 10) then if tonumber(queryData[1].myVolue) >= 500000 then --蜗壳币够,就直接扣除。 local sNum = tonumber(queryData[1].myVolue) sNum = string.sub(sNum, -3) local nNum = 0 if tonumber(sNum) <= 100 then nNum = tonumber(sNum) + 100 else nNum = tonumber(sNum) end sql = string.format("update player set GameData = JSON_SET(GameData, '$.volute', %d) where UserID = %d" , nNum , userId ) local queryData1 = skynet.server.db:QueryPlayer( dbIndex , sql ) log.info(string.format("玩家 %s 充值金额 %d 异常蜗壳币数量 %d 成功回退至蜗壳币数量 %d" , account , payCount , tonumber(queryData[1].myVolue) , nNum)) else log.info(string.format("玩家 %s 充值金额 %d 异常蜗壳币数量 %d 不足50000", account , payCount , tonumber(queryData[1].myVolue))) end end end end --break end readFile:close() writeFile:close() ]] --[[读取一个服进出的玩家 local readFile= assert(io.open("152.txt")) local writeFile= assert(io.open("152服异常关闭.txt","w")) local listAccount = {} while true do local errorData = readFile:read() if nil == errorData then break end local rewardInfo = skynet.server.common:Split(errorData, " ") if rewardInfo[10] then listAccount[ rewardInfo[10] ] = true end --log.info("11111111111111",skynet.server.common:TableToString(rewardInfo)) --break end for k, v in pairs(listAccount) do --log.info(k) writeFile:write(k) end ]] --[[ local redisKey = "PayServer:AllPlayerPayAccountZSet" --每个玩家充值的金额总和 if skynet.server.redis:exists( redisKey ) then skynet.server.redis:del( redisKey ) end local f = assert(io.open("充值.txt")) while true do local mobile = f:read() if nil == mobile then break end local rewardInfo = skynet.server.common:Split(mobile, "|") rewardInfo[2] = string.sub(rewardInfo[2] , 1,-2 ) skynet.server.redis:zadd( redisKey , tonumber(rewardInfo[1]), rewardInfo[2]) end f:close() ]] --[[ local redisKey = redisKeyUrl.AccountServerOldIOSPlayerSet if skynet.server.redis:exists( redisKey ) then skynet.server.redis:del( redisKey ) end local f = assert(io.open("old_players.txt")) while true do local mobile = f:read() if nil == mobile then break end mobile = string.sub(mobile , 1,-2 ) log.info("11111111111",redisKey, mobile) skynet.server.redis:sadd( redisKey , mobile) end f:close() ]] --[[ local f = assert(io.open("test.txt")) local accountList = {} while true do local source = f:read() if nil == source then break end log.info("读取玩家数据 " , source) table.insert(accountList , source) --local redisKey = string.format( redisKeyUrl.accountMailList , source ) --skynet.server.redis:set( redisKey , false ) --skynet.server.redis:expire( redisKey , 2592000) end f:close() ]] --[[ local account = "rl191" local redisKey = string.format(redisKeyUrl.AccountServerUserList , account ) --不用改 if skynet.server.redis:exists( redisKey) then local dbIndex = skynet.server.redis:hget( redisKey , "DBIndex") local userId = tonumber(skynet.server.redis:hget( redisKey , "UserID")) --从REDIS中取出来的数据会变成字符串 --从玩家表中获取数据 local sql = string.format(sqlUrl.queryAccountFromPlayer , userId ) local queryData = skynet.server.db:QueryPlayer( dbIndex , sql ) queryData = queryData[1] local basicInfo = json:decode(queryData.BasicInfo) local gameData = json:decode(queryData.GameData) end ]] end skynet.server.multiServer = MultiServer return MultiServer