178 lines
4.2 KiB
C#
178 lines
4.2 KiB
C#
using Godot;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Threading;
|
|
using BITKit.Entities;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace BITKit;
|
|
/// <summary>
|
|
/// 用于Godot的ECS.Entity实现
|
|
/// </summary>
|
|
public partial class Entity : Node,IEntity
|
|
{
|
|
/// <summary>
|
|
/// 类型组件的缓存
|
|
/// </summary>
|
|
private readonly Dictionary<Type,object> TypeComponents=new ();
|
|
|
|
private Object[] Components = Array.Empty<Object>();
|
|
/// <summary>
|
|
/// IEntityService的缓存
|
|
/// </summary>
|
|
private IEntitiesService _entitiesService;
|
|
/// <summary>
|
|
/// 所有EntityComponent
|
|
/// </summary>
|
|
IEntityComponent[] IEntity.Components => Components.OfType<IEntityComponent>().ToArray();
|
|
|
|
public void WaitForInitializationComplete()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// IEntity.Id实现
|
|
/// </summary>
|
|
public ulong Id { get; private set; }
|
|
|
|
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
|
|
private CancellationTokenSource _cancellationTokenSource;
|
|
|
|
|
|
/// <summary>
|
|
/// 服务提供者
|
|
/// </summary>
|
|
public IServiceProvider ServiceProvider { get; private set; }
|
|
/// <summary>
|
|
/// 服务集合
|
|
/// </summary>
|
|
public IServiceCollection ServiceCollection { get; private set; }
|
|
|
|
|
|
public void Inject(object node)
|
|
{
|
|
foreach (var fieldInfo in node.GetType()
|
|
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
|
.Where(x=>x.GetCustomAttribute<InjectAttribute>() is not null)
|
|
)
|
|
{
|
|
var attribute = fieldInfo.GetCustomAttribute<InjectAttribute>();
|
|
if(attribute is null)continue;
|
|
fieldInfo.SetValue(node,
|
|
attribute.CanBeNull
|
|
? ServiceProvider.GetService(fieldInfo.FieldType)
|
|
: ServiceProvider.GetRequiredService(fieldInfo.FieldType));
|
|
}
|
|
}
|
|
|
|
public override void _EnterTree()
|
|
{
|
|
_cancellationTokenSource = new CancellationTokenSource();
|
|
}
|
|
|
|
public override void _ExitTree()
|
|
{
|
|
_cancellationTokenSource.Cancel();
|
|
DI.Get<IEntitiesService>().UnRegister(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 加载所有EntityComponent的内部实现
|
|
/// </summary>
|
|
public override void _Ready()
|
|
{
|
|
Id = GetInstanceId();
|
|
|
|
ServiceCollection = new ServiceCollection();
|
|
|
|
DI.Get<IEntitiesService>().Register(this);
|
|
|
|
Components = MathNode.GetAllNode(this).ToArray();
|
|
List<IEntityComponent> entityComponents = new();
|
|
|
|
_entitiesService = DI.Get<IEntitiesService>();
|
|
|
|
foreach (var x in Components)
|
|
{
|
|
GetInstanceId();
|
|
|
|
if (x is IEntityComponent entityComponent)
|
|
{
|
|
entityComponent.BuildService(ServiceCollection);
|
|
}
|
|
|
|
TypeComponents.TryAdd(x.GetType(), x);
|
|
foreach (var customType in x.GetType().GetCustomAttributes<CustomTypeAttribute>())
|
|
{
|
|
TypeComponents.TryAdd(customType.Type, x);
|
|
ServiceCollection.AddSingleton(customType.Type, x);
|
|
}
|
|
|
|
ServiceProvider = ServiceCollection.BuildServiceProvider();
|
|
|
|
if (x is not IEntityComponent component) continue;
|
|
component.Entity = this;
|
|
entityComponents.Add(component);
|
|
}
|
|
|
|
foreach (var node in Components)
|
|
{
|
|
Inject(node);
|
|
}
|
|
foreach (var component in Components.OfType<IEntityBehavior>())
|
|
{
|
|
component.Initialize(this);
|
|
}
|
|
foreach (var component in Components.OfType<IEntityBehavior>())
|
|
{
|
|
component.OnAwake();
|
|
}
|
|
foreach (var component in Components.OfType<IEntityBehavior>())
|
|
{
|
|
component.OnStart();
|
|
}
|
|
}
|
|
|
|
public override void _Process(double delta)
|
|
{
|
|
foreach (var component in Components.OfType<IEntityBehavior>())
|
|
{
|
|
component.OnUpdate((float)delta);
|
|
}
|
|
foreach (var component in Components.OfType<IEntityBehavior>())
|
|
{
|
|
component.OnLateUpdate((float)delta);
|
|
}
|
|
}
|
|
|
|
public override void _PhysicsProcess(double delta)
|
|
{
|
|
foreach (var component in Components.OfType<IEntityBehavior>())
|
|
{
|
|
component.OnFixedUpdate((float)delta);
|
|
}
|
|
}
|
|
|
|
public bool TryGetComponent<T>(out T component)
|
|
{
|
|
if (TypeComponents.TryGetValue(typeof(T), out var iComponent) && iComponent is T _component)
|
|
{
|
|
component = _component;
|
|
return true;
|
|
}
|
|
component = default;
|
|
return false;
|
|
}
|
|
|
|
public bool RegisterComponent<T>(T component)
|
|
{
|
|
return TypeComponents.TryAdd(typeof(T), component);
|
|
}
|
|
|
|
|
|
}
|