summaryrefslogtreecommitdiff
path: root/world.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'world.cpp')
-rw-r--r--world.cpp132
1 files changed, 96 insertions, 36 deletions
diff --git a/world.cpp b/world.cpp
index 5cfd8bf..a08c024 100644
--- a/world.cpp
+++ b/world.cpp
@@ -8,12 +8,33 @@ extern "C" {
static int component_sizes[max_components];
+void Slinky::init(Arena* a, int size) {
+ data = arena_alloc(a, size * slinky_size);
+ entities = (Entity_Id*)arena_alloc(
+ a,
+ sizeof *entities * slinky_size
+ );
+ count = 0;
+}
+
+void* Slinky::add(Entity_Id eid, int size, int& mapping) {
+ int idx = count++;
+ assert(count <= slinky_size);
+ entities[idx] = eid;
+ mapping = idx;
+ return &((char*)data)[idx * size];
+}
+
+void* Slinky::get(Entity_Id eid, int mapping, int size) {
+ char* e = &((char*)data)[mapping * size];
+ assert(eid == entities[mapping]);
+ (void)eid;
+ return e;
+}
+
void Pool::init(Arena* a, Component_Mask m) {
int i, coff;
- next = 0;
- size = 0;
mask = m;
- count = 0;
for (i = 0, coff = 0; i < max_components; i++) {
if (m & ((Component_Mask)1 << i)) {
offsets[i] = coff;
@@ -21,50 +42,76 @@ void Pool::init(Arena* a, Component_Mask m) {
}
}
size = coff;
- data = arena_alloc(a, size * pool_cap);
+ slinkies[0].init(a, size);
+ slinky_count = 1;
+ count = 0;
}
-void* Pool::add(Arena* a, Entity_Id eid) {
- int idx;
- if (next)
- return next->add(a, eid);
- if (count >= pool_cap) {
- next = (Pool*)arena_alloc(a, sizeof *next);
- next->init(a, mask);
- return next->add(a, eid);
+Slinky& Pool::get_slinky(Arena* a) {
+ int i, e = slinky_count;
+ for (i = 0; i < e; i++) {
+ Slinky& s = slinkies[i];
+ if (s.count < slinky_size)
+ return s;
}
- idx = count++;
- entities[idx] = eid;
- mapping[entity_index(eid)] = idx;
- return &((char*)data)[idx * size];
+ assert(slinky_count < max_slinkies);
+ Slinky& s = slinkies[slinky_count++];
+ s.init(a, size);
+ return s;
+}
+
+void* Pool::add(Arena* a, Entity_Id eid) {
+ Slinky& slinky = get_slinky(a);
+ Mapping& m = mapping[entity_index(eid)];
+ m.slinky = &slinky - slinkies;
+ count++;
+ return slinky.add(eid, size, m.mapping);
}
void Pool::remove(Entity_Id eid) {
- int eind = entity_index(eid);
- int end = count - 1;
- assert(eid == entities[mapping[eind]]);
- memmove(
- (char*)data + eind * size,
- (char*)data + end * size,
- size
- );
- entities[eind] = entities[count];
- mapping[end] = eind;
- count = end;
+ Mapping& m = mapping[entity_index(eid)];
+ Slinky& s = slinkies[m.slinky];
+ assert(m.slinky >= 0);
+ if (count > 1) {
+ int idx = slinky_count - 1;
+ Entity_Id le;
+ void* last;
+#ifdef DEBUG
+ last = 0;
+#endif
+ for (; idx >= 0; idx--) {
+ Slinky& s = slinkies[idx];
+ int& c = s.count;
+ if (c) {
+ c--;
+ last = (char*)s.data + c * size;
+ le = s.entities[c];
+ s.entities[c] = 0;
+ break;
+ }
+ }
+ assert(last != 0);
+ memcpy((char*)s.data + m.mapping * size, last, size);
+ s.entities[m.mapping] = le;
+ mapping[entity_index(le)] = m;
+ m = Mapping { -1, -1 };
+ } else
+ s.count--;
+ count--;
}
void* Pool::get(Entity_Id eid, int cid) {
- int eind = entity_index(eid);
- char* e = &((char*)data)[mapping[eind] * size];
- assert(eid == entities[mapping[eind]]);
- return &e[offsets[cid]];
+ Mapping m = mapping[entity_index(eid)];
+ Slinky& s = slinkies[m.slinky];
+ char* ptr = (char*)s.get(eid, m.mapping, size);
+ return ptr + offsets[cid];
}
void* Pool::get(Entity_Id eid) {
- int eind = entity_index(eid);
- void* e = &((char*)data)[mapping[eind] * size];
- assert(eid == entities[mapping[eind]]);
- return e;
+ Mapping m = mapping[entity_index(eid)];
+ Slinky& s = slinkies[m.slinky];
+ char* ptr = (char*)s.get(eid, m.mapping, size);
+ return ptr;
}
int get_new_component_id(int size) {
@@ -91,6 +138,7 @@ void World::init(Arena* a) {
arena = a;
count = 0;
free_count = 0;
+ dq_count = 0;
for (i = 0; i < max_entities; i++)
versions[i] = 1;
for (i = 0; i < max_pools; i++)
@@ -166,7 +214,6 @@ void* World::get(Entity_Id eid, int cid) {
int eind = entity_index(eid);
Pool& p = get_pool(masks[eind]);
assert(versions[eind] == entity_version(eid));
- assert(p.entities[p.mapping[eind]] == eid);
return p.get(eid, cid);
}
@@ -202,3 +249,16 @@ void World::destroy(Entity_Id e) {
versions[entity_index(e)]++;
}
+void World::qdestroy(Entity_Id e) {
+ assert(e);
+ assert(dq_count < max_entities);
+ dq[dq_count++] = e;
+}
+
+void World::update() {
+ int i, e = dq_count;
+ Entity_Id* d = dq;
+ for (i = 0; i < e; i++, d++)
+ destroy(*d);
+ dq_count = 0;
+}