My Project
Registry.hpp
1 /*
2 ** EPITECH PROJECT, 2022
3 ** r-type
4 ** File description:
5 ** Registry
6 */
7 
8 #ifndef REGISTRY_HPP_
9  #define REGISTRY_HPP_
10 
11  #include <map>
12  #include <any>
13  #include <typeindex>
14  #include <functional>
15 
16  #include "SparseArray.hpp"
17  #include "Entity.hpp"
18 
22 class Registry
23 {
24  public:
28  explicit Registry() = default;
29 
35  explicit Registry(std::size_t nbEntities) : _nbEntities(nbEntities) {};
36 
40  virtual ~Registry() = default;
41 
48  template <class Component>
50  {
51 
52  auto [it, ok] = _componentsArrays.try_emplace(std::type_index(typeid(Component)), std::make_any<Sparse_array<Component>>(_nbEntities));
53 
54  if (ok) {
55  _erasers.emplace_back([](Registry &registry, Entity const &entity) {
56  registry.remove_component<Component>(entity);
57  });
58  } else {
59  throw std::invalid_argument("Component already registered");
60  }
61  return std::any_cast<Sparse_array<Component> &>(it->second);
62  };
63 
70  template <class Component>
72  {
73  return std::any_cast<Sparse_array<Component> &>(_componentsArrays.at(std::type_index(typeid(Component))));
74  };
75 
82  template <class Component>
84  {
85  return std::any_cast<Sparse_array<Component> &>(_componentsArrays.at(std::type_index(typeid(Component))));
86  };
87 
94  {
95  _nbEntities += 1;
96 
97  return Entity(_nbEntities - 1);
98  };
99 
107  template <class ...Components>
108  Entity spawn_entity_with(Components && ...components) {
109  Entity e = spawn_entity();
110 
111  (add_component(e, std::forward<Components>(components)), ...);
112  return e;
113  }
114 
121  Entity entity_from_index(std::size_t idx) const
122  {
123  if (idx >= _nbEntities) {
124  throw std::out_of_range("At this index, entity doesn't exist !");
125  }
126  return Entity(idx);
127  };
128 
134  void kill_entity(Entity const &e)
135  {
136  for (auto &&it : _erasers)
137  it(*this, e);
138  };
139 
148  template <typename Component>
149  typename Sparse_array<Component>::reference_type add_component(Entity const &e, Component &&c)
150  {
151  if (_componentsArrays.find(std::type_index(typeid(Component))) == _componentsArrays.end())
152  throw std::invalid_argument("Component not registered !");
153  Sparse_array<Component> &sparseArray = std::any_cast<Sparse_array<Component> &>(_componentsArrays.at(std::type_index(typeid(Component))));
154 
155  if (e > sparseArray.size()) {
156  sparseArray.extend((size_t) e - sparseArray.size());
157  }
158  return sparseArray.insert_at(e, c);
159  };
160 
170  template <typename Component, typename ...Params>
171  typename Sparse_array<Component>::reference_type emplace_component(Entity const &to, Params &&...p)
172  {
173  Sparse_array<Component> sparseArray = std::any_cast<Sparse_array<Component> &>(_componentsArrays.at(std::type_index(typeid(Component))));
174  return sparseArray.emplaceAt(to, p...);
175  };
176 
183  template <typename Component>
184  void remove_component(Entity const &from)
185  {
186  Sparse_array<Component> &sparseArray = std::any_cast<Sparse_array<Component> &>(_componentsArrays.at(std::type_index(typeid(Component))));
187 
188  if (sparseArray.size() > from) {
189  sparseArray.erase(from);
190  }
191  };
192 
200  template <class ...Component, typename Function>
201  void add_system(Function &&f) {
202  _listOfSystems.push_back([&f](Registry &registry) -> void {
203  f(registry, registry.get_components<Component>()...);
204  });
205  }
206 
214  template <class ...Component, typename Function>
215  void add_system(Function const &f) {
216  _listOfSystems.push_back([&f](Registry &registry) -> void {
217  f(registry, registry.get_components<Component>()...);
218  });
219  }
220 
224  void run_systems() {
225  for (auto &function : _listOfSystems)
226  function(*this);
227  }
228 
229  private:
230  std::vector<std::function<void (Registry &, Entity const &)>> _erasers;
231 
232  std::map<std::type_index, std::any> _componentsArrays;
233 
234  std::size_t _nbEntities = 0;
235 
236  std::vector<Entity> _killedEntities;
237 
238  std::vector<std::function<void(Registry &)>> _listOfSystems;
239 };
240 
241 #endif /* !REGISTRY_HPP_ */
Registry::Registry
Registry(std::size_t nbEntities)
Construct a new Registry object.
Definition: Registry.hpp:35
Sparse_array
Class that handle Element of type Component like a vector which can be holed.
Definition: SparseArray.hpp:22
Registry::get_components
Sparse_array< Component > & get_components()
Get the components object.
Definition: Registry.hpp:71
Sparse_array::size
size_type size() const
Overloads the operator size()
Definition: SparseArray.hpp:188
Registry::get_components
const Sparse_array< Component > & get_components() const
Get the components object.
Definition: Registry.hpp:83
Component
Namespace for all components.
Definition: CConnection.hpp:14
Registry::add_component
Sparse_array< Component >::reference_type add_component(Entity const &e, Component &&c)
A method to add a component to a known sparse array.
Definition: Registry.hpp:149
Registry::kill_entity
void kill_entity(Entity const &e)
A method to kill an entity.
Definition: Registry.hpp:134
Sparse_array::extend
void extend(size_t sizeToExtend)
Overload the operator extend()
Definition: SparseArray.hpp:198
Registry::register_component
Sparse_array< Component > & register_component()
A method to register a component to the registry, it inserts it inside the various arrays contained i...
Definition: Registry.hpp:49
Registry
Class that handle ECS.
Definition: Registry.hpp:22
Sparse_array::erase
void erase(size_type pos)
Overloads the operator erase()
Definition: SparseArray.hpp:274
Registry::~Registry
virtual ~Registry()=default
Destroy the Registry object.
Registry::emplace_component
Sparse_array< Component >::reference_type emplace_component(Entity const &to, Params &&...p)
A method to add a component at a position int the sparse array, a sparse array means that some cells ...
Definition: Registry.hpp:171
Registry::Registry
Registry()=default
Construct a new Registry object.
Registry::remove_component
void remove_component(Entity const &from)
A method to remove a component from an entity.
Definition: Registry.hpp:184
Registry::spawn_entity_with
Entity spawn_entity_with(Components &&...components)
A method that create an entity and add all components you want to it.
Definition: Registry.hpp:108
Entity
Class that handle entity in a sparse array like an index.
Definition: Entity.hpp:16
Registry::add_system
void add_system(Function &&f)
A method to add a system to the registry, adds the element to the list of systems of the registry.
Definition: Registry.hpp:201
Registry::entity_from_index
Entity entity_from_index(std::size_t idx) const
A method to get an entity with its index.
Definition: Registry.hpp:121
Registry::spawn_entity
Entity spawn_entity()
A method to spawn an entity, it adds it to the creators array.
Definition: Registry.hpp:93
Sparse_array::insert_at
reference_type insert_at(size_type pos, Component const &component)
Overloads the operator insert_at()
Definition: SparseArray.hpp:211
Registry::run_systems
void run_systems()
A method that is used to run all the systems of the registry.
Definition: Registry.hpp:224
Registry::add_system
void add_system(Function const &f)
A method to add a system to the registry, adds the element to the list of systems of the registry.
Definition: Registry.hpp:215