Techneck/code/source-c/entity/entity.c

469 lines
14 KiB
C
Raw Permalink Normal View History

2023-10-14 13:04:52 +00:00
#include "entity.h"
#include "state.h"
#include <stdlib.h>
#include <string.h>
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);
2023-10-14 19:17:30 +00:00
registry.intervals_capacity = 256;
registry.num_intervals = 0;
registry.intervals = calloc(sizeof(tc_interval_s *), registry.intervals_capacity);
2023-10-15 09:51:45 +00:00
registry.pool = tc_create_entity_pool(512);
2023-10-17 20:13:54 +00:00
registry.tags_capacity = 512;
registry.num_tags = 0;
registry.tags = calloc(sizeof(tc_entity_tag_s), registry.tags_capacity);
2023-10-14 13:04:52 +00:00
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
);
}
2023-10-15 09:51:45 +00:00
if(type.instances_capacity == 0) type.instances_capacity = 64;
type.instances = calloc(sizeof(tc_entity_s *), type.instances_capacity);
type.num_instances = 0;
2023-10-14 13:04:52 +00:00
tc_game_state_g.entity_registry.types[tc_game_state_g.entity_registry.num_types] = type;
++tc_game_state_g.entity_registry.num_types;
}
2023-10-14 14:38:38 +00:00
tc_entity_type_s * tc_get_entity_type_with_name(char *internal_name)
2023-10-14 13:04:52 +00:00
{
2023-10-15 09:51:45 +00:00
u32_t num_types = tc_game_state_g.entity_registry.num_types;
2023-10-14 13:04:52 +00:00
tc_entity_type_s *types = tc_game_state_g.entity_registry.types;
2023-10-15 09:51:45 +00:00
u32_t index = 0;
2023-10-14 13:04:52 +00:00
while(index < num_types)
{
if(!strcmp(types[index].internal_name, internal_name)) return &types[index];
++index;
}
return NULL;
}
2023-10-15 09:51:45 +00:00
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;
2023-10-17 11:25:02 +00:00
type->instances = realloc(type->instances, sizeof(tc_entity_s *) * type->instances_capacity);
2023-10-15 09:51:45 +00:00
}
type->instances[type->num_instances] = entity;
++type->num_instances;
}
2023-10-15 12:41:53 +00:00
tc_entity_s * tc_create_entity(char *type, void *userdata)
2023-10-14 13:04:52 +00:00
{
2023-10-14 14:38:38 +00:00
tc_entity_type_s *type_struct = tc_get_entity_type_with_name(type);
2023-10-14 13:04:52 +00:00
if(type_struct == NULL) return NULL;
2023-10-15 09:51:45 +00:00
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);
2023-10-15 12:41:53 +00:00
type_struct->functions.fn_create(entity, userdata);
2023-10-15 09:51:45 +00:00
tc_add_entity_instance_to_type(type_struct, entity);
2023-10-14 19:17:30 +00:00
return entity;
2023-10-14 13:04:52 +00:00
}
void tc_delete_entity(tc_entity_s *entity)
{
2023-10-15 09:51:45 +00:00
tc_entity_type_s *type = entity->type;
2023-10-17 11:25:02 +00:00
entity->type->functions.fn_delete(entity);
2023-10-15 09:51:45 +00:00
i32_t instance_index =
tc_find_entity_instance_index_in_type(type, entity);
2023-10-17 11:25:02 +00:00
free(entity->attributes);
tc_deallocate_entity(entity);
entity->attributes = NULL;
entity->type = NULL;
2023-10-15 09:51:45 +00:00
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];
}
2023-10-14 13:04:52 +00:00
}
2023-10-14 14:38:38 +00:00
tc_entity_attribute_s * tc_get_entity_attribute_with_name(tc_entity_s *entity, char *name)
{
2023-10-15 09:51:45 +00:00
u32_t attribute_index = 0;
while(attribute_index < entity->num_attributes)
2023-10-14 14:38:38 +00:00
{
tc_entity_attribute_s attribute = entity->attributes[attribute_index];
if(attribute.name == NULL)
{
++attribute_index;
continue;
}
2023-10-17 11:25:02 +00:00
if(!strcmp(attribute.name, name))
{
return &entity->attributes[attribute_index];
}
2023-10-14 14:38:38 +00:00
++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;
2023-10-14 19:17:30 +00:00
entity->attributes = realloc(entity->attributes, sizeof(tc_entity_attribute_s) * entity->attributes_capacity);
2023-10-14 14:38:38 +00:00
}
2023-10-17 11:25:02 +00:00
tc_entity_attribute_s *attribute = &entity->attributes[entity->num_attributes];
2023-10-14 14:38:38 +00:00
++entity->num_attributes;
2023-10-17 11:25:02 +00:00
return attribute;
2023-10-14 14:38:38 +00:00
}
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)
{
2023-10-17 11:25:02 +00:00
tc_entity_attribute_s *attribute = tc_get_or_allocate_entity_attribute_with_name(entity, attr_name);
attribute->value.integer = integer;
2023-10-14 14:38:38 +00:00
}
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)
{
2023-10-17 11:25:02 +00:00
tc_entity_attribute_s *attribute =
tc_get_entity_attribute_with_name(entity, attr_name);
if(attribute == NULL)
{
return NULL;
}
return attribute->value.pointer;
2023-10-14 14:38:38 +00:00
}
char * tc_get_string_from_entity(tc_entity_s *entity, char *attr_name)
{
2023-10-17 11:25:02 +00:00
tc_entity_attribute_s *attribute =
tc_get_entity_attribute_with_name(entity, attr_name);
if(attribute == NULL)
{
return NULL;
}
return attribute->value.string;
2023-10-14 14:38:38 +00:00
}
int64_t tc_get_integer_from_entity(tc_entity_s *entity, char *attr_name)
{
2023-10-17 11:25:02 +00:00
tc_entity_attribute_s *attribute =
tc_get_entity_attribute_with_name(entity, attr_name);
if(attribute == NULL)
{
return 0;
}
return attribute->value.integer;
2023-10-14 14:38:38 +00:00
}
double tc_get_float_from_entity(tc_entity_s *entity, char *attr_name)
{
2023-10-17 11:25:02 +00:00
tc_entity_attribute_s *attribute =
tc_get_entity_attribute_with_name(entity, attr_name);
if(attribute == NULL)
{
return 0.0f;
}
return attribute->value.floating;
2023-10-14 14:38:38 +00:00
}
void tc_forget_entity_attribute(tc_entity_s *entity, char *attr_name)
{
2023-10-15 09:51:45 +00:00
u32_t attribute_index = 0;
2023-10-14 14:38:38 +00:00
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;
}
2023-10-15 09:51:45 +00:00
i32_t tc_find_index_of_entity_in_intervals(tc_entity_s *entity)
2023-10-14 19:17:30 +00:00
{
2023-10-15 09:51:45 +00:00
u32_t interval_index = 0;
2023-10-14 19:17:30 +00:00
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;
}
2023-10-15 09:51:45 +00:00
u32_t tc_allocate_interval()
2023-10-14 19:17:30 +00:00
{
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
);
}
2023-10-15 09:51:45 +00:00
u32_t last = tc_game_state_g.entity_registry.num_intervals;
2023-10-14 19:17:30 +00:00
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))
{
2023-10-15 09:51:45 +00:00
i32_t interval_index;
2023-10-14 19:17:30 +00:00
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;
}
2023-10-14 13:04:52 +00:00
void tc_send_pointer_to_entity(tc_entity_s *entity, char *event_name, void *pointer)
{
tc_entity_event_s event;
2023-10-15 09:51:45 +00:00
event.identifier = event_name;
2023-10-14 13:04:52 +00:00
event.value.pointer = pointer;
tc_entity_type_s *type = entity->type;
type->functions.fn_send_event(entity, event);
2023-10-14 13:04:52 +00:00
}
void tc_send_string_to_entity(tc_entity_s *entity, char *event_name, char *string)
{
tc_entity_event_s event;
2023-10-15 09:51:45 +00:00
event.identifier = event_name;
2023-10-14 13:04:52 +00:00
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;
2023-10-15 09:51:45 +00:00
event.identifier = event_name;
2023-10-14 13:04:52 +00:00
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;
2023-10-15 09:51:45 +00:00
event.identifier = event_name;
2023-10-14 13:04:52 +00:00
event.value.floating = floating;
entity->type->functions.fn_send_event(entity, event);
}
2023-10-14 19:17:30 +00:00
void tc_tick_intervals()
{
uint64_t current_ms = SDL_GetTicks64();
tc_entity_registry_s registry = tc_game_state_g.entity_registry;
2023-10-15 09:51:45 +00:00
u32_t interval_index = 0;
2023-10-14 19:17:30 +00:00
while(interval_index < registry.num_intervals)
{
tc_interval_s interval = registry.intervals[interval_index];
2023-10-15 09:51:45 +00:00
u32_t elapsed_time = current_ms - interval.last_invocation;
2023-10-14 19:17:30 +00:00
if(elapsed_time >= interval.wanted_delta)
{
if(interval.fn_interval == NULL)
{
++interval_index;
continue;
}
interval.fn_interval(interval.entity);
}
++interval_index;
}
}
2023-10-17 20:13:54 +00:00
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 *));
}
2023-10-17 11:25:02 +00:00
/*
2023-10-14 19:17:30 +00:00
void tc_draw_all_entities_of_type(char *name)
{
tc_entity_type_s *type = tc_get_entity_type_with_name(name);
2023-10-15 09:51:45 +00:00
u32_t drawn_entities = 0;
u32_t entity_index = 0;
while(entity_index < type->num_instances)
2023-10-14 19:17:30 +00:00
{
2023-10-15 09:51:45 +00:00
tc_entity_s *entity = type->instances[entity_index];
tc_draw_entity(entity);
++drawn_entities;
2023-10-14 19:17:30 +00:00
++entity_index;
}
}
2023-10-17 11:25:02 +00:00
*/