|
|
- --[[
- 功能: 协议处理类的基类
-
- 格式化字符串说明:
- 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
-
|