CmdExportBytesDatabase.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. using Newtonsoft.Json;
  2. using Newtonsoft.Json.Linq;
  3. using XGame.Framework.Serialization;
  4. namespace etoy
  5. {
  6. internal class CmdExportBytesDatabase : Command
  7. {
  8. public override string Description => "导出数据库-字节流文本";
  9. protected virtual TableTag AllowedTableTag => TableTag.Client;
  10. protected virtual KeyValueTag AllowedKeyValueTag => KeyValueTag.Client;
  11. protected virtual string DatabaseOutput => Context.Option.ClientDatabaseOutput;
  12. private readonly string TableExt = "Table.bytes";
  13. private readonly List<Exception> _errors = new List<Exception>();
  14. protected override void OnProcess()
  15. {
  16. var outputPath = DatabaseOutput.ToPath();
  17. if (Directory.Exists(outputPath))
  18. Directory.Delete(outputPath, true);
  19. Directory.CreateDirectory(outputPath);
  20. SetProgress(0.1f);
  21. ExportTables(Context, outputPath);
  22. if (_errors.Count > 0)
  23. {
  24. SetException(new Exception(string.Join('\n', (from e in _errors select $"## ERROR: {e.Message}").ToArray())));
  25. }
  26. else
  27. {
  28. Completed();
  29. }
  30. }
  31. private void ExportTables(Context context, string outputPath)
  32. {
  33. foreach (var table in Context.Blackboard.Tables)
  34. {
  35. if (HasTableFlag(table.TableTag))
  36. {
  37. try
  38. {
  39. ExportTable(context, outputPath, table);
  40. }
  41. catch (Exception ex)
  42. {
  43. _errors.Add(ex);
  44. Console.WriteLine($"配置表导出异常 Name:{table.Name} Message:{ex.Message}\n\nStack:{ex.StackTrace}");
  45. }
  46. }
  47. }
  48. }
  49. private void ExportTable(Context context, string outputPath, Table table)
  50. {
  51. var fileName = table.Name + TableExt;
  52. var filePath = Path.Combine(outputPath, fileName);
  53. var serializables = new List<ISerializable>();
  54. for (int i = 0, rowCount = table.Rows.Count; i < rowCount; i++)
  55. {
  56. var row = table.Rows[i];
  57. var fieldGroup = new SerializableFieldGroup();
  58. for (int j = 0, colCount = row.Cells.Count; j < colCount; j++)
  59. {
  60. var cell = row.Cells[j];
  61. var fieldInfo = cell.FieldInfo;
  62. if (HasTableFlag(fieldInfo.OutputTag) == false)
  63. {
  64. continue;
  65. }
  66. if (context.Blackboard.TryGetMetadata(fieldInfo.FieldType, out var metadata))
  67. { // 是自定义属性
  68. if (metadata.StructType == MetadataStructType.Enum)
  69. {// 枚举
  70. fieldGroup.fields.Add(new SerializableEnum()
  71. {
  72. fieldType = fieldInfo.FieldType,
  73. fieldName = fieldInfo.FieldName,
  74. isRepeated = fieldInfo.IsRepeated,
  75. value = cell.Value,
  76. meta = metadata
  77. });
  78. }
  79. else
  80. { // 数据结构
  81. var structField = GenStructField(fieldInfo, cell.Value, table.Name, context, metadata);
  82. fieldGroup.fields.Add(structField);
  83. }
  84. }
  85. else
  86. { // 普通字段
  87. fieldGroup.fields.Add(new SerializableField()
  88. {
  89. fieldType = fieldInfo.FieldType,
  90. fieldName = fieldInfo.FieldName,
  91. isRepeated = fieldInfo.IsRepeated,
  92. value = cell.Value
  93. });
  94. }
  95. }
  96. if (fieldGroup.fields.Count > 0)
  97. {
  98. serializables.Add(fieldGroup);
  99. }
  100. }
  101. var writer = new Writer();
  102. writer.Write(serializables);
  103. var bytes = writer.Finish();
  104. File.WriteAllBytes(filePath, bytes);
  105. }
  106. private ISerializable GenStructField(FieldInfo fieldInfo, string value, string tableName, Context context, MetadataStruct metadata)
  107. {
  108. if (fieldInfo.IsRepeated)
  109. {
  110. var fieldArray = new SerializableArray();
  111. var jArray = JsonConvert.DeserializeObject<JArray>(value);
  112. foreach (var item in jArray)
  113. {
  114. if (item is JObject jobj)
  115. {
  116. fieldArray.fields.Add(GenSingleStructField(jobj, tableName, context, metadata));
  117. }
  118. else
  119. {
  120. throw new Exception($"配置表序列化结构体数据错误. Table:{tableName} FieldType: {fieldInfo.FieldType} Name:{fieldInfo.FieldName} Value:{value}");
  121. }
  122. }
  123. return fieldArray;
  124. }
  125. else
  126. {
  127. return GenSingleStructField(JsonConvert.DeserializeObject<JObject>(value), tableName, context, metadata);
  128. }
  129. }
  130. private ISerializable GenSingleStructField(JObject jobj, string tableName, Context context, MetadataStruct metadata)
  131. {
  132. var fieldGroup = new SerializableFieldGroup();
  133. for (int i = 0; i < metadata.Fields.Length; i++)
  134. {
  135. var metaField = metadata.Fields[i];
  136. var fieldVal = jobj[metaField.Name].ToString();
  137. if (context.Blackboard.TryGetMetadata(metaField.FieldType, out var subMeta))
  138. { // 嵌套
  139. if (subMeta.StructType == MetadataStructType.Enum)
  140. { // 枚举
  141. fieldGroup.fields.Add(new SerializableEnum()
  142. {
  143. fieldType = metaField.FieldType,
  144. fieldName = metaField.Name,
  145. isRepeated = metaField.StructRepeated,
  146. value = fieldVal,
  147. meta = subMeta,
  148. });
  149. }
  150. else
  151. { //结构体 递归
  152. if (metaField.StructRepeated)
  153. { // 数组
  154. var jArray = jobj[metaField.Name] as JArray;
  155. var fieldArray = new SerializableArray();
  156. foreach (var item in jArray)
  157. {
  158. if (item is JObject subObj)
  159. {
  160. fieldArray.fields.Add(GenSingleStructField(subObj, tableName, context, subMeta));
  161. }
  162. else
  163. {
  164. throw new Exception($"配置表序列化结构体数据错误.Table:{tableName} FieldType: {subMeta.Name} Value:{fieldVal}");
  165. }
  166. }
  167. fieldGroup.fields.Add(fieldArray);
  168. }
  169. else
  170. {
  171. fieldGroup.fields.Add(GenSingleStructField(jobj[metaField.Name] as JObject, tableName, context, subMeta));
  172. }
  173. }
  174. }
  175. else
  176. {
  177. fieldGroup.fields.Add(new SerializableField()
  178. {
  179. fieldType = metaField.FieldType,
  180. fieldName = metaField.Name,
  181. isRepeated = metaField.StructRepeated,
  182. value = fieldVal
  183. });
  184. }
  185. }
  186. return fieldGroup;
  187. }
  188. private bool HasTableFlag(TableTag tag)
  189. {
  190. return AllowedTableTag == TableTag.All || tag.HasFlag(AllowedTableTag);
  191. }
  192. //private bool HasKeyValueFlag(KeyValueTag tag)
  193. //{
  194. // return AllowedKeyValueTag == KeyValueTag.All || tag.HasFlag(AllowedKeyValueTag);
  195. //}
  196. }
  197. }