TechbloxModdingAPI/CodeGenerator/ECSAnalyzer.cs

67 lines
2.7 KiB
C#

using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Gamecraft.Tweaks;
using HarmonyLib;
using Svelto.ECS;
namespace CodeGenerator
{
public static class ECSAnalyzer
{
public static ECSClassInfo AnalyzeEntityDescriptor(Type entityDescriptorType)
{
// TODO: Add support for creating/deleting entities (getting an up to date server/client engines root)
var templateType = typeof(EntityDescriptorTemplate<>).MakeGenericType(entityDescriptorType);
var templateDescriptor = AccessTools.Property(templateType, "descriptor");
var getDescriptorExpr = Expression.MakeMemberAccess(null, templateDescriptor ?? throw new InvalidOperationException());
var getTemplateDescriptorExpr =
Expression.Lambda<Func<IEntityDescriptor>>(getDescriptorExpr);
var getTemplateDescriptor = getTemplateDescriptorExpr.Compile();
// TODO: Crashes on constructing the descriptor type. Maybe move the analysis part to a mod.
var builders = getTemplateDescriptor().componentsToBuild;
return new ECSClassInfo
{
Name = entityDescriptorType.Name.Replace("EntityComponent", "").Replace("EntityStruct", ""),
Properties = builders.Select(builder => builder.GetEntityComponentType()).SelectMany(AnalyzeFields).ToArray()
};
}
private static ECSPropertyInfo[] AnalyzeFields(Type componentType)
{
bool useReflection = componentType.IsNotPublic;
var result = new List<ECSPropertyInfo>();
foreach (var field in componentType.GetFields())
{
var attr = field.GetCustomAttribute<TweakableStatAttribute>();
string propName = field.Name;
if (attr != null)
propName = attr.propertyName;
propName = char.ToUpper(propName[0]) + propName[1..];
if (useReflection)
{
result.Add(new ECSReflectedPropertyInfo
{
Name = propName,
Type = field.FieldType,
OriginalClassName = componentType.FullName,
ComponentType = componentType
});
}
result.Add(new ECSPropertyInfo
{
Name = propName,
Type = field.FieldType,
ComponentType = componentType
});
}
return result.ToArray();
}
}
}