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"
12#include "gaia/mem/smallblock_allocator.h"
16 struct EntityContainer;
30#if GAIA_USE_WEAK_ENTITY
31 struct WeakEntityTracker;
40 using EntityContainerFlagsType = uint16_t;
41 enum EntityContainerFlags : EntityContainerFlagsType {
42 OnDelete_Remove = 1 << 0,
43 OnDelete_Delete = 1 << 1,
44 OnDelete_Error = 1 << 2,
45 OnDeleteTarget_Remove = 1 << 3,
46 OnDeleteTarget_Delete = 1 << 4,
47 OnDeleteTarget_Error = 1 << 5,
49 HasCantCombine = 1 << 7,
52 IsSingleton = 1 << 10,
53 DeleteRequested = 1 << 11,
54 RefDecreased = 1 << 12,
57 IsDontFragment = 1 << 15,
98#if GAIA_USE_SAFE_ENTITY
107#if GAIA_USE_WEAK_ENTITY
108 WeakEntityTracker* pWeakTracker =
nullptr;
121 GAIA_NODISCARD
static EntityContainer create(uint32_t index, uint32_t generation,
void* pCtx) {
126 ec.data.gen = generation;
127 ec.data.ent = (uint32_t)ctx->isEntity;
128 ec.data.pair = (uint32_t)ctx->isPair;
129 ec.data.kind = (uint32_t)ctx->kind;
138 flags |= DeleteRequested;
169 return ecs::Entity((ecs::EntityId)
id, gen, prev.entity(), prev.pair(), prev.kind());
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 {
238 template <
typename Serializer>
239 void load(Serializer& s) {
243 GAIA_NODISCARD Entity entity() const noexcept {
246 GAIA_NODISCARD
operator Entity() const noexcept {
250 bool operator==(
const SafeEntity& other)
const noexcept {
251 return m_entity == other.entity();
255 inline bool operator==(
const SafeEntity& e1, Entity e2)
noexcept {
256 return e1.entity() == e2;
258 inline bool operator==(Entity e1,
const SafeEntity& e2)
noexcept {
259 return e1 == e2.entity();
262 inline bool operator!=(
const SafeEntity& e1, Entity e2)
noexcept {
263 return e1.entity() != e2;
265 inline bool operator!=(Entity e1,
const SafeEntity& e2)
noexcept {
266 return e1 != e2.entity();
270#if GAIA_USE_WEAK_ENTITY
273 struct WeakEntityTracker {
274 GAIA_USE_SMALLBLOCK(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_pTracker ==
nullptr)
312 m_pTracker =
new WeakEntityTracker();
315 WeakEntity& operator=(
const WeakEntity& other) {
316 GAIA_ASSERT(core::addressof(other) !=
this);
321 m_entity = other.m_entity;
323 if (other.m_pTracker !=
nullptr) {
324 m_pTracker =
new WeakEntityTracker();
331 WeakEntity(WeakEntity&& other)
noexcept: m_w(other.m_w), m_pTracker(other.m_pTracker), m_entity(other.m_entity) {
333 if (other.m_pTracker !=
nullptr)
334 other.m_pTracker->pWeakEntity =
this;
335 other.m_pTracker =
nullptr;
336 other.m_entity = EntityBad;
338 WeakEntity& operator=(WeakEntity&& other)
noexcept {
339 GAIA_ASSERT(core::addressof(other) !=
this);
344 m_pTracker = other.m_pTracker;
345 m_entity = other.m_entity;
348 if (other.m_pTracker !=
nullptr)
349 other.m_pTracker->pWeakEntity =
this;
350 other.m_pTracker =
nullptr;
351 other.m_entity = EntityBad;
356 GAIA_ASSERT(m_pTracker !=
nullptr);
357 GAIA_ASSERT(m_w !=
nullptr);
358 GAIA_ASSERT(m_entity != EntityBad);
360 m_pTracker->pWeakEntity =
this;
361 m_pTracker->prev =
nullptr;
363 auto& ec = fetch_mut(*m_w, m_entity);
364 m_pTracker->next = ec.pWeakTracker;
365 if (ec.pWeakTracker !=
nullptr)
366 ec.pWeakTracker->prev = m_pTracker;
367 ec.pWeakTracker = m_pTracker;
371 if (m_pTracker ==
nullptr)
374 if (m_pTracker->next !=
nullptr)
375 m_pTracker->next->prev = m_pTracker->prev;
376 if (m_pTracker->prev !=
nullptr)
377 m_pTracker->prev->next = m_pTracker->next;
379 if (m_w !=
nullptr && valid(*m_w, m_entity)) {
380 auto& ec = fetch_mut(*m_w, m_entity);
381 if (ec.pWeakTracker == m_pTracker)
382 ec.pWeakTracker = m_pTracker->next;
386 m_pTracker =
nullptr;
389 template <
typename Serializer>
390 void save(Serializer& s)
const {
391 s.save(m_entity.val);
393 template <
typename Serializer>
394 void load(Serializer& s) {
398 m_entity = Entity(
id);
399 if (m_w !=
nullptr && m_entity != EntityBad) {
400 m_pTracker =
new WeakEntityTracker();
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 {
Array with variable size of elements of type.
Definition darray_impl.h:25
Definition archetype.h:83
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
static TItemHandle make(uint32_t id, uint32_t gen, const TItemHandle &prev)
Rebuilds a handle after its generation changes.
Definition ilist.h:405
Definition paged_storage.h:37
Definition entity_container.h:34
Definition entity_container.h:69
uint32_t ent
0-component, 1-entity
Definition entity_container.h:73
uint32_t gen
Generation ID of the record.
Definition entity_container.h:71
uint32_t kind
Component kind.
Definition entity_container.h:77
uint32_t dis
Disabled Entity does not use this bit (always zero) so we steal it for special purposes....
Definition entity_container.h:83
uint32_t pair
0-ordinary, 1-pair
Definition entity_container.h:75
Definition entity_container.h:60
uint32_t unused
Currently unused area.
Definition entity_container.h:104
uint16_t row
Row at which the entity is stored in the chunk.
Definition entity_container.h:94
uint16_t flags
Flags.
Definition entity_container.h:96
const Entity * pEntity
Cached pointer to the entity's current slot inside the owning chunk.
Definition entity_container.h:116
uint32_t idx
Allocated items: Index in the list. Deleted items: Index of the next deleted item in the list.
Definition entity_container.h:63
Archetype * pArchetype
Archetype (stable address)
Definition entity_container.h:112
Chunk * pChunk
Chunk the entity currently resides in (stable address)
Definition entity_container.h:114
Definition entity_container.h:142
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:145
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:148
Hashmap lookup structure used for Entity.
Definition id.h:468