#!/usr/bin/python # -*- coding: UTF-8 -*- #从proto文件中提取数据到lua 目前只有GameCs.proto import os import re import codecs import time import getpass import shutil CurDir = os.getcwd() ProtoName = "GameCs.proto" ProtoBytesName = "GameCs.proto.bytes" FileHead = "local NETMSG = {}\n_ENV = NETMSG\n" FileFoot = "\nreturn NETMSG" ConstDir = CurDir+"/../../client/demo/Assets/Lua/Const" ProtocolDir = "../../client/demo/Assets/Protocol/" MsgFileName = "NetMsgs.lua" MsgFilter = ["CS_MSGID_NONE", "CS_GAMEMSGID_NONE", "SC_GAMEMSGID_NONE"] def getFileData(fileName): data = None with open(fileName, encoding='UTF-8') as f: data = f.read() return data def fileWrite(fileName, data): with codecs.open(fileName, "w", "utf8") as f: #timeStr = "-- build by:" + getpass.getuser() + " " + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "\n" f.write(FileHead + data + FileFoot) return # 获取SC_GAMEMSGID_ENTER_DESK_NOTIFY = 3001 def getMsgIDStr(data, keyword): content = re.findall(r"\s+" + keyword + r"\s*{([^{}]*)}", data) if len(content) > 0: lines = content[0].split("\n") #逐行 lineList = [] #del_list = [] for line in lines: #lineList = re.findall(r"(/*\s*\w+\s*=\s*\d+)", content[0]) val = line pos = line.find("//") if pos != -1: #截取注释 val = line[0:pos] ss = re.findall(r"(\w+\s*=\s*\d+)", val) if len(ss) > 0: s = ss[0] if s.find(MsgFilter[0]) == -1 and s.find(MsgFilter[1]) == -1 and s.find(MsgFilter[2]) == -1: #注释掉的协议剔除 lineList.append(s) return lineList def getEnumKeyList(data): enumKeyList = re.findall(r"enum\s+(\w+)", data) delEnumKeyList = re.findall(r"/{2,}[\t\r\f ]*enum\s+(\w+)", data) for s in delEnumKeyList: try: enumKeyList.remove(s) except ValueError: pass return enumKeyList #获取枚举和消息ID类型 def getEnumData(data): msgValueMap = {} msgRegex = r"([\w_]+)\s?=\s?(\d+)" enumKeyList = getEnumKeyList(data) msgIdData = "" enumData = "" for key in enumKeyList: if key.find("MsgID") != -1: msgIdData = msgIdData + "-- " + key + '\n' for s in getMsgIDStr(data, key): msgKeyValue = re.findall(msgRegex, s) for pair in msgKeyValue: msgValueMap[pair[0]] = int(pair[1]) msgIdData = msgIdData + s + '\n' msgIdData = msgIdData + '\n' else: _str = key + " = {\n" for s in getMsgIDStr(data, key): _str = _str + '\t' + s + ',\n' _str = _str + '}\n\n' enumData = enumData + _str for key in msgValueMap: if key.find("REQ") !=-1: resKey = key.replace("REQ", "RES") if msgValueMap.get(resKey): if msgValueMap[key] + 1 != msgValueMap[resKey]: print(key, "请求和响应的消息ID不连续,需要修正") else: print(key,"没有响应消息") return enumData + msgIdData # 获取消息ID与消息名对应的值 ''' 通过//注释匹配 支持多ID对应一个消息 //CS_MSGID_PING //CS_GAMEMSGID_PING message CSPing { int64 clientTime = 1; int64 serverTime = 2; } ''' messageRe = re.compile(r"message\s*(\w+)\s*{") def getMessageByMsgID(data, msgID): idSearch = re.search(r"//[ \t]*" + msgID + r"\W", data) if idSearch: msgNameSearch = messageRe.search(data, idSearch.span()[1]) if msgNameSearch: return msgNameSearch.group(1) return "" def getMsgName(data): msgIdList = re.findall(r"enum\s+(\w+MsgID)", data) undefined = "--[[\n" msgData = "MsgList = {\n" for key in msgIdList: for s in getMsgIDStr(data, key): nameSearch = re.search(r"(\w+)\s*=", s) if nameSearch: name = nameSearch.group(1) msg = getMessageByMsgID(data, name) if len(msg) == 0: log = name + " not found the annotation!" undefined = undefined + log + '\n' print(log) else: msgData = msgData + ("\t[%s] = \"%s\",\n") % (name, msg) undefined = undefined + "]]" msgData = msgData + "}" return undefined + "\n" + msgData if __name__ == '__main__': protocolFile = os.path.join(CurDir, ProtoName) if not os.path.exists(ProtocolDir): os.makedirs(ProtocolDir) shutil.copy(protocolFile, os.path.join(ProtocolDir, ProtoName)) #shutil.copy(protocolFile, os.path.join(ProtocolDir, ProtoBytesName)) fileData = getFileData(protocolFile) enumData = getEnumData(fileData) msgNameData = getMsgName(fileData) fileWrite(os.path.join(ConstDir, MsgFileName), enumData + msgNameData)