using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Text; namespace KeyraysFramework.Tools { internal class OpcodeInfo { public string Name; public int Opcode; } class Program { private const string protoPath = "."; private static readonly char[] splitChars = { ' ', '\t' }; private static readonly List msgOpcode = new List(); //对应服务端的代码路径 private const string messagePath = "../../../../KYNetwork/Message/"; //对应客户端的代码路径 //private const string messagePath = "../Assets/Scripts/Runtime/Message/"; static void Main(string[] args) { string protoc = ""; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) protoc = "protoc.exe"; else protoc = "protoc"; //对应服务端的代码路径 ProcessHelper.Run(protoc, $"--csharp_out={messagePath} --proto_path=\"./\" OuterMessage.proto", waitExit: true); Proto2CS("KYFramework.Network", "OuterMessage.proto", messagePath, "OuterOpcode", 100); Console.WriteLine("proto2cs succeed!"); } public static void Proto2CS(string ns, string protoName, string outputPath, string opcodeClassName, int startOpcode, bool isClient = true) { msgOpcode.Clear(); string proto = Path.Combine(protoPath, protoName); string s = File.ReadAllText(proto); StringBuilder sb = new StringBuilder(); //sb.Append("using KeyraysFramework.Network;\n"); sb.Append($"namespace {ns}\n"); sb.Append("{\n"); bool isMsgStart = false; foreach (string line in s.Split('\n')) { string newline = line.Trim(); if (newline == "") { continue; } if (newline.StartsWith("//")) { sb.Append($"{newline}\n"); } if (newline.StartsWith("message")) { string parentClass = ""; isMsgStart = true; string msgName = newline.Split(splitChars, StringSplitOptions.RemoveEmptyEntries)[1]; string[] ss = newline.Split(new[] { "//" }, StringSplitOptions.RemoveEmptyEntries); if (ss.Length == 2) { parentClass = ss[1].Trim(); } else { parentClass = ""; } msgOpcode.Add(new OpcodeInfo() { Name = msgName, Opcode = ++startOpcode }); sb.Append($"\t[Message({opcodeClassName}.{msgName})]\n"); sb.Append($"\tpublic partial class {msgName} "); if (parentClass != "") { sb.Append($": {parentClass} "); } sb.Append("{}\n\n"); } if (isMsgStart && newline == "}") { isMsgStart = false; } } sb.Append("}\n"); GenerateOpcode(ns, opcodeClassName, outputPath, sb); } private static void GenerateOpcode(string ns, string outputFileName, string outputPath, StringBuilder sb) { sb.AppendLine($"namespace {ns}"); sb.AppendLine("{"); sb.AppendLine($"\tpublic static partial class {outputFileName}"); sb.AppendLine("\t{"); foreach (OpcodeInfo info in msgOpcode) { sb.AppendLine($"\t\t public const ushort {info.Name} = {info.Opcode};"); } sb.AppendLine("\t}"); sb.AppendLine("}"); string csPath = Path.Combine(outputPath, outputFileName + ".cs"); File.WriteAllText(csPath, sb.ToString()); } } }