diff --git a/action.bash b/action.bash index 6cec013..3aa7458 100755 --- a/action.bash +++ b/action.bash @@ -57,10 +57,10 @@ function compile_module_c_sources { MODULE_NAME=$1 get_include_path_configuration $MODULE_NAME - echo $INCLUDE_STATEMENTS MODULE_SOURCE_PATH="$REPOSITORY_FOLDER/$MODULE_NAME/src-c/" MODULE_OBJECTS_FOLDER="$MAIN_OBJECTS_FOLDER/$MODULE_NAME/" + rm -r $MODULE_OBJECTS_FOLDER mkdir -p $MODULE_OBJECTS_FOLDER # Loop through all files in the 'src-c'-folder and hand them over to GCC diff --git a/core/exports/maintree/maintree.h b/core/exports/maintree/maintree.h index bc091bb..cdf6684 100644 --- a/core/exports/maintree/maintree.h +++ b/core/exports/maintree/maintree.h @@ -6,59 +6,53 @@ #include #include -typedef void * MtType; typedef void * MtEntity; /// @brief: An MtTask is a piece of functionality with an own state/context which will be executed on the same thread or set of threads. typedef void * MtTask; typedef void * MtState; - - -typedef void (*mt_type_effector_fn) (MtType type, void *userdata, usz_t invocation); -typedef void (*mt_entity_effector_fn) (MtEntity entity, void *userdata, usz_t invocation); -typedef void (*mt_task_main_fn) (MtTask task, void *userdata); +typedef void (*MtEffectorFn) (MtEntity entity, void *userdata, usz_t invocation_id); +typedef void (*MtTaskMainFn) (MtTask task, void *userdata); typedef struct { char *task_name; usz_t min_num_threads; usz_t max_num_threads; + MtTaskMainFn continuous_threads[4]; void *userdata; } MtTaskCreationInfo; -MtState mt_create_state(char *app_name); +MtState mt_initialize(char *app_name); void mt_cleanup(MtState state); void mt_start(MtState state); -MtType mt_register_type(char *identifier); -void mt_forget_type(MtType type); +MtEntity mt_summon(MtState state); -MtEntity mt_make(MtType type); -void mt_add_registration_effector(MtState state, char *effector_name, mt_type_effector_fn function, void *userdata); -void mt_add_create_effector(MtType type, char *effector_name, mt_entity_effector_fn function, void *userdata); -void mt_add_delete_effector(MtType type, char *effector_name, mt_entity_effector_fn function, void *userdata); -void mt_add_entity_tick_effector(MtType type, char *effector_name, usz_t ticks_delta, mt_entity_effector_fn function, void *userdata); -void mt_add_tick_effector(MtState state, char *effector_name, usz_t ticks_delta, mt_entity_effector_fn function, void *userdata); +void mt_add_create_effector(MtState state, char *effector_name, MtEffectorFn function, void *userdata); +void mt_add_delete_effector(MtState state, char *effector_name, MtEffectorFn function, void *userdata); +void mt_add_entity_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata); +void mt_add_tick_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata); void mt_remove_effector(MtState state, const char *effector_name); /// @brief Adds a tick effector which only acts upon entitys with certain tags. -/// @param type The type for which to add the tick effector. +/// @param state The state in which the tick effector should reside. /// @param effector_name The name of the effector. This will be copied into the effector's structure. -/// @param ticks_delta The wanted number of ticks between two invocations of the effector +/// @param ticks_delta The wanted number of ticks between two invocations of the effector. /// @param function The function to call for an entity if it contains all necessary tags. /// @param tag_names A nullpointer-terminated list of tag-ids that must be present in an entity for that entity to be effected. -void mt_add_tagged_tick_effector(MtType type, char *effector_name, usz_t ticks_delta, mt_entity_effector_fn function, char **tag_names); +void mt_add_tagged_tick_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, char **tag_names); void mt_tag_i64(MtEntity entity, char *name, i64_t integer); void mt_tag_f64(MtEntity entity, char *name, f64_t real); void mt_tag_str(MtEntity entity, char *name, char *string); void mt_tag_ptr(MtEntity entity, char *name, void *pointer); void mt_tag_vec2(MtEntity entity, char *name, rr_vec2f_s vector); -void mt_tag_vec3(MtEntity entity, char *name, rr_vec2f_s vector); +void mt_tag_vec3(MtEntity entity, char *name, rr_vec3f_s vector); void mt_tag_vec4(MtEntity entity, char *name, rr_vec4f_s vector); void mt_untag(MtEntity entity, char *name); diff --git a/core/inc-c/entity.h b/core/inc-c/entity.h new file mode 100644 index 0000000..618568d --- /dev/null +++ b/core/inc-c/entity.h @@ -0,0 +1,109 @@ + +#ifndef MT_ENTITY_POOL_H +#define MT_ENTITY_POOL_H + +#include +#include + +typedef struct MtEntityLookupTree MtEntityLookupTree; +typedef struct MtEntityListL1 MtEntityListL1; +typedef struct MtEntityListL2 MtEntityListL2; +typedef struct MtEntityListL3 MtEntityListL3; +typedef struct MtEntityPool MtEntityPool; +typedef struct MtEntityRegistry MtEntityRegistry; +typedef struct MtEntity * MtEntity; +typedef struct MtTag * MtTag; + +struct MtEntityPool +{ + usz_t capacity; + struct MtEntity *entities; + struct MtEntity *first_free; + MtEntityPool *continuation; +}; + +struct MtEntityLookupTree +{ + MtEntityListL1 *sublists[256]; +}; + +struct MtEntityListL1 +{ + MtEntityListL2 *sublists[256]; +}; + +struct MtEntityListL2 +{ + MtEntityListL3 *sublists[256]; +}; + +struct MtEntityListL3 +{ + struct MtEntity *entities[256]; +}; + +struct MtEntityRegistry +{ + MtEntityPool pool; + MtEntityLookupTree lookup; +}; + +struct MtEntity +{ + void *parent_state; + MtEntity pool_next_free; + + u32_t identifier; + u16_t tags_capacity; + u16_t num_tags; + struct MtTag *tags; +}; + +struct MtTag +{ + u32_t identifier; + union MtTagData + { + i64_t integer; + f64_t real; + char *string; + void *pointer; + rr_vec2f_s vec2f; + rr_vec3f_s vec3f; + rr_vec4f_s vec4f; + } data; +}; + +MtEntityRegistry mt_create_entity_registry(); +void mt_delete_entity_registry(MtEntityRegistry *entity_list); + +MtEntity mt_create_entity(void *state_voidptr, u32_t identifier); +MtEntity mt_get_entity(void *state_voidptr, u32_t identifier); + +void mt_tag_i64(MtEntity entity, char *name, i64_t integer); +void mt_tag_f64(MtEntity entity, char *name, f64_t real); +void mt_tag_str(MtEntity entity, char *name, char *string); +void mt_tag_ptr(MtEntity entity, char *name, void *pointer); +void mt_tag_vec2(MtEntity entity, char *name, rr_vec2f_s vector); +void mt_tag_vec3(MtEntity entity, char *name, rr_vec3f_s vector); +void mt_tag_vec4(MtEntity entity, char *name, rr_vec4f_s vector); + +void mt_untag(MtEntity entity, char *name); + +i64_t mt_get_i64_tag(MtEntity entity, char *name); +f64_t mt_get_f64_tag(MtEntity entity, char *name); +char * mt_get_str_tag(MtEntity entity, char *name); +void * mt_get_ptr_tag(MtEntity entity, char *name); +rr_vec2f_s mt_get_vec2_tag(MtEntity entity, char *name); +rr_vec3f_s mt_get_vec3_tag(MtEntity entity, char *name); +rr_vec4f_s mt_get_vec4_tag(MtEntity entity, char *name); + + + +MtEntityPool mt_create_entity_pool(usz_t capacity); +void mt_delete_entity_pool(MtEntityPool *pool); + +MtEntity mt_get_entity_pool_slot(MtEntityPool *pool); + + +#endif // MT_ENTITY_POOL_H diff --git a/core/inc-c/state.h b/core/inc-c/state.h new file mode 100644 index 0000000..13296e1 --- /dev/null +++ b/core/inc-c/state.h @@ -0,0 +1,27 @@ + +#ifndef MT_STATE_H +#define MT_STATE_H + +#include +#include + +#include +#include + +typedef struct MtState * MtState; + +struct MtState +{ + char *app_name; + + MtTagRegistry tag_registry; + MtEntityRegistry entity_list; +}; + +MtState mt_initialize(char *app_name); +void mt_cleanup(MtState state); +void mt_start(MtState state); + +MtEntity mt_summon(MtState state); + +#endif // MT_STATE_H diff --git a/core/src-c/entity_lookup.c b/core/src-c/entity_lookup.c new file mode 100644 index 0000000..b5119b7 --- /dev/null +++ b/core/src-c/entity_lookup.c @@ -0,0 +1,57 @@ +#include +#include +#include + +MtEntity mt_create_entity(void *state_voidptr, u32_t identifier) +{ + MtState state = state_voidptr; + MtEntityListL1 *level1 = state->entity_list.lookup.sublists[identifier >> 24]; + if(level1 == NULL) + { + state->entity_list.lookup.sublists[identifier >> 24] = calloc(sizeof(MtEntityListL1), 1); + level1 = state->entity_list.lookup.sublists[identifier >> 24]; + } + + MtEntityListL2 *level2 = level1->sublists[(identifier >> 16) & 0xff]; + if(level2 == NULL) + { + level1->sublists[(identifier >> 16) & 0xff] = calloc(sizeof(MtEntityListL2), 1); + level2 = level1->sublists[(identifier >> 16) & 0xff]; + } + + MtEntityListL3 *level3 = level2->sublists[(identifier >> 8) & 0xff]; + if(level3 == NULL) + { + level2->sublists[(identifier >> 8) & 0xff] = calloc(sizeof(MtEntityListL3), 1); + level3 = level2->sublists[(identifier >> 8) & 0xff]; + } + + MtEntity entity = level3->entities[identifier & 0xff]; + if(entity == NULL) + { + entity = mt_get_entity_pool_slot(&state->entity_list.pool); + } + return entity; +} + +MtEntity mt_get_entity(void *state_voidptr, u32_t identifier) +{ + MtState state = state_voidptr; + MtEntityListL1 *level1 = state->entity_list.lookup.sublists[identifier >> 24]; + if(level1 == NULL) + return NULL; + + MtEntityListL2 *level2 = level1->sublists[(identifier >> 16) & 0xff]; + if(level2 == NULL) + return NULL; + + MtEntityListL3 *level3 = level2->sublists[(identifier >> 8) & 0xff]; + if(level3 == NULL) + return NULL; + + MtEntity entity = level3->entities[identifier & 0xff]; + if(entity == NULL) + return NULL; + + return entity; +} diff --git a/core/src-c/entity_registry.c b/core/src-c/entity_registry.c new file mode 100644 index 0000000..9518f78 --- /dev/null +++ b/core/src-c/entity_registry.c @@ -0,0 +1,143 @@ +#include +#include +#include + +void mt_delete_entity(MtEntity entity); + +MtEntityLookupTree mt_create_entity_lookup_tree(); +void mt_delete_entity_lookup_tree(MtEntityLookupTree lookup_tree); + + + +MtEntityRegistry mt_create_entity_registry() +{ + MtEntityRegistry entity_registry; + entity_registry.lookup = mt_create_entity_lookup_tree(); + return entity_registry; +} + +void mt_delete_entity_registry(MtEntityRegistry *entity_registry) +{ + mt_delete_entity_pool(&entity_registry->pool); +} + + + +MtEntityLookupTree mt_create_entity_lookup_tree() +{ + MtEntityLookupTree lookup_tree; + rr_memset(&lookup_tree.sublists[0], sizeof(MtEntityListL1 *) * 256, 0x00); + return lookup_tree; +} + +void mt_delete_entity_lookup_tree(MtEntityLookupTree lookup_tree) +{ + usz_t level1_index = 0; + while(level1_index < 256) + { + if(lookup_tree.sublists[level1_index] == NULL) + { + ++level1_index; + continue; + } + MtEntityListL1 *level1_list = lookup_tree.sublists[level1_index]; + usz_t level2_index = 0; + while(level2_index < 256) + { + MtEntityListL2 *level2_list = level1_list->sublists[level2_index]; + if(level2_list == NULL) + { + ++level2_index; + continue; + } + usz_t level3_index = 0; + while(level3_index) + { + MtEntityListL3 *level3_list = level2_list->sublists[level3_index]; + if(level3_list == NULL) + { + ++level3_index; + continue; + } + usz_t entity_index = 0; + while(entity_index) + { + MtEntity entity = level3_list->entities[entity_index]; + if(entity == NULL) + { + ++entity_index; + continue; + } + mt_delete_entity(entity); + ++entity_index; + } + free(level3_list); + ++level3_index; + } + free(level2_list); + ++level2_index; + } + free(level1_list); + ++level1_index; + } +} + + + +void mt_delete_entity(MtEntity entity) +{ + if(entity->tags != NULL) + free(entity->tags); +} + + + +void mt_reset_entity_pool_allocation(MtEntityPool *pool) +{ + usz_t entity_index = 0; + while(entity_index < pool->capacity) + { + pool->entities[entity_index].pool_next_free = &pool->entities[entity_index+1]; + ++entity_index; + } + pool->entities[pool->capacity - 1].pool_next_free = NULL; +} + +MtEntityPool mt_create_entity_pool(usz_t capacity) +{ + MtEntityPool pool; + pool.capacity = capacity; + pool.entities = calloc(sizeof(struct MtEntity), pool.capacity); + mt_reset_entity_pool_allocation(&pool); + pool.first_free = &pool.entities[0]; + pool.continuation = NULL; + return pool; +} + +void mt_delete_entity_pool(MtEntityPool *pool) +{ + if(pool->continuation != NULL) + { + mt_delete_entity_pool(pool->continuation); + free(pool->continuation); + } + free(pool->entities); +} + + + +MtEntity mt_get_entity_pool_slot(MtEntityPool *pool) +{ + if(pool->first_free == NULL) + { + if(pool->continuation == NULL) + { + pool->continuation = malloc(sizeof(MtEntityPool)); + *pool->continuation = mt_create_entity_pool(pool->capacity * 2); + } + return mt_get_entity_pool_slot(pool->continuation); + } + MtEntity allocated = pool->first_free; + pool->first_free = allocated->pool_next_free; + return allocated; +} diff --git a/core/src-c/entity_tagging.c b/core/src-c/entity_tagging.c new file mode 100644 index 0000000..74bee05 --- /dev/null +++ b/core/src-c/entity_tagging.c @@ -0,0 +1,119 @@ +#include +#include +#include + +MtTag mt_get_entity_tag_slot(MtEntity entity, char *name) +{ + MtState state = entity->parent_state; + + // Find the correct slot if it already exist + + u32_t tag_id = mt_get_tag_id(&state->tag_registry, name); + usz_t tag_index = 0; + while(tag_index < entity->num_tags) + { + if(entity->tags[tag_index].identifier == tag_id) + return &entity->tags[tag_index]; + + ++tag_index; + } + + // Create a new slot if needed + + if(entity->num_tags >= entity->tags_capacity) + { + entity->tags_capacity *= 2; + if(entity->tags_capacity == 0) + entity->tags_capacity = 4; + + entity->tags = realloc(entity->tags, sizeof(struct MtTag) * entity->tags_capacity); + } + return &entity->tags[entity->num_tags++]; +} + +void mt_tag_i64(MtEntity entity, char *name, i64_t integer) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + tag->data.integer = integer; +} + +void mt_tag_f64(MtEntity entity, char *name, f64_t real) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + tag->data.real = real; +} + +void mt_tag_str(MtEntity entity, char *name, char *string) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + tag->data.string = string; +} + +void mt_tag_ptr(MtEntity entity, char *name, void *pointer) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + tag->data.pointer = pointer; +} + +void mt_tag_vec2(MtEntity entity, char *name, rr_vec2f_s vector) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + tag->data.vec2f = vector; +} + +void mt_tag_vec3(MtEntity entity, char *name, rr_vec3f_s vector) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + tag->data.vec3f = vector; +} +void mt_tag_vec4(MtEntity entity, char *name, rr_vec4f_s vector) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + tag->data.vec4f = vector; +} + + + +void mt_untag(MtEntity entity, char *name); + +i64_t mt_get_i64_tag(MtEntity entity, char *name) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + return tag->data.integer; +} + +f64_t mt_get_f64_tag(MtEntity entity, char *name) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + return tag->data.real; +} + +char * mt_get_str_tag(MtEntity entity, char *name) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + return tag->data.string; +} + +void * mt_get_ptr_tag(MtEntity entity, char *name) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + return tag->data.pointer; +} + +rr_vec2f_s mt_get_vec2_tag(MtEntity entity, char *name) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + return tag->data.vec2f; +} + +rr_vec3f_s mt_get_vec3_tag(MtEntity entity, char *name) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + return tag->data.vec3f; +} + +rr_vec4f_s mt_get_vec4_tag(MtEntity entity, char *name) +{ + MtTag tag = mt_get_entity_tag_slot(entity, name); + return tag->data.vec4f; +} diff --git a/core/src-c/state.c b/core/src-c/state.c new file mode 100644 index 0000000..c368253 --- /dev/null +++ b/core/src-c/state.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +MtState mt_initialize(char *app_name) +{ + usz_t len_app_name = rr_measure_string(app_name); + MtState state = malloc(sizeof(struct MtState)); + + state->app_name = malloc(len_app_name + 1); + rr_memcopy(state->app_name, app_name, len_app_name + 1); + state->tag_registry = mt_create_tag_registry(state); + + return state; +} + +void mt_cleanup(MtState state) +{ + mt_delete_entity_registry(&state->entity_list); + free(state); +} + +/* TODO: This function should start a new thread with a worker system. +void mt_start(MtState state) +{ + +} +*/