2023-07-18 16:42:33 +08:00
|
|
|
using System;
|
|
|
|
using Godot;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Threading;
|
2023-11-02 20:58:36 +08:00
|
|
|
using BITKit.Entities;
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
2023-07-18 16:42:33 +08:00
|
|
|
|
|
|
|
namespace BITKit;
|
|
|
|
/// <summary>
|
|
|
|
/// 基于Godot.Node的IEntitiesService实现
|
|
|
|
/// </summary>
|
|
|
|
public partial class GodotEntitiesService : Node,IEntitiesService
|
|
|
|
{
|
|
|
|
public GodotEntitiesService()
|
|
|
|
{
|
|
|
|
DI.Register<IEntitiesService>(this);
|
|
|
|
}
|
|
|
|
private readonly Dictionary<ulong,IEntity> _entities=new ();
|
|
|
|
private CancellationTokenSource _cancellationTokenSource;
|
2023-08-18 11:03:06 +08:00
|
|
|
public event Action<IEntity> OnAdd;
|
|
|
|
public event Action<IEntity> OnRemove;
|
2023-07-18 16:42:33 +08:00
|
|
|
public IEntity[] Entities => _entities.Values.ToArray();
|
|
|
|
public bool Register(IEntity entity)
|
|
|
|
{
|
2023-11-02 20:58:36 +08:00
|
|
|
entity.ServiceCollection.AddSingleton<IEntitiesService>(this);
|
2023-07-18 16:42:33 +08:00
|
|
|
return _entities.TryAdd(entity.Id, entity);
|
|
|
|
}
|
|
|
|
public bool UnRegister(IEntity entity)
|
|
|
|
{
|
|
|
|
return _entities.TryRemove(entity.Id);
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void _Ready()
|
|
|
|
{
|
|
|
|
_cancellationTokenSource = new();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override void Dispose(bool disposing)
|
|
|
|
{
|
|
|
|
if(disposing)_cancellationTokenSource.Cancel();
|
|
|
|
}
|
|
|
|
|
|
|
|
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
|
|
|
|
|
2023-08-18 11:03:06 +08:00
|
|
|
public IEntity Get(ulong id)
|
|
|
|
{
|
|
|
|
throw new NotImplementedException();
|
|
|
|
}
|
|
|
|
|
2024-04-16 04:15:21 +08:00
|
|
|
public bool TryGetEntity(ulong id, out IEntity entity)
|
|
|
|
{
|
|
|
|
return _entities.TryGetValue(id, out entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
public IEntity GetOrAdd(ulong id, Func<ulong, IEntity> factory)
|
|
|
|
{
|
|
|
|
if (_entities.TryGetValue(id, out var entity))
|
|
|
|
{
|
|
|
|
return entity;
|
|
|
|
}
|
|
|
|
entity = factory(id);
|
|
|
|
Register(entity);
|
|
|
|
return entity;
|
|
|
|
}
|
|
|
|
|
2023-09-15 23:02:46 +08:00
|
|
|
public IEntity[] Query<T>()
|
2023-07-18 16:42:33 +08:00
|
|
|
{
|
|
|
|
return _entities.Values.Where(x => x.TryGetComponent<T>(out _)).ToArray();
|
|
|
|
}
|
|
|
|
|
2023-08-18 11:03:06 +08:00
|
|
|
T[] IEntitiesService.QueryComponents<T>()
|
|
|
|
{
|
|
|
|
return _entities.Values
|
|
|
|
.Where(x => x.TryGetComponent<T>(out _))
|
|
|
|
.Select(x =>
|
|
|
|
{
|
|
|
|
var component = x.Components.Single(x => x is T);
|
|
|
|
return (T)component;
|
|
|
|
})
|
|
|
|
.ToArray();
|
|
|
|
}
|
|
|
|
|
2023-07-18 16:42:33 +08:00
|
|
|
public ValueTuple<T>[] QueryComponents<T>() where T : IEntityComponent
|
|
|
|
{
|
|
|
|
return _entities.Values
|
|
|
|
.Where(x => x.TryGetComponent<T>(out _))
|
|
|
|
.Select(x =>
|
|
|
|
{
|
|
|
|
var component = x.Components.Single(x => x is T);
|
|
|
|
return (T)component;
|
|
|
|
})
|
|
|
|
.Select(x => new ValueTuple<T>(x))
|
|
|
|
.ToArray();
|
|
|
|
}
|
2023-09-15 23:02:46 +08:00
|
|
|
public (T, T1)[] QueryComponents<T, T1>()
|
2023-07-18 16:42:33 +08:00
|
|
|
{
|
|
|
|
var entities = _entities.Values.Where(x => x.TryGetComponent<T>(out _) && x.TryGetComponent<T1>(out _));
|
|
|
|
var result = new List<(T, T1)>();
|
|
|
|
foreach (var entity in entities)
|
|
|
|
{
|
|
|
|
var t = (T)entity.Components.Single(x => x is T);
|
|
|
|
var t1 = (T1)entity.Components.Single(x => x is T1);
|
|
|
|
result.Add(new(t,t1));
|
|
|
|
}
|
|
|
|
return result.ToArray();
|
|
|
|
}
|
|
|
|
|
2023-09-15 23:02:46 +08:00
|
|
|
public (T, T1, T2)[] QueryComponents<T, T1, T2>()
|
2023-07-18 16:42:33 +08:00
|
|
|
{
|
|
|
|
return _entities.Values
|
|
|
|
.Where(x => x.TryGetComponent<T>(out _) && x.TryGetComponent<T1>(out _) && x.TryGetComponent<T2>(out _))
|
|
|
|
.Select(x =>
|
|
|
|
{
|
|
|
|
var component = (T)x.Components.Single(x => x is T);
|
|
|
|
var component1 = (T1)x.Components.Single(x => x is T1);
|
|
|
|
var component2 = (T2)x.Components.Single(x => x is T2);
|
|
|
|
(T, T1, T2) value = new(component, component1, component2);
|
|
|
|
return value;
|
|
|
|
})
|
|
|
|
.ToArray();
|
|
|
|
}
|
|
|
|
}
|