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>(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(); foreach (var field in componentType.GetFields()) { var attr = field.GetCustomAttribute(); 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(); } } }