Multithreading for chunks

This commit is contained in:
Eric-Paul Ickhorn 2023-10-17 22:13:54 +02:00
parent 14d560dbf5
commit bb74d13e89
16 changed files with 864 additions and 12 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -1,6 +1,7 @@
#include <state.h>
#include <world/world.h>
#include <entity/registration.h>
#include <world/update/world_update.h>
#include <SDL2/SDL.h>
@ -62,7 +63,11 @@ void tc_load_textures()
void tc_init()
{
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);

View File

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

View File

@ -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;

View File

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

View File

@ -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);

View File

@ -0,0 +1,15 @@
#ifndef TC_PROMISE_H
#define TC_PROMISE_H
#include <utility/utility.h>
typedef struct
{
u64_t issueing_tick;
u32_t identifier;
} tc_promise_s;
#endif

View File

@ -0,0 +1,103 @@
#ifndef TC_WORLD_UPDATER_INTERNAL_H
#define TC_WORLD_UPDATER_INTERNAL_H
#include <world/world.h>
#include <utility/location.h>
#include <utility/promise.h>
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

View File

@ -0,0 +1,217 @@
#include <world/update/world_update.h>
#include <stddef.h>
#include <stdlib.h>
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;
}
}

View File

@ -0,0 +1,76 @@
#include <world/update/internal.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
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;
}

View File

@ -0,0 +1,65 @@
#include <world/update/internal.h>
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)
{
}

View File

@ -0,0 +1,16 @@
#ifndef TC_WORLD_CONFIGURATION_H
#define TC_WORLD_CONFIGURATION_H
#include <world/world.h>
#include <world/chunk.h>
#include <utility/location.h>
#include <utility/promise.h>
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

View File

@ -0,0 +1,212 @@
#include <world/update/world_update.h>
#include <world/update/internal.h>
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 = &registry->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);
}

View File

@ -0,0 +1,36 @@
#ifndef TC_WORLD_UPDATE_H
#define TC_WORLD_UPDATE_H
#include <SDL2/SDL.h>
#include <world/world.h>
#include <world/chunk.h>
#include <utility/location.h>
#include <utility/promise.h>
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