源战役客户端
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

471 lines
17 KiB

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