HomeServer/Server/AllServer/MultiServer/MultiServer.lua

650 lines
26 KiB
Lua
Raw Normal View History

2024-11-20 15:41:09 +08:00
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