c1_lua/lua/app/net/net_manager.lua
2023-08-29 10:58:37 +08:00

1194 lines
43 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 NetManager =
{
receiveCallbacks = {},
msgCallbacks = {},
isClosedMap = {},
chatReconnectWaitTime = 1,
connectIPMap = {},
receiveCallbackPool = {},
alreadyConnected = {},
mainReconnectWaitTime = 0,
sendQueue = {},
tillBeforeOverCount = 0,
msgId = 0
}
local CSApplication = CS.UnityEngine.Application
local CSNotReachable = CS.UnityEngine.NetworkReachability.NotReachable
local MAX_CHAT_WAIT_TIME = 16
local MAX_MAIN_WAIT_TIME = 10
local JOIN_CHAT_INTERVAL = 15
local TILL_BEFORE_INTERVAL = 0.5
local NetErrorCode = CS.BF.NetErrorCode
local pb = require "pb"
local ProtoMsgDispatch = require "app/proto/proto_msg_dispatch"
local protoPaths =
{
"assets/proto/protocol.bytes",
}
NetManager.MAIN_SOCKET_NAME = 0
NetManager.CHAT_SOCKET_NAME = 1
NetManager.LOGIN_TYPE = {
TOKEN = "token",
ANONYMOUS = "anonymous",
GOOGLE = "google",
APPLE = "apple",
FACEBOOK = "facebook",
}
function NetManager:getGate()
if EDITOR_MODE then
return "http://game.juzugame.com:3000"
else
return "https://d3ksek7t8d0wbt.cloudfront.net/"
end
end
function NetManager:init(callback)
self.chatReconnectWaitTime = 1
CS.BF.BFMain.Instance.NetMgr:InitNetClientCount(1) -- 只有主链接,没有聊天,但是聊天逻辑先不删
if self.initSucc then
if callback then
return callback()
end
end
self.initSucc = true
-- pb.option "int64_as_string" --如果需要uint64再加上
local loadCount = #protoPaths
for i, path in ipairs(protoPaths) do
ResourceManager:loadOriginAssetAsync(path, GConst.TYPEOF_UNITY_CLASS.TEXT_ASSET, function(_, textAsset)
pb.load(textAsset.bytes)
ResourceManager:unload(path)
loadCount = loadCount - 1
if loadCount == 0 then
if callback then
return callback()
end
end
end)
end
end
function NetManager:setChatUrl(url)
local arr = string.split(url, ":")
self.chatDomain = arr[1]
self.chatPort = arr[2]
end
function NetManager:getChatDomain()
return self.chatDomain
end
function NetManager:getChatPort()
return self.chatPort
end
function NetManager:getIsBusy()
return self.isSending
end
function NetManager:isNotReachable()
return CSApplication.internetReachability == CSNotReachable
end
function NetManager:connect(domain, port, callback, socketName)
socketName = socketName or NetManager.MAIN_SOCKET_NAME
if self:isAvailable(socketName) then
if callback then
callback()
end
return
end
self.alreadyConnected[socketName] = false
self.isClosedMap[socketName] = false
if socketName == NetManager.MAIN_SOCKET_NAME then
UIManager:showWaitNet(true)
end
self.connectIPMap[socketName] = ""
CS.BF.BFMain.Instance.NetMgr:AddLuaOnConnected(function(name)
self.alreadyConnected[name] = true
Logger.log("[NetManager]connect success:%s", name)
local connectIP = self:getConnectIP(name)
self.connectIPMap[socketName] = connectIP
if name == NetManager.MAIN_SOCKET_NAME then
if self.reconnectMainId then
SchedulerManager:unscheduleGlobal(self.reconnectMainId)
self.reconnectMainId = nil
end
self.mainReconnectWaitTime = 0
UIManager:hideWaitNet()
else
self.chatReconnectWaitTime = 1
if self.reconnectChatId then
SchedulerManager:unscheduleGlobal(self.reconnectChatId)
self.reconnectChatId = nil
end
if DataManager.ChatData then
DataManager.ChatData:onConnect()
end
self:joinChatChannel()
end
if callback then
callback()
end
end)
CS.BF.BFMain.Instance.NetMgr:AddLuaOnDisconnected(function(name)
-- self:onDisconnect(name)
self:disconnectAndReconnect()
end)
CS.BF.BFMain.Instance.NetMgr:AddLuaOnReceiveMessage(function(name, group, recvId, bytes)
if name == NetManager.MAIN_SOCKET_NAME then
self.recvId = recvId
if self.reconnectMainFlag then -- 如果是在重连状态下收到消息就设置下重连所需要的数据
self:setReconnectData()
end
end
self:onReceive(group, bytes)
end)
CS.BF.BFMain.Instance.NetMgr:AddLuaOnError(function(name, errorCode, errorMsg)
self:onError(name, errorCode, errorMsg)
end)
CS.BF.BFMain.Instance.NetMgr:AddLuaOnReconnectSuccess(function(name)
Logger.log("[NetManager]reconnect succes:%s", name)
if self.receiveCallbacks["ChapterSettlementRsp"] then -- 处理一下重发问题
if #self.receiveCallbacks["ChapterSettlementRsp"] > 0 then
self.receiveCallbacks["ChapterSettlementRsp"] = nil
self.isSending = false
self:trySend()
end
end
if name == NetManager.MAIN_SOCKET_NAME then
if self.reconnectMainId then
SchedulerManager:unscheduleGlobal(self.reconnectMainId)
self.reconnectMainId = nil
end
self.mainReconnectWaitTime = 0
if self.reconnectMainFlag then
self.reconnectMainFlag = false
end
if self.activeReconnectMainFlag then
self.activeReconnectMainFlag = false
UIManager:hideWaitNet()
if UIManager:getWaitNetCount() == 0 then
UIManager:hideMessageBoxByTag(GConst.GAME_OBJECT_TYPE.MESSAGEBOX_RECONNECT)
end
end
local durationTime = 0
if self.disconnectTime then
durationTime = Time:getServerTime() - self.disconnectTime
self.disconnectTime = nil
end
BIReport:postNetWorkOpt(BIReport.NETWORK_OPT_TYPE.RECONNECT, UIManager:getTopUIIndex(), nil, durationTime)
else
self.chatReconnectWaitTime = 1
if self.reconnectChatId then
SchedulerManager:unscheduleGlobal(self.reconnectChatId)
self.reconnectChatId = nil
end
if self.joinChatId then
SchedulerManager:unscheduleGlobal(self.joinChatId)
self.joinChatId = nil
end
if DataManager.ChatData then
DataManager.ChatData:onConnect()
end
self:joinChatChannel()
end
end)
CS.BF.BFMain.Instance.NetMgr:SetLuaOnDecodePbCallback(function(name, group, recvId, data)
local msgName = ProtoMsgDispatch:getReqMsgNameByMsgId(group)
if msgName == nil then
return
end
Logger.logHighlight("[NetManager]===onReceive===name:%s, msgId:%s", msgName, group)
-- 这里保证即使协议有问题解不出来也不要卡住
local ok, pbData = pcall(function()
local fullMsgName = ProtoMsgDispatch:getMsgFullNameByMsgName(msgName)
return pb.decode(fullMsgName, data)
end)
if ok and pbData then
pbData.status = not pbData.err_code and 0 or ProtoMsgDispatch:getErrCodeEnum(pbData.err_code)
if pbData.status ~= 0 then
local lastLoginInfo = LocalData:getLastLoginInfo()
BIReport:postPbAuthfailed(ProtoMsgType.FromMsgEnum.AuthReq, lastLoginInfo, self.authFailToLogin)
if self.autoReAuthSid then
SchedulerManager:unscheduleGlobal(self.autoReAuthSid)
self.autoReAuthSid = nil
end
if self.authFailToLogin then
self:closeAll()
self:clearTagAuthFailToLogin()
return
end
if msgName == "ReconnectRsp" then -- Reconnect失败就直接回登录界面
self:closeAll()
else
self:closeAndClear()
local accountInfo = LocalData:getAccountInfo()
local loginType
local lastLoginType
if accountInfo.google_id and accountInfo.google_id ~= "" then
loginType = SDKManager.BF_LOGIN_TYPE.GOOGLE
lastLoginType = NetManager.LOGIN_TYPE.GOOGLE
elseif accountInfo.apple_id and accountInfo.apple_id ~= "" then
loginType = SDKManager.BF_LOGIN_TYPE.APPLE
lastLoginType = NetManager.LOGIN_TYPE.APPLE
end
if loginType then
SDKManager:login(function(params)
if not params.token then
return
end
LocalData:setLastLoginInfo(lastLoginType, params.id, params.token)
ModuleManager.LoginManager:saveAuthArgs(false)
ModuleManager.LoginManager:initSocket()
end, loginType)
else
if not self.autoReAuth then
self.autoReAuth = true
self.autoReAuthSid = self:performWithDelayGlobal(function()
ModuleManager.LoginManager:initSocket()
end, 0.5)
else
LocalData:setLastLoginInfo()
ModuleManager.LoginManager:saveAuthArgs(false)
local params = {
content = I18N:getGlobalText(I18N.GlobalConst.DISCONNECT_RELOGIN),
okText = I18N:getGlobalText(I18N.GlobalConst.BTN_TEXT_OK),
noShowClose = true,
okFunc = function()
self.autoReAuth = false
ModuleManager.LoginManager:initSocket()
end,
boxType = GConst.MESSAGE_BOX_TYPE.MB_OK,
top = true,
}
GFunc.showMessageBox(params)
end
end
end
else
if self.autoReAuthSid then
SchedulerManager:unscheduleGlobal(self.autoReAuthSid)
self.autoReAuthSid = nil
end
self.autoReAuth = false
self:clearTagAuthFailToLogin()
ModuleManager.LoginManager:saveAuthArgs(true)
UIManager:hideWaitNet(true)
if pbData.id then -- 重连也会走到这儿但是没有token等信息
LocalData:setLastLoginInfo(NetManager.LOGIN_TYPE.TOKEN, pbData.id, pbData.token)
LocalData:setAccountInfo(pbData)
BIReport:updateAccountId(pbData.id)
end
pbData.send_id = pbData.send_id or 0
pbData.err_code = nil
CS.BF.BFMain.Instance.NetMgr.decodePbStr = json.encode(pbData)
CS.BF.BFMain.Instance.NetMgr.rspGroup = group
CS.BF.BFMain.Instance.NetMgr.decodeFinish = true
end
end
end)
CS.BF.BFMain.Instance.NetMgr:SetLuaAuthCallback(function(isSuccess)
if not isSuccess then
local params = {
content = I18N:getGlobalText(I18N.GlobalConst.DISCONNECT_RELOGIN),
okText = I18N:getGlobalText(I18N.GlobalConst.BTN_TEXT_OK),
noShowClose = true,
okFunc = function()
ModuleManager.LoginManager:goToLoginScene()
end,
boxType = GConst.MESSAGE_BOX_TYPE.MB_OK,
top = true,
}
GFunc.showMessageBox(params)
end
end)
local configuration = CS.BF.NetConnectConfiguration(CS.BF.NetServiceType.TCPService, tostring(socketName))
configuration:EnableMessageType(CS.BF.NetIncomingMessageType.DebugMessage)
configuration:EnableMessageType(CS.BF.NetIncomingMessageType.WarningMessage)
configuration:EnableMessageType(CS.BF.NetIncomingMessageType.ErrorMessage)
if socketName == NetManager.MAIN_SOCKET_NAME then
configuration.EnableSilenceReconnect = false -- game连接不用自动重连
configuration.ReconnectTimeoutTime = GConst.WAIT_NET_RSP_TIME -- 每次重连超时时间
configuration.AlreadySendMessageCacheCount = 3
else
-- configuration.ReconnectTimeoutTime = 8 -- 每次重连超时时间
-- configuration.ReconnectBaseInterval = 1 -- 每次重连间隔时间
-- configuration.AutoReconnectCount = 5 -- 重连次数
-- 自动重连可能有bug先手动重连
configuration.EnableSilenceReconnect = false -- chat连接不用自动重连
configuration.ReconnectTimeoutTime = MAX_CHAT_WAIT_TIME -- 每次重连超时时间
configuration.AlreadySendMessageCacheCount = 3
end
CS.BF.BFMain.Instance.NetMgr:ConnectWithConfiguration(socketName, configuration, domain, tonumber(port))
end
function NetManager:isConnected(socketName)
if not self.initSucc then
return false
end
return CS.BF.BFMain.Instance.NetMgr:IsConnected(socketName)
end
function NetManager:isAvailable(socketName)
if not self.initSucc then
return false
end
return CS.BF.BFMain.Instance.NetMgr:IsAvailable(socketName)
end
function NetManager:isDisconnected(socketName)
if not self.initSucc then
return true
end
return CS.BF.BFMain.Instance.NetMgr:IsDisconnected(socketName)
end
function NetManager:getConnectIP(socketName)
if not self.initSucc then
return ""
end
return CS.BF.BFMain.Instance.NetMgr:GetConnectIP(socketName)
end
function NetManager:_sendBytes(clientName, bytes, group, cmd)
self.isSending = true
CS.BF.BFMain.Instance.NetMgr:Send(clientName, group, cmd, bytes)
end
---- 后台发送协议,不锁定界面
function NetManager:sendOnBackground(msgName, params, callback, socketName)
self:_send(msgName, params, callback, socketName, false)
end
---- 后台发送协议,不锁定界面,且不会有回复
function NetManager:sendOnBackgroundWithoutRsp(msgName, params, socketName)
self:_send(msgName, params, nil, socketName, false, true)
end
function NetManager:saveAuthArgs(authArgs)
local msgFullName = ProtoMsgDispatch:getMsgFullNameByMsgName(ProtoMsgType.FromMsgEnum.AuthReq)
local bytes = pb.encode(msgFullName, authArgs)
CS.BF.BFMain.Instance.NetMgr.authReqData = bytes
end
function NetManager:saveChatAuthArgs(token)
local msgFullName = ProtoMsgDispatch:getMsgFullNameByMsgName(ProtoMsgType.FromMsgEnum.ChatAuthReq)
local args = {
id = DataManager.PlayerData:getUid(),
token = token
}
CS.BF.BFMain.Instance.NetMgr.ChatAuthReqData = pb.encode(msgFullName, args)
end
function NetManager:send(binder, msgName, params, responseData, callback, lockGame, noRsp, getType)
if responseData.rewards then
responseData.rewards = GFunc.formatRewardsToServerStruct(responseData.rewards)
end
if responseData.costs then
responseData.costs = GFunc.formatRewardsToServerStruct(responseData.costs)
end
responseData.err_code = GConst.ERROR_STR.SUCCESS
self:_send(binder, msgName, params, responseData, callback, lockGame, noRsp, getType)
end
function NetManager:sendTillBeforeOver(binder, msgName, params, responseData, callback, lockGame, noRsp, getType)
if responseData.rewards then
responseData.rewards = GFunc.formatRewardsToServerStruct(responseData.rewards)
end
if responseData.costs then
responseData.costs = GFunc.formatRewardsToServerStruct(responseData.costs)
end
responseData.err_code = GConst.ERROR_STR.SUCCESS
self:_send(binder, msgName, params, responseData, callback, lockGame, noRsp, getType, true)
end
function NetManager:_send(binder, msgName, params, responseData, callback, lockGame, noRsp, getType, beforeOver)
local socketName = NetManager.MAIN_SOCKET_NAME
if self:isDisconnected(socketName) then
if socketName == NetManager.MAIN_SOCKET_NAME then
if UIManager:getWaitNetCount() > 0 then
self:disconnect(socketName)
else
if self.reconnectMainId then
SchedulerManager:unscheduleGlobal(self.reconnectMainId)
self.reconnectMainId = nil
end
self:reconnectMain()
end
else
self:disconnect(socketName)
end
else
if beforeOver then
UIManager:showWaitNet()
self.tillBeforeOverCount = self.tillBeforeOverCount + 1
end
local pipedMsgName, pipedParams = self:pipedMessage(msgName, params)
table.insert(self.sendQueue, {
binder = binder,
originMsgName = msgName,
msgName = pipedMsgName,
params = pipedParams,
responseData = responseData,
socketName = socketName,
callback = callback,
lockGame = lockGame,
noRsp = noRsp,
getType = getType,
beforeOver = beforeOver,
})
if not self:isNotSave(msgName) then
self:saveSendQueue()
end
self:trySend()
end
end
function NetManager:trySend()
local binder
local originMsgName
local curMsgName
local curParams
local responseData
local getType
local curSocketName
local curCallback
local curLockGame
local noRsp
local beforeOver
if not self.isSending and self.sendQueue[1] then -- 没有正在发送的消息,并且有发送队列, 则继续发送
local cache = self.sendQueue[1]
binder = cache.binder
originMsgName = cache.originMsgName
curMsgName = cache.msgName
curParams = GFunc.getTable(cache.params)
responseData = cache.responseData
getType = cache.getType
curSocketName = cache.socketName
curCallback = cache.callback
curLockGame = cache.lockGame
noRsp = cache.noRsp
beforeOver = cache.beforeOver
end
if curMsgName then
if EDITOR_MODE then
local subName = curMsgName
local reqData
if curMsgName == ProtoMsgType.FromMsgEnum.PipedReq then
reqData = curParams.data
Logger.logHighlight("[NetManager]===onSend===name:%s params:%s", ProtoMsgDispatch:getReqMsgNameByMsgId(curParams.msg_id), json.encode(reqData))
else
reqData = curParams
Logger.logHighlight("[NetManager]===onSend===name:%s params:%s", subName, json.encode(reqData))
end
end
local msgFullName = ProtoMsgDispatch:getMsgFullNameByMsgName(curMsgName)
if curMsgName == ProtoMsgType.FromMsgEnum.PipedReq then
local msgName = ProtoMsgDispatch:getReqMsgNameByMsgId(curParams.msg_id)
local fullMsgName = ProtoMsgDispatch:getMsgFullNameByMsgName(msgName)
if curParams.data and type(curParams.data) == "table" then
curParams.data = pb.encode(fullMsgName, curParams.data)
end
end
local bytes = pb.encode(msgFullName, curParams)
if bytes then
if curLockGame then
UIManager:showWaitNet()
end
local msgId = ProtoMsgDispatch:getMsgIdByMsgName(curMsgName)
self:_sendBytes(curSocketName, bytes, msgId, 0)
if noRsp then
return
end
local msg = ProtoMsgDispatch:getRspMsgByMsgName(originMsgName)
if not self.receiveCallbacks[msg] then
self.receiveCallbacks[msg] = {}
end
local receiveCallback = self:getReceiveCallback()
receiveCallback.binder = binder
receiveCallback.lockGame = curLockGame
receiveCallback.callback = curCallback
receiveCallback.responseData = responseData
receiveCallback.getType = getType
receiveCallback.beforeOver = beforeOver
table.insert(self.receiveCallbacks[msg], receiveCallback)
else
Logger.logError("[NetManager]send data error %s", curMsgName)
end
end
end
-- 静默重连
function NetManager:silentReconnectMain()
self.reconnectMainFlag = true
self:setReconnectData()
CS.BF.BFMain.Instance.NetMgr:Reconnect(NetManager.MAIN_SOCKET_NAME)
end
-- 主动重连
function NetManager:reconnectMain()
UIManager:showWaitNet(true) -- 强制重新计时
if self.activeReconnectMainFlag then -- 说明之前已经在主动重连中,为了保证引用计数正确,这里减一
UIManager:hideWaitNet()
else
self.activeReconnectMainFlag = true
end
self.reconnectMainFlag = true
self:setReconnectData()
CS.BF.BFMain.Instance.NetMgr:Reconnect(NetManager.MAIN_SOCKET_NAME)
end
function NetManager:getReceiveCallback()
if #self.receiveCallbackPool > 0 then
return table.remove(self.receiveCallbackPool)
end
return {}
end
function NetManager:recycleReceiveCallback(receiveCallback)
receiveCallback.callback = nil
receiveCallback.lockGame = true
table.insert(self.receiveCallbackPool, receiveCallback)
end
function NetManager:disconnectAll()
if self.alreadyConnected[NetManager.MAIN_SOCKET_NAME] then
self:showReconnectMain()
else
self:closeAll()
end
end
function NetManager:disconnectAndReconnect()
if self.alreadyConnected[NetManager.MAIN_SOCKET_NAME] then
if not DataManager:getLoginSuccess() then -- 没登陆成功的直接重新走auth->login
ModuleManager.LoginManager:reloginOnReconnectRefuse()
return
end
if self.reconnectMainId then
return
end
if self.mainReconnectWaitTime > MAX_MAIN_WAIT_TIME then
self.mainReconnectWaitTime = MAX_MAIN_WAIT_TIME
end
self.reconnectMainId = self:performWithDelayGlobal(function ()
self.reconnectMainId = nil
self:silentReconnectMain()
end, self.mainReconnectWaitTime)
self.mainReconnectWaitTime = self.mainReconnectWaitTime + 1
else
self:closeAll()
end
end
function NetManager:showReconnectMain()
if self.reconnectMainId then
SchedulerManager:unscheduleGlobal(self.reconnectMainId)
self.reconnectMainId = nil
end
if UIManager:isDisconnectMsgBoxVisible() then
return
end
local params = {
content = I18N:getGlobalText(I18N.GlobalConst.RECONNECT),
okText = I18N:getGlobalText(I18N.GlobalConst.BTN_TEXT_OK),
cancelText = I18N:getGlobalText(I18N.GlobalConst.RELOGIN),
noShowClose = true,
okFunc = function()
self:reconnectMain()
end,
cancelFunc = function()
ModuleManager.LoginManager:goToLoginScene()
end,
boxType = GConst.MESSAGE_BOX_TYPE.MB_OK_CANCEL,
tag = GConst.GAME_OBJECT_TYPE.MESSAGEBOX_RECONNECT,
top = true,
}
GFunc.showMessageBox(params)
end
function NetManager:disconnect(socketName)
if self.isClosedMap[socketName] then
return
end
if socketName == NetManager.CHAT_SOCKET_NAME then --暂时没有维护
self.isClosedMap[socketName] = true
CS.BF.BFMain.Instance.NetMgr:Close(socketName)
if self.reconnectChatId then
return
end
if DataManager.ChatData then
DataManager.ChatData:onDisconnect()
end
self.reconnectChatId = self:performWithDelayGlobal(function ()
self.reconnectChatId = nil
if not self:isConnected(NetManager.CHAT_SOCKET_NAME) then
ModuleManager.LoginManager:connectByChannel(nil, NetManager.CHAT_SOCKET_NAME)
end
end, self.chatReconnectWaitTime)
self.chatReconnectWaitTime = self.chatReconnectWaitTime*2
if self.chatReconnectWaitTime > MAX_CHAT_WAIT_TIME then
self.chatReconnectWaitTime = MAX_CHAT_WAIT_TIME
end
else
if self.alreadyConnected[socketName] then -- 如果是成功连接过
if not DataManager:getLoginSuccess() then -- 没登陆成功的直接重新走auth->login
ModuleManager.LoginManager:reloginOnReconnectRefuse()
return
end
if UIManager:getWaitNetCount() > 0 then -- 当前在等待服务器回消息
if not self.activeReconnectMainFlag then
self:showReconnectMain()
end
else -- 否则就悄咪咪的重连
if self.mainReconnectWaitTime > MAX_MAIN_WAIT_TIME then
self.mainReconnectWaitTime = MAX_MAIN_WAIT_TIME
end
if self.reconnectMainId then
return
end
self.reconnectMainId = self:performWithDelayGlobal(function ()
self.reconnectMainId = nil
self:silentReconnectMain()
end, self.mainReconnectWaitTime)
self.mainReconnectWaitTime = self.mainReconnectWaitTime + 1
end
else -- 从来没有连上过
self:closeAll()
end
end
end
function NetManager:onDisconnect(socketName)
self:disconnect(socketName)
end
function NetManager:performWithDelayGlobal(func, delay)
local sid = SchedulerManager:performWithDelayGlobal(func, delay)
return sid
end
function NetManager:scheduleGlobal(func, delay)
local sid = SchedulerManager:scheduleGlobal(func, delay)
return sid
end
function NetManager:closeAll(errorType)
if self.isClosedMap[NetManager.MAIN_SOCKET_NAME] then
return
end
self:closeAndClear()
UIManager:showDisconnect(errorType)
end
function NetManager:onReceive(msgId, data)
self.isSending = false
--Logger.logHighlight("MSGID:"..msgId)
local msgName = ProtoMsgDispatch:getReqMsgNameByMsgId(msgId)
if msgName == nil then
return
end
-- 这里保证即使协议有问题解不出来也不要卡住
local ok, pbData = pcall(function()
local fullMsgName = ProtoMsgDispatch:getMsgFullNameByMsgName(msgName)
return pb.decode(fullMsgName, data)
end)
local msg = ProtoMsgDispatch:getRspMsgByMsgName(msgName)
if ok and pbData then
if not pbData.err_code then
pbData.status = 0
else
pbData.status = ProtoMsgDispatch:getErrCodeEnum(pbData.err_code)
end
if EDITOR_MODE then
Logger.logHighlight("[NetManager]===onReceive===name:%s, msgId:%s, data:%s", msgName, msgId, json.encode(pbData))
end
self:dispatch(msgName, pbData)
else
if EDITOR_MODE then
Logger.logHighlight("[NetManager]===onReceive failed===name:%s, msgId:%s", msgName, msgId)
end
end
local sendInfo
local sendMsgName
if self.sendQueue[1]then
sendMsgName = self.sendQueue[1].msgName
if sendMsgName == ProtoMsgType.FromMsgEnum.PipedReq then
sendMsgName = ProtoMsgDispatch:getReqMsgNameByMsgId(self.sendQueue[1].params.msg_id)
end
if ProtoMsgDispatch:getRspMsgByMsgName(sendMsgName) == msgName then
sendInfo = table.remove(self.sendQueue, 1)
self:saveSendQueue()
end
end
if not ok or not pbData then
local reqDataStr = GConst.EMPTY_STRING
if sendInfo then
if sendInfo.msgName == ProtoMsgType.FromMsgEnum.PipedReq then
reqDataStr = json.encode(sendInfo.params.data)
else
reqDataStr = json.encode(sendInfo.params)
end
end
BIReport:postPbDecodefailed(sendMsgName, reqDataStr)
elseif pbData.err_code ~= GConst.ERROR_STR.SUCCESS then
local reqDataStr = GConst.EMPTY_STRING
if sendInfo then
if sendInfo.msgName == ProtoMsgType.FromMsgEnum.PipedReq then
reqDataStr = json.encode(sendInfo.params.data)
else
reqDataStr = json.encode(sendInfo.params)
end
end
BIReport:postNetError(sendMsgName, pbData.err_code, reqDataStr, pbData)
end
local callbacks = self.receiveCallbacks[msg]
if callbacks and #callbacks > 0 then
local receiveCallback = table.remove(callbacks, 1)
local lockGame = true
local receiveFunc = nil
local responseData = nil
if receiveCallback then
lockGame = receiveCallback.lockGame
receiveFunc = receiveCallback.callback
responseData = receiveCallback.responseData
if pbData.err_code == GConst.ERROR_STR.SUCCESS and pbData.rewards then
local getType = receiveCallback.getType
if sendMsgName == "ActPayReq" then
getType = PayManager:getItemGetType(pbData.act_type, pbData.id)
elseif sendMsgName == "ActPaidResultReq" then -- 支付上报统一处理
if pbData.gift then
for _, gift in ipairs(pbData.gift) do
getType = PayManager:getItemGetType(gift.act_type, gift.id)
break
end
end
elseif sendMsgName == "AppStorePaidReq" then -- ios支付上报统一处理
if pbData.gift then
for _, gift in ipairs(pbData.gift) do
getType = PayManager:getItemGetType(gift.act_type, gift.id)
break
end
end
end
if EDITOR_MODE and not getType then
Logger.logFatal("sendMessage server have rewards but not getType, check it! manager = ", receiveCallback.binder.__cname)
end
GFunc.addRewards(pbData.rewards, getType)
end
if pbData.err_code == GConst.ERROR_STR.SUCCESS and pbData.costs and not self:getNotAddCostsRsp(msgName) then
local getType = receiveCallback.getType
if sendMsgName == "ActPayReq" then
getType = PayManager:getItemGetType(pbData.mall_type, pbData.id)
elseif sendMsgName == "ActPaidResultReq" then -- 支付上报统一处理
if pbData.gift then
for _, gift in ipairs(pbData.gift) do
getType = PayManager:getItemGetType(gift.mall_type, gift.id)
break
end
end
end
if EDITOR_MODE and not getType then
Logger.logFatal("sendMessage server have costs but not getType, check it! manager = ", receiveCallback.binder.__cname)
end
GFunc.addCosts(pbData.costs, getType)
end
if EDITOR_MODE and not self:getNotCheckResponse(ProtoMsgDispatch:getReqMsgByMsgName(msgName)) then -- 检查responseData
local fullMsgName = ProtoMsgDispatch:getMsgFullNameByMsgName(msgName)
local serverResult = pb.decode(fullMsgName, data)
self:checkCoin(responseData, serverResult)
if not GFunc.checkTableValueSame(responseData, serverResult, true) then
Logger.logWarningBox(msgName .. " : responseData not equate, please check it!")
Logger.logHighlight("------responseData not equate-------------")
Logger.printTable(responseData)
Logger.printTable(serverResult)
end
end
if receiveCallback.beforeOver then
UIManager:hideWaitNet()
self.tillBeforeOverCount = self.tillBeforeOverCount - 1
if self.tillBeforeOverCount < 0 then
self.tillBeforeOverCount = 0
end
end
self:recycleReceiveCallback(receiveCallback)
if lockGame then
UIManager:hideWaitNet()
end
if ok and pbData and receiveFunc then
if sendInfo then
if sendInfo.msgName == ProtoMsgType.FromMsgEnum.PipedReq then
pbData.reqData = sendInfo.params.data
else
pbData.reqData = sendInfo.params
end
end
receiveFunc(receiveCallback.binder, pbData)
end
end
end
if sendInfo then
self:trySend()
end
end
function NetManager:onError(socketName, errorType, errorMsg)
self.isSending = false
if socketName == NetManager.MAIN_SOCKET_NAME then
Logger.logHighlight("game net error:errorType = %d, errorMsg = %s", errorType, errorMsg)
if errorType == NetErrorCode.ConnectFailed or
errorType == NetErrorCode.ExceptionError or
errorType == NetErrorCode.ReceiveBufferError or
errorType == NetErrorCode.BeginSendError or
errorType == NetErrorCode.PeerDisconnect or
errorType == NetErrorCode.DataParseError then
self:disconnect(socketName)
elseif errorType == NetErrorCode.ServerRefuseReconnect then -- 服务器拒绝客户端的重连请求,需要关闭连接,重新登录
ModuleManager.LoginManager:reloginOnReconnectRefuse()
elseif errorType == NetErrorCode.ServerKickNtfClient or
errorType == NetErrorCode.OtherDeviceLogin then
self:closeAll(errorType)
elseif errorType == NetErrorCode.DNSParseDomainNameError then
self:closeAll()
else -- 未定义的error
self:disconnectAndReconnect()
end
if not self.disconnectTime then
self.disconnectTime = Time:getServerTime()
BIReport:postNetWorkOpt(BIReport.NETWORK_OPT_TYPE.DISCONNECT, UIManager:getTopUIIndex(), errorType)
end
elseif socketName == NetManager.CHAT_SOCKET_NAME then
Logger.logHighlight("chat net error:errorType = %d, errorMsg = %s", errorType, errorMsg)
self:disconnect(socketName)
end
end
function NetManager:setReconnectData()
local msgFullName = ProtoMsgDispatch:getMsgFullNameByMsgName(ProtoMsgType.FromMsgEnum.ReconnectReq)
CS.BF.BFMain.Instance.NetMgr.loginReqData = pb.encode(msgFullName, { recv_id = self.recvId })
end
function NetManager:dispatch(msgName, data)
if self.msgCallbacks[msgName] then
for module, callback in pairs(self.msgCallbacks[msgName]) do
callback(module, data)
end
end
end
function NetManager:getKickOutReasonEnum(enum)
return ProtoMsgDispatch:getKickOutReasonEnum(enum)
end
function NetManager:joinChatChannel()
-- if self.joinChatId then
-- SchedulerManager:unscheduleGlobal(self.joinChatId)
-- self.joinChatId = nil
-- end
-- if DataManager.ChatData:getIsJoinWorldRoom() then
-- return
-- end
-- local wordChannelId = DataManager.ChatData:getChatWorld():getLocalChatWorldChannleId()
-- local args = {
-- id = wordChannelId,
-- adjust = true -- 登录时第一次进入房间必须能接受调整,手动切房间的时候为false
-- }
-- self:send(ProtoMsgType.FromMsgEnum.JoinWorldRoomReq, args, function(data)
-- if data.status == 0 then
-- DataManager.ChatData:initChat(data)
-- else
-- self.joinChatId = self:performWithDelayGlobal(function ()
-- self.joinChatId = nil
-- self:joinChatChannel()
-- end, JOIN_CHAT_INTERVAL)
-- end
-- end, NetManager.CHAT_SOCKET_NAME, true)
end
function NetManager:registerMsgCallback(msgName, module, callback)
if not self.msgCallbacks[msgName] then
self.msgCallbacks[msgName] = {}
end
self.msgCallbacks[msgName][module] = callback
end
if NOT_PUBLISH then
NetManager._registerMsgCallback = NetManager.registerMsgCallback
function NetManager:registerMsgCallback(msgName, module, callback)
if debug.getinfo(2, "f").func ~= ServerPushManager.addServerPushListener then
Logger.logFatal("this method only called by ServerPushManager.addServerPushListener")
end
self:_registerMsgCallback(msgName, module, callback)
end
end
function NetManager:unRegisterMsgCallback(msgName, module)
if self.msgCallbacks[msgName] then
self.msgCallbacks[msgName][module] = nil
end
end
function NetManager:clearMsgCallbacks()
self.msgCallbacks = {}
self.receiveCallbacks = {}
end
function NetManager:closeAndClear()
if not self.initSucc then
return
end
if self.tillBeforeOverSid then
SchedulerManager:unscheduleGlobal(self.tillBeforeOverSid)
self.tillBeforeOverSid = nil
end
if self.reconnectMainId then
SchedulerManager:unscheduleGlobal(self.reconnectMainId)
self.reconnectMainId = nil
end
if self.reconnectChatId then
SchedulerManager:unscheduleGlobal(self.reconnectChatId)
self.reconnectChatId = nil
end
if self.joinChatId then
SchedulerManager:unscheduleGlobal(self.joinChatId)
self.joinChatId = nil
end
if self.autoReAuthSid then
SchedulerManager:unscheduleGlobal(self.autoReAuthSid)
self.autoReAuthSid = nil
end
self.isSending = false
self.sendQueue = {}
self.tillBeforeOverCount = 0
self.msgId = 0
self.activeReconnectMainFlag = false
self.reconnectMainFlag = false
CS.BF.BFMain.Instance.NetMgr:RemoveAllLuaCallback()
local mainSocketName = NetManager.MAIN_SOCKET_NAME
local chatSocketName = NetManager.CHAT_SOCKET_NAME
self.isClosedMap[mainSocketName] = true
self.isClosedMap[chatSocketName] = true
self.alreadyConnected[mainSocketName] = false
self.alreadyConnected[chatSocketName] = false
CS.BF.BFMain.Instance.NetMgr:Close(mainSocketName)
-- CS.BF.BFMain.Instance.NetMgr:Close(chatSocketName)
self:clearMsgCallbacks()
UIManager:hideWaitNet(true)
end
function NetManager:saveSendQueue()
local list = {}
for _, info in ipairs(self.sendQueue) do
if not self:isNotSave(info.msgName) then
table.insert(list, {
msgName = info.msgName,
params = info.params,
socketName = info.socketName,
})
end
end
if EDITOR_MODE and #list > 0 then
local printList = {}
for k, v in ipairs(list) do
local msgName = v.msgName
local params = v.params
if msgName == ProtoMsgType.FromMsgEnum.PipedReq then
msgName = ProtoMsgDispatch:getReqMsgNameByMsgId(params.msg_id)
params = params.data
end
table.insert(printList, {
msgName = msgName,
params = params,
socketName = v.socketName,
})
end
Logger.logHighlight("[NetManager]剩余消息队列缓存:%s", json.encode(printList))
end
LocalData:saveSendQueue(list)
end
function NetManager:isNotSave(msgName)
if msgName == ProtoMsgType.FromMsgEnum.LoginReq or
msgName == ProtoMsgType.FromMsgEnum.SyncReq or
msgName == ProtoMsgType.FromMsgEnum.IdleRewardReq or
msgName == ProtoMsgType.FromMsgEnum.IdleExtraRewardReq or
msgName == ProtoMsgType.FromMsgEnum.MailCycleReq or
msgName == ProtoMsgType.FromMsgEnum.GMReq then
return true
end
return false
end
function NetManager:getNotCheckResponse(msgName)
return true
end
function NetManager:getNotAddCostsRsp(msgName)
if msgName == ProtoMsgType.FromMsgEnum.ChapterTrainRsp then
return true
end
return false
end
function NetManager:pipedMessage(msgName, params)
return msgName, params -- 屏蔽PipedReq
-- if msgName == ProtoMsgType.FromMsgEnum.LoginReq or
-- msgName == ProtoMsgType.FromMsgEnum.SyncReq or
-- msgName == ProtoMsgType.FromMsgEnum.IdleRewardReq or
-- msgName == ProtoMsgType.FromMsgEnum.IdleExtraRewardReq or
-- msgName == ProtoMsgType.FromMsgEnum.MailCycleReq or
-- msgName == ProtoMsgType.FromMsgEnum.GMReq then
-- return msgName, params
-- end
-- local msgId = ProtoMsgDispatch:getMsgIdByMsgName(msgName)
-- self.msgId = self.msgId + 1
-- local pipedStruct = {
-- id = self.msgId,
-- ts = Time:getServerTime() * 1000,
-- msg_id = msgId,
-- data = params,
-- }
-- return ProtoMsgType.FromMsgEnum.PipedReq, pipedStruct
end
if EDITOR_MODE then
function NetManager:_checkDebugFuncMap()
if self._debugFuncMap == nil then
self._debugFuncMap = {
[BaseModule.sendMessage] = true,
[BaseModule.sendMessageTillBeforeOver] = true,
}
end
end
NetManager._releaseSend = NetManager.send
function NetManager:send(obj, msgName, params, responseData, callback, lockGame, noRsp, getType)
-- 参数检查
if (responseData.rewards or responseData.costs) and not getType and msgName ~= ProtoMsgType.FromMsgEnum.GMReq then
Logger.logFatal("sendMessage have rewards or have costs but not getType, check it! manager = ", self.__cname)
return
end
if not params then
Logger.logFatal("NetManager send params is nil %s", msgName)
end
if not responseData then
Logger.logFatal("NetManager send responseData is nil %s", msgName)
end
local msgFullName = ProtoMsgDispatch:getMsgFullNameByMsgName(msgName)
local bytes = pb.encode(msgFullName, params)
if not bytes then
Logger.logFatal("NetManager send params error %s", msgName)
return
end
if not self:getNotCheckResponse(msgName) then
local fullMsgName = ProtoMsgDispatch:getMsgFullNameByMsgName(ProtoMsgDispatch:getRspMsgByMsgName(msgName))
for name, number, type in pb.fields(fullMsgName) do
if name ~= "err_code" and responseData[name] == nil then
Logger.logFatal("NetManager send responseData error %s not have %s", msgName, name)
return
end
end
end
-- end 参数检查
self:_checkDebugFuncMap()
local currFunc = debug.getinfo(2, "f").func
if obj ~= NetManager and self._debugFuncMap[currFunc] == nil then
Logger.logFatal("you can not call NetManager:send directly")
end
local findCallback = false
if obj ~= NetManager and obj.__cname ~= "PayManager" then
for _, fieldValue in pairs(obj.class) do
if fieldValue == callback then
findCallback = true
end
end
else
findCallback = true
end
if not findCallback then
Logger.logFatal("[NetManager]callback of NetManager:send is not %s function", obj.__cname)
end
self:_releaseSend(obj, msgName, params, responseData, callback, lockGame, noRsp, getType)
end
NetManager._releaseSendTillBeforeOver = NetManager.sendTillBeforeOver
function NetManager:sendTillBeforeOver(obj, msgName, params, responseData, callback, ...)
self:_checkDebugFuncMap()
local currFunc = debug.getinfo(2, "f").func
if obj ~= NetManager and self._debugFuncMap[currFunc] == nil then
Logger.logFatal("[NetManager]you can not call NetManager:send directly")
end
self:_releaseSendTillBeforeOver(obj, msgName, params, responseData, callback, ...)
end
end
function NetManager:checkCoin(responseData, serverResponseData)
end
function NetManager:tagAuthFailToLogin()
self.authFailToLogin = true
end
function NetManager:clearTagAuthFailToLogin()
self.authFailToLogin = false
end
return NetManager