From bb74d13e89e3daa9d6d040bda0beb7e9a4568248 Mon Sep 17 00:00:00 2001 From: Eric-Paul Ickhorn Date: Tue, 17 Oct 2023 22:13:54 +0200 Subject: [PATCH] Multithreading for chunks --- build.bash | 9 +- code/source-c/entity/entity.c | 72 ++++++ code/source-c/entity/entity.h | 24 +- code/source-c/initialization.c | 11 +- code/source-c/main.c | 10 +- code/source-c/state.h | 2 +- code/source-c/utility/math.c | 6 + code/source-c/utility/math.h | 2 + code/source-c/utility/promise.h | 15 ++ code/source-c/world/update/internal.h | 103 +++++++++ .../world/update/promise_reservation.c | 217 ++++++++++++++++++ code/source-c/world/update/queue.c | 76 ++++++ code/source-c/world/update/respond.c | 65 ++++++ .../world/update/world_configuration.h | 16 ++ code/source-c/world/update/world_update.c | 212 +++++++++++++++++ code/source-c/world/update/world_update.h | 36 +++ 16 files changed, 864 insertions(+), 12 deletions(-) create mode 100644 code/source-c/utility/promise.h create mode 100644 code/source-c/world/update/internal.h create mode 100644 code/source-c/world/update/promise_reservation.c create mode 100644 code/source-c/world/update/queue.c create mode 100644 code/source-c/world/update/respond.c create mode 100644 code/source-c/world/update/world_configuration.h create mode 100644 code/source-c/world/update/world_update.c create mode 100644 code/source-c/world/update/world_update.h diff --git a/build.bash b/build.bash index 03cee03..7b63132 100644 --- a/build.bash +++ b/build.bash @@ -7,6 +7,13 @@ gcc -g3 -o dependencies/build/glad.o \ -I dependencies/include/ -Wall gcc -g3 -o techneck.elf \ - code/source-c/*.c code/source-c/entity/*.c code/source-c/utility/*.c code/source-c/world/*.c code/source-c/world/generator/*.c code/source-c/physics/*.c dependencies/build/glad.o \ + code/source-c/*.c \ + code/source-c/entity/*.c \ + code/source-c/utility/*.c \ + code/source-c/world/*.c \ + code/source-c/world/update/*.c \ + code/source-c/world/generator/*.c \ + code/source-c/physics/*.c \ + dependencies/build/glad.o \ -I dependencies/include -I code/source-c/ -lGL -lSDL2 -lm -Wall diff --git a/code/source-c/entity/entity.c b/code/source-c/entity/entity.c index 7e16b07..b29b156 100644 --- a/code/source-c/entity/entity.c +++ b/code/source-c/entity/entity.c @@ -14,6 +14,9 @@ tc_entity_registry_s tc_init_entity_registry() registry.num_intervals = 0; registry.intervals = calloc(sizeof(tc_interval_s *), registry.intervals_capacity); registry.pool = tc_create_entity_pool(512); + registry.tags_capacity = 512; + registry.num_tags = 0; + registry.tags = calloc(sizeof(tc_entity_tag_s), registry.tags_capacity); return registry; } @@ -376,6 +379,75 @@ void tc_tick_intervals() } } + + +tc_entity_tag_s * tc_get_tag(char *name) +{ + for(u32_t tag_index = 0; tag_index < tc_game_state_g.entity_registry.num_tags; ++tag_index) + { + if(!strcmp(tc_game_state_g.entity_registry.tags[tag_index].name, name)) + return &tc_game_state_g.entity_registry.tags[tag_index]; + } + return NULL; +} + +tc_entity_tag_s * tc_allocate_tag(char *name) +{ + if(tc_game_state_g.entity_registry.num_tags + >= + tc_game_state_g.entity_registry.tags_capacity + ) { + tc_game_state_g.entity_registry.tags_capacity *= 2; + tc_game_state_g.entity_registry.tags = + realloc(tc_game_state_g.entity_registry.tags, sizeof(tc_entity_tag_s) * tc_game_state_g.entity_registry.tags_capacity); + } + tc_entity_tag_s *tag = &tc_game_state_g.entity_registry.tags[tc_game_state_g.entity_registry.num_tags]; + + tag->name = name; + tag->users_capacity = 64; + tag->num_users = 0; + tag->users = calloc(sizeof(tc_entity_s *), tag->users_capacity); + ++tag->num_users; + + return tag; + +} +tc_entity_tag_s * tc_get_or_allocate_tag(char *name) +{ + tc_entity_tag_s *tag = tc_get_tag(name); + if(tag == NULL) return tc_allocate_tag(name); + return tag; +} + +void tc_add_user_to_tag(tc_entity_tag_s *tag, tc_entity_s *entity) +{ + if(tag->num_users >= tag->users_capacity) + { + tag->users_capacity *= 2; + tag->users = realloc(tag->users, sizeof(tc_entity_s *) * tag->users_capacity); + } + tag->users[tag->num_users] = entity; + ++tag->num_users; +} + +void tc_tag_entity(tc_entity_s *entity, char *name) +{ + tc_entity_tag_s *tag = tc_get_or_allocate_tag(name); + tc_add_user_to_tag(tag, entity); +} + +u32_t tc_count_entitites_with_tag(char *name) +{ + return tc_get_tag(name)->num_users; +} + +void tc_list_entities_with_tag(char *name, tc_entity_s **entities, u32_t max) +{ + tc_entity_tag_s *tag = tc_get_tag(name); + + memcpy(entities, tag->users, tc_min(max, tag->num_users) * sizeof(tc_entity_s *)); +} + /* void tc_draw_all_entities_of_type(char *name) { diff --git a/code/source-c/entity/entity.h b/code/source-c/entity/entity.h index 093a6a3..af1a77d 100644 --- a/code/source-c/entity/entity.h +++ b/code/source-c/entity/entity.h @@ -13,6 +13,7 @@ typedef struct tc_entity tc_entity_s; typedef struct tc_entity_pool tc_entity_pool_s; typedef struct tc_entity_pool_entry tc_entity_pool_entry_s; typedef struct tc_entity_registry tc_entity_registry_s; +typedef struct tc_entity_tag tc_entity_tag_s; typedef void (*tc_entity_create_fn) (tc_entity_s *entity, void *userdata); typedef void (*tc_entity_delete_fn) (tc_entity_s *entity); @@ -51,6 +52,16 @@ struct tc_entity_type tc_entity_s **instances; }; +struct tc_entity_tag +{ + char *name; + + u32_t users_capacity; + u32_t num_users; + tc_entity_s **users; + +}; + struct tc_entity_attribute { char *name; @@ -116,6 +127,10 @@ struct tc_entity_registry u32_t intervals_capacity; u32_t num_intervals; tc_interval_s *intervals; + + u32_t tags_capacity; + u32_t num_tags; + tc_entity_tag_s *tags; }; tc_entity_pool_s * tc_create_entity_pool (u32_t capacity); @@ -137,17 +152,22 @@ char * tc_get_string_from_entity (tc_entity_s *en i64_t tc_get_integer_from_entity (tc_entity_s *entity, char *attr_name); f64_t tc_get_float_from_entity (tc_entity_s *entity, char *attr_name); +void tc_tag_entity (tc_entity_s *entity, char *name); + void tc_send_pointer_to_entity (tc_entity_s *entity, char *event_name, void *pointer); void tc_send_string_to_entity (tc_entity_s *entity, char *event_name, char *string); void tc_send_integer_to_entity (tc_entity_s *entity, char *event_name, i64_t integer); void tc_send_float_to_entity (tc_entity_s *entity, char *event_name, f64_t 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_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); +u32_t tc_count_entitites_with_tag (char *name); +void tc_list_entities_with_tag (char *name, tc_entity_s **entities, u32_t max); + #endif // TC_ENTITY_H diff --git a/code/source-c/initialization.c b/code/source-c/initialization.c index 84cbb0e..76ddfe3 100644 --- a/code/source-c/initialization.c +++ b/code/source-c/initialization.c @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -62,7 +63,11 @@ void tc_load_textures() void tc_init() { - tc_init_renderer(&tc_game_state_g); + tc_start_world_updater(); + tc_init_renderer (&tc_game_state_g); + + + tc_promise_s main_world_promise = tc_worldupdate_register_world (); tc_game_state_g.asset_storage = tc_init_asset_storage("assets/"); tc_load_textures(); tc_game_state_g.block_registry = tc_init_blocks(); @@ -74,7 +79,7 @@ void tc_init() tc_add_to_hooklist(&tc_game_state_g.on_world_create, (tc_fn_hook) &tc_create_world_physics, NULL); tc_init_worlds(); - tc_game_state_g.main_world = tc_new_world(&tc_default_terrain_generator_g); + // tc_game_state_g.main_world = tc_new_world(&tc_default_terrain_generator_g); tc_game_state_g.player = tc_create_entity("player", NULL); tc_game_state_g.viewer = tc_game_state_g.player; @@ -89,7 +94,7 @@ void tc_init() void tc_cleanup() { - tc_unload_world(tc_game_state_g.main_world); + // tc_unload_world(tc_game_state_g.main_world); tc_cleanup_chunk_pool(); SDL_GL_DeleteContext(tc_game_state_g.renderer.gl_context); SDL_DestroyWindow(tc_game_state_g.renderer.window); diff --git a/code/source-c/main.c b/code/source-c/main.c index a7a33cf..bf105e4 100644 --- a/code/source-c/main.c +++ b/code/source-c/main.c @@ -83,7 +83,7 @@ void render() tc_shader_uniform_mat4f(&tc_game_state_g.renderer.draw_shader, "projection_matrix", projection_matrix); tc_shader_uniform_mat4f(&tc_game_state_g.renderer.draw_shader, "view_matrix", view_matrix); - tc_draw_world(tc_game_state_g.main_world); + // tc_draw_world(tc_game_state_g.main_world); SDL_GL_SwapWindow(tc_game_state_g.renderer.window); } @@ -284,11 +284,11 @@ bool update() tc_move_viewer_to(camera_position.x, camera_position.y, camera_position.z); tc_rotate_viewer_to(camera_rotation.x, camera_rotation.y, camera_rotation.z); - tc_game_state_g.main_world->spawn_loader->center.grid_coords.x = ((int32_t) camera_position.x) / 32 - UPDATE_DISTANCE; - tc_game_state_g.main_world->spawn_loader->center.grid_coords.y = ((int32_t) camera_position.y) / 32 - UPDATE_DISTANCE; - tc_game_state_g.main_world->spawn_loader->center.grid_coords.z = - ((int32_t) camera_position.z) / 32 - UPDATE_DISTANCE; + // tc_game_state_g.main_world->spawn_loader->center.grid_coords.x = ((int32_t) camera_position.x) / 32 - UPDATE_DISTANCE; + // tc_game_state_g.main_world->spawn_loader->center.grid_coords.y = ((int32_t) camera_position.y) / 32 - UPDATE_DISTANCE; + // tc_game_state_g.main_world->spawn_loader->center.grid_coords.z = - ((int32_t) camera_position.z) / 32 - UPDATE_DISTANCE; - tc_update_world(tc_game_state_g.main_world); + // tc_update_world(tc_game_state_g.main_world); return true; } diff --git a/code/source-c/state.h b/code/source-c/state.h index ec86260..241ffd1 100644 --- a/code/source-c/state.h +++ b/code/source-c/state.h @@ -37,7 +37,7 @@ typedef struct tc_asset_storage_s asset_storage; tc_block_registry_s block_registry; tc_entity_registry_s entity_registry; - tc_world_s *main_world; + // tc_world_s *main_world; tc_entity_s *viewer; tc_entity_s *player; diff --git a/code/source-c/utility/math.c b/code/source-c/utility/math.c index a06e98d..90169ce 100644 --- a/code/source-c/utility/math.c +++ b/code/source-c/utility/math.c @@ -10,3 +10,9 @@ f32_t tc_rad_to_deg(f32_t radians) return radians / (3.1415*2.0f) * 360.0f; } +i64_t tc_min(i64_t first, i64_t second) +{ + if(first < second) return first; + return second; +} + diff --git a/code/source-c/utility/math.h b/code/source-c/utility/math.h index 44182f9..3ce1f31 100644 --- a/code/source-c/utility/math.h +++ b/code/source-c/utility/math.h @@ -72,6 +72,8 @@ struct tc_mat3f f32_t tc_deg_to_rad (f32_t degrees); f32_t tc_rad_to_deg (f32_t radians); +i64_t tc_min (i64_t first, i64_t second); + bool_t tc_vec4f_equ (tc_vec4f_s vector_1, tc_vec4f_s vector_2); bool_t tc_vec3f_equ (tc_vec3f_s vector_1, tc_vec3f_s vector_2); bool_t tc_vec2f_equ (tc_vec2f_s vector_1, tc_vec2f_s vector_2); diff --git a/code/source-c/utility/promise.h b/code/source-c/utility/promise.h new file mode 100644 index 0000000..71445b6 --- /dev/null +++ b/code/source-c/utility/promise.h @@ -0,0 +1,15 @@ + +#ifndef TC_PROMISE_H +#define TC_PROMISE_H + +#include + +typedef struct +{ + u64_t issueing_tick; + u32_t identifier; + +} tc_promise_s; + +#endif + diff --git a/code/source-c/world/update/internal.h b/code/source-c/world/update/internal.h new file mode 100644 index 0000000..3b4f8b3 --- /dev/null +++ b/code/source-c/world/update/internal.h @@ -0,0 +1,103 @@ + +#ifndef TC_WORLD_UPDATER_INTERNAL_H +#define TC_WORLD_UPDATER_INTERNAL_H + +#include +#include +#include + +typedef struct tc_world_updater_queue tc_world_updater_queue_s; +typedef struct tc_world_updater_command tc_world_updater_command_s; + +typedef enum +{ + TC_WORLD_UPDATER_COMMAND_UNKNOWN, + TC_WORLD_UPDATER_COMMAND_MOVE_CHUNKLOADER, + TC_WORLD_UPDATER_COMMAND_PLACE_BLOCK, + TC_WORLD_UPDATER_COMMAND_STOP, + TC_WORLD_UPDATER_COMMAND_ADD_WORLD, + TC_WORLD_UPDATER_COMMAND_ADD_CHUNKLOADER, + TC_WORLD_UPDATER_COMMAND_DELETE_CHUNKLOADER, + TC_WORLD_UPDATER_COMMAND_GET_WORLD, + TC_WORLD_UPDATER_COMMAND_GET_CHUNKLOADER, + TC_WORLD_UPDATER_COMMAND_GET_CHUNKLIST + +} tc_world_update_command_e; + +struct tc_world_updater_command +{ + tc_world_updater_command_s *next; + tc_world_updater_command_s *previous; + + tc_world_update_command_e type; + + union command + { + struct move_chunkloader_command + { + u32_t loader_id; + tc_chunk_location_s new_location; + } move_chunkloader; + + struct place_block_command + { + tc_block_s block; + tc_block_location_s location; + + } place_block; + + struct get_item + { + u32_t index; + u32_t promise; + + } get_item; + + } specific; + + bool_t is_used; +}; + +struct tc_world_updater_queue +{ + tc_world_updater_command_s *first; + tc_world_updater_command_s *last; + bool_t in_action; + + u32_t capacity; + tc_world_updater_command_s *commands; +}; + +void tc_worldupdate_initialize_promises (); +tc_world_updater_queue_s tc_new_world_updater_queue (u32_t capacity); +bool_t tc_issue_world_updater_command ( + tc_world_updater_queue_s *queue, tc_world_updater_command_s command +); + +tc_world_updater_command_s tc_world_updater_query_next_command + (tc_world_updater_queue_s *queue); + + +tc_promise_s tc_worldupdate_reserve_world_promise (); +tc_promise_s tc_worldupdate_reserve_chunkloader_promise (); +tc_promise_s tc_worldupdate_reserve_chunklist_promise (); + +void tc_worldupate_set_world_promise (u32_t identifier, tc_world_s *world); +void tc_worldupate_set_chunkloader_promise (u32_t identifier, tc_chunkloader_s *chunkloader); +void tc_worldupate_set_chunklist_promise (u32_t identifier, tc_chunklist_s *chunklist); + +tc_world_updater_queue_s tc_new_world_updater_queue + (u32_t capacity); + +void tc_worldupdater_execute_move_chunkloader (tc_world_updater_command_s command); +void tc_worldupdater_execute_place_block (tc_world_updater_command_s command); +void tc_worldupdater_execute_stop (tc_world_updater_command_s command); +void tc_worldupdater_execute_add_world (tc_world_updater_command_s command); +void tc_worldupdater_execute_add_chunkloader (tc_world_updater_command_s command); +void tc_worldupdater_execute_delete_chunkloader (tc_world_updater_command_s command); +void tc_worldupdater_execute_get_world (tc_world_updater_command_s command); +void tc_worldupdater_execute_get_chunkloader (tc_world_updater_command_s command); +void tc_worldupdater_execute_get_chunklist (tc_world_updater_command_s command); + +#endif // TC_WORLD_UPDATER_INTERNAL_H + diff --git a/code/source-c/world/update/promise_reservation.c b/code/source-c/world/update/promise_reservation.c new file mode 100644 index 0000000..dd22761 --- /dev/null +++ b/code/source-c/world/update/promise_reservation.c @@ -0,0 +1,217 @@ +#include + +#include +#include + +u32_t tc_promise_identifier_counter = 0; + +typedef struct +{ + u32_t identifier; + tc_world_s *world; + +} tc_worldupdate_world_promise_s; + +typedef struct +{ + u32_t identifier; + tc_chunkloader_s *chunkloader; + +} tc_worldupdate_chunkloader_promise_s; + +typedef struct +{ + u32_t identifier; + tc_chunklist_s *chunklist; + +} tc_worldupdate_chunklist_promise_s; + +tc_worldupdate_world_promise_s *tc_worldupdate_worlds_promise_registry = NULL; +tc_worldupdate_chunkloader_promise_s *tc_worldupdate_chunkloader_promise_registry = NULL; +tc_worldupdate_chunklist_promise_s *tc_worldupdate_chunklist_promise_registry = NULL; + +#define TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE 4096 + +void tc_worldupdate_initialize_promises() +{ + tc_worldupdate_worlds_promise_registry = calloc(sizeof(tc_worldupdate_world_promise_s), TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE); + tc_worldupdate_chunkloader_promise_registry = calloc(sizeof(tc_worldupdate_chunkloader_promise_s), TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE); + tc_worldupdate_chunklist_promise_registry = calloc(sizeof(tc_worldupdate_chunklist_promise_s), TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE); +} + + + +tc_promise_s tc_worldupdate_reserve_world_promise() +{ + u32_t index = 0; + while(index < TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE) + { + tc_worldupdate_world_promise_s *entry = &tc_worldupdate_worlds_promise_registry[index]; + if(entry->identifier == 0) + if(entry->world != NULL) + { + ++tc_promise_identifier_counter; + tc_promise_s promise; + promise.identifier = tc_promise_identifier_counter; + entry->identifier = promise.identifier; + entry->world = NULL; + + return promise; + } + + ++index; + } + tc_promise_s promise; + promise.identifier = 0; + promise.issueing_tick = 0; + return promise; +} + +tc_promise_s tc_worldupdate_reserve_chunkloader_promise() +{ + u32_t index = 0; + while(index < TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE) + { + tc_worldupdate_chunkloader_promise_s *entry = &tc_worldupdate_chunkloader_promise_registry[index]; + if(entry->identifier == 0) + if(entry->chunkloader != NULL) + { + ++tc_promise_identifier_counter; + tc_promise_s promise; + promise.identifier = tc_promise_identifier_counter; + entry->identifier = promise.identifier; + entry->chunkloader = NULL; + + return promise; + } + + ++index; + } + tc_promise_s promise; + promise.identifier = 0; + promise.issueing_tick = 0; + return promise; +} + +tc_promise_s tc_worldupdate_reserve_chunklist_promise() +{ + u32_t index = 0; + while(index < TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE) + { + tc_worldupdate_chunklist_promise_s *entry = &tc_worldupdate_chunklist_promise_registry[index]; + if(entry->identifier == 0) + if(entry->chunklist != NULL) + { + ++tc_promise_identifier_counter; + tc_promise_s promise; + promise.identifier = tc_promise_identifier_counter; + entry->identifier = promise.identifier; + entry->chunklist = NULL; + + return promise; + } + + ++index; + } + tc_promise_s promise; + promise.identifier = 0; + promise.issueing_tick = 0; + return promise; +} + + + +const tc_world_s * tc_worldupdate_claim_world_promise(tc_promise_s promise) +{ + u32_t index = 0; + while(index < TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE) + { + tc_worldupdate_world_promise_s *entry = &tc_worldupdate_worlds_promise_registry[index]; + if(entry->identifier == promise.identifier) + if(entry->world != NULL) + { + entry->identifier = 0; + return entry->world; + } + + ++index; + } + return NULL; +} + +const tc_chunkloader_s * tc_worldupdate_claim_chunkloader_promise(tc_promise_s promise) +{ + u32_t index = 0; + while(index < TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE) + { + tc_worldupdate_chunkloader_promise_s *entry = &tc_worldupdate_chunkloader_promise_registry[index]; + if(entry->identifier == promise.identifier) + if(entry->chunkloader != NULL) + { + entry->identifier = 0; + return entry->chunkloader; + } + + ++index; + } + return NULL; +} + +const tc_chunklist_s * tc_worldupdate_claim_chunks_promise(tc_promise_s promise) +{ + u32_t index = 0; + while(index < TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE) + { + tc_worldupdate_chunklist_promise_s *entry = &tc_worldupdate_chunklist_promise_registry[index]; + if(entry->identifier == promise.identifier) + if(entry->chunklist != NULL) + { + entry->identifier = 0; + return entry->chunklist; + } + + ++index; + } + return NULL; +} + + + +void tc_worldupate_set_world_promise(u32_t identifier, tc_world_s *world) +{ + u32_t index = 0; + while(index < TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE) + { + tc_worldupdate_world_promise_s *entry = &tc_worldupdate_worlds_promise_registry[index]; + if(entry->identifier == identifier) + entry->world = world; + + ++index; + } +} + +void tc_worldupate_set_chunkloader_promise(u32_t identifier, tc_chunkloader_s *chunkloader) +{u32_t index = 0; + while(index < TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE) + { + tc_worldupdate_chunkloader_promise_s *entry = &tc_worldupdate_chunkloader_promise_registry[index]; + if(entry->identifier == identifier) + entry->chunkloader = chunkloader; + + ++index; + } +} + +void tc_worldupate_set_chunklist_promise(u32_t identifier, tc_chunklist_s *chunklist) +{ + u32_t index = 0; + while(index < TC_WORLDUPDATE_PROMISE_REGISTRY_SIZE) + { + tc_worldupdate_chunklist_promise_s *entry = &tc_worldupdate_chunklist_promise_registry[index]; + if(entry->identifier == identifier) + entry->chunklist = chunklist; + + ++index; + } +} + diff --git a/code/source-c/world/update/queue.c b/code/source-c/world/update/queue.c new file mode 100644 index 0000000..acecfcc --- /dev/null +++ b/code/source-c/world/update/queue.c @@ -0,0 +1,76 @@ +#include + +#include +#include +#include + +tc_world_updater_queue_s tc_new_world_updater_queue(u32_t capacity) +{ + tc_world_updater_queue_s queue; + queue.capacity = capacity; + queue.commands = calloc(sizeof(tc_world_updater_command_s), capacity); + queue.first = NULL; + queue.last = NULL; + queue.in_action = FALSE; + + return queue; +} + +// tc_allocate_world_updater_command: Returns a pointer to a command-slot in the given queue. +// Sub-function of tc_issue_world_updater_command +tc_world_updater_command_s * tc_allocate_world_updater_command(tc_world_updater_queue_s *queue) +{ + u32_t command_index = 0; + while(command_index < queue->capacity) + { + if(!queue->commands[command_index].is_used) + return &queue->commands[command_index]; + + ++command_index; + } + return NULL; +} + +bool_t tc_issue_world_updater_command(tc_world_updater_queue_s *queue, tc_world_updater_command_s command) +{ + while(queue->in_action) continue; + queue->in_action = TRUE; + + tc_world_updater_command_s *queue_command = tc_allocate_world_updater_command(queue); + if(queue_command == NULL) return FALSE; + + command.is_used = TRUE; + (*queue_command) = command; + queue_command->previous = queue->last; + queue_command->next = NULL; + + if(queue->last != NULL) queue->last->next = queue_command; + if(queue->first == NULL) queue->first = queue_command; + queue->last = queue_command; + + queue->in_action = FALSE; + + return TRUE; +} + +tc_world_updater_command_s tc_world_updater_query_next_command(tc_world_updater_queue_s *queue) +{ + while(queue->in_action) continue; + queue->in_action = TRUE; + + tc_world_updater_command_s *queue_command = queue->first; + tc_world_updater_command_s command; + memset(&command, 0x00, sizeof(tc_world_updater_command_s)); + + if(queue_command != NULL) + { + command = *queue_command; + + queue_command->is_used = FALSE; + } + queue->in_action = FALSE; + + return command; +} + + diff --git a/code/source-c/world/update/respond.c b/code/source-c/world/update/respond.c new file mode 100644 index 0000000..eda5b65 --- /dev/null +++ b/code/source-c/world/update/respond.c @@ -0,0 +1,65 @@ +#include + +void tc_worldupdater_execute_move_chunkloader(tc_world_updater_command_s command) +{ + + + +} + +void tc_worldupdater_execute_place_block(tc_world_updater_command_s command) +{ + + + +} + +void tc_worldupdater_execute_stop(tc_world_updater_command_s command) +{ + + + +} + +void tc_worldupdater_execute_add_world(tc_world_updater_command_s command) +{ + + + +} + +void tc_worldupdater_execute_add_chunkloader(tc_world_updater_command_s command) +{ + + + +} + +void tc_worldupdater_execute_delete_chunkloader(tc_world_updater_command_s command) +{ + + + +} + +void tc_worldupdater_execute_get_world(tc_world_updater_command_s command) +{ + + + +} + +void tc_worldupdater_execute_get_chunkloader(tc_world_updater_command_s command) +{ + + + +} + +void tc_worldupdater_execute_get_chunklist(tc_world_updater_command_s command) +{ + + + +} + diff --git a/code/source-c/world/update/world_configuration.h b/code/source-c/world/update/world_configuration.h new file mode 100644 index 0000000..76795d8 --- /dev/null +++ b/code/source-c/world/update/world_configuration.h @@ -0,0 +1,16 @@ + +#ifndef TC_WORLD_CONFIGURATION_H +#define TC_WORLD_CONFIGURATION_H + +#include +#include +#include +#include + +void tc_activate_world (u32_t identifier); +void tc_deactivate_world (u32_t identifier); + +void tc_update_world (u32_t identifier); + +#endif TC_WORLD_CONFIGURATION_H + diff --git a/code/source-c/world/update/world_update.c b/code/source-c/world/update/world_update.c new file mode 100644 index 0000000..d7a930b --- /dev/null +++ b/code/source-c/world/update/world_update.c @@ -0,0 +1,212 @@ +#include +#include + +typedef struct tc_world_registry +{ + u32_t worlds_capacity; + u32_t num_worlds; + tc_world_s *worlds; + +} tc_world_registry_s; + +typedef struct tc_world_updater +{ + bool_t running; + tc_world_updater_queue_s queue; + tc_world_registry_s world_registry; + + SDL_Thread *sdl_thread; + +} tc_world_updater_s; + +tc_world_updater_s *tc_world_updater_g = NULL; + +#define TICKS_PER_SECOND 2 +#define WORLD_UPDATES_PER_SECOND 0.5 + +void tc_update_all_worlds(tc_world_registry_s *registry) +{ + for(u32_t world_index = 0; world_index < registry->num_worlds; ++world_index) + { + tc_world_s *world = ®istry->worlds[world_index]; + tc_update_world(world); + } +} + +void tc_world_updater_run(void *data) +{ + u64_t tick_at_start = 0; + + u64_t world_update_count = 0; + + tc_world_updater_s *updater = data; + updater->running = TRUE; + while(updater->running) + { + tick_at_start = SDL_GetTicks(); + + if((tick_at_start / WORLD_UPDATES_PER_SECOND) == world_update_count) + { + + ++world_update_count; + } + + if(tc_world_updater_g->queue.in_action) + { + while(tc_world_updater_g->queue.in_action) continue; + } + + tc_world_updater_command_s command = + tc_world_updater_query_next_command(&tc_world_updater_g->queue); + + switch(command.type) + { + case TC_WORLD_UPDATER_COMMAND_UNKNOWN: break; + case TC_WORLD_UPDATER_COMMAND_MOVE_CHUNKLOADER: tc_worldupdater_execute_move_chunkloader(command); + case TC_WORLD_UPDATER_COMMAND_PLACE_BLOCK: tc_worldupdater_execute_place_block(command); + case TC_WORLD_UPDATER_COMMAND_STOP: tc_worldupdater_execute_stop(command); + case TC_WORLD_UPDATER_COMMAND_ADD_WORLD: tc_worldupdater_execute_add_world(command); + case TC_WORLD_UPDATER_COMMAND_ADD_CHUNKLOADER: tc_worldupdater_execute_add_chunkloader(command); + case TC_WORLD_UPDATER_COMMAND_DELETE_CHUNKLOADER: tc_worldupdater_execute_delete_chunkloader(command); + case TC_WORLD_UPDATER_COMMAND_GET_WORLD: tc_worldupdater_execute_get_world(command); + case TC_WORLD_UPDATER_COMMAND_GET_CHUNKLOADER: tc_worldupdater_execute_get_chunkloader(command); + case TC_WORLD_UPDATER_COMMAND_GET_CHUNKLIST: tc_worldupdater_execute_get_chunklist(command); + } + + u64_t tick_at_end = SDL_GetTicks(); + + + + SDL_Delay((1000 / TICKS_PER_SECOND) - (tick_at_end - tick_at_start)); + } +} + +tc_world_registry_s tc_new_world_registry() +{ + tc_world_registry_s registry; + registry.num_worlds = 0; + registry.worlds_capacity = 64; + registry.worlds = calloc(sizeof(tc_world_s), registry.worlds_capacity); + + return registry; +} + +void tc_start_world_updater() +{ + tc_worldupdate_initialize_promises(4096); + + tc_world_updater_g = malloc(sizeof(tc_world_updater_s)); + tc_world_updater_g->world_registry = tc_new_world_registry(); + tc_world_updater_g->sdl_thread = SDL_CreateThread((SDL_ThreadFunction) &tc_world_updater_run, "w_update", &tc_world_updater_g); + tc_world_updater_g->queue = tc_new_world_updater_queue(4096); + + SDL_DetachThread(tc_world_updater_g->sdl_thread); +} + +tc_promise_s tc_worldupdate_register_world() +{ + tc_promise_s promise = tc_worldupdate_reserve_world_promise(); + + + return promise; +} + +tc_promise_s tc_worldupdate_add_chunkloader() +{ + tc_promise_s promise = tc_worldupdate_reserve_chunkloader_promise(); + tc_world_updater_command_s command; + command.type = TC_WORLD_UPDATER_COMMAND_ADD_CHUNKLOADER; + tc_issue_world_updater_command(&tc_world_updater_g->queue, command); + + return promise; +} + +void tc_worldupdate_delete_chunkloader(u32_t loader_id) +{ + tc_world_updater_command_s command; + command.type = TC_WORLD_UPDATER_COMMAND_DELETE_CHUNKLOADER; + command.specific.get_item.index = loader_id; + + tc_issue_world_updater_command(&tc_world_updater_g->queue, command); +} + +u32_t tc_worldupdate_get_chunkloader_count_of_world(u32_t world_id) +{ + return 0; // TODO +} + +u32_t tc_worldupdate_get_world_count() +{ + return 0; // TODO +} + +tc_promise_s tc_worldupdate_get_world(u32_t index) +{ + tc_promise_s promise = tc_worldupdate_reserve_world_promise(); + tc_world_updater_command_s command; + command.type = TC_WORLD_UPDATER_COMMAND_GET_WORLD; + command.specific.get_item.index = index; + command.specific.get_item.promise = promise.identifier; + + tc_issue_world_updater_command(&tc_world_updater_g->queue, command); + + return promise; +} + + +tc_promise_s tc_worldupdate_get_chunkloader_of_world(u32_t world_id, u32_t index) +{ + tc_promise_s promise = tc_worldupdate_reserve_chunkloader_promise(); + tc_world_updater_command_s command; + command.type = TC_WORLD_UPDATER_COMMAND_GET_CHUNKLOADER; + command.specific.get_item.index = index; + command.specific.get_item.promise = promise.identifier; + + tc_issue_world_updater_command(&tc_world_updater_g->queue, command); + + return promise; +} + +tc_promise_s tc_worldupdate_get_chunks_of_chunkloader(u32_t loader_id) +{ + tc_promise_s promise = tc_worldupdate_reserve_chunklist_promise(); + tc_world_updater_command_s command; + command.type = TC_WORLD_UPDATER_COMMAND_GET_CHUNKLIST; + command.specific.get_item.index = loader_id; + command.specific.get_item.promise = promise.identifier; + + tc_issue_world_updater_command(&tc_world_updater_g->queue, command); + + return promise; +} + + + +void tc_worldupdate_move_chunkloader_to(u32_t loader_id, tc_chunk_location_s location) +{ + tc_world_updater_command_s command; + command.type = TC_WORLD_UPDATER_COMMAND_MOVE_CHUNKLOADER; + command.specific.move_chunkloader.loader_id = loader_id; + command.specific.move_chunkloader.new_location = location; + + tc_issue_world_updater_command(&tc_world_updater_g->queue, command); +} + +void tc_worldupdate_place_block(tc_block_location_s location, tc_block_s block) +{ + tc_world_updater_command_s command; + command.type = TC_WORLD_UPDATER_COMMAND_PLACE_BLOCK; + command.specific.place_block.location = location; + command.specific.place_block.block = block; + + tc_issue_world_updater_command(&tc_world_updater_g->queue, command); +} + +void tc_worldupdate_stop() +{ + tc_world_updater_command_s command; + command.type = TC_WORLD_UPDATER_COMMAND_STOP; + + tc_issue_world_updater_command(&tc_world_updater_g->queue, command); +} + diff --git a/code/source-c/world/update/world_update.h b/code/source-c/world/update/world_update.h new file mode 100644 index 0000000..a04d9d5 --- /dev/null +++ b/code/source-c/world/update/world_update.h @@ -0,0 +1,36 @@ + +#ifndef TC_WORLD_UPDATE_H +#define TC_WORLD_UPDATE_H + +#include + +#include +#include +#include +#include + +void tc_start_world_updater (); + +tc_promise_s tc_worldupdate_register_world (); +void tc_worldupdate_remove_world (u32_t world_id); + +tc_promise_s tc_worldupdate_add_chunkloader (); +void tc_worldupdate_delete_chunkloader (u32_t loader_id); + +u32_t tc_worldupdate_get_world_count (); +tc_promise_s tc_worldupdate_get_world (u32_t index); + +u32_t tc_worldupdate_get_chunkloader_count_of_world (u32_t world_id); +tc_promise_s tc_worldupdate_get_chunkloader_of_world (u32_t world_id, u32_t index); +tc_promise_s tc_worldupdate_get_chunks_of_chunkloader (u32_t loader_id); + +void tc_worldupdate_move_chunkloader_to (u32_t loader_id, tc_chunk_location_s location); +void tc_worldupdate_place_block (tc_block_location_s location, tc_block_s block); +void tc_worldupdate_stop (); + +const tc_world_s * tc_worldupdate_claim_world_promise (tc_promise_s promise); +const tc_chunkloader_s * tc_worldupdate_claim_chunkloader_promise (tc_promise_s promise); +const tc_chunklist_s * tc_worldupdate_claim_chunks_promise (tc_promise_s promise); + +#endif +