namespace Theater_ECS; using System; using System.Threading; using System.Collections; class ComponentManager { private Monitor _Lock = new .() ~ delete _; private int_cosize _ComponentSize = -1; private readonly int _IndexSize = sizeof(int_cosize); private int_cosize _Next = 0; private List _Data = null ~ delete _; private List _Available = new .() ~ delete _; private HashSet _Deleted = new .() ~ delete _; ///Make the component manager useable for a specific type of component public void Initialize(int_cosize count) where T : struct { _ComponentSize = sizeof(T); _Data = new .( //So that we dont have to realloc as frequently (_IndexSize + _ComponentSize) * count ); } ///Creates space for a new component instance and returns a pointer to it public (Component, void*) Create(Entity owner) { if (_Available.Count > 0) { var idx = _Available.PopFront(); _Deleted.Remove(idx); *(int_cosize*)(void*)&_Data[idx * (_ComponentSize + _IndexSize)] = owner; void* toReturn = (void*)&_Data[idx * (_ComponentSize + _IndexSize) + _IndexSize]; return ( idx, toReturn ); } else { Grow(); *(int_cosize*)(void*)(_Data.Ptr + (_Next * (_ComponentSize + _IndexSize))) = owner; //This calculates to the next biggest position + the offset of the index void* toReturn = (void*)(_Data.Ptr + (_Next * (_ComponentSize + _IndexSize) + _IndexSize)); return ( _Next++, toReturn ); } } ///Remove an entry, and returns a pointer to the removed object, if you want to public Result Remove(int_cosize idx) { if (idx >= _Next || _Deleted.Contains(idx)) return .Err; *(int_cosize*)(void*)&_Data[idx * (_ComponentSize + _IndexSize)] = -1; _Deleted.Add(idx); return .Ok( (void*)(_Data.Ptr + idx * (_ComponentSize + _IndexSize) + _IndexSize) ); } public int_cosize Count { get { return (.)(_Data.Count / (_ComponentSize + _IndexSize)); } } public Span<(Entity, T)> GetAll() where T : struct { return .((.)(void*)_Data.Ptr, Count); } [Unchecked] public T* Get(int_cosize idx) where T : struct { return (T*)(void*)(_Data.Ptr + idx * (_ComponentSize + _IndexSize) + _IndexSize); } [Unchecked] public void GetEntities(List list) { var ec = (_Data.Count / (_ComponentSize + _IndexSize)); list.GrowUninitialized(ec); for (int i < ec) *(list.Ptr + (i)) = *(Entity*)(void*)(_Data.Ptr +i * (_ComponentSize + _IndexSize)); } public void Use() => _Lock.Enter(); public void StopUsing() => _Lock.Exit(); public void Grow(int_cosize amount = 1) { //Make more size useable _Data.GrowUninitialized((_ComponentSize + _IndexSize) * amount); } }