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

650 lines
26 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 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