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.
852 lines
30 KiB
852 lines
30 KiB
3 years ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.IO;
|
||
|
using System.Linq;
|
||
|
using System.Reflection;
|
||
|
using System.Text;
|
||
|
using System.Text.RegularExpressions;
|
||
|
using System.Threading.Tasks;
|
||
|
using Microsoft.CodeAnalysis;
|
||
|
using Microsoft.CodeAnalysis.CSharp;
|
||
|
using Microsoft.CodeAnalysis.Emit;
|
||
|
using Microsoft.Extensions.Primitives;
|
||
|
using MongoDB.Bson;
|
||
|
using MongoDB.Bson.Serialization;
|
||
|
using OfficeOpenXml;
|
||
|
using ProtoBuf;
|
||
|
using LicenseContext = OfficeOpenXml.LicenseContext;
|
||
|
|
||
|
namespace ET
|
||
|
{
|
||
|
public enum ConfigType
|
||
|
{
|
||
|
c = 0,
|
||
|
s = 1,
|
||
|
}
|
||
|
|
||
|
class HeadInfo
|
||
|
{
|
||
|
public string FieldAttribute;
|
||
|
public string FieldDesc;
|
||
|
public string FieldName;
|
||
|
public string FieldType;
|
||
|
public int FieldIndex;
|
||
|
|
||
|
public HeadInfo(string cs, string desc, string name, string type, int index)
|
||
|
{
|
||
|
this.FieldAttribute = cs;
|
||
|
this.FieldDesc = desc;
|
||
|
this.FieldName = name;
|
||
|
this.FieldType = type;
|
||
|
this.FieldIndex = index;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 这里加个标签是为了防止编译时裁剪掉protobuf,因为整个tool工程没有用到protobuf,编译会去掉引用,然后动态编译就会出错
|
||
|
[ProtoContract]
|
||
|
class Table
|
||
|
{
|
||
|
public bool C;
|
||
|
public bool S;
|
||
|
public int Index;
|
||
|
public Dictionary<string, HeadInfo> HeadInfos = new Dictionary<string, HeadInfo>();
|
||
|
}
|
||
|
|
||
|
public static class ExcelExporter
|
||
|
{
|
||
|
private static string template;
|
||
|
|
||
|
public const string ClientClassDir = "../Unity/Codes/Model/Generate/Config";
|
||
|
public const string ServerClassDir = "../Server/Model/Generate/Config";
|
||
|
|
||
|
private const string excelDir = "../Excel";
|
||
|
|
||
|
private const string jsonDir = "../Excel/Json/{0}/{1}";
|
||
|
|
||
|
private const string clientProtoDir = "../Unity/Assets/Bundles/Config/{0}";
|
||
|
private const string serverProtoDir = "../Config/{0}";
|
||
|
private static Assembly[] configAssemblies = new Assembly[2];
|
||
|
|
||
|
private static Dictionary<string, Table> tables = new Dictionary<string, Table>();
|
||
|
private static Dictionary<string, ExcelPackage> packages = new Dictionary<string, ExcelPackage>();
|
||
|
|
||
|
// 表的前5行和前2列都有特殊作用
|
||
|
const int RealDataStartRow = 6; // 表中数据开始的行
|
||
|
const int RealDataStartCol = 3; // 表中数据开始的列
|
||
|
|
||
|
// for emum
|
||
|
// 快捷正则测试网址:https://regex101.com/
|
||
|
// example: 3.刀|Knife
|
||
|
private const string enumPattern = @"[0-9]*[.](.*?)[|]\w+";
|
||
|
private const string enumClientFilePath = "../Unity/Codes/Model/Generate/ConfigEnum.cs";
|
||
|
private const string enumServerFilePath = "../Server/Model/Generate/ConfigEnum.cs";
|
||
|
private static FileStream enumClientFileStream = new FileStream(enumClientFilePath, FileMode.Create);
|
||
|
private static StreamWriter enumClientFileStreamWriter = new StreamWriter(enumClientFileStream);
|
||
|
private static FileStream enumServerFileStream = new FileStream(enumServerFilePath, FileMode.Create);
|
||
|
private static StreamWriter enumServerFileStreamWriter = new StreamWriter(enumServerFileStream);
|
||
|
|
||
|
// private static string skillModelClassTemplate;
|
||
|
private const string skillEditorDataDir = "../Unity/Assets/Editor/SkillEditor/ModelClass";
|
||
|
|
||
|
private static Table GetTable(string protoName)
|
||
|
{
|
||
|
if (!tables.TryGetValue(protoName, out var table))
|
||
|
{
|
||
|
table = new Table();
|
||
|
tables[protoName] = table;
|
||
|
}
|
||
|
|
||
|
return table;
|
||
|
}
|
||
|
|
||
|
public static ExcelPackage GetPackage(string filePath)
|
||
|
{
|
||
|
if (!packages.TryGetValue(filePath, out var package))
|
||
|
{
|
||
|
using Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||
|
package = new ExcelPackage(stream);
|
||
|
packages[filePath] = package;
|
||
|
}
|
||
|
|
||
|
return package;
|
||
|
}
|
||
|
|
||
|
public static void Export()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
template = File.ReadAllText("Template.txt");
|
||
|
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
|
||
|
|
||
|
ExportAttri();
|
||
|
ExportWorldParam();
|
||
|
ExportTextConfig();
|
||
|
|
||
|
if (Directory.Exists(ClientClassDir))
|
||
|
{
|
||
|
Directory.Delete(ClientClassDir, true);
|
||
|
}
|
||
|
|
||
|
if (Directory.Exists(ServerClassDir))
|
||
|
{
|
||
|
Directory.Delete(ServerClassDir, true);
|
||
|
}
|
||
|
|
||
|
enumClientFileStreamWriter.WriteLine("namespace ET");
|
||
|
enumClientFileStreamWriter.WriteLine("{");
|
||
|
enumServerFileStreamWriter.WriteLine("namespace ET");
|
||
|
enumServerFileStreamWriter.WriteLine("{");
|
||
|
|
||
|
foreach (string path in Directory.GetFiles(excelDir))
|
||
|
{
|
||
|
string fileName = Path.GetFileName(path);
|
||
|
if (!fileName.EndsWith(".xlsx") || fileName.StartsWith("~$") || fileName.Contains("#"))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
|
||
|
string fileNameWithoutCS = fileNameWithoutExtension;
|
||
|
string cs = "cs";
|
||
|
if (fileNameWithoutExtension.Contains("@"))
|
||
|
{
|
||
|
string[] ss = fileNameWithoutExtension.Split("@");
|
||
|
fileNameWithoutCS = ss[0];
|
||
|
cs = ss[1];
|
||
|
}
|
||
|
|
||
|
if (cs == "")
|
||
|
{
|
||
|
cs = "cs";
|
||
|
}
|
||
|
|
||
|
ExcelPackage p = GetPackage(Path.GetFullPath(path));
|
||
|
|
||
|
string firstCellContent = p.Workbook.Worksheets[0].Cells[1, 1].Text.Trim();
|
||
|
if (firstCellContent.Contains("#"))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
string protoName = fileNameWithoutCS;
|
||
|
if (fileNameWithoutCS.Contains('_'))
|
||
|
{
|
||
|
protoName = fileNameWithoutCS.Substring(0, fileNameWithoutCS.LastIndexOf('_'));
|
||
|
}
|
||
|
|
||
|
Table table = GetTable(protoName);
|
||
|
|
||
|
if (cs.Contains("c"))
|
||
|
{
|
||
|
table.C = true;
|
||
|
}
|
||
|
|
||
|
if (cs.Contains("s"))
|
||
|
{
|
||
|
table.S = true;
|
||
|
}
|
||
|
|
||
|
ExportExcelClass(p, protoName, table);
|
||
|
Log.Console("ExportExcelClass {0}",fileName);
|
||
|
}
|
||
|
|
||
|
enumClientFileStreamWriter.WriteLine("}");
|
||
|
enumClientFileStreamWriter.Close();
|
||
|
enumClientFileStream.Close();
|
||
|
|
||
|
enumServerFileStreamWriter.WriteLine("}");
|
||
|
enumServerFileStreamWriter.Close();
|
||
|
enumServerFileStream.Close();
|
||
|
|
||
|
foreach (var kv in tables)
|
||
|
{
|
||
|
if (kv.Value.C)
|
||
|
{
|
||
|
ExportClass(kv.Key, kv.Value.HeadInfos, ConfigType.c);
|
||
|
}
|
||
|
|
||
|
if (kv.Value.S)
|
||
|
{
|
||
|
ExportClass(kv.Key, kv.Value.HeadInfos, ConfigType.s);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 动态编译生成的配置代码
|
||
|
configAssemblies[(int) ConfigType.c] = DynamicBuild(ConfigType.c);
|
||
|
configAssemblies[(int) ConfigType.s] = DynamicBuild(ConfigType.s);
|
||
|
|
||
|
foreach (string path in Directory.GetFiles(excelDir))
|
||
|
{
|
||
|
ExportExcel(path);
|
||
|
}
|
||
|
|
||
|
// 多线程导出
|
||
|
//List<Task> tasks = new List<Task>();
|
||
|
//foreach (string path in Directory.GetFiles(excelDir))
|
||
|
//{
|
||
|
// Task task = Task.Run(() => ExportExcel(path));
|
||
|
// tasks.Add(task);
|
||
|
//}
|
||
|
//Task.WaitAll(tasks.ToArray());
|
||
|
|
||
|
// 导出StartConfig
|
||
|
string startConfigPath = Path.Combine(excelDir, "StartConfig");
|
||
|
DirectoryInfo directoryInfo = new DirectoryInfo(startConfigPath);
|
||
|
foreach (FileInfo subStartConfig in directoryInfo.GetFiles("*", SearchOption.AllDirectories))
|
||
|
{
|
||
|
ExportExcel(subStartConfig.FullName);
|
||
|
}
|
||
|
|
||
|
Log.Console("Export Excel Sucess!");
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
Log.Console(e.ToString());
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
tables.Clear();
|
||
|
foreach (var kv in packages)
|
||
|
{
|
||
|
kv.Value.Dispose();
|
||
|
}
|
||
|
|
||
|
packages.Clear();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void ExportExcel(string path)
|
||
|
{
|
||
|
string dir = Path.GetDirectoryName(path);
|
||
|
string relativePath = Path.GetRelativePath(excelDir, dir);
|
||
|
string fileName = Path.GetFileName(path);
|
||
|
if (!fileName.EndsWith(".xlsx") || fileName.StartsWith("~$") || fileName.Contains("#"))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
|
||
|
string fileNameWithoutCS = fileNameWithoutExtension;
|
||
|
string cs = "cs";
|
||
|
if (fileNameWithoutExtension.Contains("@"))
|
||
|
{
|
||
|
string[] ss = fileNameWithoutExtension.Split("@");
|
||
|
fileNameWithoutCS = ss[0];
|
||
|
cs = ss[1];
|
||
|
}
|
||
|
|
||
|
if (cs == "")
|
||
|
{
|
||
|
cs = "cs";
|
||
|
}
|
||
|
|
||
|
string protoName = fileNameWithoutCS;
|
||
|
if (fileNameWithoutCS.Contains('_'))
|
||
|
{
|
||
|
protoName = fileNameWithoutCS.Substring(0, fileNameWithoutCS.LastIndexOf('_'));
|
||
|
}
|
||
|
|
||
|
Table table = GetTable(protoName);
|
||
|
|
||
|
ExcelPackage p = GetPackage(Path.GetFullPath(path));
|
||
|
|
||
|
if (cs.Contains("c"))
|
||
|
{
|
||
|
ExportExcelJson(p, fileNameWithoutCS, table, ConfigType.c, relativePath);
|
||
|
ExportExcelProtobuf(ConfigType.c, protoName, relativePath);
|
||
|
}
|
||
|
|
||
|
if (cs.Contains("s"))
|
||
|
{
|
||
|
ExportExcelJson(p, fileNameWithoutCS, table, ConfigType.s, relativePath);
|
||
|
ExportExcelProtobuf(ConfigType.s, protoName, relativePath);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static string GetProtoDir(ConfigType configType, string relativeDir)
|
||
|
{
|
||
|
if (configType == ConfigType.c)
|
||
|
{
|
||
|
return string.Format(clientProtoDir, relativeDir);
|
||
|
}
|
||
|
|
||
|
return string.Format(serverProtoDir, relativeDir);
|
||
|
}
|
||
|
|
||
|
private static Assembly GetAssembly(ConfigType configType)
|
||
|
{
|
||
|
return configAssemblies[(int) configType];
|
||
|
}
|
||
|
|
||
|
private static string GetClassDir(ConfigType configType)
|
||
|
{
|
||
|
if (configType == ConfigType.c)
|
||
|
{
|
||
|
return ClientClassDir;
|
||
|
}
|
||
|
|
||
|
return ServerClassDir;
|
||
|
}
|
||
|
|
||
|
// 动态编译生成的cs代码
|
||
|
private static Assembly DynamicBuild(ConfigType configType)
|
||
|
{
|
||
|
string classPath = GetClassDir(configType);
|
||
|
List<SyntaxTree> syntaxTrees = new List<SyntaxTree>();
|
||
|
List<string> protoNames = new List<string>();
|
||
|
foreach (string classFile in Directory.GetFiles(classPath, "*.cs"))
|
||
|
{
|
||
|
protoNames.Add(Path.GetFileNameWithoutExtension(classFile));
|
||
|
syntaxTrees.Add(CSharpSyntaxTree.ParseText(File.ReadAllText(classFile)));
|
||
|
}
|
||
|
|
||
|
List<PortableExecutableReference> references = new List<PortableExecutableReference>();
|
||
|
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||
|
foreach (Assembly assembly in assemblies)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
if (assembly.IsDynamic)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (assembly.Location == "")
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
Console.WriteLine(e);
|
||
|
throw;
|
||
|
}
|
||
|
|
||
|
PortableExecutableReference reference = MetadataReference.CreateFromFile(assembly.Location);
|
||
|
references.Add(reference);
|
||
|
}
|
||
|
|
||
|
CSharpCompilation compilation = CSharpCompilation.Create(null,
|
||
|
syntaxTrees.ToArray(),
|
||
|
references.ToArray(),
|
||
|
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
|
||
|
|
||
|
using MemoryStream memSteam = new MemoryStream();
|
||
|
|
||
|
EmitResult emitResult = compilation.Emit(memSteam);
|
||
|
if (!emitResult.Success)
|
||
|
{
|
||
|
StringBuilder stringBuilder = new StringBuilder();
|
||
|
foreach (Diagnostic t in emitResult.Diagnostics)
|
||
|
{
|
||
|
stringBuilder.AppendLine(t.GetMessage());
|
||
|
}
|
||
|
|
||
|
throw new Exception($"动态编译失败:\n{stringBuilder}");
|
||
|
}
|
||
|
|
||
|
memSteam.Seek(0, SeekOrigin.Begin);
|
||
|
|
||
|
Assembly ass = Assembly.Load(memSteam.ToArray());
|
||
|
return ass;
|
||
|
}
|
||
|
|
||
|
|
||
|
#region 导出class
|
||
|
|
||
|
static void ExportExcelClass(ExcelPackage p, string name, Table table)
|
||
|
{
|
||
|
foreach (ExcelWorksheet worksheet in p.Workbook.Worksheets)
|
||
|
{
|
||
|
if (worksheet.Name.StartsWith("#") || worksheet.Dimension==null)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
ExportSheetClass(name, worksheet, table);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void ExportSheetClass(string protoName, ExcelWorksheet worksheet, Table table)
|
||
|
{
|
||
|
const int row = 2;
|
||
|
string protoNameWithoutConfig = protoName;
|
||
|
if (protoNameWithoutConfig.EndsWith("Config"))
|
||
|
{
|
||
|
protoNameWithoutConfig = protoNameWithoutConfig.Substring(0, protoNameWithoutConfig.Length - 6);
|
||
|
}
|
||
|
for (int col = 3; col <= worksheet.Dimension.End.Column; ++col)
|
||
|
{
|
||
|
if (worksheet.Name.StartsWith("#"))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
string fieldName = worksheet.Cells[row + 2, col].Text.Trim();
|
||
|
if (fieldName == "")
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (table.HeadInfos.ContainsKey(fieldName))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
string fieldCS = worksheet.Cells[row, col].Text.Trim().ToLower();
|
||
|
string firstField = worksheet.Cells[1, col].Text.Trim().ToLower();
|
||
|
bool isEnumType = false;
|
||
|
if (firstField.Contains("#enum"))
|
||
|
{
|
||
|
// 只写客户端的,否则会重复
|
||
|
if (table.C)
|
||
|
{
|
||
|
ExportEnum(enumClientFileStreamWriter, protoNameWithoutConfig, fieldName, firstField);
|
||
|
}
|
||
|
|
||
|
if (table.S)
|
||
|
{
|
||
|
ExportEnum(enumServerFileStreamWriter, protoNameWithoutConfig, fieldName, firstField);
|
||
|
}
|
||
|
isEnumType = true;
|
||
|
}
|
||
|
|
||
|
if (fieldCS.Contains("#")|| (firstField.Contains("#")&&!isEnumType))
|
||
|
{
|
||
|
table.HeadInfos[fieldName] = null;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (fieldCS == ""|| fieldCS.Length>2)
|
||
|
{
|
||
|
fieldCS = "cs";
|
||
|
}
|
||
|
|
||
|
if (table.HeadInfos.TryGetValue(fieldName, out var oldClassField))
|
||
|
{
|
||
|
if (oldClassField.FieldAttribute != fieldCS)
|
||
|
{
|
||
|
Log.Console($"field cs not same: {worksheet.Name} {fieldName} oldcs: {oldClassField.FieldAttribute} {fieldCS}");
|
||
|
}
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
string fieldDesc = worksheet.Cells[row + 1, col].Text.Trim();
|
||
|
string fieldType = worksheet.Cells[row + 3, col].Text.Trim();
|
||
|
|
||
|
table.HeadInfos[fieldName] = new HeadInfo(fieldCS, fieldDesc, fieldName, fieldType, ++table.Index);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void ExportClass(string protoName, Dictionary<string, HeadInfo> classField, ConfigType configType)
|
||
|
{
|
||
|
string dir = GetClassDir(configType);
|
||
|
if (!Directory.Exists(dir))
|
||
|
{
|
||
|
Directory.CreateDirectory(dir);
|
||
|
}
|
||
|
|
||
|
string exportPath = Path.Combine(dir, $"{protoName}.cs");
|
||
|
|
||
|
using FileStream txt = new FileStream(exportPath, FileMode.Create);
|
||
|
using StreamWriter sw = new StreamWriter(txt);
|
||
|
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
foreach ((string _, HeadInfo headInfo) in classField)
|
||
|
{
|
||
|
if (headInfo == null)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (headInfo.FieldType == "json")
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!headInfo.FieldAttribute.Contains(configType.ToString()))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
sb.Append($"\t\t/// <summary>{headInfo.FieldDesc}</summary>\n");
|
||
|
sb.Append($"\t\t[ProtoMember({headInfo.FieldIndex})]\n");
|
||
|
string fieldType = headInfo.FieldType;
|
||
|
if (fieldType == "int[][]")
|
||
|
{
|
||
|
fieldType = "string[]";
|
||
|
}
|
||
|
|
||
|
sb.Append($"\t\tpublic {fieldType} {headInfo.FieldName} {{ get; set; }}\n");
|
||
|
}
|
||
|
|
||
|
string content = template.Replace("(ConfigName)", protoName).Replace(("(Fields)"), sb.ToString());
|
||
|
sw.Write(content);
|
||
|
Log.Console("ExportClass {0}",protoName);
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
#region 导出json
|
||
|
|
||
|
|
||
|
static void ExportExcelJson(ExcelPackage p, string name, Table table, ConfigType configType, string relativeDir)
|
||
|
{
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
sb.AppendLine("{\"list\":[");
|
||
|
foreach (ExcelWorksheet worksheet in p.Workbook.Worksheets)
|
||
|
{
|
||
|
if (worksheet.Name.StartsWith("#")||worksheet.Dimension==null)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ExportSheetJson(worksheet, name, table.HeadInfos, configType, sb);
|
||
|
}
|
||
|
|
||
|
sb.AppendLine("]}");
|
||
|
|
||
|
string dir = string.Format(jsonDir, configType.ToString(), relativeDir);
|
||
|
if (!Directory.Exists(dir))
|
||
|
{
|
||
|
Directory.CreateDirectory(dir);
|
||
|
}
|
||
|
|
||
|
string jsonPath = Path.Combine(dir, $"{name}.txt");
|
||
|
using FileStream txt = new FileStream(jsonPath, FileMode.Create);
|
||
|
using StreamWriter sw = new StreamWriter(txt);
|
||
|
sw.Write(sb.ToString());
|
||
|
Log.Console("ExportExcelJson {0}",name);
|
||
|
}
|
||
|
|
||
|
static void ExportSheetJson(ExcelWorksheet worksheet, string name,
|
||
|
Dictionary<string, HeadInfo> classField, ConfigType configType, StringBuilder sb)
|
||
|
{
|
||
|
string configTypeStr = configType.ToString();
|
||
|
for (int row = 6; row <= worksheet.Dimension.End.Row; ++row)
|
||
|
{
|
||
|
string prefix = worksheet.Cells[row, 2].Text.Trim();
|
||
|
if (prefix.Contains("#"))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (prefix == "")
|
||
|
{
|
||
|
prefix = "cs";
|
||
|
}
|
||
|
|
||
|
if (!prefix.Contains(configTypeStr))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (worksheet.Cells[row, 3].Text.Trim() == "")
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
sb.Append("{");
|
||
|
sb.Append($"\"_t\":\"{name}\"");
|
||
|
for (int col = 3; col <= worksheet.Dimension.End.Column; ++col)
|
||
|
{
|
||
|
string fieldName = worksheet.Cells[4, col].Text.Trim();
|
||
|
if (!classField.ContainsKey(fieldName))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
HeadInfo headInfo = classField[fieldName];
|
||
|
|
||
|
if (headInfo == null)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!headInfo.FieldAttribute.Contains(configTypeStr))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (headInfo.FieldType == "json")
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
string fieldN = headInfo.FieldName;
|
||
|
if (fieldN == "Id")
|
||
|
{
|
||
|
fieldN = "_id";
|
||
|
}
|
||
|
|
||
|
sb.Append($",\"{fieldN}\":{Convert(headInfo.FieldType, worksheet.Cells[row, col].Text.Trim())}");
|
||
|
}
|
||
|
|
||
|
sb.Append("},\n");
|
||
|
}
|
||
|
Log.Console("ExportSheetJson {0}",name);
|
||
|
}
|
||
|
|
||
|
private static string Convert(string type, string value)
|
||
|
{
|
||
|
switch (type)
|
||
|
{
|
||
|
case "uint[]":
|
||
|
case "int[]":
|
||
|
case "int32[]":
|
||
|
case "long[]":
|
||
|
// {
|
||
|
// value = value.Replace("{", "").Replace("}", "");
|
||
|
// return $"[{value}]";
|
||
|
// }
|
||
|
return $"[{value}]";
|
||
|
case "string[]":
|
||
|
var temp = ConvertStringArr(value);
|
||
|
return $"[{temp}]";
|
||
|
case "int[][]":
|
||
|
return $"[{value}]";
|
||
|
case "int":
|
||
|
case "uint":
|
||
|
case "int32":
|
||
|
case "int64":
|
||
|
case "long":
|
||
|
case "float":
|
||
|
case "double":
|
||
|
{
|
||
|
value = value.Replace("{", "").Replace("}", "");
|
||
|
if (value == "")
|
||
|
{
|
||
|
return "0";
|
||
|
}
|
||
|
return value;
|
||
|
}
|
||
|
case "string":
|
||
|
return $"\"{value}\"";
|
||
|
case "AttrConfig":
|
||
|
string[] ss = value.Split(':');
|
||
|
return "{\"_t\":\"AttrConfig\"," + "\"Ks\":" + ss[0] + ",\"Vs\":" + ss[1] + "}";
|
||
|
default:
|
||
|
throw new Exception($"不支持此类型: {type}");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static string ConvertStringArr(string value)
|
||
|
{
|
||
|
var strList = value.Split(",");
|
||
|
string temp = "";
|
||
|
foreach (var v in strList)
|
||
|
{
|
||
|
if (temp.Length > 0)
|
||
|
{
|
||
|
temp = temp + ",";
|
||
|
}
|
||
|
|
||
|
temp = temp + "\"" + v + "\"";
|
||
|
}
|
||
|
|
||
|
return temp;
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
|
||
|
// 根据生成的类,把json转成protobuf
|
||
|
private static void ExportExcelProtobuf(ConfigType configType, string protoName, string relativeDir)
|
||
|
{
|
||
|
string dir = GetProtoDir(configType, relativeDir);
|
||
|
if (!Directory.Exists(dir))
|
||
|
{
|
||
|
Directory.CreateDirectory(dir);
|
||
|
}
|
||
|
|
||
|
Assembly ass = GetAssembly(configType);
|
||
|
Type type = ass.GetType($"ET.{protoName}Category");
|
||
|
Type subType = ass.GetType($"ET.{protoName}");
|
||
|
|
||
|
Serializer.NonGeneric.PrepareSerializer(type);
|
||
|
Serializer.NonGeneric.PrepareSerializer(subType);
|
||
|
|
||
|
IMerge final = Activator.CreateInstance(type) as IMerge;
|
||
|
|
||
|
string p = Path.Combine(string.Format(jsonDir, configType, relativeDir));
|
||
|
string[] ss = Directory.GetFiles(p, $"{protoName}_*.txt");
|
||
|
List<string> jsonPaths = ss.ToList();
|
||
|
jsonPaths.Add(Path.Combine(string.Format(jsonDir, configType, relativeDir), $"{protoName}.txt"));
|
||
|
|
||
|
jsonPaths.Sort();
|
||
|
jsonPaths.Reverse();
|
||
|
foreach (string jsonPath in jsonPaths)
|
||
|
{
|
||
|
string json = File.ReadAllText(jsonPath);
|
||
|
object deserialize = BsonSerializer.Deserialize(json, type);
|
||
|
final.Merge(deserialize);
|
||
|
}
|
||
|
|
||
|
string path = Path.Combine(dir, $"{protoName}Category.bytes");
|
||
|
|
||
|
using FileStream file = File.Create(path);
|
||
|
Serializer.Serialize(file, final);
|
||
|
}
|
||
|
|
||
|
public static void ExportAttri()
|
||
|
{
|
||
|
string path = "../Excel/AttributesConfig.xlsx";
|
||
|
string classPath = "../Unity/Codes/Model/Module/Numeric/NumericType.cs";
|
||
|
using Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||
|
using ExcelPackage p = new ExcelPackage(stream);
|
||
|
var worksheet = p.Workbook.Worksheets[0];
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
int fieldCol = 0;
|
||
|
sb.Append("namespace ET\n{\n");
|
||
|
sb.Append("\tpublic static partial class NumericType\n\t{");
|
||
|
//找出属性名字
|
||
|
for (int col = 3; col <= worksheet.Dimension.End.Column; col++)
|
||
|
{
|
||
|
if (worksheet.Cells[4, col].Text.Trim() == "Field")
|
||
|
{
|
||
|
fieldCol = col;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
for (int row = 6; row <= worksheet.Dimension.End.Row; ++row)
|
||
|
{
|
||
|
sb.Append("\n\t\tpublic const int "+worksheet.Cells[row, fieldCol].Text.Trim()+" = " + worksheet.Cells[row, 3].Text.Trim()+"; // "+
|
||
|
worksheet.Cells[row, 4].Text.Trim());
|
||
|
|
||
|
}
|
||
|
sb.Append("\n }\n}");
|
||
|
using FileStream txt = new FileStream(classPath, FileMode.Create);
|
||
|
using StreamWriter sw = new StreamWriter(txt);
|
||
|
sw.Write(sb.ToString());
|
||
|
|
||
|
}
|
||
|
|
||
|
public static void ExportWorldParam()
|
||
|
{
|
||
|
string path = "../Excel/WorldParametersConfig.xlsx";
|
||
|
string classPath = "../Unity/Codes/Hotfix/Demo/WorldParam.cs";
|
||
|
using Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||
|
using ExcelPackage p = new ExcelPackage(stream);
|
||
|
var worksheet = p.Workbook.Worksheets[0];
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
int fieldCol = 0;
|
||
|
sb.Append("namespace ET\n{\n");
|
||
|
sb.Append("\tpublic static class WorldParam\n\t{");
|
||
|
//找出属性名字
|
||
|
for (int col = 3; col <= worksheet.Dimension.End.Column; col++)
|
||
|
{
|
||
|
if (worksheet.Cells[4, col].Text.Trim() == "Field")
|
||
|
{
|
||
|
fieldCol = col;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
for (int row = 6; row <= worksheet.Dimension.End.Row; ++row)
|
||
|
{
|
||
|
sb.Append("\n\t\tpublic const int "+worksheet.Cells[row, fieldCol].Text.Trim()+" = " + worksheet.Cells[row, 3].Text.Trim()+"; //"+
|
||
|
worksheet.Cells[row, 4].Text.Trim());
|
||
|
|
||
|
}
|
||
|
sb.Append("\n }\n}");
|
||
|
using FileStream txt = new FileStream(classPath, FileMode.Create);
|
||
|
using StreamWriter sw = new StreamWriter(txt);
|
||
|
sw.Write(sb.ToString());
|
||
|
|
||
|
}
|
||
|
|
||
|
static void ExportEnum(StreamWriter sw, string protoNameWithoutConfig, string fieldFname, string firstFieldText)
|
||
|
{
|
||
|
var matchs = Regex.Matches(firstFieldText, enumPattern);
|
||
|
if (matchs.Count > 0)
|
||
|
{
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
sb.AppendLine($"\tpublic enum {protoNameWithoutConfig}{fieldFname}Enum");
|
||
|
sb.AppendLine("\t{");
|
||
|
foreach (Match match in matchs)
|
||
|
{
|
||
|
string enumStr = match.Value;
|
||
|
int firstDotIndx = enumStr.IndexOf('.');
|
||
|
string enumIndex = enumStr.Substring(0, firstDotIndx);
|
||
|
int spiltIndex = enumStr.LastIndexOf('|');
|
||
|
string enumZHName = enumStr.Substring(firstDotIndx+1, spiltIndex - firstDotIndx - 1);
|
||
|
string enumName = enumStr.Substring(spiltIndex+1);
|
||
|
sb.Append($"\t\t// {enumZHName}\n");
|
||
|
sb.Append($"\t\t{enumName.ToUpper()} = {enumIndex},\n");
|
||
|
}
|
||
|
sb.AppendLine("\t}");
|
||
|
|
||
|
sw.Write(sb);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Console.WriteLine($"枚举生成错误:表 {protoNameWithoutConfig}Config 中的属性 {fieldFname} 的枚举配置不对");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static void ExportTextConfig()
|
||
|
{
|
||
|
string path = "../Excel/TextConfig.xlsx";
|
||
|
string classPath = "../Unity/Codes/ModelView/Demo/Common/TextConfigEnum.cs";
|
||
|
using Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||
|
using ExcelPackage p = new ExcelPackage(stream);
|
||
|
var worksheet = p.Workbook.Worksheets[0];
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
int idCol = 3;
|
||
|
int textCol = 4;
|
||
|
sb.Append("namespace ET\n{\n");
|
||
|
sb.Append("\tpublic enum TextConfigEnum\n\t{");
|
||
|
|
||
|
for (int row = 6; row <= worksheet.Dimension.End.Row; ++row)
|
||
|
{
|
||
|
sb.Append("\n\t\t" + "/// <summary>"+worksheet.Cells[row, textCol].Text.Trim() + "</summary>");
|
||
|
sb.Append("\n\t\t" + "ID_"+worksheet.Cells[row, idCol].Text.Trim()+" = " + worksheet.Cells[row, idCol].Text.Trim()+",");
|
||
|
|
||
|
}
|
||
|
sb.Append("\n }\n}");
|
||
|
using FileStream txt = new FileStream(classPath, FileMode.Create);
|
||
|
using StreamWriter sw = new StreamWriter(txt);
|
||
|
sw.Write(sb.ToString());
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|