TechbloxModdingAPI/CodeGenerator/BlockClassGenerator.cs

101 lines
3.9 KiB
C#

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<EngineBlockComponent>(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<T>(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)
});
}
}
}
}