98 lines
2.7 KiB
C
98 lines
2.7 KiB
C
#include "world.h"
|
|
#include "entity.h"
|
|
|
|
/* ========================== *
|
|
* World allocation
|
|
* ========================== */
|
|
|
|
void world_alloc(struct world *world)
|
|
{
|
|
MEMZERO_STRUCT(world);
|
|
world->entities_arena = arena_alloc(GIGABYTE(64));
|
|
world->entities = (struct entity *)world->entities_arena.base;
|
|
}
|
|
|
|
void world_copy_replace(struct world *dest, struct world *src)
|
|
{
|
|
__prof;
|
|
|
|
/* Copy non-arena fields */
|
|
MEMCPY(dest, src, FIELD_OFFSETOF(struct world, _copy_barrier));
|
|
|
|
/* Copy arena contents */
|
|
arena_copy_replace(&dest->entities_arena, &src->entities_arena);
|
|
}
|
|
|
|
/* ========================== *
|
|
* Entity allocation
|
|
* ========================== */
|
|
|
|
struct entity *world_alloc_entity(struct world *world)
|
|
{
|
|
struct entity *entity = NULL;
|
|
struct entity_handle handle;
|
|
if (world->first_free_entity.gen) {
|
|
/* Reuse from free list */
|
|
entity = world_entity_from_handle(world, world->first_free_entity);
|
|
world->first_free_entity = entity->next_free;
|
|
handle = entity->handle;
|
|
} else {
|
|
/* Make new */
|
|
u64 idx = world->entities_count++;
|
|
entity = arena_push(&world->entities_arena, struct entity);
|
|
handle = (struct entity_handle) { .gen = 1, .idx = idx };
|
|
}
|
|
*entity = *entity_nil();
|
|
entity->handle = handle;
|
|
return entity;
|
|
}
|
|
|
|
void world_release_entity(struct world *world, struct entity *entity)
|
|
{
|
|
struct entity_handle next_free = world->first_free_entity;
|
|
world->first_free_entity = entity->handle;
|
|
*entity = (struct entity) {
|
|
.handle.gen = entity->handle.gen + 1,
|
|
.next_free = next_free
|
|
};
|
|
}
|
|
|
|
/* ========================== *
|
|
* Queries
|
|
* ========================== */
|
|
|
|
/* Returns a valid entity or nil entity. Always safe to read result, need to check to write. */
|
|
struct entity *world_entity_from_handle(struct world *world, struct entity_handle handle)
|
|
{
|
|
if (handle.idx < world->entities_count) {
|
|
struct entity *entities = world->entities;
|
|
struct entity *entity = &entities[handle.idx];
|
|
if (entity->handle.gen == handle.gen) {
|
|
return entity;
|
|
}
|
|
}
|
|
return entity_nil();
|
|
}
|
|
|
|
/* ========================== *
|
|
* Tree
|
|
* ========================== */
|
|
|
|
void world_link_entities(struct world *world, struct entity *parent, struct entity *child)
|
|
{
|
|
struct entity *first_child = world_entity_from_handle(world, parent->first);
|
|
struct entity *last_child = world_entity_from_handle(world, parent->last);
|
|
|
|
child->prev = last_child->handle;
|
|
child->parent = parent->handle;
|
|
|
|
if (last_child->valid) {
|
|
last_child->next = child->handle;
|
|
}
|
|
parent->last = child->handle;
|
|
|
|
if (!first_child->valid) {
|
|
parent->first = child->handle;
|
|
}
|
|
}
|