|
|
-
-
- BaseController = BaseController or BaseClass()
- local BaseController = BaseController
- local UserMsgAdapter = UserMsgAdapter
- BaseController.request_protocals_list = Array.New()
- BaseController.handle_protocals = {} --处理的指令列表
- BaseController.is_delay_send_protocal = false
- function BaseController:__init()
- --销毁引用
- local function onViewDestoryHandler(view)
- self:clearViewQuoted(view)
- end
- self.clearViewQuoted_BindId = self:Bind(BaseView.DestroyEvent,onViewDestoryHandler)
-
- end
-
- function BaseController:RemoveCheckOutEvent()
-
- end
-
-
- function BaseController:EnableCheckoutClear(bool)
- bool = bool == nil and true or bool
- self.checkout_clear_view = bool
- if bool then
- self.view_list = {} --依附于该控制器的界面
- setmetatable(self.view_list, {__mode = "v"}) --弱引用
- --创建窗口
- local function onViewCreateHandler(list)
- self:addView(list)
- end
- self.CreateView_BindId = self:Bind(BaseView.CreateView,onViewCreateHandler)
-
-
- local function close_view()
- for k,v in pairs(self.view_list) do
- v:Close()
- end
- self:RemoveCheckOutEvent()
- end
-
- self:Bind(EventName.CHANGE_ACCOUNT, close_view)
- self:Bind(EventName.CHANGE_ROLE, close_view)
- end
- end
-
- function BaseController:__delete()
- if GlobalEventSystem then
- if self.clearViewQuoted_BindId then
- GlobalEventSystem:UnBind(self.clearViewQuoted_BindId)
- self.clearViewQuoted_BindId = nil
- end
- if self.CreateView_BindId then
- GlobalEventSystem:UnBind(self.CreateView_BindId)
- self.CreateView_BindId = nil
- end
- end
-
- if self.checkout_timer then
- for k, timer_id in pairs(self.checkout_timer) do
- GlobalTimerQuest:CancelQuest(timer_id)
- end
- self.checkout_timer = nil
- end
- end
-
-
- function BaseController:addView(list)
- if list and list[1] then
- for k,v in pairs(self) do
- if list[1] == v then
- table.insert(self.view_list,v)
- return
- end
- end
- end
- end
-
- --清除view的引用
- function BaseController:clearViewQuoted(view)
- -- if self._class_type._source == view._source then
- --只检测baseitem
- local function checkBaseItem(table)
- --判断纯队列 或者单个baseitem
- if type(table) == "table" and (not table._class_type or table._class_type.Class_Type == "BaseItem" or table._is_uitabwindow) then
- if (table._class_type and table._class_type.Class_Type == "BaseItem") or table._is_uitabwindow then
- if not table._use_delete_method then
- if table._is_uitabwindow then
- GlobalEventSystem:Fire(LuaErrorModel.SEND_LUAERROR_MESSAGE,"BaseView没清除UITabWindow")
- else
- GlobalEventSystem:Fire(LuaErrorModel.SEND_LUAERROR_MESSAGE,view._class_type._source.."有baseitem没deleteMe " .. table._class_type._source)
- end
- end
- else
- for k, value in pairs(table) do
- checkBaseItem(value)
- end
- end
- end
- return
- end
- for k,v in pairs(self) do
- if view == v then
- -- for p,value in pairs(view) do
- -- if type(value) == "number" then
- -- if EventSystem.checkHasUnBind(value) then
- -- Alert.show(view._class_type._source.."有事件没解绑 "..p)
- -- end
- -- end
- -- end
- if not Application.isMobilePlatform then
- for p,value in pairs(view) do
- if type(value) == "table" and (not value._class_type or value._class_type.Class_Type == "BaseItem" or value._is_uitabwindow) then
- checkBaseItem(value)
- end
- end
- end
- self[k] = nil
- break
- end
- end
- -- end
- end
-
- function BaseController:AddSendFmtCheckout(cmd, time, callback)
- self.checkout_timer = self.checkout_timer or {}
- local timer_id = self.checkout_timer[cmd]
- if timer_id then
- GlobalTimerQuest:CancelQuest(timer_id)
- timer_id = nil
- end
-
- timer_id = GlobalTimerQuest:AddDelayQuest(callback,time)
- self.checkout_timer[cmd] = timer_id
- end
-
- function BaseController:RemoveSendFmtCheckout(cmd)
- if self.checkout_timer then
- local timer_id = self.checkout_timer[cmd]
- if timer_id then
- GlobalTimerQuest:CancelQuest(timer_id)
- self.checkout_timer[cmd] = nil
- end
- end
- end
-
- --[[@
- 功能: 注册一条协议的响应函数
- 参数:
- id 协议号
- func_name 继承ProtocalBase类的成员函数名称
- 返回值:
- 无
- 其它: 无
- 作者: raowei
- ]]
- function BaseController:RegisterProtocal(id, func_name)
- local register_func = nil
- register_func = function(data_list)
- local oper_func = self[func_name]
- if oper_func then
- oper_func(self, data_list)
- end
-
- if self.checkout_timer then
- local timer_id = self.checkout_timer[id]
- if timer_id then
- GlobalTimerQuest:CancelQuest(timer_id)
- self.checkout_timer[id] = nil
- end
- end
- end
-
- UserMsgAdapter.RegisterMsgOperate(id, register_func)
- end
- --[[@
- 功能: 根据格式化字符串发送协议内容到Game服
- 参数:
- cmd 指令号 int
- fmt_str 格式化字符串(说明请参照文件头部) string
- ... 发送到协议中的字段
- 返回值:
- 无
- 其它: 无
- 作者: raowei
- ]]
- function BaseController.SendFmtFromDelayList(vo)
- if vo == nil then return end
-
- local cmd = vo.cmd
- local fmt_str = vo.fmt_str
- local arg_list = vo.args
- UserMsgAdapter.WriteBegin(cmd)
- if fmt_str ~= nil then
- UserMsgAdapter.WriteFMT(fmt_str, unpack(vo.args))
- end
- UserMsgAdapter.SendToGame()
- end
-
- function BaseController:RegisterProtocal2(id, func)
- UserMsgAdapter.RegisterMsgOperate(id, func)
- end
-
- function BaseController:SendFmtToGame(cmd, fmt_str, ...)
- -- if cmd == 32007 or cmd == 12005 or cmd == 12002 or cmd == 61105 then
- -- if not LoginModel:getInstance().show_loading_state or cmd == 32007 or cmd == 12005 or cmd == 12002 or cmd == 61105 then
- -- BaseController.SendFmtFromDelayList(vo)
- -- else
- if ... and cmd ~= 12001 then--12001走路发的协议
- print("send cmd log: ",cmd,fmt_str,...)
- end
- if BaseController.is_delay_send_protocal or BaseController.request_protocals_list:GetSize() > 0 then
- local vo = {cmd = cmd, fmt_str = fmt_str, args = {...}}
- BaseController.request_protocals_list:PushBack(vo)
- else
- UserMsgAdapter.SendAllFmtToGame(cmd, fmt_str, ...)
- end
- -- end
- end
-
- function BaseController:SendAllFmtToGame2(cmd, fmt_str, ...)
- UserMsgAdapter.SendAllFmtToGame2(cmd, fmt_str, ...)
- end
-
- function BaseController.DelaySendFmtToGame()
- if BaseController.request_protocals_list:GetSize() > 0 then
- local vo = BaseController.request_protocals_list:PopFront()
- UserMsgAdapter.SendAllFmtToGame(vo.cmd, vo.fmt_str, unpack(vo.args))
- end
- end
-
-
-
-
-
- function BaseController:WriteBegin(cmd)
- UserMsgAdapter.WriteBegin(cmd)
- end
- function BaseController:WriteFMT(fmt_str, ...)
- UserMsgAdapter.WriteFMT(fmt_str, ...)
- end
- function BaseController:SendToGame()
- UserMsgAdapter.SendToGame()
- end
-
- --[[@
- 功能: 从协议缓冲区按格式化字符串读取内容
- 参数:
- fmt_str 格式化字符串(参见文件头部说明) string
- 返回值:
- 根据格式化字符串返回多个值
- 其它: 无
- 作者: raowei
- ]]
- function BaseController:ReadFmt(fmt_str)
- return UserMsgAdapter.ReadFmt(fmt_str)
- end
-
- --[[@
- 功能: 绑定事件
- 参数: 绑定的id,绑定的函数
- 返回值: 一个事件的handler
- 其它: 无
- 作者: raowei
- ]]
- function BaseController:Bind(event_id, event_func,class_name)
-
- return GlobalEventSystem:Bind(event_id,event_func,class_name)
- end
- --[[@
- 功能: 解除绑定事件
- 参数: 事件的handler
- 返回值: 无
- 其它: 无
- 作者: raowei
- ]]
- function BaseController:UnBind( obj )
- GlobalEventSystem:UnBind( obj )
- end
- --[[@
- 功能: 立即触发事件
- 参数: 绑定的id,绑定的函数
- 返回值: 绑定的id,传递的参数
- 其它: 无
- 作者: raowei
- ]]
- function BaseController:Fire(event_id,...)
- GlobalEventSystem:Fire( event_id ,...)
- end
- --[[@
- 功能: 下一帧触发事件
- 参数: 绑定的id,绑定的函数
- 返回值: 绑定的id,传递的参数
- 其它: 无
- 作者: raowei
- ]]
- function BaseController:FireNextFrame(event_id,...)
- GlobalEventSystem:FireNextFrame( event_id ,...)
- end
-
- --生成model的绑定请求协议的事件
- local function BindReqEvent(self, id, req_event_data, register_func)
- local req_event_failed_str = "req net proto " .. id .. " failed with fire event " .. req_event_data[1]
- local function on_req( ... )
- req_event_data[2] = req_event_data[2] or ""
- local need_print = self.proto_info[id].show_print
- local arge = {req_event_data[2], ...}
-
- if need_print then
- local arge_str = ""
- if #arge > 0 then
- for i,v in ipairs(arge) do
- arge_str = arge_str.."[No."..(i)..":"..tostring(arge[i]).."] "
- end
- else
- arge_str = "none arge"
- end
- print('Cat:BaseController.lua req net proto : '..id.." arges:", arge_str)
- --网络协议的参数数量不对!比如"cii"就只需要传入3个,具体传了哪些见上条打印
- local has_proto_field_desc = (arge[1] and type(arge[1])=="string")
- local need_assert = has_proto_field_desc and (#arge[1] ~= #arge - 1)
- if need_assert then
- local error_str = req_event_failed_str..":proto fields num not match!"
- assert(false, error_str)
- end
- end
-
- if not self.proto_info[id].is_debug then
- if self.proto_info[id].req_func then
- table.remove(arge,1)
- self.proto_info[id].req_func( self, unpack(arge))
- else
- self:SendFmtToGame(id, unpack(arge))
- end
- else
- self.proto_info[id].req_arge = arge
- register_func()
- end
- end
- self.model:Bind(req_event_data[1], on_req)
- end
-
- --自动生成发送和收到网络协议的处理代码,注:之所以是local function就是不想外部调用
- local function RegisterProtocalAndReqEvent(self, id, req_event_data)
- local register_func = function()
- local proto = self.proto_info[id]
-
- if proto.handler_manual then
- proto.handler_manual(self)
- return
- end
-
- if proto.show_print then
- assert(_G["SCMD"..id]~=nil, "cannot find SCMD"..id..".lua, have you generated this proto file yet?")
- end
- --Cat_Todo : 这里可以考虑用个协议对象池,这样就不需要频繁new协议对象了
- local scmd = _G["SCMD"..id].New(not proto.is_debug)
- if proto.is_debug and self.CreateDebugSCMD then
- --如果该协议的is_debug属性为true,调用handler前将进入CreateDebugSCMD函数,在这里返回一个调试用的结构体模仿收到网络信息,之所以放在一个函数里处理是因为想删掉时可以方便点
- scmd = self:CreateDebugSCMD(id, scmd, self.proto_info[id].req_arge)
- end
- if proto.show_print then
- print("Cat:BaseController [start:handle"..id..(proto.is_debug and " Debug Model!" or "").."] scmd:", scmd)
- PrintTable(scmd)
- print("Cat:BaseController [end]")
- end
- -- local handler = proto.handler or self["Handle"..id]
- if proto.handler then
- proto.handler(self, scmd, id)
- end
- end
- UserMsgAdapter.RegisterMsgOperate(id, register_func)
-
- if req_event_data and req_event_data[1] then
- BindReqEvent(self, id, req_event_data, register_func)
- end
- end
-
- --[[说明:
- 本套做法好处:不再需要手写代码绑定Req请求协议的代码,且发送Req请求协议事件时可以传入收到回复协议的回调函数,所以不再需要触发和监听Ack收到协议的事件;调试代码集中在CreateDebugSCMD函数里方便管理;可以针对某协议开关调试和打印信息,show_print为true时除了打印请求和收到的协议内容,还会判定请求的协议内容是否有问题信息,建议前期开启方便定位bug
- 具体用法:配置proto_info:
- )key值为协议id
- )req_event_data会生成self.model的绑定事件,具体生成什么代码见BaseController,为nil就不生成;想请求该协议时可:
- req_event_data第一个参数是事件名,后续参数可选,第二个参数必须为 协议内容的格式字符串
- )handler就是收到后端回复时的处理函数,触发时机在CreateDebugSCMD之后
- )handler_manual就是收到后端回复时的手写处理函数,会绕过部分功能比如CreateDebugSCMD
- )req_func就是适应部分自己处理发协议的事件响应,没有的话就用默认方式发,有的话会返回{self, 内容}
- )is_debug为true的话将不发送协议,直接回调收到协议的处理函数;
- )show_print控制是否在请求和收到协议时打印相关信息
- ]]--
- function BaseController:RegisterProtocalByCFG(proto_info)
- self.proto_info = proto_info
- self.ack_call_back = self.ack_call_back or {}
- for k,v in pairs(self.proto_info) do
- RegisterProtocalAndReqEvent(self, k, v.req_event_data)
- end
- end
-
- --打开界面
- function BaseController:OpenView( class_name, show, ... )
- if show then
- if not self[class_name] then
- self[class_name] = _G[class_name].New()
- end
- if not self[class_name]:HasOpen() then
- self[class_name]:Open(...)
- end
- else
- if self[class_name] then
- self[class_name]:Close(...)
- end
- end
- end
|