k/ECS/Core/World.cs
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sandbox.k.ECS.Core;
public class World
{
private EntityManager _entityManager = new EntityManager();
private ComponentStorageContainer _componentStorages = new ComponentStorageContainer();
private static World _default;
public ComponentStorageContainer ComponentStorages => _componentStorages;
public EntityManager EntityManager => _entityManager;
public static World Default => _default ??= new World();
public static void ResetDefault() => _default = new World();
// Entity management
public int CreateEntity() => _entityManager.CreateEntity();
public void DestroyEntity(int entity)
{
if (!_entityManager.IsAlive(entity)) return;
foreach ( var (_, storage) in _componentStorages.Values )
{
storage.Remove( entity );
}
_entityManager.DestroyEntity(entity);
}
// Component management
public void AddComponent<T>(int entity, T component)
{
var storage = GetOrCreateStorage<T>();
if ( storage == null )
{
Log.Error( $"No storage for component type {typeof(T).Name}" );
return;
}
storage.Add(entity, component);
}
public void RemoveComponent<T>(int entity)
{
if (HasComponent<T>(entity))
GetStorage<T>().Remove(entity);
}
public bool HasComponent(Type type, int entity)
{
if (!_componentStorages.TryGetValue(type, out var storage))
return false;
return storage.Has(entity);
}
public bool HasComponent<T>(int entity)
{
if (!_componentStorages.TryGetValue(typeof(T), out var storage))
return false;
return storage.Has(entity);
}
public T GetComponent<T>(int entity)
{
return GetStorage<T>().Get(entity);
}
public ref T GetComponentRef<T>(int entity)
{
return ref GetStorage<T>().GetRef(entity);
}
// Storage management
private ComponentStorage<T> GetStorage<T>()
{
if (!_componentStorages.TryGetValue(typeof(T), out var storage))
throw new KeyNotFoundException($"No storage for component type {typeof(T).Name}");
return (ComponentStorage<T>)storage;
}
private ComponentStorage<T> GetOrCreateStorage<T>()
{
if (!_componentStorages.TryGetValue(typeof(T), out var storage))
{
var instance = new ComponentStorage<T>();
storage = instance;
_componentStorages.AddStorage( instance );
}
return (ComponentStorage<T>)storage;
}
// Systems query shortcuts
public IEnumerable<int> GetEntitiesWith<T>()
{
if (!_componentStorages.TryGetValue(typeof(T), out var storage))
return Enumerable.Empty<int>();
return ((ComponentStorage<T>)storage).GetAllEntities();
}
public IEnumerable<int> GetEntitiesWithout<T>()
{
var entities = new HashSet<int>();
foreach ( var (key, storage) in _componentStorages.Values )
{
if ( key == typeof(T) ) continue;
var loopEntities = storage.GetAllEntities();
foreach ( var entity in loopEntities )
{
entities.Add( entity );
}
}
return entities;
}
public IEnumerable<int> GetEntitiesWith<T1, T2>()
{
return GetEntitiesWith<T1>().Intersect(GetEntitiesWith<T2>());
}
public IEnumerable<int> GetFilter(IEnumerable<int> withFilter, IEnumerable<int> withoutFilter)
{
return withFilter.Except(withoutFilter);
}
}