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.
 
 
 
 
 
 

174 lines
5.5 KiB

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 从proto文件中提取数据到lua 目前只有GameCs.proto
import os
import re
import codecs
import string
import time
import getpass
import shutil
CurDir = os.getcwd()
ProtoName = "../protocol/GameCs.proto"
# ProtoBytesName = "GameCs.proto.bytes"
FileHead = "using System.Collections.Generic;\nusing ProtoCSClass;\nusing xFrame.NetWork;\nusing Type = System.Type;\nnamespace Proto{\n"
ClassHead = "\npublic class NetMsgs{\n\tpublic Dictionary<int, Type> msgMap = new Dictionary<int, Type>(3000);\n\tpublic NetMsgs(){\n\t\t"
FileFoot = "\n}}"
# ConstDir = CurDir + "/../../client/client/Assets/Lua/Const"
ProtocolDir = "../../client/client/Assets/Protocol/"
MsgFileName = "NetMsgs.cs"
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 = "public enum ClientMsgId{"
enumData = ""
for key in enumKeyList:
if key.find("MsgID") != -1:
msgIdData = msgIdData + "\n// " + 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 = "public enum " + 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 normalName(name)
def getMsgName(data):
msgIdList = re.findall(r"enum\s+(\w+MsgID)", data)
undefined = "/*\n"
msgData = "\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 + ("\tmsgMap.Add((int)ClientMsgId.%s, typeof(%s));\n") % (name, msg)
undefined = undefined + "*/"
msgData = msgData + "}"
return undefined + "\n" + msgData
if __name__ == '__main__':
protoc = os.path.join(CurDir, "protoc")
protoc = os.path.join(protoc, "protoc.exe")
protocolFile = os.path.join(CurDir, ProtoName)
# print("protoc", protoc)
# 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))
# cmd = "%s ./%s --csharp_out=%s" % (protoc, ProtoName, ProtocolDir)
# os.system(cmd)
fileData = getFileData(protocolFile)
enumData = getEnumData(fileData)
msgNameData = getMsgName(fileData)
fileWrite(os.path.join(ProtocolDir, MsgFileName), enumData + ClassHead + msgNameData)