--[[ 协议模板规则如下 1.在module文件夹下面建立的所有文件夹都是一个一个的模块,里面至少要有一个proto.lua和handler.lua文件 2.handler.lua里面填写该模块的cg_xxx函数 3.proto.lua里面填写该模块的cg和gc协议 4.对于proto.lua里面的不是以cg和gc开头的table,是作为子结构,其中,如果没有local开头的,那么子结构的名字将作为客户端对应的类的名字,如果有local开头或者是直接在table里面展开的子结构,客户端对应的类的名字将根据一层一层的字段自动生成 5.协议的每个字段{名字,容量,类型} 名字:只能用string,不能用number,并且不能以下划线开头(避免生成的跟客户端的私有变量冲突) 容量:为预分配的最大空间,当容量大于1的时候,该字段就必需包含长度,例如字段名为aa,aa就是一个table,那么长度就是aa[0],aa[0]必需小于等于容量 类型: {"aa", 1, "int"} --32位整型 {"aa", 1, "double"} --64位浮点数 {"aa", 1, "string", 128} --一个字符串,里面最多有128个字节,字符串长度上限不填的话,默认是64 {"aa", 1, sub} --aa是一个table,里面的字段由子结构的模板sub决定 {"aa", 2, "int"} --数组,里面最多有2个整型 {"aa", 2, "double"} --数组,里面最多有2个64位浮点数 {"aa", 2, "string", 128} --字符串数组,每个字符串里面最多有128个字节,字符串长度上限不填的话,默认是64 {"aa", 2, sub} --aa是一个table,aa[1]也是一个table,aa[1]里面的字段由子结构的模板sub决定 --]] local msg_ex = _G.msg_ex cg = cg or {} gc = gc or {} proto_handler = proto_handler or {} proto_id = proto_id or {} proto_name = proto_name or {} proto_template = proto_template or {} list = list or {} -- 消息发送对象列表 第0为长度 后面1-x为obj local Config = require("Config") local mt = { __index = function(t, k) local id = t[1] or "" assert(nil, id .. " " .. k .. " not exist") end } local function proto_container_metatable(msg) if not Config.IS_WINDOWS then return end setmetatable(msg, mt) for _, v in pairs(msg) do if type(v) == "table" then proto_container_metatable(v) end end end local function proto_container_resize(msg, template) for _, v in ipairs(template) do if v[2] < 2 then if type(v[3]) == "table" then cnt = cnt + 1 msg[v[1]] = {} proto_container_resize(msg[v[1]], v[3]) end else if type(v[3]) == "table" then local v2 = v[2] if v2 == 2 and (v[1] == "items" or v[1] == "equips" or v[1] == "gems") then v2 = 1 end cnt = cnt + 1 msg[v[1]] = {} for i = 1, v2 do msg[v[1]][i] = {} proto_container_resize(msg[v[1]][i], v[3]) end else cnt = cnt + 1 msg[v[1]] = {} end end end end function register(name, id, template, handler) if not proto_name[id] then msg_ex.register_template(id, template) if string.sub(name, 1, 2) == "CG" then cg[id] = {[1] = id} proto_container_resize(cg[id], template) proto_container_metatable(cg[id]) elseif string.sub(name, 1, 2) == "GC" then gc[name] = {[1] = id} cnt = 0 proto_container_resize(gc[name], template) if 8000 < cnt then end end end proto_handler[id] = handler proto_name[id] = name proto_template[id] = template end if msg_ex then send = msg_ex.unicast sendMulti = msg_ex.multicast sendWorld = msg_ex.broadcast end local out = {} local out_len = 0 local function add_space(step) for i = 1, step do out_len = out_len + 1 out[out_len] = " " end end local set = {} function trace(m, template, step, print_on_err) if not step then template = proto_template[m[1]] step = 0 out_len = 0 end for k in pairs(set) do set[k] = nil end for _, v in ipairs(template) do set[v[1]] = true end for k in pairs(m) do if k ~= 1 and not set[k] then print(table.concat(out, nil, 1, out_len)) assert(nil, k .. " not need") end end for _, v in ipairs(template) do add_space(step) out_len = out_len + 1 out[out_len] = v[1] out_len = out_len + 1 out[out_len] = "=" if v[2] < 2 then if type(v[3]) == "table" then if type(m[v[1]]) ~= "table" then print(table.concat(out, nil, 1, out_len)) assert(nil, v[1] .. " is not table") end out_len = out_len + 1 out[out_len] = "\n" trace(m[v[1]], v[3], step + 1, print_on_err) else if (v[3] == "byte" or v[3] == "short" or v[3] == "int" or v[3] == "double" or v[3] == "uint") and type(m[v[1]]) ~= "number" then print(table.concat(out, nil, 1, out_len)) assert(nil, v[1] .. " is not number") end if v[3] == "string" and type(m[v[1]]) ~= "string" then print(table.concat(out, nil, 1, out_len)) assert(nil, v[1] .. " is not string") end out_len = out_len + 1 out[out_len] = m[v[1]] out_len = out_len + 1 out[out_len] = "\n" end else if type(m[v[1]]) ~= "table" then print(table.concat(out, nil, 1, out_len)) assert(nil, v[1] .. " is not table") end out_len = out_len + 1 out[out_len] = "\n" if type(m[v[1]][0]) ~= "number" then print(table.concat(out, nil, 1, out_len)) assert(nil, v[1] .. " len is not number") end add_space(step + 1) out_len = out_len + 1 out[out_len] = "0=" out_len = out_len + 1 out[out_len] = m[v[1]][0] out_len = out_len + 1 out[out_len] = "\n" for i = 1, m[v[1]][0] do if type(v[3]) == "table" then if type(m[v[1]][i]) ~= "table" then print(table.concat(out, nil, 1, out_len)) assert(nil, v[1] .. " " .. i .. " is not table") end add_space(step + 1) out_len = out_len + 1 out[out_len] = i out_len = out_len + 1 out[out_len] = "=" out_len = out_len + 1 out[out_len] = "\n" trace(m[v[1]][i], v[3], step + 2, print_on_err) else if (v[3] == "byte" or v[3] == "short" or v[3] == "int" or v[3] == "double" or v[3] == "uint") and type(m[v[1]][i]) ~= "number" then print(table.concat(out, nil, 1, out_len)) assert(nil, v[1] .. " " .. i .. " is not number") end if v[3] == "string" and type(m[v[1]][i]) ~= "string" then print(table.concat(out, nil, 1, out_len)) assert(nil, v[1] .. " " .. i .. " is not string") end add_space(step + 1) out_len = out_len + 1 out[out_len] = i out_len = out_len + 1 out[out_len] = "=" out_len = out_len + 1 out[out_len] = m[v[1]][i] out_len = out_len + 1 out[out_len] = "\n" end end end end if step == 0 and not print_on_err then print(table.concat(out, nil, 1, out_len)) end end