框架更新
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
namespace Fantasy.Tools.ProtocalExporter;
|
||||
|
||||
public static class NetworkProtocolTemplate
|
||||
{
|
||||
private static string? _cachedTemplate;
|
||||
|
||||
public static string Template
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_cachedTemplate != null)
|
||||
{
|
||||
return _cachedTemplate;
|
||||
}
|
||||
|
||||
// 尝试从多个位置读取模板文件
|
||||
var possiblePaths = new[]
|
||||
{
|
||||
Path.Combine(ExporterAges.Instance.Folder ?? Directory.GetCurrentDirectory(), "NetworkProtocolTemplate.txt"),
|
||||
Path.Combine(Directory.GetCurrentDirectory(), "NetworkProtocolTemplate.txt"),
|
||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "NetworkProtocolTemplate.txt")
|
||||
};
|
||||
|
||||
foreach (var path in possiblePaths)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
_cachedTemplate = File.ReadAllText(path);
|
||||
return _cachedTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
throw new FileNotFoundException("找不到 NetworkProtocolTemplate.txt 模板文件!\n" +
|
||||
"请确保模板文件位于以下位置之一:\n" +
|
||||
string.Join("\n", possiblePaths));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ using Fantasy.Helper;
|
||||
using Fantasy.Network;
|
||||
using OpCode = Fantasy.Network.OpCode;
|
||||
using OpCodeType = Fantasy.Network.OpCodeType;
|
||||
|
||||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
||||
// ReSharper disable PossibleNullReferenceException
|
||||
@@ -14,19 +13,38 @@ using OpCodeType = Fantasy.Network.OpCodeType;
|
||||
|
||||
namespace Fantasy.Tools.ProtocalExporter;
|
||||
|
||||
// 自定义异常,用于协议格式错误
|
||||
public class ProtocolFormatException : Exception
|
||||
{
|
||||
public ProtocolFormatException(string message) : base(message) { }
|
||||
}
|
||||
|
||||
public enum NetworkProtocolOpCodeType
|
||||
{
|
||||
None = 0,
|
||||
Outer = 1,
|
||||
Inner = 2,
|
||||
}
|
||||
|
||||
public sealed class OpcodeInfo
|
||||
{
|
||||
public uint Code;
|
||||
public string Name;
|
||||
}
|
||||
|
||||
public sealed class MessageFieldInfo
|
||||
{
|
||||
public string FieldName;
|
||||
public string FieldType;
|
||||
}
|
||||
|
||||
public sealed class MessageHelperInfo
|
||||
{
|
||||
public string MessageName;
|
||||
public string MessageType; // "IMessage" or "IRequest"
|
||||
public string ResponseType; // Only for IRequest
|
||||
public List<MessageFieldInfo> Fields = new(); // 消息的属性字段
|
||||
}
|
||||
|
||||
public sealed class ProtocolExporter
|
||||
{
|
||||
private string _serverTemplate;
|
||||
@@ -38,13 +56,12 @@ public sealed class ProtocolExporter
|
||||
private readonly string _networkProtocolServerDirectory;
|
||||
private readonly string _networkProtocolDirectoryOuter;
|
||||
private readonly string _networkProtocolDirectoryInner;
|
||||
|
||||
|
||||
public ProtocolExporter()
|
||||
{
|
||||
Console.OutputEncoding = Encoding.UTF8;
|
||||
|
||||
if (ExporterSettingsHelper.NetworkProtocolDirectory == null ||
|
||||
ExporterSettingsHelper.NetworkProtocolDirectory.Trim() == "")
|
||||
|
||||
if (ExporterSettingsHelper.NetworkProtocolDirectory == null || ExporterSettingsHelper.NetworkProtocolDirectory.Trim() == "")
|
||||
{
|
||||
Log.Info($"NetworkProtocolDirectory Can not be empty!");
|
||||
return;
|
||||
@@ -123,12 +140,21 @@ public sealed class ProtocolExporter
|
||||
var errorCodeStr = new StringBuilder();
|
||||
var usingNamespace = new HashSet<string>();
|
||||
var saveDirectory = new Dictionary<string, string>();
|
||||
var helperInfos = new List<MessageHelperInfo>();
|
||||
|
||||
OpcodeInfo opcodeInfo = null;
|
||||
ProtocolOpCode protocolOpCode = null;
|
||||
string[] protocolFiles = null;
|
||||
_opcodes.Clear();
|
||||
MessageHelperInfo currentHelperInfo = null; // 当前正在处理的消息Helper信息
|
||||
|
||||
// 格式检测相关
|
||||
var allMessageNames = new HashSet<string>(); // 所有消息名称
|
||||
var currentFieldNames = new HashSet<string>(); // 当前消息的字段名
|
||||
var currentFieldNumbers = new HashSet<int>(); // 当前消息的字段编号
|
||||
var currentFilePath = ""; // 当前处理的文件路径
|
||||
|
||||
_opcodes.Clear();
|
||||
|
||||
switch (opCodeType)
|
||||
{
|
||||
case NetworkProtocolOpCodeType.Outer:
|
||||
@@ -137,12 +163,12 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
saveDirectory.Add(_networkProtocolServerDirectory, _serverTemplate);
|
||||
}
|
||||
|
||||
|
||||
if (ExporterAges.Instance.ExportPlatform.HasFlag(ExportPlatform.Client))
|
||||
{
|
||||
saveDirectory.Add(_networkProtocolClientDirectory, _clientTemplate);
|
||||
}
|
||||
|
||||
|
||||
protocolOpCode = new ProtocolOpCode()
|
||||
{
|
||||
Message = OpCodeType.OuterMessage,
|
||||
@@ -162,8 +188,7 @@ public sealed class ProtocolExporter
|
||||
RoamingResponse = OpCodeType.OuterRoamingResponse,
|
||||
};
|
||||
opCodeName = "OuterOpcode";
|
||||
protocolFiles = FileHelper.GetDirectoryFile(_networkProtocolDirectoryOuter, "*.proto",
|
||||
SearchOption.AllDirectories);
|
||||
protocolFiles = FileHelper.GetDirectoryFile(_networkProtocolDirectoryOuter, "*.proto", SearchOption.AllDirectories);
|
||||
break;
|
||||
}
|
||||
case NetworkProtocolOpCodeType.Inner:
|
||||
@@ -188,8 +213,7 @@ public sealed class ProtocolExporter
|
||||
};
|
||||
opCodeName = "InnerOpcode";
|
||||
saveDirectory.Add(_networkProtocolServerDirectory, _serverTemplate);
|
||||
protocolFiles = FileHelper.GetDirectoryFile(_networkProtocolDirectoryInner, "*.proto",
|
||||
SearchOption.AllDirectories);
|
||||
protocolFiles = FileHelper.GetDirectoryFile(_networkProtocolDirectoryInner, "*.proto", SearchOption.AllDirectories);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -198,11 +222,12 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#region GenerateFiles
|
||||
|
||||
foreach (var filePath in protocolFiles)
|
||||
{
|
||||
currentFilePath = filePath; // 记录当前文件路径
|
||||
var keyIndex = 1;
|
||||
var parameter = "";
|
||||
var hasOpCode = false;
|
||||
@@ -227,8 +252,7 @@ public sealed class ProtocolExporter
|
||||
|
||||
if (currentLine.StartsWith("///"))
|
||||
{
|
||||
messageStr.AppendFormat(" /// <summary>\r\n" + " /// {0}\r\n" + " /// </summary>\r\n",
|
||||
currentLine.Substring("///".Length));
|
||||
messageStr.AppendFormat(" /// <summary>\r\n" + " /// {0}\r\n" + " /// </summary>\r\n", currentLine.Substring("///".Length));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -247,15 +271,6 @@ public sealed class ProtocolExporter
|
||||
protocolOpCodeType = OpCodeProtocolType.ProtoBuf;
|
||||
break;
|
||||
}
|
||||
// case "MemoryPack":
|
||||
// {
|
||||
// keyIndex = 0;
|
||||
// protocolType = "\t[MemoryPackable]";
|
||||
// protocolIgnore = "\t\t[MemoryPackIgnore]";
|
||||
// protocolMember = "MemoryPackOrder";
|
||||
// // protocolOpCodeType = OpCodeProtocolType.MemoryPack;
|
||||
// break;
|
||||
// }
|
||||
case "Bson":
|
||||
{
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
@@ -263,7 +278,6 @@ public sealed class ProtocolExporter
|
||||
Log.Error("Under Outer, /// does not support the Bson protocol!");
|
||||
return;
|
||||
}
|
||||
|
||||
protocolType = null;
|
||||
protocolIgnore = "\t\t[BsonIgnore]";
|
||||
protocolMember = null;
|
||||
@@ -293,6 +307,21 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
isMsgHead = true;
|
||||
className = currentLine.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries)[1];
|
||||
|
||||
// 检测消息名称是否重复
|
||||
if (!allMessageNames.Add(className))
|
||||
{
|
||||
var errorMsg = $"协议格式错误!\n文件: {currentFilePath}\n消息名称重复: {className}";
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(errorMsg);
|
||||
Console.ResetColor();
|
||||
throw new ProtocolFormatException(errorMsg);
|
||||
}
|
||||
|
||||
// 清空当前消息的字段集合
|
||||
currentFieldNames.Clear();
|
||||
currentFieldNumbers.Clear();
|
||||
|
||||
var splits = currentLine.Split(new[] { "//" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (isSetProtocol)
|
||||
@@ -306,12 +335,11 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
messageStr.AppendLine("\t[ProtoContract]");
|
||||
}
|
||||
|
||||
|
||||
if (splits.Length > 1)
|
||||
{
|
||||
hasOpCode = true;
|
||||
var parameterArray = currentLine.Split(new[] { "//" }, StringSplitOptions.RemoveEmptyEntries)[1]
|
||||
.Trim().Split(',');
|
||||
var parameterArray = currentLine.Split(new[] { "//" }, StringSplitOptions.RemoveEmptyEntries)[1].Trim().Split(',');
|
||||
parameter = parameterArray[0].Trim();
|
||||
opcodeInfo = new OpcodeInfo()
|
||||
{
|
||||
@@ -339,15 +367,12 @@ public sealed class ProtocolExporter
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
responseTypeStr = parameterArray[1].Trim();
|
||||
customRouteType = parameter.Contains("IRoaming")
|
||||
? $"Fantasy.RoamingType.{parameterArray[2].Trim()}"
|
||||
: $"Fantasy.RouteType.{parameterArray[2].Trim()}";
|
||||
customRouteType = parameter.Contains("IRoaming") ? $"Fantasy.RoamingType.{parameterArray[2].Trim()}" : $"Fantasy.RouteType.{parameterArray[2].Trim()}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -361,11 +386,6 @@ public sealed class ProtocolExporter
|
||||
messageStr.Append(string.IsNullOrWhiteSpace(parameter)
|
||||
? $"\tpublic partial class {className} : AMessage"
|
||||
: $"\tpublic partial class {className} : AMessage, {parameter}");
|
||||
if (protocolMember == "ProtoMember")
|
||||
{
|
||||
messageStr.Append(", IProto");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -380,22 +400,33 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
messageStr.AppendLine("\n\t{");
|
||||
messageStr.AppendLine($"\t\tpublic static {className} Create(Scene scene)");
|
||||
messageStr.AppendLine(
|
||||
$"\t\t{{\n\t\t\treturn scene.MessagePoolComponent.Rent<{className}>();\n\t\t}}");
|
||||
messageStr.AppendLine($"\t\t{{\n\t\t\treturn scene.MessagePoolComponent.Rent<{className}>();\n\t\t}}");
|
||||
messageStr.AppendLine($"\t\tpublic override void Dispose()");
|
||||
messageStr.AppendLine($"\t\t{{");
|
||||
messageStr.AppendLine(
|
||||
$"<<<<Dispose>>>#if FANTASY_NET || FANTASY_UNITY\n\t\t\tGetScene().MessagePoolComponent.Return<{className}>(this);\n#endif");
|
||||
messageStr.AppendLine($"<<<<Dispose>>>#if FANTASY_NET || FANTASY_UNITY\n\t\t\tGetScene().MessagePoolComponent.Return<{className}>(this);\n#endif");
|
||||
messageStr.AppendLine($"\t\t}}");
|
||||
|
||||
if (parameter == "IMessage")
|
||||
{
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.Message,
|
||||
protocolOpCode.AMessage++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.Message, protocolOpCode.AMessage++);
|
||||
messageStr.AppendLine($"\t\tpublic uint OpCode() {{ return {opCodeName}.{className}; }}");
|
||||
|
||||
// 收集客户端Helper信息
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
currentHelperInfo = new MessageHelperInfo
|
||||
{
|
||||
MessageName = className,
|
||||
MessageType = "IMessage"
|
||||
};
|
||||
helperInfos.Add(currentHelperInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 保存 responseTypeStr 用于后续收集Helper信息
|
||||
var savedResponseType = responseTypeStr;
|
||||
|
||||
if (responseTypeStr != null)
|
||||
{
|
||||
messageStr.AppendLine(protocolIgnore);
|
||||
@@ -413,8 +444,7 @@ public sealed class ProtocolExporter
|
||||
|
||||
if (hasOpCode)
|
||||
{
|
||||
messageStr.AppendLine(
|
||||
$"\t\tpublic uint OpCode() {{ return {opCodeName}.{className}; }}");
|
||||
messageStr.AppendLine($"\t\tpublic uint OpCode() {{ return {opCodeName}.{className}; }}");
|
||||
}
|
||||
|
||||
if (customRouteType != null)
|
||||
@@ -428,19 +458,28 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
case "IRequest":
|
||||
{
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.Request,
|
||||
protocolOpCode.ARequest++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.Request, protocolOpCode.ARequest++);
|
||||
|
||||
// 收集客户端Helper信息
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
currentHelperInfo = new MessageHelperInfo
|
||||
{
|
||||
MessageName = className,
|
||||
MessageType = "IRequest",
|
||||
ResponseType = savedResponseType
|
||||
};
|
||||
helperInfos.Add(currentHelperInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "IResponse":
|
||||
{
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.Response,
|
||||
protocolOpCode.AResponse++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.Response, protocolOpCode.AResponse++);
|
||||
if (!string.IsNullOrEmpty(protocolMember))
|
||||
{
|
||||
errorCodeStr.AppendLine($"\t\t[{protocolMember}(ErrorCodeKeyIndex)]");
|
||||
}
|
||||
|
||||
errorCodeStr.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
|
||||
disposeStr.AppendLine($"\t\t\tErrorCode = default;");
|
||||
break;
|
||||
@@ -451,28 +490,44 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
case "IAddressableRouteMessage":
|
||||
{
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.AddressableMessage,
|
||||
protocolOpCode.AAddressableMessage++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.AddressableMessage, protocolOpCode.AAddressableMessage++);
|
||||
|
||||
// 收集客户端Helper信息
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
currentHelperInfo = new MessageHelperInfo
|
||||
{
|
||||
MessageName = className,
|
||||
MessageType = "IMessage" // IAddressableRouteMessage也是Send方式
|
||||
};
|
||||
helperInfos.Add(currentHelperInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "IAddressableRouteRequest":
|
||||
{
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.AddressableRequest,
|
||||
protocolOpCode.AAddressableRequest++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.AddressableRequest, protocolOpCode.AAddressableRequest++);
|
||||
|
||||
// 收集客户端Helper信息
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
currentHelperInfo = new MessageHelperInfo
|
||||
{
|
||||
MessageName = className,
|
||||
MessageType = "IRequest",
|
||||
ResponseType = savedResponseType
|
||||
};
|
||||
helperInfos.Add(currentHelperInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "IAddressableRouteResponse":
|
||||
{
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.AddressableResponse,
|
||||
protocolOpCode.AAddressableResponse++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.AddressableResponse, protocolOpCode.AAddressableResponse++);
|
||||
if (!string.IsNullOrEmpty(protocolMember))
|
||||
{
|
||||
errorCodeStr.AppendLine($"\t\t[{protocolMember}(ErrorCodeKeyIndex)]");
|
||||
}
|
||||
|
||||
errorCodeStr.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
|
||||
disposeStr.AppendLine($"\t\t\tErrorCode = default;");
|
||||
break;
|
||||
@@ -481,44 +536,54 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Inner)
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
"Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
throw new NotSupportedException("Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
}
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.CustomRouteMessage, protocolOpCode.ACustomRouteMessage++);
|
||||
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.CustomRouteMessage,
|
||||
protocolOpCode.ACustomRouteMessage++);
|
||||
// 收集客户端Helper信息
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
currentHelperInfo = new MessageHelperInfo
|
||||
{
|
||||
MessageName = className,
|
||||
MessageType = "IMessage" // ICustomRouteMessage也是Send方式
|
||||
};
|
||||
helperInfos.Add(currentHelperInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ICustomRouteRequest":
|
||||
{
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Inner)
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
"Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
throw new NotSupportedException("Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
}
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.CustomRouteRequest, protocolOpCode.ACustomRouteRequest++);
|
||||
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.CustomRouteRequest,
|
||||
protocolOpCode.ACustomRouteRequest++);
|
||||
// 收集客户端Helper信息
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
currentHelperInfo = new MessageHelperInfo
|
||||
{
|
||||
MessageName = className,
|
||||
MessageType = "IRequest",
|
||||
ResponseType = savedResponseType
|
||||
};
|
||||
helperInfos.Add(currentHelperInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ICustomRouteResponse":
|
||||
{
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Inner)
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
"Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
throw new NotSupportedException("Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
}
|
||||
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.CustomRouteResponse,
|
||||
protocolOpCode.ACustomRouteResponse++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.CustomRouteResponse, protocolOpCode.ACustomRouteResponse++);
|
||||
if (!string.IsNullOrEmpty(protocolMember))
|
||||
{
|
||||
errorCodeStr.AppendLine($"\t\t[{protocolMember}(ErrorCodeKeyIndex)]");
|
||||
}
|
||||
|
||||
errorCodeStr.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
|
||||
disposeStr.AppendLine($"\t\t\tErrorCode = default;");
|
||||
break;
|
||||
@@ -529,8 +594,18 @@ public sealed class ProtocolExporter
|
||||
// {
|
||||
// throw new NotSupportedException("Under Inner, /// does not support the IRoamingMessage!");
|
||||
// }
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.RoamingMessage, protocolOpCode.ARoamingMessage++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.RoamingMessage, protocolOpCode.ARoamingMessage++);
|
||||
|
||||
// 收集客户端Helper信息
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
currentHelperInfo = new MessageHelperInfo
|
||||
{
|
||||
MessageName = className,
|
||||
MessageType = "IMessage" // IRoamingMessage也是Send方式
|
||||
};
|
||||
helperInfos.Add(currentHelperInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "IRoamingRequest":
|
||||
@@ -539,8 +614,19 @@ public sealed class ProtocolExporter
|
||||
// {
|
||||
// throw new NotSupportedException("Under Inner, /// does not support the IRoamingRequest!");
|
||||
// }
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.RoamingRequest, protocolOpCode.ARoamingRequest++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.RoamingRequest, protocolOpCode.ARoamingRequest++);
|
||||
|
||||
// 收集客户端Helper信息
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
currentHelperInfo = new MessageHelperInfo
|
||||
{
|
||||
MessageName = className,
|
||||
MessageType = "IRequest",
|
||||
ResponseType = savedResponseType
|
||||
};
|
||||
helperInfos.Add(currentHelperInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "IRoamingResponse":
|
||||
@@ -549,13 +635,11 @@ public sealed class ProtocolExporter
|
||||
// {
|
||||
// throw new NotSupportedException("Under Inner, /// does not support the IRoamingResponse!");
|
||||
// }
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.RoamingResponse, protocolOpCode.ARoamingResponse++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.RoamingResponse, protocolOpCode.ARoamingResponse++);
|
||||
if (!string.IsNullOrEmpty(protocolMember))
|
||||
{
|
||||
errorCodeStr.AppendLine($"\t\t[{protocolMember}(ErrorCodeKeyIndex)]");
|
||||
}
|
||||
|
||||
errorCodeStr.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
|
||||
disposeStr.AppendLine($"\t\t\tErrorCode = default;");
|
||||
break;
|
||||
@@ -564,41 +648,31 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
"Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
throw new NotSupportedException("Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
}
|
||||
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.RouteMessage, protocolOpCode.ARouteMessage++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.RouteMessage, protocolOpCode.ARouteMessage++);
|
||||
break;
|
||||
}
|
||||
case "IRouteRequest":
|
||||
{
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
"Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
throw new NotSupportedException("Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
}
|
||||
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.RouteRequest, protocolOpCode.ARouteRequest++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.RouteRequest, protocolOpCode.ARouteRequest++);
|
||||
break;
|
||||
}
|
||||
case "IRouteResponse":
|
||||
{
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer)
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
"Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
throw new NotSupportedException("Under Inner, /// does not support the ICustomRouteMessage!");
|
||||
}
|
||||
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType,
|
||||
protocolOpCode.RouteResponse, protocolOpCode.ARouteResponse++);
|
||||
opcodeInfo.Code = OpCode.Create(protocolOpCodeType, protocolOpCode.RouteResponse, protocolOpCode.ARouteResponse++);
|
||||
if (!string.IsNullOrEmpty(protocolMember))
|
||||
{
|
||||
errorCodeStr.AppendLine($"\t\t[{protocolMember}(ErrorCodeKeyIndex)]");
|
||||
}
|
||||
|
||||
errorCodeStr.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
|
||||
disposeStr.AppendLine($"\t\t\tErrorCode = default;");
|
||||
break;
|
||||
@@ -620,6 +694,7 @@ public sealed class ProtocolExporter
|
||||
case "}":
|
||||
{
|
||||
isMsgHead = false;
|
||||
currentHelperInfo = null; // 清空当前Helper信息
|
||||
errorCodeStr = errorCodeStr.Replace("ErrorCodeKeyIndex", keyIndex.ToString());
|
||||
messageStr = messageStr.Replace("<<<<Dispose>>>", disposeStr.ToString());
|
||||
messageStr.Append(errorCodeStr);
|
||||
@@ -643,28 +718,35 @@ public sealed class ProtocolExporter
|
||||
|
||||
if (currentLine.StartsWith("//"))
|
||||
{
|
||||
messageStr.AppendFormat("\t\t///<summary>\r\n" + "\t\t/// {0}\r\n" + "\t\t///</summary>\r\n",
|
||||
currentLine.TrimStart('/', '/'));
|
||||
messageStr.AppendFormat("\t\t///<summary>\r\n" + "\t\t/// {0}\r\n" + "\t\t///</summary>\r\n", currentLine.TrimStart('/', '/'));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentLine.StartsWith("repeated"))
|
||||
if (currentLine.StartsWith("repeatedArray"))
|
||||
{
|
||||
Repeated(messageStr, disposeStr, currentLine, protocolMember, ref keyIndex);
|
||||
Repeated(messageStr, disposeStr, currentLine, protocolMember, ref keyIndex, currentHelperInfo, "repeatedArray", className, currentFilePath, currentFieldNames, currentFieldNumbers);
|
||||
}
|
||||
else if (currentLine.StartsWith("repeatedList"))
|
||||
{
|
||||
Repeated(messageStr, disposeStr, currentLine, protocolMember, ref keyIndex, currentHelperInfo, "repeatedList", className, currentFilePath, currentFieldNames, currentFieldNumbers);
|
||||
}
|
||||
else if (currentLine.StartsWith("repeated"))
|
||||
{
|
||||
Repeated(messageStr, disposeStr, currentLine, protocolMember, ref keyIndex, currentHelperInfo, "repeated", className, currentFilePath, currentFieldNames, currentFieldNumbers);
|
||||
}
|
||||
else
|
||||
{
|
||||
Members(messageStr, disposeStr, currentLine, protocolMember, ref keyIndex);
|
||||
Members(messageStr, disposeStr, currentLine, protocolMember, ref keyIndex, currentHelperInfo, className, currentFilePath, currentFieldNames, currentFieldNumbers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var namespaceBuilder = new StringBuilder();
|
||||
|
||||
|
||||
foreach (var @namespace in usingNamespace)
|
||||
{
|
||||
namespaceBuilder.Append($"using {@namespace};\n");
|
||||
}
|
||||
|
||||
|
||||
var csName = $"{Path.GetFileNameWithoutExtension(filePath)}.cs";
|
||||
foreach (var (directory, template) in saveDirectory)
|
||||
{
|
||||
@@ -673,12 +755,25 @@ public sealed class ProtocolExporter
|
||||
content = content.Replace("(UsingNamespace)", namespaceBuilder.ToString());
|
||||
await File.WriteAllTextAsync(csFile, content);
|
||||
}
|
||||
|
||||
file.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GenerateNetworkProtocolHelper
|
||||
|
||||
// 为客户端生成NetworkProtocolHelper
|
||||
if (opCodeType == NetworkProtocolOpCodeType.Outer &&
|
||||
ExporterAges.Instance.ExportPlatform.HasFlag(ExportPlatform.Client) &&
|
||||
helperInfos.Count > 0)
|
||||
{
|
||||
var helperContent = GenerateNetworkProtocolHelperFile(helperInfos);
|
||||
var helperFilePath = Path.Combine(_networkProtocolClientDirectory, "NetworkProtocolHelper.cs");
|
||||
await File.WriteAllTextAsync(helperFilePath, helperContent);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GenerateOpCode
|
||||
|
||||
file.Clear();
|
||||
@@ -691,7 +786,7 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
file.AppendLine($"\t\t public const uint {opcode.Name} = {opcode.Code};");
|
||||
}
|
||||
|
||||
|
||||
_opcodes.Clear();
|
||||
file.AppendLine("\t}");
|
||||
file.AppendLine("}");
|
||||
@@ -701,12 +796,10 @@ public sealed class ProtocolExporter
|
||||
var csFile = Path.Combine(directory, $"{opCodeName}.cs");
|
||||
await File.WriteAllTextAsync(csFile, file.ToString());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
private void Repeated(StringBuilder file, StringBuilder disposeStr, string newline, string protocolMember,
|
||||
ref int keyIndex)
|
||||
|
||||
private void Repeated(StringBuilder file, StringBuilder disposeStr, string newline, string protocolMember, ref int keyIndex, MessageHelperInfo currentHelperInfo, string repeatedType, string messageName, string filePath, HashSet<string> fieldNames, HashSet<int> fieldNumbers)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -715,21 +808,97 @@ public sealed class ProtocolExporter
|
||||
var property = newline.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries);
|
||||
var type = property[1];
|
||||
var name = property[2];
|
||||
// var memberIndex = int.Parse(property[4]);
|
||||
var fieldNumber = int.Parse(property[4]);
|
||||
type = ConvertType(type);
|
||||
|
||||
// 检测字段名重复
|
||||
if (!fieldNames.Add(name))
|
||||
{
|
||||
var errorMsg = $"协议格式错误!\n文件: {filePath}\n消息: {messageName}\n字段名重复: {name}";
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(errorMsg);
|
||||
Console.ResetColor();
|
||||
throw new ProtocolFormatException(errorMsg);
|
||||
}
|
||||
|
||||
// 检测字段编号重复
|
||||
if (!fieldNumbers.Add(fieldNumber))
|
||||
{
|
||||
var errorMsg = $"协议格式错误!\n文件: {filePath}\n消息: {messageName}\n字段编号重复: {fieldNumber} (字段: {name})";
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(errorMsg);
|
||||
Console.ResetColor();
|
||||
throw new ProtocolFormatException(errorMsg);
|
||||
}
|
||||
|
||||
file.AppendLine($"\t\t[{protocolMember}({keyIndex++})]");
|
||||
file.AppendLine($"\t\tpublic List<{type}> {name} = new List<{type}>();");
|
||||
disposeStr.AppendLine($"\t\t\t{name}.Clear();");
|
||||
|
||||
switch (repeatedType)
|
||||
{
|
||||
case "repeated":
|
||||
// public List<string> List = new List<string>();
|
||||
file.AppendLine($"\t\tpublic List<{type}> {name} = new List<{type}>();");
|
||||
disposeStr.AppendLine($"\t\t\t{name}.Clear();");
|
||||
|
||||
// 收集字段信息到Helper
|
||||
if (currentHelperInfo != null)
|
||||
{
|
||||
currentHelperInfo.Fields.Add(new MessageFieldInfo
|
||||
{
|
||||
FieldName = name,
|
||||
FieldType = $"List<{type}>"
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case "repeatedArray":
|
||||
// public string[] List;
|
||||
file.AppendLine($"\t\tpublic {type}[] {name};");
|
||||
disposeStr.AppendLine($"\t\t\t{name} = default;");
|
||||
|
||||
// 收集字段信息到Helper
|
||||
if (currentHelperInfo != null)
|
||||
{
|
||||
currentHelperInfo.Fields.Add(new MessageFieldInfo
|
||||
{
|
||||
FieldName = name,
|
||||
FieldType = $"{type}[]"
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case "repeatedList":
|
||||
// public List<string> List;
|
||||
file.AppendLine($"\t\tpublic List<{type}> {name};");
|
||||
disposeStr.AppendLine($"\t\t\t{name} = default;");
|
||||
|
||||
// 收集字段信息到Helper
|
||||
if (currentHelperInfo != null)
|
||||
{
|
||||
currentHelperInfo.Fields.Add(new MessageFieldInfo
|
||||
{
|
||||
FieldName = name,
|
||||
FieldType = $"List<{type}>"
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (ProtocolFormatException)
|
||||
{
|
||||
// 格式错误已经打印过了,直接重新抛出
|
||||
throw;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"{newline}\n {e}");
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine($"解析字段时出错: {newline}\n错误: {e.Message}");
|
||||
Console.ResetColor();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void Members(StringBuilder file, StringBuilder disposeStr, string currentLine, string protocolMember,
|
||||
ref int keyIndex)
|
||||
private void Members(StringBuilder file, StringBuilder disposeStr, string currentLine, string protocolMember, ref int keyIndex, MessageHelperInfo currentHelperInfo, string messageName, string filePath, HashSet<string> fieldNames, HashSet<int> fieldNumbers)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -738,19 +907,56 @@ public sealed class ProtocolExporter
|
||||
var property = currentLine.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries);
|
||||
var type = property[0];
|
||||
var name = property[1];
|
||||
// var memberIndex = int.Parse(property[3]);
|
||||
var fieldNumber = int.Parse(property[3]);
|
||||
var typeCs = ConvertType(type);
|
||||
|
||||
// 检测字段名重复
|
||||
if (!fieldNames.Add(name))
|
||||
{
|
||||
var errorMsg = $"协议格式错误!\n文件: {filePath}\n消息: {messageName}\n字段名重复: {name}";
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(errorMsg);
|
||||
Console.ResetColor();
|
||||
throw new ProtocolFormatException(errorMsg);
|
||||
}
|
||||
|
||||
// 检测字段编号重复
|
||||
if (!fieldNumbers.Add(fieldNumber))
|
||||
{
|
||||
var errorMsg = $"协议格式错误!\n文件: {filePath}\n消息: {messageName}\n字段编号重复: {fieldNumber} (字段: {name})";
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(errorMsg);
|
||||
Console.ResetColor();
|
||||
throw new ProtocolFormatException(errorMsg);
|
||||
}
|
||||
if (protocolMember != null)
|
||||
{
|
||||
file.AppendLine($"\t\t[{protocolMember}({keyIndex++})]");
|
||||
}
|
||||
|
||||
file.AppendLine($"\t\tpublic {typeCs} {name} {{ get; set; }}");
|
||||
disposeStr.AppendLine($"\t\t\t{name} = default;");
|
||||
|
||||
// 收集字段信息到Helper
|
||||
if (currentHelperInfo != null)
|
||||
{
|
||||
currentHelperInfo.Fields.Add(new MessageFieldInfo
|
||||
{
|
||||
FieldName = name,
|
||||
FieldType = typeCs
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (ProtocolFormatException)
|
||||
{
|
||||
// 格式错误已经打印过了,直接重新抛出
|
||||
throw;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"{currentLine}\n {e}");
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine($"解析字段时出错: {currentLine}\n错误: {e.Message}");
|
||||
Console.ResetColor();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -823,10 +1029,9 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
roamingTypeFileSb.AppendLine($"\t\t\t\tyield return {roamingType};");
|
||||
}
|
||||
|
||||
roamingTypeFileSb.AppendLine("\t\t\t}\n\t\t}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
roamingTypeFileSb.AppendLine("\t}\n}");
|
||||
var file = roamingTypeFileSb.ToString();
|
||||
@@ -841,7 +1046,7 @@ public sealed class ProtocolExporter
|
||||
await File.WriteAllTextAsync($"{_networkProtocolClientDirectory}RoamingType.cs", file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task RouteType()
|
||||
{
|
||||
var routeTypeFile = $"{_networkProtocolDirectory}RouteType.Config";
|
||||
@@ -855,7 +1060,6 @@ public sealed class ProtocolExporter
|
||||
{
|
||||
protoFileText = await File.ReadAllTextAsync(routeTypeFile);
|
||||
}
|
||||
|
||||
var routeTypeFileSb = new StringBuilder();
|
||||
routeTypeFileSb.AppendLine("namespace Fantasy\n{");
|
||||
routeTypeFileSb.AppendLine("\t// Route协议定义(需要定义1000以上、因为1000以内的框架预留)\t");
|
||||
@@ -897,16 +1101,10 @@ public sealed class ProtocolExporter
|
||||
await File.WriteAllTextAsync($"{_networkProtocolClientDirectory}RouteType.cs", file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void LoadTemplate()
|
||||
{
|
||||
// 获取当前运行根目录(即应用程序的工作目录)
|
||||
string currentDirectory = Directory.GetCurrentDirectory();
|
||||
string filePath = Path.Combine(currentDirectory, "Template.txt");
|
||||
|
||||
// 读取文件所有行
|
||||
string[] lines = File.ReadAllLines(filePath);
|
||||
string[] lines = NetworkProtocolTemplate.Template.Split(["\r\n", "\n"], StringSplitOptions.None);
|
||||
|
||||
StringBuilder serverSb = new StringBuilder();
|
||||
StringBuilder clientSb = new StringBuilder();
|
||||
@@ -921,14 +1119,12 @@ public sealed class ProtocolExporter
|
||||
flag = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (trim.StartsWith("#else"))
|
||||
else if (trim.StartsWith("#else"))
|
||||
{
|
||||
flag = 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (trim.StartsWith($"#endif"))
|
||||
else if (trim.StartsWith($"#endif"))
|
||||
{
|
||||
flag = 0;
|
||||
continue;
|
||||
@@ -958,4 +1154,109 @@ public sealed class ProtocolExporter
|
||||
_serverTemplate = serverSb.Replace("(NetworkProtocol)", "ProtoBuf").ToString();
|
||||
_clientTemplate = clientSb.Replace("(NetworkProtocol)", "ProtoBuf").ToString();
|
||||
}
|
||||
|
||||
private string GenerateNetworkProtocolHelperFile(List<MessageHelperInfo> helperInfos)
|
||||
{
|
||||
var helperSb = new StringBuilder();
|
||||
|
||||
// 添加文件头和命名空间
|
||||
helperSb.AppendLine("using System.Runtime.CompilerServices;");
|
||||
helperSb.AppendLine("using Fantasy;");
|
||||
helperSb.AppendLine("using Fantasy.Async;");
|
||||
helperSb.AppendLine("using Fantasy.Network;");
|
||||
helperSb.AppendLine("using System.Collections.Generic;");
|
||||
helperSb.AppendLine("#pragma warning disable CS8618");
|
||||
helperSb.AppendLine();
|
||||
helperSb.AppendLine("namespace Fantasy");
|
||||
helperSb.AppendLine("{");
|
||||
helperSb.AppendLine("\tpublic static class NetworkProtocolHelper");
|
||||
helperSb.AppendLine("\t{");
|
||||
|
||||
foreach (var info in helperInfos)
|
||||
{
|
||||
if (info.MessageType == "IMessage")
|
||||
{
|
||||
// 版本1: 生成接受消息对象的 Send 方法
|
||||
helperSb.AppendLine($"\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
helperSb.AppendLine($"\t\tpublic static void {info.MessageName}(this Session session, {info.MessageName} message)");
|
||||
helperSb.AppendLine("\t\t{");
|
||||
helperSb.AppendLine("\t\t\tsession.Send(message);");
|
||||
helperSb.AppendLine("\t\t}");
|
||||
helperSb.AppendLine();
|
||||
|
||||
// 版本2: 生成接受属性参数的 Send 方法
|
||||
if (info.Fields.Count > 0)
|
||||
{
|
||||
var parameters = string.Join(", ", info.Fields.Select(f => $"{f.FieldType} {char.ToLower(f.FieldName[0])}{f.FieldName.Substring(1)}"));
|
||||
helperSb.AppendLine($"\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
helperSb.AppendLine($"\t\tpublic static void {info.MessageName}(this Session session, {parameters})");
|
||||
helperSb.AppendLine("\t\t{");
|
||||
helperSb.AppendLine($"\t\t\tusing var message = Fantasy.{info.MessageName}.Create(session.Scene);");
|
||||
foreach (var field in info.Fields)
|
||||
{
|
||||
var paramName = $"{char.ToLower(field.FieldName[0])}{field.FieldName.Substring(1)}";
|
||||
helperSb.AppendLine($"\t\t\tmessage.{field.FieldName} = {paramName};");
|
||||
}
|
||||
helperSb.AppendLine("\t\t\tsession.Send(message);");
|
||||
helperSb.AppendLine("\t\t}");
|
||||
helperSb.AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 没有字段的消息,生成无参数版本
|
||||
helperSb.AppendLine($"\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
helperSb.AppendLine($"\t\tpublic static void {info.MessageName}(this Session session)");
|
||||
helperSb.AppendLine("\t\t{");
|
||||
helperSb.AppendLine($"\t\t\tusing var message = Fantasy.{info.MessageName}.Create(session.Scene);");
|
||||
helperSb.AppendLine("\t\t\tsession.Send(message);");
|
||||
helperSb.AppendLine("\t\t}");
|
||||
helperSb.AppendLine();
|
||||
}
|
||||
}
|
||||
else if (info.MessageType == "IRequest")
|
||||
{
|
||||
// 版本1: 生成接受请求对象的 Call 方法
|
||||
helperSb.AppendLine($"\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
helperSb.AppendLine($"\t\tpublic static async FTask<{info.ResponseType}> {info.MessageName}(this Session session, {info.MessageName} request)");
|
||||
helperSb.AppendLine("\t\t{");
|
||||
helperSb.AppendLine($"\t\t\treturn ({info.ResponseType})await session.Call(request);");
|
||||
helperSb.AppendLine("\t\t}");
|
||||
helperSb.AppendLine();
|
||||
|
||||
// 版本2: 生成接受属性参数的 Call 方法
|
||||
if (info.Fields.Count > 0)
|
||||
{
|
||||
var parameters = string.Join(", ", info.Fields.Select(f => $"{f.FieldType} {char.ToLower(f.FieldName[0])}{f.FieldName.Substring(1)}"));
|
||||
helperSb.AppendLine($"\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
helperSb.AppendLine($"\t\tpublic static async FTask<{info.ResponseType}> {info.MessageName}(this Session session, {parameters})");
|
||||
helperSb.AppendLine("\t\t{");
|
||||
helperSb.AppendLine($"\t\t\tusing var request = Fantasy.{info.MessageName}.Create(session.Scene);");
|
||||
foreach (var field in info.Fields)
|
||||
{
|
||||
var paramName = $"{char.ToLower(field.FieldName[0])}{field.FieldName.Substring(1)}";
|
||||
helperSb.AppendLine($"\t\t\trequest.{field.FieldName} = {paramName};");
|
||||
}
|
||||
helperSb.AppendLine($"\t\t\treturn ({info.ResponseType})await session.Call(request);");
|
||||
helperSb.AppendLine("\t\t}");
|
||||
helperSb.AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 没有字段的请求,生成无参数版本
|
||||
helperSb.AppendLine($"\t\t[MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
helperSb.AppendLine($"\t\tpublic static async FTask<{info.ResponseType}> {info.MessageName}(this Session session)");
|
||||
helperSb.AppendLine("\t\t{");
|
||||
helperSb.AppendLine($"\t\t\tusing var request = Fantasy.{info.MessageName}.Create(session.Scene);");
|
||||
helperSb.AppendLine($"\t\t\treturn ({info.ResponseType})await session.Call(request);");
|
||||
helperSb.AppendLine("\t\t}");
|
||||
helperSb.AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
helperSb.AppendLine("\t}");
|
||||
helperSb.AppendLine("}");
|
||||
|
||||
return helperSb.ToString();
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"Export": {
|
||||
"NetworkProtocolDirectory": {
|
||||
"Value": "../../../Config/NetworkProtocol/",
|
||||
"Value": "../../../Examples/Config/NetworkProtocol/",
|
||||
"Comment": "ProtoBuf文件所在的文件夹位置"
|
||||
},
|
||||
"NetworkProtocolServerDirectory": {
|
||||
"Value": "../../../Entity/Generate/NetworkProtocol/",
|
||||
"Value": "../../../Examples/Server/Entity/Generate/NetworkProtocol/",
|
||||
"Comment": "ProtoBuf生成到服务端的文件夹位置"
|
||||
},
|
||||
"NetworkProtocolClientDirectory": {
|
||||
"Value": "../../../../Fishing2/Assets/Scripts/Generate/NetworkProtocol/",
|
||||
"Value": "../../../Examples/Client/Unity/Assets/Scripts/Hotfix/Generate/NetworkProtocol/",
|
||||
"Comment": "ProtoBuf生成到客户端的文件夹位置"
|
||||
},
|
||||
"Serializes": {
|
||||
|
||||
@@ -32,16 +32,16 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\Fantasy\Fantasy.Net\Fantasy.Net\Runtime\Core\Helper\FileHelper.cs">
|
||||
<Compile Include="..\..\..\Fantasy.Net\Fantasy.Net\Runtime\Core\Helper\FileHelper.cs">
|
||||
<Link>Core\FileHelper.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\..\Fantasy\Fantasy.Net\Fantasy.Net\Runtime\Core\Helper\HashCodeHelper.cs">
|
||||
<Compile Include="..\..\..\Fantasy.Net\Fantasy.Net\Runtime\Core\Helper\HashCodeHelper.cs">
|
||||
<Link>Core\HashCodeHelper.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\..\Fantasy\Fantasy.Net\Fantasy.Net\Runtime\Core\Helper\JsonHelper.cs">
|
||||
<Compile Include="..\..\..\Fantasy.Net\Fantasy.Net\Runtime\Core\Helper\JsonHelper.cs">
|
||||
<Link>Core\JsonHelper.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\..\Fantasy\Fantasy.Net\Fantasy.Net\Runtime\Core\Network\Message\PacketParser\OpCode.cs">
|
||||
<Compile Include="..\..\..\Fantasy.Net\Fantasy.Net\Runtime\Core\Network\Message\PacketParser\OpCode.cs">
|
||||
<Link>ProtocalExporter\OpCode.cs</Link>
|
||||
</Compile>
|
||||
<Compile Update="ExporterSettingsHelper.cs">
|
||||
@@ -53,15 +53,15 @@
|
||||
<None Update="ExporterSettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="NetworkProtocolTemplate.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Run.bat">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Run.sh">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Template.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# NetworkProtocolTemplate.txt 使用说明
|
||||
|
||||
## 概述
|
||||
这个模板文件用于生成网络协议的 C# 代码文件。您可以根据需要自定义模板内容。
|
||||
|
||||
## 占位符说明
|
||||
|
||||
模板中包含以下占位符,会在代码生成时被替换:
|
||||
|
||||
### `(UsingNamespace)`
|
||||
- 用于插入自定义命名空间的 using 语句
|
||||
- 例如:当使用自定义序列化器时,会在此处插入相关的 using 语句
|
||||
|
||||
### `(Content)`
|
||||
- 用于插入生成的协议类代码
|
||||
- 所有 message 定义都会被转换为 C# 类并插入到此处
|
||||
|
||||
## 模板结构
|
||||
|
||||
### 服务端部分(#if SERVER)
|
||||
包含服务端特有的引用和配置:
|
||||
- `using MongoDB.Bson.Serialization.Attributes` - 用于 MongoDB 持久化
|
||||
- 额外的编译器指令和 ReSharper 配置
|
||||
|
||||
### 客户端部分(#else)
|
||||
包含客户端需要的基本引用:
|
||||
- 较少的 using 语句
|
||||
- 简化的警告抑制
|
||||
|
||||
## 自定义方法
|
||||
|
||||
如果需要修改生成的代码格式,可以:
|
||||
1. 修改 using 语句部分
|
||||
2. 添加或删除编译器指令
|
||||
3. 修改命名空间结构
|
||||
4. 添加全局特性或注释
|
||||
|
||||
## 注意事项
|
||||
|
||||
⚠️ **不要删除占位符**:`(UsingNamespace)` 和 `(Content)` 是必需的,删除会导致代码生成失败
|
||||
|
||||
⚠️ **保持条件编译**:`#if SERVER` / `#else` / `#endif` 结构用于区分服务端和客户端代码
|
||||
|
||||
⚠️ **编码格式**:文件应使用 UTF-8 编码
|
||||
|
||||
## 文件位置
|
||||
|
||||
编译后,模板文件会被复制到输出目录,确保与可执行文件在同一位置。
|
||||
@@ -1,6 +1,7 @@
|
||||
#if SERVER
|
||||
using ProtoBuf;
|
||||
(UsingNamespace)
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using Fantasy;
|
||||
@@ -16,10 +17,11 @@ using Fantasy.Serialize;
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
namespace Fantasy
|
||||
{
|
||||
#else
|
||||
using ProtoBuf;
|
||||
using System;
|
||||
(UsingNamespace)
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
@@ -30,4 +32,4 @@ using Fantasy.Serialize;
|
||||
namespace Fantasy
|
||||
{
|
||||
#endif
|
||||
(Content)}
|
||||
(Content)}
|
||||
@@ -16,9 +16,15 @@ try
|
||||
// 运行导出协议的代码
|
||||
new ProtocolExporter().Run();
|
||||
}
|
||||
catch (Fantasy.Tools.ProtocalExporter.ProtocolFormatException)
|
||||
{
|
||||
// 协议格式错误已经打印过详细信息,这里不再重复打印
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine($"程序执行出错: {e.Message}");
|
||||
Console.ResetColor();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user