diff options
Diffstat (limited to 'world.cpp')
-rw-r--r-- | world.cpp | 132 |
1 files changed, 96 insertions, 36 deletions
@@ -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; +} |