导出网络协议增加了缓存文件保证一致性

导出网络协议增加了缓存文件保证一致性
This commit is contained in:
ALEXTANGXIAO
2023-09-05 23:56:50 +08:00
parent 285483034e
commit caf5b2b54e
10 changed files with 240 additions and 80 deletions

1
.gitignore vendored
View File

@@ -130,3 +130,4 @@ Bin/
#Server_Config #Server_Config
DotNet/Config/GameConfig DotNet/Config/GameConfig
DotNet/Config/ProtoBuf/OpCode.Cache

View File

@@ -1,12 +1,34 @@
#if TENGINE_NET #if TENGINE_NET
namespace TEngine.Core; namespace TEngine.Core;
/// <summary>
/// 导出类型枚举,用于标识不同类型的导出操作。
/// </summary>
public enum ExportType public enum ExportType
{ {
/// <summary>
/// 无导出类型。
/// </summary>
None = 0, None = 0,
ProtoBuf = 1, // 导出ProtoBuf /// <summary>
AllExcelIncrement = 2, // 所有-增量导出Excel /// 导出ProtoBuf类型。
AllExcel = 3, // 所有-全量导出Excel /// </summary>
Max, // 这个一定放最后 ProtoBuf = 1,
/// <summary>
/// 导出网络协议并重新生成OpCode。
/// </summary>
ProtoBufAndOpCodeCache = 2,
/// <summary>
/// 所有数据的增量导出Excel类型。
/// </summary>
AllExcelIncrement = 3,
/// <summary>
/// 所有数据的全量导出Excel类型。
/// </summary>
AllExcel = 4,
/// <summary>
/// 导出类型枚举的最大值,一定要放在最后。
/// </summary>
Max,
} }
#endif #endif

View File

