#ifndef CORE_COMPONENTS_HPP #define CORE_COMPONENTS_HPP #include "core/data/HashMap.hpp" namespace Core { using Entity = int; template class Components final { HashMap entityToIndex{}; List indexToEntity{}; List components{}; public: template struct Node final { const Entity& entity; R& component; }; template class EntityIterator final { C& components; i64 index; public: EntityIterator(C& components_, i64 index_) : components(components_), index(index_) { } EntityIterator& operator++() { index++; return *this; } bool operator!=(const EntityIterator& other) const { return index != other.index; } Node operator*() const { return {components.indexToEntity[index], components.components[index]}; } }; template struct EntityIteratorAdapter final { C& components; EntityIterator begin() { return EntityIterator(components, 0); } EntityIterator end() { return EntityIterator(components, components.components.getLength()); } }; template check_return Error put(T*& t, Entity ent, Args&&... args) { i64 index = components.getLength(); i64* indexP = nullptr; CORE_RETURN_ERROR(entityToIndex.tryEmplace(indexP, ent, index)); Error e = Error::NONE; if(checkError(e, indexToEntity.add(ent))) { (void)entityToIndex.remove(ent); return e; } if(checkError(e, components.put(t, Core::forward(args)...))) { (void)entityToIndex.remove(ent); (void)indexToEntity.removeLast(); } return e; } template check_return Error add(Entity e, Args&&... args) { T* t = nullptr; return put(t, e, Core::forward(args)...); } check_return Error remove(Entity ent) { i64* indexP = entityToIndex.search(ent); if(indexP == nullptr) { return Error::NOT_FOUND; } i64 lastIndex = components.getLength() - 1; i64 index = *indexP; CORE_RETURN_ERROR(entityToIndex.remove(ent)); CORE_RETURN_ERROR(components.removeBySwap(index)); if(index == lastIndex) { return indexToEntity.removeBySwap(index); } Entity other = indexToEntity[lastIndex]; CORE_RETURN_ERROR(indexToEntity.removeBySwap(index)); return entityToIndex.add(other, index); } T* search(Entity e) { i64* index = entityToIndex.search(e); if(index == nullptr) { return nullptr; } return &(components[*index]); } const T* search(Entity e) const { const i64* index = entityToIndex.search(e); if(index == nullptr) { return nullptr; } return &(components[*index]); } auto begin() { return components.begin(); } auto begin() const { return components.begin(); } auto end() { return components.end(); } auto end() const { return components.end(); } EntityIteratorAdapter entities() { return {*this}; } EntityIteratorAdapter entities() const { return {*this}; } }; } #endif