You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
4.9 KiB

1 month ago
#!/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)