using System;
using System.Linq.Expressions;
using Svelto.DataStructures;
using Svelto.ECS;
using Svelto.ECS.Internal;
using TechbloxModdingAPI.Blocks;
namespace TechbloxModdingAPI
{
public abstract class EcsObjectBase
{
public abstract EGID Id { get; } //Abstract to support the 'place' Block constructor
protected internal EcsInitData InitData;
///
/// Holds information needed to construct a component initializer
///
protected internal struct EcsInitData
{
private FasterDictionary group;
private EntityReference reference;
public static implicit operator EcsInitData(EntityInitializer initializer) => new EcsInitData
{group = GetInitGroup(initializer), reference = initializer.reference};
public EntityInitializer Initializer(EGID id) => new EntityInitializer(id, group, reference);
public bool Valid => group != null;
}
private delegate FasterDictionary GetInitGroupFunc(
EntityInitializer initializer);
///
/// Accesses the group field of the initializer
///
private static GetInitGroupFunc GetInitGroup = CreateAccessor("_group");
//https://stackoverflow.com/questions/55878525/unit-testing-ref-structs-with-private-fields-via-reflection
private static TDelegate CreateAccessor(string memberName) where TDelegate : Delegate
{
var invokeMethod = typeof(TDelegate).GetMethod("Invoke");
if (invokeMethod == null)
throw new InvalidOperationException($"{typeof(TDelegate)} signature could not be determined.");
var delegateParameters = invokeMethod.GetParameters();
if (delegateParameters.Length != 1)
throw new InvalidOperationException("Delegate must have a single parameter.");
var paramType = delegateParameters[0].ParameterType;
var objParam = Expression.Parameter(paramType, "obj");
var memberExpr = Expression.PropertyOrField(objParam, memberName);
Expression returnExpr = memberExpr;
if (invokeMethod.ReturnType != memberExpr.Type)
returnExpr = Expression.ConvertChecked(memberExpr, invokeMethod.ReturnType);
var lambda =
Expression.Lambda(returnExpr, $"Access{paramType.Name}_{memberName}", new[] {objParam});
return lambda.Compile();
}
}
}