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,
56 IsDontFragment = 1 << 15,
97#if GAIA_USE_SAFE_ENTITY
106#if GAIA_USE_WEAK_ENTITY
107 WeakEntityTracker* pWeakTracker =
nullptr;
120 GAIA_NODISCARD
static EntityContainer create(uint32_t index, uint32_t generation,
void* pCtx) {
125 ec.data.gen = generation;
126 ec.data.ent = (uint32_t)ctx->isEntity;
127 ec.data.pair = (uint32_t)ctx->isPair;
128 ec.data.kind = (uint32_t)ctx->kind;
137 flags |= DeleteRequested;
168 return ecs::Entity((ecs::EntityId)
id, gen, prev.entity(), prev.pair(), prev.kind());
175#if GAIA_USE_SAFE_ENTITY
180 World* m_w =
nullptr;
184 SafeEntity() =
default;
185 SafeEntity(World& w, Entity entity): m_w(&w), m_entity(entity) {
186 auto& ec = fetch_mut(w, entity);
193 if GAIA_UNLIKELY (m_w ==
nullptr)
196 auto& ec = fetch_mut(*m_w, m_entity);
197 GAIA_ASSERT(ec.refCnt > 0);
203 SafeEntity(const SafeEntity& other): m_w(other.m_w), m_entity(other.m_entity) {
204 auto& ec = fetch_mut(*m_w, m_entity);
207 SafeEntity& operator=(
const SafeEntity& other) {
208 GAIA_ASSERT(core::addressof(other) !=
this);
211 m_entity = other.m_entity;
213 auto& ec = fetch_mut(*m_w, m_entity);
218 SafeEntity(SafeEntity&& other)
noexcept: m_w(other.m_w), m_entity(other.m_entity) {
220 other.m_entity = EntityBad;
222 SafeEntity& operator=(SafeEntity&& other)
noexcept {
223 GAIA_ASSERT(core::addressof(other) !=
this);
226 m_entity = other.m_entity;
229 other.m_entity = EntityBad;
233 template <
typename Serializer>
234 void save(Serializer& s)
const {
237 template <
typename Serializer>
238 void load(Serializer& s) {
242 GAIA_NODISCARD Entity entity() const noexcept {
245 GAIA_NODISCARD
operator Entity() const noexcept {
249 bool operator==(
const SafeEntity& other)
const noexcept {
250 return m_entity == other.entity();
254 inline bool operator==(
const SafeEntity& e1, Entity e2)
noexcept {
255 return e1.entity() == e2;
257 inline bool operator==(Entity e1,
const SafeEntity& e2)
noexcept {
258 return e1 == e2.entity();
261 inline bool operator!=(
const SafeEntity& e1, Entity e2)
noexcept {
262 return e1.entity() != e2;
264 inline bool operator!=(Entity e1,
const SafeEntity& e2)
noexcept {
265 return e1 != e2.entity();
269#if GAIA_USE_WEAK_ENTITY
272 struct WeakEntityTracker {
273 WeakEntityTracker* next =
nullptr;
274 WeakEntityTracker* prev =
nullptr;
275 WeakEntity* pWeakEntity =
nullptr;
290 friend struct WeakEntityTracker;
292 World* m_w =
nullptr;
293 WeakEntityTracker* m_pTracker =
nullptr;
297 WeakEntity() =
default;
298 WeakEntity(World& w, Entity entity): m_w(&w), m_pTracker(new WeakEntityTracker()), m_entity(entity) {
305 WeakEntity(
const WeakEntity& other): m_w(other.m_w), m_entity(other.m_entity) {
306 if (other.m_pTracker ==
nullptr)
309 m_pTracker =
new WeakEntityTracker();
312 WeakEntity& operator=(
const WeakEntity& other) {
313 GAIA_ASSERT(core::addressof(other) !=
this);
318 m_entity = other.m_entity;
320 if (other.m_pTracker !=
nullptr) {
321 m_pTracker =
new WeakEntityTracker();
328 WeakEntity(WeakEntity&& other)
noexcept: m_w(other.m_w), m_pTracker(other.m_pTracker), m_entity(other.m_entity) {
330 if (other.m_pTracker !=
nullptr)
331 other.m_pTracker->pWeakEntity =
this;
332 other.m_pTracker =
nullptr;
333 other.m_entity = EntityBad;
335 WeakEntity& operator=(WeakEntity&& other)
noexcept {
336 GAIA_ASSERT(core::addressof(other) !=
this);
341 m_pTracker = other.m_pTracker;
342 m_entity = other.m_entity;
345 if (other.m_pTracker !=
nullptr)
346 other.m_pTracker->pWeakEntity =
this;
347 other.m_pTracker =
nullptr;
348 other.m_entity = EntityBad;
353 GAIA_ASSERT(m_pTracker !=
nullptr);
354 GAIA_ASSERT(m_w !=
nullptr);
355 GAIA_ASSERT(m_entity != EntityBad);
357 m_pTracker->pWeakEntity =
this;
358 m_pTracker->prev =
nullptr;
360 auto& ec = fetch_mut(*m_w, m_entity);
361 m_pTracker->next = ec.pWeakTracker;
362 if (ec.pWeakTracker !=
nullptr)
363 ec.pWeakTracker->prev = m_pTracker;
364 ec.pWeakTracker = m_pTracker;
368 if (m_pTracker ==
nullptr)
371 if (m_pTracker->next !=
nullptr)
372 m_pTracker->next->prev = m_pTracker->prev;
373 if (m_pTracker->prev !=
nullptr)
374 m_pTracker->prev->next = m_pTracker->next;
376 if (m_w !=
nullptr && valid(*m_w, m_entity)) {
377 auto& ec = fetch_mut(*m_w, m_entity);
378 if (ec.pWeakTracker == m_pTracker)
379 ec.pWeakTracker = m_pTracker->next;
383 m_pTracker =
nullptr;
386 template <
typename Serializer>
387 void save(Serializer& s)
const {
388 s.save(m_entity.val);
390 template <
typename Serializer>
391 void load(Serializer& s) {
395 m_entity = Entity(
id);
396 if (m_w !=
nullptr && m_entity != EntityBad) {
397 m_pTracker =
new WeakEntityTracker();
402 GAIA_NODISCARD Entity entity() const noexcept {
405 GAIA_NODISCARD
operator Entity() const noexcept {
409 bool operator==(
const WeakEntity& other)
const noexcept {
410 return m_entity == other.entity();
414 inline bool operator==(
const WeakEntity& e1, Entity e2)
noexcept {
415 return e1.entity() == e2;
417 inline bool operator==(Entity e1,
const WeakEntity& e2)
noexcept {
418 return e1 == e2.entity();
421 inline bool operator!=(
const WeakEntity& e1, Entity e2)
noexcept {
422 return e1.entity() != e2;
424 inline bool operator!=(Entity e1,
const WeakEntity& e2)
noexcept {
425 return e1 != e2.entity();
431 inline page_storage_id to_page_storage_id<ecs::EntityContainer>::get(
const ecs::EntityContainer& item)
noexcept {
Definition archetype.h:83
Definition robin_hood.h:720
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Paged implicit list with page-local slot metadata and lazily allocated page payloads....
Definition ilist.h:475
Definition paged_storage.h:37
Definition entity_container.h:33
Definition entity_container.h:68
uint32_t ent
0-component, 1-entity
Definition entity_container.h:72
uint32_t gen
Generation ID of the record.
Definition entity_container.h:70
uint32_t kind
Component kind.
Definition entity_container.h:76
uint32_t dis
Disabled Entity does not use this bit (always zero) so we steal it for special purposes....
Definition entity_container.h:82
uint32_t pair
0-ordinary, 1-pair
Definition entity_container.h:74
Definition entity_container.h:59
uint32_t unused
Currently unused area.
Definition entity_container.h:103
uint16_t row
Row at which the entity is stored in the chunk.
Definition entity_container.h:93
uint16_t flags
Flags.
Definition entity_container.h:95
const Entity * pEntity
Cached pointer to the entity's current slot inside the owning chunk.
Definition entity_container.h:115
uint32_t idx
Allocated items: Index in the list. Deleted items: Index of the next deleted item in the list.
Definition entity_container.h:62
Archetype * pArchetype
Archetype (stable address)
Definition entity_container.h:111
Chunk * pChunk
Chunk the entity currently resides in (stable address)
Definition entity_container.h:113
Definition entity_container.h:141
cnt::paged_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:144
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:147
Hashmap lookup structure used for Entity.
Definition id.h:439