power_play/src/world.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;
}
}