#include "entity.h" #include "state.h" #include #include tc_entity_registry_s tc_init_entity_registry() { tc_entity_registry_s registry; registry.types_capacity = 64; registry.num_types = 0; registry.types = calloc(sizeof(tc_entity_type_s), registry.types_capacity); registry.intervals_capacity = 256; registry.num_intervals = 0; registry.intervals = calloc(sizeof(tc_interval_s *), registry.intervals_capacity); registry.pool = tc_create_entity_pool(512); return registry; } void tc_register_entity_type(tc_entity_type_s type) { if(tc_game_state_g.entity_registry.num_types >= tc_game_state_g.entity_registry.types_capacity ) { tc_game_state_g.entity_registry.types_capacity *= 2; tc_game_state_g.entity_registry.types = realloc( tc_game_state_g.entity_registry.types, tc_game_state_g.entity_registry.types_capacity ); } if(type.instances_capacity == 0) type.instances_capacity = 64; type.instances = calloc(sizeof(tc_entity_s *), type.instances_capacity); type.num_instances = 0; tc_game_state_g.entity_registry.types[tc_game_state_g.entity_registry.num_types] = type; ++tc_game_state_g.entity_registry.num_types; } tc_entity_type_s * tc_get_entity_type_with_name(char *internal_name) { u32_t num_types = tc_game_state_g.entity_registry.num_types; tc_entity_type_s *types = tc_game_state_g.entity_registry.types; u32_t index = 0; while(index < num_types) { if(!strcmp(types[index].internal_name, internal_name)) return &types[index]; ++index; } return NULL; } i32_t tc_find_entity_instance_index_in_type(tc_entity_type_s *type, tc_entity_s *entity) { u32_t index = 0; while(index < type->num_instances) { if(type->instances[index] == entity) return index; ++index; } return -1; } void tc_add_entity_instance_to_type(tc_entity_type_s *type, tc_entity_s *entity) { if(type->num_instances >= type->instances_capacity) { type->instances_capacity *= 2; type->instances = realloc(type->instances, type->instances_capacity); } type->instances[type->num_instances] = entity; ++type->num_instances; } tc_entity_s * tc_create_entity(char *type, void *userdata) { tc_entity_type_s *type_struct = tc_get_entity_type_with_name(type); if(type_struct == NULL) return NULL; tc_entity_s *entity = tc_allocate_entity(); entity->type = type_struct; entity->num_attributes = 0; entity->attributes_capacity = 8; entity->attributes = calloc(sizeof(tc_entity_attribute_s), entity->attributes_capacity); type_struct->functions.fn_create(entity, userdata); tc_add_entity_instance_to_type(type_struct, entity); return entity; } void tc_spawn_entity(tc_entity_s *entity, tc_location_s location) { entity->type->functions.fn_spawn(entity, location); } void tc_teleport_entity(tc_entity_s *entity, tc_location_s location) { entity->type->functions.fn_teleport(entity, location); } void tc_draw_entity(tc_entity_s *entity) { entity->type->functions.fn_draw(entity); } void tc_delete_entity(tc_entity_s *entity) { tc_entity_type_s *type = entity->type; i32_t instance_index = tc_find_entity_instance_index_in_type(type, entity); if(instance_index == -1) { puts("Entity can't be found as an instance of it's type?!"); } else { --type->num_instances; type->instances[instance_index] = type->instances[type->num_instances]; } entity->type->functions.fn_delete(entity); tc_deallocate_entity(entity); } tc_entity_attribute_s * tc_get_entity_attribute_with_name(tc_entity_s *entity, char *name) { u32_t attribute_index = 0; while(attribute_index < entity->num_attributes) { tc_entity_attribute_s attribute = entity->attributes[attribute_index]; if(attribute.name == NULL) { puts("NAAJAA"); ++attribute_index; continue; } if(!strcmp(attribute.name, name)) return &entity->attributes[attribute_index]; ++attribute_index; } return NULL; } tc_entity_attribute_s * tc_allocate_entity_attribute(tc_entity_s *entity) { if(entity->num_attributes >= entity->attributes_capacity) { entity->attributes_capacity *= 2; entity->attributes = realloc(entity->attributes, sizeof(tc_entity_attribute_s) * entity->attributes_capacity); } ++entity->num_attributes; return &entity->attributes[entity->num_attributes-1]; } tc_entity_attribute_s * tc_get_or_allocate_entity_attribute_with_name(tc_entity_s *entity, char *name) { tc_entity_attribute_s *attribute; if((attribute = tc_get_entity_attribute_with_name(entity, name)) == NULL) { attribute = tc_allocate_entity_attribute(entity); attribute->name = name; } return attribute; } void tc_set_pointer_for_entity(tc_entity_s *entity, char *attr_name, void *pointer) { tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.pointer = pointer; } void tc_set_string_for_entity(tc_entity_s *entity, char *attr_name, char *string) { tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.string = string; } void tc_set_integer_for_entity(tc_entity_s *entity, char *attr_name, int64_t integer) { tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.integer = integer; } void tc_set_float_for_entity(tc_entity_s *entity, char *attr_name, double floating) { tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.floating = floating; } void * tc_get_pointer_from_entity(tc_entity_s *entity, char *attr_name) { return tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.pointer; } char * tc_get_string_from_entity(tc_entity_s *entity, char *attr_name) { return tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.string; } int64_t tc_get_integer_from_entity(tc_entity_s *entity, char *attr_name) { return tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.integer; } double tc_get_float_from_entity(tc_entity_s *entity, char *attr_name) { return tc_get_or_allocate_entity_attribute_with_name(entity, attr_name)->value.floating; } void tc_forget_entity_attribute(tc_entity_s *entity, char *attr_name) { u32_t attribute_index = 0; while(attribute_index < entity->attributes_capacity) { tc_entity_attribute_s *attribute = &entity->attributes[attribute_index]; if(attribute->name == NULL) { ++attribute_index; continue; } if(!strcmp(attribute->name, attr_name)) { entity->attributes[attribute_index] = entity->attributes[entity->num_attributes]; --entity->num_attributes; break; } ++attribute_index; } return; } i32_t tc_find_index_of_entity_in_intervals(tc_entity_s *entity) { u32_t interval_index = 0; while(interval_index < tc_game_state_g.entity_registry.num_intervals) { if(tc_game_state_g.entity_registry.intervals[interval_index].entity == entity) return interval_index; ++interval_index; } return -1; } u32_t tc_allocate_interval() { if( tc_game_state_g.entity_registry.num_intervals >= tc_game_state_g.entity_registry.intervals_capacity ) { tc_game_state_g.entity_registry.intervals_capacity *= 2; tc_game_state_g.entity_registry.intervals = realloc( tc_game_state_g.entity_registry.intervals, sizeof(tc_interval_s) * tc_game_state_g.entity_registry.intervals_capacity ); } u32_t last = tc_game_state_g.entity_registry.num_intervals; tc_game_state_g.entity_registry.intervals[last].last_invocation = 0.0f; ++tc_game_state_g.entity_registry.num_intervals; return last; } void tc_schedule_interval(tc_entity_s *entity, float wanted_delta, void (*fn_interval)(tc_entity_s *entity)) { i32_t interval_index; if((interval_index = tc_find_index_of_entity_in_intervals(entity)) == -1) { interval_index = tc_allocate_interval(); } tc_interval_s entry; entry.entity = entity; entry.wanted_delta = wanted_delta; entry.fn_interval = fn_interval; tc_game_state_g.entity_registry.intervals[interval_index] = entry; } void tc_send_pointer_to_entity(tc_entity_s *entity, char *event_name, void *pointer) { tc_entity_event_s event; event.identifier = event_name; event.value.pointer = pointer; entity->type->functions.fn_send_event(entity, event); } void tc_send_string_to_entity(tc_entity_s *entity, char *event_name, char *string) { tc_entity_event_s event; event.identifier = event_name; event.value.string = string; entity->type->functions.fn_send_event(entity, event); } void tc_send_integer_to_entity(tc_entity_s *entity, char *event_name, int64_t integer) { tc_entity_event_s event; event.identifier = event_name; event.value.integer = integer; entity->type->functions.fn_send_event(entity, event); } void tc_send_float_to_entity(tc_entity_s *entity, char *event_name, double floating) { tc_entity_event_s event; event.identifier = event_name; event.value.floating = floating; entity->type->functions.fn_send_event(entity, event); } void tc_tick_intervals() { uint64_t current_ms = SDL_GetTicks64(); tc_entity_registry_s registry = tc_game_state_g.entity_registry; u32_t interval_index = 0; while(interval_index < registry.num_intervals) { tc_interval_s interval = registry.intervals[interval_index]; u32_t elapsed_time = current_ms - interval.last_invocation; if(elapsed_time >= interval.wanted_delta) { if(interval.fn_interval == NULL) { ++interval_index; continue; } interval.fn_interval(interval.entity); } ++interval_index; } } void tc_draw_all_entities_of_type(char *name) { tc_entity_type_s *type = tc_get_entity_type_with_name(name); u32_t drawn_entities = 0; u32_t entity_index = 0; while(entity_index < type->num_instances) { tc_entity_s *entity = type->instances[entity_index]; tc_draw_entity(entity); ++drawn_entities; ++entity_index; } }