LubanAssistant添加配置定义加载相关代码
parent
8288591827
commit
1e7fb10db2
|
|
@ -0,0 +1,152 @@
|
|||
|
||||
namespace LubanAssistant
|
||||
{
|
||||
partial class AssistantTab : Microsoft.Office.Tools.Ribbon.RibbonBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 必需的设计器变量。
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
public AssistantTab()
|
||||
: base(Globals.Factory.GetRibbonFactory())
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有正在使用的资源。
|
||||
/// </summary>
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region 组件设计器生成的代码
|
||||
|
||||
/// <summary>
|
||||
/// 设计器支持所需的方法 - 不要修改
|
||||
/// 使用代码编辑器修改此方法的内容。
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.tab1 = this.Factory.CreateRibbonTab();
|
||||
this.group3 = this.Factory.CreateRibbonGroup();
|
||||
this.SetRootFile = this.Factory.CreateRibbonButton();
|
||||
this.group1 = this.Factory.CreateRibbonGroup();
|
||||
this.load = this.Factory.CreateRibbonButton();
|
||||
this.group2 = this.Factory.CreateRibbonGroup();
|
||||
this.saveAll = this.Factory.CreateRibbonButton();
|
||||
this.saveSelected = this.Factory.CreateRibbonButton();
|
||||
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
|
||||
this.tab1.SuspendLayout();
|
||||
this.group3.SuspendLayout();
|
||||
this.group1.SuspendLayout();
|
||||
this.group2.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tab1
|
||||
//
|
||||
this.tab1.ControlId.ControlIdType = Microsoft.Office.Tools.Ribbon.RibbonControlIdType.Office;
|
||||
this.tab1.Groups.Add(this.group3);
|
||||
this.tab1.Groups.Add(this.group1);
|
||||
this.tab1.Groups.Add(this.group2);
|
||||
this.tab1.Label = "TabAddIns";
|
||||
this.tab1.Name = "tab1";
|
||||
//
|
||||
// group3
|
||||
//
|
||||
this.group3.Items.Add(this.SetRootFile);
|
||||
this.group3.Name = "group3";
|
||||
//
|
||||
// SetRootFile
|
||||
//
|
||||
this.SetRootFile.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
|
||||
this.SetRootFile.Label = "设置Root文件";
|
||||
this.SetRootFile.Name = "SetRootFile";
|
||||
this.SetRootFile.ShowImage = true;
|
||||
this.SetRootFile.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnChooseRootFileClick);
|
||||
//
|
||||
// group1
|
||||
//
|
||||
this.group1.Items.Add(this.load);
|
||||
this.group1.Name = "group1";
|
||||
//
|
||||
// load
|
||||
//
|
||||
this.load.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
|
||||
this.load.Label = "加载数据表";
|
||||
this.load.Name = "load";
|
||||
this.load.ShowImage = true;
|
||||
this.load.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnLoadClick);
|
||||
//
|
||||
// group2
|
||||
//
|
||||
this.group2.Items.Add(this.saveAll);
|
||||
this.group2.Items.Add(this.saveSelected);
|
||||
this.group2.Name = "group2";
|
||||
//
|
||||
// saveAll
|
||||
//
|
||||
this.saveAll.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
|
||||
this.saveAll.Label = "保存所有";
|
||||
this.saveAll.Name = "saveAll";
|
||||
this.saveAll.ShowImage = true;
|
||||
this.saveAll.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnSaveAllClick);
|
||||
//
|
||||
// saveSelected
|
||||
//
|
||||
this.saveSelected.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
|
||||
this.saveSelected.Label = "保存选中";
|
||||
this.saveSelected.Name = "saveSelected";
|
||||
this.saveSelected.ShowImage = true;
|
||||
this.saveSelected.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnSaveSelectedClick);
|
||||
//
|
||||
// openFileDialog1
|
||||
//
|
||||
this.openFileDialog1.FileName = "openFileDialog1";
|
||||
//
|
||||
// AssistantTab
|
||||
//
|
||||
this.Name = "AssistantTab";
|
||||
this.RibbonType = "Microsoft.Excel.Workbook";
|
||||
this.Tabs.Add(this.tab1);
|
||||
this.Load += new Microsoft.Office.Tools.Ribbon.RibbonUIEventHandler(this.AssistantTab_Load);
|
||||
this.tab1.ResumeLayout(false);
|
||||
this.tab1.PerformLayout();
|
||||
this.group3.ResumeLayout(false);
|
||||
this.group3.PerformLayout();
|
||||
this.group1.ResumeLayout(false);
|
||||
this.group1.PerformLayout();
|
||||
this.group2.ResumeLayout(false);
|
||||
this.group2.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal Microsoft.Office.Tools.Ribbon.RibbonTab tab1;
|
||||
internal Microsoft.Office.Tools.Ribbon.RibbonGroup group1;
|
||||
internal Microsoft.Office.Tools.Ribbon.RibbonButton load;
|
||||
internal Microsoft.Office.Tools.Ribbon.RibbonGroup group2;
|
||||
internal Microsoft.Office.Tools.Ribbon.RibbonButton saveAll;
|
||||
internal Microsoft.Office.Tools.Ribbon.RibbonGroup group3;
|
||||
internal Microsoft.Office.Tools.Ribbon.RibbonButton SetRootFile;
|
||||
internal Microsoft.Office.Tools.Ribbon.RibbonButton saveSelected;
|
||||
private System.Windows.Forms.OpenFileDialog openFileDialog1;
|
||||
}
|
||||
|
||||
partial class ThisRibbonCollection
|
||||
{
|
||||
internal AssistantTab AssistantTab
|
||||
{
|
||||
get { return this.GetRibbon<AssistantTab>(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
using Microsoft.Office.Tools.Ribbon;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace LubanAssistant
|
||||
{
|
||||
public partial class AssistantTab
|
||||
{
|
||||
private string RootDefineFile
|
||||
{
|
||||
get => Properties.Settings.Default.rootDefineFile;
|
||||
set
|
||||
{
|
||||
Properties.Settings.Default.rootDefineFile = value;
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
}
|
||||
|
||||
private void AssistantTab_Load(object sender, RibbonUIEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private bool CheckChooseRootDefineFile()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(RootDefineFile) || !File.Exists(RootDefineFile))
|
||||
{
|
||||
if (TryChooseRootDefineFile(out var rootDefineFile))
|
||||
{
|
||||
RootDefineFile = rootDefineFile;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryChooseRootDefineFile(out string rootDefineFile)
|
||||
{
|
||||
var dialog = new OpenFileDialog();
|
||||
dialog.DefaultExt = "xml";
|
||||
dialog.Filter = "root file (*.xml)|*.xml";
|
||||
dialog.Title = "Choose Root Xml File";
|
||||
dialog.CheckFileExists = true;
|
||||
if (dialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
rootDefineFile = dialog.FileName;
|
||||
return true;
|
||||
}
|
||||
rootDefineFile = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void BtnChooseRootFileClick(object sender, RibbonControlEventArgs e)
|
||||
{
|
||||
if (TryChooseRootDefineFile(out var rootDefineFile))
|
||||
{
|
||||
RootDefineFile = rootDefineFile;
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnLoadClick(object sender, RibbonControlEventArgs e)
|
||||
{
|
||||
if (CheckChooseRootDefineFile())
|
||||
{
|
||||
MessageBox.Show("load");
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnSaveAllClick(object sender, RibbonControlEventArgs e)
|
||||
{
|
||||
MessageBox.Show("点击save");
|
||||
}
|
||||
|
||||
private void BtnSaveSelectedClick(object sender, RibbonControlEventArgs e)
|
||||
{
|
||||
MessageBox.Show("点击save");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="openFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
<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.
|
||||
|
|
@ -31,6 +32,8 @@
|
|||
<DefineConstants>VSTO40</DefineConstants>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<BootstrapperComponentsLocation>HomeSite</BootstrapperComponentsLocation>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.VSTORuntime.4.0">
|
||||
|
|
@ -46,6 +49,9 @@
|
|||
-->
|
||||
<OfficeApplication>Excel</OfficeApplication>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
<!--
|
||||
This section defines properties that are set when the "Debug" configuration is selected.
|
||||
|
||||
|
|
@ -68,8 +74,9 @@
|
|||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||
<DefineConstants>$(DefineConstants);DEBUG;TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;VSTO40,LUBAN_ASSISTANT</DefineConstants>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<!--
|
||||
This section defines properties that are set when the "Release" configuration is selected.
|
||||
|
|
@ -100,15 +107,66 @@
|
|||
-->
|
||||
<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>
|
||||
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Neo.Lua, Version=5.3.0.0, Culture=neutral, PublicKeyToken=fdb0cd4fe8a6e3b2, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NeoLua.1.3.13\lib\net47\Neo.Lua.dll</HintPath>
|
||||
</Reference>
|
||||
<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>
|
||||
</Reference>
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Text.Encodings.Web, Version=5.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Text.Encodings.Web.5.0.1\lib\net461\System.Text.Encodings.Web.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Text.Json, Version=5.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Text.Json.5.0.2\lib\net461\System.Text.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="YamlDotNet, Version=11.0.0.0, Culture=neutral, PublicKeyToken=ec19458f3c15af5e, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\YamlDotNet.11.2.1\lib\net45\YamlDotNet.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Office.Tools.v4.0.Framework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
|
|
@ -156,9 +214,309 @@
|
|||
can be found.
|
||||
-->
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Luban.Common\Source\EErrorCode.cs">
|
||||
<Link>Source\EErrorCode.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Common\Source\Utils\FileUtil.cs">
|
||||
<Link>Source\Utils\FileUtil.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Common\Source\Utils\LogUtil.cs">
|
||||
<Link>Source\Utils\LogUtil.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Common\Source\Utils\TypeUtil.cs">
|
||||
<Link>Source\Utils\TypeUtil.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Common\Source\Utils\XmlUtil.cs">
|
||||
<Link>Source\Utils\XmlUtil.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\DataCreateException.cs">
|
||||
<Link>Source\DataCreators\DataCreateException.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\ExcelDataCreator.cs">
|
||||
<Link>Source\DataCreators\ExcelDataCreator.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\ExcelNamedRowDataCreator.cs">
|
||||
<Link>Source\DataCreators\ExcelNamedRowDataCreator.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\JsonDataCreator.cs">
|
||||
<Link>Source\DataCreators\JsonDataCreator.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\MultiRowExcelDataCreator.cs">
|
||||
<Link>Source\DataCreators\MultiRowExcelDataCreator.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataCreators\StringDataCreator.cs">
|
||||
<Link>Source\DataCreators\StringDataCreator.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\AbstractDataSource.cs">
|
||||
<Link>Source\DataSources\AbstractDataSource.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\ExcelDataSource.cs">
|
||||
<Link>Source\DataSources\Excel\ExcelDataSource.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\ExcelStream.cs">
|
||||
<Link>Source\DataSources\Excel\ExcelStream.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Excel\Sheet.cs">
|
||||
<Link>Source\DataSources\Excel\Sheet.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataSources\Json\JsonDataSource.cs">
|
||||
<Link>Source\DataSources\Json\JsonDataSource.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DArray.cs">
|
||||
<Link>Source\Datas\DArray.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DBean.cs">
|
||||
<Link>Source\Datas\DBean.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DBool.cs">
|
||||
<Link>Source\Datas\DBool.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DByte.cs">
|
||||
<Link>Source\Datas\DByte.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DBytes.cs">
|
||||
<Link>Source\Datas\DBytes.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DDateTime.cs">
|
||||
<Link>Source\Datas\DDateTime.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DDouble.cs">
|
||||
<Link>Source\Datas\DDouble.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DEnum.cs">
|
||||
<Link>Source\Datas\DEnum.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DFint.cs">
|
||||
<Link>Source\Datas\DFint.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DFloat.cs">
|
||||
<Link>Source\Datas\DFloat.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DFlong.cs">
|
||||
<Link>Source\Datas\DFlong.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DFshort.cs">
|
||||
<Link>Source\Datas\DFshort.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DInt.cs">
|
||||
<Link>Source\Datas\DInt.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DList.cs">
|
||||
<Link>Source\Datas\DList.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DLong.cs">
|
||||
<Link>Source\Datas\DLong.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DMap.cs">
|
||||
<Link>Source\Datas\DMap.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DSet.cs">
|
||||
<Link>Source\Datas\DSet.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DShort.cs">
|
||||
<Link>Source\Datas\DShort.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DString.cs">
|
||||
<Link>Source\Datas\DString.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DVector2.cs">
|
||||
<Link>Source\Datas\DVector2.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DVector3.cs">
|
||||
<Link>Source\Datas\DVector3.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\DVector4.cs">
|
||||
<Link>Source\Datas\DVector4.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Datas\Record.cs">
|
||||
<Link>Source\Datas\Record.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataVisitors\IDataActionVisitor.cs">
|
||||
<Link>Source\DataVisitors\IDataActionVisitor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\DataVisitors\IDataFuncVisitor.cs">
|
||||
<Link>Source\DataVisitors\IDataFuncVisitor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Defs\CfgDefTypeBase.cs">
|
||||
<Link>Source\Defs\CfgDefTypeBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Defs\DefBean.cs">
|
||||
<Link>Source\Defs\DefBean.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Defs\DefTable.cs">
|
||||
<Link>Source\Defs\DefTable.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\RawDefs\CfgBean.cs">
|
||||
<Link>Source\RawDefs\CfgBean.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\RawDefs\CfgField.cs">
|
||||
<Link>Source\RawDefs\CfgField.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\RawDefs\Defines.cs">
|
||||
<Link>Source\RawDefs\Defines.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\RawDefs\Group.cs">
|
||||
<Link>Source\RawDefs\Group.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\RawDefs\Patch.cs">
|
||||
<Link>Source\RawDefs\Patch.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\RawDefs\ResourceInfo.cs">
|
||||
<Link>Source\RawDefs\ResourceInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\RawDefs\Service.cs">
|
||||
<Link>Source\RawDefs\Service.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\RawDefs\Table.cs">
|
||||
<Link>Source\RawDefs\Table.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\TypeVisitors\DeepCompareTypeDefine.cs">
|
||||
<Link>Source\TypeVisitors\DeepCompareTypeDefine.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\TypeVisitors\IsMultiData.cs">
|
||||
<Link>Source\TypeVisitors\IsMultiData.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\TypeVisitors\IsNotSepTypeVisitor.cs">
|
||||
<Link>Source\TypeVisitors\IsNotSepTypeVisitor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\TypeVisitors\RefTypeVisitor.cs">
|
||||
<Link>Source\Defs\RefTypeVisitor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Cfg\Source\Utils\DataUtil.cs">
|
||||
<Link>Source\Utils\DataUtil.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Defs\CommonDefLoader.cs">
|
||||
<Link>Source\Defs\CommonDefLoader.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Defs\DefAssemblyBase.cs">
|
||||
<Link>Source\Defs\DefAssemblyBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Defs\DefBeanBase.cs">
|
||||
<Link>Source\Defs\DefBeanBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Defs\DefEnum.cs">
|
||||
<Link>Source\Defs\DefEnum.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Defs\DefFieldBase.cs">
|
||||
<Link>Source\Defs\DefFieldBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\ELanguage.cs">
|
||||
<Link>Source\ELanguage.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\RawDefs\Bean.cs">
|
||||
<Link>Source\RawDefs\Bean.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\RawDefs\Field.cs">
|
||||
<Link>Source\RawDefs\Field.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\RawDefs\PEnum.cs">
|
||||
<Link>Source\RawDefs\PEnum.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TArray.cs">
|
||||
<Link>Source\Types\TArray.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TBean.cs">
|
||||
<Link>Source\Types\TBean.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TBool.cs">
|
||||
<Link>Source\Types\TBool.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TByte.cs">
|
||||
<Link>Source\Types\TByte.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TBytes.cs">
|
||||
<Link>Source\Types\TBytes.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TDateTime.cs">
|
||||
<Link>Source\Types\TDateTime.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TDouble.cs">
|
||||
<Link>Source\Types\TDouble.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TEnum.cs">
|
||||
<Link>Source\Types\TEnum.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TFint.cs">
|
||||
<Link>Source\Types\TFint.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TFloat.cs">
|
||||
<Link>Source\Types\TFloat.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TFlong.cs">
|
||||
<Link>Source\Types\TFlong.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TFshort.cs">
|
||||
<Link>Source\Types\TFshort.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TInt.cs">
|
||||
<Link>Source\Types\TInt.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TList.cs">
|
||||
<Link>Source\Types\TList.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TLong.cs">
|
||||
<Link>Source\Types\TLong.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TMap.cs">
|
||||
<Link>Source\Types\TMap.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TSet.cs">
|
||||
<Link>Source\Types\TSet.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TShort.cs">
|
||||
<Link>Source\Types\TShort.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TString.cs">
|
||||
<Link>Source\Types\TString.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TText.cs">
|
||||
<Link>Source\Types\TText.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TType.cs">
|
||||
<Link>Source\Types\TType.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TVector2.cs">
|
||||
<Link>Source\Types\TVector2.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TVector3.cs">
|
||||
<Link>Source\Types\TVector3.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Types\TVector4.cs">
|
||||
<Link>Source\Types\TVector4.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\TypeVisitors\AllFalseVisitor.cs">
|
||||
<Link>Source\TypeVisitors\AllFalseVisitor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\TypeVisitors\AllTrueVisitor.cs">
|
||||
<Link>Source\TypeVisitors\AllTrueVisitor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\TypeVisitors\DecoratorFuncVisitor.cs">
|
||||
<Link>Source\TypeVisitors\DecoratorFuncVisitor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\TypeVisitors\ITypeActionVisitor.cs">
|
||||
<Link>Source\TypeVisitors\ITypeActionVisitor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\TypeVisitors\ITypeFuncVisitor.cs">
|
||||
<Link>Source\TypeVisitors\ITypeFuncVisitor.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Job.Common\Source\Utils\DefUtil.cs">
|
||||
<Link>Source\Utils\DefUtil.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Luban.Server.Common\Source\IAgent.cs">
|
||||
<Link>Source\IAgent.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="AssistantTab.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="AssistantTab.Designer.cs">
|
||||
<DependentUpon>AssistantTab.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="AssistantTab.resx">
|
||||
<DependentUpon>AssistantTab.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
|
|
@ -168,6 +526,9 @@
|
|||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="app.config" />
|
||||
<None Include="LubanAssistant_TemporaryKey.pfx" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
|
|
@ -175,7 +536,37 @@
|
|||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Compile Include="Source\AtomicLong.cs" />
|
||||
<Compile Include="Source\CacheFileUtil.cs" />
|
||||
<Compile Include="Source\Collections\CollectionExtension.cs" />
|
||||
<Compile Include="Source\Collections\CollectionUtil.cs" />
|
||||
<Compile Include="Source\Common\HashUtil.cs" />
|
||||
<Compile Include="Source\Common\MathUtil.cs" />
|
||||
<Compile Include="Source\Common\SerializationUtil.cs" />
|
||||
<Compile Include="Source\Common\StringUtil.cs" />
|
||||
<Compile Include="Source\Common\TimeUtil.cs" />
|
||||
<Compile Include="Source\Common\ValueUtil.cs" />
|
||||
<Compile Include="Source\DataSources\DataSourceFactory.cs" />
|
||||
<Compile Include="Source\Datas\DText.cs" />
|
||||
<Compile Include="Source\Datas\DType.cs" />
|
||||
<Compile Include="Source\Defs\CfgDefLoader.cs" />
|
||||
<Compile Include="Source\Defs\DefAssembly.cs" />
|
||||
<Compile Include="Source\Defs\DefField.cs" />
|
||||
<Compile Include="Source\Defs\DefTypeBase.cs" />
|
||||
<Compile Include="Source\FileInfo.cs" />
|
||||
<Compile Include="Source\GetImportFileOrDirectory.cs" />
|
||||
<Compile Include="Source\LocalAgent.cs" />
|
||||
<Compile Include="Source\QueryFilesExists.cs" />
|
||||
<Compile Include="Source\Serialization\BeanBase.cs" />
|
||||
<Compile Include="Source\Serialization\ByteBuf.cs" />
|
||||
<Compile Include="Source\Serialization\EUnmarshalError.cs" />
|
||||
<Compile Include="Source\Serialization\FieldTag.cs" />
|
||||
<Compile Include="Source\Serialization\ISerializable.cs" />
|
||||
<Compile Include="Source\Serialization\ITypeId.cs" />
|
||||
<Compile Include="Source\Serialization\SerializationException.cs" />
|
||||
<Compile Include="Source\Utils\DataLoaderUtil.cs" />
|
||||
<Compile Include="ThisAddIn.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
|
@ -187,10 +578,22 @@
|
|||
</Compile>
|
||||
<AppDesigner Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="TypeVisitors\" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignManifests>true</SignManifests>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ManifestKeyFile>LubanAssistant_TemporaryKey.pfx</ManifestKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ManifestCertificateThumbprint>DB8575295993B72B55091F842E5704CA3A263CD5</ManifestCertificateThumbprint>
|
||||
</PropertyGroup>
|
||||
<!-- Include the build rules for a C# project. -->
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- Include additional build rules for an Office application add-in. -->
|
||||
|
|
@ -206,4 +609,12 @@
|
|||
</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>
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ namespace LubanAssistant.Properties {
|
|||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
|
@ -22,5 +22,17 @@ namespace LubanAssistant.Properties {
|
|||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string rootDefineFile {
|
||||
get {
|
||||
return ((string)(this["rootDefineFile"]));
|
||||
}
|
||||
set {
|
||||
this["rootDefineFile"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="LubanAssistant.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="rootDefineFile" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using System.Threading;
|
||||
|
||||
namespace Bright.Threading
|
||||
{
|
||||
public class AtomicLong
|
||||
{
|
||||
private long _value;
|
||||
public AtomicLong(long initValue = 0)
|
||||
{
|
||||
_value = initValue;
|
||||
}
|
||||
|
||||
public long IncrementAndGet()
|
||||
{
|
||||
return Interlocked.Add(ref _value, 1);
|
||||
}
|
||||
|
||||
public long AddAndGet(long step)
|
||||
{
|
||||
return Interlocked.Add(ref _value, step);
|
||||
}
|
||||
|
||||
public long GetAndAdd(long step)
|
||||
{
|
||||
return Interlocked.Add(ref _value, step);
|
||||
}
|
||||
|
||||
public long Value { get => Interlocked.Read(ref _value); set => Interlocked.Exchange(ref _value, value); }
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
using Luban.Common.Protos;
|
||||
using Luban.Common.Utils;
|
||||
using Luban.Server.Common;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Luban.Job.Common.Utils
|
||||
{
|
||||
public static class CacheFileUtil
|
||||
{
|
||||
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public static string GenStringOrBytesMd5AndAddCache(string fileName, object content)
|
||||
{
|
||||
switch (content)
|
||||
{
|
||||
case string s: return GenMd5AndAddCache(fileName, s);
|
||||
case byte[] bs: return GenMd5AndAddCache(fileName, bs);
|
||||
default: throw new System.NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GenMd5AndAddCache(string fileName, string content, bool withUtf8Bom = false)
|
||||
{
|
||||
content = content.Replace("\r\n", "\n");
|
||||
byte[] bytes;
|
||||
if (!withUtf8Bom)
|
||||
{
|
||||
bytes = System.Text.Encoding.UTF8.GetBytes(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
//bytes = new byte[System.Text.Encoding.UTF8.GetByteCount(content) + 3 /* bom header */];
|
||||
//bytes[0] = 0xef;
|
||||
//bytes[1] = 0xbb;
|
||||
//bytes[2] = 0xbf;
|
||||
//System.Text.Encoding.UTF8.GetBytes(content, bytes.AsSpan(3));
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
var md5 = FileUtil.CalcMD5(bytes);
|
||||
#if !LUBAN_ASSISTANT
|
||||
CacheManager.Ins.AddCache(fileName, md5, bytes);
|
||||
#endif
|
||||
return md5;
|
||||
}
|
||||
|
||||
public static string GenMd5AndAddCache(string fileName, byte[] bytes)
|
||||
{
|
||||
var md5 = FileUtil.CalcMD5(bytes);
|
||||
#if !LUBAN_ASSISTANT
|
||||
CacheManager.Ins.AddCache(fileName, md5, bytes);
|
||||
#endif
|
||||
return md5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bright.Collections
|
||||
{
|
||||
public static class CollectionExtension
|
||||
{
|
||||
|
||||
public static void AddRange<T>(this IList<T> dst, IEnumerable<T> src)
|
||||
{
|
||||
foreach (var x in src)
|
||||
{
|
||||
dst.Add(x);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryAdd<TK, TV>(this IDictionary<TK, TV> map, TK key, TV value)
|
||||
{
|
||||
if (map.ContainsKey(key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
map.Add(key, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static TV GetValueOrDefault<TK, TV>(this IDictionary<TK, TV> map, TK key, TV defaultValue = default)
|
||||
{
|
||||
return map.TryGetValue(key, out var value) ? value : defaultValue;
|
||||
}
|
||||
|
||||
public static TV GetOrAdd<TK, TV>(this IDictionary<TK, TV> map, TK key, Func<TK, TV> creator)
|
||||
{
|
||||
if (map.TryGetValue(key, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
TV newValue = creator(key);
|
||||
map.Add(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static TV GetOrAdd<TK, TV>(this IDictionary<TK, TV> map, TK key) where TV : new()
|
||||
{
|
||||
if (map.TryGetValue(key, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
TV newValue = new TV();
|
||||
map.Add(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static TV Get<TK, TV>(this IDictionary<TK, TV> map, TK key) where TV : class
|
||||
{
|
||||
return map.TryGetValue(key, out var value) ? value : null;
|
||||
}
|
||||
|
||||
public static bool Contains<TK, TV>(this IDictionary<TK, TV> map, TK key, TV value)
|
||||
{
|
||||
return map.Contains(new KeyValuePair<TK, TV>(key, value));
|
||||
}
|
||||
|
||||
public static void PutAll<TK, TV>(this IDictionary<TK, TV> dst, IDictionary<TK, TV> src)
|
||||
{
|
||||
foreach (var e in src)
|
||||
{
|
||||
dst[e.Key] = e.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsEmpty<TE>(this ICollection<TE> c)
|
||||
{
|
||||
return c.Count == 0;
|
||||
}
|
||||
|
||||
public static void Merge(this IDictionary<int, float> dst, IDictionary<int, float> src)
|
||||
{
|
||||
foreach (var e in src)
|
||||
{
|
||||
if (dst.TryGetValue(e.Key, out var v))
|
||||
{
|
||||
dst[e.Key] = v + e.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst[e.Key] = e.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Replace(this IDictionary<int, float> dst, IDictionary<int, float> src)
|
||||
{
|
||||
dst.Clear();
|
||||
dst.PutAll(src);
|
||||
}
|
||||
|
||||
public static int AddValue<T>(this IDictionary<T, int> dst, T key, int add)
|
||||
{
|
||||
if (dst.TryGetValue(key, out var value))
|
||||
{
|
||||
return dst[key] = value + add;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dst[key] = add;
|
||||
}
|
||||
}
|
||||
|
||||
public static long AddValue<T>(this IDictionary<T, long> dst, T key, long add)
|
||||
{
|
||||
if (dst.TryGetValue(key, out var value))
|
||||
{
|
||||
return dst[key] = value + add;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dst[key] = add;
|
||||
}
|
||||
}
|
||||
|
||||
public static int IncrementValue<T>(this IDictionary<T, int> dst, T key)
|
||||
{
|
||||
if (dst.TryGetValue(key, out var value))
|
||||
{
|
||||
return dst[key] = value + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dst[key] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static long IncrementValue<T>(this IDictionary<T, long> dst, T key)
|
||||
{
|
||||
if (dst.TryGetValue(key, out var value))
|
||||
{
|
||||
return dst[key] = value + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dst[key] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ContainsAll<T>(this IList<T> a, IList<T> b)
|
||||
{
|
||||
foreach (var x in b)
|
||||
{
|
||||
if (!a.Contains(x))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static void RemoveAll<T>(this IList<T> a, IList<T> b)
|
||||
{
|
||||
foreach (var x in b)
|
||||
{
|
||||
a.Remove(x);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool DicEquals<TK, TV>(this IDictionary<TK, TV> a, IDictionary<TK, TV> b)
|
||||
{
|
||||
if (a.Count != b.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
foreach (var e in a)
|
||||
{
|
||||
if (!(b.TryGetValue(e.Key, out var v) && v.Equals(e.Value)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void AddAll<TK, TV>(this Dictionary<TK, TV> data, Dictionary<TK, TV> b)
|
||||
{
|
||||
foreach (var e in b)
|
||||
{
|
||||
data[e.Key] = e.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<TK, TV> Plus<TK, TV>(this Dictionary<TK, TV> data, TK key, TV value)
|
||||
{
|
||||
var newMap = new Dictionary<TK, TV>(data)
|
||||
{
|
||||
[key] = value
|
||||
};
|
||||
return newMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static T[] CopySubArray<T>(this T[] data, int index, int length)
|
||||
{
|
||||
T[] result = new T[length];
|
||||
Array.Copy(data, index, result, 0, length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回第一个满足条件的元素的index
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="arr"></param>
|
||||
/// <param name="predic"></param>
|
||||
/// <returns>返回第一个满足条件的元素的index,如果没找到,返回 -1</returns>
|
||||
public static int IndexOfFirst<T>(IEnumerable<T> arr, Func<T, bool> predic)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (var x in arr)
|
||||
{
|
||||
if (predic(x))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回最后一个满足条件的元素的index
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="arr"></param>
|
||||
/// <param name="predic"></param>
|
||||
/// <returns>返回最后一个满足条件的元素的index,如果没找到,返回 -1</returns>
|
||||
public static int IndexOfLast<T>(IEnumerable<T> arr, Func<T, bool> predic)
|
||||
{
|
||||
int i = -1;
|
||||
foreach (var x in arr)
|
||||
{
|
||||
if (predic(x))
|
||||
{
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Bright.Collections
|
||||
{
|
||||
|
||||
public static class EmptyDictionary<TK, TV>
|
||||
{
|
||||
public static Dictionary<TK, TV> Empty { get; } = new Dictionary<TK, TV>();
|
||||
}
|
||||
|
||||
public static class CollectionUtil
|
||||
{
|
||||
|
||||
public static Dictionary<TK, TV> SingletonMap<TK, TV>(TK key, TV value)
|
||||
{
|
||||
var newMap = new Dictionary<TK, TV>
|
||||
{
|
||||
{ key, value }
|
||||
};
|
||||
return newMap;
|
||||
}
|
||||
|
||||
public static string ToString<TK, TV>(IDictionary<TK, TV> m)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append('{');
|
||||
foreach (var e in m)
|
||||
{
|
||||
sb.Append(e.Key).Append(':').Append(e.Value).Append(',');
|
||||
}
|
||||
sb.Append('}');
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static void Replace<TK, TV>(IDictionary<TK, TV> dest, IDictionary<TK, TV> src)
|
||||
{
|
||||
dest.Clear();
|
||||
foreach (var entry in src)
|
||||
{
|
||||
dest.Add(entry.Key, entry.Value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void MergeIntValueDic<TK>(IDictionary<TK, int> dest, IDictionary<TK, int> src)
|
||||
{
|
||||
foreach (var entry in src)
|
||||
{
|
||||
if (dest.ContainsKey(entry.Key))
|
||||
{
|
||||
dest[entry.Key] = dest[entry.Key] + entry.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest.Add(entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void MergeFloatValueDic<TK>(IDictionary<TK, float> dest, IDictionary<TK, float> src)
|
||||
{
|
||||
foreach (var entry in src)
|
||||
{
|
||||
if (dest.ContainsKey(entry.Key))
|
||||
{
|
||||
dest[entry.Key] = dest[entry.Key] + entry.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest.Add(entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
|
||||
namespace Bright.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// 从 System.Collections.HashTable 源码抄来
|
||||
/// </summary>
|
||||
public static class HashUtil
|
||||
{
|
||||
|
||||
private static readonly int[] primes = {
|
||||
3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
|
||||
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
|
||||
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
|
||||
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
|
||||
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369};
|
||||
|
||||
private const int HashPrime = 101;
|
||||
|
||||
private const int MaxPrimeArrayLength = 0x7FEFFFFD;
|
||||
|
||||
public static int GetPrime(int min)
|
||||
{
|
||||
if (min < 0)
|
||||
throw new ArgumentException();
|
||||
|
||||
for (int i = 0; i < primes.Length; i++)
|
||||
{
|
||||
int prime = primes[i];
|
||||
if (prime >= min) return prime;
|
||||
}
|
||||
|
||||
//outside of our predefined table.
|
||||
//compute the hard way.
|
||||
for (int i = (min | 1); i < int.MaxValue; i += 2)
|
||||
{
|
||||
if (IsPrime(i) && ((i - 1) % HashPrime != 0))
|
||||
return i;
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
public static bool IsPrime(int candidate)
|
||||
{
|
||||
if ((candidate & 1) != 0)
|
||||
{
|
||||
int limit = (int)Math.Sqrt(candidate);
|
||||
for (int divisor = 3; divisor <= limit; divisor += 2)
|
||||
{
|
||||
if ((candidate % divisor) == 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return (candidate == 2);
|
||||
}
|
||||
|
||||
public static int GetMinPrime()
|
||||
{
|
||||
return primes[0];
|
||||
}
|
||||
|
||||
// Returns size of hashtable to grow to.
|
||||
public static int ExpandPrime(int oldSize)
|
||||
{
|
||||
int newSize = 2 * oldSize;
|
||||
|
||||
// Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow.
|
||||
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
|
||||
if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
|
||||
{
|
||||
return MaxPrimeArrayLength;
|
||||
}
|
||||
|
||||
return GetPrime(newSize);
|
||||
}
|
||||
|
||||
public static int CalcHash(int x)
|
||||
{
|
||||
int hash = 17;
|
||||
return hash * 23 + x;
|
||||
}
|
||||
|
||||
public static int CalcHash(int x, int y)
|
||||
{
|
||||
int hash = 17;
|
||||
hash = hash * 23 + x;
|
||||
return hash * 23 + y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
namespace Bright.Common
|
||||
{
|
||||
public static class MathUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// 确保返回 x + y 的正确值, 如果溢出 抛出异常
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static int AddExactly(int x, int y)
|
||||
{
|
||||
return checked(x + y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保返回 x + y 的正确值, 如果溢出 抛出异常
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static long AddExactly(long x, long y)
|
||||
{
|
||||
return checked(x + y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保返回 x - y 的正确值, 如果溢出 抛出异常
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static int SubExcatly(int x, int y)
|
||||
{
|
||||
return checked(x - y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保返回 x - y 的正确值, 如果溢出 抛出异常
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static long SubExactly(long x, long y)
|
||||
{
|
||||
return checked(x - y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保返回 x * y 的正确值, 如果溢出 抛出异常
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static int MultifyExactly(int x, int y)
|
||||
{
|
||||
return checked(x * y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保返回 x * y 的正确值, 如果溢出 抛出异常
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static long MultifyExactly(long x, long y)
|
||||
{
|
||||
return checked(x * y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取 >= x/y 的最小整数
|
||||
/// </summary>
|
||||
/// <param name="x">除数</param>
|
||||
/// <param name="y">被除数</param>
|
||||
/// <returns></returns>
|
||||
public static int Ceil(int x, int y)
|
||||
{
|
||||
return (x + y - 1) / y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取 >= x/y 的最小整数
|
||||
/// </summary>
|
||||
/// <param name="x">除数</param>
|
||||
/// <param name="y">被除数</param>
|
||||
/// <returns></returns>
|
||||
public static long Ceil(long x, long y)
|
||||
{
|
||||
return (x + y - 1) / y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回 [min, max] 之间的数
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
/// <returns></returns>
|
||||
public static int Clamp(int value, int min, int max)
|
||||
{
|
||||
return value < min ? min : (value > max ? max : value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Bright.Serialization;
|
||||
|
||||
namespace Bright.Common
|
||||
{
|
||||
public static class SerializationUtil
|
||||
{
|
||||
public static void Serialize<T>(ByteBuf os, List<T> list) where T : ISerializable
|
||||
{
|
||||
os.WriteSize(list.Count);
|
||||
foreach (var e in list)
|
||||
{
|
||||
e.Serialize(os);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Deserialize<T>(ByteBuf os, List<T> list) where T : ISerializable, new()
|
||||
{
|
||||
int n = os.ReadSize();
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
T e = new T();
|
||||
e.Deserialize(os);
|
||||
list.Add(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Serialize(ByteBuf os, List<string> list)
|
||||
{
|
||||
os.WriteSize(list.Count);
|
||||
foreach (var e in list)
|
||||
{
|
||||
os.WriteString(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Deserialize(ByteBuf os, List<string> list)
|
||||
{
|
||||
int n = os.ReadSize();
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
list.Add(os.ReadString());
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe int FloatToIntBits(float f)
|
||||
{
|
||||
return *((int*)&f);
|
||||
}
|
||||
|
||||
public static void SerializeBool(ByteBuf buf, bool x)
|
||||
{
|
||||
buf.WriteBool(x);
|
||||
}
|
||||
|
||||
public static bool DeserializeBool(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadBool();
|
||||
}
|
||||
|
||||
public static void SerializeByte(ByteBuf buf, byte x)
|
||||
{
|
||||
buf.WriteByte(x);
|
||||
}
|
||||
|
||||
public static byte DeserializeByte(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadByte();
|
||||
}
|
||||
|
||||
public static void SerializeShort(ByteBuf buf, short x)
|
||||
{
|
||||
buf.WriteShort(x);
|
||||
}
|
||||
|
||||
public static short DeserializeShort(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadShort();
|
||||
}
|
||||
|
||||
public static void SerializeFshort(ByteBuf buf, short x)
|
||||
{
|
||||
buf.WriteFshort(x);
|
||||
}
|
||||
|
||||
public static short DeserializeFshort(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadFshort();
|
||||
}
|
||||
|
||||
public static void SerializeInt(ByteBuf buf, int x)
|
||||
{
|
||||
buf.WriteInt(x);
|
||||
}
|
||||
|
||||
public static int DeserializeInt(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadInt();
|
||||
}
|
||||
|
||||
public static void SerializeFint(ByteBuf buf, int x)
|
||||
{
|
||||
buf.WriteFint(x);
|
||||
}
|
||||
|
||||
public static int DeserializeFint(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadFint();
|
||||
}
|
||||
|
||||
public static void SerializeLong(ByteBuf buf, long x)
|
||||
{
|
||||
buf.WriteLong(x);
|
||||
}
|
||||
|
||||
public static long DeserializeLong(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadLong();
|
||||
}
|
||||
|
||||
public static void SerializeFlong(ByteBuf buf, long x)
|
||||
{
|
||||
buf.WriteFlong(x);
|
||||
}
|
||||
|
||||
public static long DeserializeFlong(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadFlong();
|
||||
}
|
||||
|
||||
public static void SerializeFloat(ByteBuf buf, float x)
|
||||
{
|
||||
buf.WriteFloat(x);
|
||||
}
|
||||
|
||||
public static float DeserializeFloat(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadFloat();
|
||||
}
|
||||
|
||||
public static void SerializeDouble(ByteBuf buf, double x)
|
||||
{
|
||||
buf.WriteDouble(x);
|
||||
}
|
||||
|
||||
public static double DeserializeDouble(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadDouble();
|
||||
}
|
||||
|
||||
public static void SerializeString(ByteBuf buf, string x)
|
||||
{
|
||||
buf.WriteString(x);
|
||||
}
|
||||
|
||||
public static string DeserializeString(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadString();
|
||||
}
|
||||
|
||||
public static void SerializeBytes(ByteBuf buf, byte[] x)
|
||||
{
|
||||
buf.WriteBytes(x);
|
||||
}
|
||||
|
||||
public static byte[] DeserializeBytes(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadBytes();
|
||||
}
|
||||
|
||||
public static void SerializeVector2(ByteBuf buf, Vector2 x)
|
||||
{
|
||||
buf.WriteVector2(x);
|
||||
}
|
||||
|
||||
public static Vector2 DeserializeVector2(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadVector2();
|
||||
}
|
||||
|
||||
public static void SerializeVector3(ByteBuf buf, Vector3 x)
|
||||
{
|
||||
buf.WriteVector3(x);
|
||||
}
|
||||
|
||||
public static Vector3 DeserializeVector3(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadVector3();
|
||||
}
|
||||
|
||||
public static void SerializeVector4(ByteBuf buf, Vector4 x)
|
||||
{
|
||||
buf.WriteVector4(x);
|
||||
}
|
||||
|
||||
public static Vector4 DeserializeVector4(ByteBuf buf)
|
||||
{
|
||||
return buf.ReadVector4();
|
||||
}
|
||||
|
||||
public static void SerializeBean<T>(ByteBuf buf, T x) where T : BeanBase
|
||||
{
|
||||
x.Serialize(buf);
|
||||
}
|
||||
|
||||
public static T DeserializeBean<T>(ByteBuf buf) where T : BeanBase, new()
|
||||
{
|
||||
var x = new T();
|
||||
x.Deserialize(buf);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Bright.Common
|
||||
{
|
||||
public static class StringUtil
|
||||
{
|
||||
public static string ToStr(object o)
|
||||
{
|
||||
return ToStr(o, new StringBuilder());
|
||||
}
|
||||
|
||||
public static string ToStr(object o, StringBuilder sb)
|
||||
{
|
||||
foreach (var p in o.GetType().GetFields())
|
||||
{
|
||||
|
||||
sb.Append($"{p.Name} = {p.GetValue(o)},");
|
||||
}
|
||||
|
||||
foreach (var p in o.GetType().GetProperties())
|
||||
{
|
||||
sb.Append($"{p.Name} = {p.GetValue(o)},");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string ArrayToString<T>(T[] arr)
|
||||
{
|
||||
return "[" + string.Join(",", arr) + "]";
|
||||
}
|
||||
|
||||
|
||||
public static string CollectionToString<T>(IEnumerable<T> arr)
|
||||
{
|
||||
return "[" + string.Join(",", arr) + "]";
|
||||
}
|
||||
|
||||
|
||||
public static string CollectionToString<TK, TV>(IDictionary<TK, TV> dic)
|
||||
{
|
||||
var sb = new StringBuilder('{');
|
||||
foreach (var e in dic)
|
||||
{
|
||||
sb.Append(e.Key).Append(':');
|
||||
sb.Append(e.Value).Append(',');
|
||||
}
|
||||
sb.Append('}');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Bright.Time
|
||||
{
|
||||
public static class TimeUtil
|
||||
{
|
||||
|
||||
public static readonly long TIMEZONE_OFFSET_MILLS = (long)TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.FromUnixTimeSeconds(0)).TotalMilliseconds;
|
||||
public static readonly int TIMEZONE_OFFSET = (int)TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.FromUnixTimeSeconds(0)).TotalSeconds;
|
||||
|
||||
public const long DAY_MILLISECONDS = 86400000;
|
||||
public const int DAY_SECONDS = 86400;
|
||||
public const int HOUR_SECONDS = 3600;
|
||||
public const int MINUTE_SECONDS = 60;
|
||||
|
||||
public const int WEEKDAY_OF_19700101 = 3;
|
||||
|
||||
public const long HOUR_MILLISECONDS = 3600000;
|
||||
public const long MINUTE_MILLISECONDS = 60000;
|
||||
public const long WEEK_MILLISECONDS = DAY_MILLISECONDS * 7;
|
||||
|
||||
public static bool IsSameDay(int time1, int time2)
|
||||
{
|
||||
return (time1 + TIMEZONE_OFFSET) / DAY_SECONDS == (time2 + TIMEZONE_OFFSET) / DAY_SECONDS;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
private static long s_millisTimeOffsetForTest;
|
||||
|
||||
/// <summary>
|
||||
/// 用于调整服务器内时间,只对测试版本生效
|
||||
/// </summary>
|
||||
public static long MillisTimeOffsetForTest
|
||||
{
|
||||
get
|
||||
{
|
||||
return Interlocked.Read(ref s_millisTimeOffsetForTest);
|
||||
}
|
||||
set
|
||||
{
|
||||
Interlocked.Exchange(ref s_millisTimeOffsetForTest, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static long NowMillis => DateTimeOffset.Now.ToUnixTimeMilliseconds() + s_millisTimeOffsetForTest;
|
||||
|
||||
public static int Now => (int)(DateTimeOffset.Now.ToUnixTimeSeconds() + s_millisTimeOffsetForTest / 1000);
|
||||
|
||||
#else
|
||||
public static long NowMillis => DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
|
||||
public static int Now => (int)DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||
#endif
|
||||
|
||||
public static bool IsSameWeek(int time1, int time2)
|
||||
{
|
||||
return GetMondayZeroTimeOfThisWeek(time1) == GetMondayZeroTimeOfThisWeek(time2);
|
||||
}
|
||||
|
||||
public static int TodayZeroTime()
|
||||
{
|
||||
return TodayZeroTime(Now);
|
||||
}
|
||||
|
||||
public static int TodayZeroTime(int time)
|
||||
{
|
||||
return (time + TIMEZONE_OFFSET) / DAY_SECONDS * DAY_SECONDS - TIMEZONE_OFFSET;
|
||||
}
|
||||
|
||||
|
||||
public static int TomorrowZeroTime()
|
||||
{
|
||||
return TomorrowZeroTime(Now);
|
||||
}
|
||||
|
||||
public static int TomorrowZeroTime(int time)
|
||||
{
|
||||
return TodayZeroTime(time) + DAY_SECONDS;
|
||||
}
|
||||
|
||||
public static int AnotherDayZeroTime(int time, int offsetDayNum)
|
||||
{
|
||||
return TodayZeroTime(time) + DAY_SECONDS * offsetDayNum;
|
||||
}
|
||||
|
||||
public static bool IsContinuesDay(int time1, int time2)
|
||||
{
|
||||
return (time1 + TIMEZONE_OFFSET) / DAY_SECONDS + 1 == (time2 + TIMEZONE_OFFSET) / DAY_SECONDS;
|
||||
}
|
||||
|
||||
public static int DayOffset(int time1, int time2)
|
||||
{
|
||||
int a = (time1 + TIMEZONE_OFFSET) / DAY_SECONDS;
|
||||
int b = (time2 + TIMEZONE_OFFSET) / DAY_SECONDS;
|
||||
return Math.Abs(a - b);
|
||||
}
|
||||
|
||||
public static int GetSecondsFromTodayZeroTime(int time)
|
||||
{
|
||||
return time - TodayZeroTime(time);
|
||||
}
|
||||
|
||||
public static int GetHourOfToday(int time)
|
||||
{
|
||||
return (time + TIMEZONE_OFFSET) % DAY_SECONDS / HOUR_SECONDS;
|
||||
}
|
||||
|
||||
public static int GetMinuteOfToday(int time)
|
||||
{
|
||||
long interval = time - TodayZeroTime(time);
|
||||
long left = interval % HOUR_SECONDS;
|
||||
return (int)(left / MINUTE_SECONDS);
|
||||
}
|
||||
|
||||
public static long GetSecondsOfDay(int hour, int minute)
|
||||
{
|
||||
return hour * HOUR_SECONDS + minute * MINUTE_SECONDS;
|
||||
}
|
||||
|
||||
public static int GetWeekDay(int time)
|
||||
{
|
||||
return ((time + TIMEZONE_OFFSET) / DAY_SECONDS + WEEKDAY_OF_19700101) % 7;
|
||||
}
|
||||
|
||||
|
||||
public static int GetMondayZeroTimeOfNextWeek(int time)
|
||||
{
|
||||
return TodayZeroTime(time) + DAY_SECONDS * (7 - GetWeekDay(time));
|
||||
}
|
||||
|
||||
public static int GetMondayZeroTimeOfNextWeek()
|
||||
{
|
||||
return GetMondayZeroTimeOfNextWeek(Now);
|
||||
}
|
||||
|
||||
public static int GetMondayZeroTimeOfThisWeek(int time)
|
||||
{
|
||||
return TodayZeroTime(time) - DAY_SECONDS * GetWeekDay(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* weekday 0 - 6 对应 周一 到 周日
|
||||
*/
|
||||
public static long GetSecondsOfWeek(int weekday, int hour, int minute, int second)
|
||||
{
|
||||
return (weekday * 86400 + hour * 3600 + minute * 60 + second) * 1000L;
|
||||
}
|
||||
|
||||
public static long ToMills(float seconds)
|
||||
{
|
||||
return (long)((double)seconds * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
namespace Bright.Common
|
||||
{
|
||||
public static class ValueUtil
|
||||
{
|
||||
public static void Swap<T>(ref T a, ref T b)
|
||||
{
|
||||
T temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
|
||||
public static void LockAndSwap<T>(object locker, ref T a, ref T b)
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
T temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Luban.Job.Cfg.DataSources
|
||||
{
|
||||
static class DataSourceFactory
|
||||
{
|
||||
public static readonly string[] validDataSourceSuffixes = new string[]
|
||||
{
|
||||
".xlsx",
|
||||
".xls",
|
||||
".csv",
|
||||
".xml",
|
||||
".lua",
|
||||
".json",
|
||||
".yml",
|
||||
".bin",
|
||||
};
|
||||
|
||||
public static AbstractDataSource Create(string url, string sheetName, Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
string ext = url.Contains(".") ? Path.GetExtension(url)?.Substring(1) : url;
|
||||
AbstractDataSource source;
|
||||
switch (ext)
|
||||
{
|
||||
case "csv":
|
||||
case "xls":
|
||||
case "xlsx": source = new Excel.ExcelDataSource(); break;
|
||||
case "json": source = new Json.JsonDataSource(); break;
|
||||
default: throw new Exception($"不支持的文件类型:{url}");
|
||||
}
|
||||
source.Load(url, sheetName, stream);
|
||||
return source;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"文件{url} 加载失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
using Luban.Job.Cfg.DataVisitors;
|
||||
|
||||
namespace Luban.Job.Cfg.Datas
|
||||
{
|
||||
public class DText : DType
|
||||
{
|
||||
public const string KEY_NAME = "key";
|
||||
public const string TEXT_NAME = "text";
|
||||
|
||||
public string Key { get; }
|
||||
|
||||
private readonly string _rawValue;
|
||||
|
||||
public string RawValue => _rawValue;
|
||||
|
||||
public override string TypeName => "text";
|
||||
|
||||
public DText(string key, string x)
|
||||
{
|
||||
Key = key;
|
||||
_rawValue = x;
|
||||
}
|
||||
|
||||
public override void Apply<T>(IDataActionVisitor<T> visitor, T x)
|
||||
{
|
||||
visitor.Accept(this, x);
|
||||
}
|
||||
|
||||
public override void Apply<T1, T2>(IDataActionVisitor<T1, T2> visitor, T1 x, T2 y)
|
||||
{
|
||||
visitor.Accept(this, x, y);
|
||||
}
|
||||
|
||||
public override TR Apply<TR>(IDataFuncVisitor<TR> visitor)
|
||||
{
|
||||
return visitor.Accept(this);
|
||||
}
|
||||
|
||||
public override TR Apply<T, TR>(IDataFuncVisitor<T, TR> visitor, T x)
|
||||
{
|
||||
return visitor.Accept(this, x);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is DText o && o._rawValue == this._rawValue && o.Key == this.Key;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _rawValue.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
using Luban.Job.Cfg.DataVisitors;
|
||||
|
||||
namespace Luban.Job.Cfg.Datas
|
||||
{
|
||||
public abstract class DType
|
||||
{
|
||||
public abstract void Apply<T>(IDataActionVisitor<T> visitor, T x);
|
||||
|
||||
public abstract void Apply<T1, T2>(IDataActionVisitor<T1, T2> visitor, T1 x, T2 y);
|
||||
|
||||
public abstract TR Apply<TR>(IDataFuncVisitor<TR> visitor);
|
||||
|
||||
public abstract TR Apply<T, TR>(IDataFuncVisitor<T, TR> visitor, T x);
|
||||
|
||||
public abstract string TypeName { get; }
|
||||
}
|
||||
|
||||
public abstract class DType<T> : DType
|
||||
{
|
||||
public T Value { get; }
|
||||
|
||||
protected DType(T value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,471 @@
|
|||
using Bright.Collections;
|
||||
using Luban.Common.Utils;
|
||||
using Luban.Job.Cfg.Datas;
|
||||
using Luban.Job.Cfg.DataSources.Excel;
|
||||
using Luban.Job.Cfg.RawDefs;
|
||||
using Luban.Job.Cfg.Utils;
|
||||
using Luban.Job.Common.Defs;
|
||||
using Luban.Job.Common.RawDefs;
|
||||
using Luban.Job.Common.Types;
|
||||
using Luban.Job.Common.Utils;
|
||||
using Luban.Server.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Luban.Job.Cfg.Defs
|
||||
{
|
||||
class CfgDefLoader : CommonDefLoader
|
||||
{
|
||||
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly List<string> _importExcelTableFiles = new();
|
||||
private readonly List<string> _importExcelEnumFiles = new();
|
||||
private readonly List<string> _importExcelBeanFiles = new();
|
||||
|
||||
|
||||
private readonly List<Patch> _patches = new();
|
||||
|
||||
private readonly List<Table> _cfgTables = new List<Table>();
|
||||
|
||||
private readonly List<Service> _cfgServices = new List<Service>();
|
||||
|
||||
private readonly List<Group> _cfgGroups = new List<Group>();
|
||||
|
||||
private readonly List<string> _defaultGroups = new List<string>();
|
||||
|
||||
public CfgDefLoader(IAgent agent) : base(agent)
|
||||
{
|
||||
RegisterRootDefineHandler("importexcel", AddImportExcel);
|
||||
RegisterRootDefineHandler("patch", AddPatch);
|
||||
RegisterRootDefineHandler("service", AddService);
|
||||
RegisterRootDefineHandler("group", AddGroup);
|
||||
|
||||
RegisterModuleDefineHandler("table", AddTable);
|
||||
|
||||
|
||||
IsBeanFieldMustDefineId = false;
|
||||
}
|
||||
|
||||
public Defines BuildDefines()
|
||||
{
|
||||
return new Defines()
|
||||
{
|
||||
TopModule = TopModule,
|
||||
Patches = _patches,
|
||||
Enums = _enums,
|
||||
Beans = _beans,
|
||||
Tables = _cfgTables,
|
||||
Services = _cfgServices,
|
||||
Groups = _cfgGroups,
|
||||
};
|
||||
}
|
||||
|
||||
private static readonly List<string> _excelImportRequireAttrs = new List<string> { "name", "type" };
|
||||
private void AddImportExcel(XElement e)
|
||||
{
|
||||
ValidAttrKeys(RootXml, e, null, _excelImportRequireAttrs);
|
||||
var importName = XmlUtil.GetRequiredAttribute(e, "name");
|
||||
if (string.IsNullOrWhiteSpace(importName))
|
||||
{
|
||||
throw new Exception("importexcel 属性name不能为空");
|
||||
}
|
||||
var type = XmlUtil.GetRequiredAttribute(e, "type");
|
||||
if (string.IsNullOrWhiteSpace(type))
|
||||
{
|
||||
throw new Exception($"importexcel name:'{importName}' type属性不能为空");
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case "table": this._importExcelTableFiles.Add(importName); break;
|
||||
case "enum": this._importExcelEnumFiles.Add(importName); break;
|
||||
case "bean": this._importExcelBeanFiles.Add(importName); break;
|
||||
default: throw new Exception($"importexcel name:'{importName}' type:'{type}' 不合法. 有效值为 table|enum|bean");
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly List<string> _patchRequireAttrs = new List<string> { "name" };
|
||||
private void AddPatch(XElement e)
|
||||
{
|
||||
ValidAttrKeys(RootXml, e, null, _patchRequireAttrs);
|
||||
var patchName = e.Attribute("name").Value;
|
||||
if (string.IsNullOrWhiteSpace(patchName))
|
||||
{
|
||||
throw new Exception("patch 属性name不能为空");
|
||||
}
|
||||
if (this._patches.Any(b => b.Name == patchName))
|
||||
{
|
||||
throw new Exception($"patch '{patchName}' 重复");
|
||||
}
|
||||
_patches.Add(new Patch(patchName));
|
||||
}
|
||||
|
||||
private static readonly List<string> _groupOptionalAttrs = new List<string> { "default" };
|
||||
private static readonly List<string> _groupRequireAttrs = new List<string> { "name" };
|
||||
|
||||
private void AddGroup(XElement e)
|
||||
{
|
||||
ValidAttrKeys(RootXml, e, _groupOptionalAttrs, _groupRequireAttrs);
|
||||
List<string> groupNames = CreateGroups(e.Attribute("name").Value);
|
||||
|
||||
foreach (var g in groupNames)
|
||||
{
|
||||
if (_cfgGroups.Any(cg => cg.Names.Contains(g)))
|
||||
{
|
||||
throw new Exception($"group名:'{g}' 重复");
|
||||
}
|
||||
}
|
||||
|
||||
if (XmlUtil.GetOptionBoolAttribute(e, "default"))
|
||||
{
|
||||
this._defaultGroups.AddRange(groupNames);
|
||||
}
|
||||
_cfgGroups.Add(new Group() { Names = groupNames });
|
||||
}
|
||||
|
||||
private void FillValueValidator(CfgField f, string attrValue, string validatorName)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(attrValue))
|
||||
{
|
||||
var validator = new Validator() { Type = validatorName, Rule = attrValue };
|
||||
f.Validators.Add(validator);
|
||||
f.ValueValidators.Add(validator);
|
||||
}
|
||||
}
|
||||
|
||||
private void FillValidators(string defineFile, string key, string attr, List<Validator> result)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(attr))
|
||||
{
|
||||
#if !LUBAN_ASSISTANT
|
||||
foreach (var validatorStr in attr.Split('#', StringSplitOptions.RemoveEmptyEntries))
|
||||
#else
|
||||
foreach (var validatorStr in attr.Split('#'))
|
||||
#endif
|
||||
{
|
||||
var sepIndex = validatorStr.IndexOf(':');
|
||||
if (sepIndex <= 0)
|
||||
{
|
||||
throw new Exception($"定义文件:{defineFile} key:'{key}' attr:'{attr}' 不是合法的 validator 定义 (key1:value1#key2:value2 ...)");
|
||||
}
|
||||
#if !LUBAN_ASSISTANT
|
||||
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) });
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<string> _serviceAttrs = new List<string> { "name", "manager", "group" };
|
||||
|
||||
private void AddService(XElement e)
|
||||
{
|
||||
var name = XmlUtil.GetRequiredAttribute(e, "name");
|
||||
var manager = XmlUtil.GetRequiredAttribute(e, "manager");
|
||||
List<string> groups = CreateGroups(XmlUtil.GetOptionalAttribute(e, "group"));
|
||||
var refs = new List<string>();
|
||||
|
||||
s_logger.Trace("service name:{name} manager:{manager}", name, manager);
|
||||
ValidAttrKeys(RootXml, e, _serviceAttrs, _serviceAttrs);
|
||||
foreach (XElement ele in e.Elements())
|
||||
{
|
||||
string tagName = ele.Name.LocalName;
|
||||
s_logger.Trace("service {service_name} tag: {name} {value}", name, tagName, ele);
|
||||
switch (tagName)
|
||||
{
|
||||
case "ref":
|
||||
{
|
||||
refs.Add(XmlUtil.GetRequiredAttribute(ele, "name"));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new Exception($"service:'{name}' tag:'{tagName}' 非法");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ValidGroup(groups, out var invalidGroup))
|
||||
{
|
||||
throw new Exception($"service:'{name}' group:'{invalidGroup}' 不存在");
|
||||
}
|
||||
_cfgServices.Add(new Service() { Name = name, Manager = manager, Groups = groups, Refs = refs });
|
||||
}
|
||||
|
||||
|
||||
private readonly Dictionary<string, Table> _name2CfgTable = new Dictionary<string, Table>();
|
||||
|
||||
private static List<string> CreateGroups(string s)
|
||||
{
|
||||
return s.Split(',', ';').Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
|
||||
}
|
||||
|
||||
private bool ValidGroup(List<string> groups, out string invalidGroup)
|
||||
{
|
||||
foreach (var g in groups)
|
||||
{
|
||||
if (!this._cfgGroups.Any(cg => cg.Names.Contains(g)))
|
||||
{
|
||||
invalidGroup = g;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
invalidGroup = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
private ETableMode ConvertMode(string defineFile, string tableName, string modeStr, string indexStr)
|
||||
{
|
||||
ETableMode mode;
|
||||
switch (modeStr)
|
||||
{
|
||||
case "one":
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(indexStr))
|
||||
{
|
||||
throw new Exception($"定义文件:{defineFile} table:'{tableName}' mode=one 是单例表,不支持定义index属性");
|
||||
}
|
||||
mode = ETableMode.ONE;
|
||||
break;
|
||||
}
|
||||
case "map":
|
||||
{
|
||||
//if ((string.IsNullOrWhiteSpace(indexStr) || indexStr.Split(',').Length != 1))
|
||||
//{
|
||||
// throw new Exception($"定义文件:{CurImportFile} table:{tableName} 是单键表,必须在index属性里指定1个key");
|
||||
//}
|
||||
mode = ETableMode.MAP;
|
||||
break;
|
||||
}
|
||||
case "":
|
||||
{
|
||||
mode = ETableMode.MAP;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentException($"不支持的 mode:{modeStr}");
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
private readonly List<string> _tableOptionalAttrs = new List<string> { "index", "mode", "group", "patch_input", "comment", "define_from_file" };
|
||||
private readonly List<string> _tableRequireAttrs = new List<string> { "name", "value", "input" };
|
||||
|
||||
private void AddTable(string defineFile, XElement e)
|
||||
{
|
||||
ValidAttrKeys(defineFile, e, _tableOptionalAttrs, _tableRequireAttrs);
|
||||
string name = XmlUtil.GetRequiredAttribute(e, "name");
|
||||
string module = CurNamespace;
|
||||
string valueType = XmlUtil.GetRequiredAttribute(e, "value");
|
||||
bool defineFromFile = XmlUtil.GetOptionBoolAttribute(e, "define_from_file");
|
||||
string index = XmlUtil.GetOptionalAttribute(e, "index");
|
||||
string group = XmlUtil.GetOptionalAttribute(e, "group");
|
||||
string comment = XmlUtil.GetOptionalAttribute(e, "comment");
|
||||
string input = XmlUtil.GetRequiredAttribute(e, "input");
|
||||
string patchInput = XmlUtil.GetOptionalAttribute(e, "patch_input");
|
||||
string mode = XmlUtil.GetOptionalAttribute(e, "mode");
|
||||
string tags = XmlUtil.GetOptionalAttribute(e, "tags");
|
||||
AddTable(defineFile, name, module, valueType, index, mode, group, comment, defineFromFile, input, patchInput, tags);
|
||||
}
|
||||
|
||||
private void AddTable(string defineFile, string name, string module, string valueType, string index, string mode, string group,
|
||||
string comment, bool defineFromExcel, string input, string patchInput, string tags)
|
||||
{
|
||||
var p = new Table()
|
||||
{
|
||||
Name = name,
|
||||
Namespace = module,
|
||||
ValueType = valueType,
|
||||
LoadDefineFromFile = defineFromExcel,
|
||||
Index = index,
|
||||
Groups = CreateGroups(group),
|
||||
Comment = comment,
|
||||
Mode = ConvertMode(defineFile, name, mode, index),
|
||||
Tags = tags,
|
||||
};
|
||||
|
||||
if (p.Groups.Count == 0)
|
||||
{
|
||||
p.Groups = this._defaultGroups;
|
||||
}
|
||||
else if (!ValidGroup(p.Groups, out var invalidGroup))
|
||||
{
|
||||
throw new Exception($"定义文件:{defineFile} table:'{p.Name}' group:'{invalidGroup}' 不存在");
|
||||
}
|
||||
p.InputFiles.AddRange(input.Split(',').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(patchInput))
|
||||
{
|
||||
foreach (var subPatchStr in patchInput.Split('|').Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)))
|
||||
{
|
||||
var nameAndDirs = subPatchStr.Split(':');
|
||||
if (nameAndDirs.Length != 2)
|
||||
{
|
||||
throw new Exception($"定义文件:{defineFile} table:'{p.Name}' patch_input:'{subPatchStr}' 定义不合法");
|
||||
}
|
||||
var patchDirs = nameAndDirs[1].Split(',', ';').ToList();
|
||||
if (!p.PatchInputFiles.TryAdd(nameAndDirs[0], patchDirs))
|
||||
{
|
||||
throw new Exception($"定义文件:{defineFile} table:'{p.Name}' patch_input:'{subPatchStr}' 子patch:'{nameAndDirs[0]}' 重复");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_cfgTables.Add(p);
|
||||
}
|
||||
|
||||
|
||||
private static readonly List<string> _fieldOptionalAttrs = new()
|
||||
{
|
||||
"index",
|
||||
"sep",
|
||||
"validator",
|
||||
"key_validator",
|
||||
"value_validator",
|
||||
"ref",
|
||||
"path",
|
||||
"range",
|
||||
"multi_rows",
|
||||
"group",
|
||||
"res",
|
||||
"convert",
|
||||
"comment",
|
||||
"tags",
|
||||
"default",
|
||||
"orientation",
|
||||
};
|
||||
|
||||
private static readonly List<string> _fieldRequireAttrs = new List<string> { "name", "type" };
|
||||
|
||||
protected override Field CreateField(string defineFile, XElement e)
|
||||
{
|
||||
ValidAttrKeys(defineFile, e, _fieldOptionalAttrs, _fieldRequireAttrs);
|
||||
|
||||
return CreateField(defineFile, XmlUtil.GetRequiredAttribute(e, "name"),
|
||||
XmlUtil.GetRequiredAttribute(e, "type"),
|
||||
XmlUtil.GetOptionalAttribute(e, "index"),
|
||||
XmlUtil.GetOptionalAttribute(e, "sep"),
|
||||
XmlUtil.GetOptionBoolAttribute(e, "multi_rows"),
|
||||
XmlUtil.GetOptionalAttribute(e, "group"),
|
||||
XmlUtil.GetOptionalAttribute(e, "res"),
|
||||
XmlUtil.GetOptionalAttribute(e, "convert"),
|
||||
XmlUtil.GetOptionalAttribute(e, "comment"),
|
||||
XmlUtil.GetOptionalAttribute(e, "ref"),
|
||||
XmlUtil.GetOptionalAttribute(e, "path"),
|
||||
XmlUtil.GetOptionalAttribute(e, "range"),
|
||||
XmlUtil.GetOptionalAttribute(e, "key_validator"),
|
||||
XmlUtil.GetOptionalAttribute(e, "value_validator"),
|
||||
XmlUtil.GetOptionalAttribute(e, "validator"),
|
||||
XmlUtil.GetOptionalAttribute(e, "tags"),
|
||||
false,
|
||||
DefUtil.ParseOrientation(XmlUtil.GetOptionalAttribute(e, "orientation"))
|
||||
);
|
||||
}
|
||||
|
||||
private Field CreateField(string defileFile, string name, string type, string index, string sep, bool isMultiRow, string group, string resource, string converter,
|
||||
string comment, string refs, string path, string range, string keyValidator, string valueValidator, string validator, string tags,
|
||||
bool ignoreNameValidation, bool isRowOrient)
|
||||
{
|
||||
var f = new CfgField()
|
||||
{
|
||||
Name = name,
|
||||
Index = index,
|
||||
Sep = sep,
|
||||
IsMultiRow = isMultiRow,
|
||||
Groups = CreateGroups(group),
|
||||
Resource = resource,
|
||||
Converter = converter,
|
||||
Comment = comment,
|
||||
Tags = tags,
|
||||
IgnoreNameValidation = ignoreNameValidation,
|
||||
IsRowOrient = isRowOrient,
|
||||
};
|
||||
|
||||
// 字段与table的默认组不一样。
|
||||
// table 默认只属于default=1的组
|
||||
// 字段默认属于所有组
|
||||
if (f.Groups.Count == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (!ValidGroup(f.Groups, out var invalidGroup))
|
||||
{
|
||||
throw new Exception($"定义文件:{defileFile} field:'{name}' group:'{invalidGroup}' 不存在");
|
||||
}
|
||||
f.Type = type;
|
||||
|
||||
|
||||
FillValueValidator(f, refs, "ref");
|
||||
FillValueValidator(f, path, "path"); // (ue4|unity|normal|regex);xxx;xxx
|
||||
FillValueValidator(f, range, "range");
|
||||
|
||||
FillValidators(defileFile, "key_validator", keyValidator, f.KeyValidators);
|
||||
FillValidators(defileFile, "value_validator", valueValidator, f.ValueValidators);
|
||||
FillValidators(defileFile, "validator", validator, f.Validators);
|
||||
return f;
|
||||
}
|
||||
|
||||
private static readonly List<string> _beanOptinsAttrs = new List<string> { "value_type", "alias", "sep", "comment", "tags" };
|
||||
private static readonly List<string> _beanRequireAttrs = new List<string> { "name" };
|
||||
|
||||
protected override void AddBean(string defineFile, XElement e, string parent)
|
||||
{
|
||||
ValidAttrKeys(defineFile, e, _beanOptinsAttrs, _beanRequireAttrs);
|
||||
|
||||
var b = new CfgBean()
|
||||
{
|
||||
Name = XmlUtil.GetRequiredAttribute(e, "name"),
|
||||
Namespace = CurNamespace,
|
||||
Parent = parent.Length > 0 ? parent : "",
|
||||
TypeId = 0,
|
||||
IsSerializeCompatible = true,
|
||||
IsValueType = XmlUtil.GetOptionBoolAttribute(e, "value_type"),
|
||||
Alias = XmlUtil.GetOptionalAttribute(e, "alias"),
|
||||
Sep = XmlUtil.GetOptionalAttribute(e, "sep"),
|
||||
Comment = XmlUtil.GetOptionalAttribute(e, "comment"),
|
||||
Tags = XmlUtil.GetOptionalAttribute(e, "tags"),
|
||||
};
|
||||
var childBeans = new List<XElement>();
|
||||
|
||||
bool defineAnyChildBean = false;
|
||||
foreach (XElement fe in e.Elements())
|
||||
{
|
||||
switch (fe.Name.LocalName)
|
||||
{
|
||||
case "var":
|
||||
{
|
||||
if (defineAnyChildBean)
|
||||
{
|
||||
throw new LoadDefException($"定义文件:{defineFile} 类型:{b.FullName} 的多态子bean必须在所有成员字段 <var> 之前定义");
|
||||
}
|
||||
b.Fields.Add(CreateField(defineFile, fe)); ;
|
||||
break;
|
||||
}
|
||||
case "bean":
|
||||
{
|
||||
defineAnyChildBean = true;
|
||||
childBeans.Add(fe);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new LoadDefException($"定义文件:{defineFile} 类型:{b.FullName} 不支持 tag:{fe.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
s_logger.Trace("add bean:{@bean}", b);
|
||||
_beans.Add(b);
|
||||
|
||||
var fullname = b.FullName;
|
||||
foreach (var cb in childBeans)
|
||||
{
|
||||
AddBean(defineFile, cb, fullname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
using Bright.Collections;
|
||||
using Luban.Job.Cfg.Datas;
|
||||
using Luban.Job.Cfg.RawDefs;
|
||||
using Luban.Job.Cfg.TypeVisitors;
|
||||
using Luban.Job.Common.Defs;
|
||||
using Luban.Server.Common;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Luban.Job.Cfg.Defs
|
||||
{
|
||||
public class TableDataInfo
|
||||
{
|
||||
public List<Record> MainRecords { get; }
|
||||
|
||||
public List<Record> PatchRecords { get; }
|
||||
|
||||
public List<Record> FinalRecords { get; set; }
|
||||
|
||||
public Dictionary<DType, Record> FinalRecordMap { get; set; }
|
||||
|
||||
public TableDataInfo(List<Record> mainRecords, List<Record> patchRecords)
|
||||
{
|
||||
MainRecords = mainRecords;
|
||||
PatchRecords = patchRecords;
|
||||
}
|
||||
}
|
||||
|
||||
public class DefAssembly : DefAssemblyBase
|
||||
{
|
||||
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
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;
|
||||
|
||||
public Patch TargetPatch { get; private set; }
|
||||
|
||||
public TimeZoneInfo TimeZone { get; }
|
||||
|
||||
public DefAssembly(string patchName, TimeZoneInfo timezone, List<string> excludeTags, IAgent agent)
|
||||
{
|
||||
this._patchName = patchName;
|
||||
this.TimeZone = timezone;
|
||||
this._excludeTags = excludeTags;
|
||||
this.Agent = agent;
|
||||
}
|
||||
|
||||
public bool NeedExport(List<string> groups)
|
||||
{
|
||||
if (groups.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return groups.Any(g => CfgTargetService.Groups.Contains(g));
|
||||
}
|
||||
|
||||
private readonly List<Patch> _patches = new List<Patch>();
|
||||
|
||||
private readonly List<Service> _cfgServices = new List<Service>();
|
||||
|
||||
private readonly ConcurrentDictionary<string, TableDataInfo> _recordsByTables = new();
|
||||
|
||||
public Dictionary<string, DefTable> CfgTables { get; } = new Dictionary<string, DefTable>();
|
||||
|
||||
public Patch GetPatch(string name)
|
||||
{
|
||||
return _patches.Find(b => b.Name == name);
|
||||
}
|
||||
|
||||
public void AddCfgTable(DefTable table)
|
||||
{
|
||||
if (!CfgTables.TryAdd(table.FullName, table))
|
||||
{
|
||||
throw new Exception($"table:'{table.FullName}' duplicated");
|
||||
}
|
||||
}
|
||||
|
||||
public DefTable GetCfgTable(string name)
|
||||
{
|
||||
return CfgTables.TryGetValue(name, out var t) ? t : null;
|
||||
}
|
||||
|
||||
public void AddDataTable(DefTable table, List<Record> mainRecords, List<Record> patchRecords)
|
||||
{
|
||||
_recordsByTables[table.FullName] = new TableDataInfo(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;
|
||||
}
|
||||
}
|
||||
|
||||
public TableDataInfo GetTableDataInfo(DefTable table)
|
||||
{
|
||||
return _recordsByTables[table.FullName];
|
||||
}
|
||||
|
||||
public List<DefTable> GetExportTables()
|
||||
{
|
||||
return Types.Values.Where(t => t is DefTable ct && ct.NeedExport).Select(t => (DefTable)t).ToList();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
AddType(new DefEnum(e));
|
||||
}
|
||||
|
||||
foreach (var b in defines.Beans)
|
||||
{
|
||||
AddType(new DefBean((CfgBean)b));
|
||||
}
|
||||
|
||||
foreach (var p in defines.Tables)
|
||||
{
|
||||
var table = new DefTable(p);
|
||||
AddType(table);
|
||||
AddCfgTable(table);
|
||||
}
|
||||
|
||||
_cfgServices.AddRange(defines.Services);
|
||||
|
||||
foreach (var type in Types.Values)
|
||||
{
|
||||
type.AssemblyBase = this;
|
||||
}
|
||||
|
||||
foreach (var type in Types.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
s_logger.Trace("precompile type:{0} begin", type.FullName);
|
||||
type.PreCompile();
|
||||
s_logger.Trace("precompile type:{0} end", type.FullName);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
this.Agent.Error("precompile type:{0} error", type.FullName);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
foreach (var type in Types.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
s_logger.Trace("compile type:{0} begin", type.FullName);
|
||||
type.Compile();
|
||||
s_logger.Trace("compile type:{0} end", type.FullName);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
this.Agent.Error("compile type:{0} error", type.FullName);
|
||||
s_logger.Error("compile type:{0} error", type.FullName);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
foreach (var type in Types.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
s_logger.Trace("post compile type:{0} begin", type.FullName);
|
||||
type.PostCompile();
|
||||
s_logger.Trace("post compile type:{0} end", type.FullName);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
this.Agent.Error("post compile type:{0} error", type.FullName);
|
||||
s_logger.Error("post compile type:{0} error", type.FullName);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// 丑陋. 怎么写更好?
|
||||
|
||||
// 递归 设置DefBean及DefField 的 IsMultiRow
|
||||
|
||||
MarkMultiRows();
|
||||
}
|
||||
|
||||
public void MarkMultiRows()
|
||||
{
|
||||
var multiRowBeans = new HashSet<DefBean>();
|
||||
for (bool anyMark = true; anyMark;)
|
||||
{
|
||||
anyMark = false;
|
||||
foreach (var type in this.Types.Values)
|
||||
{
|
||||
if (type is DefBean beanType && !beanType.IsMultiRow)
|
||||
{
|
||||
bool isMultiRows;
|
||||
if (beanType.IsNotAbstractType)
|
||||
{
|
||||
isMultiRows = beanType.HierarchyFields.Any(f => ((DefField)f).ComputeIsMultiRow());
|
||||
}
|
||||
else
|
||||
{
|
||||
isMultiRows = beanType.HierarchyNotAbstractChildren.Any(c => ((DefBean)c).IsMultiRow);
|
||||
}
|
||||
if (isMultiRows)
|
||||
{
|
||||
beanType.IsMultiRow = true;
|
||||
//s_logger.Info("bean:{bean} is multi row", beanType.FullName);
|
||||
anyMark = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
using Luban.Common.Utils;
|
||||
using Luban.Job.Cfg.DataCreators;
|
||||
using Luban.Job.Cfg.Datas;
|
||||
using Luban.Job.Cfg.RawDefs;
|
||||
using Luban.Job.Common.Defs;
|
||||
using Luban.Job.Common.Types;
|
||||
using Luban.Job.Common.TypeVisitors;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Luban.Job.Cfg.Defs
|
||||
{
|
||||
public class DefField : DefFieldBase
|
||||
{
|
||||
public DefAssembly Assembly => (DefAssembly)HostType.AssemblyBase;
|
||||
|
||||
|
||||
public bool RawIsMultiRow { get; }
|
||||
|
||||
public bool IsMultiRow { get; private set; }
|
||||
|
||||
public bool ComputeIsMultiRow()
|
||||
{
|
||||
if (IsMultiRow)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (CType)
|
||||
{
|
||||
case TBean b: { return IsMultiRow = ((DefBean)b.Bean).IsMultiRow; }
|
||||
case TList b: { return IsMultiRow = b.ElementType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; }
|
||||
case TArray b: { return IsMultiRow = b.ElementType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; }
|
||||
case TMap b: { return IsMultiRow = b.ValueType is TBean b2 && ((DefBean)b2.Bean).IsMultiRow; }
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string Index { get; }
|
||||
|
||||
public List<string> Groups { get; }
|
||||
|
||||
public DefField IndexField { get; private set; }
|
||||
|
||||
|
||||
public string Sep { get; set; }
|
||||
|
||||
// 如果没有指定sep
|
||||
// 如果是bean,且指定了sep,则使用此值
|
||||
// 如果是vectorN,使用 ,
|
||||
public string ActualSep => string.IsNullOrWhiteSpace(Sep) ? (CType is TBean bean ? ((DefBean)bean.Bean).Sep : "") : Sep;
|
||||
|
||||
public bool NeedExport => Assembly.NeedExport(this.Groups);
|
||||
|
||||
public TEnum Remapper { get; private set; }
|
||||
|
||||
public CfgField RawDefine { get; }
|
||||
|
||||
public string GetTextKeyName(string name) => name + TText.L10N_FIELD_SUFFIX;
|
||||
|
||||
public bool GenTextKey => this.CType is TText;
|
||||
|
||||
|
||||
public string DefaultValue { get; }
|
||||
|
||||
public DType DefalutDtypeValue { get; private set; }
|
||||
|
||||
public bool IsRowOrient { get; }
|
||||
|
||||
public DefField(DefTypeBase host, CfgField f, int idOffset) : base(host, f, idOffset)
|
||||
{
|
||||
Index = f.Index;
|
||||
Sep = f.Sep;
|
||||
this.IsMultiRow = this.RawIsMultiRow = f.IsMultiRow;
|
||||
this.Groups = f.Groups;
|
||||
this.RawDefine = f;
|
||||
this.DefaultValue = f.DefaultValue;
|
||||
this.IsRowOrient = f.IsRowOrient;
|
||||
}
|
||||
|
||||
public override void Compile()
|
||||
{
|
||||
base.Compile();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(this.DefaultValue))
|
||||
{
|
||||
this.DefalutDtypeValue = CType.Apply(StringDataCreator.Ins, this.DefaultValue);
|
||||
}
|
||||
|
||||
switch (CType)
|
||||
{
|
||||
case TArray t:
|
||||
{
|
||||
if (t.ElementType is TBean e && !e.IsDynamic && e.Bean.HierarchyFields.Count == 0)
|
||||
{
|
||||
throw new Exception($"container element type:'{e.Bean.FullName}' can't be empty bean");
|
||||
}
|
||||
if (t.ElementType is TText)
|
||||
{
|
||||
throw new Exception($"bean:{HostType.FullName} field:{Name} container element type can't text");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TList t:
|
||||
{
|
||||
if (t.ElementType is TBean e && !e.IsDynamic && e.Bean.HierarchyFields.Count == 0)
|
||||
{
|
||||
throw new Exception($"container element type:'{e.Bean.FullName}' can't be empty bean");
|
||||
}
|
||||
if (t.ElementType is TText)
|
||||
{
|
||||
throw new Exception($"bean:{HostType.FullName} field:{Name} container element type can't text");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TSet t:
|
||||
{
|
||||
if (t.ElementType is TText)
|
||||
{
|
||||
throw new Exception($"bean:{HostType.FullName} field:{Name} container element type can't text");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TMap t:
|
||||
{
|
||||
if (t.KeyType is TText)
|
||||
{
|
||||
throw new Exception($"bean:{HostType.FullName} field:{Name} container key type can't text");
|
||||
}
|
||||
if (t.ValueType is TText)
|
||||
{
|
||||
throw new Exception($"bean:{HostType.FullName} field:{Name} container value type can't text");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsMultiRow && !CType.IsCollection && !CType.IsBean)
|
||||
{
|
||||
throw new Exception($"只有容器类型才支持 multi_line 属性");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(Sep) && CType is TBean bean)
|
||||
{
|
||||
Sep = bean.GetBeanAs<DefBean>().Sep;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(Index))
|
||||
{
|
||||
if ((CType is TArray tarray) && (tarray.ElementType is TBean b))
|
||||
{
|
||||
if ((IndexField = b.GetBeanAs<DefBean>().GetField(Index)) == null)
|
||||
{
|
||||
throw new Exception($"type:'{HostType.FullName}' field:'{Name}' index:'{Index}'. index not exist");
|
||||
}
|
||||
}
|
||||
else if ((CType is TList tlist) && (tlist.ElementType is TBean tb))
|
||||
{
|
||||
if ((IndexField = tb.GetBeanAs<DefBean>().GetField(Index)) == null)
|
||||
{
|
||||
throw new Exception($"type:'{HostType.FullName}' field:'{Name}' index:'{Index}'. index not exist");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"type:'{HostType.FullName}' field:'{Name}' index:'{Index}'. only array:bean or list:bean support index");
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(this.RawDefine.Converter))
|
||||
{
|
||||
this.Remapper = AssemblyBase.GetDefTType(HostType.Namespace, this.RawDefine.Converter, this.IsNullable) as TEnum;
|
||||
if (this.Remapper == null)
|
||||
{
|
||||
throw new Exception($"type:'{HostType.FullName}' field:'{Name}' converter:'{this.RawDefine.Converter}' not exists");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
using Luban.Common.Utils;
|
||||
using Luban.Server.Common;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Luban.Job.Common.Defs
|
||||
{
|
||||
public abstract class DefTypeBase
|
||||
{
|
||||
public DefAssemblyBase AssemblyBase { get; set; }
|
||||
|
||||
public int Id { get; protected set; }
|
||||
|
||||
public string TopModule => AssemblyBase.TopModule;
|
||||
|
||||
public IAgent Agent => AssemblyBase.Agent;
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Namespace { get; set; }
|
||||
|
||||
public string FullName => TypeUtil.MakeFullName(Namespace, Name);
|
||||
|
||||
public string NamespaceWithTopModule => TypeUtil.MakeNamespace(AssemblyBase.TopModule, Namespace);
|
||||
|
||||
public string FullNameWithTopModule => TypeUtil.MakeFullName(AssemblyBase.TopModule, FullName);
|
||||
|
||||
public string JavaFullName => TypeUtil.MakeFullName(Namespace, Name);
|
||||
|
||||
public string GoFullName => TypeUtil.MakeGoFullName(Namespace, Name);
|
||||
|
||||
public string GoPkgName => TypeUtil.MakeGoPkgName(Namespace);
|
||||
|
||||
public string CppNamespaceBegin => TypeUtil.MakeCppNamespaceBegin(Namespace);
|
||||
|
||||
public string CppNamespaceEnd => TypeUtil.MakeCppNamespaceEnd(Namespace);
|
||||
|
||||
public string CppFullNameWithTopModule => TypeUtil.MakeCppFullName(AssemblyBase.TopModule, FullName);
|
||||
|
||||
public string TypescriptNamespaceBegin => TypeUtil.MakeTypescriptNamespaceBegin(Namespace);
|
||||
|
||||
public string TypescriptNamespaceEnd => TypeUtil.MakeTypescriptNamespaceEnd(Namespace);
|
||||
|
||||
public string CppFullName => TypeUtil.MakeCppFullName(Namespace, Name);
|
||||
|
||||
public string PyFullName => TypeUtil.MakePyFullName(Namespace, Name);
|
||||
|
||||
public string RustFullName => TypeUtil.MakeRustFullName(Namespace, Name);
|
||||
|
||||
public string Comment { get; protected set; }
|
||||
|
||||
public Dictionary<string, string> Tags { get; protected set; }
|
||||
|
||||
public bool HasTag(string attrName)
|
||||
{
|
||||
return Tags != null && Tags.ContainsKey(attrName);
|
||||
}
|
||||
|
||||
public string GetTag(string attrName)
|
||||
{
|
||||
return Tags != null && Tags.TryGetValue(attrName, out var value) ? value : null;
|
||||
}
|
||||
|
||||
public virtual void PreCompile() { }
|
||||
|
||||
public abstract void Compile();
|
||||
|
||||
public virtual void PostCompile() { }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
using Bright.Serialization;
|
||||
|
||||
namespace Luban.Common.Protos
|
||||
{
|
||||
public class FileInfo : BeanBase
|
||||
{
|
||||
public string FilePath { get; set; }
|
||||
|
||||
public string MD5 { get; set; }
|
||||
|
||||
public override void Serialize(ByteBuf os)
|
||||
{
|
||||
os.WriteString(FilePath);
|
||||
os.WriteString(MD5);
|
||||
}
|
||||
|
||||
public override void Deserialize(ByteBuf os)
|
||||
{
|
||||
FilePath = os.ReadString();
|
||||
MD5 = os.ReadString();
|
||||
}
|
||||
|
||||
public override int GetTypeId()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
using Bright.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Luban.Common.Protos
|
||||
{
|
||||
public class GetImportFileOrDirectoryArg : BeanBase
|
||||
{
|
||||
public string FileOrDirName { get; set; }
|
||||
|
||||
public List<string> InclusiveSuffixs { get; set; } = new List<string>();
|
||||
|
||||
public override int GetTypeId()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void Serialize(ByteBuf os)
|
||||
{
|
||||
os.WriteString(FileOrDirName);
|
||||
Bright.Common.SerializationUtil.Serialize(os, InclusiveSuffixs);
|
||||
}
|
||||
public override void Deserialize(ByteBuf os)
|
||||
{
|
||||
FileOrDirName = os.ReadString();
|
||||
Bright.Common.SerializationUtil.Deserialize(os, InclusiveSuffixs);
|
||||
}
|
||||
}
|
||||
|
||||
public class GetImportFileOrDirectoryRes : BeanBase
|
||||
{
|
||||
public EErrorCode Err { get; set; }
|
||||
|
||||
public bool IsFile { get; set; }
|
||||
|
||||
public string Md5 { get; set; }
|
||||
|
||||
//public byte[] Content { get; set; }
|
||||
|
||||
public List<FileInfo> SubFiles { get; set; }
|
||||
|
||||
public override int GetTypeId()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void Serialize(ByteBuf os)
|
||||
{
|
||||
os.WriteInt((int)Err);
|
||||
os.WriteBool(IsFile);
|
||||
os.WriteString(Md5);
|
||||
Bright.Common.SerializationUtil.Serialize(os, SubFiles);
|
||||
}
|
||||
public override void Deserialize(ByteBuf os)
|
||||
{
|
||||
Err = (EErrorCode)os.ReadInt();
|
||||
IsFile = os.ReadBool();
|
||||
Md5 = os.ReadString();
|
||||
Bright.Common.SerializationUtil.Deserialize(os, SubFiles = new List<FileInfo>());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
|
||||
using Bright.Time;
|
||||
using Luban.Common.Protos;
|
||||
using Luban.Common.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Luban.Server.Common
|
||||
{
|
||||
public class LocalAgent : IAgent
|
||||
{
|
||||
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public LocalAgent()
|
||||
{
|
||||
}
|
||||
|
||||
public Task<byte[]> ReadAllBytesAsync(string file)
|
||||
{
|
||||
return FileUtil.ReadAllBytesAsync(file);
|
||||
}
|
||||
|
||||
public async Task<byte[]> GetFromCacheOrReadAllBytesAsync(string file, string md5)
|
||||
{
|
||||
var content = await ReadAllBytesAsync(file).ConfigureAwait(false);
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
public async Task<GetImportFileOrDirectoryRes> GetFileOrDirectoryAsync(string file, params string[] searchPatterns)
|
||||
{
|
||||
long t1 = TimeUtil.NowMillis;
|
||||
var re = new GetImportFileOrDirectoryRes()
|
||||
{
|
||||
SubFiles = new List<Luban.Common.Protos.FileInfo>(),
|
||||
};
|
||||
var suffixes = new List<string>(searchPatterns.Select(s => s.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)));
|
||||
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(file))
|
||||
{
|
||||
re.Err = 0;
|
||||
re.IsFile = false;
|
||||
foreach (var subFile in Directory.GetFiles(file, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
if (FileUtil.IsValidInputFile(subFile) && (suffixes.Count == 0 || suffixes.Any(s => subFile.EndsWith(s))))
|
||||
{
|
||||
|
||||
var md5 = FileUtil.CalcMD5(await FileUtil.ReadAllBytesAsync(subFile));
|
||||
re.SubFiles.Add(new Luban.Common.Protos.FileInfo() { FilePath = FileUtil.Standardize(subFile), MD5 = md5 });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (File.Exists(file))
|
||||
{
|
||||
re.IsFile = true;
|
||||
re.Md5 = FileUtil.CalcMD5(await FileUtil.ReadAllBytesAsync(file));
|
||||
}
|
||||
else
|
||||
{
|
||||
re.Err = Luban.Common.EErrorCode.FILE_OR_DIR_NOT_EXISTS;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
re.Err = Luban.Common.EErrorCode.READ_FILE_FAIL;
|
||||
s_logger.Error(e);
|
||||
}
|
||||
|
||||
s_logger.Trace(" GetImportFileOrDirectory file:{file} err:{err} cost:{time}", file, re.Err, TimeUtil.NowMillis - t1);
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
public Task<QueryFilesExistsRes> QueryFileExistsAsync(QueryFilesExistsArg arg)
|
||||
{
|
||||
var re = new QueryFilesExistsRes() { Exists = new List<bool>(arg.Files.Count) };
|
||||
foreach (var f in arg.Files)
|
||||
{
|
||||
re.Exists.Add(File.Exists(Path.Combine(arg.Root, f)));
|
||||
}
|
||||
return Task.FromResult(re);
|
||||
}
|
||||
|
||||
public async Task<XElement> OpenXmlAsync(string xmlFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
s_logger.Trace("open {xml}", xmlFile);
|
||||
return XElement.Load(new MemoryStream(await ReadAllBytesAsync(xmlFile)));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"打开定义文件:{xmlFile} 失败 --> {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#region log
|
||||
|
||||
public void Error(string fmt, params object[] objs)
|
||||
{
|
||||
Log("error", string.Format(fmt, objs));
|
||||
}
|
||||
|
||||
public void Info(string fmt, params object[] objs)
|
||||
{
|
||||
Log("info", string.Format(fmt, objs));
|
||||
}
|
||||
|
||||
private void Log(string level, string content)
|
||||
{
|
||||
//Session.Send(new PushLog() { Level = level, LogContent = content });
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
using Bright.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Luban.Common.Protos
|
||||
{
|
||||
public class QueryFilesExistsArg : BeanBase
|
||||
{
|
||||
public string Root { get; set; }
|
||||
|
||||
public List<string> Files { get; set; }
|
||||
|
||||
public override int GetTypeId()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void Serialize(ByteBuf os)
|
||||
{
|
||||
os.WriteString(Root);
|
||||
Bright.Common.SerializationUtil.Serialize(os, Files);
|
||||
}
|
||||
public override void Deserialize(ByteBuf os)
|
||||
{
|
||||
Root = os.ReadString();
|
||||
Bright.Common.SerializationUtil.Deserialize(os, Files = new List<string>());
|
||||
}
|
||||
}
|
||||
|
||||
public class QueryFilesExistsRes : BeanBase
|
||||
{
|
||||
public List<bool> Exists { get; set; }
|
||||
|
||||
public override int GetTypeId()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void Serialize(ByteBuf os)
|
||||
{
|
||||
os.WriteSize(Exists.Count);
|
||||
foreach (var v in Exists)
|
||||
{
|
||||
os.WriteBool(v);
|
||||
}
|
||||
}
|
||||
public override void Deserialize(ByteBuf os)
|
||||
{
|
||||
int n = os.ReadSize();
|
||||
Exists = new List<bool>();
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
Exists.Add(os.ReadBool());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
namespace Bright.Serialization
|
||||
{
|
||||
public abstract class BeanBase : ITypeId, ISerializable
|
||||
{
|
||||
public abstract int GetTypeId();
|
||||
|
||||
public abstract void Serialize(ByteBuf os);
|
||||
|
||||
public abstract void Deserialize(ByteBuf os);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,10 @@
|
|||
namespace Bright.Serialization
|
||||
{
|
||||
public enum EDeserializeError
|
||||
{
|
||||
OK,
|
||||
NOT_ENOUGH,
|
||||
EXCEED_SIZE,
|
||||
// UNMARSHAL_ERR,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
namespace Bright.Serialization
|
||||
{
|
||||
|
||||
// 把 int,long,string,bool 调整到最小
|
||||
// 这样 marshal compatible write(field_id << tag_shift | tag_id) < 2^7 能在一个字节
|
||||
// 内序列化, 优化序列化最终大小
|
||||
#pragma warning disable CA1720 // 标识符包含类型名称
|
||||
public static class FieldTag
|
||||
{
|
||||
public const int
|
||||
INT = 0,
|
||||
LONG = 1,
|
||||
STRING = 2,
|
||||
BOOL = 3,
|
||||
|
||||
BYTE = 4,
|
||||
SHORT = 5,
|
||||
FSHORT = 6,
|
||||
FINT = 7,
|
||||
FLONG = 8,
|
||||
FLOAT = 9,
|
||||
DOUBLE = 10,
|
||||
BYTES = 11,
|
||||
ARRAY = 12,
|
||||
LIST = 13,
|
||||
SET = 14,
|
||||
MAP = 15,
|
||||
BEAN = 16,
|
||||
TEXT = 17,
|
||||
VECTOR2 = 18,
|
||||
VECTOR3 = 19,
|
||||
VECTOR4 = 20,
|
||||
DYNAMIC_BEAN = 21,
|
||||
|
||||
NOT_USE = 22;
|
||||
|
||||
|
||||
public const int TAG_SHIFT = 5;
|
||||
public const int TAG_MASK = (1 << TAG_SHIFT) - 1;
|
||||
}
|
||||
#pragma warning restore CA1720 // 标识符包含类型名称
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
namespace Bright.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// 非兼容binary序列化
|
||||
/// </summary>
|
||||
public interface ISerializable
|
||||
{
|
||||
void Serialize(ByteBuf os);
|
||||
|
||||
void Deserialize(ByteBuf os);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
namespace Bright.Serialization
|
||||
{
|
||||
public interface ITypeId
|
||||
{
|
||||
int GetTypeId();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#define CPU_SUPPORT_MEMORY_NOT_ALIGN //CPU 是否支持读取非对齐内存
|
||||
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// 1. 整理代码
|
||||
/// 2. 优化序列化 (像这样 data[endPos + 1] = (byte)(x >> 8) 挨个字节赋值总感觉很低效,能优化吗)
|
||||
/// </summary>
|
||||
|
||||
|
||||
namespace Bright.Serialization
|
||||
{
|
||||
public class SerializationException : Exception
|
||||
{
|
||||
public SerializationException() { }
|
||||
public SerializationException(string msg) : base(msg) { }
|
||||
|
||||
public SerializationException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
using Bright.Time;
|
||||
using Luban.Common.Utils;
|
||||
using Luban.Job.Cfg.DataCreators;
|
||||
using Luban.Job.Cfg.Datas;
|
||||
using Luban.Job.Cfg.DataSources;
|
||||
using Luban.Job.Cfg.Defs;
|
||||
using Luban.Job.Common.Types;
|
||||
using Luban.Job.Common.Utils;
|
||||
using Luban.Server.Common;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Luban.Job.Cfg.Utils
|
||||
{
|
||||
public static class DataLoaderUtil
|
||||
{
|
||||
private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public class InputFileInfo
|
||||
{
|
||||
public string MD5 { get; set; }
|
||||
|
||||
public string OriginFile { get; set; }
|
||||
|
||||
public string ActualFile { get; set; }
|
||||
|
||||
public string SheetName { get; set; }
|
||||
}
|
||||
|
||||
public static async Task<List<InputFileInfo>> CollectInputFilesAsync(IAgent agent, IEnumerable<string> files, string dataDir)
|
||||
{
|
||||
var collectTasks = new List<Task<List<InputFileInfo>>>();
|
||||
foreach (var file in files)
|
||||
{
|
||||
(var actualFile, var sheetName) = FileUtil.SplitFileAndSheetName(FileUtil.Standardize(file));
|
||||
var actualFullPath = FileUtil.Combine(dataDir, actualFile);
|
||||
var originFullPath = FileUtil.Combine(dataDir, file);
|
||||
//s_logger.Info("== get input file:{file} actualFile:{actual}", file, actualFile);
|
||||
|
||||
collectTasks.Add(Task.Run(async () =>
|
||||
{
|
||||
var fileOrDirContent = await agent.GetFileOrDirectoryAsync(actualFullPath, DataSourceFactory.validDataSourceSuffixes);
|
||||
if (fileOrDirContent.IsFile)
|
||||
{
|
||||
return new List<InputFileInfo> { new InputFileInfo() { OriginFile = file, ActualFile = actualFullPath, SheetName = sheetName, MD5 = fileOrDirContent.Md5 } };
|
||||
}
|
||||
else
|
||||
{
|
||||
return fileOrDirContent.SubFiles.Select(f => new InputFileInfo() { OriginFile = f.FilePath, ActualFile = f.FilePath, MD5 = f.MD5 }).ToList();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
var allFiles = new List<InputFileInfo>();
|
||||
foreach (var t in collectTasks)
|
||||
{
|
||||
allFiles.AddRange(await t);
|
||||
}
|
||||
return allFiles;
|
||||
}
|
||||
|
||||
//private async Task<List<InputFileInfo>> CollectInputFilesAsync(RemoteAgent agent, DefTable table, string dataDir)
|
||||
//{
|
||||
// var collectTasks = new List<Task<List<InputFileInfo>>>();
|
||||
// foreach (var file in table.InputFiles)
|
||||
// return CollectInputFilesAsync(agent, table.InputFiles, dataDir)
|
||||
//}
|
||||
|
||||
public static async Task GenerateLoadRecordFromFileTasksAsync(IAgent agent, DefTable table, string dataDir, List<string> inputFiles2, List<Task<List<Record>>> tasks)
|
||||
{
|
||||
var inputFileInfos = await CollectInputFilesAsync(agent, inputFiles2, dataDir);
|
||||
|
||||
// check cache (table, exporttestdata) -> (list<InputFileInfo>, List<DType>)
|
||||
// (md5, sheetName,exportTestData) -> (value_type, List<DType>)
|
||||
|
||||
foreach (var file in inputFileInfos)
|
||||
{
|
||||
var actualFile = file.ActualFile;
|
||||
//s_logger.Info("== get input file:{file} actualFile:{actual}", file, actualFile);
|
||||
|
||||
tasks.Add(Task.Run(async () =>
|
||||
{
|
||||
var res = LoadCfgRecords(table.ValueTType,
|
||||
file.OriginFile,
|
||||
file.SheetName,
|
||||
await agent.GetFromCacheOrReadAllBytesAsync(file.ActualFile, file.MD5),
|
||||
FileUtil.IsExcelFile(file.ActualFile));
|
||||
|
||||
return res;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task 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);
|
||||
|
||||
var patchLoadTasks = new List<Task<List<Record>>>();
|
||||
|
||||
Task patchGenerateTask = null;
|
||||
if (!string.IsNullOrWhiteSpace(patchName))
|
||||
{
|
||||
var patchInputFiles = table.GetPatchInputFiles(patchName);
|
||||
if (patchInputFiles != null)
|
||||
{
|
||||
patchGenerateTask = GenerateLoadRecordFromFileTasksAsync(agent, table, patchDataDir, patchInputFiles, patchLoadTasks);
|
||||
}
|
||||
}
|
||||
|
||||
await mainGenerateTask;
|
||||
|
||||
var mainRecords = new List<Record>(256);
|
||||
foreach (var task in mainLoadTasks)
|
||||
{
|
||||
mainRecords.AddRange(await task);
|
||||
}
|
||||
s_logger.Trace("== load main records. count:{count}", mainRecords.Count);
|
||||
|
||||
List<Record> patchRecords = null;
|
||||
if (patchGenerateTask != null)
|
||||
{
|
||||
patchRecords = new List<Record>(64);
|
||||
await patchGenerateTask;
|
||||
foreach (var task in patchLoadTasks)
|
||||
{
|
||||
patchRecords.AddRange(await task);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
public static async Task LoadCfgDataAsync(IAgent agent, DefAssembly ass, string dataDir, string patchName, string patchDataDir)
|
||||
{
|
||||
var ctx = agent;
|
||||
List<DefTable> exportTables = ass.Types.Values.Where(t => t is DefTable ct && ct.NeedExport).Select(t => (DefTable)t).ToList();
|
||||
var genDataTasks = new List<Task>();
|
||||
var outputDataFiles = new ConcurrentBag<FileInfo>();
|
||||
long genDataStartTime = TimeUtil.NowMillis;
|
||||
|
||||
foreach (DefTable c in exportTables)
|
||||
{
|
||||
var table = c;
|
||||
genDataTasks.Add(Task.Run(async () =>
|
||||
{
|
||||
long beginTime = TimeUtil.NowMillis;
|
||||
await LoadTableAsync(agent, table, dataDir, patchName, patchDataDir);
|
||||
long endTime = TimeUtil.NowMillis;
|
||||
if (endTime - beginTime > 100)
|
||||
{
|
||||
ctx.Info("====== load {0} cost {1} ms ======", table.FullName, (endTime - beginTime));
|
||||
}
|
||||
}));
|
||||
}
|
||||
await Task.WhenAll(genDataTasks.ToArray());
|
||||
}
|
||||
|
||||
public static List<Record> LoadCfgRecords(TBean recordType, string originFile, string sheetName, byte[] content, bool multiRecord)
|
||||
{
|
||||
// (md5,sheet,multiRecord,exportTestData) -> (valuetype, List<(datas)>)
|
||||
var dataSource = DataSourceFactory.Create(originFile, sheetName, new MemoryStream(content));
|
||||
try
|
||||
{
|
||||
if (multiRecord)
|
||||
{
|
||||
return dataSource.ReadMulti(recordType);
|
||||
}
|
||||
else
|
||||
{
|
||||
Record record = dataSource.ReadOne(recordType);
|
||||
return record != null ? new List<Record> { record } : new List<Record>();
|
||||
}
|
||||
}
|
||||
catch (DataCreateException dce)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dce.OriginDataLocation))
|
||||
{
|
||||
dce.OriginDataLocation = originFile;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception($"配置文件:{originFile} 生成失败.", e);
|
||||
}
|
||||
}
|
||||
|
||||
#if !LUBAN_ASSISTANT
|
||||
public static async Task LoadTextTablesAsync(IAgent agent, DefAssembly ass, string baseDir, string textTableFiles)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
var textTable = ass.ExportTextTable;
|
||||
for (int i = 0; i < tasks.Count; i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ using System.Xml.Linq;
|
|||
using Excel = Microsoft.Office.Interop.Excel;
|
||||
using Office = Microsoft.Office.Core;
|
||||
using Microsoft.Office.Tools.Excel;
|
||||
using Microsoft.Office.Tools.Ribbon;
|
||||
|
||||
namespace LubanAssistant
|
||||
{
|
||||
|
|
@ -19,6 +20,17 @@ namespace LubanAssistant
|
|||
{
|
||||
}
|
||||
|
||||
//protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
|
||||
//{
|
||||
// return new ToolTab();
|
||||
//}
|
||||
|
||||
|
||||
protected override IRibbonExtension[] CreateRibbonObjects()
|
||||
{
|
||||
return new IRibbonExtension[] { new AssistantTab() };
|
||||
}
|
||||
|
||||
#region VSTO 生成的代码
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<section name="LubanAssistant.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<userSettings>
|
||||
<LubanAssistant.Properties.Settings>
|
||||
<setting name="rootDefineFile" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
</LubanAssistant.Properties.Settings>
|
||||
</userSettings>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?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="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" />
|
||||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
|
||||
<package id="YamlDotNet" version="11.2.1" targetFramework="net472" />
|
||||
</packages>
|
||||
Loading…
Reference in New Issue