Compare commits

...

3 Commits

32 changed files with 948 additions and 59 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/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

@ -1,7 +1,7 @@
#include <entity/registration.h>
#include <chunk_pool.h>
#include <chunk.h>
#include <world.h>
#include <world/chunk_pool.h>
#include <world/chunk.h>
#include <world/world.h>
#include <state.h>
#include <glad/glad.h>
@ -32,6 +32,9 @@ void tc_create_chunk_entity(tc_entity_s *entity, void *userdata)
void tc_delete_chunk_entity(tc_entity_s *entity)
{
tc_chunk_s *chunk = entity->specific;
tc_world_s *world = chunk->location.world;
tc_run_hooklist(&world->on_chunk_delete, entity);
if(chunk->vao != 0) glDeleteVertexArrays(1, &chunk->vao);
if(chunk->vbo != 0) glDeleteBuffers(1, &chunk->vbo);
@ -39,8 +42,10 @@ void tc_delete_chunk_entity(tc_entity_s *entity)
if(chunk->vertex_uvs != NULL) free(chunk->vertex_uvs);
tc_physics_entity_s *physics_body = tc_get_pointer_from_entity(entity, "physics_body");
if(physics_body != 0)
{
tc_remove_physics_entity(physics_body);
}
tc_deallocate_chunk(entity->specific);
}

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;
}
@ -325,7 +328,8 @@ void tc_send_pointer_to_entity(tc_entity_s *entity, char *event_name, void *poin
tc_entity_event_s event;
event.identifier = event_name;
event.value.pointer = pointer;
entity->type->functions.fn_send_event(entity, event);
tc_entity_type_s *type = entity->type;
type->functions.fn_send_event(entity, event);
}
void tc_send_string_to_entity(tc_entity_s *entity, char *event_name, char *string)
@ -375,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

@ -2,8 +2,8 @@
#ifndef TC_ENTITY_H
#define TC_ENTITY_H
#include "utility/location.h"
#include "utility/utility.h"
#include <utility/location.h>
#include <utility/utility.h>
typedef struct tc_interval tc_interval_s;
typedef struct tc_entity_event tc_entity_event_s;
@ -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

@ -2,7 +2,7 @@
#ifndef TC_ENTITY_REGISTRATION_H
#define TC_ENTITY_REGISTRATION_H
#include "../entity.h"
#include <entity/entity.h>
void tc_register_chunk_entity ();
void tc_register_player_entity ();

View File

@ -1,6 +1,7 @@
#include "state.h"
#include "world.h"
#include "entity/registration.h"
#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

