namespace OECS; /// /// The central container for all ECS state. /// /// Manages entity lifecycle, component storage, and provides the primary /// API for adding, removing, and querying components. /// public class World : IDisposable { private readonly EntityAllocator _allocator; private readonly ComponentStore _components; public World() { _allocator = new EntityAllocator(); _components = new ComponentStore(); } // ── Entity Management ──────────────────────────────────────────── /// /// Creates a new entity and returns its handle. /// public Entity CreateEntity() { return _allocator.Allocate(); } /// /// Destroys an entity, removing all its components and recycling its ID. /// public void DestroyEntity(Entity entity) { if (!_allocator.IsAlive(entity)) return; // Singleton entity is never destroyed. if (entity.Id == 1) return; _components.RemoveAll(entity); _allocator.Free(entity); } /// /// Returns true if the entity is currently alive (not destroyed). /// public bool IsAlive(Entity entity) { return _allocator.IsAlive(entity); } // ── Component Management ───────────────────────────────────────── /// /// Adds a component to the entity. Replaces the existing component if /// the entity already has one of type . /// public void AddComponent(Entity entity, T component) where T : struct { ThrowIfNotAlive(entity); _components.Add(entity, component); } /// /// Removes the component of type from the entity. /// No-op if the entity does not have the component. /// public void RemoveComponent(Entity entity) where T : struct { _components.Remove(entity); } /// /// Returns a reference to the component of type /// for the given entity. Throws if the entity does not have the component. /// public ref T GetComponent(Entity entity) where T : struct { return ref _components.Get(entity); } /// /// Returns true if the entity has a component of type . /// public bool HasComponent(Entity entity) where T : struct { return _components.Has(entity); } // ── Queries ────────────────────────────────────────────────────── /// /// Returns a new for constructing queries. /// public QueryBuilder Query() => new(); /// /// Iterates all entities matching the query, providing ref access to /// one component type. /// public void ForEach( QueryDescriptor query, ForEachAction action) where T1 : struct { QueryExecutor.ForEach(_components, query, action); } /// /// Iterates all entities matching the query, providing ref access to /// two component types. /// public void ForEach( QueryDescriptor query, ForEachAction action) where T1 : struct where T2 : struct { QueryExecutor.ForEach(_components, query, action); } /// /// Iterates all entities matching the query, providing ref access to /// three component types. /// public void ForEach( QueryDescriptor query, ForEachAction action) where T1 : struct where T2 : struct where T3 : struct { QueryExecutor.ForEach(_components, query, action); } /// /// Iterates all entities matching the query, providing ref access to /// four component types. /// public void ForEach( QueryDescriptor query, ForEachAction action) where T1 : struct where T2 : struct where T3 : struct where T4 : struct { QueryExecutor.ForEach(_components, query, action); } /// /// Iterates all entities matching the query, providing ref access to /// five component types. /// public void ForEach( QueryDescriptor query, ForEachAction action) where T1 : struct where T2 : struct where T3 : struct where T4 : struct where T5 : struct { QueryExecutor.ForEach(_components, query, action); } /// /// Iterates all entities matching the query, providing ref access to /// six component types. /// public void ForEach( QueryDescriptor query, ForEachAction action) where T1 : struct where T2 : struct where T3 : struct where T4 : struct where T5 : struct where T6 : struct { QueryExecutor.ForEach(_components, query, action); } // ── Internal Access ─────────────────────────────────────────────── /// /// The component store. Exposed internally for query execution and /// system infrastructure. /// internal ComponentStore Components => _components; // ── Helpers ─────────────────────────────────────────────────────── private void ThrowIfNotAlive(Entity entity) { if (!_allocator.IsAlive(entity)) throw new InvalidOperationException($"Entity {entity} is not alive."); } // ── Cleanup ─────────────────────────────────────────────────────── public void Dispose() { // Future: dispose R3 subscriptions, etc. } }