main
walon 2021-10-12 16:05:10 +08:00
parent 48c2ce74b7
commit 4e7c993d53
17 changed files with 556 additions and 123 deletions

View File

@ -23,7 +23,7 @@ namespace Luban.Common.Utils
public static string GetFileName(string path)
{
int index = path.Replace('\\', '/').LastIndexOf('/');
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
return index >= 0 ? path[(index + 1)..] : path;
#else
return index >= 0 ? path.Substring(index + 1, path.Length - index - 1) : path;
@ -33,7 +33,7 @@ namespace Luban.Common.Utils
public static string GetParent(string path)
{
int index = path.Replace('\\', '/').LastIndexOf('/');
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
return index >= 0 ? path[..index] : ".";
#else
return index >= 0 ? path.Substring(0, index) : ".";
@ -70,7 +70,7 @@ namespace Luban.Common.Utils
}
var f = new FileInfo(file);
string fname = f.Name;
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
return !fname.StartsWith('.') && !fname.StartsWith('_') && !fname.StartsWith('~');
#else
return !fname.StartsWith(".") && !fname.StartsWith("_") && !fname.StartsWith("~");
@ -129,7 +129,7 @@ namespace Luban.Common.Utils
else
{
int lastPathSep = url.LastIndexOf('/', sheetSepIndex);
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
if (lastPathSep >= 0)
{
return (url[0..(lastPathSep + 1)] + url[(sheetSepIndex + 1)..], url[(lastPathSep + 1)..sheetSepIndex]);
@ -183,7 +183,7 @@ namespace Luban.Common.Utils
}
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
await File.WriteAllBytesAsync(outputPath, content);
#else
await Task.Run(() => File.WriteAllBytes(outputPath, content));

View File

@ -22,7 +22,7 @@ namespace Luban.Job.Cfg.DataSources
{
try
{
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
string ext = url.Contains('.') ? Path.GetExtension(url)?[1..] : url;
#else
string ext = url.Contains(".") ? Path.GetExtension(url)?.Substring(1) : url;

View File

@ -140,7 +140,7 @@ namespace Luban.Job.Cfg.Defs
{
if (!string.IsNullOrWhiteSpace(attr))
{
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
foreach (var validatorStr in attr.Split('#', StringSplitOptions.RemoveEmptyEntries))
#else
foreach (var validatorStr in attr.Split('#'))
@ -151,7 +151,7 @@ namespace Luban.Job.Cfg.Defs
{
throw new Exception($"定义文件:{defineFile} key:'{key}' attr:'{attr}' 不是合法的 validator 定义 (key1:value1#key2:value2 ...)");
}
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
result.Add(new Validator() { Type = validatorStr[..sepIndex], Rule = validatorStr[(sepIndex + 1)..] });
#else
result.Add(new Validator() { Type = validatorStr.Substring(0, sepIndex), Rule = validatorStr.Substring(sepIndex + 1, validatorStr.Length - sepIndex - 1) });
@ -365,7 +365,7 @@ namespace Luban.Job.Cfg.Defs
for (int i = 1; i < attrs.Length; i++)
{
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
var pair = attrs[i].Split('=', 2);
#else
var pair = attrs[i].Split(new char[] { '=' }, 2);

View File

@ -31,7 +31,7 @@ namespace Luban.Job.Cfg.Defs
return DeepCompareTypeDefine.Ins.Compare(this, b, new Dictionary<DefTypeBase, bool>(), new HashSet<DefTypeBase>());
}
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
public string GoBinImport
{
get
@ -219,7 +219,11 @@ namespace Luban.Job.Cfg.Defs
Id = TypeUtil.ComputCfgHashIdByName(FullName);
}
// 检查别名是否重复
#if !LUBAN_LITE
HashSet<string> nameOrAliasName = cs.Select(b => b.Name).ToHashSet();
#else
HashSet<string> nameOrAliasName = new HashSet<string>(cs.Select(b => b.Name));
#endif
foreach (DefBean c in cs)
{
if (!string.IsNullOrWhiteSpace(c.Alias) && !nameOrAliasName.Add(c.Alias))

View File

@ -104,7 +104,7 @@ namespace Luban.Job.Cfg.TypeVisitors
|| f1.NeedExport != f2.NeedExport
|| f1.Index != f2.Index
|| f1.Sep != f2.Sep
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
|| f1.ResourceTag != f2.ResourceTag
#endif
|| f1.IsMultiRow != f2.IsMultiRow

View File

@ -16,7 +16,7 @@ namespace Luban.Job.Cfg.Validators
public static string GetActualTableName(string table)
{
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
return table.EndsWith("?") ? table[0..^1] : table;
#else
return table.EndsWith("?") ? table.Substring(0, table.Length - 1) : table;
@ -44,7 +44,7 @@ namespace Luban.Job.Cfg.Validators
if (table.EndsWith("?"))
{
zeroAble = true;
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
actualTable = table[0..^1];
#else
actualTable = table.Substring(0, table.Length - 1);
@ -72,7 +72,7 @@ namespace Luban.Job.Cfg.Validators
string actualTable;
if (table.EndsWith("?"))
{
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
actualTable = table[0..^1];
#else
actualTable = table.Substring(0, table.Length - 1);
@ -97,7 +97,7 @@ namespace Luban.Job.Cfg.Validators
foreach (var table in Tables)
{
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
string actualTable = table.EndsWith("?") ? table[0..^1] : table;
#else
string actualTable = table.EndsWith("?") ? table.Substring(0, table.Length - 1) : table;

View File

@ -117,7 +117,7 @@ namespace Luban.Job.Common.Defs
public TType CreateType(string module, string type)
{
#if LUBAN_ASSISTANT
#if LUBAN_LITE
int sepIndex = type.IndexOf(',');
#else
int sepIndex = type.IndexOf(',', System.StringComparison.Ordinal);
@ -138,7 +138,7 @@ namespace Luban.Job.Common.Defs
bool nullable;
var (type, tags) = DefUtil.ParseType(rawType);
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
if (type.EndsWith('?'))
#else
if (type.EndsWith("?"))
@ -149,7 +149,7 @@ namespace Luban.Job.Common.Defs
throw new Exception($"not support nullable type:'{module}.{type}'");
}
nullable = true;
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
type = type[0..^1];
#else
type = type.Substring(0, type.Length - 1);

View File

@ -21,7 +21,7 @@ namespace Luban.Job.Common.Utils
int sepIndex = pair.IndexOfAny(s_attrKeyValueSep);
if (sepIndex >= 0)
{
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
am.Add(pair[..sepIndex].Trim(), pair[(sepIndex + 1)..].Trim());
#else
am.Add(pair.Substring(0, sepIndex).Trim(), pair.Substring(sepIndex + 1).Trim());
@ -44,7 +44,7 @@ namespace Luban.Job.Common.Utils
}
else
{
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
return (s[..sepIndex], ParseAttrs(s[(sepIndex + 1)..]));
#else
return (s.Substring(0, sepIndex), ParseAttrs(s.Substring(sepIndex + 1)));

View File

@ -119,7 +119,7 @@ namespace LubanAssistant
{
try
{
await LoadUtil.LoadDataToCurrentDoc(RootDefineFile, InputDataDir, tableName);
await LoadUtil.LoadTableDataToCurrentWorkSheetAsync(RootDefineFile, InputDataDir, tableName);
}
catch (Exception e)
{
@ -143,7 +143,7 @@ namespace LubanAssistant
private bool HasNotsaveDataInCurrentWorksapce()
{
return true;
return false;
}
private void BtnLoadDataClick(object sender, RibbonControlEventArgs e)

View File

@ -14,33 +14,14 @@ namespace LubanAssistant
{
static class LoadUtil
{
public static async Task LoadDataToCurrentDoc(string rootDefineFile, string inputDataDir, string tableName)
public static async Task LoadTableDataToCurrentWorkSheetAsync(string rootDefineFile, string inputDataDir, string tableName)
{
IAgent agent = new LocalAgent();
var loader = new CfgDefLoader(agent);
await loader.LoadAsync(rootDefineFile);
var tableDataInfo = await DataLoaderUtil.LoadTableDataAsync(rootDefineFile, inputDataDir, tableName);
var rawDefines = loader.BuildDefines();
Console.WriteLine("load record num:{0}", tableDataInfo.MainRecords.Count);
TimeZoneInfo timeZoneInfo = null;
var excludeTags = new List<string>();
var ass = new DefAssembly("", timeZoneInfo, excludeTags, agent);
ass.Load(rawDefines);
DefAssemblyBase.LocalAssebmly = ass;
var table = ass.GetCfgTable(tableName);
if (table == null)
{
throw new Exception($"table:{tableName}不存在");
}
await DataLoaderUtil.LoadTableAsync(agent, table, inputDataDir, "", "");
var datas = ass.GetTableAllDataList(table);
MessageBox.Show($"table:{table.FullName} input:{StringUtil.CollectionToString(table.InputFiles)} record num:{datas.Count}");
Microsoft.Office.Interop.Excel.Worksheet cur = Globals.LubanAssistant.Application.ActiveSheet;
Console.WriteLine("== active sheet name:{0}", cur.Name);
}
}
}

View File

@ -7,6 +7,7 @@ using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
using Microsoft.Office.Tools.Ribbon;
using Luban.Common.Utils;
namespace LubanAssistant
{
@ -14,6 +15,7 @@ namespace LubanAssistant
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
LogUtil.InitSimpleNLogConfigure(NLog.LogLevel.Info);
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)

View File

@ -1,5 +1,4 @@
<Project ToolsVersion="16.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Scriban.4.1.0\build\Scriban.props" Condition="Exists('..\packages\Scriban.4.1.0\build\Scriban.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<!--
This section defines project-level properties.
@ -74,7 +73,7 @@
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
<DefineConstants>TRACE;DEBUG;VSTO40,LUBAN_ASSISTANT</DefineConstants>
<DefineConstants>TRACE;DEBUG;VSTO40,LUBAN_LITE</DefineConstants>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
@ -107,9 +106,6 @@
-->
<ItemGroup>
<Reference Include="Accessibility" />
<Reference Include="CommandLine, Version=2.8.0.0, Culture=neutral, PublicKeyToken=5a870481e358d379, processorArchitecture=MSIL">
<HintPath>..\packages\CommandLineParser.2.8.0\lib\net461\CommandLine.dll</HintPath>
</Reference>
<Reference Include="ExcelDataReader, Version=3.6.0.0, Culture=neutral, PublicKeyToken=93517dbe6a4012fa, processorArchitecture=MSIL">
<HintPath>..\packages\ExcelDataReader.3.6.0\lib\net45\ExcelDataReader.dll</HintPath>
</Reference>
@ -122,9 +118,6 @@
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.7.11\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="Scriban, Version=4.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Scriban.4.1.0\lib\netstandard2.0\Scriban.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
@ -634,12 +627,4 @@
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Scriban.4.1.0\build\Scriban.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Scriban.4.1.0\build\Scriban.props'))" />
<Error Condition="!Exists('..\packages\Scriban.4.1.0\build\Scriban.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Scriban.4.1.0\build\Scriban.targets'))" />
</Target>
<Import Project="..\packages\Scriban.4.1.0\build\Scriban.targets" Condition="Exists('..\packages\Scriban.4.1.0\build\Scriban.targets')" />
</Project>

View File

@ -18,7 +18,7 @@ using System.Xml.Linq;
namespace Luban.Job.Cfg.Defs
{
class CfgDefLoader : CommonDefLoader
public class CfgDefLoader : CommonDefLoader
{
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
@ -140,7 +140,7 @@ namespace Luban.Job.Cfg.Defs
{
if (!string.IsNullOrWhiteSpace(attr))
{
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
foreach (var validatorStr in attr.Split('#', StringSplitOptions.RemoveEmptyEntries))
#else
foreach (var validatorStr in attr.Split('#'))
@ -151,7 +151,7 @@ namespace Luban.Job.Cfg.Defs
{
throw new Exception($"定义文件:{defineFile} key:'{key}' attr:'{attr}' 不是合法的 validator 定义 (key1:value1#key2:value2 ...)");
}
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
result.Add(new Validator() { Type = validatorStr[..sepIndex], Rule = validatorStr[(sepIndex + 1)..] });
#else
result.Add(new Validator() { Type = validatorStr.Substring(0, sepIndex), Rule = validatorStr.Substring(sepIndex + 1, validatorStr.Length - sepIndex - 1) });
@ -319,6 +319,428 @@ namespace Luban.Job.Cfg.Defs
_cfgTables.Add(p);
}
private async Task<CfgBean> LoadTableValueTypeDefineFromFileAsync(Table table, string dataDir)
{
var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, table.InputFiles, dataDir);
var file = inputFileInfos[0];
var source = new ExcelDataSource();
var stream = new MemoryStream(await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5));
var sheet = source.LoadFirstSheet(file.OriginFile, file.SheetName, stream);
var cb = new CfgBean() { Namespace = table.Namespace, Name = table.ValueType, };
var rc = sheet.RowColumns;
var attrRow = sheet.RowColumns[0];
if (rc.Count < sheet.AttrRowCount + 1)
{
throw new Exception($"table:'{table.Name}' file:{file.OriginFile} 至少包含 属性行和标题行");
}
var titleRow = sheet.RowColumns[sheet.AttrRowCount];
// 有可能没有注释行,此时使用标题行,这个是必须有的
var descRow = sheet.HeaderRowCount >= sheet.AttrRowCount + 2 ? sheet.RowColumns[sheet.AttrRowCount + 1] : titleRow;
foreach (var f in sheet.RootFields)
{
var cf = new CfgField() { Name = f.Name, Id = 0 };
string[] attrs = (attrRow[f.FromIndex].Value?.ToString() ?? "").Trim().Split('&').Select(s => s.Trim()).ToArray();
if (attrs.Length == 0 || string.IsNullOrWhiteSpace(attrs[0]))
{
throw new Exception($"table:'{table.Name}' file:{file.OriginFile} title:'{f.Name}' type missing!");
}
// 优先取desc行如果为空,则取title行
cf.Comment = descRow[f.FromIndex].Value?.ToString();
if (string.IsNullOrWhiteSpace(cf.Comment))
{
cf.Comment = titleRow[f.FromIndex].Value?.ToString();
}
if (string.IsNullOrWhiteSpace(cf.Comment))
{
cf.Comment = "";
}
cf.Type = attrs[0];
for (int i = 1; i < attrs.Length; i++)
{
#if !LUBAN_LITE
var pair = attrs[i].Split('=', 2);
#else
var pair = attrs[i].Split(new char[] { '=' }, 2);
#endif
if (pair.Length != 2)
{
throw new Exception($"table:'{table.Name}' file:{file.OriginFile} title:'{f.Name}' attr:'{attrs[i]}' is invalid!");
}
var attrName = pair[0].Trim();
var attrValue = pair[1].Trim();
switch (attrName)
{
case "index":
{
cf.Index = attrValue;
break;
}
case "sep":
{
cf.Sep = attrValue;
break;
}
case "ref":
case "path":
case "range":
{
var validator = new Validator() { Type = attrName, Rule = attrValue };
cf.Validators.Add(validator);
cf.ValueValidators.Add(validator);
break;
}
case "multi_rows":
{
cf.IsMultiRow = attrValue == "1" || attrValue.Equals("true", StringComparison.OrdinalIgnoreCase);
break;
}
case "group":
{
cf.Groups = attrValue.Split(',').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
break;
}
case "comment":
{
cf.Comment = attrValue;
break;
}
case "convert":
{
cf.Converter = attrValue;
break;
}
case "default":
{
cf.DefaultValue = attrValue;
break;
}
case "tags":
{
cf.Tags = attrValue;
break;
}
case "orientation":
{
cf.IsRowOrient = DefUtil.ParseOrientation(attrValue);
break;
}
default:
{
throw new Exception($"table:'{table.Name}' file:{file.OriginFile} title:'{f.Name}' attr:'{attrs[i]}' is invalid!");
}
}
}
cb.Fields.Add(cf);
}
return cb;
}
private async Task LoadTableValueTypeDefinesFromFileAsync(string dataDir)
{
var loadTasks = new List<Task<CfgBean>>();
foreach (var table in this._cfgTables.Where(t => t.LoadDefineFromFile))
{
loadTasks.Add(Task.Run(async () => await this.LoadTableValueTypeDefineFromFileAsync(table, dataDir)));
}
foreach (var task in loadTasks)
{
this._beans.Add(await task);
}
}
private async Task LoadTableListFromFileAsync(string dataDir)
{
if (this._importExcelTableFiles.Count == 0)
{
return;
}
var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, this._importExcelTableFiles, dataDir);
var defTableRecordType = new DefBean(new CfgBean()
{
Namespace = "__intern__",
Name = "__TableRecord__",
Parent = "",
Alias = "",
IsValueType = false,
Sep = "",
TypeId = 0,
IsSerializeCompatible = false,
Fields = new List<Field>
{
new CfgField() { Name = "full_name", Type = "string" },
new CfgField() { Name = "value_type", Type = "string" },
new CfgField() { Name = "index", Type = "string" },
new CfgField() { Name = "mode", Type = "string" },
new CfgField() { Name = "group", Type = "string" },
new CfgField() { Name = "comment", Type = "string" },
new CfgField() { Name = "define_from_excel", Type = "bool" },
new CfgField() { Name = "input", Type = "string" },
new CfgField() { Name = "patch_input", Type = "string" },
new CfgField() { Name = "tags", Type = "string" },
}
})
{
AssemblyBase = new DefAssembly("", null, new List<string>(), Agent),
};
defTableRecordType.PreCompile();
defTableRecordType.Compile();
defTableRecordType.PostCompile();
var tableRecordType = TBean.Create(false, defTableRecordType);
foreach (var file in inputFileInfos)
{
var source = new ExcelDataSource();
var bytes = await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5);
var records = DataLoaderUtil.LoadCfgRecords(tableRecordType, file.OriginFile, null, bytes, true);
foreach (var r in records)
{
DBean data = r.Data;
//s_logger.Info("== read text:{}", r.Data);
string fullName = (data.GetField("full_name") as DString).Value.Trim();
string name = TypeUtil.GetName(fullName);
if (string.IsNullOrWhiteSpace(fullName) || string.IsNullOrWhiteSpace(name))
{
throw new Exception($"file:{file.ActualFile} 定义了一个空的table类名");
}
string module = TypeUtil.GetNamespace(fullName);
string valueType = (data.GetField("value_type") as DString).Value.Trim();
string index = (data.GetField("index") as DString).Value.Trim();
string mode = (data.GetField("mode") as DString).Value.Trim();
string group = (data.GetField("group") as DString).Value.Trim();
string comment = (data.GetField("comment") as DString).Value.Trim();
bool isDefineFromExcel = (data.GetField("define_from_excel") as DBool).Value;
string inputFile = (data.GetField("input") as DString).Value.Trim();
string patchInput = (data.GetField("patch_input") as DString).Value.Trim();
string tags = (data.GetField("tags") as DString).Value.Trim();
AddTable(file.OriginFile, name, module, valueType, index, mode, group, comment, isDefineFromExcel, inputFile, patchInput, tags);
};
}
}
private async Task LoadEnumListFromFileAsync(string dataDir)
{
if (this._importExcelEnumFiles.Count == 0)
{
return;
}
var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, this._importExcelEnumFiles, dataDir);
var defTableRecordType = new DefBean(new CfgBean()
{
Namespace = "__intern__",
Name = "__EnumInfo__",
Parent = "",
Alias = "",
IsValueType = false,
Sep = "",
TypeId = 0,
IsSerializeCompatible = false,
Fields = new List<Field>
{
new CfgField() { Name = "full_name", Type = "string" },
new CfgField() { Name = "item", Type = "string" },
new CfgField() { Name = "alias", Type = "string" },
new CfgField() { Name = "value", Type = "int" },
new CfgField() { Name = "comment", Type = "string" },
new CfgField() { Name = "tags", Type = "string" },
}
})
{
AssemblyBase = new DefAssembly("", null, new List<string>(), Agent),
};
defTableRecordType.PreCompile();
defTableRecordType.Compile();
defTableRecordType.PostCompile();
var tableRecordType = TBean.Create(false, defTableRecordType);
foreach (var file in inputFileInfos)
{
var source = new ExcelDataSource();
var bytes = await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5);
var records = DataLoaderUtil.LoadCfgRecords(tableRecordType, file.OriginFile, null, bytes, true);
PEnum curEnum = null;
foreach (var r in records)
{
DBean data = r.Data;
//s_logger.Info("== read text:{}", r.Data);
string fullName = (data.GetField("full_name") as DString).Value.Trim();
string name = TypeUtil.GetName(fullName);
if (string.IsNullOrWhiteSpace(fullName) || string.IsNullOrWhiteSpace(name))
{
throw new Exception($"file:{file.ActualFile} 定义了一个空的enum类名");
}
string module = TypeUtil.GetNamespace(fullName);
if (curEnum == null || curEnum.Name != name || curEnum.Namespace != module)
{
curEnum = new PEnum() { Name = name, Namespace = module, IsFlags = false, Comment = "", IsUniqueItemId = true };
this._enums.Add(curEnum);
}
string item = (data.GetField("item") as DString).Value.Trim();
if (string.IsNullOrWhiteSpace(item))
{
throw new Exception($"file:{file.ActualFile} module:'{module}' name:'{name}' 定义了一个空枚举项");
}
string alias = (data.GetField("alias") as DString).Value.Trim();
string value = (data.GetField("value") as DInt).Value.ToString();
string comment = (data.GetField("comment") as DString).Value.Trim();
string tags = (data.GetField("tags") as DString).Value.Trim();
curEnum.Items.Add(new EnumItem() { Name = item, Alias = alias, Value = value, Comment = comment, Tags = tags });
};
}
}
private async Task LoadBeanListFromFileAsync(string dataDir)
{
if (this._importExcelBeanFiles.Count == 0)
{
return;
}
var inputFileInfos = await DataLoaderUtil.CollectInputFilesAsync(this.Agent, this._importExcelBeanFiles, dataDir);
var ass = new DefAssembly("", null, new List<string>(), Agent);
var defBeanFieldType = new DefBean(new CfgBean()
{
Namespace = "__intern__",
Name = "__FieldInfo__",
Parent = "",
Alias = "",
IsValueType = false,
Sep = "",
TypeId = 0,
IsSerializeCompatible = false,
Fields = new List<Field>
{
new CfgField() { Name = "name", Type = "string" },
new CfgField() { Name = "type", Type = "string" },
new CfgField() { Name = "sep", Type = "string" },
new CfgField() { Name = "is_multi_rows", Type = "bool" },
new CfgField() { Name = "index", Type = "string" },
new CfgField() { Name = "group", Type = "string" },
new CfgField() { Name = "ref", Type = "string", IgnoreNameValidation = true },
new CfgField() { Name = "path", Type = "string" },
new CfgField() { Name = "comment", Type = "string" },
new CfgField() { Name = "tags", Type = "string" },
new CfgField() { Name = "orientation", Type = "string" },
}
})
{
AssemblyBase = ass,
};
defBeanFieldType.PreCompile();
defBeanFieldType.Compile();
defBeanFieldType.PostCompile();
ass.AddType(defBeanFieldType);
var defTableRecordType = new DefBean(new CfgBean()
{
Namespace = "__intern__",
Name = "__BeanInfo__",
Parent = "",
Alias = "",
IsValueType = false,
Sep = "",
TypeId = 0,
IsSerializeCompatible = false,
Fields = new List<Field>
{
new CfgField() { Name = "full_name", Type = "string" },
new CfgField() { Name = "sep", Type = "string" },
new CfgField() { Name = "comment", Type = "string" },
new CfgField() { Name = "tags", Type = "string" },
new CfgField() { Name = "fields", Type = "list,__FieldInfo__", IsMultiRow = true },
}
})
{
AssemblyBase = ass,
};
ass.AddType(defTableRecordType);
defTableRecordType.PreCompile();
defTableRecordType.Compile();
defTableRecordType.PostCompile();
ass.MarkMultiRows();
var tableRecordType = TBean.Create(false, defTableRecordType);
foreach (var file in inputFileInfos)
{
var source = new ExcelDataSource();
var bytes = await this.Agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5);
var records = DataLoaderUtil.LoadCfgRecords(tableRecordType, file.OriginFile, null, bytes, true);
foreach (var r in records)
{
DBean data = r.Data;
//s_logger.Info("== read text:{}", r.Data);
string fullName = (data.GetField("full_name") as DString).Value.Trim();
string name = TypeUtil.GetName(fullName);
if (string.IsNullOrWhiteSpace(fullName) || string.IsNullOrWhiteSpace(name))
{
throw new Exception($"file:{file.ActualFile} 定义了一个空bean类名");
}
string module = TypeUtil.GetNamespace(fullName);
string sep = (data.GetField("sep") as DString).Value.Trim();
string comment = (data.GetField("comment") as DString).Value.Trim();
string tags = (data.GetField("tags") as DString).Value.Trim();
DList fields = data.GetField("fields") as DList;
var curBean = new CfgBean()
{
Name = name,
Namespace = module,
Sep = sep,
Comment = comment,
Tags = tags,
Parent = "",
Fields = fields.Datas.Select(d => (DBean)d).Select(b => this.CreateField(
file.ActualFile,
(b.GetField("name") as DString).Value.Trim(),
(b.GetField("type") as DString).Value.Trim(),
(b.GetField("index") as DString).Value.Trim(),
(b.GetField("sep") as DString).Value.Trim(),
(b.GetField("is_multi_rows") as DBool).Value,
(b.GetField("group") as DString).Value,
"",
"",
(b.GetField("comment") as DString).Value.Trim(),
(b.GetField("ref") as DString).Value.Trim(),
(b.GetField("path") as DString).Value.Trim(),
"",
"",
"",
"",
(b.GetField("tags") as DString).Value.Trim(),
false,
DefUtil.ParseOrientation((b.GetField("orientation") as DString).Value)
)).ToList(),
};
this._beans.Add(curBean);
};
}
}
public async Task LoadDefinesFromFileAsync(string dataDir)
{
await Task.WhenAll(LoadTableListFromFileAsync(dataDir), LoadEnumListFromFileAsync(dataDir), LoadBeanListFromFileAsync(dataDir));
await LoadTableValueTypeDefinesFromFileAsync(dataDir);
}
private static readonly List<string> _fieldOptionalAttrs = new()
{

View File

@ -13,16 +13,19 @@ namespace Luban.Job.Cfg.Defs
{
public class TableDataInfo
{
public DefTable Table { get; }
public List<Record> MainRecords { get; }
public List<Record> PatchRecords { get; }
public List<Record> FinalRecords { get; set; }
//public List<Record> FinalRecords { get; set; }
public Dictionary<DType, Record> FinalRecordMap { get; set; }
//public Dictionary<DType, Record> FinalRecordMap { get; set; }
public TableDataInfo(List<Record> mainRecords, List<Record> patchRecords)
public TableDataInfo(DefTable table, List<Record> mainRecords, List<Record> patchRecords)
{
Table = table;
MainRecords = mainRecords;
PatchRecords = patchRecords;
}
@ -34,6 +37,8 @@ namespace Luban.Job.Cfg.Defs
public new static DefAssembly LocalAssebmly { get => (DefAssembly)DefAssemblyBase.LocalAssebmly; set => DefAssemblyBase.LocalAssebmly = value; }
public Service CfgTargetService { get; private set; }
private readonly string _patchName;
private readonly List<string> _excludeTags;
@ -51,7 +56,11 @@ namespace Luban.Job.Cfg.Defs
public bool NeedExport(List<string> groups)
{
return true;
if (groups.Count == 0)
{
return true;
}
return groups.Any(g => CfgTargetService.Groups.Contains(g));
}
private readonly List<Patch> _patches = new List<Patch>();
@ -62,6 +71,7 @@ namespace Luban.Job.Cfg.Defs
public Dictionary<string, DefTable> CfgTables { get; } = new Dictionary<string, DefTable>();
public Patch GetPatch(string name)
{
return _patches.Find(b => b.Name == name);
@ -82,30 +92,12 @@ namespace Luban.Job.Cfg.Defs
public void AddDataTable(DefTable table, List<Record> mainRecords, List<Record> patchRecords)
{
_recordsByTables[table.FullName] = new TableDataInfo(mainRecords, patchRecords);
_recordsByTables[table.FullName] = new TableDataInfo(table, mainRecords, patchRecords);
}
public List<Record> GetTableAllDataList(DefTable table)
{
return _recordsByTables[table.FullName].FinalRecords;
}
public List<Record> GetTableExportDataList(DefTable table)
{
var tableDataInfo = _recordsByTables[table.FullName];
if (_excludeTags.Count == 0)
{
return tableDataInfo.FinalRecords;
}
else
{
var finalRecords = tableDataInfo.FinalRecords.Where(r => r.IsNotFiltered(_excludeTags)).ToList();
if (table.IsOneValueTable && finalRecords.Count != 1)
{
throw new Exception($"配置表 {table.FullName} 是单值表 mode=one,但数据个数:{finalRecords.Count} != 1");
}
return finalRecords;
}
return _recordsByTables[table.FullName].MainRecords;
}
public TableDataInfo GetTableDataInfo(DefTable table)
@ -118,12 +110,60 @@ namespace Luban.Job.Cfg.Defs
return Types.Values.Where(t => t is DefTable ct && ct.NeedExport).Select(t => (DefTable)t).ToList();
}
public void Load(Defines defines)
public List<DefTypeBase> GetExportTypes()
{
var refTypes = new Dictionary<string, DefTypeBase>();
var targetService = CfgTargetService;
foreach (var refType in targetService.Refs)
{
if (!this.Types.ContainsKey(refType))
{
throw new Exception($"service:'{targetService.Name}' ref:'{refType}' 类型不存在");
}
if (!refTypes.TryAdd(refType, this.Types[refType]))
{
throw new Exception($"service:'{targetService.Name}' ref:'{refType}' 重复引用");
}
}
foreach (var e in this.Types)
{
if (!refTypes.ContainsKey(e.Key) && (e.Value is DefEnum))
{
refTypes.Add(e.Key, e.Value);
}
}
foreach (var table in GetExportTables())
{
refTypes[table.FullName] = table;
table.ValueTType.Apply(RefTypeVisitor.Ins, refTypes);
}
return refTypes.Values.ToList();
}
public void Load(string outputService, Defines defines)
{
SupportDatetimeType = true;
TopModule = defines.TopModule;
CfgTargetService = defines.Services.Find(s => s.Name == outputService);
if (CfgTargetService == null)
{
throw new ArgumentException($"service:{outputService} not exists");
}
if (!string.IsNullOrWhiteSpace(_patchName))
{
TargetPatch = defines.Patches.Find(b => b.Name == _patchName);
if (TargetPatch == null)
{
throw new Exception($"patch '{_patchName}' not in valid patch set");
}
}
this._patches.AddRange(defines.Patches);
foreach (var e in defines.Enums)

View File

@ -38,7 +38,7 @@ namespace Luban.Job.Common.Utils
throw new System.NotSupportedException();
}
var md5 = FileUtil.CalcMD5(bytes);
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
CacheManager.Ins.AddCache(fileName, md5, bytes);
#endif
return md5;
@ -47,7 +47,7 @@ namespace Luban.Job.Common.Utils
public static string GenMd5AndAddCache(string fileName, byte[] bytes)
{
var md5 = FileUtil.CalcMD5(bytes);
#if !LUBAN_ASSISTANT
#if !LUBAN_LITE
CacheManager.Ins.AddCache(fileName, md5, bytes);
#endif
return md5;

View File

@ -4,6 +4,7 @@ using Luban.Job.Cfg.DataCreators;
using Luban.Job.Cfg.Datas;
using Luban.Job.Cfg.DataSources;
using Luban.Job.Cfg.Defs;
using Luban.Job.Common.Defs;
using Luban.Job.Common.Types;
using Luban.Job.Common.Utils;
using Luban.Server.Common;
@ -18,7 +19,7 @@ namespace Luban.Job.Cfg.Utils
{
public static class DataLoaderUtil
{
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
//private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
public class InputFileInfo
{
@ -95,7 +96,7 @@ namespace Luban.Job.Cfg.Utils
}
}
public static async Task LoadTableAsync(IAgent agent, DefTable table, string dataDir, string patchName, string patchDataDir)
public static async Task<TableDataInfo> LoadTableAsync(IAgent agent, DefTable table, string dataDir, string patchName, string patchDataDir)
{
var mainLoadTasks = new List<Task<List<Record>>>();
var mainGenerateTask = GenerateLoadRecordFromFileTasksAsync(agent, table, dataDir, table.InputFiles, mainLoadTasks);
@ -119,7 +120,7 @@ namespace Luban.Job.Cfg.Utils
{
mainRecords.AddRange(await task);
}
s_logger.Trace("== load main records. count:{count}", mainRecords.Count);
//s_logger.Trace("== load main records. count:{count}", mainRecords.Count);
List<Record> patchRecords = null;
if (patchGenerateTask != null)
@ -130,12 +131,10 @@ namespace Luban.Job.Cfg.Utils
{
patchRecords.AddRange(await task);
}
s_logger.Trace("== load patch records. count:{count}", patchRecords.Count);
//s_logger.Trace("== load patch records. count:{count}", patchRecords.Count);
}
table.Assembly.AddDataTable(table, mainRecords, patchRecords);
s_logger.Trace("table:{name} record num:{num}", table.FullName, mainRecords.Count);
return new TableDataInfo(table, mainRecords, patchRecords);
}
public static async Task LoadCfgDataAsync(IAgent agent, DefAssembly ass, string dataDir, string patchName, string patchDataDir)
@ -193,31 +192,34 @@ namespace Luban.Job.Cfg.Utils
}
}
#if !LUBAN_ASSISTANT
public static async Task LoadTextTablesAsync(IAgent agent, DefAssembly ass, string baseDir, string textTableFiles)
public static async Task<TableDataInfo> LoadTableDataAsync(string rootDefineFile, string inputDataDir, string tableName)
{
var tasks = new List<Task<byte[]>>();
var files = textTableFiles.Split(',');
foreach (var file in await CollectInputFilesAsync(agent, files, baseDir))
{
tasks.Add(agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5));
}
IAgent agent = new LocalAgent();
var loader = new CfgDefLoader(agent);
await loader.LoadAsync(rootDefineFile);
await loader.LoadDefinesFromFileAsync(inputDataDir);
var textTable = ass.ExportTextTable;
for (int i = 0; i < tasks.Count; i++)
var rawDefines = loader.BuildDefines();
TimeZoneInfo timeZoneInfo = null;
var excludeTags = new List<string>();
var ass = new DefAssembly("", timeZoneInfo, excludeTags, agent);
ass.Load("all", rawDefines);
DefAssemblyBase.LocalAssebmly = ass;
var table = ass.GetCfgTable(tableName);
if (table == null)
{
var bytes = await tasks[i];
try
{
textTable.LoadFromFile(files[i], bytes);
}
catch (Exception e)
{
throw new Exception($"load text table file:{files[i]} fail", e);
}
throw new Exception($"table:{tableName}不存在");
}
var tableDataInfo = await LoadTableAsync(agent, table, inputDataDir, "", "");
//MessageBox.Show($"table:{table.FullName} input:{StringUtil.CollectionToString(table.InputFiles)} record num:{datas.Count}");
return tableDataInfo;
}
#endif
}
}

View File

@ -1,17 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CommandLineParser" version="2.8.0" targetFramework="net472" />
<package id="ExcelDataReader" version="3.6.0" targetFramework="net472" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="5.0.0" targetFramework="net472" />
<package id="Microsoft.CSharp" version="4.7.0" targetFramework="net472" />
<package id="Microsoft.CSharp" version="4.5.0" targetFramework="net472" />
<package id="NeoLua" version="1.3.13" targetFramework="net472" />
<package id="NLog" version="4.7.11" targetFramework="net472" />
<package id="Scriban" version="4.1.0" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.Memory" version="4.5.4" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" targetFramework="net472" />
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net472" />
<package id="System.Text.Encodings.Web" version="5.0.1" targetFramework="net472" />
<package id="System.Text.Json" version="5.0.2" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />