#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; } }