#ifndef LIBCATBOY_ECS_ECS_HPP #define LIBCATBOY_ECS_ECS_HPP #include "component_view.hpp" #include "fwd.hpp" #include "sparseSet.hpp" #include #include #include #include #include #include #include #include namespace libcatboy { namespace ecs { template class basic_registry { public: using entity_type = Entity; public: entity_type create_entity() { if (m_graveyard.empty()) { entity_type entity = m_entityCounter++; m_alive.insert(entity); return entity; } entity_type entity = m_graveyard.front(); m_alive.insert(entity); m_graveyard.pop(); return entity; } void erase_entity(entity_type entity) { if (!m_alive.contains(entity)) return; m_alive.erase(entity); for (const auto& [type, set] : m_components) { set->erase(entity); } m_graveyard.push(entity); } public: template void register_component() { get_set(); } template void unregister_component() { auto it = m_components.find(typeid(T)); if (it == m_components.end()) return; delete reinterpret_cast*>(it->second); m_components.erase(it); } public: template void insert(entity_type entity, T&& component) { emplace>(entity, std::forward(component)); } template T& emplace(entity_type entity, Args&&... args) { if (m_alive.find(entity) == m_alive.end()) throw std::runtime_error("entity is dead"); return get_set().emplace(entity, std::forward(args)...); } public: template T& at(entity_type entity) { if (m_alive.find(entity) == m_alive.end()) throw std::runtime_error("entity is dead"); return get_set().at(entity); } template const T& at(entity_type entity) const { if (m_alive.find(entity) == m_alive.end()) throw std::runtime_error("entity is dead"); return get_set().at(entity); } public: template void erase(entity_type entity) { if (m_alive.find(entity) == m_alive.end()) throw std::runtime_error("entity is dead"); get_set().erase(entity); } public: template requires(sizeof...(Sum) >= 1) component_view view() { return { { (&get_set())... } }; } private: template sparse_set& get_set() { auto it = m_components.find(typeid(T)); if (it != m_components.end()) return dynamic_cast&>(*it->second); sparse_set* set = new sparse_set(); m_components.emplace(typeid(T), set); return *set; } template const sparse_set& get_set() const { auto it = m_components.find(typeid(T)); if (it != m_components.end()) return dynamic_cast&>(*it->second); throw std::runtime_error("error"); } private: std::unordered_map m_components; std::unordered_set m_alive; std::queue m_graveyard; entity_type m_entityCounter = 0; }; } // namespace ecs } // namespace libcatboy #endif // LIBCATBOY_ECS_ECS_HPP