2023-10-04 00:36:25 +00:00
|
|
|
using System;
|
|
|
|
using System.CodeDom;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Linq.Expressions;
|
|
|
|
using System.Reflection;
|
|
|
|
using Gamecraft.Tweaks;
|
2023-10-07 23:55:50 +00:00
|
|
|
using HarmonyLib;
|
2023-10-04 00:36:25 +00:00
|
|
|
using Svelto.ECS;
|
|
|
|
|
|
|
|
namespace CodeGenerator
|
|
|
|
{
|
2023-10-07 23:55:50 +00:00
|
|
|
public static class ECSAnalyzer
|
2023-10-04 00:36:25 +00:00
|
|
|
{
|
|
|
|
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);
|
2023-10-07 23:55:50 +00:00
|
|
|
var templateDescriptor = AccessTools.Property(templateType, "descriptor");
|
|
|
|
var getDescriptorExpr = Expression.MakeMemberAccess(null, templateDescriptor ?? throw new InvalidOperationException());
|
2023-10-04 00:36:25 +00:00
|
|
|
var getTemplateDescriptorExpr =
|
|
|
|
Expression.Lambda<Func<IEntityDescriptor>>(getDescriptorExpr);
|
|
|
|
var getTemplateDescriptor = getTemplateDescriptorExpr.Compile();
|
2023-10-07 23:55:50 +00:00
|
|
|
// TODO: Crashes on constructing the descriptor type. Maybe move the analysis part to a mod.
|
2023-10-04 00:36:25 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|