using System.CodeDom; using System.CodeDom.Compiler; using System.IO; using System.Linq; using RobocraftX.Common; using Svelto.ECS; using Techblox.EngineBlock; namespace CodeGenerator { public class BlockClassGenerator { public void Generate(string name, string group) { if (group is null) { group = GetGroup(name) + "_BLOCK_GROUP"; if (typeof(CommonExclusiveGroups).GetFields().All(field => field.Name != group)) group = GetGroup(name) + "_BLOCK_BUILD_GROUP"; } var codeUnit = new CodeCompileUnit(); var ns = new CodeNamespace("TechbloxModdingAPI.Blocks"); ns.Imports.Add(new CodeNamespaceImport("RobocraftX.Common")); ns.Imports.Add(new CodeNamespaceImport("Svelto.ECS")); var cl = new CodeTypeDeclaration(name); cl.BaseTypes.Add(new CodeTypeReference("Block")); cl.Members.Add(new CodeConstructor { Parameters = {new CodeParameterDeclarationExpression("EGID", "egid")}, Comments = {new CodeCommentStatement($"{name} constructor", true)}, BaseConstructorArgs = {new CodeVariableReferenceExpression("egid")} }); cl.Members.Add(new CodeConstructor { Parameters = { new CodeParameterDeclarationExpression(typeof(uint), "id") }, Comments = {new CodeCommentStatement($"{name} constructor", true)}, BaseConstructorArgs = { new CodeObjectCreateExpression("EGID", new CodeVariableReferenceExpression("id"), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("CommonExclusiveGroups"), group)) } }); GenerateProperties(cl); ns.Types.Add(cl); codeUnit.Namespaces.Add(ns); var provider = CodeDomProvider.CreateProvider("CSharp"); using (var sw = new StreamWriter($"{name}.cs")) { provider.GenerateCodeFromCompileUnit(codeUnit, sw, new CodeGeneratorOptions {BracingStyle = "C"}); } } private static string GetGroup(string name) { var ret = ""; foreach (var ch in name) { if (char.IsUpper(ch) && ret.Length > 0) ret += "_" + ch; else ret += char.ToUpper(ch); } return ret; } private void GenerateProperties(CodeTypeDeclaration cl) where T : IEntityComponent { var type = typeof(T); foreach (var field in type.GetFields()) { var propName = char.ToUpper(field.Name[0]) + field.Name.Substring(1); var structFieldReference = new CodeFieldReferenceExpression(new CodeMethodInvokeExpression( new CodeMethodReferenceExpression(new CodeSnippetExpression("BlockEngine"), "GetBlockInfo", new CodeTypeReference(type)), new CodeThisReferenceExpression()), field.Name); cl.Members.Add(new CodeMemberProperty { Name = propName, HasGet = true, HasSet = true, GetStatements = { new CodeMethodReturnStatement(structFieldReference) }, SetStatements = { new CodeAssignStatement(structFieldReference, new CodePropertySetValueReferenceExpression()) }, Type = new CodeTypeReference(field.FieldType) }); } } } }