Add first, inperformant version of ECS

The ECS can't handle many entities in this state; it is really slow.
This commit also doesn't contain any tests for its functions.
This commit is contained in:
Eric-Paul Ickhorn 2024-09-11 12:16:57 +02:00
parent 0408d19a72
commit e3e4e5ee84
8 changed files with 308 additions and 0 deletions

View File

@ -0,0 +1,24 @@
#ifndef VOXULA_H
#define VOXULA_H
#include <stdint.h>
#include <voxula/internals/utility.h>
typedef void vecs_s;
typedef struct vecs_entity vecs_entity_s;
struct vecs_entity
{
vecs_s *ecs;
vx_uuid_d uuid;
};
vecs_s * vecs_new();
void vecs_free(vecs_s *ecs);
vecs_entity_s vecs_summon(vecs_s *ecs);
void vecs_vanish(vecs_entity_s *entity);
#endif // VOXULA_H

View File

@ -0,0 +1,20 @@
#ifndef VECS_ENTITY_H
#define VECS_ENTITY_H
#include <stdint.h>
#include <voxula/internals/utility.h>
typedef struct vecs_entity vecs_entity_s;
struct vecs_entity
{
void *head_structure;
vx_uuid_d uuid;
};
vecs_entity_s vecs_summon(void *ecs_pointer);
void vecs_vanish(vecs_entity_s *entity);
#endif // VECS_ENTITY_H

View File

@ -0,0 +1,69 @@
#ifndef VECS_H
#define VECS_H
#include <stdint.h>
#include <voxula/internals/utility.h>
#include <voxula/internals/ecs/lookup.h>
typedef struct vecs vecs_s;
typedef struct vecs_shadow vecs_shadow_s;
typedef struct vecs_tag vecs_tag_s;
typedef struct vecs_tag_name_resolver vecs_tag_name_resolver_s;
typedef struct vecs_tag_name vecs_tag_name_s;
struct vecs_tag_name
{
vx_uuid_d uuid;
uint32_t length;
char *string;
};
struct vecs_tag_name_resolver
{
uint32_t names_capacity;
uint32_t num_names;
vecs_tag_name_s *names;
vx_uuid_table_s *uuid_table;
vx_arena_s *string_arena;
};
struct vecs_tag
{
void *pointer;
vecs_tag_s *next_in_chain;
vecs_tag_name_s *name;
vecs_tag_s *next_with_same_name;
vecs_tag_s *previous_with_same_name;
};
struct vecs_shadow
{
vx_uuid_d identifier;
vecs_tag_s *first_tag;
};
struct vecs
{
vx_pool_s *tag_pool;
vx_pool_s *shadow_pool;
vecs_tag_name_resolver_s resolver;
vecs_entity_map_s lookup_map;
vx_uuid_table_s *uuid_table;
};
vecs_s * vecs_new();
void vecs_free(vecs_s *ecs);
vecs_tag_name_resolver_s vecs_create_tag_name_resolver();
void vecs_delete_tag_name_resolver(vecs_tag_name_resolver_s *resolver);
vecs_tag_name_s * vecs_make_tag_name(vecs_tag_name_resolver_s *resolver, const char *name);
vecs_tag_name_s * vecs_search_tag_name(vecs_tag_name_resolver_s *resolver, const char *name);
#endif // VECS_H

View File

@ -0,0 +1,33 @@
#ifndef VOXULA_ENTITY_LOOKUP_H
#define VOXULA_ENTITY_LOOKUP_H
#include <stdbool.h>
#include <stdint.h>
#include <voxula/internals/utility.h>
typedef struct vecs_entity_map vecs_entity_map_s;
typedef struct vecs_entity_entry vecs_entity_entry_s;
struct vecs_entity_entry
{
void *shadow;
};
struct vecs_entity_map
{
uint32_t entries_capacity;
uint32_t num_entries;
vecs_entity_entry_s *entries;
};
vecs_entity_map_s vecs_create_lookup_map();
void vecs_delete_lookup_map(vecs_entity_map_s *map);
void * vecs_lookup_entity(vecs_entity_map_s *map, vx_uuid_d uuid);
void vecs_register_entity(vecs_entity_map_s *map, void *shadow_ptr);
void vecs_unregister_entity(vecs_entity_map_s *map, void *shadow_ptr);
#endif // VOXULA_ENTITY_LOOKUP_H

View File

@ -0,0 +1,25 @@
#include <voxula/internals/ecs/entity.h>
#include <voxula/internals/ecs/head.h>
vecs_entity_s vecs_summon(void *ecs_pointer)
{
vecs_s *ecs = ecs_pointer;
vecs_entity_s entity;
entity.head_structure = ecs;
entity.uuid = vx_new_uuid(ecs->uuid_table);
vecs_shadow_s *shadow = vx_pool(ecs->shadow_pool);
shadow->identifier = entity.uuid;
shadow->first_tag = NULL;
vecs_register_entity(&ecs->lookup_map, shadow);
return entity;
}
void vecs_vanish(vecs_entity_s *entity)
{
vecs_s *ecs = entity->head_structure;
vecs_shadow_s *shadow = vecs_lookup_entity(&ecs->lookup_map, entity->uuid);
vecs_unregister_entity(&ecs->lookup_map, shadow);
}

21
modules/ecs/src-c/head.c Normal file
View File

@ -0,0 +1,21 @@
#include <voxula/internals/ecs/lookup.h>
#include <voxula/internals/ecs/head.h>
#include <stdlib.h>
vecs_s * vecs_new()
{
vecs_s *ecs = malloc(sizeof(vecs_s));
ecs->resolver = vecs_create_tag_name_resolver();
ecs->lookup_map = vecs_create_lookup_map();
ecs->shadow_pool = vx_new_pool(sizeof(vecs_shadow_s), 8192);
ecs->tag_pool = vx_new_pool(sizeof(vecs_tag_s), 32768);
ecs->uuid_table = vx_new_uuid_table();
return ecs;
}
void vecs_free(vecs_s *ecs)
{
vecs_delete_tag_name_resolver(&ecs->resolver);
vx_free_pool(ecs->shadow_pool);
vx_free_pool(ecs->tag_pool);
}

View File

@ -0,0 +1,55 @@
#include <voxula/internals/ecs/lookup.h>
#include <voxula/internals/ecs/head.h>
#include <stdlib.h>
vecs_entity_map_s vecs_create_lookup_map()
{
vecs_entity_map_s map;
map.num_entries = 0;
map.entries_capacity = 8192;
map.entries = malloc(map.entries_capacity * sizeof(vx_uuid_entry_s));
return map;
}
void vecs_delete_lookup_map(vecs_entity_map_s *map)
{
free(map->entries);
}
void * vecs_lookup_entity(vecs_entity_map_s *map, vx_uuid_d uuid)
{
uint32_t entry_index = 0;
while(entry_index < map->num_entries)
{
vecs_shadow_s *shadow = map->entries[entry_index].shadow;
if(shadow->identifier == uuid)
{
return shadow;
}
++entry_index;
}
return NULL;
}
void vecs_register_entity(vecs_entity_map_s *map, void *shadow_ptr)
{
vecs_entity_entry_s *entry = &map->entries[map->num_entries];
entry->shadow = shadow_ptr;
++map->num_entries;
}
void vecs_unregister_entity(vecs_entity_map_s *map, void *shadow_ptr)
{
vecs_shadow_s *shadow = shadow_ptr;
uint32_t entry_index = 0;
while(entry_index < map->num_entries)
{
vecs_shadow_s *entry = map->entries[entry_index].shadow;
if(entry->identifier == shadow->identifier)
{
map->entries[entry_index] = map->entries[map->num_entries - 1];
break;
}
++entry_index;
}
}

View File

@ -0,0 +1,61 @@
#include <voxula/internals/ecs/head.h>
#include <stdlib.h>
#include <string.h>
vecs_tag_name_resolver_s vecs_create_tag_name_resolver()
{
vecs_tag_name_resolver_s resolver;
resolver.names_capacity = 1024;
resolver.num_names = 0;
resolver.names = malloc(resolver.names_capacity * sizeof(vecs_tag_name_s));
resolver.string_arena = vx_new_arena(16384);
return resolver;
}
void vecs_delete_tag_name_resolver(vecs_tag_name_resolver_s *resolver)
{
vx_free_arena(resolver->string_arena);
free(resolver->names);
}
vecs_tag_name_s * vecs_force_create_tag_name(vecs_tag_name_resolver_s *resolver, const char *name)
{
uint32_t len_name = strlen(name);
vecs_tag_name_s *tag_name = &resolver->names[resolver->num_names];
++resolver->num_names;
tag_name->length = len_name;
tag_name->string = vx_arena_dupe_string(resolver->string_arena, name);
tag_name->uuid = vx_new_uuid(resolver->uuid_table);
return tag_name;
}
vecs_tag_name_s * vecs_make_tag_name(vecs_tag_name_resolver_s *resolver, const char *name)
{
vecs_tag_name_s *tag_name = vecs_search_tag_name(resolver, name);
if(tag_name)
{
return tag_name;
}
return vecs_force_create_tag_name(resolver, name);
}
vecs_tag_name_s * vecs_search_tag_name(vecs_tag_name_resolver_s *resolver, const char *string)
{
uint32_t len_string = strlen(string);
uint32_t name_index = 0;
while(name_index < resolver->num_names)
{
vecs_tag_name_s *name = &resolver->names[name_index];
if(name->length != len_string)
{
++name_index;
continue;
}
if( ! memcmp(name->string, string, name->length))
{
return name;
}
++name_index;
}
return NULL;
}