2#include "gaia/config/config.h"
7#include "gaia/cnt/ilist.h"
8#include "gaia/cnt/map.h"
9#include "gaia/cnt/paged_storage.h"
10#include "gaia/ecs/api.h"
11#include "gaia/ecs/id.h"
15 struct EntityContainer;
29#if GAIA_USE_WEAK_ENTITY
30 struct WeakEntityTracker;
39 using EntityContainerFlagsType = uint16_t;
40 enum EntityContainerFlags : EntityContainerFlagsType {
41 OnDelete_Remove = 1 << 0,
42 OnDelete_Delete = 1 << 1,
43 OnDelete_Error = 1 << 2,
44 OnDeleteTarget_Remove = 1 << 3,
45 OnDeleteTarget_Delete = 1 << 4,
46 OnDeleteTarget_Error = 1 << 5,
48 HasCantCombine = 1 << 7,
51 IsSingleton = 1 << 10,
52 DeleteRequested = 1 << 11,
53 RefDecreased = 1 << 12,
95#if GAIA_USE_SAFE_ENTITY
104#if GAIA_USE_WEAK_ENTITY
105 WeakEntityTracker* pWeakTracker =
nullptr;
117 GAIA_NODISCARD
static EntityContainer create(uint32_t index, uint32_t generation,
void* pCtx) {
122 ec.data.gen = generation;
123 ec.data.ent = (uint32_t)ctx->isEntity;
124 ec.data.pair = (uint32_t)ctx->isPair;
125 ec.data.kind = (uint32_t)ctx->kind;
134 flags |= DeleteRequested;
138#if GAIA_USE_PAGED_ENTITY_CONTAINER
139 struct EntityContainer_paged_ilist_storage:
public cnt::page_storage<EntityContainer> {
140 void add_item(EntityContainer&& container) {
141 this->add(GAIA_MOV(container));
144 void del_item([[maybe_unused]] EntityContainer& container) {
154#if GAIA_USE_PAGED_ENTITY_CONTAINER
176#if GAIA_USE_SAFE_ENTITY
181 World* m_w =
nullptr;
185 SafeEntity() =
default;
186 SafeEntity(World& w, Entity entity): m_w(&w), m_entity(entity) {
187 auto& ec = fetch_mut(w, entity);
194 if GAIA_UNLIKELY (m_w ==
nullptr)
197 auto& ec = fetch_mut(*m_w, m_entity);
198 GAIA_ASSERT(ec.refCnt > 0);
204 SafeEntity(const SafeEntity& other): m_w(other.m_w), m_entity(other.m_entity) {
205 auto& ec = fetch_mut(*m_w, m_entity);
208 SafeEntity& operator=(
const SafeEntity& other) {
209 GAIA_ASSERT(core::addressof(other) !=
this);
212 m_entity = other.m_entity;
214 auto& ec = fetch_mut(*m_w, m_entity);
219 SafeEntity(SafeEntity&& other)
noexcept: m_w(other.m_w), m_entity(other.m_entity) {
221 other.m_entity = EntityBad;
223 SafeEntity& operator=(SafeEntity&& other)
noexcept {
224 GAIA_ASSERT(core::addressof(other) !=
this);
227 m_entity = other.m_entity;
230 other.m_entity = EntityBad;
234 template <
typename Serializer>
235 void save(Serializer& s)
const {
236 s.save(m_entity.val);
238 template <
typename Serializer>
239 void load(Serializer& s) {
242 m_entity = Entity(
id);
245 GAIA_NODISCARD Entity entity() const noexcept {
248 GAIA_NODISCARD
operator Entity() const noexcept {
252 bool operator==(
const SafeEntity& other)
const noexcept {
253 return m_entity == other.entity();
257 inline bool operator==(
const SafeEntity& e1, Entity e2)
noexcept {
258 return e1.entity() == e2;
260 inline bool operator==(Entity e1,
const SafeEntity& e2)
noexcept {
261 return e1 == e2.entity();
264 inline bool operator!=(
const SafeEntity& e1, Entity e2)
noexcept {
265 return e1.entity() != e2;
267 inline bool operator!=(Entity e1,
const SafeEntity& e2)
noexcept {
268 return e1 != e2.entity();
272#if GAIA_USE_WEAK_ENTITY
275 struct WeakEntityTracker {
276 WeakEntityTracker* next =
nullptr;
277 WeakEntityTracker* prev =
nullptr;
278 WeakEntity* pWeakEntity =
nullptr;
293 friend struct WeakEntityTracker;
295 World* m_w =
nullptr;
296 WeakEntityTracker* m_pTracker =
nullptr;
300 WeakEntity() =
default;
301 WeakEntity(World& w, Entity entity): m_w(&w), m_pTracker(new WeakEntityTracker()), m_entity(entity) {
308 WeakEntity(
const WeakEntity& other): m_w(other.m_w), m_entity(other.m_entity) {
309 if (other.m_entity == EntityBad)
312 m_pTracker =
new WeakEntityTracker();
313 m_pTracker->pWeakEntity =
this;
315 auto& ec = fetch_mut(*other.m_w, other.m_entity);
316 if (ec.pWeakTracker !=
nullptr) {
317 ec.pWeakTracker->prev = m_pTracker;
318 m_pTracker->next = ec.pWeakTracker;
320 ec.pWeakTracker = m_pTracker;
322 WeakEntity& operator=(
const WeakEntity& other) {
323 GAIA_ASSERT(core::addressof(other) !=
this);
326 m_entity = other.m_entity;
328 if (other.m_entity != EntityBad) {
329 m_pTracker =
new WeakEntityTracker();
330 m_pTracker->pWeakEntity =
this;
332 auto& ec = fetch_mut(*other.m_w, other.m_entity);
333 if (ec.pWeakTracker !=
nullptr) {
334 ec.pWeakTracker->prev = m_pTracker;
335 m_pTracker->next = ec.pWeakTracker;
337 ec.pWeakTracker = m_pTracker;
343 WeakEntity(WeakEntity&& other)
noexcept: m_w(other.m_w), m_pTracker(other.m_pTracker), m_entity(other.m_entity) {
345 other.m_pTracker->pWeakEntity =
this;
346 other.m_pTracker =
nullptr;
347 other.m_entity = EntityBad;
349 WeakEntity& operator=(WeakEntity&& other)
noexcept {
350 GAIA_ASSERT(core::addressof(other) !=
this);
353 m_pTracker = other.m_pTracker;
354 m_entity = other.m_entity;
357 other.m_pTracker->pWeakEntity =
this;
358 other.m_pTracker =
nullptr;
359 other.m_entity = EntityBad;
364 GAIA_ASSERT(m_pTracker !=
nullptr);
365 m_pTracker->pWeakEntity =
this;
367 auto& ec = fetch_mut(*m_w, m_entity);
368 if (ec.pWeakTracker !=
nullptr) {
369 ec.pWeakTracker->prev = m_pTracker;
370 m_pTracker->next = ec.pWeakTracker;
372 ec.pWeakTracker = m_pTracker;
376 if (m_pTracker ==
nullptr)
379 if (m_pTracker->next !=
nullptr)
380 m_pTracker->next->prev = m_pTracker->prev;
381 if (m_pTracker->prev !=
nullptr)
382 m_pTracker->prev->next = m_pTracker->next;
384 auto& ec = fetch_mut(*m_w, m_entity);
385 if (ec.pWeakTracker == m_pTracker)
386 ec.pWeakTracker =
nullptr;
389 m_pTracker =
nullptr;
392 template <
typename Serializer>
393 void save(Serializer& s)
const {
394 s.save(m_entity.val);
396 template <
typename Serializer>
397 void load(Serializer& s) {
401 m_entity = Entity(
id);
405 GAIA_NODISCARD Entity entity() const noexcept {
408 GAIA_NODISCARD
operator Entity() const noexcept {
412 bool operator==(
const WeakEntity& other)
const noexcept {
413 return m_entity == other.entity();
417 inline bool operator==(
const WeakEntity& e1, Entity e2)
noexcept {
418 return e1.entity() == e2;
420 inline bool operator==(Entity e1,
const WeakEntity& e2)
noexcept {
421 return e1 == e2.entity();
424 inline bool operator!=(
const WeakEntity& e1, Entity e2)
noexcept {
425 return e1.entity() != e2;
427 inline bool operator!=(Entity e1,
const WeakEntity& e2)
noexcept {
428 return e1 != e2.entity();
434 inline page_storage_id to_page_storage_id<ecs::EntityContainer>::get(
const ecs::EntityContainer& item)
noexcept {
Definition archetype.h:82
Definition robin_hood.h:720
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Implicit list. Rather than with pointers, items.
Definition ilist.h:76
Definition paged_storage.h:37
Definition entity_container.h:33
Definition entity_container.h:66
uint32_t ent
0-component, 1-entity
Definition entity_container.h:70
uint32_t gen
Generation ID of the record.
Definition entity_container.h:68
uint32_t kind
Component kind.
Definition entity_container.h:74
uint32_t dis
Disabled Entity does not use this bit (always zero) so we steal it for special purposes....
Definition entity_container.h:80
uint32_t pair
0-ordinary, 1-pair
Definition entity_container.h:72
Definition entity_container.h:57
uint32_t unused
Currently unused area.
Definition entity_container.h:101
uint16_t row
Row at which the entity is stored in the chunk.
Definition entity_container.h:91
uint16_t flags
Flags.
Definition entity_container.h:93
uint32_t idx
Allocated items: Index in the list. Deleted items: Index of the next deleted item in the list.
Definition entity_container.h:60
Archetype * pArchetype
Archetype (stable address)
Definition entity_container.h:109
Chunk * pChunk
Chunk the entity currently resides in (stable address)
Definition entity_container.h:111
Definition entity_container.h:151
cnt::ilist< EntityContainer, Entity > entities
Implicit list of entities. Used for look-ups only when searching for entities in chunks + data valida...
Definition entity_container.h:157
cnt::map< EntityLookupKey, EntityContainer > pairs
Just like m_recs.entities, but stores pairs. Needs to be a map because pair ids are huge numbers.
Definition entity_container.h:161
Hashmap lookup structure used for Entity.
Definition id.h:336