Lazarus
Engine for creating roguelikes in C++
 All Classes Namespaces Functions
Entity.h
1 #pragma once
2 
3 #include <memory>
4 #include <typeindex>
5 #include <sstream>
6 #include <unordered_map>
7 #include <vector>
8 
9 #include <lazarus/common.h>
10 
11 namespace __lz // Meant for internal use only
12 {
13 template <typename T>
14 std::type_index getTypeIndex()
15 {
16  return std::type_index(typeid(T));
17 }
18 
20 {
21 public:
22  virtual ~BaseComponentHandle() = default;
23 };
24 
25 template <typename Component>
27 {
28 public:
29  ComponentHandle(std::shared_ptr<Component> comp)
30  : component(std::move(comp))
31  {
32  }
33 
34  Component *get() { return component.get(); }
35 
36 private:
37  std::shared_ptr<Component> component;
38 };
39 }
40 
41 namespace lz
42 {
43 using Identifier = size_t;
44 
50 class Entity
51 {
52 public:
58  Entity();
59 
63  Identifier getId() const { return entityId; }
64 
68  template <typename Component>
69  bool has() const;
70 
74  template <typename T, typename V, typename... Types>
75  bool has() const;
76 
87  template <typename Component, typename... Args>
88  void addComponent(Args&&... args);
89 
96  template <typename Component>
97  void removeComponent();
98 
104  template <typename Component>
105  Component* get();
106 
111  bool isDeleted() const { return deleted; }
112 
119  void markForDeletion() { deleted = true; }
120 
124  bool operator==(const Entity& other);
125 
129  bool operator!=(const Entity& other);
130 
134  bool operator<(const Entity& other);
135 
136 private:
137  const Identifier entityId;
138  static Identifier entityCount; // Keep track of the number of entities to assign new IDs
139  std::unordered_map<std::type_index, std::shared_ptr<__lz::BaseComponentHandle>> components;
140  bool deleted = false;
141 };
142 
143 template <typename Component>
144 bool Entity::has() const
145 {
146  return components.find(__lz::getTypeIndex<Component>()) != components.end();
147 }
148 
149 template <typename T, typename V, typename... Types>
150 bool Entity::has() const
151 {
152  return has<T>() && has<V, Types...>();
153 }
154 
155 template <typename Component, typename... Args>
156 void Entity::addComponent(Args&&... args)
157 {
158  // Check if the entity already holds a component T
159  if (has<Component>())
160  {
161  std::stringstream msg;
162  msg << "Entity " << getId() << " already holds a component of type "
163  << typeid(Component).name();
164  throw __lz::LazarusException(msg.str());
165  }
166 
167  // Construct component and add it to the map
168  std::shared_ptr<__lz::BaseComponentHandle> handle(
169  new __lz::ComponentHandle<Component>(std::make_shared<Component>(args...))
170  );
171  components[__lz::getTypeIndex<Component>()] = std::move(handle);
172 }
173 
174 template <typename Component>
176 {
177  if (!has<Component>())
178  {
179  std::stringstream msg;
180  msg << "Entity " << getId() << " does not have a component of type "
181  << typeid(Component).name();
182  throw __lz::LazarusException(msg.str());
183  }
184 
185  components.erase(__lz::getTypeIndex<Component>());
186 }
187 
188 template <typename Component>
189 Component* Entity::get()
190 {
191  auto found = components.find(__lz::getTypeIndex<Component>());
192  if (found == components.end())
193  return nullptr; // TODO: Log this case
194  auto compHandle = dynamic_cast<__lz::ComponentHandle<Component>*>(found->second.get());
195  return compHandle->get();
196 }
197 } // namespace lz
Definition: Entity.h:26
Identifier getId() const
Returns the ID of the entity.
Definition: Entity.h:63
bool operator!=(const Entity &other)
Returns true if the IDs of the entities are different.
Definition: Entity.cpp:17
Definition: common.h:21
Definition: Entity.h:19
bool isDeleted() const
Returns whether this entity is marked for deletion upon the next pass of the garbage collector...
Definition: Entity.h:111
void addComponent(Args &&...args)
Attaches a component to the entity.
Definition: Entity.h:156
void removeComponent()
Removes the component of type T from the entity.
Definition: Entity.h:175
Component * get()
Returns a pointer to the entity's component of the specified type.
Definition: Entity.h:189
bool has() const
Returns whether the entity has a component of type T.
Definition: Entity.h:144
bool operator==(const Entity &other)
Returns true if the IDs of the entities are the same.
Definition: Entity.cpp:12
An Entity is a collection of components with a unique ID.
Definition: Entity.h:50
Entity()
Default constructor.
Definition: Entity.cpp:7
bool operator<(const Entity &other)
Returns true if the ID of this entity is smaller than the other.
Definition: Entity.cpp:22
void markForDeletion()
Marks the entity for deletion.
Definition: Entity.h:119