-- 是否显示解析协议的具体信息 local showNetLog = true; VT_None = 0; -- bool,1字节 VT_Bool = 1; -- 无符号uchar,1字节,对应java的byte VT_UChar = 2; -- 有符号char,1字节,对应java的byte VT_Char = 3; -- 有符号short,2字节 VT_Short = 4; -- 无符号ushort,2字节 VT_UShort = 5; -- 有符号int,4字节 VT_Int = 6; -- 无符号uint,4字节 VT_UInt = 7; -- 浮点数,4字节 VT_Float = 8; -- 长整形,int64,8字节,对应java的long VT_LLong = 9; -- 字符串,使用UTF8编码,先保存2字节长度,再保存字符串数据 VT_String = 10; -- 双精度浮点数 VT_Double = 11; -- 二进制数据,先保存4个字节长度,再保存数据 VT_Buffer = 12; VT_Byte = VT_Char; VT_Long = VT_LLong; -- 保存所有简单类型 local gSimpleNetVarType = {} for i = 1 , 12 do gSimpleNetVarType[i] = cc.SimpleNetVar:create(i); gSimpleNetVarType[i]:retain(); autoGC(gSimpleNetVarType[i]); end -- 保存所有全局类 local gNetClassType = {} -- 获取网络数据类型 function getVarType(t) if type(t) == "number" then local simpleType = gSimpleNetVarType[t]; assert(simpleType); return simpleType; else assert(t); return t; end end local newBindableArray = require("luaScript.Protocol.BindableArray") local function tableNewHook(tab , cls) local ret = newBindableArray(tab); rawset(ret , "NetVar" , cls); return ret; end local function tableReadHook(tab , cls) local ret = newBindableArray(tab); rawset(ret , "NetVar" , cls); return ret; end local function tableWriteHook(tab , cls) return rawget(tab , "Datas"); end -- Map类型 function VT_Map(keyType , valueType) local var = cc.MapNetVar:create(getVarType(keyType) , getVarType(valueType)); var:setNewHookFunc(tableNewHook); var:setReadHookFunc(tableReadHook); var:setWriteHookFunc(tableWriteHook); return var; end -- Vector类型 function VT_Vector(valueType) local var = cc.VectorNetVar:create(getVarType(valueType)); var:setNewHookFunc(tableNewHook); var:setReadHookFunc(tableReadHook); var:setWriteHookFunc(tableWriteHook); return var; end -- Vector类型 function VT_VectorToSet(valueType , defaultValue) local var = cc.VectorToSetNetVar:create(getVarType(valueType) , defaultValue); var:setNewHookFunc(tableNewHook); var:setReadHookFunc(tableReadHook); var:setWriteHookFunc(tableWriteHook); return var; end -- Vector类型 function VT_VectorToMap(valueType , mapKeyName) assert(type(mapKeyName) == "string"); local var = cc.VectorToMapNetVar:create(getVarType(valueType) , mapKeyName); var:setNewHookFunc(tableNewHook); var:setReadHookFunc(tableReadHook); var:setWriteHookFunc(tableWriteHook); return var; end -- 由用户决定读写函数 function VT_Custom(name , newFunc , readFunc , writeFunc) assert(type(name) == "string" and type(newFunc) == "function" and type(readFunc) == "function" and type(writeFunc) == "function"); return cc.CustomNetVar:create(name , newFunc , readFunc , writeFunc); end function VT_CustomVectorToMap(valueType , mapKeyName) assert(type(mapKeyName) == "string"); local var = cc.CustomToMapNetVar:create(getVarType(valueType), mapKeyName); var:setNewHookFunc(tableNewHook); var:setReadHookFunc(tableReadHook); var:setWriteHookFunc(tableWriteHook); return var; end -- 定义一个枚举 function VT_Enum(name , valueType , values) assert(type(name) == "string" and type(values) == "table"); local enumVar = cc.EnumNetVar:create(name , getVarType(valueType)); for i , v in pairs(values) do enumVar:addValue(i , v); end return enumVar; end -- 属性ID function VT_PropertyID(classTable) assert(tolua.type(classTable) == "cc.NetClass"); return cc.PropertyIdNetVar:create(classTable); end -- 属性,需要传一个类的名字进来,属性最终序列化会变成一个属性ID+属性值(根据不同属性长度会不同) function VT_Property(classTable) assert(tolua.type(classTable) == "cc.NetClass"); return cc.PropertyNetVar:create(classTable); end local function VT_MapPropertytableReadHook(tab , cls) local ret = newBindableArray(tab); rawset(ret , "NetVar" , cls); return ret; end -- 属性映射表类型 function VT_MapProperty(classTable) assert(tolua.type(classTable) == "cc.NetClass"); local var = cc.MapPropertyNetVar:create(classTable); var:setNewHookFunc(tableNewHook); var:setReadHookFunc(VT_MapPropertytableReadHook); var:setWriteHookFunc(tableWriteHook); return var; end local RemainTime = require("luaScript.Protocol.RemainTime") function VT_RemainTime(numberType, scaler, onTimeOver) local numberNetVar = getVarType(numberType); local function newRemainTime() return RemainTime:new(); end local function newFunc(defaultValue) local instance = newRemainTime(); if type(defaultValue) == "number" then instance:setRemainTime(defaultValue); end return instance; end local function readFunc(stream) local remainTime = NetStream.readNetVar(numberNetVar , stream) local instance = newRemainTime(); instance:setRemainTime(remainTime / scaler); return instance end local function writeFunc(value , stream) NetStream.writeNetVar(numberNetVar , stream , value.RemainTime * scaler) end return VT_Custom("VT_RemainTime" , newFunc , readFunc , writeFunc); end -- 从NetStream解析出一个类 function cc.NetClass:tryRead(stream) local result; local errorMessage; function readIt() cc.NetVar:setLogEnabled(showNetLog); result = NetStream.readNetVar(self , stream); end function onError(msg) errorMessage = msg; print("读取数据时发生了错误:" , msg); cc.NetVar:setLogEnabled(showNetLog); end xpcall(readIt, onError) return result; end -- 从NetStream解析出一个类 function cc.NetClass:read(stream) local result; local errorMessage; function readIt() cc.NetVar:setLogEnabled(showNetLog); result = NetStream.readNetVar(self , stream); end function onError(msg) errorMessage = msg; cc.NetVar:setLogEnabled(showNetLog); print("读取数据时发生了错误,尝试以详细输出方式读取:" , msg); NetStream.reset(stream); xpcall(readIt, function(msg) cc.NetVar:setLogEnabled(showNetLog); print(msg) end ) cc.NetVar:setLogEnabled(showNetLog); end xpcall(readIt, onError) cc.NetVar:setLogEnabled(showNetLog); --readIt(); if errorMessage then error(errorMessage); end return result; end -- 创建类实例 function cc.NetClass:new() local object = NetStream.newNetVar(self); return object; end -- 把类实例写入到stream function cc.NetClass:write(stream , object) NetStream.writeNetVar(self , stream , object); end -- 把类实例发送到服务器 function cc.NetClass:send(object , moduleID , commandID, net) local stream = NetStream.new(); self:write(stream , object); net:send(moduleID , commandID , stream); NetStream.delete(stream); end -- 保存到字符串 function cc.NetClass:saveToString(object) local stream = NetStream.new(); self:write(stream , object); local data = NetStream.getWriteData(stream); NetStream.delete(stream); return data; end -- 从字符串载入类 function cc.NetClass:loadFromString(stringData) local stream = NetStream.new(stringData); local responseInfo = self:read(stream); NetStream.delete(stream); return responseInfo; end -- 保存到文件 function cc.NetClass:saveToFile(object , filename) local stream = NetStream.new(); self:write(stream , object); local data = NetStream.getWriteData(stream); local f = io.open(filename , "wb"); if f then f:write(data); f:close(); end NetStream.delete(stream); return data; end -- 从文件载入类 function cc.NetClass:loadFromFile(filename) local f , err = io.open(filename , "rb"); if not f then return f , err; end local stringData = f:read("*a"); f:close(); local stream = NetStream.new(stringData); local responseInfo = self:read(stream); NetStream.delete(stream); return responseInfo; end -- 克隆一份 function cc.NetClass:clone(object) assert(object); local stream = NetStream.new(); self:write(stream , object); local responseInfo = self:read(stream); NetStream.delete(stream); return responseInfo; end -- 定义一个成员变量 function defVar(name , valueType , defaultValue , propId , minVersion) return cc.MemberVar:create(name , getVarType(valueType) , propId or -1 , defaultValue , true , minVersion or 0); end -- 定义一个本地成员变量(不序列化到网络) function localVar(name , valueType , defaultValue , propId) return cc.MemberVar:create(name , getVarType(valueType) , propId or -1 , defaultValue , false , 0); end local function classNewHook(tab , cls) if not cls or type(cls) ~= "userdata" then log(table.tostring(tab)) end log(type(cls)) local ret = newBindableArray(tab); rawset(ret , "NetVar" , cls); local onNew = cls.onNew; if onNew then onNew(cls , ret); end return ret; end local function classReadHook(tab , cls) local ret = newBindableArray(tab); rawset(ret , "NetVar" , cls); local onRead = cls.onRead; if onRead then onRead(cls , ret); end return ret; end local function classWriteHook(tab , cls) local onWrite = cls.onWrite; if onWrite then onWrite(cls , tab); end return rawget(tab , "Datas"); end -- 定义一个类 function defClass(name , ...) local arg = {...}; local cls = cc.NetClass:create(name); cls:setNewHookFunc(classNewHook); cls:setReadHookFunc(classReadHook); cls:setWriteHookFunc(classWriteHook); for i , v in ipairs(arg) do cls:addMemberVar(v) end if gNetClassType then print(string.format("the class named [%s] is exist",name)) end gNetClassType[name] = cls; local propByIds = {}; local propByNames = {}; -- 根据属性ID保存所有属性 for i , v in ipairs(arg) do propByIds[v:getPropId()] = v; propByNames[v:getName()] = v; end -- 根据属性ID获取属性名 function cls:getPropName(id) local prop = propByIds[id]; if prop then return prop:getName(); else return nil; end end -- 根据属性ID获取属性名 function cls:getPropId(name) local prop = propByNames[name]; if prop then return prop:getPropId(); else return nil; end end -- 根据属性ID设置一个值 function cls:set(object , id , value) object[self:getPropName(id)] = value; end -- 根据属性ID获取一个值 function cls:get(object , id) return object[self:getPropName(id)]; end -- 根据属性ID增加一个值 function cls:add(object , id , value) local name = self:getPropName(id); object[name] = object[name] + value; end cls:retain(); autoGC(cls); -- _G[name] = cls; return cls; end