using System.Collections.Generic; using System.IO; using System.Text; using UnityEditor; using UnityEngine; public class BinaryMsgTool { [MenuItem("ProTool/AutoScript/BinaryMsg")] public static void BinaryMsg() { var binaryMsgProto = Application.dataPath + "../../jjbb_public/CreatePacketTool/BinaryMessage.proto"; var fileReader = new StreamReader(binaryMsgProto); var allClass = ReadAllClasses(fileReader, true); Debug.Log("allClass:" + allClass.Count); WriteBianryMsgInfoCs(allClass); fileReader.Close(); } [MenuItem("ProTool/AutoScript/BinaryLua")] public static void BinaryLua() { var binaryMsgProto = Application.dataPath + "../../jjbb_public/CreatePacketTool/BinaryMessage.proto"; var fileReader = new StreamReader(binaryMsgProto); var allClass = ReadAllClasses(fileReader, false, true); Debug.Log("allClass:" + allClass.Count); WriteBianryMsgInfoLua(allClass); fileReader.Close(); } private static List ReadAllClasses(StreamReader fileReader, bool csFile = false, bool luaFile = false) { var classes = new List(); while (!fileReader.EndOfStream) { var line = fileReader.ReadLine(); line = line.Trim(); if (line.StartsWith("//@")) if (csFile && !line.Contains("luaonly") || luaFile && !line.Contains("csonly")) { var readClass = ReadClass(fileReader, line); if (readClass != null) classes.Add(readClass); } } return classes; } private static MsgStrClass ReadClass(StreamReader fileReader, string sysIdLine) { var msgClass = new MsgStrClass(); //get sysID if (sysIdLine.Contains("sysid")) { var headLineSprit = sysIdLine.Split(' '); var sysIDSprit = headLineSprit[1].Split('='); var cmdIDSprit = headLineSprit[2].Split('='); msgClass.sysID = byte.Parse(sysIDSprit[1]); msgClass.cmdID = byte.Parse(cmdIDSprit[1]); } //get class name var nameLine = fileReader.ReadLine(); var nameLineSplit = nameLine.Split(' '); msgClass.msgName = nameLineSplit[1].Trim(); //get props var brackLine = fileReader.ReadLine(); if (!brackLine.Contains("{")) { Debug.LogError("类名下一行需紧跟大括号!!!"); Debug.LogError("大括号独立一行!!"); return null; } var bracketCnt = 1; while (bracketCnt > 0) { var lineStr = fileReader.ReadLine().Trim(); if (lineStr.Contains("{")) { ++bracketCnt; continue; } if (lineStr.Contains("}")) { --bracketCnt; continue; } //single prop if (!string.IsNullOrEmpty(lineStr)) msgClass.msgProps.Add(GetPropClass(lineStr)); } return msgClass; } private static MsgProp GetPropClass(string propStr) { var msgProp = new MsgProp(); var propSplit = propStr.Split(' '); if (propSplit[0].StartsWith("required")) msgProp.isList = false; else if (propSplit[0].StartsWith("repeated")) msgProp.isList = true; msgProp.baseType = propSplit[1].Trim(); msgProp.propName = propSplit[2].Trim(); return msgProp; } public class MsgProp { public string baseType; public bool isList; public string propName; } public class MsgStrClass { public byte cmdID; public string msgName; public List msgProps = new List(); public byte sysID; } #region cs private static void WriteBianryMsgInfoCs(List msgClasses) { //write BinaryMessageInfo var binaryInfoPath = Application.dataPath + "/Project/Script/GameLogic/NetWork/BinaryMessage/BinaryMessageInfo.cs"; var fileStream = new FileStream(binaryInfoPath, FileMode.Create, FileAccess.Write); fileStream.SetLength(0); var tempWriter = new StreamWriter(fileStream); var tempBasePath = Application.dataPath + "/Editor/AutoScript/Resources/BinaryMessageInfo.txt"; var tempClass = Application.dataPath + "/Editor/AutoScript/Resources/BinaryMessageClassTemp.txt"; var tempBaseReader = new StreamReader(tempBasePath); var tempBase = tempBaseReader.ReadToEnd(); var tempClassReader = new StreamReader(tempClass); var tempClassStr = tempClassReader.ReadToEnd(); tempWriter.Write(tempBase); for (var i = 0; i < msgClasses.Count; ++i) { var classStr = GetClassStrCS(msgClasses[i], tempClassStr); tempWriter.Write(classStr); tempWriter.WriteLine(); } tempWriter.Close(); //write BinaryMessageID var binaryIDPath = Application.dataPath + "/Project/Script/GameLogic/NetWork/BinaryMessage/BinaryMessageID.cs"; var msgIDfs = new FileStream(binaryIDPath, FileMode.Create, FileAccess.Write); msgIDfs.SetLength(0); var msgIDWriter = new StreamWriter(msgIDfs); var msgIDTemp = Application.dataPath + "/Project3D/Tool/Editor/AutoScript/Resources/BinaryMessageID.txt"; var msgIDReader = new StreamReader(msgIDTemp); var msgIDStr = msgIDReader.ReadToEnd(); var binaryDistribute = new Dictionary>(); for (var i = 0; i < msgClasses.Count; ++i) { if (!binaryDistribute.ContainsKey(msgClasses[i].sysID)) binaryDistribute.Add(msgClasses[i].sysID, new List()); binaryDistribute[msgClasses[i].sysID].Add(msgClasses[i]); } var msgIDInfo = ""; var msgHandles = ""; foreach (var distribute in binaryDistribute) { if (distribute.Key == 0) continue; var distibuteStr = ""; var distibuteHandleStr = ""; distibuteStr += "\t\tif (sysID == " + distribute.Key + ")\n"; distibuteStr += "\t\t{\n"; distibuteHandleStr = distibuteStr; foreach (var msgClass in distribute.Value) { distibuteStr += "\t\t\tif (cmdID == " + msgClass.cmdID + ")\n"; distibuteStr += "\t\t\t\treturn new " + msgClass.msgName + "();\n"; distibuteHandleStr += "\t\t\tif (cmdID == " + msgClass.cmdID + ")\n"; distibuteHandleStr += "\t\t\t\treturn new " + msgClass.msgName + "_Handle();\n"; } distibuteStr += "\t\t}\n"; distibuteHandleStr += "\t\t}\n"; msgIDInfo += distibuteStr; msgHandles += distibuteHandleStr; } msgIDStr = msgIDStr.Replace("{BinaryIDs}", msgIDInfo); msgIDStr = msgIDStr.Replace("{BinaryHandles}", msgHandles); msgIDWriter.Write(msgIDStr); msgIDWriter.Close(); //write BinaryMessageHandle for (var i = 0; i < msgClasses.Count; ++i) { if (msgClasses[i].sysID == 0) continue; WriteMsgHandle(msgClasses[i]); } } private static string GetClassStrCS(MsgStrClass msgClass, string tempStr) { var msgStr = tempStr; msgStr = msgStr.Replace("{ClassName}", msgClass.msgName); msgStr = msgStr.Replace("{sysIDValue}", msgClass.sysID.ToString()); msgStr = msgStr.Replace("{cmdIDValue}", msgClass.cmdID.ToString()); var propStr = ""; var propReadStr = ""; var propWriteStr = ""; for (var i = 0; i < msgClass.msgProps.Count; ++i) { var prop = ""; var propRead = ""; var propWrite = ""; var propBaseType = GetTypeStr(msgClass.msgProps[i].baseType); if (!msgClass.msgProps[i].isList) { prop = "\tpublic " + propBaseType + " " + msgClass.msgProps[i].propName + ";"; propRead = GetReadFuncStr(msgClass.msgProps[i].baseType, msgClass.msgProps[i].propName); propWrite = GetWriteFuncStr(msgClass.msgProps[i].baseType, msgClass.msgProps[i].propName, 2); } else { prop = "\tpublic List<" + propBaseType + "> " + msgClass.msgProps[i].propName + " = new List<" + GetTypeStr(msgClass.msgProps[i].baseType) + ">();"; var propReadFunc = GetReadFuncStr(msgClass.msgProps[i].baseType, "temp", true); propRead = "\t\tvar " + msgClass.msgProps[i].propName + "Cnt = binaryReader.ReadInt32();\n"; propRead += "\t\tfor (int i = 0; i < " + msgClass.msgProps[i].propName + "Cnt; ++i)\n"; propRead += "\t\t{\n"; propRead += "\t\t" + propReadFunc + "\n"; propRead += "\t\t" + msgClass.msgProps[i].propName + ".Add(temp);\n"; propRead += "\t\t}\n"; propWrite += "\t\tbinaryWriter.Write(" + msgClass.msgProps[i].propName + ".Count);\n"; propWrite += "\t\tfor (int i = 0; i < " + msgClass.msgProps[i].propName + ".Count; ++i)\n"; propWrite += "\t\t{\n"; propWrite += GetWriteFuncStr(msgClass.msgProps[i].baseType, msgClass.msgProps[i].propName + "[i]", 3) + "\n"; propWrite += "\t\t}\n"; } propStr += prop + "\n"; propReadStr += propRead + "\n"; propWriteStr += propWrite + "\n"; } msgStr = msgStr.Replace("{Proprites}", propStr); msgStr = msgStr.Replace("{ReadProps}", propReadStr); msgStr = msgStr.Replace("{WriteProps}", propWriteStr); return msgStr; } public static string GetTypeStr(string type) { if (type == "int32") return "Int32"; if (type == "int64") return "Int64"; return type; } public static string GetReadFuncStr(string type, string name, bool needConstruct = false) { var construct = ""; if (needConstruct) construct = "var "; if (type == "int32") return "\t\t" + construct + name + " = binaryReader.ReadInt32();"; if (type == "byte") return "\t\t" + construct + name + " = binaryReader.ReadByte();"; if (type == "string") return "\t\t" + construct + name + " = BinaryMessageHandle.ReadString(binaryReader);"; if (type == "int64") return "\t\t" + construct + name + " = binaryReader.ReadInt64();"; var structStr = "\t\t" + construct + name + " = new " + type + "();\n"; structStr += "\t\t" + name + ".ReadMsg(binaryReader);"; return structStr; } private static void AppendTab(StringBuilder builder, int count) { for (var i = 0; i < count; i++) builder.Append('\t'); } public static string GetWriteFuncStr(string type, string name, int tabCount) { var builder = new StringBuilder(); switch (type) { case "int32": case "byte": case "int64": AppendTab(builder, tabCount); builder.Append(string.Format("binaryWriter.Write({0});", name)); builder.Append('\n'); break; case "string": AppendTab(builder, tabCount); builder.Append('{'); builder.Append('\n'); AppendTab(builder, tabCount + 1); builder.Append(string.Format("var bytes = System.Text.Encoding.UTF8.GetBytes({0});", name)); builder.Append('\n'); AppendTab(builder, tabCount + 1); builder.Append("binaryWriter.Write((short)bytes.Length);"); builder.Append('\n'); AppendTab(builder, tabCount + 1); builder.Append("binaryWriter.Write(bytes);"); builder.Append('\n'); AppendTab(builder, tabCount + 1); builder.Append("binaryWriter.Write((byte)0);"); builder.Append('\n'); AppendTab(builder, tabCount); builder.Append('}'); builder.Append('\n'); break; //struct default: AppendTab(builder, tabCount); builder.Append(string.Format("{0}.WriteMsg(binaryWriter);", name)); builder.Append('\n'); break; } return builder.ToString(); } public static void WriteMsgHandle(MsgStrClass msgClass) { var fileName = Application.dataPath + "/Project/Script/GameLogic/NetWork/BinaryMessage/BinaryMsgHandles/" + msgClass.msgName + "_Handle.cs"; if (File.Exists(fileName)) return; var msgHandlefs = new FileStream(fileName, FileMode.Create, FileAccess.Write); msgHandlefs.SetLength(0); var msgHandleWriter = new StreamWriter(msgHandlefs); var msgIDTemp = Application.dataPath + "/Project3D/Tool/Editor/AutoScript/Resources/MsgHandleTemp.txt"; var msgIDReader = new StreamReader(msgIDTemp); var msgIDStr = msgIDReader.ReadToEnd(); var msgHandleStr = msgIDStr.Replace("{ClassName}", msgClass.msgName); msgHandleWriter.Write(msgHandleStr); msgHandleWriter.Close(); } #endregion #region lua private static void WriteBianryMsgInfoLua(List msgClasses) { //write BinaryMessageID var binaryIDPath = Application.dataPath + "/Project/Script/LuaScripts/NetWork/Lua/LuaMessageManager.txt"; var msgIDfs = new FileStream(binaryIDPath, FileMode.Create, FileAccess.Write); msgIDfs.SetLength(0); var msgIDWriter = new StreamWriter(msgIDfs); var msgIDTemp = Application.dataPath + "/Project3D/Tool/Editor/AutoScript/Resources/LuaMessageManager.txt"; var msgIDReader = new StreamReader(msgIDTemp); var msgIDStr = msgIDReader.ReadToEnd(); var binaryDistribute = new Dictionary>(); for (var i = 0; i < msgClasses.Count; ++i) { if (!binaryDistribute.ContainsKey(msgClasses[i].sysID)) binaryDistribute.Add(msgClasses[i].sysID, new List()); binaryDistribute[msgClasses[i].sysID].Add(msgClasses[i]); } var msgIDInfo = ""; foreach (var distribute in binaryDistribute) { if (distribute.Key == 0) continue; var distibuteStr = ""; distibuteStr += "\tif(sysID == " + distribute.Key + ") then\n"; for (var i = 0; i < distribute.Value.Count; ++i) { if (i == 0) distibuteStr += "\t\tif (cmdID == " + distribute.Value[i].cmdID + ") then\n"; else distibuteStr += "\t\telseif (cmdID == " + distribute.Value[i].cmdID + ") then\n"; var handleName = "LuaHandle" + distribute.Value[i].msgName; distibuteStr += "\t\t\trequire \"LuaHandle" + distribute.Value[i].msgName + "\"\n"; distibuteStr += "\t\t\t" + handleName + ".HandlePacket(binaryReader)\n"; } distibuteStr += "\t\tend\n"; distibuteStr += "\tend\n"; msgIDInfo += distibuteStr; } msgIDStr = msgIDStr.Replace("{ProMsg}", msgIDInfo); msgIDWriter.Write(msgIDStr); msgIDWriter.Close(); for (var i = 0; i < msgClasses.Count; ++i) { if (msgClasses[i].sysID == 0) continue; WriteMsgHandleLua(msgClasses[i]); } for (var i = 0; i < msgClasses.Count; ++i) WriteMsgExtraLua(msgClasses[i], msgClasses); } private static void WriteMsgHandleLua(MsgStrClass msgClass) { var fileName = Application.dataPath + "/Project/Script/LuaScripts/NetWork/Lua/Handle/LuaHandle" + msgClass.msgName + ".txt"; if (File.Exists(fileName)) return; var msgHandlefs = new FileStream(fileName, FileMode.Create, FileAccess.Write); msgHandlefs.SetLength(0); var msgHandleWriter = new StreamWriter(msgHandlefs); var msgIDTemp = Application.dataPath + "/Project3D/Tool/Editor/AutoScript/Resources/LuaHandleTemp.txt"; var msgIDReader = new StreamReader(msgIDTemp); var msgIDStr = msgIDReader.ReadToEnd(); var msgHandleStr = msgIDStr.Replace("{ClassName}", msgClass.msgName); msgHandleWriter.Write(msgHandleStr); msgHandleWriter.Close(); } private static void WriteMsgExtraLua(MsgStrClass msgClass, List msgClasses) { var fileName = Application.dataPath + "/Project/Script/LuaScripts/NetWork/Lua/Distributes/LuaDistributes" + msgClass.msgName + ".txt"; var msgHandlefs = new FileStream(fileName, FileMode.Create, FileAccess.Write); msgHandlefs.SetLength(0); var msgHandleWriter = new StreamWriter(msgHandlefs); var msgDistributeTemp = Application.dataPath + "/Project3D/Tool/Editor/AutoScript/Resources/LuaDistributesTemp.txt"; var msgDistributeReader = new StreamReader(msgDistributeTemp); var msgDistributeStr = msgDistributeReader.ReadToEnd(); msgDistributeStr = msgDistributeStr.Replace("{sysID}", msgClass.sysID.ToString()); msgDistributeStr = msgDistributeStr.Replace("{cmdID}", msgClass.cmdID.ToString()); msgDistributeStr = msgDistributeStr.Replace("{ClassName}", msgClass.msgName); var readLuaStr = ""; var writeLuaStr = ""; for (var i = 0; i < msgClass.msgProps.Count; ++i) if (!msgClass.msgProps[i].isList) { var nameFormat = string.Format("packet['{0}']", msgClass.msgProps[i].propName); readLuaStr += GetReadFuncLua(msgClass.msgProps[i].baseType, nameFormat, msgClasses); readLuaStr += "\n\n"; writeLuaStr += GetWriteFuncLua(msgClass.msgProps[i].baseType, nameFormat); writeLuaStr += "\n\n"; } else { readLuaStr += "packet['" + msgClass.msgProps[i].propName + "'] = {}\n"; readLuaStr += string.Format("local {0}Cnt = binaryReader:ReadInt32()\n", msgClass.msgProps[i].propName); readLuaStr += string.Format("for i=1,{0}Cnt,1 do\n", msgClass.msgProps[i].propName); var nameFormat = "packet['" + msgClass.msgProps[i].propName + "'][i]"; readLuaStr += GetReadFuncLua(msgClass.msgProps[i].baseType, nameFormat, msgClasses); readLuaStr += "\nend\n"; writeLuaStr += string.Format("if({0} == nil) then\n", msgClass.msgProps[i].propName); writeLuaStr += "\t" + msgClass.msgProps[i].propName + " = {}\nend\n"; writeLuaStr += string.Format("message:WriteInt(#packet['{0}'])\n", msgClass.msgProps[i].propName); writeLuaStr += string.Format("for k,v in ipairs(packet['{0}']) do\n", msgClass.msgProps[i].propName); writeLuaStr += GetWriteFuncLua(msgClass.msgProps[i].baseType, "v"); writeLuaStr += "\nend\n\n"; } msgDistributeStr = msgDistributeStr.Replace("{ReadPacket}", readLuaStr); msgDistributeStr = msgDistributeStr.Replace("{WritePacket}", writeLuaStr); msgHandleWriter.Write(msgDistributeStr); msgHandleWriter.Close(); } public static string GetReadFuncLua(string type, string name, List structs) { if (type == "int32") return name + " = binaryReader:ReadInt32()"; if (type == "byte") return name + " = binaryReader:ReadByte()"; if (type == "string") return name + " = CS.BinaryMessageHandle.ReadString(binaryReader)"; if (type == "int64") return name + " = binaryReader:ReadInt64()"; var structStr = string.Format("require \"LuaDistributes{0}\"\n", type); structStr += name + " = LuaDistributes" + type + ".ReadPacket(binaryReader)\n"; return structStr; } public static string GetWriteFuncLua(string type, string name) { if (type == "int32") { var writeStr = ""; writeStr += string.Format("if({0} == nil) then\n", name); writeStr += string.Format("\t{0} = 0\nend\n", name); writeStr += string.Format("message:WriteInt({0})", name); return writeStr; } if (type == "byte") { var writeStr = ""; writeStr += string.Format("if({0} == nil) then\n", name); writeStr += string.Format("\t{0} = 0\nend\n", name); writeStr += string.Format("message:WriteByte({0})", name); return writeStr; } if (type == "string") { var writeStr = ""; writeStr += string.Format("if({0} == nil) then\n", name); writeStr += string.Format("\t{0} = \"\"\nend\n", name); writeStr += string.Format("message:WriteString({0})", name); return writeStr; } if (type == "int64") { var writeStr = ""; writeStr += string.Format("if({0} == nil) then\n", name); writeStr += string.Format("\t{0} = 0\nend\n", name); writeStr += string.Format("message:WriteLong({0})", name); return writeStr; } else //struct { //writeStr += string.Format("if({0} == nil) then\n", name); //writeStr += "\t" + name + " = {}\nend\n"; //writeStr += string.Format("CS.BinaryMessageHandle.LuaWriteInt64(binaryWriter, {0})/n", name); var writeStr = string.Format("require \"LuaDistributes{0}\"\n", type); writeStr += "LuaDistributes" + type + ".WritePacket(" + name + ", binaryWriter)\n"; return writeStr; } } #endregion }