// See https://aka.ms/new-console-template for more information using System.Collections.Immutable; using System.Reflection; using System.Text; var assemblyPath = args[0]; var targetPath = args[1]; var assembly = Assembly.LoadFrom(assemblyPath); var types = assembly.GetTypes().Where(t => t.FullName.StartsWith("DB.") && t.FullName.EndsWith("IDEnum")).ToImmutableList(); foreach (var type in types) { var tableRecordType = assembly.GetType(type.FullName.Replace("IDEnum", "TableRecord"))!; var patchClassName = $"patch_{type.Name}"; var readCommands = new StringBuilder(); var writeCommands = new StringBuilder(); var tableRecordFields = new StringBuilder(); foreach (var field in tableRecordType.GetFields(BindingFlags.Public | BindingFlags.Instance)) { tableRecordFields.Append("public "); if (field.FieldType.IsEnum) { tableRecordFields.Append("System.Int32 "); } else { tableRecordFields.Append(field.FieldType.FullName); tableRecordFields.Append(" "); } tableRecordFields.Append(field.Name); tableRecordFields.AppendLine(";"); readCommands.Append(field.Name) .Append(" = (") .Append(field.FieldType.FullName) .Append(")src[i].") .Append(field.Name) .Append(", "); writeCommands.Append(field.Name) .Append(" = (") .Append(field.FieldType.IsEnum ? "int" : field.FieldType.FullName) .Append(")src[i].") .Append(field.Name) .Append(", "); } using var sw = File.CreateText(Path.Combine(targetPath, patchClassName + ".cs")); sw.WriteLine($$""" // ReSharper disable CheckNamespace // ReSharper disable InconsistentNaming using System; using System.CodeDom.Compiler; using System.IO; using System.Text; using MonoMod; using LooseDBTables; using UnityEngine; namespace DB; [MonoModIgnore] [GeneratedCode("LooseDBTables.GeneratePatches", "1.0.0.0")] public class {{type.Name}} { public static extern bool LoadFromFile(string filename); public static extern void DumpToFile(string filename); protected static {{tableRecordType.Name}}[] records; } [GeneratedCode("LooseDBTables.GeneratePatches", "1.0.0.0")] [Serializable] public class Serializable{{tableRecordType.Name}} { {{tableRecordFields}} } [GeneratedCode("LooseDBTables.GeneratePatches", "1.0.0.0")] public class {{patchClassName}} : {{type.Name}} { public new static bool LoadFromFile(string filename) { if (!File.Exists(filename)) { return false; } var table = JsonUtility.FromJson>(File.ReadAllText(filename)); try { if (table.records.Length != records.Length) { Debug.LogError($"Count read error: {filename}"); return false; } var src = table.records; var dst = records; for (var i = 0; i < table.records.Length; i++) { dst[i] = new {{tableRecordType.Name}} { {{readCommands}} }; } } catch { Debug.LogError($"File read error: {filename}"); return false; } return true; } public new static void DumpToFile(string filename) { var table = new Table() { records = new Serializable{{tableRecordType.Name}}[records.Length] }; var src = records; var dst = table.records; for (var i = 0; i < records.Length; i++) { dst[i] = new Serializable{{tableRecordType.Name}} { {{writeCommands}} }; } File.WriteAllText(filename, JsonUtility.ToJson(table, true), Encoding.UTF8); } } """); } using var dbLoaderSw = File.CreateText(Path.Combine(targetPath, "DBLoader.cs")); dbLoaderSw.WriteLine($$""" // ReSharper disable CheckNamespace using System; using System.CodeDom.Compiler; using System.IO; using System.Text; namespace DB; [GeneratedCode("LooseDBTables.GeneratePatches", "1.0.0.0")] public class DBLoader { public static void LoadAll(string dirPath) { {{string.Join("\n", types.Select(t => $"{t.Name}.LoadFromFile(Path.Combine(dirPath, \"{t.Name.Replace("IDEnum", "TableRecord")}.json\"));"))}} } public static void DumpAll(string dirPath) { {{string.Join("\n", types.Select(t => $"{t.Name}.DumpToFile(Path.Combine(dirPath, \"{t.Name.Replace("IDEnum", "TableRecord")}.json\"));"))}} } } """);