diff --git a/.gitignore b/.gitignore
index 9c630850..df089d85 100644
--- a/.gitignore
+++ b/.gitignore
@@ -129,4 +129,5 @@ DotNet/ThirdParty/obj/
Bin/
#Server_Config
-DotNet/Config/GameConfig
\ No newline at end of file
+DotNet/Config/GameConfig
+DotNet/Config/ProtoBuf/OpCode.Cache
diff --git a/Assets/GameScripts/DotNet/Core/Exporter/Excel/Base/ExportType.cs b/Assets/GameScripts/DotNet/Core/Exporter/Excel/Base/ExportType.cs
index 6a9c6f83..6f435890 100644
--- a/Assets/GameScripts/DotNet/Core/Exporter/Excel/Base/ExportType.cs
+++ b/Assets/GameScripts/DotNet/Core/Exporter/Excel/Base/ExportType.cs
@@ -1,12 +1,34 @@
#if TENGINE_NET
namespace TEngine.Core;
+///
+/// 导出类型枚举,用于标识不同类型的导出操作。
+///
public enum ExportType
{
- None = 0,
- ProtoBuf = 1, // 导出ProtoBuf
- AllExcelIncrement = 2, // 所有-增量导出Excel
- AllExcel = 3, // 所有-全量导出Excel
- Max, // 这个一定放最后
+ ///
+ /// 无导出类型。
+ ///
+ None = 0,
+ ///
+ /// 导出ProtoBuf类型。
+ ///
+ ProtoBuf = 1,
+ ///
+ /// 导出网络协议并重新生成OpCode。
+ ///
+ ProtoBufAndOpCodeCache = 2,
+ ///
+ /// 所有数据的增量导出Excel类型。
+ ///
+ AllExcelIncrement = 3,
+ ///
+ /// 所有数据的全量导出Excel类型。
+ ///
+ AllExcel = 4,
+ ///
+ /// 导出类型枚举的最大值,一定要放在最后。
+ ///
+ Max,
}
#endif
diff --git a/Assets/GameScripts/DotNet/Core/Exporter/Exporter.cs b/Assets/GameScripts/DotNet/Core/Exporter/Exporter.cs
index 80ed1a53..e9bfd275 100644
--- a/Assets/GameScripts/DotNet/Core/Exporter/Exporter.cs
+++ b/Assets/GameScripts/DotNet/Core/Exporter/Exporter.cs
@@ -3,16 +3,21 @@ using System.Diagnostics;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;
-using TEngine.Core;
+using TEngine.Helper;
using Microsoft.Extensions.Configuration;
#pragma warning disable CS8601
-#pragma warning disable CS8618
namespace TEngine.Core;
+///
+/// 数据导出器,用于执行导出操作。
+///
public sealed class Exporter
{
+ ///
+ /// 开始执行数据导出操作。
+ ///
public void Start()
{
Console.OutputEncoding = Encoding.UTF8;
@@ -25,8 +30,9 @@ public sealed class Exporter
LogInfo("请输入你想要做的操作:");
LogInfo("1:导出网络协议(ProtoBuf)");
- LogInfo("2:增量导出服务器启动Excel(包含常量枚举)");
- LogInfo("3:全量导出服务器启动Excel(包含常量枚举)");
+ LogInfo("2:导出网络协议并重新生成OpCode(ProtoBuf)");
+ LogInfo("3:增量导出Excel(包含常量枚举)");
+ LogInfo("4:全量导出Excel(包含常量枚举)");
var keyChar = Console.ReadKey().KeyChar;
@@ -39,13 +45,17 @@ public sealed class Exporter
LogInfo("");
exportType = (ExportType) key;
- // LoadConfig();
-
+
switch (exportType)
{
case ExportType.ProtoBuf:
{
- _ = new ProtoBufExporter();
+ _ = new ProtoBufExporter(false);
+ break;
+ }
+ case ExportType.ProtoBufAndOpCodeCache:
+ {
+ _ = new ProtoBufExporter(true);
break;
}
case ExportType.AllExcel:
@@ -61,11 +71,19 @@ public sealed class Exporter
Environment.Exit(0);
}
+ ///
+ /// 输出信息到控制台。
+ ///
+ /// 要输出的信息。
public static void LogInfo(string msg)
{
Console.WriteLine(msg);
}
+ ///
+ /// 输出错误信息到控制台。
+ ///
+ /// 要输出的错误信息。
public static void LogError(string msg)
{
ConsoleColor color = Console.ForegroundColor;
@@ -74,6 +92,10 @@ public sealed class Exporter
Console.ForegroundColor = color;
}
+ ///
+ /// 输出异常信息到控制台。
+ ///
+ /// 要输出的异常。
public static void LogError(Exception e)
{
ConsoleColor color = Console.ForegroundColor;
diff --git a/Assets/GameScripts/DotNet/Core/Exporter/ProtoBuf/OpCodeCache.cs b/Assets/GameScripts/DotNet/Core/Exporter/ProtoBuf/OpCodeCache.cs
new file mode 100644
index 00000000..0183c7b7
--- /dev/null
+++ b/Assets/GameScripts/DotNet/Core/Exporter/ProtoBuf/OpCodeCache.cs
@@ -0,0 +1,60 @@
+#if TENGINE_NET
+using TEngine.Helper;
+
+namespace TEngine.Core;
+
+///
+/// 网络协议操作码缓存。
+///
+public class OpCodeCache
+{
+ private readonly List _opCodes = new List();
+ private readonly SortedDictionary _opcodeCache;
+ private readonly SortedDictionary _saveOpCodeCache = new();
+ private readonly string _opcodeCachePath = $"{Define.ProtoBufDirectory}OpCode.Cache";
+
+ ///
+ /// 构造函数,用于初始化网络协议操作码缓存。
+ ///
+ public OpCodeCache(bool regenerate)
+ {
+ if (File.Exists(_opcodeCachePath) && !regenerate)
+ {
+ var readAllText = File.ReadAllText(_opcodeCachePath);
+ _opcodeCache = readAllText.Deserialize>();
+ _opCodes.AddRange(_opcodeCache.Values);
+ }
+ else
+ {
+ _opcodeCache = new SortedDictionary();
+ }
+ }
+
+ ///
+ /// 保存网络协议操作码。
+ ///
+ public void Save()
+ {
+ File.WriteAllText(_opcodeCachePath, _saveOpCodeCache.ToJson());
+ }
+
+ ///
+ /// 根据className获得OpCode、如果是新增的会产生一个新的OpCode。
+ ///
+ /// 协议名。
+ /// 操作码。
+ ///
+ public uint GetOpcodeCache(string className, ref uint opcode)
+ {
+ if (!_opcodeCache.TryGetValue(className, out var opCode))
+ {
+ while (_opCodes.Contains(++opcode)) { }
+ opCode = opcode;
+ _opCodes.Add(opCode);
+ }
+
+ _saveOpCodeCache.Add(className, opCode);
+ return opCode;
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Assets/GameScripts/DotNet/Core/Exporter/ProtoBuf/OpCodeCache.cs.meta b/Assets/GameScripts/DotNet/Core/Exporter/ProtoBuf/OpCodeCache.cs.meta
new file mode 100644
index 00000000..f7e5402c
--- /dev/null
+++ b/Assets/GameScripts/DotNet/Core/Exporter/ProtoBuf/OpCodeCache.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: e0f0d02da06c4ca981417bfe43162809
+timeCreated: 1693928511
\ No newline at end of file
diff --git a/Assets/GameScripts/DotNet/Core/Exporter/ProtoBuf/ProtoBufExporter.cs b/Assets/GameScripts/DotNet/Core/Exporter/ProtoBuf/ProtoBufExporter.cs
index ce2b2d59..1b5f5f24 100644
--- a/Assets/GameScripts/DotNet/Core/Exporter/ProtoBuf/ProtoBufExporter.cs
+++ b/Assets/GameScripts/DotNet/Core/Exporter/ProtoBuf/ProtoBufExporter.cs
@@ -1,28 +1,52 @@
#if TENGINE_NET
using System.Text;
using TEngine.Core.Network;
-
-#pragma warning disable CS8604
-#pragma warning disable CS8602
-#pragma warning disable CS8600
-#pragma warning disable CS8618
+using TEngine.Helper;
namespace TEngine.Core;
+///
+/// ProtoBuf操作码类型枚举
+///
public enum ProtoBufOpCodeType
{
+ ///
+ /// 无
+ ///
None = 0,
+ ///
+ /// 外部操作码类型
+ ///
Outer = 1,
+ ///
+ /// 内部操作码类型
+ ///
Inner = 2,
+ ///
+ /// 使用BSON的内部操作码类型
+ ///
InnerBson = 3,
}
+///
+/// 操作码信息类
+///
public sealed class OpcodeInfo
{
+ ///
+ /// 操作码
+ ///
public uint Code;
+ ///
+ /// 名称
+ ///
public string Name;
}
+
+///
+/// ProtoBuf导出器类
+///
public sealed class ProtoBufExporter
{
private uint _aMessage;
@@ -33,18 +57,21 @@ public sealed class ProtoBufExporter
private uint _aRouteResponse;
private string _serverTemplate;
private string _clientTemplate;
-
+ private readonly OpCodeCache _opCodeCache;
private readonly List _opcodes = new();
- public ProtoBufExporter()
+ ///
+ /// 构造函数,用于初始化导出器
+ ///
+ public ProtoBufExporter(bool regenerateOpCodeCache)
{
Console.OutputEncoding = Encoding.UTF8;
-
+
if (!Directory.Exists(Define.ProtoBufServerDirectory))
{
Directory.CreateDirectory(Define.ProtoBufServerDirectory);
}
-
+
if (!Directory.Exists(Define.ProtoBufClientDirectory))
{
Directory.CreateDirectory(Define.ProtoBufClientDirectory);
@@ -54,17 +81,19 @@ public sealed class ProtoBufExporter
{
Directory.CreateDirectory($"{Define.ProtoBufDirectory}Outer");
}
-
+
if (!Directory.Exists($"{Define.ProtoBufDirectory}Inner"))
{
Directory.CreateDirectory($"{Define.ProtoBufDirectory}Inner");
}
- if (!Directory.Exists($"{Define.ProtoBufDirectory}Bson"))
+ if (!Directory.Exists($"{Define.ProtoBufDirectory}InnerBosn"))
{
- Directory.CreateDirectory($"{Define.ProtoBufDirectory}Bson");
+ Directory.CreateDirectory($"{Define.ProtoBufDirectory}InnerBosn");
}
+ _opCodeCache = new OpCodeCache(regenerateOpCodeCache);
+
var tasks = new Task[2];
tasks[0] = Task.Run(RouteType);
tasks[1] = Task.Run(async () =>
@@ -75,6 +104,7 @@ public sealed class ProtoBufExporter
await Start(ProtoBufOpCodeType.InnerBson);
});
Task.WaitAll(tasks);
+ _opCodeCache.Save();
}
private async Task Start(ProtoBufOpCodeType opCodeType)
@@ -85,7 +115,7 @@ public sealed class ProtoBufExporter
_opcodes.Clear();
var file = new StringBuilder();
var saveDirectory = new Dictionary();
-
+
switch (opCodeType)
{
case ProtoBufOpCodeType.Outer:
@@ -99,8 +129,9 @@ public sealed class ProtoBufExporter
opCodeName = "OuterOpcode";
saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate);
saveDirectory.Add(Define.ProtoBufClientDirectory, _clientTemplate);
- files.Add($"{Define.ProtoBufDirectory}OuterMessage.proto");
- files.AddRange(Directory.GetFiles($"{Define.ProtoBufDirectory}Outer").ToList());
+ var protoBufFiles = FileHelper.GetDirectoryFile(
+ $"{Define.ProtoBufDirectory}Outer", "*.proto", SearchOption.AllDirectories);
+ files.AddRange(protoBufFiles);
break;
}
case ProtoBufOpCodeType.Inner:
@@ -114,8 +145,8 @@ public sealed class ProtoBufExporter
_aRouteResponse = Opcode.InnerRouteResponse + 1000;
opCodeName = "InnerOpcode";
saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate);
- files.Add($"{Define.ProtoBufDirectory}InnerMessage.proto");
- files.AddRange(Directory.GetFiles($"{Define.ProtoBufDirectory}Inner").ToList());
+ var protoBufFiles = FileHelper.GetDirectoryFile($"{Define.ProtoBufDirectory}Inner", "*.proto", SearchOption.AllDirectories);
+ files.AddRange(protoBufFiles);
break;
}
case ProtoBufOpCodeType.InnerBson:
@@ -129,8 +160,8 @@ public sealed class ProtoBufExporter
_aRouteResponse = Opcode.InnerBsonRouteResponse + 1000;
opCodeName = "InnerBsonOpcode";
saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate);
- files.Add($"{Define.ProtoBufDirectory}InnerBsonMessage.proto");
- files.AddRange(Directory.GetFiles($"{Define.ProtoBufDirectory}Bson").ToList());
+ var protoBufFiles = FileHelper.GetDirectoryFile($"{Define.ProtoBufDirectory}InnerBosn", "*.proto", SearchOption.AllDirectories);
+ files.AddRange(protoBufFiles);
break;
}
}
@@ -143,6 +174,7 @@ public sealed class ProtoBufExporter
var isMsgHead = false;
string responseTypeStr = null;
string customRouteType = null;
+
var protoFileText = await File.ReadAllTextAsync(filePath);
foreach (var line in protoFileText.Split('\n'))
@@ -176,17 +208,20 @@ public sealed class ProtoBufExporter
switch (parameterArray.Length)
{
case 2:
+ {
+ if (parameter == "ICustomRouteMessage")
+ {
+ customRouteType = parameterArray[1].Trim();
+ break;
+ }
+
responseTypeStr = parameterArray[1].Trim();
break;
+ }
case 3:
{
- customRouteType = parameterArray[1].Trim();
-
- if (parameterArray.Length == 3)
- {
- responseTypeStr = parameterArray[2].Trim();
- }
-
+ responseTypeStr = parameterArray[1].Trim();
+ customRouteType = parameterArray[2].Trim();
break;
}
}
@@ -197,8 +232,8 @@ public sealed class ProtoBufExporter
}
file.Append(string.IsNullOrWhiteSpace(parameter)
- ? $"\tpublic partial class {className} : AProto"
- : $"\tpublic partial class {className} : AProto, {parameter}");
+ ? $"\tpublic partial class {className} : AProto"
+ : $"\tpublic partial class {className} : AProto, {parameter}");
opcodeInfo.Name = className;
continue;
}
@@ -216,7 +251,7 @@ public sealed class ProtoBufExporter
if (string.IsNullOrWhiteSpace(parameter) || parameter == "IMessage")
{
- opcodeInfo.Code += ++_aMessage;
+ opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aMessage);
file.AppendLine($"\t\tpublic uint OpCode() {{ return {opCodeName}.{className}; }}");
}
else
@@ -260,13 +295,13 @@ public sealed class ProtoBufExporter
case "IRequest":
case "IBsonRequest":
{
- opcodeInfo.Code += ++_aRequest;
+ opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRequest);
break;
}
case "IResponse":
case "IBsonResponse":
{
- opcodeInfo.Code += ++_aResponse;
+ opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aResponse);
file.AppendLine("\t\t[ProtoMember(91, IsRequired = true)]");
file.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
break;
@@ -275,15 +310,15 @@ public sealed class ProtoBufExporter
{
if (parameter.EndsWith("RouteMessage") || parameter == "IRouteMessage")
{
- opcodeInfo.Code += ++_aRouteMessage;
+ opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRouteMessage);
}
else if (parameter.EndsWith("RouteRequest") || parameter == "IRouteRequest")
{
- opcodeInfo.Code += ++_aRouteRequest;
+ opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRouteRequest);
}
else if (parameter.EndsWith("RouteResponse") || parameter == "IRouteResponse")
{
- opcodeInfo.Code += ++_aRouteResponse;
+ opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRouteResponse);
file.AppendLine("\t\t[ProtoMember(91, IsRequired = true)]");
file.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
}
@@ -343,14 +378,14 @@ public sealed class ProtoBufExporter
file.AppendLine("{");
file.AppendLine($"\tpublic static partial class {opCodeName}");
file.AppendLine("\t{");
-
+
foreach (var opcode in _opcodes)
{
file.AppendLine($"\t\t public const int {opcode.Name} = {opcode.Code};");
}
-
+
_opcodes.Clear();
-
+
file.AppendLine("\t}");
file.AppendLine("}");
@@ -359,7 +394,6 @@ public sealed class ProtoBufExporter
var csFile = Path.Combine(directory, $"{opCodeName}.cs");
await File.WriteAllTextAsync(csFile, file.ToString());
}
-
#endregion
}
@@ -380,11 +414,11 @@ public sealed class ProtoBufExporter
{
continue;
}
-
- var splits = currentLine.Split(new[] { "//" }, StringSplitOptions.RemoveEmptyEntries);
+
+ var splits = currentLine.Split(new[] {"//"}, StringSplitOptions.RemoveEmptyEntries);
var routeTypeStr = splits[0].Split("=", StringSplitOptions.RemoveEmptyEntries);
routeTypeFileSb.Append($"\t\t{routeTypeStr[0].Trim()} = {routeTypeStr[1].Trim()},");
-
+
if (splits.Length > 1)
{
routeTypeFileSb.Append($" // {splits[1].Trim()}\n");
@@ -400,7 +434,7 @@ public sealed class ProtoBufExporter
await File.WriteAllTextAsync($"{Define.ProtoBufServerDirectory}RouteType.cs", file);
await File.WriteAllTextAsync($"{Define.ProtoBufClientDirectory}RouteType.cs", file);
}
-
+
private void Repeated(StringBuilder file, string newline)
{
try
@@ -421,7 +455,7 @@ public sealed class ProtoBufExporter
Exporter.LogError($"{newline}\n {e}");
}
}
-
+
private void Members(StringBuilder file, string currentLine)
{
try
@@ -434,7 +468,7 @@ public sealed class ProtoBufExporter
var memberIndex = int.Parse(property[3]);
var typeCs = ConvertType(type);
string defaultValue = GetDefault(typeCs);
-
+
file.AppendLine($"\t\t[ProtoMember({memberIndex})]");
file.AppendLine($"\t\tpublic {typeCs} {name} {{ get; set; }}");
}
@@ -443,7 +477,7 @@ public sealed class ProtoBufExporter
Exporter.LogError($"{currentLine}\n {e}");
}
}
-
+
private string ConvertType(string type)
{
return type switch
@@ -458,11 +492,11 @@ public sealed class ProtoBufExporter
_ => type
};
}
-
+
private string GetDefault(string type)
{
type = type.Trim();
-
+
switch (type)
{
case "byte":
@@ -479,6 +513,9 @@ public sealed class ProtoBufExporter
}
}
+ ///
+ /// 加载模板
+ ///
private void LoadTemplate()
{
string[] lines = File.ReadAllLines(Define.ProtoBufTemplatePath, Encoding.UTF8);
@@ -496,12 +533,12 @@ public sealed class ProtoBufExporter
flag = 1;
continue;
}
- else if (trim.StartsWith("#else"))
+ else if(trim.StartsWith("#else"))
{
flag = 2;
continue;
}
- else if (trim.StartsWith($"#endif"))
+ else if(trim.StartsWith($"#endif"))
{
flag = 0;
continue;
diff --git a/Assets/GameScripts/DotNet/Core/Helper/FileHelper.cs b/Assets/GameScripts/DotNet/Core/Helper/FileHelper.cs
index 88c91469..fc34225b 100644
--- a/Assets/GameScripts/DotNet/Core/Helper/FileHelper.cs
+++ b/Assets/GameScripts/DotNet/Core/Helper/FileHelper.cs
@@ -1,26 +1,29 @@
using System.Collections.Generic;
using System.IO;
-namespace TEngine.Core
+namespace TEngine
{
+ ///
+ /// 文件操作助手类,提供了各种文件操作方法。
+ ///
public static class FileHelper
{
///
- /// 获取文件全路径。
+ /// 获取相对路径的完整路径。
///
- ///
- ///
+ /// 相对路径。
+ /// 完整路径。
public static string GetFullPath(string relativePath)
{
return Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), relativePath));
}
///
- /// 拷贝文件到目标路径、如果目标目录不存在会自动创建目录
+ /// 将文件复制到目标路径,如果目标目录不存在会自动创建目录。
///
- ///
- ///
- ///
+ /// 源文件路径。
+ /// 目标文件路径。
+ /// 是否覆盖已存在的目标文件。
public static void Copy(string sourceFile, string destinationFile, bool overwrite)
{
var directoriesByFilePath = GetDirectoriesByFilePath(destinationFile);
@@ -39,10 +42,10 @@ namespace TEngine.Core
}
///
- /// 获取文件路径内的所有文件夹路径
+ /// 获取文件路径内的所有文件夹路径。
///
- ///
- ///
+ /// 文件路径。
+ /// 文件夹路径列表。
public static List GetDirectoriesByFilePath(string filePath)
{
var dir = "";
@@ -59,11 +62,11 @@ namespace TEngine.Core
}
///
- /// 把文件夹里所有内容拷贝的目标位置
+ /// 将文件夹内的所有内容复制到目标位置。
///
- ///
- ///
- ///
+ /// 源文件夹路径。
+ /// 目标文件夹路径。
+ /// 是否覆盖已存在的文件。
public static void CopyDirectory(string sourceDirectory, string destinationDirectory, bool overwrite)
{
// 创建目标文件夹
@@ -99,11 +102,23 @@ namespace TEngine.Core
CopyDirectory(directory, destinationPath, overwrite);
}
}
-
+
///
- /// 清除文件夹里的所有文件
+ /// 获取目录下的所有文件
///
- ///
+ /// 文件夹路径。
+ /// 需要查找的文件通配符
+ /// 查找的类型
+ ///
+ public static string[] GetDirectoryFile(string folderPath, string searchPattern, SearchOption searchOption)
+ {
+ return Directory.GetFiles(folderPath, searchPattern, searchOption);
+ }
+
+ ///
+ /// 清空文件夹内的所有文件。
+ ///
+ /// 文件夹路径。
public static void ClearDirectoryFile(string folderPath)
{
if (!Directory.Exists(folderPath))
diff --git a/DotNet/Config/ProtoBuf/InnerMessage.proto b/DotNet/Config/ProtoBuf/Inner/InnerMessage.proto
similarity index 100%
rename from DotNet/Config/ProtoBuf/InnerMessage.proto
rename to DotNet/Config/ProtoBuf/Inner/InnerMessage.proto
diff --git a/DotNet/Config/ProtoBuf/InnerBsonMessage.proto b/DotNet/Config/ProtoBuf/InnerBosn/InnerBsonMessage.proto
similarity index 100%
rename from DotNet/Config/ProtoBuf/InnerBsonMessage.proto
rename to DotNet/Config/ProtoBuf/InnerBosn/InnerBsonMessage.proto
diff --git a/DotNet/Config/ProtoBuf/OuterMessage.proto b/DotNet/Config/ProtoBuf/Outer/OuterMessage.proto
similarity index 100%
rename from DotNet/Config/ProtoBuf/OuterMessage.proto
rename to DotNet/Config/ProtoBuf/Outer/OuterMessage.proto