@@ -3,16 +3,21 @@ using System.Diagnostics;
using System.Reflection; using System.Reflection;
using System.Runtime.Loader; using System.Runtime.Loader;
using System.Text; using System.Text;
using TEngine.Core; using TEngine.Helper;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
#pragma warning disable CS8601 #pragma warning disable CS8601
#pragma warning disable CS8618
namespace TEngine.Core; namespace TEngine.Core;
/// <summary>
/// 数据导出器,用于执行导出操作。
/// </summary>
public sealed class Exporter public sealed class Exporter
{ {
/// <summary>
/// 开始执行数据导出操作。
/// </summary>
public void Start() public void Start()
{ {
Console.OutputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8;
@@ -25,8 +30,9 @@ public sealed class Exporter
LogInfo("请输入你想要做的操作:"); LogInfo("请输入你想要做的操作:");
LogInfo("1:导出网络协议ProtoBuf"); LogInfo("1:导出网络协议ProtoBuf");
LogInfo("2:增量导出服务器启动Excel包含常量枚举"); LogInfo("2:导出网络协议并重新生成OpCodeProtoBuf");
LogInfo("3:量导出服务器启动Excel包含常量枚举"); LogInfo("3:量导出Excel包含常量枚举");
LogInfo("4:全量导出Excel包含常量枚举");
var keyChar = Console.ReadKey().KeyChar; var keyChar = Console.ReadKey().KeyChar;
@@ -39,13 +45,17 @@ public sealed class Exporter
LogInfo(""); LogInfo("");
exportType = (ExportType) key; exportType = (ExportType) key;
// LoadConfig();
switch (exportType) switch (exportType)
{ {
case ExportType.ProtoBuf: case ExportType.ProtoBuf:
{ {
_ = new ProtoBufExporter(); _ = new ProtoBufExporter(false);
break;
}
case ExportType.ProtoBufAndOpCodeCache:
{
_ = new ProtoBufExporter(true);
break; break;
} }
case ExportType.AllExcel: case ExportType.AllExcel:
@@ -61,11 +71,19 @@ public sealed class Exporter
Environment.Exit(0); Environment.Exit(0);
} }
/// <summary>
/// 输出信息到控制台。
/// </summary>
/// <param name="msg">要输出的信息。</param>
public static void LogInfo(string msg) public static void LogInfo(string msg)
{ {
Console.WriteLine(msg); Console.WriteLine(msg);
} }
/// <summary>
/// 输出错误信息到控制台。
/// </summary>
/// <param name="msg">要输出的错误信息。</param>
public static void LogError(string msg) public static void LogError(string msg)
{ {
ConsoleColor color = Console.ForegroundColor; ConsoleColor color = Console.ForegroundColor;
@@ -74,6 +92,10 @@ public sealed class Exporter
Console.ForegroundColor = color; Console.ForegroundColor = color;
} }
/// <summary>
/// 输出异常信息到控制台。
/// </summary>
/// <param name="e">要输出的异常。</param>
public static void LogError(Exception e) public static void LogError(Exception e)
{ {
ConsoleColor color = Console.ForegroundColor; ConsoleColor color = Console.ForegroundColor;

View File

@@ -0,0 +1,60 @@
#if TENGINE_NET
using TEngine.Helper;
namespace TEngine.Core;
/// <summary>
/// 网络协议操作码缓存。
/// </summary>
public class OpCodeCache
{
private readonly List<uint> _opCodes = new List<uint>();
private readonly SortedDictionary<string, uint> _opcodeCache;
private readonly SortedDictionary<string, uint> _saveOpCodeCache = new();
private readonly string _opcodeCachePath = $"{Define.ProtoBufDirectory}OpCode.Cache";
/// <summary>
/// 构造函数,用于初始化网络协议操作码缓存。
/// </summary>
public OpCodeCache(bool regenerate)
{
if (File.Exists(_opcodeCachePath) && !regenerate)
{
var readAllText = File.ReadAllText(_opcodeCachePath);
_opcodeCache = readAllText.Deserialize<SortedDictionary<string, uint>>();
_opCodes.AddRange(_opcodeCache.Values);
}
else
{
_opcodeCache = new SortedDictionary<string, uint>();
}
}
/// <summary>
/// 保存网络协议操作码。
/// </summary>
public void Save()
{
File.WriteAllText(_opcodeCachePath, _saveOpCodeCache.ToJson());
}
/// <summary>
/// 根据className获得OpCode、如果是新增的会产生一个新的OpCode。
/// </summary>
/// <param name="className">协议名。</param>
/// <param name="opcode">操作码。</param>
/// <returns></returns>
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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e0f0d02da06c4ca981417bfe43162809
timeCreated: 1693928511

View File

@@ -1,28 +1,52 @@
#if TENGINE_NET #if TENGINE_NET
using System.Text; using System.Text;
using TEngine.Core.Network; using TEngine.Core.Network;
using TEngine.Helper;
#pragma warning disable CS8604
#pragma warning disable CS8602
#pragma warning disable CS8600
#pragma warning disable CS8618
namespace TEngine.Core; namespace TEngine.Core;
/// <summary>
/// ProtoBuf操作码类型枚举
/// </summary>
public enum ProtoBufOpCodeType public enum ProtoBufOpCodeType
{ {
/// <summary>
/// 无
/// </summary>
None = 0, None = 0,
/// <summary>
/// 外部操作码类型
/// </summary>
Outer = 1, Outer = 1,
/// <summary>
/// 内部操作码类型
/// </summary>
Inner = 2, Inner = 2,
/// <summary>
/// 使用BSON的内部操作码类型
/// </summary>
InnerBson = 3, InnerBson = 3,
} }
/// <summary>
/// 操作码信息类
/// </summary>
public sealed class OpcodeInfo public sealed class OpcodeInfo
{ {
/// <summary>
/// 操作码
/// </summary>
public uint Code; public uint Code;
/// <summary>
/// 名称
/// </summary>
public string Name; public string Name;
} }
/// <summary>
/// ProtoBuf导出器类
/// </summary>
public sealed class ProtoBufExporter public sealed class ProtoBufExporter
{ {
private uint _aMessage; private uint _aMessage;
@@ -33,10 +57,13 @@ public sealed class ProtoBufExporter
private uint _aRouteResponse; private uint _aRouteResponse;
private string _serverTemplate; private string _serverTemplate;
private string _clientTemplate; private string _clientTemplate;
private readonly OpCodeCache _opCodeCache;
private readonly List<OpcodeInfo> _opcodes = new(); private readonly List<OpcodeInfo> _opcodes = new();
public ProtoBufExporter() /// <summary>
/// 构造函数,用于初始化导出器
/// </summary>
public ProtoBufExporter(bool regenerateOpCodeCache)
{ {
Console.OutputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8;
@@ -60,11 +87,13 @@ public sealed class ProtoBufExporter
Directory.CreateDirectory($"{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]; var tasks = new Task[2];
tasks[0] = Task.Run(RouteType); tasks[0] = Task.Run(RouteType);
tasks[1] = Task.Run(async () => tasks[1] = Task.Run(async () =>
@@ -75,6 +104,7 @@ public sealed class ProtoBufExporter
await Start(ProtoBufOpCodeType.InnerBson); await Start(ProtoBufOpCodeType.InnerBson);
}); });
Task.WaitAll(tasks); Task.WaitAll(tasks);
_opCodeCache.Save();
} }
private async Task Start(ProtoBufOpCodeType opCodeType) private async Task Start(ProtoBufOpCodeType opCodeType)
@@ -99,8 +129,9 @@ public sealed class ProtoBufExporter
opCodeName = "OuterOpcode"; opCodeName = "OuterOpcode";
saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate); saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate);
saveDirectory.Add(Define.ProtoBufClientDirectory, _clientTemplate); saveDirectory.Add(Define.ProtoBufClientDirectory, _clientTemplate);
files.Add($"{Define.ProtoBufDirectory}OuterMessage.proto"); var protoBufFiles = FileHelper.GetDirectoryFile(
files.AddRange(Directory.GetFiles($"{Define.ProtoBufDirectory}Outer").ToList()); $"{Define.ProtoBufDirectory}Outer", "*.proto", SearchOption.AllDirectories);
files.AddRange(protoBufFiles);
break; break;
} }
case ProtoBufOpCodeType.Inner: case ProtoBufOpCodeType.Inner:
@@ -114,8 +145,8 @@ public sealed class ProtoBufExporter
_aRouteResponse = Opcode.InnerRouteResponse + 1000; _aRouteResponse = Opcode.InnerRouteResponse + 1000;
opCodeName = "InnerOpcode"; opCodeName = "InnerOpcode";
saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate); saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate);
files.Add($"{Define.ProtoBufDirectory}InnerMessage.proto"); var protoBufFiles = FileHelper.GetDirectoryFile($"{Define.ProtoBufDirectory}Inner", "*.proto", SearchOption.AllDirectories);
files.AddRange(Directory.GetFiles($"{Define.ProtoBufDirectory}Inner").ToList()); files.AddRange(protoBufFiles);
break; break;
} }
case ProtoBufOpCodeType.InnerBson: case ProtoBufOpCodeType.InnerBson:
@@ -129,8 +160,8 @@ public sealed class ProtoBufExporter
_aRouteResponse = Opcode.InnerBsonRouteResponse + 1000; _aRouteResponse = Opcode.InnerBsonRouteResponse + 1000;
opCodeName = "InnerBsonOpcode"; opCodeName = "InnerBsonOpcode";
saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate); saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate);
files.Add($"{Define.ProtoBufDirectory}InnerBsonMessage.proto"); var protoBufFiles = FileHelper.GetDirectoryFile($"{Define.ProtoBufDirectory}InnerBosn", "*.proto", SearchOption.AllDirectories);
files.AddRange(Directory.GetFiles($"{Define.ProtoBufDirectory}Bson").ToList()); files.AddRange(protoBufFiles);
break; break;
} }
} }
@@ -143,6 +174,7 @@ public sealed class ProtoBufExporter
var isMsgHead = false; var isMsgHead = false;
string responseTypeStr = null; string responseTypeStr = null;
string customRouteType = null; string customRouteType = null;
var protoFileText = await File.ReadAllTextAsync(filePath); var protoFileText = await File.ReadAllTextAsync(filePath);
foreach (var line in protoFileText.Split('\n')) foreach (var line in protoFileText.Split('\n'))
@@ -176,17 +208,20 @@ public sealed class ProtoBufExporter
switch (parameterArray.Length) switch (parameterArray.Length)
{ {
case 2: case 2:
responseTypeStr = parameterArray[1].Trim(); {
break; if (parameter == "ICustomRouteMessage")
case 3:
{ {
customRouteType = parameterArray[1].Trim(); customRouteType = parameterArray[1].Trim();
break;
if (parameterArray.Length == 3)
{
responseTypeStr = parameterArray[2].Trim();
} }
responseTypeStr = parameterArray[1].Trim();
break;
}
case 3:
{
responseTypeStr = parameterArray[1].Trim();
customRouteType = parameterArray[2].Trim();
break; break;
} }
} }
@@ -216,7 +251,7 @@ public sealed class ProtoBufExporter
if (string.IsNullOrWhiteSpace(parameter) || parameter == "IMessage") 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}; }}"); file.AppendLine($"\t\tpublic uint OpCode() {{ return {opCodeName}.{className}; }}");
} }
else else
@@ -260,13 +295,13 @@ public sealed class ProtoBufExporter
case "IRequest": case "IRequest":
case "IBsonRequest": case "IBsonRequest":
{ {
opcodeInfo.Code += ++_aRequest; opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRequest);
break; break;
} }
case "IResponse": case "IResponse":
case "IBsonResponse": case "IBsonResponse":
{ {
opcodeInfo.Code += ++_aResponse; opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aResponse);
file.AppendLine("\t\t[ProtoMember(91, IsRequired = true)]"); file.AppendLine("\t\t[ProtoMember(91, IsRequired = true)]");
file.AppendLine("\t\tpublic uint ErrorCode { get; set; }"); file.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
break; break;
@@ -275,15 +310,15 @@ public sealed class ProtoBufExporter
{ {
if (parameter.EndsWith("RouteMessage") || parameter == "IRouteMessage") if (parameter.EndsWith("RouteMessage") || parameter == "IRouteMessage")
{ {
opcodeInfo.Code += ++_aRouteMessage; opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRouteMessage);
} }
else if (parameter.EndsWith("RouteRequest") || parameter == "IRouteRequest") else if (parameter.EndsWith("RouteRequest") || parameter == "IRouteRequest")
{ {
opcodeInfo.Code += ++_aRouteRequest; opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRouteRequest);
} }
else if (parameter.EndsWith("RouteResponse") || parameter == "IRouteResponse") 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\t[ProtoMember(91, IsRequired = true)]");
file.AppendLine("\t\tpublic uint ErrorCode { get; set; }"); file.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
} }
@@ -359,7 +394,6 @@ public sealed class ProtoBufExporter
var csFile = Path.Combine(directory, $"{opCodeName}.cs"); var csFile = Path.Combine(directory, $"{opCodeName}.cs");
await File.WriteAllTextAsync(csFile, file.ToString()); await File.WriteAllTextAsync(csFile, file.ToString());
} }
#endregion #endregion
} }
@@ -381,7 +415,7 @@ public sealed class ProtoBufExporter
continue; continue;
} }
var splits = currentLine.Split(new[] { "//" }, StringSplitOptions.RemoveEmptyEntries); var splits = currentLine.Split(new[] {"//"}, StringSplitOptions.RemoveEmptyEntries);
var routeTypeStr = splits[0].Split("=", StringSplitOptions.RemoveEmptyEntries); var routeTypeStr = splits[0].Split("=", StringSplitOptions.RemoveEmptyEntries);
routeTypeFileSb.Append($"\t\t{routeTypeStr[0].Trim()} = {routeTypeStr[1].Trim()},"); routeTypeFileSb.Append($"\t\t{routeTypeStr[0].Trim()} = {routeTypeStr[1].Trim()},");
@@ -479,6 +513,9 @@ public sealed class ProtoBufExporter
} }
} }
/// <summary>
/// 加载模板
/// </summary>
private void LoadTemplate() private void LoadTemplate()
{ {
string[] lines = File.ReadAllLines(Define.ProtoBufTemplatePath, Encoding.UTF8); string[] lines = File.ReadAllLines(Define.ProtoBufTemplatePath, Encoding.UTF8);
@@ -496,12 +533,12 @@ public sealed class ProtoBufExporter
flag = 1; flag = 1;
continue; continue;
} }
else if (trim.StartsWith("#else")) else if(trim.StartsWith("#else"))
{ {
flag = 2; flag = 2;
continue; continue;
} }
else if (trim.StartsWith($"#endif")) else if(trim.StartsWith($"#endif"))
{ {
flag = 0; flag = 0;
continue; continue;

View File

@@ -1,26 +1,29 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
namespace TEngine.Core namespace TEngine
{ {
/// <summary>
/// 文件操作助手类,提供了各种文件操作方法。
/// </summary>
public static class FileHelper public static class FileHelper
{ {
/// <summary> /// <summary>
/// 获取文件全路径。 /// 获取相对路径的完整路径。
/// </summary> /// </summary>
/// <param name="relativePath"></param> /// <param name="relativePath">相对路径。</param>
/// <returns></returns> /// <returns>完整路径。</returns>
public static string GetFullPath(string relativePath) public static string GetFullPath(string relativePath)
{ {
return Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), relativePath)); return Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), relativePath));
} }
/// <summary> /// <summary>
/// 拷贝文件到目标路径如果目标目录不存在会自动创建目录 /// 将文件复制到目标路径如果目标目录不存在会自动创建目录
/// </summary> /// </summary>
/// <param name="sourceFile"></param> /// <param name="sourceFile">源文件路径。</param>
/// <param name="destinationFile"></param> /// <param name="destinationFile">目标文件路径。</param>
/// <param name="overwrite"></param> /// <param name="overwrite">是否覆盖已存在的目标文件。</param>
public static void Copy(string sourceFile, string destinationFile, bool overwrite) public static void Copy(string sourceFile, string destinationFile, bool overwrite)
{ {
var directoriesByFilePath = GetDirectoriesByFilePath(destinationFile); var directoriesByFilePath = GetDirectoriesByFilePath(destinationFile);
@@ -39,10 +42,10 @@ namespace TEngine.Core
} }
/// <summary> /// <summary>
/// 获取文件路径内的所有文件夹路径 /// 获取文件路径内的所有文件夹路径
/// </summary> /// </summary>
/// <param name="filePath"></param> /// <param name="filePath">文件路径。</param>
/// <returns></returns> /// <returns>文件夹路径列表。</returns>
public static List<string> GetDirectoriesByFilePath(string filePath) public static List<string> GetDirectoriesByFilePath(string filePath)
{ {
var dir = ""; var dir = "";
@@ -59,11 +62,11 @@ namespace TEngine.Core
} }
/// <summary> /// <summary>
/// 文件夹所有内容拷贝的目标位置 /// 文件夹内的所有内容复制到目标位置
/// </summary> /// </summary>
/// <param name="sourceDirectory"></param> /// <param name="sourceDirectory">源文件夹路径。</param>
/// <param name="destinationDirectory"></param> /// <param name="destinationDirectory">目标文件夹路径。</param>
/// <param name="overwrite"></param> /// <param name="overwrite">是否覆盖已存在的文件。</param>
public static void CopyDirectory(string sourceDirectory, string destinationDirectory, bool overwrite) public static void CopyDirectory(string sourceDirectory, string destinationDirectory, bool overwrite)
{ {
// 创建目标文件夹 // 创建目标文件夹
@@ -101,9 +104,21 @@ namespace TEngine.Core
} }
/// <summary> /// <summary>
/// 清除文件夹里的所有文件 /// 获取目录下的所有文件
/// </summary> /// </summary>
/// <param name="folderPath"></param> /// <param name="folderPath">文件夹路径。</param>
/// <param name="searchPattern">需要查找的文件通配符</param>
/// <param name="searchOption">查找的类型</param>
/// <returns></returns>
public static string[] GetDirectoryFile(string folderPath, string searchPattern, SearchOption searchOption)
{
return Directory.GetFiles(folderPath, searchPattern, searchOption);
}
/// <summary>
/// 清空文件夹内的所有文件。
/// </summary>
/// <param name="folderPath">文件夹路径。</param>
public static void ClearDirectoryFile(string folderPath) public static void ClearDirectoryFile(string folderPath)
{ {
if (!Directory.Exists(folderPath)) if (!Directory.Exists(folderPath))