R-Type  1.0.1.0
Rewrite of the R-Type game with networking ability
Loading...
Searching...
No Matches
Registry.hpp
1/*
2** EPITECH PROJECT, 2023
3** Registry.hpp
4** File description:
5** Registry.hpp
6*/
7
8#ifndef URANUS_REGISTRY_HPP
9#define URANUS_REGISTRY_HPP
10
11#include "Entity.hpp"
12#include "SparseArray.hpp"
13#include "uranus/Core.hpp"
14#include "uranus/Exceptions.hpp"
15#include <any>
16#include <functional>
17#include <list>
18#include <stdexcept>
19#include <typeindex>
20#include <unordered_map>
21
22namespace uranus::ecs {
26 class Registry {
27 public:
34 template<class Component>
35 SparseArray<Component> &registerComponent(std::function<void(const size_t &)> &);
36
43 template<class Component>
44 SparseArray<Component> &registerComponent(std::function<void(const size_t &)> &&);
45
52 template<class Component>
53 typename SparseArray<Component>::ReferenceType getComponent(const Entity &e);
54
61 template<class Component>
62 typename SparseArray<Component>::ConstReferenceType getComponent(const Entity &e) const;
63
70 template<class Component>
71 typename SparseArray<Component>::ReferenceType getComponent(const size_t &e);
72
79 template<class Component>
80 typename SparseArray<Component>::ConstReferenceType getComponent(const size_t &e) const;
81
87 template<class Component>
89
95 template<class Component>
97
103
111 Entity entityFromIndex(std::size_t idx) const;
112
117 void killEntity(const Entity &e);
118
123 void killEntity(const size_t &e);
124
128 void killAllEntities();
129
137 template<typename Component>
138 typename SparseArray<Component>::ReferenceType addComponent(const Entity &to, Component &&c);
139
148 template<typename Component, typename... Params>
149 typename SparseArray<Component>::ReferenceType emplaceComponent(const Entity &to, Params &&...p);
150
156 template<typename Component>
157 void removeComponent(const Entity &from);
158
164 template<typename Component>
165 void removeComponent(const size_t &from);
166
171 int entitiesAliveCount() const;
172
177 size_t getEntityCounter() const;
178
184 private:
185 std::unordered_map<std::type_index, std::any> _componentsArrays;
186 std::unordered_map<std::type_index, std::function<void(size_t const &)>> _destroyArrays;
187 size_t _entityCounter = 0;
188 std::list<size_t> _freeIds;
189 };
190
191 template<class Component>
192 SparseArray<Component> &Registry::registerComponent(std::function<void(const size_t &)> &&deleteFunction)
193 {
194 auto const &typeIndex = std::type_index(typeid(Component)); // NOLINT
195 if (_componentsArrays.find(typeIndex) != _componentsArrays.end()) throw std::runtime_error("Component already registered");
196 if (_destroyArrays.find(typeIndex) != _destroyArrays.end()) throw std::runtime_error("Delete function already registered");
198 _destroyArrays[typeIndex] = deleteFunction;
199 return std::any_cast<SparseArray<Component> &>(_componentsArrays[typeIndex]);
200 }
201
202 template<class Component>
203 SparseArray<Component> &Registry::registerComponent(std::function<void(const size_t &)> &deleteFunction)
204 {
205 auto const &typeIndex = std::type_index(typeid(Component)); // NOLINT
206 if (_componentsArrays.find(typeIndex) != _componentsArrays.end()) throw std::runtime_error("Component already registered");
207 if (_destroyArrays.find(typeIndex) != _destroyArrays.end()) throw std::runtime_error("Delete function already registered");
209 _destroyArrays[typeIndex] = deleteFunction;
210 return std::any_cast<SparseArray<Component> &>(_componentsArrays[typeIndex]);
211 }
212
213 template<class Component>
214 typename SparseArray<Component>::ReferenceType Registry::getComponent(const Entity &e)
215 {
216 auto const &typeIndex = std::type_index(typeid(Component)); // NOLINT
217 if (_componentsArrays.find(typeIndex) == _componentsArrays.end()) throw std::runtime_error("Component not registered");
218 return std::any_cast<SparseArray<Component> &>(_componentsArrays[typeIndex])[e];
219 }
220
221 template<class Component>
222 typename SparseArray<Component>::ReferenceType Registry::getComponent(const size_t &e)
223 {
224 auto const &typeIndex = std::type_index(typeid(Component)); // NOLINT
225 if (_componentsArrays.find(typeIndex) == _componentsArrays.end()) throw std::runtime_error("Component not registered");
226 return std::any_cast<SparseArray<Component> &>(_componentsArrays[typeIndex])[e];
227 }
228
229 template<class Component>
230 typename SparseArray<Component>::ConstReferenceType Registry::getComponent(const Entity &e) const
231 {
232 auto const &typeIndex = std::type_index(typeid(Component)); // NOLINT
233 if (_componentsArrays.find(typeIndex) == _componentsArrays.end()) throw std::runtime_error("Component not registered");
234 return std::any_cast<SparseArray<Component> const &>(_componentsArrays.at(typeIndex))[e];
235 }
236
237 template<class Component>
238 typename SparseArray<Component>::ConstReferenceType Registry::getComponent(const size_t &e) const
239 {
240 auto const &typeIndex = std::type_index(typeid(Component)); // NOLINT
241 if (_componentsArrays.find(typeIndex) == _componentsArrays.end()) throw std::runtime_error("Component not registered");
242 return std::any_cast<SparseArray<Component> const &>(_componentsArrays.at(typeIndex))[e];
243 }
244
245 template<class Component>
247 {
248 auto const &typeIndex = std::type_index(typeid(Component)); // NOLINT
249 if (_componentsArrays.find(typeIndex) == _componentsArrays.end()) throw std::runtime_error("Component not registered");
250 return std::any_cast<SparseArray<Component> &>(_componentsArrays[typeIndex]);
251 }
252
253 template<class Component>
255 {
256 auto const &typeIndex = std::type_index(typeid(Component)); // NOLINT
257 if (_componentsArrays.find(typeIndex) == _componentsArrays.end()) throw std::runtime_error("Component not registered");
258 return std::any_cast<SparseArray<Component> const &>(_componentsArrays.at(typeIndex));
259 }
260
262 {
263 if (_freeIds.empty()) return Entity(_entityCounter++);
264 const size_t id = _freeIds.back();
265 _freeIds.pop_back();
266// spdlog::info("popped: {}", id);
267 return Entity(id);
268 }
269
270 inline Entity Registry::entityFromIndex(std::size_t idx) const
271 {
272 if (idx >= _entityCounter) throw ex::InvalidEntityIndex("Entity index out of range");
273 if (std::find(_freeIds.begin(), _freeIds.end(), idx) != _freeIds.end()) throw ex::InvalidEntityIndex("Entity index is not valid");
274 return Entity(idx);
275 }
276
277 inline void Registry::killEntity(const Entity &e)
278 {
279 if (std::find(_freeIds.begin(), _freeIds.end(), e) != _freeIds.end()) return;
280 _freeIds.push_back(e._id);
281 for (auto &i : _destroyArrays)
282 i.second(e._id);
283 }
284
285 inline void Registry::killEntity(const size_t &e)
286 {
287 if (std::find(_freeIds.begin(), _freeIds.end(), e) != _freeIds.end()) return;
288 _freeIds.push_back(e);
289 for (auto &i : _destroyArrays)
290 i.second(e);
291// spdlog::info("entity delete: {}", e);
292 }
293
295 {
296 for (size_t i = 0; i < _entityCounter; i++)
297 killEntity(i);
298 _freeIds.clear();
299 _entityCounter = 0;
300 }
301
302 template<typename Component>
303 typename SparseArray<Component>::ReferenceType Registry::addComponent(const Entity &to, Component &&c)
304 {
305 auto &components = getComponents<Component>();
306 return components.insertAt(to, std::forward<Component>(c));
307 }
308
309 template<typename Component, typename... Params>
310 typename SparseArray<Component>::ReferenceType Registry::emplaceComponent(const Entity &to, Params &&...p)
311 {
312 auto &components = getComponents<Component>();
313 return components.emplaceAt(to, std::forward<Params>(p)...);
314 }
315
316 template<typename Component>
318 {
319 auto &components = getComponents<Component>();
320 components.erase(from);
321 }
322
323 template<typename Component>
324 void Registry::removeComponent(const size_t &from)
325 {
326 auto &components = getComponents<Component>();
327 components.erase(from);
328 }
329
331 {
332 return static_cast<int>(_entityCounter - _freeIds.size());
333 }
334
335 inline size_t Registry::getEntityCounter() const
336 {
337 return _entityCounter;
338 }
339
340} // namespace uranus::ecs
341
342#endif // URANUS_REGISTRY_HPP
This file is used to include some core files of the engine.
Entity class, used to identify entities.
Definition: Entity.hpp:21
size_t _id
Id of the entity.
Definition: Entity.hpp:48
Registry class, used to store and manage entities and their components.
Definition: Registry.hpp:26
size_t getEntityCounter() const
Get the counter used to generate new entity ids.
Definition: Registry.hpp:335
Entity spawnEntity()
Spawn a new entity.
Definition: Registry.hpp:261
SparseArray< Component > & registerComponent(std::function< void(const size_t &)> &)
Register a component type and it's delete function.
Definition: Registry.hpp:203
std::unordered_map< std::type_index, std::function< void(size_t const &)> > _destroyArrays
Map containing all the components delete functions.
Definition: Registry.hpp:186
SparseArray< Component >::ReferenceType emplaceComponent(const Entity &to, Params &&...p)
Emplace a component to an entity.
Definition: Registry.hpp:310
SparseArray< Component > const & getComponents() const
Get the const SparseArray of a component type.
void killAllEntities()
Destroy all entities.
Definition: Registry.hpp:294
SparseArray< Component > & getComponents()
Get the SparseArray of a component type.
Definition: Registry.hpp:246
void killEntity(const Entity &e)
Destroy an entity.
Definition: Registry.hpp:277
size_t _entityCounter
Counter used to generate new entity ids.
Definition: Registry.hpp:187
Entity entityFromIndex(std::size_t idx) const
Create an entity from an index (only use this if you know what you're doing) (this will not create a ...
Definition: Registry.hpp:270
std::unordered_map< std::type_index, std::any > _componentsArrays
Get the maximum index of an entity.
Definition: Registry.hpp:185
std::list< size_t > _freeIds
Queue containing the ids of the destroyed entities.
Definition: Registry.hpp:188
int entitiesAliveCount() const
Get the number of entities alive.
Definition: Registry.hpp:330
SparseArray< Component >::ReferenceType addComponent(const Entity &to, Component &&c)
Add a component to an entity.
Definition: Registry.hpp:303
SparseArray< Component >::ReferenceType getComponent(const Entity &e)
Get a component from an entity.
Definition: Registry.hpp:214
void removeComponent(const Entity &from)
Remove a component from an entity.
Definition: Registry.hpp:317
SparseArray class, used to store components in a sparse way.
Definition: SparseArray.hpp:25
Thrown when an entity has an invalid index.
Definition: Exceptions.hpp:17
Namespace containing all the ECS related classes.
Definition: Components.hpp:21