diff --git a/src/Luban.Job.Db/Luban.Job.Db.csproj b/src/Luban.Job.Db/Luban.Job.Db.csproj
new file mode 100644
index 0000000..aa0bab2
--- /dev/null
+++ b/src/Luban.Job.Db/Luban.Job.Db.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Library
+ net5.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Luban.Job.Db/Source/Defs/DbDefLoader.cs b/src/Luban.Job.Db/Source/Defs/DbDefLoader.cs
new file mode 100644
index 0000000..e1ed832
--- /dev/null
+++ b/src/Luban.Job.Db/Source/Defs/DbDefLoader.cs
@@ -0,0 +1,52 @@
+using Luban.Job.Common.Utils;
+using Luban.Job.Common.Defs;
+using System.Collections.Generic;
+using System.Xml.Linq;
+using Luban.Server.Common;
+using Luban.Common.Utils;
+using Luban.Job.Db.RawDefs;
+
+namespace Luban.Job.Db.Defs
+{
+ class DbDefLoader : CommonDefLoader
+ {
+ private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
+
+ private readonly List
_tables = new List();
+
+ public DbDefLoader(RemoteAgent agent) : base(agent)
+ {
+ RegisterModuleDefineHandler("table", AddTable);
+ }
+
+ public Defines BuildDefines()
+ {
+ return new Defines();
+ }
+
+
+
+ private readonly List _tableOptionalAttrs = new List { "memory" };
+ private readonly List _tableRequireAttrs = new List { "name", "id", "key", "value" };
+
+ private void AddTable(XElement e)
+ {
+ ValidAttrKeys(e, _tableOptionalAttrs, _tableRequireAttrs);
+ var p = new Table()
+ {
+ Id = XmlUtil.GetRequiredIntAttribute(e, "id"),
+ Name = XmlUtil.GetRequiredAttribute(e, "name"),
+ Namespace = CurNamespace,
+ KeyType = XmlUtil.GetRequiredAttribute(e, "key"),
+ ValueType = XmlUtil.GetRequiredAttribute(e, "value"),
+ IsPersistent = !XmlUtil.GetOptionBoolAttribute(e, "memory"),
+ };
+
+ s_logger.Trace("add Db:{@Db}", p);
+ _tables.Add(p);
+ }
+
+
+
+ }
+}
diff --git a/src/Luban.Job.Db/Source/Defs/DbDefTypeBase.cs b/src/Luban.Job.Db/Source/Defs/DbDefTypeBase.cs
new file mode 100644
index 0000000..a3618b0
--- /dev/null
+++ b/src/Luban.Job.Db/Source/Defs/DbDefTypeBase.cs
@@ -0,0 +1,9 @@
+using Luban.Job.Common.Defs;
+
+namespace Luban.Job.Db.Defs
+{
+ abstract class DbDefTypeBase : DefTypeBase
+ {
+ public DefAssembly Assembly => (DefAssembly)AssemblyBase;
+ }
+}
diff --git a/src/Luban.Job.Db/Source/Defs/DefAssembly.cs b/src/Luban.Job.Db/Source/Defs/DefAssembly.cs
new file mode 100644
index 0000000..fdc49af
--- /dev/null
+++ b/src/Luban.Job.Db/Source/Defs/DefAssembly.cs
@@ -0,0 +1,109 @@
+using Luban.Job.Common.Defs;
+using Luban.Job.Db.RawDefs;
+using Luban.Server.Common;
+using System;
+using System.Collections.Generic;
+
+namespace Luban.Job.Db.Defs
+{
+ class DefAssembly : DefAssemblyBase
+ {
+ private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
+
+ private readonly Dictionary name2DbTables = new Dictionary();
+
+ private readonly Dictionary id2DbTables = new Dictionary();
+
+ public void AddDbTable(DefTable table)
+ {
+ if (!name2DbTables.TryAdd(table.FullName, table))
+ {
+ throw new Exception($"table:{table.FullName} duplicated");
+ }
+ if (!id2DbTables.TryAdd(table.TableUId, table))
+ {
+ throw new Exception($"table:{table.FullName} 与 table:{id2DbTables[table.TableUId].FullName} id:{table.TableUId} duplicated");
+ }
+ }
+
+
+ public void Load(Defines defines, RemoteAgent agent)
+ {
+ this.Agent = agent;
+ TopModule = defines.TopModule;
+
+
+ foreach (var c in defines.Consts)
+ {
+ AddType(new DefConst(c));
+ }
+
+ foreach (var e in defines.Enums)
+ {
+ AddType(new DefEnum(e));
+ }
+
+ foreach (var b in defines.Beans)
+ {
+ AddType(new DefBean(b));
+ }
+
+ foreach (var p in defines.DbTables)
+ {
+ AddType(new DefTable(p));
+ }
+
+ 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)
+ {
+ 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)
+ {
+ 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)
+ {
+ agent.Error("post compile type:{0} error", type.FullName);
+ s_logger.Error("post compile type:{0} error", type.FullName);
+ throw;
+ }
+ }
+ }
+
+
+ }
+}
diff --git a/src/Luban.Job.Db/Source/Defs/DefBean.cs b/src/Luban.Job.Db/Source/Defs/DefBean.cs
new file mode 100644
index 0000000..e2717c7
--- /dev/null
+++ b/src/Luban.Job.Db/Source/Defs/DefBean.cs
@@ -0,0 +1,182 @@
+using Luban.Job.Common.RawDefs;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Luban.Job.Db.Defs
+{
+ class DefBean : DbDefTypeBase
+ {
+ public const string TYPE_NAME_KEY = "__type__";
+
+ public bool IsBean => true;
+
+ public string Parent { get; }
+
+ public bool IsValueType { get; }
+
+ public bool IsMultiRow { get; set; }
+
+ public DefBean ParentDefType { get; protected set; }
+
+ public DefBean RootDefType => this.ParentDefType == null ? this : this.ParentDefType.RootDefType;
+
+ public bool IsSerializeCompatible { get; }
+
+ public List Children { get; private set; }
+
+ public List HierarchyNotAbstractChildren { get; private set; }
+
+ public bool IsNotAbstractType => Children == null;
+
+ public bool IsAbstractType => Children != null;
+
+ public List HierarchyFields { get; private set; } = new List();
+
+ public List Fields { get; } = new List();
+
+ public string CsClassModifier => IsAbstractType ? "abstract" : "sealed";
+
+ public string CsMethodModifier => ParentDefType != null ? "override" : (IsAbstractType ? "virtual" : "");
+
+ public DefBean(Bean b)
+ {
+ Name = b.Name;
+ Namespace = b.Namespace;
+ Parent = b.Parent;
+ Id = b.TypeId;
+ IsValueType = b.IsValueType;
+ foreach (var field in b.Fields)
+ {
+ Fields.Add(new DefField(this, field, 0));
+ }
+ }
+
+ private void CollectHierarchyNotAbstractChildren(List children)
+ {
+ if (IsAbstractType)
+ {
+ foreach (var c in Children)
+ {
+ c.CollectHierarchyNotAbstractChildren(children);
+ }
+ }
+ else
+ {
+ children.Add(this);
+ }
+ }
+
+ internal DefBean GetNotAbstractChildType(string typeNameOrAliasName)
+ {
+ if (string.IsNullOrWhiteSpace(typeNameOrAliasName))
+ {
+ return null;
+ }
+ foreach (var c in HierarchyNotAbstractChildren)
+ {
+ if (c.Name == typeNameOrAliasName)
+ {
+ return c;
+ }
+ }
+ return null;
+ }
+
+ internal DefField GetField(string index)
+ {
+ return HierarchyFields.Where(f => f.Name == index).FirstOrDefault();
+ }
+
+ internal bool TryGetField(string index, out DefField field, out int fieldIndexId)
+ {
+ for (int i = 0; i < HierarchyFields.Count; i++)
+ {
+ if (HierarchyFields[i].Name == index)
+ {
+ field = HierarchyFields[i];
+ fieldIndexId = i;
+ return true;
+ }
+ }
+ field = null;
+ fieldIndexId = 0;
+ return false;
+ }
+
+ private void CollectHierarchyFields(List fields)
+ {
+ if (ParentDefType != null)
+ {
+ ParentDefType.CollectHierarchyFields(fields);
+ }
+ fields.AddRange(Fields);
+ }
+
+ public override void PreCompile()
+ {
+ var agent = AssemblyBase.Agent;
+ agent.Trace("compile bean module:{0} name:{1} begin", Namespace, Name);
+ if (!string.IsNullOrEmpty(Parent))
+ {
+ if ((ParentDefType = (DefBean)Assembly.GetDefType(Namespace, Parent)) == null)
+ {
+ throw new Exception($"bean:{FullName} parent:{Parent} not exist");
+ }
+ if (ParentDefType.Children == null)
+ {
+ ParentDefType.Children = new List();
+ }
+ ParentDefType.Children.Add(this);
+ }
+
+ CollectHierarchyFields(HierarchyFields);
+ }
+
+ public override void Compile()
+ {
+ var agent = AssemblyBase.Agent;
+ var cs = new List();
+ if (Children != null)
+ {
+ CollectHierarchyNotAbstractChildren(cs);
+ }
+ HierarchyNotAbstractChildren = cs;
+
+
+ var ids = new HashSet();
+ foreach (var c in cs)
+ {
+ if (c.Id == 0)
+ {
+ throw new Exception($"bean:{FullName} is child of dynamic type. beanid:{Id} can't be 0!");
+ }
+ if (!ids.Add(c.Id))
+ {
+ throw new Exception($"bean:{c.FullName} beanid:{c.Id} duplicate!");
+ }
+ }
+
+ DefField.CompileFields(this, HierarchyFields, true);
+ if (IsValueType && HierarchyFields.Any(f => f.CType.NeedSetChildrenRoot()))
+ {
+ foreach (var f in Fields)
+ {
+ if (f.CType.NeedSetChildrenRoot())
+ {
+ throw new Exception($"bean:{FullName} value type field:{f.Name} must be primitive type");
+ }
+ }
+
+ }
+ }
+
+ public override void PostCompile()
+ {
+ foreach (var field in HierarchyFields)
+ {
+ field.PostCompile();
+ }
+ }
+ }
+}
diff --git a/src/Luban.Job.Db/Source/Defs/DefField.cs b/src/Luban.Job.Db/Source/Defs/DefField.cs
new file mode 100644
index 0000000..f545d04
--- /dev/null
+++ b/src/Luban.Job.Db/Source/Defs/DefField.cs
@@ -0,0 +1,15 @@
+using Luban.Job.Common.Defs;
+using Luban.Job.Common.RawDefs;
+
+namespace Luban.Job.Db.Defs
+{
+ class DefField : DefFieldBase
+ {
+ public DefAssembly Assembly => (DefAssembly)HostType.AssemblyBase;
+
+ public DefField(DbDefTypeBase host, Field f, int idOffset) : base(host, f, idOffset)
+ {
+
+ }
+ }
+}
diff --git a/src/Luban.Job.Db/Source/Defs/DefTable.cs b/src/Luban.Job.Db/Source/Defs/DefTable.cs
new file mode 100644
index 0000000..c3df85f
--- /dev/null
+++ b/src/Luban.Job.Db/Source/Defs/DefTable.cs
@@ -0,0 +1,52 @@
+using Luban.Job.Common.Types;
+using Luban.Job.Db.RawDefs;
+using System;
+
+namespace Luban.Job.Db.Defs
+{
+ class DefTable : DbDefTypeBase
+ {
+ public DefTable(Table b)
+ {
+ Name = b.Name;
+ Namespace = b.Namespace;
+ TableUId = b.Id;
+ KeyType = b.KeyType;
+ ValueType = b.ValueType;
+ IsPersistent = b.IsPersistent;
+ }
+
+ public string KeyType { get; }
+
+ public string ValueType { get; }
+
+ public bool IsPersistent { get; }
+
+ public TType KeyTType { get; private set; }
+
+ public TBean ValueTType { get; private set; }
+
+ public int TableUId { get; set; }
+
+ public string InternalTableType => "_" + Name;
+
+ //public string BaseTableType => KeyTType.GetDbCsBaseTableType(KeyTType, ValueTType);
+
+ public override void Compile()
+ {
+ var ass = Assembly;
+
+ ass.AddDbTable(this);
+
+ if ((KeyTType = ass.CreateType(Namespace, KeyType)) == null)
+ {
+ throw new Exception($"table:{FullName} key:{KeyType} 类型不合法");
+ }
+
+ if ((ValueTType = (TBean)ass.CreateType(Namespace, ValueType)) == null)
+ {
+ throw new Exception($"table:{FullName} value:{ValueType} 类型不合法");
+ }
+ }
+ }
+}
diff --git a/src/Luban.Job.Db/Source/Generate/CsRender.cs b/src/Luban.Job.Db/Source/Generate/CsRender.cs
new file mode 100644
index 0000000..29a390d
--- /dev/null
+++ b/src/Luban.Job.Db/Source/Generate/CsRender.cs
@@ -0,0 +1,357 @@
+using Luban.Job.Common.Defs;
+using Luban.Job.Common.Utils;
+using Luban.Job.Db.Defs;
+using Scriban;
+using System;
+using System.Collections.Generic;
+
+namespace Luban.Job.Db.Generate
+{
+ class CsRender
+ {
+ public string RenderAny(object o)
+ {
+ switch (o)
+ {
+ case DefConst c: return Render(c);
+ case DefEnum e: return Render(e);
+ case DefBean b: return Render(b);
+ case DefTable p: return Render(p);
+ default: throw new Exception($"unknown render type:{o}");
+ }
+ }
+
+ public string Render(DefConst c)
+ {
+ return RenderUtil.RenderCsConstClass(c);
+ }
+
+ public string Render(DefEnum e)
+ {
+ return RenderUtil.RenderCsEnumClass(e);
+ }
+
+ [ThreadStatic]
+ private static Template t_beanRender;
+ public string Render(DefBean b)
+ {
+ var template = t_beanRender ??= Template.Parse(@"
+using Bright.Serialization;
+
+namespace {{namespace_with_top_module}}
+{
+
+{{if !is_value_type}}
+public {{cs_class_modifier}} class {{name}} : {{if parent_def_type}} {{parent}} {{else}} Bright.Transaction.BeanBase {{end}}
+{
+ {{- for field in fields }}
+ {{if is_abstract_type}}protected{{else}}private{{end}} {{field.ctype.db_cs_define_type}} {{field.internal_name}};
+ {{-end}}
+
+ public {{name}}()
+ {
+ {{- for field in fields }}
+ {{if field.ctype.need_init}}{{field.db_cs_init_field}} {{end}}
+ {{end}}
+ }
+
+ {{- for field in fields }}
+ {{if field.ctype.has_setter}}
+
+ private sealed class {{field.log_type}} : Bright.Transaction.FieldLogger<{{name}}, {{field.ctype.db_cs_define_type}}>
+ {
+ public {{field.log_type}}({{name}} self, {{field.ctype.db_cs_define_type}} value) : base(self, value) { }
+
+ public override long FieldId => host._objectId_ + {{field.id}};
+
+ public override void Commit() { this.host.{{field.internal_name}} = this.Value; }
+
+
+ public override void WriteBlob(ByteBuf _buf)
+ {
+ _buf.WriteInt(FieldTag.{{field.ctype.tag_name}});
+ {{field.db_write_blob}}
+ }
+ }
+
+ public {{field.ctype.db_cs_define_type}} {{field.public_name}}
+ {
+ get
+ {
+ if (this.InitedObjectId)
+ {
+ var txn = Bright.Transaction.TransactionContext.ThreadStaticTxn;
+ if (txn == null) return {{field.internal_name}};
+ var log = ({{field.log_type}})txn.GetField(_objectId_ + {{field.id}});
+ return log != null ? log.Value : {{field.internal_name}};
+ }
+ else
+ {
+ return {{field.internal_name}};
+ }
+ }
+ set
+ {
+ {{if db_field_cannot_null}}if (value == null) throw new ArgumentNullException();{{end}}
+ if (this.InitedObjectId)
+ {
+ var txn = Bright.Transaction.TransactionContext.ThreadStaticTxn;
+ txn.PutField(_objectId_ + {{field.id}}, new {{field.log_type}}(this, value));
+ {{-if field.ctype.need_set_children_root}}
+ value?.InitRoot(GetRoot());
+ {{end}}
+ }
+ else
+ {
+ {{field.internal_name}} = value;
+ }
+ }
+ }
+ {{else}}
+
+ {{if field.ctype.is_collection}}
+
+ private class {{field.log_type}} : {{field.ctype.db_cs_define_type}}.Log
+ {
+ private readonly {{name}} host;
+ public {{field.log_type}}({{name}} host, {{field.ctype.immutable_type}} value) : base(value) { this.host = host; }
+
+ public override long FieldId => host._objectId_ + {{field.id}};
+
+ public override Bright.Transaction.BeanBase Host => host;
+
+ public override void Commit()
+ {
+ Commit(host.{{field.internal_name}});
+ }
+
+ public override void WriteBlob(ByteBuf _buf)
+ {
+ _buf.WriteInt(FieldTag.{{field.ctype.tag_name}});
+ {{field.db_write_blob}}
+ }
+ }
+ {{end}}
+
+ public {{field.ctype.db_cs_define_type}} {{field.public_name}} => {{field.internal_name}};
+ {{end}}
+ {{-end}}
+
+ {{if is_abstract_type}}
+ public static void Serialize{{name}}(ByteBuf _buf, {{name}} x)
+ {
+ if (x == null) { _buf.WriteInt(0); return; }
+ _buf.WriteInt(x.GetTypeId());
+ x.Serialize(_buf);
+ }
+
+ public static {{name}} Deserialize{{name}}(ByteBuf _buf)
+ {
+ {{name}} x;
+ switch (_buf.ReadInt())
+ {
+ case 0 : return null;
+ {{- for child in hierarchy_not_abstract_children}}
+ case {{child.full_name}}.ID: x = new {{child.full_name}}(); break;
+ {{-end}}
+ default: throw new SerializationException();
+ }
+ x.Deserialize(_buf);
+ return x;
+ }
+ {{else}}
+ public override void Serialize(ByteBuf _buf)
+ {
+ _buf.WriteLong(_objectId_);
+ {{- for field in hierarchy_fields }}
+ { _buf.WriteInt(FieldTag.{{field.ctype.tag_name}} | ({{field.id}} << FieldTag.TAG_SHIFT)); {{field.db_serialize_compatible}} }
+ {{-end}}
+ }
+
+ public override void Deserialize(ByteBuf _buf)
+ {
+ _objectId_ = _buf.ReadLong();
+ while(_buf.NotEmpty)
+ {
+ int _tag_ = _buf.ReadInt();
+ switch (_tag_)
+ {
+ {{- for field in hierarchy_fields }}
+ case FieldTag.{{field.ctype.tag_name}} | ({{field.id}} << FieldTag.TAG_SHIFT) : { {{field.db_deserialize_compatible}} break; }
+ {{-end}}
+ default: { _buf.SkipUnknownField(_tag_); break; }
+ }
+ }
+ }
+
+ public const int ID = {{id}};
+ public override int GetTypeId() => ID;
+
+ {{end}}
+
+ protected override void InitChildrenRoot(Bright.Transaction.TKey root)
+ {
+ {{- for field in hierarchy_fields }}
+ {{if field.ctype.need_set_children_root}}this.{{field.internal_name}}?.InitRoot(root);{{end}}
+ {{-end}}
+ }
+
+ public override string ToString()
+ {
+ return ""{{full_name}}{ ""
+ {{- for field in hierarchy_fields }}
+ + ""{{field.public_name}}:"" + {{field.db_cs_to_string}} + "",""
+ {{-end}}
+ + ""}"";
+ }
+}
+
+{{else}}
+ public struct {{name}} : ISerializable
+{
+ {{- for field in fields }}
+ private {{field.ctype.db_cs_define_type}} {{field.internal_name}};
+ {{-end}}
+
+ {{- for field in fields }}
+ public {{field.ctype.db_cs_define_type}} {{field.public_name}} {get => {{field.internal_name}}; set => {{field.internal_name}} = value;}
+ {{-end}}
+
+ public void Serialize(ByteBuf _buf)
+ {
+ _buf.WriteSize({{hierarchy_fields.size}});
+ {{- for field in hierarchy_fields }}
+ { _buf.WriteInt(FieldTag.{{field.ctype.tag_name}} | ({{field.id}} << FieldTag.TAG_SHIFT)); {{field.db_serialize_compatible}} }
+ {{-end}}
+ }
+
+ public void Deserialize(ByteBuf _buf)
+ {
+ for (int _var_num_ = _buf.ReadSize(); -- _var_num_ >= 0;)
+ {
+ int _tag_ = _buf.ReadInt();
+ switch (_tag_)
+ {
+ {{- for field in hierarchy_fields }}
+ case FieldTag.{{field.ctype.tag_name}} | ({{field.id}} << FieldTag.TAG_SHIFT) : { {{field.db_deserialize_compatible}} break; }
+ {{-end}}
+ default: { _buf.SkipUnknownField(_tag_); break; }
+ }
+ }
+ }
+
+ public int GetTypeId() => 0;
+
+ public override string ToString()
+ {
+ return ""{{full_name}}{ ""
+ {{- for field in hierarchy_fields }}
+ + ""{{field.public_name}}:"" + {{field.db_cs_to_string}} + "",""
+ {{-end}}
+ + ""}"";
+ }
+}
+
+{{end}}
+
+}
+");
+ var result = template.Render(b);
+ return result;
+ }
+
+ [ThreadStatic]
+ private static Template t_tableRender;
+ public string Render(DefTable p)
+ {
+ var template = t_tableRender ??= Template.Parse(@"
+using System;
+using System.Threading.Tasks;
+
+namespace {{namespace_with_top_module}}
+{
+
+public sealed class {{name}}
+{
+ public static {{base_table_type}} Table { get; } = new {{internal_table_type}}({{table_uid}});
+
+ private class {{internal_table_type}} : {{base_table_type}}
+ {
+ public {{internal_table_type}}(int tableId) : base(tableId)
+ {
+
+ }
+ };
+
+ public static {{value_ttype.cs_define_type}} Get({{key_ttype.cs_define_type}} key)
+ {
+ return Table.Get(key);
+ }
+
+ public static {{value_ttype.cs_define_type}} CreateIfNotExist({{key_ttype.cs_define_type}} key)
+ {
+ return Table.CreateIfNotExist(key);
+ }
+
+ public static void Insert({{key_ttype.cs_define_type}} key, {{value_ttype.cs_define_type}} value)
+ {
+ Table.Insert(key, value);
+ }
+
+ public static void Remove({{key_ttype.cs_define_type}} key)
+ {
+ Table.Remove(key);
+ }
+
+ public static void Put({{key_ttype.cs_define_type}} key, {{value_ttype.cs_define_type}} value)
+ {
+ Table.Put(key, value);
+ }
+
+ public static {{value_ttype.cs_define_type}} Select({{key_ttype.cs_define_type}} key)
+ {
+ return Table.Select(key);
+ }
+}
+}
+
+");
+ var result = template.Render(p);
+
+ return result;
+ }
+
+ [ThreadStatic]
+ private static Template t_stubRender;
+ public string RenderTables(string name, string module, List tables)
+ {
+ var template = t_stubRender ??= Template.Parse(@"
+using Bright.Serialization;
+
+namespace {{namespace}}
+{
+
+public static class {{name}}
+{
+ public static System.Collections.Generic.List TableList { get; } = new System.Collections.Generic.List
+ {
+ {{- for table in tables }}
+ {{table.full_name}}.Table,
+ {{-end}}
+ };
+}
+
+}
+
+");
+ var result = template.Render(new
+ {
+ Name = name,
+ Namespace = module,
+ Tables = tables,
+ });
+
+ return result;
+ }
+ }
+}
diff --git a/src/Luban.Job.Db/Source/JobController.cs b/src/Luban.Job.Db/Source/JobController.cs
new file mode 100644
index 0000000..71c29f9
--- /dev/null
+++ b/src/Luban.Job.Db/Source/JobController.cs
@@ -0,0 +1,18 @@
+using Luban.Common.Protos;
+using Luban.Server.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Luban.Job.Db
+{
+ public class JobController : IJobController
+ {
+ public Task GenAsync(RemoteAgent agent, GenJob rpc)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Luban.Job.Db/Source/Program.cs b/src/Luban.Job.Db/Source/Program.cs
new file mode 100644
index 0000000..27f0d46
--- /dev/null
+++ b/src/Luban.Job.Db/Source/Program.cs
@@ -0,0 +1,119 @@
+//using Bright.Common;
+//using CommandLine;
+//using CommandLine.Text;
+//using Gen.Client.Common.Net;
+//using Gen.Client.Common.Utils;
+//using Gen.Db.Common.RawDefs;
+//using Luban.Job.Common.Net;
+//using Luban.Job.Common.Utils;
+//using System;
+
+//namespace Luban.Job.Db.Client
+//{
+// public class CommandLineOptions
+// {
+// [Option('h', "host", Required = true, HelpText = "gen server host")]
+// public string Host { get; set; }
+
+// [Option('p', "port", Required = false, HelpText = "gen server port")]
+// public int Port { get; set; } = 8899;
+
+// [Option('d', "define", Required = true, HelpText = "define file")]
+// public string DefineFile { get; set; }
+
+// [Option('c', "outputcodedir", Required = true, HelpText = "output code directory")]
+// public string OutputCodeDir { get; set; }
+
+// [Option('l', "language", Required = true, HelpText = "code language. only support cs currently")]
+// public string Languange { get; set; } = "cs";
+
+// [Option('v', "verbose", Required = false, HelpText = "verbose output")]
+// public bool Verbose { get; set; }
+
+// [Option("cachemetainfofile", Required = false, HelpText = "cache meta info file")]
+// public string CacheMetaInfoFile { get; set; } = ".cache.meta";
+// }
+
+// class Program
+// {
+// private static NLog.Logger s_logger;
+
+// private static CommandLineOptions _options;
+
+// static void Main(string[] args)
+// {
+// var parseResult = Parser.Default.ParseArguments(args);
+
+// parseResult.WithNotParsed(errs =>
+// {
+// Environment.Exit(1);
+// });
+
+// parseResult.WithParsed(opts =>
+// {
+// _options = opts;
+// });
+
+// LogUtil.InitSimpleNLogConfigure(NLog.LogLevel.Info);
+
+// s_logger = NLog.LogManager.GetCurrentClassLogger();
+
+// int exitCode = 0;
+// try
+// {
+// var timer = new ProfileTimer();
+// timer.StartPhase("total");
+
+// long beginTime = Bright.Time.TimeUtil.NowMillis;
+
+// timer.StartPhase("load cache meta file");
+// CacheMetaManager.Ins.Load(_options.CacheMetaInfoFile);
+// timer.EndPhaseAndLog();
+
+// RpcManager.Ins.Start();
+// var conn = GenClient.Ins.Start(_options.Host, _options.Port, ProtocolStub.Factories, _options.Verbose);
+// conn.Wait();
+
+// timer.StartPhase("load defines");
+// var loader = new DbDefLoader();
+// loader.Load(_options.DefineFile);
+// timer.EndPhaseAndLog();
+
+// timer.StartPhase("call GenDb");
+// string outputDir = _options.OutputCodeDir;
+
+// var rpc = new GenDb();
+// var res = rpc.Call(GenClient.Ins.Session, new GenDbArg()
+// {
+// Define = loader.BuildDefines(),
+// OutputCodeRelatePath = outputDir,
+
+// }).Result;
+// timer.EndPhaseAndLog();
+
+// if (res.OK)
+// {
+// timer.StartPhase("fetch generated files");
+// DownloadFileUtil.DownloadGeneratedFiles(outputDir, res.NewCodeFiles).Wait();
+// timer.EndPhaseAndLog();
+
+// CacheMetaManager.Ins.Save();
+// timer.EndPhaseAndLog();
+// s_logger.Info("==== run succ ====");
+// }
+// else
+// {
+// timer.EndPhaseAndLog();
+// s_logger.Error("==== run fail ====");
+// exitCode = 1;
+// }
+// }
+// catch (Exception e)
+// {
+// s_logger.Error(e, "==== run fail ====");
+// exitCode = 1;
+// }
+// Environment.Exit(exitCode);
+// }
+// }
+//}
diff --git a/src/Luban.Job.Db/Source/RawDefs/Defines.cs b/src/Luban.Job.Db/Source/RawDefs/Defines.cs
new file mode 100644
index 0000000..cb5b7d7
--- /dev/null
+++ b/src/Luban.Job.Db/Source/RawDefs/Defines.cs
@@ -0,0 +1,20 @@
+using Luban.Job.Common.RawDefs;
+using System.Collections.Generic;
+
+namespace Luban.Job.Db.RawDefs
+{
+ public class Defines
+ {
+ public string Language { get; set; } = "cs";
+
+ public string TopModule { get; set; } = "";
+
+ public List Beans { get; set; } = new List();
+
+ public List Consts { get; set; } = new List();
+
+ public List Enums { get; set; } = new List();
+
+ public List DbTables { get; set; } = new List();
+ }
+}
diff --git a/src/Luban.Job.Db/Source/RawDefs/Table.cs b/src/Luban.Job.Db/Source/RawDefs/Table.cs
new file mode 100644
index 0000000..681d164
--- /dev/null
+++ b/src/Luban.Job.Db/Source/RawDefs/Table.cs
@@ -0,0 +1,17 @@
+namespace Luban.Job.Db.RawDefs
+{
+ public class Table
+ {
+ public string Namespace { get; set; }
+
+ public string Name { get; set; }
+
+ public int Id { get; set; }
+
+ public string KeyType { get; set; }
+
+ public string ValueType { get; set; }
+
+ public bool IsPersistent { get; set; }
+ }
+}
diff --git a/src/Luban.Job.Db/Source/RpcController.cs b/src/Luban.Job.Db/Source/RpcController.cs
new file mode 100644
index 0000000..d2befb6
--- /dev/null
+++ b/src/Luban.Job.Db/Source/RpcController.cs
@@ -0,0 +1,623 @@
+namespace Luban.Job.Db
+{
+ class RpcController
+ {
+
+ //private void LogException(IContext ctx, Exception e)
+ //{
+ // if (e is AggregateException ae)
+ // {
+ // foreach (var ie in ae.InnerExceptions)
+ // {
+ // LogException(ctx, ie);
+ // }
+ // }
+ // else
+ // {
+
+ // s_logger.Error(e, "发生异常");
+ // ctx.Error(e, " {0} \n ", e.StackTrace);
+ // }
+ //}
+
+ //private bool ValidateDataType(string outputDataType)
+ //{
+ // switch (outputDataType)
+ // {
+ // case "bin":
+ // case "cbin":
+ // case "json": return true;
+ // default: return false;
+ // }
+ //}
+
+ //private void OnGenDb(Session session, GenDb proto)
+ //{
+ // var timer = new ProfileTimer();
+
+ // timer.StartPhase("生成代码");
+
+ // var res = new GenDbRes();
+
+ // string relatePath = proto.Arg.OutputCodeRelatePath;
+
+ // var ass = new DefAssembly();
+ // var ctx = new SessionContext(session, proto.Arg.Verbose);
+ // try
+ // {
+ // var genCodeTasks = new List();
+ // var outputFiles = new ConcurrentBag();
+
+ // ass.Load(EJobType.DB, proto.Arg.Define, ctx);
+ // var render = new Generate.Db.CsRender();
+ // foreach (var c in ass.Types.Values)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var module = ass.TopModule;
+ // var name = "Tables";
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTables(name, module, ass.Types.Values.Where(t => t is BTable).ToList()), "cs");
+ // var file = FileUtil.GetCsDefTypePath(name);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // Task.WhenAll(genCodeTasks).Wait();
+ // ctx.Info(timer.EndPhaseAndLogToString());
+
+ // res.NewCodeFiles = outputFiles.ToList();
+ // res.OK = true;
+ // }
+ // catch (Exception e)
+ // {
+ // res.OK = false;
+ // LogException(ctx, e);
+ // }
+
+ // proto.ReturnResult(session, res);
+ //}
+
+ //private ICsCodeRender CreateCsCodeRender(string outputDataType)
+ //{
+ // switch (outputDataType)
+ // {
+ // case "bin": return new AppCsBinCodeRender();
+ // case "cbin": return new AppCsCompatibleBinCodeRender();
+ // case "json": return new AppCsJsonCodeRender();
+ // default: throw new ArgumentException($"not support output data type:{outputDataType}");
+ // }
+ //}
+
+ //private void OnGenCfg(Session session, GenCfg proto)
+ //{
+ // var res = new GenCfgRes();
+
+ // string lan = proto.Arg.Define.Language;
+
+ // DefAssembly ass = new DefAssembly();
+
+ // var ctx = new SessionContext(session, proto.Arg.Verbose);
+
+
+ // var allJobs = new List();
+
+
+ // try
+ // {
+ // string outputDataType = proto.Arg.OutputDataType;
+ // if (!ValidateDataType(outputDataType))
+ // {
+ // throw new ArgumentException($"unknown outputdatatype:{outputDataType}");
+ // }
+
+ // bool exportTestData = proto.Arg.ExportTestData;
+
+ // long genStartTime = TimeUtil.NowMillis;
+ // var genCodeTasks = new List();
+ // var outputCodeFiles = new ConcurrentBag();
+
+ // ass.Load(EJobType.CONFIG, proto.Arg.Define, ctx);
+ // EGenTypes genTypes = proto.Arg.GenTypes;
+ // var targetService = ass.CfgTargetService;
+
+ // List exportTables = ass.Types.Values.Where(t => t is CTable ct && ct.NeedExport).Select(t => (CTable)t).ToList();
+
+ // if (genTypes.HasFlag(EGenTypes.APP_CODE))
+ // {
+ // var refTypes = new Dictionary();
+ // long genCodeStartTime = TimeUtil.NowMillis;
+
+ // foreach (var refType in targetService.Refs)
+ // {
+ // if (!ass.Types.ContainsKey(refType))
+ // {
+ // throw new Exception($"service:{targetService.Name} ref:{refType} 类型不存在");
+ // }
+ // if (!refTypes.TryAdd(refType, ass.Types[refType]))
+ // {
+ // throw new Exception($"service:{targetService.Name} ref:{refType} 重复引用");
+ // }
+ // }
+
+ // foreach (var table in exportTables)
+ // {
+ // refTypes[table.FullName] = table;
+ // table.ValueTType.Apply(RefTypeVisitor.Ins, refTypes);
+ // }
+
+ // foreach (var type in ass.Types)
+ // {
+ // if (type.Value is DefConst || type.Value is DefEnum)
+ // {
+ // refTypes[type.Key] = type.Value;
+ // }
+ // }
+
+ // List exportTypes = refTypes.Values.ToList();
+
+ // switch (lan)
+ // {
+ // case "cs":
+ // {
+ // ICsCodeRender render = CreateCsCodeRender(outputDataType);
+ // foreach (var c in exportTypes)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+
+
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var module = ass.TopModule;
+ // var name = targetService.Manager;
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderService(name, module, exportTables), "cs");
+ // var file = FileUtil.GetCsDefTypePath(name);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+
+ // break;
+ // }
+ // case "go":
+ // {
+ // //
+ // // TODO?
+ // // 由于 go 语言不支持类型继承
+ // // go 不支持 table.value_type 为多态的表
+ // //
+ // //
+ // var render = new AppGoCodeRender();
+
+
+ // foreach (var c in exportTypes)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "go");
+ // var file = FileUtil.GetGoDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var module = ass.TopModule;
+ // var name = targetService.Manager;
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderService(name, module, exportTables), "go");
+ // var file = FileUtil.GetGoDefTypePath(name);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+
+ // break;
+ // }
+ // case "lua":
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var render = new Generate.Cfg.LuaRender();
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAll(exportTypes.ToList()), "lua");
+ // var file = "CfgTypes.lua";
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // break;
+ // }
+ // case "editor_cs":
+ // {
+ // var render = new EditorCsRender();
+ // foreach (var c in ass.Types.Values)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // break;
+ // }
+ // case "editor_cpp":
+ // {
+ // var render = new EditorCppRender();
+ // foreach (var c in ass.Types.Values)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // break;
+ // }
+ // case "editor_ue_cpp":
+ // {
+ // var render = new UE4EditorCppRender();
+
+ // var renderTypes = ass.Types.Values.Where(c => c is DefEnum || c is DefBean).ToList();
+
+ // foreach (var c in renderTypes)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp");
+ // var file = c.UeEditorHeaderFileName;
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+
+ // int TYPE_PER_STUB_FILE = 200;
+
+ // for (int i = 0, n = (renderTypes.Count + TYPE_PER_STUB_FILE - 1) / TYPE_PER_STUB_FILE; i < n; i++)
+ // {
+ // int index = i;
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // int startIndex = index * TYPE_PER_STUB_FILE;
+ // var content = RenderUtils.ConcatAutoGenerationHeader(
+ // render.RenderStub(renderTypes.GetRange(startIndex, Math.Min(TYPE_PER_STUB_FILE, renderTypes.Count - startIndex))),
+ // "cpp");
+ // var file = $"Stub_{index}.cpp";
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // break;
+ // }
+ // case "ue_bp_cpp":
+ // {
+ // var render = new UE4BpCppRender();
+ // foreach (var c in exportTypes)
+ // {
+ // if (c is DefConst || c is CTable)
+ // {
+ // continue;
+ // }
+
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp");
+ // var file = c.UeBpHeaderFileName;
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+
+ // //{
+ // // var module = ass.TopModule;
+ // // var name = targetService.Manager;
+ // // var content = render.RenderService(name, module, exportTables);
+ // // var file = FileUtil.GetCppDefTypeCppFilePath(name);
+ // // var md5 = GenMd5AndAddCache(file, content);
+ // // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // //}
+ // break;
+ // }
+ // default:
+ // {
+ // throw new Exception($"unknown language:{lan}");
+ // }
+ // }
+
+
+ // allJobs.Add(Task.Run(async () =>
+ // {
+ // await Task.WhenAll(genCodeTasks);
+ // res.NewAppCodeFiles = outputCodeFiles.ToList();
+ // long genCodeEndTime = TimeUtil.NowMillis;
+ // ctx.Info("====== 生成代码 总共耗时 {0} ms ======", (genCodeEndTime - genCodeStartTime));
+ // }));
+ // }
+
+ // if ((genTypes & (EGenTypes.APP_DATA | EGenTypes.APP_RESOURCE_LIST)) != 0)
+ // {
+ // var genDataTasks = new List();
+ // var outputDataFiles = new ConcurrentBag();
+ // var render = new AppBinaryDataRender();
+ // long genDataStartTime = TimeUtil.NowMillis;
+
+ // foreach (CTable c in exportTables)
+ // {
+ // genDataTasks.Add(Task.Run(async () =>
+ // {
+ // long beginTime = TimeUtil.NowMillis;
+ // await c.Load(session, exportTestData);
+ // long endTime = TimeUtil.NowMillis;
+ // if (endTime - beginTime > 100)
+ // {
+ // ctx.Info("====== 配置表 {0} 加载耗时 {1} ms ======", c.FullName, (endTime - beginTime));
+ // }
+ // }));
+ // }
+ // Task.WaitAll(genDataTasks.ToArray());
+ // }
+
+
+ // if (genTypes.HasFlag(EGenTypes.APP_DATA))
+ // {
+ // var genDataTasks = new List();
+ // var outputDataFiles = new ConcurrentBag();
+ // var render = new AppBinaryDataRender();
+ // long genDataStartTime = TimeUtil.NowMillis;
+
+ // foreach (CTable c in exportTables)
+ // {
+ // genDataTasks.Add(Task.Run(() =>
+ // {
+ // var content = c.ToOutputData(outputDataType);
+ // var file = c.OutputDataFile;
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputDataFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+
+ // allJobs.Add(Task.Run(async () =>
+ // {
+ // await Task.WhenAll(genDataTasks);
+ // long genDataEndTime = TimeUtil.NowMillis;
+ // ctx.Info("====== 生成配置数据 总共耗时 {0} ms ======", (genDataEndTime - genDataStartTime));
+ // res.NewAppDataFiles = outputDataFiles.ToList();
+
+ // long verifyStartTime = TimeUtil.NowMillis;
+ // render.VerifyTables(exportTables);
+ // res.PathQueries = ass.GetPathQueries();
+
+ // long verifyEndTime = TimeUtil.NowMillis;
+ // ctx.Info("====== 校验配置 总共耗时 {0} ms ======", (verifyEndTime - verifyStartTime));
+ // }));
+ // }
+
+ // if (genTypes.HasFlag(EGenTypes.APP_RESOURCE_LIST))
+ // {
+ // var genDataTasks = new List>>();
+ // var render = new AppBinaryDataRender();
+ // long genDataStartTime = TimeUtil.NowMillis;
+
+ // foreach (CTable c in exportTables)
+ // {
+ // genDataTasks.Add(Task.Run(() =>
+ // {
+ // return c.ExportResourceList();
+ // }));
+ // }
+
+ // allJobs.Add(Task.Run(async () =>
+ // {
+ // var ress = new HashSet<(string, string)>(10000);
+ // foreach (var task in genDataTasks)
+ // {
+ // foreach (var ri in await task)
+ // {
+ // if (ress.Add((ri.Resource, ri.Tag)))
+ // {
+ // res.ResourceList.Add(ri);
+ // }
+ // }
+ // }
+ // long genDataEndTime = TimeUtil.NowMillis;
+ // ctx.Info("====== 生成导出资源列表 总共耗时 {0} ms ======", (genDataEndTime - genDataStartTime));
+ // }));
+ // }
+
+ // Task.WhenAll(allJobs).Wait();
+
+ // long genEndTime = TimeUtil.NowMillis;
+ // ctx.Info("======== 服务器端 总共耗时 {0} ms =======", (genEndTime - genStartTime));
+
+ // res.OK = true;
+ // }
+ // catch (Exception e)
+ // {
+ // res.OK = false;
+ // LogException(ctx, e);
+ // }
+
+ // proto.ReturnResult(session, res);
+ //}
+
+ //private void OnGenProto(Session session, GenProto proto)
+ //{
+ // var timer = new ProfileTimer();
+
+ // timer.StartPhase("服务器生成代码");
+
+ // var res = new GenProtoRes();
+
+ // string relatePath = proto.Arg.OutputCodeRelatePath;
+
+ // DefAssembly ass = new DefAssembly();
+ // var ctx = new SessionContext(session, proto.Arg.Verbose);
+ // try
+ // {
+ // var genCodeTasks = new List();
+ // var outputFiles = new ConcurrentBag();
+
+ // ass.Load(EJobType.PROTO, proto.Arg.Define, ctx);
+ // var outputSyncFiles = new ConcurrentBag();
+
+ // switch (proto.Arg.Define.Language)
+ // {
+ // case "cs":
+ // {
+ // var render = new CsRender();
+ // foreach (var c in ass.Types.Values)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var module = ass.TopModule;
+ // var name = "ProtocolStub";
+ // var content = RenderUtils.ConcatAutoGenerationHeader(
+ // render.RenderStubs(name, module,
+ // ass.Types.Values.Where(t => t is PProto).ToList(),
+ // ass.Types.Values.Where(t => t is PRpc).ToList()),
+ // "cs");
+ // var file = FileUtil.GetCsDefTypePath(name);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // break;
+ // }
+ // case "lua":
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var render = new Generate.Proto.LuaRender();
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTypes(ass.Types.Values.ToList()), "lua");
+ // var file = "ProtoTypes.lua";
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // break;
+ // }
+ // default:
+ // {
+ // throw new Exception($"unknown lan:{proto.Arg.Define.Language}");
+ // }
+ // }
+
+ // Task.WhenAll(genCodeTasks).Wait();
+ // res.NewCodeFiles = outputFiles.ToList();
+
+ // ctx.Info(timer.EndPhaseAndLogToString());
+
+ // res.OK = true;
+ // }
+ // catch (Exception e)
+ // {
+ // res.OK = false;
+ // LogException(ctx, e);
+ // }
+
+ // proto.ReturnResult(session, res);
+ //}
+
+ //private void OnGenRep(Session session, GenRep proto)
+ //{
+ // var timer = new ProfileTimer();
+
+ // timer.StartPhase("服务器生成代码");
+
+ // var res = new GenRepRes();
+
+ // string relatePath = proto.Arg.OutputCodeRelatePath;
+
+ // DefAssembly ass = new DefAssembly();
+ // var ctx = new SessionContext(session, proto.Arg.Verbose);
+ // try
+ // {
+ // var genCodeTasks = new List();
+ // var outputFiles = new ConcurrentBag();
+
+ // ass.Load(EJobType.REP, proto.Arg.Define, ctx);
+ // var outputSyncFiles = new ConcurrentBag();
+
+ // switch (proto.Arg.Define.Language)
+ // {
+ // case "cs":
+ // {
+ // var render = new Generate.Rep.CsRender();
+ // foreach (var c in ass.Types.Values)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var module = ass.TopModule;
+ // var name = "RepStub";
+ // var content = RenderUtils.ConcatAutoGenerationHeader(
+ // render.RenderStubs(name, module, ass.Types.Values.Where(t => (t is DefActor) || (t is DefComponent)).ToList()),
+ // "cs");
+ // var file = FileUtil.GetCsDefTypePath(name);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // break;
+ // }
+ // case "lua":
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var render = new Generate.Rep.LuaRender();
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTypes(ass.Types.Values.ToList()), "lua");
+ // var file = "RepTypes.lua";
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // break;
+ // }
+ // default:
+ // {
+ // throw new Exception($"unknown lan:{proto.Arg.Define.Language}");
+ // }
+ // }
+
+ // Task.WhenAll(genCodeTasks).Wait();
+ // res.NewCodeFiles = outputFiles.ToList();
+
+ // ctx.Info(timer.EndPhaseAndLogToString());
+
+ // res.OK = true;
+ // }
+ // catch (Exception e)
+ // {
+ // res.OK = false;
+ // LogException(ctx, e);
+ // }
+
+ // proto.ReturnResult(session, res);
+ //}
+ }
+}
diff --git a/src/Luban.Job.Db/Source/TTypeExtensions.cs b/src/Luban.Job.Db/Source/TTypeExtensions.cs
new file mode 100644
index 0000000..d0a982e
--- /dev/null
+++ b/src/Luban.Job.Db/Source/TTypeExtensions.cs
@@ -0,0 +1,18 @@
+using Luban.Job.Common.Types;
+using System;
+
+namespace Luban.Job.Db
+{
+ static class TTypeExtensions
+ {
+ public static string DbCsDefineType(this TType type)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static bool NeedSetChildrenRoot(this TType type)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Luban.Job.Db/Source/TypeVisitors/DbCsInitFieldVisitor.cs b/src/Luban.Job.Db/Source/TypeVisitors/DbCsInitFieldVisitor.cs
new file mode 100644
index 0000000..7f1e9b5
--- /dev/null
+++ b/src/Luban.Job.Db/Source/TypeVisitors/DbCsInitFieldVisitor.cs
@@ -0,0 +1,133 @@
+using Luban.Job.Common.Types;
+using Luban.Job.Common.TypeVisitors;
+using System;
+
+namespace Luban.Job.Db.TypeVisitors
+{
+ class DbCsInitFieldVisitor : ITypeFuncVisitor
+ {
+ public static DbCsInitFieldVisitor Ins { get; } = new DbCsInitFieldVisitor();
+
+ public string Accept(TBool type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TByte type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TShort type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TFshort type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TInt type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TFint type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TLong type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TFlong type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TFloat type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TDouble type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TEnum type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TString type, string fieldName, string logType)
+ {
+ return $"{fieldName} = \"\";";
+ }
+
+ public string Accept(TBytes type, string fieldName, string logType)
+ {
+ return $"{fieldName} = System.Array.Empty();";
+ }
+
+ public string Accept(TText type, string fieldName, string logType)
+ {
+ throw new NotSupportedException();
+ }
+
+ public string Accept(TBean type, string fieldName, string logType)
+ {
+ if (type.Bean.IsAbstractType)
+ {
+ return $"{fieldName} = default;";
+ }
+ else
+ {
+ return $"{fieldName} = new {type.DbCsDefineType()}();";
+ }
+ }
+
+ public string Accept(TArray type, string fieldName, string logType)
+ {
+ throw new NotSupportedException();
+ }
+
+ public string Accept(TList type, string fieldName, string logType)
+ {
+ return $"{fieldName} = new {type.DbCsDefineType()}(_v => new {logType}(this, _v));";
+ }
+
+ public string Accept(TSet type, string fieldName, string logType)
+ {
+ return $"{fieldName} = new {type.DbCsDefineType()}(_v => new {logType}(this, _v));";
+ }
+
+ public string Accept(TMap type, string fieldName, string logType)
+ {
+ return $"{fieldName} = new {type.DbCsDefineType()}(_v => new {logType}(this, _v));";
+ }
+
+ public string Accept(TVector2 type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TVector3 type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TVector4 type, string fieldName, string logType)
+ {
+ return $"{fieldName} = default;";
+ }
+
+ public string Accept(TDateTime type, string x, string y)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/src/Luban.Job.Db/Source/TypeVisitors/DbWriteBlob.cs b/src/Luban.Job.Db/Source/TypeVisitors/DbWriteBlob.cs
new file mode 100644
index 0000000..eda6716
--- /dev/null
+++ b/src/Luban.Job.Db/Source/TypeVisitors/DbWriteBlob.cs
@@ -0,0 +1,136 @@
+using Luban.Job.Common.Types;
+using Luban.Job.Common.TypeVisitors;
+using System;
+
+namespace Luban.Job.Db.TypeVisitors
+{
+ class DbWriteBlob : ITypeFuncVisitor
+ {
+ public static DbWriteBlob Ins { get; } = new DbWriteBlob();
+
+ public string Accept(TBool type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteBool({fieldName});";
+ }
+
+ public string Accept(TByte type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteByte({fieldName});";
+ }
+
+ public string Accept(TShort type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteShort({fieldName});";
+ }
+
+ public string Accept(TFshort type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteFshort({fieldName});";
+ }
+
+ public string Accept(TInt type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteInt({fieldName});";
+ }
+
+ public string Accept(TFint type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteFint({fieldName});";
+ }
+
+ public string Accept(TLong type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteLong({fieldName});";
+ }
+
+ public string Accept(TFlong type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteFlong({fieldName});";
+ }
+
+ public string Accept(TFloat type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteFloat({fieldName});";
+ }
+
+ public string Accept(TDouble type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteDouble({fieldName});";
+ }
+
+ public string Accept(TEnum type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteInt((int){fieldName});";
+ }
+
+ public string Accept(TString type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteString({fieldName});";
+ }
+
+ public string Accept(TBytes type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteBytes({fieldName});";
+ }
+
+ public string Accept(TText type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteString({fieldName});";
+ }
+
+ public string Accept(TBean type, string byteBufName, string fieldName)
+ {
+ var bean = type.Bean;
+ if (bean.IsNotAbstractType)
+ {
+
+ return $"{fieldName}.Serialize({byteBufName});";
+ }
+ else
+ {
+ return $"{bean.FullName}.Serialize{bean.Name}({byteBufName}, {fieldName});";
+ }
+ }
+
+ public string Accept(TArray type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteSize({fieldName}.Length); foreach(var _e in {fieldName}) {{ {type.ElementType.Apply(this, byteBufName, "_e")} }}";
+ }
+
+ public string Accept(TList type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteSize({fieldName}.Count); foreach(var _e in {fieldName}) {{ {type.ElementType.Apply(this, byteBufName, "_e")} }}";
+ }
+
+ public string Accept(TSet type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteSize({fieldName}.Count); foreach(var _e in {fieldName}) {{ {type.ElementType.Apply(this, byteBufName, "_e")} }}";
+ }
+
+ public string Accept(TMap type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteSize({fieldName}.Count); foreach(var _e in {fieldName}) {{ {type.KeyType.Apply(this, byteBufName, "_e.Key")} {type.ValueType.Apply(this, byteBufName, "_e.Value")}}}";
+
+ }
+
+ public string Accept(TVector2 type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteVector2({fieldName});";
+ }
+
+ public string Accept(TVector3 type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteVector3({fieldName});";
+ }
+
+ public string Accept(TVector4 type, string byteBufName, string fieldName)
+ {
+ return $"{byteBufName}.WriteVector4({fieldName});";
+ }
+
+ public string Accept(TDateTime type, string x, string y)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Luban.Job.Db/Source/TypeVisitors/ImmutableTypeName.cs b/src/Luban.Job.Db/Source/TypeVisitors/ImmutableTypeName.cs
new file mode 100644
index 0000000..144ccb6
--- /dev/null
+++ b/src/Luban.Job.Db/Source/TypeVisitors/ImmutableTypeName.cs
@@ -0,0 +1,125 @@
+using Luban.Job.Common.Types;
+using Luban.Job.Common.TypeVisitors;
+
+namespace Luban.Job.Db.TypeVisitors
+{
+ class ImmutableTypeName : ITypeFuncVisitor
+ {
+ public static ImmutableTypeName Ins { get; } = new ImmutableTypeName();
+
+ public string Accept(TBool type)
+ {
+ return "";
+ }
+
+ public string Accept(TByte type)
+ {
+ return "";
+ }
+
+ public string Accept(TShort type)
+ {
+ return "";
+ }
+
+ public string Accept(TFshort type)
+ {
+ return "";
+ }
+
+ public string Accept(TInt type)
+ {
+ return "";
+ }
+
+ public string Accept(TFint type)
+ {
+ return "";
+ }
+
+ public string Accept(TLong type)
+ {
+ return "";
+ }
+
+ public string Accept(TFlong type)
+ {
+ return "";
+ }
+
+ public string Accept(TFloat type)
+ {
+ return "";
+ }
+
+ public string Accept(TDouble type)
+ {
+ return "";
+ }
+
+ public string Accept(TEnum type)
+ {
+ return "";
+ }
+
+ public string Accept(TString type)
+ {
+ return "";
+ }
+
+ public string Accept(TBytes type)
+ {
+ return "";
+ }
+
+ public string Accept(TText type)
+ {
+ return "";
+ }
+
+ public string Accept(TBean type)
+ {
+ return "";
+ }
+
+ public string Accept(TArray type)
+ {
+ return "";
+ }
+
+ public string Accept(TList type)
+ {
+ return $"System.Collections.Immutable.ImmutableList<{type.ElementType.DbCsDefineType()}>";
+ }
+
+ public string Accept(TSet type)
+ {
+ return $"System.Collections.Immutable.ImmutableHashSet<{type.ElementType.DbCsDefineType()}>";
+ }
+
+ public string Accept(TMap type)
+ {
+ return $"System.Collections.Immutable.ImmutableDictionary<{type.KeyType.DbCsDefineType()}, {type.ValueType.DbCsDefineType()}>";
+ }
+
+ public string Accept(TVector2 type)
+ {
+ return "";
+ }
+
+ public string Accept(TVector3 type)
+ {
+ return "";
+ }
+
+ public string Accept(TVector4 type)
+ {
+ return "";
+ }
+
+ public string Accept(TDateTime type)
+ {
+ return "";
+ }
+ }
+}
diff --git a/src/Luban.Job.Proto/Luban.Job.Proto.csproj b/src/Luban.Job.Proto/Luban.Job.Proto.csproj
new file mode 100644
index 0000000..c23729e
--- /dev/null
+++ b/src/Luban.Job.Proto/Luban.Job.Proto.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Library
+ net5.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Luban.Job.Proto/Source/Defs/DefAssembly.cs b/src/Luban.Job.Proto/Source/Defs/DefAssembly.cs
new file mode 100644
index 0000000..9c161f9
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/Defs/DefAssembly.cs
@@ -0,0 +1,111 @@
+using Luban.Job.Common.Defs;
+using Luban.Job.Proto.RawDefs;
+using Luban.Server.Common;
+using System;
+using System.Collections.Generic;
+
+namespace Luban.Job.Proto.Defs
+{
+
+ class DefAssembly : DefAssemblyBase
+ {
+ private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
+
+ private readonly Dictionary id2Protos = new Dictionary();
+
+ public DefTypeBase GetProto(int id)
+ {
+ return id2Protos.TryGetValue(id, out var p) ? p : null;
+ }
+
+ public void AddProto(DefTypeBase proto)
+ {
+ if (!id2Protos.TryAdd(proto.Id, proto))
+ {
+ throw new Exception($"proto:{proto.FullName} id:{proto.Id} duplicated with {id2Protos[proto.Id].FullName}");
+ }
+ }
+
+
+ public void Load(Defines defines, RemoteAgent agent)
+ {
+ this.Agent = agent;
+ TopModule = defines.TopModule;
+
+ foreach (var c in defines.Consts)
+ {
+ AddType(new DefConst(c));
+ }
+
+ foreach (var e in defines.Enums)
+ {
+ AddType(new DefEnum(e));
+ }
+
+ foreach (var b in defines.Beans)
+ {
+ AddType(new DefBean(b));
+ }
+
+ foreach (var p in defines.Protos)
+ {
+ AddType(new DefProto(p));
+ }
+ foreach (var r in defines.Rpcs)
+ {
+ AddType(new DefRpc(r));
+ }
+
+ 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)
+ {
+ 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)
+ {
+ 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)
+ {
+ agent.Error("post compile type:{0} error", type.FullName);
+ s_logger.Error("post compile type:{0} error", type.FullName);
+ throw;
+ }
+ }
+
+ }
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/Defs/DefBean.cs b/src/Luban.Job.Proto/Source/Defs/DefBean.cs
new file mode 100644
index 0000000..a7fe8cb
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/Defs/DefBean.cs
@@ -0,0 +1,18 @@
+using Luban.Job.Common.Defs;
+using Luban.Job.Common.RawDefs;
+
+namespace Luban.Job.Proto.Defs
+{
+ class DefBean : DefBeanBase
+ {
+ public DefBean(Bean b) : base(b)
+ {
+
+ }
+
+ protected override DefFieldBase CreateField(Field f, int idOffset)
+ {
+ return new DefField(this, f, idOffset);
+ }
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/Defs/DefField.cs b/src/Luban.Job.Proto/Source/Defs/DefField.cs
new file mode 100644
index 0000000..fffc0de
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/Defs/DefField.cs
@@ -0,0 +1,15 @@
+using Luban.Job.Common.Defs;
+using Luban.Job.Common.RawDefs;
+
+namespace Luban.Job.Proto.Defs
+{
+ class DefField : DefFieldBase
+ {
+ public DefAssembly Assembly => (DefAssembly)HostType.AssemblyBase;
+
+ public DefField(DefTypeBase host, Field f, int idOffset) : base(host, f, idOffset)
+ {
+
+ }
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/Defs/DefProto.cs b/src/Luban.Job.Proto/Source/Defs/DefProto.cs
new file mode 100644
index 0000000..c9f24bc
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/Defs/DefProto.cs
@@ -0,0 +1,37 @@
+
+using Luban.Common.Utils;
+using Luban.Job.Common.Utils;
+using Luban.Job.Proto.RawDefs;
+using System.Collections.Generic;
+
+namespace Luban.Job.Proto.Defs
+{
+ class DefProto : ProtoDefTypeBase
+ {
+
+ public DefProto(PProto b)
+ {
+ Name = b.Name;
+ Namespace = b.Namespace;
+ Id = b.Id;
+
+ foreach (var field in b.Fields)
+ {
+ Fields.Add(new DefField(this, field, 0));
+ }
+ }
+
+ public List Fields { get; set; } = new List();
+
+ public override void Compile()
+ {
+ var pass = Assembly;
+ if (Id == 0)
+ {
+ Id = (int)TypeUtil.ComputProtoHashIdByName(FullName);
+ }
+ pass.AddProto(this);
+ DefField.CompileFields(this, Fields, false);
+ }
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/Defs/DefRpc.cs b/src/Luban.Job.Proto/Source/Defs/DefRpc.cs
new file mode 100644
index 0000000..d5d345f
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/Defs/DefRpc.cs
@@ -0,0 +1,50 @@
+using Luban.Job.Common.Utils;
+using Luban.Job.Common.Types;
+using System;
+using Luban.Job.Proto.RawDefs;
+using Luban.Common.Utils;
+
+namespace Luban.Job.Proto.Defs
+{
+ class DefRpc : ProtoDefTypeBase
+ {
+
+ public DefRpc(PRpc r)
+ {
+ Name = r.Name;
+ Namespace = r.Namespace;
+ Id = r.Id;
+ ArgType = r.ArgType;
+ ResType = r.ResType;
+ }
+
+ public string ArgType { get; set; }
+
+ public string ResType { get; set; }
+
+ public TType TArgType { get; private set; }
+
+ public TType TResType { get; private set; }
+
+
+ public override void Compile()
+ {
+ var pass = Assembly;
+ if (Id == 0)
+ {
+ Id = (int)TypeUtil.ComputProtoHashIdByName(FullName);
+ }
+ pass.AddProto(this);
+
+ if ((TArgType = Assembly.CreateType(Namespace, ArgType)) == null)
+ {
+ throw new Exception($"rpc name:{FullName} arg:{ArgType} is invalid");
+ }
+
+ if ((TResType = Assembly.CreateType(Namespace, ResType)) == null)
+ {
+ throw new Exception($"rpc name:{FullName} res:{ResType} is invalid");
+ }
+ }
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/Defs/ProtoDefLoader.cs b/src/Luban.Job.Proto/Source/Defs/ProtoDefLoader.cs
new file mode 100644
index 0000000..150f628
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/Defs/ProtoDefLoader.cs
@@ -0,0 +1,100 @@
+using Luban.Job.Common.Utils;
+using Luban.Job.Common.Defs;
+using Luban.Server.Common;
+using System;
+using System.Collections.Generic;
+using System.Xml.Linq;
+using Luban.Common.Utils;
+using Luban.Job.Proto.RawDefs;
+
+namespace Luban.Job.Proto.Defs
+{
+ class ProtoDefLoader : CommonDefLoader
+ {
+ private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger();
+
+ private readonly List _protos = new List();
+ private readonly List _rpcs = new List();
+
+ public ProtoDefLoader(RemoteAgent agent) : base(agent)
+ {
+ RegisterRootDefineHandler("service", AddService);
+ RegisterModuleDefineHandler("proto", AddProto);
+ RegisterModuleDefineHandler("rpc", AddRpc);
+ }
+
+ public Defines BuildDefines()
+ {
+ return new Defines();
+ }
+
+ private readonly List rpcAttrs = new List { "id" };
+ private readonly List rpcRequiredAttrs = new List { "name", "arg", "res" };
+ private void AddRpc(XElement e)
+ {
+ ValidAttrKeys(e, rpcAttrs, rpcRequiredAttrs);
+ var r = new PRpc()
+ {
+ Name = XmlUtil.GetRequiredAttribute(e, "name"),
+ Namespace = CurNamespace,
+ ArgType = XmlUtil.GetRequiredAttribute(e, "arg"),
+ ResType = XmlUtil.GetRequiredAttribute(e, "res"),
+ };
+ s_logger.Trace("add rpc:{@rpc}", r);
+ _rpcs.Add(r);
+ }
+
+
+ private readonly List protoAttrs = new List { "id" };
+ private readonly List protoRequiredAttrs = new List { "name" };
+
+ private void AddProto(XElement e)
+ {
+ ValidAttrKeys(e, protoAttrs, protoRequiredAttrs);
+
+ var p = new PProto()
+ {
+ Name = XmlUtil.GetRequiredAttribute(e, "name"),
+ Namespace = CurNamespace,
+ Id = XmlUtil.GetOptionIntAttribute(e, "id"),
+ };
+
+ foreach (XElement fe in e.Elements())
+ {
+ switch (fe.Name.LocalName)
+ {
+ case "var":
+ {
+ p.Fields.Add(CreateField(fe)); ;
+ break;
+ }
+ default:
+ {
+ throw new Exception($"定义文件:{CurImportFile} 不支持 tag:{fe.Name}");
+ }
+ }
+
+ }
+
+ s_logger.Trace("add proto:{@proto}", p);
+ _protos.Add(p);
+ }
+
+ private readonly List serviceAttrs = new List { "name" };
+ private void AddService(XElement e)
+ {
+ var name = XmlUtil.GetRequiredAttribute(e, "name");
+ s_logger.Trace("service {service}", name);
+ ValidAttrKeys(e, serviceAttrs, serviceAttrs);
+ foreach (XElement ele in e.Elements())
+ {
+ s_logger.Trace("service {service_name} node: {name} {value}", name, ele.Name, ele.Attribute("value")?.Value);
+ }
+ }
+
+ protected override void AddBean(XElement e, string parent)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/Defs/ProtoDefTypeBase.cs b/src/Luban.Job.Proto/Source/Defs/ProtoDefTypeBase.cs
new file mode 100644
index 0000000..2180ba7
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/Defs/ProtoDefTypeBase.cs
@@ -0,0 +1,29 @@
+using Luban.Job.Common.Utils;
+using Luban.Job.Common.Defs;
+using Luban.Common.Utils;
+
+namespace Luban.Job.Proto.Defs
+{
+ abstract class ProtoDefTypeBase : DefTypeBase
+ {
+ public DefAssembly Assembly => (DefAssembly)AssemblyBase;
+
+ public virtual string UeBpName => "U" + Name;
+
+ public virtual string UeBpFullName => TypeUtil.MakeCppJoinedFullName("U" + Namespace, Name);
+
+ //public string UeBpHeaderFileName => "bp_" + FileUtil.GetUeCppDefTypeHeaderFilePath(FullName);
+
+ //public string UeBpHeaderFileNameWithoutSuffix => "bp_" + FileUtil.GetUeCppDefTypeHeaderFilePathWithoutSuffix(FullName);
+
+ //public string EditorUeFullName => TypeUtil.MakeCppFullName(Namespace, Name);
+
+ //public string UeFname => "F" + Name;
+
+ //public string UeFfullName => TypeUtil.MakeCppFullName(Namespace, UeFname);
+
+ //public string UeHeaderFileName => FileUtil.GetUeCppDefTypeHeaderFilePath(FullName);
+
+ //public string UeEditorHeaderFileName => "editor_" + FileUtil.GetUeCppDefTypeHeaderFilePath(FullName);
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/Generate/CsRender.cs b/src/Luban.Job.Proto/Source/Generate/CsRender.cs
new file mode 100644
index 0000000..a3e972a
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/Generate/CsRender.cs
@@ -0,0 +1,324 @@
+using Luban.Job.Common.Defs;
+using Luban.Job.Common.Utils;
+using Luban.Job.Proto.Defs;
+using Scriban;
+using System;
+using System.Collections.Generic;
+
+namespace Luban.Job.Proto.Generate
+{
+ class CsRender
+ {
+ public string RenderAny(object o)
+ {
+ switch (o)
+ {
+ case DefConst c: return Render(c);
+ case DefEnum e: return Render(e);
+ case DefBean b: return Render(b);
+ case DefProto p: return Render(p);
+ case DefRpc r: return Render(r);
+
+ default: throw new Exception($"unknown render type:{o}");
+ }
+ }
+
+ public string Render(DefConst c)
+ {
+ return RenderUtil.RenderCsConstClass(c);
+ }
+
+ public string Render(DefEnum e)
+ {
+ return RenderUtil.RenderCsEnumClass(e);
+ }
+
+ [ThreadStatic]
+ private static Template t_beanRender;
+ public string Render(DefBean b)
+ {
+ var template = t_beanRender ??= Template.Parse(@"
+using Bright.Serialization;
+
+namespace {{namespace_with_top_module}}
+{
+
+ public {{if is_value_type}}struct{{else}}{{cs_class_modifier}} class{{end}} {{name}} : {{if parent_def_type}} {{parent}} {{else}} BeanBase {{end}}
+ {
+ {{if !is_value_type}}
+ public {{name}}()
+ {
+ }
+ {{end}}
+
+ public {{name}}(Bright.Common.NotNullInitialization _) {{if parent_def_type}} : base(_) {{end}}
+ {
+ {{if is_value_type}}
+ {{- for field in fields }}
+ {{if field.ctype.need_init}}{{field.proto_cs_init_field}}{{else}}{{field.proto_cs_init_field_default_value}} {{end}}
+ {{-end}}
+ {{else}}
+ {{- for field in fields }}
+ {{if field.ctype.need_init}}{{field.proto_cs_init_field}}{{end}}
+ {{-end}}
+ {{end}}
+ }
+
+ public static void Serialize{{name}}(ByteBuf _buf, {{name}} x)
+ {
+ {{if is_abstract_type}}
+ if (x != null)
+ {
+ _buf.WriteInt(x.GetTypeId());
+ x.Serialize(_buf);
+ }
+ else
+ {
+ _buf.WriteInt(0);
+ }
+ {{else}}
+ x.Serialize(_buf);
+ {{end}}
+ }
+
+ public static {{name}} Deserialize{{name}}(ByteBuf _buf)
+ {
+ {{if is_abstract_type}}
+ {{full_name}} x;
+ switch (_buf.ReadInt())
+ {
+ case 0 : return null;
+ {{- for child in hierarchy_not_abstract_children}}
+ case {{child.full_name}}.ID: x = new {{child.full_name}}(); break;
+ {{-end}}
+ default: throw new SerializationException();
+ }
+ x.Deserialize(_buf);
+ {{else}}
+ var x = new {{full_name}}();
+ x.Deserialize(_buf);
+ {{end}}
+ return x;
+ }
+ {{- for field in fields }}
+ public {{field.ctype.cs_define_type}} {{field.lan_style_name}};
+ {{-end}}
+
+ {{if !is_abstract_type}}
+ public const int ID = {{id}};
+ public override int GetTypeId() => ID;
+ {{end}}
+
+ public override void Serialize(ByteBuf _buf)
+ {
+ {{if parent_def_type}} base.Serialize(_buf); {{end}}
+ {{- for field in fields }}
+ {{field.cs_serialize}}
+ {{-end}}
+ }
+
+ public override void Deserialize(ByteBuf _buf)
+ {
+ {{if parent_def_type}} base.Deserialize(_buf); {{end}}
+ {{- for field in fields }}
+ {{field.cs_deserialize}}
+ {{-end}}
+ }
+
+ public override string ToString()
+ {
+ return ""{{full_name}}{ ""
+ {{- for field in hierarchy_fields }}
+ + ""{{field.lan_style_name}}:"" + {{field.proto_cs_to_string}} + "",""
+ {{-end}}
+ + ""}"";
+ }
+ }
+
+}
+
+");
+ var result = template.Render(b);
+
+ return result;
+ }
+
+ [ThreadStatic]
+ private static Template t_protoRender;
+ public string Render(DefProto p)
+ {
+ var template = t_protoRender ??= Template.Parse(@"
+using Bright.Serialization;
+
+namespace {{namespace_with_top_module}}
+{
+
+ public sealed class {{name}} : Bright.Net.Codecs.Protocol
+ {
+ {{- for field in fields }}
+ public {{field.ctype.cs_define_type}} {{field.lan_style_name}};
+ {{-end}}
+ public {{name}}()
+ {
+ }
+
+ public {{name}}(Bright.Common.NotNullInitialization _)
+ {
+ {{- for field in fields }}
+ {{if field.ctype.need_init}}{{field.proto_cs_init_field}}{{end}}
+ {{-end}}
+ }
+ public const int ID = {{id}};
+
+ public override int GetTypeId()
+ {
+ return ID;
+ }
+
+ public override void Serialize(ByteBuf _buf)
+ {
+ {{- for field in fields }}
+ {{field.cs_serialize}}
+ {{-end}}
+ }
+
+ public override void Deserialize(ByteBuf _buf)
+ {
+ {{- for field in fields }}
+ {{field.cs_deserialize}}
+ {{-end}}
+ }
+
+ public override void Reset()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public override object Clone()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public override string ToString()
+ {
+ return ""{{full_name}}{ ""
+ {{- for field in fields }}
+ + ""{{field.lan_style_name}}:"" + {{field.proto_cs_to_string}} + "",""
+ {{-end}}
+ + ""}"";
+ }
+ }
+
+}
+
+");
+ var result = template.Render(p);
+
+ return result;
+ }
+
+ [ThreadStatic]
+ private static Template t_rpcRender;
+ public string Render(DefRpc r)
+ {
+ var template = t_rpcRender ??= Template.Parse(@"
+using Bright.Serialization;
+
+namespace {{namespace_with_top_module}}
+{
+
+ public sealed class {{name}} : Bright.Net.Codecs.Rpc<{{targ_type.cs_define_type}}, {{tres_type.cs_define_type}}>
+ {
+ public {{name}}()
+ {
+ }
+
+ public const int ID = {{id}};
+
+ public override int GetTypeId()
+ {
+ return ID;
+ }
+
+ public override void SerializeArg(ByteBuf buf, {{targ_type.cs_define_type}} arg)
+ {
+ {{targ_type.cs_define_type}}.Serialize{{targ_type.bean.name}}(buf, arg);
+ }
+
+ public override {{targ_type.cs_define_type}} DeserializeArg(ByteBuf buf)
+ {
+ return {{targ_type.cs_define_type}}.Deserialize{{targ_type.bean.name}}(buf);
+ }
+
+ public override void SerializeRes(ByteBuf buf, {{tres_type.cs_define_type}} res)
+ {
+ {{tres_type.cs_define_type}}.Serialize{{tres_type.bean.name}}(buf, res);
+ }
+
+ public override {{tres_type.cs_define_type}} DeserializeRes(ByteBuf buf)
+ {
+ return {{tres_type.cs_define_type}}.Deserialize{{tres_type.bean.name}}(buf);
+ }
+
+ public override void Reset()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public override object Clone()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public override string ToString()
+ {
+ return $""{{full_name}}{%{ {{arg:{Arg},res:{Res} }} }%}"";
+ }
+ }
+}
+
+");
+ var result = template.Render(r);
+
+ return result;
+ }
+
+ [ThreadStatic]
+ private static Template t_stubRender;
+ public string RenderStubs(string name, string module, List protos, List rpcs)
+ {
+ var template = t_stubRender ??= Template.Parse(@"
+using Bright.Serialization;
+
+namespace {{namespace}}
+{
+
+ public static class {{name}}
+ {
+ public static System.Collections.Generic.Dictionary Factories { get; } = new System.Collections.Generic.Dictionary
+ {
+ {{- for proto in protos }}
+ [{{proto.full_name}}.ID] = () => new {{proto.full_name}}(),
+ {{-end}}
+
+ {{- for rpc in rpcs }}
+ [{{rpc.full_name}}.ID] = () => new {{rpc.full_name}}(),
+ {{-end}}
+ };
+ }
+
+}
+
+");
+ var result = template.Render(new
+ {
+ Name = name,
+ Namespace = module,
+ Protos = protos,
+ Rpcs = rpcs,
+ });
+
+ return result;
+ }
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/Generate/LuaRender.cs b/src/Luban.Job.Proto/Source/Generate/LuaRender.cs
new file mode 100644
index 0000000..17d6500
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/Generate/LuaRender.cs
@@ -0,0 +1,303 @@
+using Luban.Job.Common.Defs;
+using Luban.Job.Proto.Defs;
+using Scriban;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Luban.Job.Proto.Generate
+{
+ class LuaRender
+ {
+
+ [ThreadStatic]
+ private static Template t_allRender;
+ public string RenderTypes(List types)
+ {
+ var consts = types.Where(t => t is DefConst).ToList();
+ var enums = types.Where(t => t is DefEnum).ToList();
+ var beans = types.Where(t => t is DefBean).ToList();
+ var protos = types.Where(t => t is DefProto).ToList();
+ var rpcs = types.Where(t => t is DefRpc).ToList();
+ var template = t_allRender ??= Template.Parse(@"
+local setmetatable = setmetatable
+local pairs = pairs
+local ipairs = ipairs
+local tinsert = table.insert
+
+local function SimpleClass()
+ local class = {}
+ class.__index = class
+ class.New = function(...)
+ local ctor = class.ctor
+ local o = ctor and ctor(...) or {}
+ setmetatable(o, class)
+ return o
+ end
+ return class
+end
+
+
+local function get_map_size(m)
+ local n = 0
+ for _ in pairs(m) do
+ n = n + 1
+ end
+ return n
+end
+
+local consts =
+{
+ {{- for c in consts }}
+ ---@class {{c.full_name}}
+ {{- for item in c.items }}
+ ---@field public {{item.name}} {{item.type}}
+ {{-end}}
+ ['{{c.full_name}}'] = { {{ for item in c.items }} {{item.name}}={{item.to_lua_const_value}}, {{end}} };
+ {{-end}}
+}
+
+local enums =
+{
+ {{- for c in enums }}
+ ---@class {{c.full_name}}
+ {{- for item in c.items }}
+ ---@field public {{item.name}} int
+ {{-end}}
+ ['{{c.full_name}}'] = { {{ for item in c.items }} {{item.name}}={{item.int_value}}, {{end}} };
+ {{-end}}
+}
+
+
+local function InitTypes(methods)
+ local readBool = methods.readBool
+ local writeBool = methods.writeBool
+ local readByte = methods.readByte
+ local writeByte = methods.writeByte
+ local readShort = methods.readShort
+ local writeShort = methods.writeShort
+ local readFshort = methods.readFshort
+ local writeInt = methods.writeInt
+ local readInt = methods.readInt
+ local writeFint = methods.writeFint
+ local readFint = methods.readFint
+ local readLong = methods.readLong
+ local writeLong = methods.writeLong
+ local readFlong = methods.readFlong
+ local writeFlong = methods.writeFlong
+ local readFloat = methods.readFloat
+ local writeFloat = methods.writeFloat
+ local readDouble = methods.readDouble
+ local writeDouble = methods.writeDouble
+ local readSize = methods.readSize
+ local writeSize = methods.writeSize
+
+ local readString = methods.readString
+ local writeString = methods.writeString
+ local readBytes = methods.readBytes
+ local writeBytes = methods.writeBytes
+
+ local function readVector2(bs)
+ return { x = readFloat(bs), y = readFloat(bs) }
+ end
+
+ local function writeVector2(bs, v)
+ writeFloat(bs, v.x)
+ writeFloat(bs, v.y)
+ end
+
+ local function readVector3(bs)
+ return { x = readFloat(bs), y = readFloat(bs), z = readFloat(bs) }
+ end
+
+ local function writeVector3(bs, v)
+ writeFloat(bs, v.x)
+ writeFloat(bs, v.y)
+ writeFloat(bs, v.z)
+ end
+
+
+ local function readVector4(bs)
+ return { x = readFloat(bs), y = readFloat(bs), z = readFloat(bs), w = readFloat(bs) }
+ end
+
+ local function writeVector4(bs, v)
+ writeFloat(bs, v.x)
+ writeFloat(bs, v.y)
+ writeFloat(bs, v.z)
+ writeFloat(bs, v.w)
+ end
+
+ local function writeList(bs, list, keyFun)
+ writeSize(bs, #list)
+ for _, v in pairs(list) do
+ keyFun(bs, v)
+ end
+ end
+
+ local function readList(bs, keyFun)
+ local list = {}
+ local v
+ for i = 1, readSize(bs) do
+ tinsert(list, keyFun(bs))
+ end
+ return list
+ end
+
+ local writeArray = writeList
+ local readArray = readList
+
+ local function writeSet(bs, set, keyFun)
+ writeSize(bs, #set)
+ for _, v in ipairs(set) do
+ keyFun(bs, v)
+ end
+ end
+
+ local function readSet(bs, keyFun)
+ local set = {}
+ local v
+ for i = 1, readSize(bs) do
+ tinsert(set, keyFun(bs))
+ end
+ return set
+ end
+
+ local function writeMap(bs, map, keyFun, valueFun)
+ writeSize(bs, get_map_size(map))
+ for k, v in pairs(map) do
+ keyFun(bs, k)
+ valueFun(bs, v)
+ end
+ end
+
+ local function readMap(bs, keyFun, valueFun)
+ local map = {}
+ for i = 1, readSize(bs) do
+ local k = keyFun(bs)
+ local v = valueFun(bs)
+ map[k] = v
+ end
+ return map
+ end
+
+ local default_vector2 = {x=0,y=0}
+ local default_vector3 = {x=0,y=0,z=0}
+ local default_vector4 = {x=0,y=0,z=0,w=0}
+
+ local beans = {}
+{{ for bean in beans }}
+ do
+ ---@class {{bean.full_name}} {{if bean.parent_def_type}}:{{bean.parent}} {{end}}
+ {{- for field in bean.fields}}
+ ---@field public {{field.name}} {{field.lua_comment_type}}
+ {{-end}}
+ local class = SimpleClass()
+ class._id = {{bean.id}}
+ class._name = '{{bean.full_name}}'
+ --local name2id = { {{for c in bean.hierarchy_not_abstract_children}} ['{{c.full_name}}'] = {{c.id}}, {{end}} }
+ local id2name = { {{for c in bean.hierarchy_not_abstract_children}} [{{c.id}}] = '{{c.full_name}}', {{end}} }
+{{if bean.is_abstract_type}}
+ class._serialize = function(bs, self)
+ writeInt(bs, self._id)
+ beans[self._name]._serialize(bs, self)
+ end
+ class._deserialize = function(bs)
+ local id = readInt(bs)
+ return beans[id2name[id]]._deserialize(bs)
+ end
+{{else}}
+ class._serialize = function(bs, self)
+ {{- for field in bean.hierarchy_fields }}
+ {{field.proto_lua_serialize_while_nil}}
+ {{-end}}
+ end
+ class._deserialize = function(bs)
+ local o = {
+ {{- for field in bean.hierarchy_fields }}
+ {{field.name}} = {{field.proto_lua_deserialize}},
+ {{-end}}
+ }
+ setmetatable(o, class)
+ return o
+ end
+{{end}}
+ beans[class._name] = class
+ end
+{{end}}
+
+ local protos = { }
+{{ for proto in protos }}
+ do
+ ---@class {{proto.full_name}}
+ {{- for field in proto.fields}}
+ ---@field public {{field.name}} {{field.lua_comment_type}}
+ {{-end}}
+ local class = SimpleClass()
+ class._id = {{proto.id}}
+ class._name = '{{proto.full_name}}'
+ class._serialize = function(self, bs)
+ {{- for field in proto.fields }}
+ {{field.proto_lua_serialize_while_nil}}
+ {{-end}}
+ end
+ class._deserialize = function(self, bs)
+ {{- for field in proto.fields }}
+ self.{{field.name}} = {{field.proto_lua_deserialize}}
+ {{-end}}
+ end
+ protos[class._id] = class
+ protos[class._name] = class
+ end
+{{end}}
+
+ local rpcs = { }
+{{ for rpc in rpcs }}
+ do
+ ---@class {{rpc.full_name}}
+ ---@field public is_request bool
+ ---@field public rpc_id long
+ ---@field public arg {{rpc.targ_type.lua_comment_type}}
+ ---@field public res {{rpc.tres_type.lua_comment_type}}
+ local class = SimpleClass()
+ class._id = {{rpc.id}}
+ class._name = '{{rpc.full_name}}'
+ class._arg_name = '{{rpc.targ_type.bean.full_name}}'
+ class._res_name = '{{rpc.tres_type.bean.full_name}}'
+ class._serialize = function(self, bs)
+ local composite_id = self.rpc_id * 2
+ if self.is_request then
+ writeLong(bs, composite_id)
+ beans['{{rpc.targ_type.bean.full_name}}']._serialize(self.arg, bs)
+ else
+ writeLong(bs, composite_id + 1)
+ beans['{{rpc.tres_type.bean.full_name}}']._serialize(self.res, bs)
+ end
+ end
+ class._deserialize = function(self, bs)
+ local composite_id = readLong(bs)
+ self.rpc_id = composite_id // 2
+ if composite_id % 2 == 0 then
+ self.is_request = true
+ self.arg = beans['{{rpc.targ_type.bean.full_name}}']._deserialize(bs)
+ else
+ self.is_request = false
+ self.res = beans['{{rpc.tres_type.bean.full_name}}']._deserialize(bs)
+ end
+ end
+ rpcs[class._id] = class
+ rpcs[class._name] = class
+ end
+{{end}}
+
+ return { consts = consts, enums = enums, beans = beans, protos = protos, rpcs = rpcs }
+ end
+
+return { InitTypes = InitTypes}
+
+
+");
+ return template.Render(new { Consts = consts, Enums = enums, Beans = beans, Protos = protos, Rpcs = rpcs });
+ }
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/GenerateProto.cs b/src/Luban.Job.Proto/Source/GenerateProto.cs
new file mode 100644
index 0000000..bdfc84d
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/GenerateProto.cs
@@ -0,0 +1,56 @@
+//using Bright.Time;
+//using Gen.Proto.Common.RawDefs;
+//using Luban.Job.Common.Utils;
+
+//namespace Luban.Job.Proto.Client
+//{
+// class GenerateProto
+// {
+// public bool Handle(CommandLineOptions options)
+// {
+// var timer = new ProfileTimer();
+// timer.StartPhase("所有阶段");
+
+// timer.StartPhase("加载定义");
+// var protoLoader = new ProtoDefLoader();
+// protoLoader.Load(options.DefineFile);
+// long defEndTime = TimeUtil.NowMillis;
+// timer.EndPhaseAndLog();
+
+
+// timer.StartPhase("发起 GenProto");
+// string outputDir = options.OutputCodeDir;
+
+// var defines = protoLoader.BuildDefines();
+
+
+// defines.Target = options.Target;
+// defines.Language = options.Languange;
+// var rpc = new GenProto();
+// var res = rpc.Call(GenClient.Ins.Session, new GenProtoArg()
+// {
+// Define = defines,
+// OutputCodeRelatePath = outputDir,
+// }).Result;
+// timer.EndPhaseAndLog();
+
+
+// if (res.OK)
+// {
+// timer.StartPhase("获取生成文件");
+
+// DownloadFileUtil.DownloadGeneratedFiles(outputDir, res.NewCodeFiles).Wait();
+
+// timer.EndPhaseAndLog();
+
+// timer.EndPhaseAndLog();
+// return true;
+// }
+// else
+// {
+// timer.EndPhaseAndLog();
+// return false;
+// }
+// }
+// }
+//}
diff --git a/src/Luban.Job.Proto/Source/JobController.cs b/src/Luban.Job.Proto/Source/JobController.cs
new file mode 100644
index 0000000..d53e3e7
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/JobController.cs
@@ -0,0 +1,16 @@
+using Luban.Common.Protos;
+using Luban.Server.Common;
+using System;
+using System.Threading.Tasks;
+
+namespace Luban.Job.Proto
+{
+ [Controller("proto")]
+ public class JobController : IJobController
+ {
+ public Task GenAsync(RemoteAgent agent, GenJob rpc)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/RawDefs/Defines.cs b/src/Luban.Job.Proto/Source/RawDefs/Defines.cs
new file mode 100644
index 0000000..34bfe46
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/RawDefs/Defines.cs
@@ -0,0 +1,26 @@
+using Luban.Job.Common.RawDefs;
+using System.Collections.Generic;
+
+namespace Luban.Job.Proto.RawDefs
+{
+ public class Defines
+ {
+ public string Target { get; set; } = "*";
+
+ public string Language { get; set; } = "cs";
+
+ public string TopModule { get; set; } = "";
+
+ public List ProtoServices { get; set; } = new List();
+
+ public List Beans { get; set; } = new List();
+
+ public List Consts { get; set; } = new List();
+
+ public List Enums { get; set; } = new List();
+
+ public List Protos { get; set; } = new List();
+
+ public List Rpcs { get; set; } = new List();
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/RawDefs/PProto.cs b/src/Luban.Job.Proto/Source/RawDefs/PProto.cs
new file mode 100644
index 0000000..fd4f12c
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/RawDefs/PProto.cs
@@ -0,0 +1,17 @@
+using Luban.Job.Common.RawDefs;
+using System.Collections.Generic;
+
+namespace Luban.Job.Proto.RawDefs
+{
+
+ public class PProto
+ {
+ public string Namespace { get; set; }
+
+ public string Name { get; set; }
+
+ public int Id { get; set; }
+
+ public List Fields { get; set; } = new List();
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/RawDefs/PRpc.cs b/src/Luban.Job.Proto/Source/RawDefs/PRpc.cs
new file mode 100644
index 0000000..9ff2375
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/RawDefs/PRpc.cs
@@ -0,0 +1,16 @@
+namespace Luban.Job.Proto.RawDefs
+{
+
+ public class PRpc
+ {
+ public string Namespace { get; set; }
+
+ public string Name { get; set; }
+
+ public int Id { get; set; }
+
+ public string ArgType { get; set; }
+
+ public string ResType { get; set; }
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/RawDefs/Service.cs b/src/Luban.Job.Proto/Source/RawDefs/Service.cs
new file mode 100644
index 0000000..2276b7f
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/RawDefs/Service.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+
+namespace Luban.Job.Proto.RawDefs
+{
+
+ public class Service
+ {
+ public List Prefixs { get; set; } = new List();
+
+ public List FullNames { get; set; } = new List();
+ }
+}
diff --git a/src/Luban.Job.Proto/Source/RpcController.cs b/src/Luban.Job.Proto/Source/RpcController.cs
new file mode 100644
index 0000000..c8acc9e
--- /dev/null
+++ b/src/Luban.Job.Proto/Source/RpcController.cs
@@ -0,0 +1,623 @@
+namespace Luban.Job.Proto.Server.Net
+{
+ class RpcController
+ {
+
+ //private void LogException(IContext ctx, Exception e)
+ //{
+ // if (e is AggregateException ae)
+ // {
+ // foreach (var ie in ae.InnerExceptions)
+ // {
+ // LogException(ctx, ie);
+ // }
+ // }
+ // else
+ // {
+
+ // s_logger.Error(e, "发生异常");
+ // ctx.Error(e, " {0} \n ", e.StackTrace);
+ // }
+ //}
+
+ //private bool ValidateDataType(string outputDataType)
+ //{
+ // switch (outputDataType)
+ // {
+ // case "bin":
+ // case "cbin":
+ // case "json": return true;
+ // default: return false;
+ // }
+ //}
+
+ //private void OnGenDb(Session session, GenDb proto)
+ //{
+ // var timer = new ProfileTimer();
+
+ // timer.StartPhase("生成代码");
+
+ // var res = new GenDbRes();
+
+ // string relatePath = proto.Arg.OutputCodeRelatePath;
+
+ // var ass = new DefAssembly();
+ // var ctx = new SessionContext(session, proto.Arg.Verbose);
+ // try
+ // {
+ // var genCodeTasks = new List();
+ // var outputFiles = new ConcurrentBag();
+
+ // ass.Load(EJobType.DB, proto.Arg.Define, ctx);
+ // var render = new Generate.Db.CsRender();
+ // foreach (var c in ass.Types.Values)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var module = ass.TopModule;
+ // var name = "Tables";
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTables(name, module, ass.Types.Values.Where(t => t is BTable).ToList()), "cs");
+ // var file = FileUtil.GetCsDefTypePath(name);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // Task.WhenAll(genCodeTasks).Wait();
+ // ctx.Info(timer.EndPhaseAndLogToString());
+
+ // res.NewCodeFiles = outputFiles.ToList();
+ // res.OK = true;
+ // }
+ // catch (Exception e)
+ // {
+ // res.OK = false;
+ // LogException(ctx, e);
+ // }
+
+ // proto.ReturnResult(session, res);
+ //}
+
+ //private ICsCodeRender CreateCsCodeRender(string outputDataType)
+ //{
+ // switch (outputDataType)
+ // {
+ // case "bin": return new AppCsBinCodeRender();
+ // case "cbin": return new AppCsCompatibleBinCodeRender();
+ // case "json": return new AppCsJsonCodeRender();
+ // default: throw new ArgumentException($"not support output data type:{outputDataType}");
+ // }
+ //}
+
+ //private void OnGenCfg(Session session, GenCfg proto)
+ //{
+ // var res = new GenCfgRes();
+
+ // string lan = proto.Arg.Define.Language;
+
+ // DefAssembly ass = new DefAssembly();
+
+ // var ctx = new SessionContext(session, proto.Arg.Verbose);
+
+
+ // var allJobs = new List();
+
+
+ // try
+ // {
+ // string outputDataType = proto.Arg.OutputDataType;
+ // if (!ValidateDataType(outputDataType))
+ // {
+ // throw new ArgumentException($"unknown outputdatatype:{outputDataType}");
+ // }
+
+ // bool exportTestData = proto.Arg.ExportTestData;
+
+ // long genStartTime = TimeUtil.NowMillis;
+ // var genCodeTasks = new List();
+ // var outputCodeFiles = new ConcurrentBag();
+
+ // ass.Load(EJobType.CONFIG, proto.Arg.Define, ctx);
+ // EGenTypes genTypes = proto.Arg.GenTypes;
+ // var targetService = ass.CfgTargetService;
+
+ // List exportTables = ass.Types.Values.Where(t => t is CTable ct && ct.NeedExport).Select(t => (CTable)t).ToList();
+
+ // if (genTypes.HasFlag(EGenTypes.APP_CODE))
+ // {
+ // var refTypes = new Dictionary();
+ // long genCodeStartTime = TimeUtil.NowMillis;
+
+ // foreach (var refType in targetService.Refs)
+ // {
+ // if (!ass.Types.ContainsKey(refType))
+ // {
+ // throw new Exception($"service:{targetService.Name} ref:{refType} 类型不存在");
+ // }
+ // if (!refTypes.TryAdd(refType, ass.Types[refType]))
+ // {
+ // throw new Exception($"service:{targetService.Name} ref:{refType} 重复引用");
+ // }
+ // }
+
+ // foreach (var table in exportTables)
+ // {
+ // refTypes[table.FullName] = table;
+ // table.ValueTType.Apply(RefTypeVisitor.Ins, refTypes);
+ // }
+
+ // foreach (var type in ass.Types)
+ // {
+ // if (type.Value is DefConst || type.Value is DefEnum)
+ // {
+ // refTypes[type.Key] = type.Value;
+ // }
+ // }
+
+ // List exportTypes = refTypes.Values.ToList();
+
+ // switch (lan)
+ // {
+ // case "cs":
+ // {
+ // ICsCodeRender render = CreateCsCodeRender(outputDataType);
+ // foreach (var c in exportTypes)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+
+
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var module = ass.TopModule;
+ // var name = targetService.Manager;
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderService(name, module, exportTables), "cs");
+ // var file = FileUtil.GetCsDefTypePath(name);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+
+ // break;
+ // }
+ // case "go":
+ // {
+ // //
+ // // TODO?
+ // // 由于 go 语言不支持类型继承
+ // // go 不支持 table.value_type 为多态的表
+ // //
+ // //
+ // var render = new AppGoCodeRender();
+
+
+ // foreach (var c in exportTypes)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "go");
+ // var file = FileUtil.GetGoDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var module = ass.TopModule;
+ // var name = targetService.Manager;
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderService(name, module, exportTables), "go");
+ // var file = FileUtil.GetGoDefTypePath(name);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+
+ // break;
+ // }
+ // case "lua":
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var render = new Generate.Cfg.LuaRender();
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAll(exportTypes.ToList()), "lua");
+ // var file = "CfgTypes.lua";
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // break;
+ // }
+ // case "editor_cs":
+ // {
+ // var render = new EditorCsRender();
+ // foreach (var c in ass.Types.Values)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // break;
+ // }
+ // case "editor_cpp":
+ // {
+ // var render = new EditorCppRender();
+ // foreach (var c in ass.Types.Values)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // break;
+ // }
+ // case "editor_ue_cpp":
+ // {
+ // var render = new UE4EditorCppRender();
+
+ // var renderTypes = ass.Types.Values.Where(c => c is DefEnum || c is DefBean).ToList();
+
+ // foreach (var c in renderTypes)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp");
+ // var file = c.UeEditorHeaderFileName;
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+
+ // int TYPE_PER_STUB_FILE = 200;
+
+ // for (int i = 0, n = (renderTypes.Count + TYPE_PER_STUB_FILE - 1) / TYPE_PER_STUB_FILE; i < n; i++)
+ // {
+ // int index = i;
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // int startIndex = index * TYPE_PER_STUB_FILE;
+ // var content = RenderUtils.ConcatAutoGenerationHeader(
+ // render.RenderStub(renderTypes.GetRange(startIndex, Math.Min(TYPE_PER_STUB_FILE, renderTypes.Count - startIndex))),
+ // "cpp");
+ // var file = $"Stub_{index}.cpp";
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // break;
+ // }
+ // case "ue_bp_cpp":
+ // {
+ // var render = new UE4BpCppRender();
+ // foreach (var c in exportTypes)
+ // {
+ // if (c is DefConst || c is CTable)
+ // {
+ // continue;
+ // }
+
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cpp");
+ // var file = c.UeBpHeaderFileName;
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputCodeFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+
+ // //{
+ // // var module = ass.TopModule;
+ // // var name = targetService.Manager;
+ // // var content = render.RenderService(name, module, exportTables);
+ // // var file = FileUtil.GetCppDefTypeCppFilePath(name);
+ // // var md5 = GenMd5AndAddCache(file, content);
+ // // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // //}
+ // break;
+ // }
+ // default:
+ // {
+ // throw new Exception($"unknown language:{lan}");
+ // }
+ // }
+
+
+ // allJobs.Add(Task.Run(async () =>
+ // {
+ // await Task.WhenAll(genCodeTasks);
+ // res.NewAppCodeFiles = outputCodeFiles.ToList();
+ // long genCodeEndTime = TimeUtil.NowMillis;
+ // ctx.Info("====== 生成代码 总共耗时 {0} ms ======", (genCodeEndTime - genCodeStartTime));
+ // }));
+ // }
+
+ // if ((genTypes & (EGenTypes.APP_DATA | EGenTypes.APP_RESOURCE_LIST)) != 0)
+ // {
+ // var genDataTasks = new List();
+ // var outputDataFiles = new ConcurrentBag();
+ // var render = new AppBinaryDataRender();
+ // long genDataStartTime = TimeUtil.NowMillis;
+
+ // foreach (CTable c in exportTables)
+ // {
+ // genDataTasks.Add(Task.Run(async () =>
+ // {
+ // long beginTime = TimeUtil.NowMillis;
+ // await c.Load(session, exportTestData);
+ // long endTime = TimeUtil.NowMillis;
+ // if (endTime - beginTime > 100)
+ // {
+ // ctx.Info("====== 配置表 {0} 加载耗时 {1} ms ======", c.FullName, (endTime - beginTime));
+ // }
+ // }));
+ // }
+ // Task.WaitAll(genDataTasks.ToArray());
+ // }
+
+
+ // if (genTypes.HasFlag(EGenTypes.APP_DATA))
+ // {
+ // var genDataTasks = new List();
+ // var outputDataFiles = new ConcurrentBag();
+ // var render = new AppBinaryDataRender();
+ // long genDataStartTime = TimeUtil.NowMillis;
+
+ // foreach (CTable c in exportTables)
+ // {
+ // genDataTasks.Add(Task.Run(() =>
+ // {
+ // var content = c.ToOutputData(outputDataType);
+ // var file = c.OutputDataFile;
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputDataFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+
+ // allJobs.Add(Task.Run(async () =>
+ // {
+ // await Task.WhenAll(genDataTasks);
+ // long genDataEndTime = TimeUtil.NowMillis;
+ // ctx.Info("====== 生成配置数据 总共耗时 {0} ms ======", (genDataEndTime - genDataStartTime));
+ // res.NewAppDataFiles = outputDataFiles.ToList();
+
+ // long verifyStartTime = TimeUtil.NowMillis;
+ // render.VerifyTables(exportTables);
+ // res.PathQueries = ass.GetPathQueries();
+
+ // long verifyEndTime = TimeUtil.NowMillis;
+ // ctx.Info("====== 校验配置 总共耗时 {0} ms ======", (verifyEndTime - verifyStartTime));
+ // }));
+ // }
+
+ // if (genTypes.HasFlag(EGenTypes.APP_RESOURCE_LIST))
+ // {
+ // var genDataTasks = new List>>();
+ // var render = new AppBinaryDataRender();
+ // long genDataStartTime = TimeUtil.NowMillis;
+
+ // foreach (CTable c in exportTables)
+ // {
+ // genDataTasks.Add(Task.Run(() =>
+ // {
+ // return c.ExportResourceList();
+ // }));
+ // }
+
+ // allJobs.Add(Task.Run(async () =>
+ // {
+ // var ress = new HashSet<(string, string)>(10000);
+ // foreach (var task in genDataTasks)
+ // {
+ // foreach (var ri in await task)
+ // {
+ // if (ress.Add((ri.Resource, ri.Tag)))
+ // {
+ // res.ResourceList.Add(ri);
+ // }
+ // }
+ // }
+ // long genDataEndTime = TimeUtil.NowMillis;
+ // ctx.Info("====== 生成导出资源列表 总共耗时 {0} ms ======", (genDataEndTime - genDataStartTime));
+ // }));
+ // }
+
+ // Task.WhenAll(allJobs).Wait();
+
+ // long genEndTime = TimeUtil.NowMillis;
+ // ctx.Info("======== 服务器端 总共耗时 {0} ms =======", (genEndTime - genStartTime));
+
+ // res.OK = true;
+ // }
+ // catch (Exception e)
+ // {
+ // res.OK = false;
+ // LogException(ctx, e);
+ // }
+
+ // proto.ReturnResult(session, res);
+ //}
+
+ //private void OnGenProto(Session session, GenProto proto)
+ //{
+ // var timer = new ProfileTimer();
+
+ // timer.StartPhase("服务器生成代码");
+
+ // var res = new GenProtoRes();
+
+ // string relatePath = proto.Arg.OutputCodeRelatePath;
+
+ // DefAssembly ass = new DefAssembly();
+ // var ctx = new SessionContext(session, proto.Arg.Verbose);
+ // try
+ // {
+ // var genCodeTasks = new List();
+ // var outputFiles = new ConcurrentBag();
+
+ // ass.Load(EJobType.PROTO, proto.Arg.Define, ctx);
+ // var outputSyncFiles = new ConcurrentBag();
+
+ // switch (proto.Arg.Define.Language)
+ // {
+ // case "cs":
+ // {
+ // var render = new CsRender();
+ // foreach (var c in ass.Types.Values)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var module = ass.TopModule;
+ // var name = "ProtocolStub";
+ // var content = RenderUtils.ConcatAutoGenerationHeader(
+ // render.RenderStubs(name, module,
+ // ass.Types.Values.Where(t => t is PProto).ToList(),
+ // ass.Types.Values.Where(t => t is PRpc).ToList()),
+ // "cs");
+ // var file = FileUtil.GetCsDefTypePath(name);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // break;
+ // }
+ // case "lua":
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var render = new Generate.Proto.LuaRender();
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTypes(ass.Types.Values.ToList()), "lua");
+ // var file = "ProtoTypes.lua";
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // break;
+ // }
+ // default:
+ // {
+ // throw new Exception($"unknown lan:{proto.Arg.Define.Language}");
+ // }
+ // }
+
+ // Task.WhenAll(genCodeTasks).Wait();
+ // res.NewCodeFiles = outputFiles.ToList();
+
+ // ctx.Info(timer.EndPhaseAndLogToString());
+
+ // res.OK = true;
+ // }
+ // catch (Exception e)
+ // {
+ // res.OK = false;
+ // LogException(ctx, e);
+ // }
+
+ // proto.ReturnResult(session, res);
+ //}
+
+ //private void OnGenRep(Session session, GenRep proto)
+ //{
+ // var timer = new ProfileTimer();
+
+ // timer.StartPhase("服务器生成代码");
+
+ // var res = new GenRepRes();
+
+ // string relatePath = proto.Arg.OutputCodeRelatePath;
+
+ // DefAssembly ass = new DefAssembly();
+ // var ctx = new SessionContext(session, proto.Arg.Verbose);
+ // try
+ // {
+ // var genCodeTasks = new List();
+ // var outputFiles = new ConcurrentBag();
+
+ // ass.Load(EJobType.REP, proto.Arg.Define, ctx);
+ // var outputSyncFiles = new ConcurrentBag();
+
+ // switch (proto.Arg.Define.Language)
+ // {
+ // case "cs":
+ // {
+ // var render = new Generate.Rep.CsRender();
+ // foreach (var c in ass.Types.Values)
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderAny(c), "cs");
+ // var file = FileUtil.GetCsDefTypePath(c.FullName);
+ // var md5 = GenMd5AndAddCache(file, content);
+
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // }
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var module = ass.TopModule;
+ // var name = "RepStub";
+ // var content = RenderUtils.ConcatAutoGenerationHeader(
+ // render.RenderStubs(name, module, ass.Types.Values.Where(t => (t is DefActor) || (t is DefComponent)).ToList()),
+ // "cs");
+ // var file = FileUtil.GetCsDefTypePath(name);
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // break;
+ // }
+ // case "lua":
+ // {
+ // genCodeTasks.Add(Task.Run(() =>
+ // {
+ // var render = new Generate.Rep.LuaRender();
+ // var content = RenderUtils.ConcatAutoGenerationHeader(render.RenderTypes(ass.Types.Values.ToList()), "lua");
+ // var file = "RepTypes.lua";
+ // var md5 = GenMd5AndAddCache(file, content);
+ // outputFiles.Add(new FileInfo() { FilePath = file, MD5 = md5 });
+ // }));
+ // break;
+ // }
+ // default:
+ // {
+ // throw new Exception($"unknown lan:{proto.Arg.Define.Language}");
+ // }
+ // }
+
+ // Task.WhenAll(genCodeTasks).Wait();
+ // res.NewCodeFiles = outputFiles.ToList();
+
+ // ctx.Info(timer.EndPhaseAndLogToString());
+
+ // res.OK = true;
+ // }
+ // catch (Exception e)
+ // {
+ // res.OK = false;
+ // LogException(ctx, e);
+ // }
+
+ // proto.ReturnResult(session, res);
+ //}
+ }
+}
diff --git a/src/Luban.Server/Luban.Server.csproj b/src/Luban.Server/Luban.Server.csproj
index e344b9b..9b280be 100644
--- a/src/Luban.Server/Luban.Server.csproj
+++ b/src/Luban.Server/Luban.Server.csproj
@@ -30,6 +30,8 @@
+
+
diff --git a/src/Luban.Server/Source/Program.cs b/src/Luban.Server/Source/Program.cs
index 498b694..7e7d487 100644
--- a/src/Luban.Server/Source/Program.cs
+++ b/src/Luban.Server/Source/Program.cs
@@ -47,6 +47,8 @@ namespace Luban.Server
#if EMBED_CFG
GenServer.Ins.RegisterJob("cfg", new Luban.Job.Cfg.JobController());
#endif
+ GenServer.Ins.RegisterJob("proto", new Luban.Job.Proto.JobController());
+ GenServer.Ins.RegisterJob("db", new Luban.Job.Db.JobController());
int processorCount = System.Environment.ProcessorCount;
ThreadPool.SetMinThreads(Math.Max(4, processorCount), 5);
ThreadPool.SetMaxThreads(Math.Max(16, processorCount * 4), 10);
diff --git a/src/Luban.sln b/src/Luban.sln
index e94de77..d1ea460 100644
--- a/src/Luban.sln
+++ b/src/Luban.sln
@@ -15,6 +15,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luban.Server.Common", "Luba
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luban.Server", "Luban.Server\Luban.Server.csproj", "{714B78D2-A3BE-4845-AF0E-0A5076B8E77E}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luban.Job.Proto", "Luban.Job.Proto\Luban.Job.Proto.csproj", "{845D3933-EA3F-4A7D-97A3-77E696A2D261}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Luban.Job.Db", "Luban.Job.Db\Luban.Job.Db.csproj", "{7467AC15-C61F-4C56-942F-18EAEA902C58}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -45,6 +49,14 @@ Global
{714B78D2-A3BE-4845-AF0E-0A5076B8E77E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{714B78D2-A3BE-4845-AF0E-0A5076B8E77E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{714B78D2-A3BE-4845-AF0E-0A5076B8E77E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {845D3933-EA3F-4A7D-97A3-77E696A2D261}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {845D3933-EA3F-4A7D-97A3-77E696A2D261}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {845D3933-EA3F-4A7D-97A3-77E696A2D261}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {845D3933-EA3F-4A7D-97A3-77E696A2D261}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7467AC15-C61F-4C56-942F-18EAEA902C58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7467AC15-C61F-4C56-942F-18EAEA902C58}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7467AC15-C61F-4C56-942F-18EAEA902C58}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7467AC15-C61F-4C56-942F-18EAEA902C58}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE