#include "ecs.hpp" TypeSafeInt_B(EntityHandle); const uint64_t bucketItemCount = 256; struct EntityBucket{ Entity entities[bucketItemCount]; }; uint64_t entityBucketIncrementer = 2; EntityHandle_T entityBucketCounter{0}; EntityHandle_T entityCounter{0}; EntityBucket *entityBuckets = nullptr; DynArray entitiesMarkedForRemoval{16}; DynArray EntitiesToBeRemoved{16}; void ECS_Init() { entityBuckets = Pke_New(entityBucketIncrementer); } EntityHandle ECS_CreateEntity_Inner(EntityHandle parentEntityHandle) { EntityHandle_T entityHandle_T{Buckets_NewHandle(bucketItemCount, entityBucketIncrementer, entityBucketCounter, entityCounter, entityBuckets)}; EntityHandle entityHandle{entityHandle_T}; Entity *entity = &entityBuckets[Buckets_GetBucketIndex(entityHandle_T)].entities[Buckets_GetItemIndex(entityHandle_T)]; entity->handle = entityHandle; entity->parentHandle = parentEntityHandle; return entityHandle; } EntityHandle ECS_CreateEntity(EntityHandle parentEntityHandle) { return ECS_CreateEntity_Inner(parentEntityHandle); } void ECS_MarkForRemoval(EntityHandle entityHandle) { auto b = Buckets_GetBucketIndex(static_cast(entityHandle)); auto e = Buckets_GetItemIndex(static_cast(entityHandle)); const Entity *ent = &entityBuckets[b].entities[e]; assert(ent->isMarkedForRemoval == false && "Entity already marked for removal"); entitiesMarkedForRemoval.Push(entityHandle); } void ECS_Tick(double delta) { EntitiesToBeRemoved.Resize(0); for (long b = 0; b <= entityBucketCounter; ++b) { uint64_t entCount = b == entityBucketCounter ? entityCounter >> 32 : bucketItemCount; for (long e = 0; e < entCount; ++e) { Entity *ent = &entityBuckets[b].entities[e]; if (ent->handle == EntityHandle{EntityHandle_T{0xFFFFFFFFFFFFFFFF}}) continue; if (ent->isMarkedForRemoval) { ent->handle = EntityHandle{EntityHandle_T{0xFFFFFFFFFFFFFFFF}}; ent->parentHandle = EntityHandle{EntityHandle_T{0xFFFFFFFFFFFFFFFF}}; ent->isMarkedForRemoval = false; } else { if (entitiesMarkedForRemoval.Has(ent->handle)) { ent->isMarkedForRemoval = true; EntitiesToBeRemoved.Push(ent->handle); continue; } if (EntitiesToBeRemoved.Has(ent->parentHandle)) { ent->isMarkedForRemoval = true; EntitiesToBeRemoved.Push(ent->handle); } } } } entitiesMarkedForRemoval.Resize(0); }