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; /// /// 用于Godot的ECS.Entity实现 /// public partial class Entity : Node,IEntity { /// /// 类型组件的缓存 /// private readonly Dictionary TypeComponents=new (); private Object[] Components = Array.Empty(); /// /// IEntityService的缓存 /// private IEntitiesService _entitiesService; /// /// 所有EntityComponent /// IEntityComponent[] IEntity.Components => Components.OfType().ToArray(); public void WaitForInitializationComplete() { throw new NotImplementedException(); } /// /// IEntity.Id实现 /// public ulong Id { get; private set; } public CancellationToken CancellationToken => _cancellationTokenSource.Token; private CancellationTokenSource _cancellationTokenSource; /// /// 服务提供者 /// public IServiceProvider ServiceProvider { get; private set; } /// /// 服务集合 /// 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() is not null) ) { var attribute = fieldInfo.GetCustomAttribute(); 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().UnRegister(this); } /// /// 加载所有EntityComponent的内部实现 /// public override void _Ready() { Id = GetInstanceId(); ServiceCollection = new ServiceCollection(); DI.Get().Register(this); Components = MathNode.GetAllNode(this).ToArray(); List entityComponents = new(); _entitiesService = DI.Get(); 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()) { 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()) { component.Initialize(this); } foreach (var component in Components.OfType()) { component.OnAwake(); } foreach (var component in Components.OfType()) { component.OnStart(); } } public override void _Process(double delta) { foreach (var component in Components.OfType()) { component.OnUpdate((float)delta); } foreach (var component in Components.OfType()) { component.OnLateUpdate((float)delta); } } public override void _PhysicsProcess(double delta) { foreach (var component in Components.OfType()) { component.OnFixedUpdate((float)delta); } } public bool TryGetComponent(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 component) { return TypeComponents.TryAdd(typeof(T), component); } }