@ -21,6 +21,8 @@ void tc_add_physics_object(tc_physics_simulation_s *simulation, tc_physics_entit
void tc_add_physics_object_to(tc_physics_entity_s *container, tc_physics_entity_s *object)
{
if(container != NULL) object->super = container;
if((container->value.group.num_entities+1)
>=
container->value.group.entities_capacity
@ -76,7 +78,7 @@ i32_t tc_physics_find_entity_in_group(tc_physics_entity_s *group, tc_physics_ent
i32_t index = 0;
while(index < group->value.group.num_entities)
{
if(entity->super->value.group.entities[group->value.group.num_entities]
if(group->value.group.entities[group->value.group.num_entities]
==
entity
) return index;
@ -99,15 +101,18 @@ void tc_remove_physics_entity(tc_physics_entity_s *entity)
{
if(entity->super == NULL) return;
tc_free_physics_entity(entity);
// Fill up the gap created inside the entities-array.
i32_t index = 0;
if((index = tc_physics_find_entity_in_group(entity->super, entity)) == -1) return;
tc_physics_entity_s *super = entity->super;
entity->super->value.group.entities[index] =
entity->super->value.group.entities[entity->super->value.group.num_entities-1];
i32_t index = 0;
if((index = tc_physics_find_entity_in_group(super, entity)) == -1) return;
super->value.group.entities[index] =
super->value.group.entities[super->value.group.num_entities-1];
--super->value.group.num_entities;
tc_free_physics_entity(entity);
}

View File

@ -6,7 +6,7 @@
#include <physics/primitives.h>
#include <utility/utility.h>
#include <entity.h>
#include <entity/entity.h>
typedef struct tc_physics_entity tc_physics_entity_s;
typedef struct tc_entity_physics_attributes tc_entity_physics_attributes_s;

View File

@ -8,9 +8,9 @@
#include <assets.h>
#include <shaders.h>
#include <entity.h>
#include <entity/entity.h>
#include <blocks.h>
#include <world.h>
#include <world/world.h>
#include <utility/utility.h>
typedef struct tc_camera
@ -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

@ -1,4 +1,4 @@
#include "world.h"
#include <utility/utility.h>
int tc_perlin_permutation[] = {
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225,

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

@ -1,4 +1,4 @@
#include <chunk.h>
#include <world/chunk.h>
#include <glad/glad.h>
#include <stddef.h>
@ -38,6 +38,10 @@ void tc_draw_chunkloader_zone(tc_chunkloader_s *loader)
tc_chunklist_s *list = &loader->chunklist;
for(tc_chunklist_entry_s *current = list->first; current != NULL; current = current->next)
{
if(current->entity == NULL)
{
return;
}
tc_send_pointer_to_entity(current->entity, "draw", 0);
}

View File

@ -3,7 +3,7 @@
#define TC_CHUNK_H
#include <utility/location.h>
#include <entity.h>
#include <entity/entity.h>
typedef struct tc_chunk tc_chunk_s;
typedef struct tc_chunkloader tc_chunkloader_s;

View File

@ -3,7 +3,7 @@
#define TC_CHUNK_POOL_H
#include <utility/utility.h>
#include <chunk.h>
#include <world/chunk.h>
typedef struct tc_chunk_pool tc_chunk_pool_s;
typedef struct tc_chunk_pool_entry tc_chunk_pool_entry_s;

View File

@ -1,5 +1,6 @@
#include "world.h"
#include "entity.h"
#include <world/world.h>
#include <entity/entity.h>
#include <state.h>
#include <stdlib.h>
#include <stdio.h>
@ -95,7 +96,6 @@ void tc_chunklist_add_item(tc_chunklist_s *list, tc_entity_s *chunk)
new_entry.entity = chunk;
new_entry.next = list->first;
(*list->first_free) = new_entry;
list->first = list->first_free;
// Link everything together
@ -104,6 +104,7 @@ void tc_chunklist_add_item(tc_chunklist_s *list, tc_entity_s *chunk)
list->first_free->previous = NULL;
// Finally assign it
list->first = list->first_free;
list->first_free = tc_chunklist_find_first_free(list);
}
@ -117,6 +118,9 @@ void tc_chunklist_remove_item(tc_chunklist_s *list, tc_entity_s *chunk)
if(entry->previous != NULL)
entry->previous->next = entry->next;
if(entry->next != NULL)
entry->next->previous = entry->previous;
entry->entity = NULL;
list->first_free = entry;
}
@ -130,7 +134,7 @@ tc_chunkloader_s tc_create_chunkloader(tc_chunk_location_s location)
loader.extent.y = UPDATE_DISTANCE * 2 + 1;
loader.extent.z = UPDATE_DISTANCE * 2 + 1;
loader.center = location;
loader.chunklist = tc_create_chunklist(200);
loader.chunklist = tc_create_chunklist(512);
loader.needs_reload = FALSE;
return loader;
@ -149,13 +153,13 @@ void tc_delete_chunkloader(tc_chunkloader_s loader)
bool_t tc_coord_is_within_loaders_range(tc_chunkloader_s *loader, tc_vec3i_s coord)
{
if(coord.x < (loader->center.grid_coords.x - loader->extent.x / 2)) return FALSE;
if(coord.y < (loader->center.grid_coords.y - loader->extent.y / 2)) return FALSE;
if(coord.z < (loader->center.grid_coords.z - loader->extent.z / 2)) return FALSE;
if(coord.x < ((loader->center.grid_coords.x - loader->extent.x / 2)-1)) return FALSE;
if(coord.y < ((loader->center.grid_coords.y - loader->extent.y / 2)-1)) return FALSE;
if(coord.z < ((loader->center.grid_coords.z - loader->extent.z / 2)-1)) return FALSE;
if(coord.x > (loader->center.grid_coords.x + loader->extent.x / 2)) return FALSE;
if(coord.y > (loader->center.grid_coords.y + loader->extent.y / 2)) return FALSE;
if(coord.z > (loader->center.grid_coords.z + loader->extent.z / 2)) return FALSE;
if(coord.x > ((loader->center.grid_coords.x + loader->extent.x / 2)+1)) return FALSE;
if(coord.y > ((loader->center.grid_coords.y + loader->extent.y / 2)+1)) return FALSE;
if(coord.z > ((loader->center.grid_coords.z + loader->extent.z / 2)+1)) return FALSE;
return TRUE;
}
@ -178,7 +182,9 @@ void tc_unload_chunk_at(tc_chunkloader_s *loader, tc_chunk_location_s location)
if(entity == NULL) return;
tc_chunk_s *chunk = entity->specific;
tc_world_s *world = location.world;
tc_run_hooklist(&world->on_chunk_unload, entity);
--chunk->refcounter;
if(chunk->refcounter < 1)

View File

@ -1,4 +1,4 @@
#include "world.h"
#include <world/world.h>
bool_t tc_generate_default_terrain_chunk(tc_worldgen_s *gen, tc_chunk_s *chunk)
{

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

View File

@ -1,4 +1,4 @@
#include <world.h>
#include <world/world.h>
#include <state.h>
#include <stdlib.h>
@ -48,6 +48,9 @@ tc_chunkloader_s tc_create_spawn_loader(tc_world_s *world)
tc_chunkloader_s loader = tc_create_chunkloader(loader_location);
loader.is_rendered = TRUE;
loader.extent.x = 9.0f;
loader.extent.z = 9.0f;
loader.extent.y = 3.0f;
return loader;
}
@ -59,6 +62,7 @@ tc_world_s * tc_new_world(tc_worldgen_s *generator)
world->before_chunk_generate = tc_new_hooklist(16);
world->after_chunk_generate = tc_new_hooklist(16);
world->on_chunk_delete = tc_new_hooklist(16);
world->on_chunk_unload = tc_new_hooklist(16);
world->on_chunk_update = tc_new_hooklist(16);
world->worldgen = &tc_default_terrain_generator_g;
world->num_loaders = 1;

View File

@ -8,9 +8,9 @@
#include <hook.h>
#include <physics/simulation.h>
#include <utility/math.h>
#include <entity.h>
#include <chunk.h>
#include <chunk_pool.h>
#include <entity/entity.h>
#include <world/chunk.h>
#include <world/chunk_pool.h>
#define UPDATE_DISTANCE 2
@ -52,8 +52,9 @@ struct tc_world
tc_hooklist_s on_chunk_create;
tc_hooklist_s before_chunk_generate;
tc_hooklist_s after_chunk_generate;
tc_hooklist_s on_chunk_delete;
tc_hooklist_s on_chunk_update;
tc_hooklist_s on_chunk_unload;
tc_hooklist_s on_chunk_delete;
};
extern tc_worldgen_s tc_default_terrain_generator_g;

View File

@ -1,9 +1,11 @@
#include <world.h>
#include <world/world.h>
#include <stddef.h> // For NULL
#include <stdio.h>
void tc_initialize_chunk_physics(tc_entity_s *chunk_entity, void *userdata)
{
tc_chunk_s *chunk = chunk_entity->specific;
tc_world_s *world = chunk->location.world;
tc_physics_simulation_s *simulation = world->physics;
@ -41,10 +43,19 @@ void tc_initialize_chunk_physics(tc_entity_s *chunk_entity, void *userdata)
tc_set_pointer_for_entity(chunk_entity, "physics_body", chunk_body);
}
void tc_free_chunk_physics(tc_entity_s *chunk_entity, void *userdata)
{
tc_physics_entity_s *body =
tc_get_pointer_from_entity(chunk_entity, "physics_body");
tc_remove_physics_entity(body);
}
void tc_create_world_physics(tc_world_s *world, void *userdata)
{
world->physics = tc_new_physics_simulation();
tc_add_to_hooklist(&world->on_chunk_create, (tc_fn_hook) tc_initialize_chunk_physics, NULL);
tc_add_to_hooklist(&world->on_chunk_update, (tc_fn_hook) tc_initialize_chunk_physics, NULL);
// tc_add_to_hooklist(&world->on_chunk_update, (tc_fn_hook) tc_initialize_chunk_physics, NULL);
tc_add_to_hooklist(&world->on_chunk_delete, (tc_fn_hook) tc_free_chunk_physics, NULL);
}