summaryrefslogtreecommitdiff
path: root/src/ecs.cpp
blob: 2c0a26f1db30a0c4857b177fd7006c4a6fa4bf50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

#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<EntityHandle> entitiesMarkedForRemoval{16};
DynArray<EntityHandle> EntitiesToBeRemoved{16};

void ECS_Init() {
	entityBuckets = pke::PkeNew<EntityBucket>(entityBucketIncrementer);
}

EntityHandle ECS_CreateEntity_Inner(EntityHandle parentEntityHandle) {
	EntityHandle_T entityHandle_T{Buckets_NewHandle<EntityBucket>(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_T>(entityHandle));
	auto e = Buckets_GetItemIndex(static_cast<EntityHandle_T>(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);
}