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.
271 lines
9.2 KiB
271 lines
9.2 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.IO; |
|
using System.Text; |
|
|
|
namespace ET |
|
{ |
|
internal class OpcodeInfo |
|
{ |
|
public string Name; |
|
public int Opcode; |
|
} |
|
|
|
public static class Proto2CS |
|
{ |
|
public static void Export() |
|
{ |
|
// InnerMessage.proto生成cs代码 |
|
InnerProto2CS.Proto2CS(); |
|
Log.Console("proto2cs succeed!"); |
|
} |
|
} |
|
|
|
public static class InnerProto2CS |
|
{ |
|
private const string protoPath = "."; |
|
private const string clientMessagePath = "../Unity/Codes/Model/Generate/Message/"; |
|
private const string serverMessagePath = "../Server/Model/Generate/Message/"; |
|
private static readonly char[] splitChars = { ' ', '\t' }; |
|
private static readonly List<OpcodeInfo> msgOpcode = new List<OpcodeInfo>(); |
|
|
|
public static void Proto2CS() |
|
{ |
|
msgOpcode.Clear(); |
|
Proto2CS("ET", "../Proto/InnerMessage.proto", serverMessagePath, "InnerOpcode", OpcodeRangeDefine.InnerMinOpcode); |
|
GenerateOpcode("ET", "InnerOpcode", serverMessagePath); |
|
|
|
Proto2CS("ET", "../Proto/MongoMessage.proto", serverMessagePath, "MongoOpcode", OpcodeRangeDefine.MongoMinOpcode); |
|
GenerateOpcode("ET", "MongoOpcode", serverMessagePath); |
|
|
|
Proto2CS("ET", "../Proto/OuterMessage.proto", serverMessagePath, "OuterOpcode", OpcodeRangeDefine.OuterMinOpcode); |
|
GenerateOpcode("ET", "OuterOpcode", serverMessagePath); |
|
|
|
Proto2CS("ET", "../Proto/OuterMessage.proto", clientMessagePath, "OuterOpcode", OpcodeRangeDefine.OuterMinOpcode); |
|
GenerateOpcode("ET", "OuterOpcode", clientMessagePath); |
|
} |
|
|
|
public static void Proto2CS(string ns, string protoName, string outputPath, string opcodeClassName, int startOpcode) |
|
{ |
|
if (!Directory.Exists(outputPath)) |
|
{ |
|
Directory.CreateDirectory(outputPath); |
|
} |
|
|
|
msgOpcode.Clear(); |
|
string proto = Path.Combine(protoPath, protoName); |
|
string csPath = Path.Combine(outputPath, Path.GetFileNameWithoutExtension(proto) + ".cs"); |
|
|
|
string s = File.ReadAllText(proto); |
|
|
|
StringBuilder sb = new StringBuilder(); |
|
sb.Append("using ET;\n"); |
|
sb.Append("using ProtoBuf;\n"); |
|
sb.Append("using System.Collections.Generic;\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("//ResponseType")) |
|
{ |
|
string responseType = line.Split(" ")[1].TrimEnd('\r', '\n'); |
|
sb.AppendLine($"\t[ResponseType(nameof({responseType}))]"); |
|
continue; |
|
} |
|
|
|
if (newline.StartsWith("//")) |
|
{ |
|
sb.Append($"{newline}\n"); |
|
continue; |
|
} |
|
|
|
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(); |
|
} |
|
|
|
msgOpcode.Add(new OpcodeInfo() { Name = msgName, Opcode = ++startOpcode }); |
|
|
|
sb.Append($"\t[Message({opcodeClassName}.{msgName})]\n"); |
|
sb.Append($"\t[ProtoContract]\n"); |
|
sb.Append($"\tpublic partial class {msgName}: Object"); |
|
if (parentClass == "IActorMessage" || parentClass == "IActorRequest" || parentClass == "IActorResponse") |
|
{ |
|
sb.Append($", {parentClass}\n"); |
|
} |
|
else if (parentClass != "") |
|
{ |
|
sb.Append($", {parentClass}\n"); |
|
} |
|
else |
|
{ |
|
sb.Append("\n"); |
|
} |
|
|
|
continue; |
|
} |
|
|
|
if (isMsgStart) |
|
{ |
|
if (newline == "{") |
|
{ |
|
sb.Append("\t{\n"); |
|
continue; |
|
} |
|
|
|
if (newline == "}") |
|
{ |
|
isMsgStart = false; |
|
sb.Append("\t}\n\n"); |
|
continue; |
|
} |
|
|
|
if (newline.Trim().StartsWith("//")) |
|
{ |
|
sb.AppendLine(newline); |
|
continue; |
|
} |
|
|
|
if (newline.Trim() != "" && newline != "}") |
|
{ |
|
if (newline.StartsWith("repeated")) |
|
{ |
|
Repeated(sb, ns, newline); |
|
} |
|
else |
|
{ |
|
Members(sb, newline, true); |
|
} |
|
} |
|
} |
|
} |
|
|
|
sb.Append("}\n"); |
|
using FileStream txt = new FileStream(csPath, FileMode.Create, FileAccess.ReadWrite); |
|
using StreamWriter sw = new StreamWriter(txt); |
|
sw.Write(sb.ToString()); |
|
} |
|
|
|
private static void GenerateOpcode(string ns, string outputFileName, string outputPath) |
|
{ |
|
if (!Directory.Exists(outputPath)) |
|
{ |
|
Directory.CreateDirectory(outputPath); |
|
} |
|
|
|
StringBuilder sb = new StringBuilder(); |
|
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"); |
|
|
|
using FileStream txt = new FileStream(csPath, FileMode.Create); |
|
using StreamWriter sw = new StreamWriter(txt); |
|
sw.Write(sb.ToString()); |
|
} |
|
|
|
private static void Repeated(StringBuilder sb, string ns, string newline) |
|
{ |
|
try |
|
{ |
|
int index = newline.IndexOf(";"); |
|
newline = newline.Remove(index); |
|
string[] ss = newline.Split(splitChars, StringSplitOptions.RemoveEmptyEntries); |
|
string type = ss[1]; |
|
type = ConvertType(type); |
|
string name = ss[2]; |
|
int n = int.Parse(ss[4]); |
|
|
|
sb.Append($"\t\t[ProtoMember({n})]\n"); |
|
sb.Append($"\t\tpublic List<{type}> {name} = new List<{type}>();\n\n"); |
|
} |
|
catch (Exception e) |
|
{ |
|
Console.WriteLine($"{newline}\n {e}"); |
|
} |
|
} |
|
|
|
private static string ConvertType(string type) |
|
{ |
|
string typeCs = ""; |
|
switch (type) |
|
{ |
|
case "int16": |
|
typeCs = "short"; |
|
break; |
|
case "int32": |
|
typeCs = "int"; |
|
break; |
|
case "bytes": |
|
typeCs = "byte[]"; |
|
break; |
|
case "uint32": |
|
typeCs = "uint"; |
|
break; |
|
case "long": |
|
typeCs = "long"; |
|
break; |
|
case "int64": |
|
typeCs = "long"; |
|
break; |
|
case "uint64": |
|
typeCs = "ulong"; |
|
break; |
|
case "uint16": |
|
typeCs = "ushort"; |
|
break; |
|
default: |
|
typeCs = type; |
|
break; |
|
} |
|
|
|
return typeCs; |
|
} |
|
|
|
private static void Members(StringBuilder sb, string newline, bool isRequired) |
|
{ |
|
try |
|
{ |
|
int index = newline.IndexOf(";"); |
|
newline = newline.Remove(index); |
|
string[] ss = newline.Split(splitChars, StringSplitOptions.RemoveEmptyEntries); |
|
string type = ss[0]; |
|
string name = ss[1]; |
|
int n = int.Parse(ss[3]); |
|
string typeCs = ConvertType(type); |
|
|
|
sb.Append($"\t\t[ProtoMember({n})]\n"); |
|
sb.Append($"\t\tpublic {typeCs} {name} {{ get; set; }}\n\n"); |
|
} |
|
catch (Exception e) |
|
{ |
|
Console.WriteLine($"{newline}\n {e}"); |
|
} |
|
} |
|
} |
|
} |