341 lines
12 KiB
C#
Executable File
341 lines
12 KiB
C#
Executable File
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 Program
|
|
{
|
|
public static void Main()
|
|
{
|
|
// InnerMessage.proto生成cs代码
|
|
InnerProto2CS.Proto2CS();
|
|
|
|
Console.WriteLine("proto2cs succeed!");
|
|
}
|
|
}
|
|
|
|
public static class InnerProto2CS
|
|
{
|
|
private const string protoPath = "./";
|
|
private const string clientMessagePath = "../Unity/Assets/Hotfix/Logic/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", 10000);
|
|
GenerateOpcode("ET","InnerOpcode", "InnerOpcode", serverMessagePath);
|
|
|
|
Proto2CS("ET", "../Proto/InnerBsonMessage.proto", serverMessagePath, "InnerOpcode", 40000);
|
|
GenerateOpcode("ET", "InnerBsonOpcode","InnerOpcode", serverMessagePath);
|
|
|
|
Proto2CS("ET", "../Proto/OuterMessage.proto", serverMessagePath, "OuterOpcode", 20000);
|
|
GenerateOpcode("ET","OuterOpcode", "OuterOpcode", serverMessagePath);
|
|
|
|
Proto2CS("ET", "../Proto/OuterMessage.proto", clientMessagePath, "OuterOpcode", 20000);
|
|
GenerateOpcode("ET", "OuterOpcode","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;
|
|
string parentClass = "";
|
|
bool isEnumStart = false;
|
|
bool isOutEnumStart = 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(typeof({responseType}))]");
|
|
continue;
|
|
}
|
|
|
|
if (newline.StartsWith("//"))
|
|
{
|
|
sb.Append($"{newline}\n");
|
|
}
|
|
//IActorLocationResponse IActorResponse IResponse
|
|
string msgName = null;
|
|
parentClass = "";
|
|
if (newline.StartsWith("message"))
|
|
{
|
|
msgName = newline.Split(splitChars, StringSplitOptions.RemoveEmptyEntries)[1];
|
|
string[] ss = newline.Split(new[] { "//" }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
if (ss.Length == 2)
|
|
{
|
|
parentClass = ss[1].Trim();
|
|
//if (parentClass == "IActorLocationRequest" || parentClass == "IActorRequest" || parentClass == "IRequest")
|
|
//{
|
|
// string responseType = line.Split(" ")[1].TrimEnd('\r', '\n');
|
|
// Char char1 = responseType[0];
|
|
// Char char3 = responseType[2];
|
|
// responseType = char3 + "2" + char1 + responseType.Remove(0, 3);
|
|
// sb.AppendLine($"\t[ResponseType(typeof({responseType}))]");
|
|
//}
|
|
}
|
|
isMsgStart = true;
|
|
|
|
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}");
|
|
if (parentClass == "IActorMessage" || parentClass == "IActorRequest" || parentClass == "IActorResponse")
|
|
{
|
|
sb.Append($":{parentClass}\n");
|
|
}
|
|
else if (parentClass != "")
|
|
{
|
|
sb.Append($":{parentClass}\n");
|
|
}
|
|
else
|
|
{
|
|
sb.Append("\n");
|
|
}
|
|
|
|
continue;
|
|
}
|
|
if (isOutEnumStart&&newline == "{")
|
|
{
|
|
sb.Append("\t{\n");
|
|
continue;
|
|
}
|
|
|
|
if (isOutEnumStart&&newline == "}")
|
|
{
|
|
isOutEnumStart = false;
|
|
sb.Append("\t}\n\n");
|
|
continue;
|
|
}
|
|
if (newline.StartsWith("enum"))
|
|
{
|
|
isOutEnumStart = true;
|
|
sb.AppendLine("\tpublic " + line);
|
|
continue;
|
|
}
|
|
if (isOutEnumStart)
|
|
{
|
|
sb.AppendLine(line.Replace(';', ','));
|
|
continue;
|
|
}
|
|
if (isMsgStart)
|
|
{
|
|
if (newline == "{")
|
|
{
|
|
sb.Append("\t{\n");
|
|
continue;
|
|
}
|
|
|
|
if (newline == "}")
|
|
{
|
|
if (isEnumStart)
|
|
isEnumStart = false;
|
|
else
|
|
isMsgStart = false;
|
|
sb.Append("\t}\n\n");
|
|
continue;
|
|
}
|
|
|
|
if (newline.Trim().StartsWith("//"))
|
|
{
|
|
sb.AppendLine(newline);
|
|
continue;
|
|
}
|
|
|
|
if (newline.StartsWith("enum"))
|
|
{
|
|
isEnumStart = true;
|
|
sb.AppendLine("\tpublic "+line);
|
|
continue;
|
|
}
|
|
if (isEnumStart)
|
|
{
|
|
sb.AppendLine(line.Replace(';',','));
|
|
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 outputClassName, 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 {outputClassName}");
|
|
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[3]);
|
|
|
|
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 EnumMember(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[3]);
|
|
|
|
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 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[2]);
|
|
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}");
|
|
}
|
|
}
|
|
}
|
|
}
|