|
- using System;
- using System.CodeDom;
- using System.CodeDom.Compiler;
- using System.IO;
- using System.Linq;
-
- namespace CodeGenerator
- {
- public static class ECSClassGenerator
- {
- public static void Generate(Type entityDescriptorType)
- {
- var info = ECSAnalyzer.AnalyzeEntityDescriptor(entityDescriptorType);
-
- 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(info.Name);
- cl.BaseTypes.Add(new CodeTypeReference("SignalingBlock"));
- cl.Members.Add(new CodeConstructor
- {
- Parameters = {new CodeParameterDeclarationExpression("EGID", "egid")},
- Comments =
- {
- _start,
- new CodeCommentStatement($"Constructs a(n) {info.Name} object representing an existing block.", true),
- _end
- },
- BaseConstructorArgs = {new CodeVariableReferenceExpression("egid")},
- Attributes = MemberAttributes.Public | MemberAttributes.Final
- });
- foreach (var propertyInfo in info.Properties)
- {
- if (propertyInfo is ECSReflectedPropertyInfo reflectedPropertyInfo)
- GenerateReflectedProperty(reflectedPropertyInfo, cl);
- else
- GenerateProperty(propertyInfo, cl);
- }
- ns.Types.Add(cl);
- codeUnit.Namespaces.Add(ns);
-
- var provider = CodeDomProvider.CreateProvider("CSharp");
- var path = $"../../../../TechbloxModdingAPI/Blocks/{info.Name}.cs";
- using (var sw = new StreamWriter(path))
- {
- provider.GenerateCodeFromCompileUnit(codeUnit, sw, new CodeGeneratorOptions {BracingStyle = "C"});
- }
-
- File.WriteAllLines(path,
- File.ReadAllLines(path).SkipWhile(line => line.StartsWith("//") || line.Length == 0));
- }
-
- private static void GenerateProperty(ECSPropertyInfo info, CodeTypeDeclaration cl)
- {
- var getStruct = new CodeMethodInvokeExpression(
- new CodeMethodReferenceExpression(new CodeSnippetExpression("BlockEngine"),
- "GetBlockInfo", new CodeTypeReference(info.ComponentType)),
- new CodeThisReferenceExpression());
- CodeExpression structFieldReference = new CodeFieldReferenceExpression(getStruct, info.Name);
- cl.Members.Add(new CodeMemberProperty
- {
- Name = info.Name,
- HasGet = true,
- HasSet = true,
- GetStatements =
- {
- new CodeMethodReturnStatement(structFieldReference)
- },
- SetStatements =
- {
- new CodeAssignStatement(structFieldReference, new CodePropertySetValueReferenceExpression())
- },
- Type = new CodeTypeReference(info.Type),
- Attributes = MemberAttributes.Public | MemberAttributes.Final,
- Comments =
- {
- _start,
- new CodeCommentStatement($"Gets or sets the {info.ComponentType.Name}'s {info.Name} property." +
- " May not be saved.", // TODO: Doesn't know if tweakable stat
- true),
- _end
- }
- });
- }
-
- private static void GenerateReflectedProperty(ECSReflectedPropertyInfo info, CodeTypeDeclaration cl)
- {
- var reflectedType = new CodeSnippetExpression($"HarmonyLib.AccessTools.TypeByName(\"{info.OriginalClassName}\")");
-
- CodeExpression reflectedGet = new CodeCastExpression(info.Type, new CodeMethodInvokeExpression(
- new CodeMethodReferenceExpression(new CodeSnippetExpression("BlockEngine"),
- "GetBlockInfo"),
- new CodeThisReferenceExpression(), reflectedType, new CodePrimitiveExpression(info.Name)));
- CodeExpression reflectedSet = new CodeMethodInvokeExpression(
- new CodeMethodReferenceExpression(new CodeSnippetExpression("BlockEngine"),
- "SetBlockInfo"),
- new CodeThisReferenceExpression(), reflectedType, new CodePrimitiveExpression(info.Name),
- new CodePropertySetValueReferenceExpression());
- cl.Members.Add(new CodeMemberProperty
- {
- Name = info.Name,
- HasGet = true,
- HasSet = true,
- GetStatements =
- {
- new CodeMethodReturnStatement(reflectedGet)
- },
- SetStatements =
- {
- (CodeStatement)new CodeExpressionStatement(reflectedSet)
- },
- Type = new CodeTypeReference(info.Type),
- Attributes = MemberAttributes.Public | MemberAttributes.Final,
- Comments =
- {
- _start,
- new CodeCommentStatement($"Gets or sets the {info.ComponentType.Name}'s {info.Name} property." +
- " May not be saved.", // TODO: Doesn't know if tweakable stat
- true),
- _end
- }
- });
- }
-
- private static readonly CodeCommentStatement _start = new("<summary>", true);
- private static readonly CodeCommentStatement _end = new("</summary>", true);
- }
- }
|