From 40be22f69bda0ca01ed8b6fce19689f7c01484ff Mon Sep 17 00:00:00 2001 From: Eric-Paul Ickhorn Date: Sat, 14 Oct 2023 21:17:30 +0200 Subject: [PATCH] An ECS-oid structure --- code/source-c/chunk_loader.c | 6 +- code/source-c/chunk_pool.c | 32 ++++++---- code/source-c/entity.c | 112 +++++++++++++++++++++++++++++++-- code/source-c/entity.h | 42 +++++++++---- code/source-c/entity_pool.c | 23 ++++++- code/source-c/initialization.c | 2 + code/source-c/main.c | 9 ++- code/source-c/state.h | 3 + code/source-c/world.c | 82 +++++++++++++++++++++--- code/source-c/world.h | 9 ++- 10 files changed, 276 insertions(+), 44 deletions(-) diff --git a/code/source-c/chunk_loader.c b/code/source-c/chunk_loader.c index 9e9c1db..8098c25 100644 --- a/code/source-c/chunk_loader.c +++ b/code/source-c/chunk_loader.c @@ -1,4 +1,5 @@ #include "world.h" +#include "entity.h" #include #include @@ -59,7 +60,8 @@ tc_chunk_s * tc_load_chunk_of_loader(tc_chunkloader_s *loader, tc_vec3i_s coord) if(chunk == NULL) { - chunk = tc_allocate_chunk(loader->world); + tc_entity_s *entity = tc_create_entity("chunk"); // TODO: FURTHER RESTRUCTUING FOR ENTITIES + chunk = entity->specific; chunk->position = coord; loader->world->worldgen->fn_generate_chunk(loader->world->worldgen, chunk); @@ -89,7 +91,7 @@ void tc_reload_chunk(tc_world_s *world, tc_vec3i_s coord) void tc_remove_loaders_chunk(tc_chunkloader_s *loader, uint32_t index) { - tc_free_chunk(loader->world, loader->chunks[index]); + tc_free_chunk(loader->chunks[index]); if(loader->num_chunks != 0) { diff --git a/code/source-c/chunk_pool.c b/code/source-c/chunk_pool.c index d019398..f9c65c6 100644 --- a/code/source-c/chunk_pool.c +++ b/code/source-c/chunk_pool.c @@ -3,6 +3,8 @@ #include #include +tc_chunk_pool_s *tc_chunk_pool_g = NULL; + void tc_reset_chunk_pool(tc_chunk_pool_s *chunk_pool) { chunk_pool->used_entries = 0; @@ -20,7 +22,7 @@ void tc_reset_chunk_pool(tc_chunk_pool_s *chunk_pool) chunk_pool->entries[chunk_pool->capacity-1].next = NULL; } -tc_chunk_pool_s * tc_new_chunk_pool(uint32_t capacity) +tc_chunk_pool_s * tc_internal_new_chunk_pool(uint32_t capacity) { tc_chunk_pool_s *pool = malloc(sizeof(tc_chunk_pool_s)); pool->capacity = capacity; @@ -30,11 +32,17 @@ tc_chunk_pool_s * tc_new_chunk_pool(uint32_t capacity) return pool; } +void tc_init_chunk_pool(uint32_t capacity) +{ + tc_chunk_pool_g = tc_internal_new_chunk_pool(capacity); +} + tc_chunk_pool_entry_s * tc_allocate_chunk_pool_entry(tc_chunk_pool_s *pool) { if(pool->first_free == NULL) { - pool->continuation = tc_new_chunk_pool(pool->capacity * 2); + if(pool->continuation == NULL) + pool->continuation = tc_internal_new_chunk_pool(pool->capacity * 2); return tc_allocate_chunk_pool_entry(pool->continuation); } tc_chunk_pool_entry_s *allocated = pool->first_free; @@ -43,18 +51,16 @@ tc_chunk_pool_entry_s * tc_allocate_chunk_pool_entry(tc_chunk_pool_s *pool) return allocated; } -tc_chunk_s * tc_allocate_chunk(tc_world_s *world) +tc_chunk_s * tc_allocate_chunk() { - tc_chunk_pool_entry_s *entry = tc_allocate_chunk_pool_entry(world->pool); + tc_chunk_pool_entry_s *entry = tc_allocate_chunk_pool_entry(tc_chunk_pool_g); entry->chunk.pool_entry = entry; return &entry->chunk; } -void tc_free_chunk(tc_world_s *world, tc_chunk_s *chunk) +void tc_free_chunk(tc_chunk_s *chunk) { - tc_chunk_pool_s *pool = world->pool; - if(chunk->vao != 0) { glDeleteVertexArrays(1, &chunk->vertex_data); @@ -79,12 +85,12 @@ void tc_free_chunk(tc_world_s *world, tc_chunk_s *chunk) chunk->vertex_uvs = NULL; } - chunk->num_vertices = 0; - chunk->position.x = 0; - chunk->position.y = 0; - chunk->position.z = 0; + chunk->num_vertices = 0; + chunk->position.x = 0; + chunk->position.y = 0; + chunk->position.z = 0; memset(&chunk->blocks, 0x00, sizeof(uint32_t) * 32 * 32 * 32); - chunk->pool_entry->next = pool->first_free; - pool->first_free = chunk->pool_entry; + chunk->pool_entry->next = tc_chunk_pool_g->first_free; + tc_chunk_pool_g->first_free = chunk->pool_entry; } diff --git a/code/source-c/entity.c b/code/source-c/entity.c index 40b5301..59ad76d 100644 --- a/code/source-c/entity.c +++ b/code/source-c/entity.c @@ -10,9 +10,12 @@ tc_entity_registry_s tc_init_entity_registry() registry.types_capacity = 64; registry.num_types = 0; registry.types = calloc(sizeof(tc_entity_type_s), registry.types_capacity); - registry.entities_capacity = 512; + registry.entities_capacity = 1024; registry.num_entities = 0; registry.entities = calloc(sizeof(tc_entity_s *), registry.entities_capacity); + registry.intervals_capacity = 256; + registry.num_intervals = 0; + registry.intervals = calloc(sizeof(tc_interval_s *), registry.intervals_capacity); return registry; } @@ -55,7 +58,11 @@ tc_entity_s * tc_create_entity(char *type) tc_entity_type_s *type_struct = tc_get_entity_type_with_name(type); if(type_struct == NULL) return NULL; - return type_struct->functions.fn_create(); + tc_entity_s *entity = type_struct->functions.fn_create(); + entity->type = type_struct; + ++tc_game_state_g.entity_registry.num_entities; + + return entity; } void tc_spawn_entity(tc_entity_s *entity, tc_location_s location) @@ -68,9 +75,14 @@ void tc_teleport_entity(tc_entity_s *entity, tc_location_s location) entity->type->functions.fn_teleport(entity, location); } +void tc_draw_entity(tc_entity_s *entity) +{ + entity->type->functions.fn_draw(entity); +} + void tc_delete_entity(tc_entity_s *entity) { - entity->type->functions.fn_delete(entity); + entity->type->functions.fn_draw(entity); } @@ -98,7 +110,7 @@ tc_entity_attribute_s * tc_allocate_entity_attribute(tc_entity_s *entity) if(entity->num_attributes >= entity->attributes_capacity) { entity->attributes_capacity *= 2; - entity->attributes = realloc(entity->attributes, sizeof(tc_entity_s) * entity->attributes_capacity); + entity->attributes = realloc(entity->attributes, sizeof(tc_entity_attribute_s) * entity->attributes_capacity); } ++entity->num_attributes; return &entity->attributes[entity->num_attributes-1]; @@ -186,6 +198,54 @@ void tc_forget_entity_attribute(tc_entity_s *entity, char *attr_name) +int32_t tc_find_index_of_entity_in_intervals(tc_entity_s *entity) +{ + uint32_t interval_index = 0; + while(interval_index < tc_game_state_g.entity_registry.num_intervals) + { + if(tc_game_state_g.entity_registry.intervals[interval_index].entity == entity) + return interval_index; + + ++interval_index; + } + return -1; +} + +uint32_t tc_allocate_interval() +{ + if( + tc_game_state_g.entity_registry.num_intervals + >= + tc_game_state_g.entity_registry.intervals_capacity + ) { + tc_game_state_g.entity_registry.intervals_capacity *= 2; + tc_game_state_g.entity_registry.intervals = + realloc( + tc_game_state_g.entity_registry.intervals, + sizeof(tc_interval_s) * tc_game_state_g.entity_registry.intervals_capacity + ); + } + uint32_t last = tc_game_state_g.entity_registry.num_intervals; + tc_game_state_g.entity_registry.intervals[last].last_invocation = 0.0f; + ++tc_game_state_g.entity_registry.num_intervals; + + return last; +} + +void tc_schedule_interval(tc_entity_s *entity, float wanted_delta, void (*fn_interval)(tc_entity_s *entity)) +{ + int32_t interval_index; + if((interval_index = tc_find_index_of_entity_in_intervals(entity)) == -1) + { + interval_index = tc_allocate_interval(); + } + tc_interval_s entry; + entry.entity = entity; + entry.wanted_delta = wanted_delta; + entry.fn_interval = fn_interval; + tc_game_state_g.entity_registry.intervals[interval_index] = entry; +} + void tc_send_pointer_to_entity(tc_entity_s *entity, char *event_name, void *pointer) { tc_entity_event_s event; @@ -218,3 +278,47 @@ void tc_send_float_to_entity(tc_entity_s *entity, char *event_name, double floa entity->type->functions.fn_send_event(entity, event); } +void tc_tick_intervals() +{ + uint64_t current_ms = SDL_GetTicks64(); + tc_entity_registry_s registry = tc_game_state_g.entity_registry; + + uint32_t interval_index = 0; + while(interval_index < registry.num_intervals) + { + tc_interval_s interval = registry.intervals[interval_index]; + uint32_t elapsed_time = current_ms - interval.last_invocation; + if(elapsed_time >= interval.wanted_delta) + { + if(interval.fn_interval == NULL) + { + ++interval_index; + continue; + } + interval.fn_interval(interval.entity); + } + ++interval_index; + } +} + + +void tc_draw_all_entities_of_type(char *name) +{ + tc_entity_type_s *type = tc_get_entity_type_with_name(name); + tc_entity_registry_s registry = tc_game_state_g.entity_registry; + + uint32_t drawn_entities = 0; + uint32_t entity_index = 0; + while(entity_index < registry.num_entities) + { + tc_entity_s *entity = registry.entities[entity_index]; + if(entity->type == type) + { + tc_draw_entity(entity); + ++drawn_entities; + } + ++entity_index; + } + printf("Drew %d out of %d Entities!\n", drawn_entities, registry.num_entities); +} + diff --git a/code/source-c/entity.h b/code/source-c/entity.h index 61d2434..b10b49e 100644 --- a/code/source-c/entity.h +++ b/code/source-c/entity.h @@ -5,11 +5,12 @@ #include "location.h" #include "utility.h" -typedef struct tc_entity_event tc_entity_event_s; -typedef struct tc_entity_type tc_entity_type_s; -typedef struct tc_entity_attribute tc_entity_attribute_s; -typedef struct tc_entity tc_entity_s; -typedef struct tc_entity_registry tc_entity_registry_s; +typedef struct tc_entity_event tc_entity_event_s; +typedef struct tc_entity_type tc_entity_type_s; +typedef struct tc_entity_attribute tc_entity_attribute_s; +typedef struct tc_entity tc_entity_s; +typedef struct tc_interval tc_interval_s; +typedef struct tc_entity_registry tc_entity_registry_s; typedef struct @@ -17,6 +18,7 @@ typedef struct tc_entity_s * (*fn_create) (); void (*fn_spawn) (tc_entity_s *entity, tc_location_s location); void (*fn_teleport) (tc_entity_s *entity, tc_location_s location); + void (*fn_draw) (tc_entity_s *entity); void (*fn_delete) (tc_entity_s *entity); void (*fn_send_event) (tc_entity_s *entity, tc_entity_event_s event); @@ -41,7 +43,6 @@ struct tc_entity_type char *display_name; tc_fn_entity_s functions; - }; struct tc_entity_attribute @@ -72,15 +73,27 @@ struct tc_entity }; +struct tc_interval +{ + uint64_t last_invocation; + uint64_t wanted_delta; + tc_entity_s *entity; + void (*fn_interval) (tc_entity_s *entity); +}; + struct tc_entity_registry { - uint32_t types_capacity; - uint32_t num_types; - tc_entity_type_s *types; + uint32_t types_capacity; + uint32_t num_types; + tc_entity_type_s *types; - uint32_t entities_capacity; - uint32_t num_entities; - tc_entity_s **entities; + uint32_t entities_capacity; + uint32_t num_entities; + tc_entity_s **entities; + + uint32_t intervals_capacity; + uint32_t num_intervals; + tc_interval_s *intervals; }; tc_entity_registry_s tc_init_entity_registry (); @@ -91,6 +104,7 @@ tc_entity_type_s * tc_get_entity_type_with_name (char *name); tc_entity_s * tc_create_entity (char *type); void tc_spawn_entity (tc_entity_s *entity, tc_location_s location); void tc_teleport_entity (tc_entity_s *entity, tc_location_s location); +void tc_draw_entity (tc_entity_s *entity); void tc_delete_entity (tc_entity_s *entity); void tc_set_pointer_for_entity (tc_entity_s *entity, char *attr_name, void *pointer); @@ -108,6 +122,10 @@ void tc_send_string_to_entity (tc_entity_s *en void tc_send_integer_to_entity (tc_entity_s *entity, char *event_name, int64_t integer); void tc_send_float_to_entity (tc_entity_s *entity, char *event_name, double floating); +void tc_schedule_interval (tc_entity_s *entity, float wanted_delta, void (*fn_interval)(tc_entity_s *entity)); +void tc_tick_intervals (); +void tc_draw_all_entities_of_type (char *name); + tc_entity_s * tc_allocate_entity (); void tc_deallocate_entity (tc_entity_s *entity); diff --git a/code/source-c/entity_pool.c b/code/source-c/entity_pool.c index 0e73ae8..dfd5f3a 100644 --- a/code/source-c/entity_pool.c +++ b/code/source-c/entity_pool.c @@ -3,6 +3,17 @@ #include +// TODO: Write a *real* pool allocator + +void tc_reset_entity(tc_entity_s *entity) +{ + if(entity->attributes != NULL) free(entity->attributes); + entity->attributes_capacity = 8; + entity->attributes = + calloc(sizeof(tc_entity_attribute_s), entity->attributes_capacity); + +} + tc_entity_s * tc_allocate_entity() { tc_entity_registry_s registry = tc_game_state_g.entity_registry; @@ -14,16 +25,24 @@ tc_entity_s * tc_allocate_entity() { registry.entities[entity_index] = calloc(sizeof(tc_entity_s), 1); ++registry.num_entities; + + registry.entities[entity_index]->attributes_capacity = 8; + registry.entities[entity_index]->attributes = + calloc(sizeof(tc_entity_attribute_s), registry.entities[entity_index]->attributes_capacity); + + tc_reset_entity(registry.entities[entity_index]); return registry.entities[entity_index]; } ++entity_index; } - registry.entities_capacity *= 2; registry.entities = - realloc(registry.entities, sizeof(tc_entity_s *) * registry.entities_capacity); + realloc(registry.entities, sizeof(tc_entity_s *) * registry.entities_capacity * 2); + memset(®istry.entities[registry.entities_capacity], 0x00, sizeof(tc_entity_s *) * registry.entities_capacity); + registry.entities_capacity *= 2; registry.entities[registry.num_entities] = malloc(sizeof(tc_entity_s)); + tc_reset_entity(registry.entities[registry.num_entities]); ++registry.num_entities; return registry.entities[registry.num_entities-1]; diff --git a/code/source-c/initialization.c b/code/source-c/initialization.c index ed50b9b..3c8863a 100644 --- a/code/source-c/initialization.c +++ b/code/source-c/initialization.c @@ -73,6 +73,8 @@ void tc_init() tc_game_state_g.viewer = tc_game_state_g.player; tc_init_worlds(); tc_game_state_g.main_world = tc_new_world(&tc_default_terrain_generator_g); + tc_game_state_g.tps = 120; + puts("Finished initializing!"); } diff --git a/code/source-c/main.c b/code/source-c/main.c index b7cbadf..ad95164 100644 --- a/code/source-c/main.c +++ b/code/source-c/main.c @@ -184,6 +184,8 @@ bool go_backwards = false; bool rotate_left = false; bool rotate_right = false; +uint64_t tc_last_update = 0; + bool update() { tc_vec3_s camera_rotation; @@ -375,6 +377,9 @@ bool update() tc_update_world(tc_game_state_g.main_world); + // uint64_t current_ms = SDL_GetTicks64(); + // uint32_t ticks_between = current_ms - tc_last_update; + return true; } @@ -389,6 +394,8 @@ int main(int argc, char **argv) { frame_index = -1; } + tc_tick_intervals(); + render(); if(frame_index == 1) @@ -397,7 +404,7 @@ int main(int argc, char **argv) } ++frame_index; - SDL_Delay(1000/60); + SDL_Delay(2); } tc_cleanup(); diff --git a/code/source-c/state.h b/code/source-c/state.h index 5cd66a2..9a65520 100644 --- a/code/source-c/state.h +++ b/code/source-c/state.h @@ -41,6 +41,9 @@ typedef struct tc_entity_s *viewer; tc_entity_s *player; + uint16_t fps; + uint16_t tps; + tc_image_s *block_texture_atlas; } techneck_s; diff --git a/code/source-c/world.c b/code/source-c/world.c index 38afe5f..babc6ab 100644 --- a/code/source-c/world.c +++ b/code/source-c/world.c @@ -5,6 +5,7 @@ #include tc_worldgen_s tc_default_terrain_generator_g; +tc_entity_type_s *tc_chunk_entity_type_g = NULL; void tc_upload_chunk(tc_chunk_s *chunk) { @@ -36,8 +37,11 @@ void tc_upload_chunk(tc_chunk_s *chunk) ); glBindVertexArray(0); } -void tc_draw_chunk(tc_chunk_s *chunk, tc_world_s *world) + +void tc_draw_chunk_entity(tc_entity_s *entity) { + tc_chunk_s *chunk = entity->specific; + mat4x4 model_matrix; mat4x4_identity(model_matrix); mat4x4_translate_in_place(model_matrix, chunk->position.x*32, chunk->position.y*32, -chunk->position.z*32); @@ -75,9 +79,78 @@ void tc_init_world_generators() tc_default_terrain_generator_g.name = "Default Terrain Generator"; tc_default_terrain_generator_g.fn_generate_chunk = &tc_generate_default_terrain_chunk; } + + + +tc_entity_s * tc_create_chunk_entity() +{ + tc_entity_s *chunk = tc_allocate_entity(); + tc_set_string_for_entity(chunk, "type", "chunk"); + tc_set_integer_for_entity(chunk, "grid_x", 0); + tc_set_integer_for_entity(chunk, "grid_y", 0); + tc_set_integer_for_entity(chunk, "grid_z", 0); + chunk->specific = tc_allocate_chunk(); + + return chunk; +} + +void tc_spawn_chunk_entity(tc_entity_s *entity, tc_location_s location) +{ + + + +} + +void tc_teleport_chunk_entity(tc_entity_s *entity, tc_location_s location) +{ + tc_chunk_s *chunk = entity->specific; + chunk->world = location.world; + chunk->position.x = location.position.x / 32; + chunk->position.y = location.position.y / 32; + chunk->position.z = location.position.z / 32; + + + +} + +void tc_delete_chunk_entity(tc_entity_s *entity) +{ + tc_free_chunk(entity->specific); + + + +} + +void tc_receive_chunk_entity_event(tc_entity_s *entity, tc_entity_event_s event) +{ + + + +} + +void tc_add_chunk_entity_type() +{ + tc_fn_entity_s chunk_functions; + chunk_functions.fn_create = &tc_create_chunk_entity; + chunk_functions.fn_spawn = &tc_spawn_chunk_entity; + chunk_functions.fn_teleport = &tc_teleport_chunk_entity; + chunk_functions.fn_draw = &tc_draw_chunk_entity; + chunk_functions.fn_delete = &tc_delete_chunk_entity; + chunk_functions.fn_send_event = &tc_receive_chunk_entity_event; + + tc_entity_type_s chunk_type; + chunk_type.internal_name = "chunk"; + chunk_type.display_name = NULL; + chunk_type.functions = chunk_functions; + + tc_register_entity_type(chunk_type); + tc_chunk_entity_type_g = tc_get_entity_type_with_name("chunk"); +} void tc_init_worlds() { + tc_init_chunk_pool(256); + tc_add_chunk_entity_type(); tc_init_world_generators(); } @@ -91,14 +164,10 @@ void tc_set_block_in_chunk( chunk->blocks[x][y][z] = block.type_identifier; } - void tc_draw_world(tc_world_s *world) { - for(uint32_t loader_index = 0; loader_index < world->num_loaders; ++loader_index) - for(uint32_t chunk_index = 0; chunk_index < world->loaders[loader_index].num_chunks; ++chunk_index) - tc_draw_chunk(world->loaders[loader_index].chunks[chunk_index], world); + tc_draw_all_entities_of_type("chunk"); } - tc_chunkloader_s tc_create_chunkloader(tc_world_s *world) { tc_chunkloader_s loader; @@ -128,7 +197,6 @@ tc_chunkloader_s tc_create_spawn_loader(tc_world_s *world) tc_world_s * tc_new_world(tc_worldgen_s *generator) { tc_world_s *world = calloc(sizeof(tc_world_s), 1); - world->pool = tc_new_chunk_pool(512); world->worldgen = &tc_default_terrain_generator_g; world->num_loaders = 1; world->loaders = malloc(sizeof(tc_chunkloader_s) * world->num_loaders); diff --git a/code/source-c/world.h b/code/source-c/world.h index 066ac93..970e520 100644 --- a/code/source-c/world.h +++ b/code/source-c/world.h @@ -38,6 +38,7 @@ struct tc_block struct tc_chunk { + tc_world_s *world; tc_chunk_pool_entry_s *pool_entry; tc_vec3i_s position; @@ -75,6 +76,8 @@ typedef struct tc_chunkloader struct tc_chunk_pool { + tc_world_s *world; + uint32_t capacity; uint32_t used_entries; tc_chunk_pool_entry_s *entries; @@ -130,9 +133,9 @@ void tc_on_each_loaded_chunk ( void *userdata ); -tc_chunk_pool_s * tc_new_chunk_pool (uint32_t capacity); -tc_chunk_s * tc_allocate_chunk (tc_world_s *world); -void tc_free_chunk (tc_world_s *world, tc_chunk_s *chunk); +void tc_init_chunk_pool (uint32_t capacity); +tc_chunk_s * tc_allocate_chunk (); +void tc_free_chunk (tc_chunk_s *chunk); #endif