using System; using System.Collections.Generic; using gaemstone.Utility; using static flecs_hub.flecs; namespace gaemstone.ECS; public unsafe partial class World { private readonly Dictionary _lookupByType = new(); public void AddLookupByType(Type type, Entity entity) { // If an existing lookup already exists with the same entity, don't throw an exception. if (_lookupByType.TryGetValue(type, out var existing) && (existing == entity)) return; _lookupByType.Add(type, entity); } public void RemoveLookupByType(Type type) { if (!_lookupByType.Remove(type)) throw new InvalidOperationException( $"Lookup for {type} does not exist"); } public EntityRef? LookupByType() => LookupByType(typeof(T)); public EntityRef? LookupByType(Type type) => LookupAlive(_lookupByType.GetValueOrDefault(type)); public EntityRef LookupByTypeOrThrow() => LookupByTypeOrThrow(typeof(T)); public EntityRef LookupByTypeOrThrow(Type type) => LookupByType(type) ?? throw new EntityNotFoundException( $"Entity of type {type} not found"); public EntityRef? LookupAlive(Entity value) => EntityRef.CreateOrNull(this, new(ecs_get_alive(this, value))); public EntityRef LookupAliveOrThrow(Entity entity) => LookupAlive(entity) ?? throw new EntityNotFoundException( $"Entity {entity} is not alive"); public EntityRef? LookupByPath(EntityPath path) => LookupByPath(default, path); public EntityRef? LookupByPath(Entity parent, EntityPath path) => EntityRef.CreateOrNull(this, EntityPath.Lookup(this, parent, path, false)); public EntityRef LookupByPathOrThrow(EntityPath path) => LookupByPathOrThrow(default, path); public EntityRef LookupByPathOrThrow(Entity parent, EntityPath path) => new(this, EntityPath.Lookup(this, parent, path, true)); public EntityRef? LookupBySymbol(string symbol) { using var alloc = TempAllocator.Use(); var entity = ecs_lookup_symbol(this, alloc.AllocateCString(symbol), false); return EntityRef.CreateOrNull(this, new(entity)); } public EntityRef LookupBySymbolOrThrow(string symbol) => LookupBySymbol(symbol) ?? throw new EntityNotFoundException( $"Entity with symbol '{symbol}' not found"); public class EntityNotFoundException : Exception { public EntityNotFoundException(string message) : base(message) { } } } public static class LookupExtensions { public static EntityRef CreateLookup(this EntityRef entity) => entity.CreateLookup(typeof(T)); public static EntityRef CreateLookup(this EntityRef entity, Type type) { entity.World.AddLookupByType(type, entity); return entity; } }