--[[
|
|
功能: 协议处理类的基类
|
|
|
|
格式化字符串说明:
|
|
i: 32位无符号整数
|
|
I: 32位有符号整数
|
|
h: 16位无符号整数
|
|
H: 16位有符号整数
|
|
c: 8位无符号整数
|
|
C: 8位有符号整数
|
|
l: 64位无符号整数
|
|
L: 64位有符号整数
|
|
s: 字符串
|
|
|
|
示例:
|
|
self:SendFmtToGame(10003, "ihs", val_int, val_short, val_string)
|
|
表示发送一条10003协议, 协议内容由
|
|
一个32位有符号整数,
|
|
一个16位有符号整数,
|
|
一个字符串,共三个字段组成
|
|
|
|
val_int, val_short, val_str = self:ReadFmt("ihs")
|
|
表示从当前协议缓冲区中读取一个三个字段组成的协议,
|
|
返回值直接赋值给val_int, val_short, val_str
|
|
]]
|
|
UserMsgAdapter = UserMsgAdapter or BaseClass()
|
|
local UserMsgAdapter = UserMsgAdapter
|
|
local networkMgr = networkMgr
|
|
local Time = Time
|
|
local Status = Status
|
|
local print = print
|
|
local rawget = rawget
|
|
local unpack = unpack
|
|
local tostring = tostring
|
|
local tonumber = tonumber
|
|
local string_sub = string.sub
|
|
local table_insert = table.insert
|
|
local string_len = string.len
|
|
local ByteBuffer = ByteBuffer
|
|
local table_concat = table.concat
|
|
local logWarn = logWarn
|
|
local Util = Util
|
|
|
|
local can_print_cmd = RuntimePlatform and ApplicationPlatform ~= RuntimePlatform.Android and ApplicationPlatform ~= RuntimePlatform.IPhonePlayer
|
|
UserMsgAdapter.SPLIT_CHAT = '糴' --协议传输分隔符
|
|
function UserMsgAdapter:__init()
|
|
UserMsgAdapter.Instance = self
|
|
UserMsgAdapter.send_byteBuff = false
|
|
UserMsgAdapter.receive_byteBuff = false
|
|
UserMsgAdapter.register_list = {}
|
|
UserMsgAdapter.new_fmt_mode = false --新的协议解释类型
|
|
self.is_game_connected = false --是否已经连接服务器
|
|
self.reconnect_times = 0 --重连次数
|
|
|
|
UserMsgAdapter.result_list = {}
|
|
|
|
self.cmd_callback_queue = Array.New() --协议callback队列
|
|
self.curr_frame_receive_count = 0
|
|
|
|
UserMsgAdapter.write_cmd = 0
|
|
|
|
-- local function onUpdate()
|
|
-- self:Update()
|
|
-- end
|
|
-- TimerQuest.AddPeriodQuest(GlobalTimerQuest, onUpdate, 0.2, -1)
|
|
LateUpdateBeat:Add(UserMsgAdapter.Update,self)
|
|
UserMsgAdapter.initEvents(self)
|
|
end
|
|
function UserMsgAdapter:getInstance()
|
|
if UserMsgAdapter.Instance == nil then
|
|
UserMsgAdapter.Instance = UserMsgAdapter.New()
|
|
end
|
|
return UserMsgAdapter.Instance
|
|
end
|
|
|
|
|
|
function UserMsgAdapter:IsGameConnected()
|
|
return self.is_game_connected
|
|
end
|
|
|
|
function UserMsgAdapter:IsWaitPlayerHandle()
|
|
return self.wait_player_handle
|
|
end
|
|
|
|
function UserMsgAdapter:initEvents()
|
|
--当连接建立时--
|
|
local function OnConnect()
|
|
logWarn("Game Server connected!!")
|
|
self.is_game_connected = true
|
|
EventSystem.Fire(GlobalEventSystem,EventName.GAME_CONNECT)
|
|
end
|
|
|
|
--异常断线--
|
|
local function OnException()
|
|
self.is_game_connected = false
|
|
-- networkMgr:SendConnect()
|
|
--判断在游戏中进行静默重连, 10004进入游戏之后,is_back_from_game为false
|
|
if LoginModel.Instance and LoginModel.Instance.is_back_from_game == false then
|
|
self.reconnect_times = 0
|
|
self.default_auto_connect = 4
|
|
UserMsgAdapter.ReconnectHandler(self)
|
|
--判断从游戏中返回,在选角、创角界面,普通重连,is_back_from_game为true nil
|
|
-- elseif LoginModel.Instance and ((LoginModel.Instance.is_back_from_game or LoginModel.Instance.is_back_from_game == nil) )then --and LoginModel.Instance.account_data_10000) then
|
|
elseif LoginModel.Instance == nil or LoginModel.Instance.is_back_from_game ~= true then
|
|
self.reconnect_times = 0
|
|
self.default_auto_connect = 0
|
|
UserMsgAdapter.ReconnectHandler(self)
|
|
end
|
|
EventSystem.Fire(GlobalEventSystem,EventName.GAME_DISCONNECT)
|
|
-- LogError("OnException------->>>>")
|
|
end
|
|
|
|
--连接中断,或者被踢掉--
|
|
local function OnDisconnect()
|
|
self.is_game_connected = false
|
|
if LoginModel.Instance == nil or LoginModel.Instance.is_back_from_game == false then
|
|
self.reconnect_times = 0
|
|
self.default_auto_connect = 2
|
|
UserMsgAdapter.ReconnectHandler(self)
|
|
end
|
|
EventSystem.Fire(GlobalEventSystem,EventName.GAME_DISCONNECT)
|
|
-- LogError("OnDisconnect------->>>>")
|
|
end
|
|
|
|
--收到服务端消息--
|
|
local function OnMessage(buffer)
|
|
-- if currProtoType == ProtocalType.BINARY then
|
|
UserMsgAdapter.receiveMessage(self, buffer)
|
|
-- end
|
|
----------------------------------------------------
|
|
--print('OnMessage-------->>>')
|
|
end
|
|
|
|
EventSystem.Bind(GlobalEventSystem,Protocal.Connect, OnConnect)
|
|
EventSystem.Bind(GlobalEventSystem,Protocal.Message, OnMessage)
|
|
EventSystem.Bind(GlobalEventSystem,Protocal.Exception, OnException)
|
|
EventSystem.Bind(GlobalEventSystem,Protocal.Disconnect, OnDisconnect)
|
|
end
|
|
|
|
function UserMsgAdapter:ReconnectHandler()
|
|
if LoginModel.Instance and LoginModel.Instance.not_show_reconnect then
|
|
return
|
|
end
|
|
|
|
--玩家选择重连、返回处理
|
|
if self.wait_player_handle then
|
|
return
|
|
end
|
|
|
|
--静默连接处理
|
|
if not ClientConfig.is_ban_auto_connect and self.default_auto_connect and self.default_auto_connect > 0 then
|
|
self.default_auto_connect = self.default_auto_connect - 1
|
|
self.default_auto_connect = self.default_auto_connect > 0 and self.default_auto_connect or nil
|
|
|
|
self:SetIsAutoConnecting(true)
|
|
|
|
local function default_connect()
|
|
local function on_connect( )
|
|
if LoginModel.Instance then
|
|
LoginModel.Instance.reconnect_on_game = true
|
|
end
|
|
--清除所有model的缓存(部分model除外)
|
|
LuaMemManager:getInstance():ClearModelData( )
|
|
EventSystem.Fire(GlobalEventSystem,EventName.SHOW_LOADING_VIEW)
|
|
EventSystem.Fire(GlobalEventSystem,LoginStateEvent.START_GAME_CONNECT)
|
|
end
|
|
LoginController.Instance:CheckResUpdate(on_connect, false)
|
|
self:AddConnectCheckTimer()
|
|
end
|
|
GlobalTimerQuest:AddDelayQuest(default_connect,2)
|
|
return
|
|
end
|
|
|
|
if self.has_show_alert_view then
|
|
return
|
|
end
|
|
self.has_show_alert_view = true
|
|
local function ok()
|
|
self.wait_player_handle = false
|
|
local run = function()
|
|
if LoginModel.Instance then
|
|
LoginModel.Instance.reconnect_on_game = true
|
|
end
|
|
--清除所有model的缓存(部分model除外)
|
|
LuaMemManager:getInstance():ClearModelData( )
|
|
EventSystem.Fire(GlobalEventSystem,EventName.SHOW_LOADING_VIEW)
|
|
EventSystem.Fire(GlobalEventSystem,LoginStateEvent.START_GAME_CONNECT)
|
|
end
|
|
LoginController.Instance:CheckResUpdate(run, false)
|
|
self:AddConnectCheckTimer()
|
|
self.has_show_alert_view = false
|
|
end
|
|
local function cancle()
|
|
self.wait_player_handle = false
|
|
local run = function()
|
|
LoginModel.Instance.reconnect_on_game = false
|
|
EventSystem.Fire(GlobalEventSystem,EventName.SHOW_LOADING_VIEW)
|
|
EventSystem.Fire(GlobalEventSystem,EventName.CHANGE_ACCOUNT)
|
|
end
|
|
LoginController.Instance:CheckResUpdate(run, false)
|
|
self.has_show_alert_view = false
|
|
end
|
|
|
|
if self.reconnect_times < 4 then
|
|
self.reconnect_times = self.reconnect_times + 1
|
|
|
|
local check_gameout_state = function()
|
|
if LoginModel.Instance:IsGameOutState() then
|
|
LoginModel.Instance:ResetGameOutState()
|
|
self.reconnect_times = 0
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
if self.reconnect_times == 4 then
|
|
local function func()
|
|
if check_gameout_state() then
|
|
return
|
|
end
|
|
self.wait_player_handle = true
|
|
Alert.show("无法重连到服务器,请确认网络后重试", Alert.Type.One, cancle, cancle, "返回登录")
|
|
end
|
|
GlobalTimerQuest:AddDelayQuest(func,2)
|
|
else
|
|
local function func()
|
|
if LoginModel.Instance.not_show_reconnect then
|
|
return
|
|
end
|
|
if check_gameout_state() then
|
|
return
|
|
end
|
|
self.wait_player_handle = true
|
|
Alert.show("网络已断开链接", Alert.Type.Two, ok, cancle, "重连", "返回登录")
|
|
end
|
|
GlobalTimerQuest:AddDelayQuest(func,2)
|
|
end
|
|
end
|
|
end
|
|
|
|
function UserMsgAdapter:SetIsAutoConnecting( flag )
|
|
self.is_auto_connecting = flag
|
|
end
|
|
|
|
function UserMsgAdapter:GetIsAutoConnecting( )
|
|
return self.is_auto_connecting
|
|
end
|
|
|
|
function UserMsgAdapter:AddConnectCheckTimer()
|
|
|
|
self:RemoveConnectCheckTimer()
|
|
local time = 0
|
|
local last_net_available = Util.NetAvailable
|
|
local function onTimer()
|
|
time = time + 1
|
|
if time >= 12 or self.is_game_connected or (LoginModel.Instance and LoginModel.Instance.is_back_from_game and not LoginModel.Instance.account_data_10000) then
|
|
self:RemoveConnectCheckTimer()
|
|
if time >= 12 then
|
|
Message.show("重连失败")
|
|
self:ReconnectHandler()
|
|
end
|
|
return
|
|
end
|
|
--print("Net Available Check...")
|
|
if not self.is_game_connected and LoginModel:getInstance().reconnect_on_game then
|
|
if not last_net_available and Util.NetAvailable then
|
|
networkMgr:SendConnect()
|
|
end
|
|
end
|
|
|
|
last_net_available = Util.NetAvailable
|
|
end
|
|
self.connect_timer = GlobalTimerQuest:AddPeriodQuest(onTimer,1,-1)
|
|
end
|
|
|
|
function UserMsgAdapter:RemoveConnectCheckTimer()
|
|
if self.connect_timer then
|
|
GlobalTimerQuest:CancelQuest(self.connect_timer)
|
|
self.connect_timer = nil
|
|
end
|
|
end
|
|
|
|
function UserMsgAdapter:Update()
|
|
if self.cmd_callback_queue:GetSize() > 0 and (not self.cmd_handler_time or Time.time - self.cmd_handler_time > 0.5) then
|
|
local size = self.cmd_callback_queue:GetSize()
|
|
if size <= 4 then
|
|
UserMsgAdapter.ImmeHandlerCallback(self, self.cmd_callback_queue:PopFront())
|
|
else
|
|
-- local len = math.ceil(size * 0.25)
|
|
-- print("---------------------------->self.curr_frame_receive_count= ", self.curr_frame_receive_count)
|
|
for i = 1, self.curr_frame_receive_count + 1 do --保证比增加的量多一个
|
|
if i > size then break end
|
|
UserMsgAdapter.ImmeHandlerCallback(self, self.cmd_callback_queue:PopFront())
|
|
end
|
|
-- for i = 1, len do --保证比增加的量多一个
|
|
-- self:ImmeHandlerCallback(self.cmd_callback_queue:PopFront())
|
|
-- end
|
|
end
|
|
self.curr_frame_receive_count = 0
|
|
end
|
|
end
|
|
|
|
function UserMsgAdapter:ImmeHandlerCallback(buffer)
|
|
if buffer then
|
|
self.cmd_handler_time = Time.time
|
|
local cmd = buffer:ReadUshort()
|
|
local can_rar = buffer:ReadByte()
|
|
local call_back = UserMsgAdapter.register_list[cmd]
|
|
if can_print_cmd then
|
|
if cmd ~= 10006 and cmd ~= 12008 and cmd ~= 12001 and cmd then
|
|
logWarn("receive cmd = "..cmd)
|
|
end
|
|
end
|
|
if call_back then
|
|
UserMsgAdapter.receive_byteBuff = buffer
|
|
call_back()
|
|
end
|
|
self.cmd_handler_time = false
|
|
end
|
|
end
|
|
|
|
function UserMsgAdapter:receiveMessage(buffer)
|
|
if self.cmd_callback_queue:GetSize() == 0 --没有队列
|
|
and (not self.last_handler_time or Time.time - self.last_handler_time >= 0.01) --超过一定的频率
|
|
and (not self.cmd_handler_time or Time.time - self.cmd_handler_time > 0.5) then --保护措施
|
|
self.last_handler_time = Time.time
|
|
self.curr_frame_receive_count = 0
|
|
UserMsgAdapter.ImmeHandlerCallback(self, buffer)
|
|
else
|
|
self.curr_frame_receive_count = self.curr_frame_receive_count + 1
|
|
self.cmd_callback_queue:PushBack(buffer)
|
|
end
|
|
--print('receiveMessage->call_back: cmd:>'..cmd)
|
|
end
|
|
|
|
--发送一次性封装好的数据给服务器
|
|
function UserMsgAdapter.SendAllFmtToGame(cmd, fmt_str, ...)
|
|
UserMsgAdapter.WriteBegin(cmd)
|
|
UserMsgAdapter.WriteFMT(fmt_str, ...)
|
|
UserMsgAdapter.SendToGame()
|
|
end
|
|
|
|
--发送一次性封装好的数据给服务器
|
|
function UserMsgAdapter.SendAllFmtToGame2(cmd, fmt_str, ...)
|
|
local args_list = {...}
|
|
networkMgr:SendAllFmtToGame(cmd, fmt_str, table_concat(args_list, UserMsgAdapter.SPLIT_CHAT))
|
|
end
|
|
|
|
function UserMsgAdapter.WriteBegin(cmd)
|
|
UserMsgAdapter.send_byteBuff = ByteBuffer.New()
|
|
UserMsgAdapter.send_byteBuff:WriteShort(cmd)
|
|
if can_print_cmd then
|
|
if cmd ~= 10006 and cmd ~= 12001 and cmd then
|
|
logWarn("send cmd="..cmd)
|
|
end
|
|
end
|
|
UserMsgAdapter.write_cmd = cmd or 0
|
|
end
|
|
|
|
function UserMsgAdapter.WriteFMT(fmt_str, ...)
|
|
if fmt_str then
|
|
local args_list = {...}
|
|
local buffer = UserMsgAdapter.send_byteBuff
|
|
local function writeStream(buffer,type,value)
|
|
-- log("send Message = "..value)
|
|
if value == nil then
|
|
GameError.Instance:SendErrorToPHP("UserMsgAdapter WriteFMT nil cmd is = "..UserMsgAdapter.write_cmd.." "..debug.traceback())
|
|
if type == "s" then
|
|
value = ""
|
|
else
|
|
value = 0
|
|
end
|
|
end
|
|
if type == "c" then
|
|
buffer:WriteByte(value)
|
|
elseif type == "i" then
|
|
buffer:WriteUint(tonumber(value))
|
|
elseif type == "I" then
|
|
buffer:WriteInt(value)
|
|
elseif type == "h" then
|
|
buffer:WriteUshort(value)
|
|
elseif type == "H" then
|
|
buffer:WriteShort(value)
|
|
elseif type == "l" then
|
|
buffer:WriteUlong(value)
|
|
elseif type == "L" then
|
|
buffer:WriteLong(value)
|
|
elseif type == "s" then
|
|
buffer:WriteString(value)
|
|
elseif type == "B" then
|
|
buffer:WriteBytes(value)
|
|
end
|
|
end
|
|
|
|
for i = 1, string_len(fmt_str) do
|
|
writeStream(buffer,string_sub(fmt_str,i,i),args_list[i])
|
|
end
|
|
end
|
|
end
|
|
|
|
function UserMsgAdapter.SendToGame()
|
|
if UserMsgAdapter.send_byteBuff then
|
|
networkMgr:SendMessage(UserMsgAdapter.send_byteBuff)
|
|
end
|
|
UserMsgAdapter.send_byteBuff = false
|
|
end
|
|
|
|
|
|
function UserMsgAdapter.ReadFmt(fmt_str)
|
|
if UserMsgAdapter.receive_byteBuff and fmt_str then
|
|
local buffer = UserMsgAdapter.receive_byteBuff
|
|
local function readStream(buffer,type)
|
|
local value = nil
|
|
if type == "c" then
|
|
value = buffer:ReadByte()
|
|
elseif type == "i" then
|
|
value = buffer:ReadUint()
|
|
elseif type == "I" then
|
|
value = buffer:ReadInt()
|
|
elseif type == "h" then
|
|
value = buffer:ReadUshort()
|
|
elseif type == "H" then
|
|
value = buffer:ReadShort()
|
|
elseif type == "l" then
|
|
value = tonumber(tostring(buffer:ReadUlong()))
|
|
elseif type == "L" then
|
|
value = tonumber(tostring(buffer:ReadLong()))
|
|
elseif type == "s" then
|
|
value = buffer:ReadString()
|
|
elseif type == "B" then
|
|
value = buffer:ReadBytes()
|
|
end
|
|
-- log("receive message = "..value)
|
|
return value
|
|
end
|
|
local len = string_len(fmt_str)
|
|
if len == 1 then
|
|
return readStream(buffer, fmt_str)
|
|
else
|
|
for i = 1, len do
|
|
UserMsgAdapter.result_list[i] = readStream(buffer,string_sub(fmt_str,i,i))
|
|
end
|
|
return unpack(UserMsgAdapter.result_list)
|
|
end
|
|
end
|
|
end
|
|
|
|
function UserMsgAdapter.ReadFmt2(fmt_str)
|
|
-- return UserMsgAdapter.ReadFmt(fmt_str)
|
|
local result = networkMgr:ReadFmt(UserMsgAdapter.receive_byteBuff, fmt_str)
|
|
if result then
|
|
local list = Split(result, UserMsgAdapter.SPLIT_CHAT)
|
|
if list then
|
|
local n_v = nil
|
|
for k, v in ipairs(list) do
|
|
n_v = tonumber(v)
|
|
if n_v then
|
|
list[k] = n_v
|
|
end
|
|
end
|
|
return unpack(list)
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function UserMsgAdapter.RegisterMsgOperate(id, register_func)
|
|
UserMsgAdapter.register_list[id] = register_func
|
|
end
|
|
|