Files
dusk/archive/entity/component.c
T
2026-05-21 10:18:20 -05:00

133 lines
4.2 KiB
C

/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "entitymanager.h"
#include "assert/assert.h"
#include "util/memory.h"
componentdefinition_t COMPONENT_DEFINITIONS[] = {
[COMPONENT_TYPE_NULL] = { 0 },
#define X(enm, type, field, iMethod, dMethod) \
[COMPONENT_TYPE_##enm] = { \
.enumName = #enm, \
.name = #field, \
.init = iMethod, \
.dispose = dMethod \
},
#include "componentlist.h"
#undef X
[COMPONENT_TYPE_COUNT] = { 0 }
};
void componentInit(
const entityid_t entityId,
const componentid_t componentId,
const componenttype_t type
) {
assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB");
assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB");
assertTrue(type < COMPONENT_TYPE_COUNT, "Component type OOB");
assertTrue(type != COMPONENT_TYPE_NULL, "Cannot initialize null component");
componentindex_t index = componentGetIndex(entityId, componentId);
component_t *cmp = &ENTITY_MANAGER.components[index];
memoryZero(cmp, sizeof(component_t));
cmp->type = type;
if(COMPONENT_DEFINITIONS[type].init) {
COMPONENT_DEFINITIONS[type].init(entityId, componentId);
}
}
void * componentGetData(
const entityid_t entityId,
const componentid_t componentId,
const componenttype_t type
) {
assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB");
assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB");
assertTrue(type < COMPONENT_TYPE_COUNT, "Component type OOB");
assertTrue(type != COMPONENT_TYPE_NULL, "Cannot get data of null component");
componentindex_t index = componentGetIndex(entityId, componentId);
component_t *cmp = &ENTITY_MANAGER.components[index];
assertTrue(cmp->type == type, "Component type mismatch");
return &cmp->data;
}
componentindex_t componentGetIndex(
const entityid_t entityId,
const componentid_t componentId
) {
assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB");
assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB");
return (entityId * ENTITY_COMPONENT_COUNT_MAX) + componentId;
}
entityid_t componentGetEntitiesWithComponent(
const componenttype_t type,
entityid_t outEntities[ENTITY_COUNT_MAX],
componentid_t outComponents[ENTITY_COUNT_MAX]
) {
assertTrue(type < COMPONENT_TYPE_COUNT, "Component type OOB");
assertTrue(type != COMPONENT_TYPE_NULL, "Cannot check NULL type");
assertNotNull(outEntities, "Output entities array cannot be null");
assertNotNull(outComponents, "Output components array cannot be null");
entityid_t written = 0;
for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) {
componentid_t used = ENTITY_MANAGER.entitiesWithComponent[
type * ENTITY_COUNT_MAX + i
];
if(used == COMPONENT_ID_INVALID) continue;
assertTrue(
ENTITY_MANAGER.components[componentGetIndex(i, used)].type == type,
"Component type mismatch in entitiesWithComponent lookup"
);
assertTrue(
(ENTITY_MANAGER.entities[i].state & ENTITY_STATE_ACTIVE) != 0,
"Inactive entity in entitiesWithComponent lookup"
);
assertTrue(
used < ENTITY_COMPONENT_COUNT_MAX,
"Component ID OOB in entitiesWithComponent lookup"
);
assertTrue(
componentGetIndex(i,used) < ENTITY_COUNT_MAX*ENTITY_COMPONENT_COUNT_MAX,
"Component index OOB in entitiesWithComponent lookup"
);
assertTrue(
ENTITY_MANAGER.components[componentGetIndex(i,used)].type == type,
"Component type mismatch in entitiesWithComponent lookup"
);
outComponents[written] = used;
outEntities[written++] = i;
}
return written;
}
void componentDispose(
const entityid_t entityId,
const componentid_t componentId
) {
assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB");
assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB");
componentindex_t index = componentGetIndex(entityId, componentId);
component_t *cmp = &ENTITY_MANAGER.components[index];
if(cmp->type == COMPONENT_TYPE_NULL) return;
if(COMPONENT_DEFINITIONS[cmp->type].dispose) {
COMPONENT_DEFINITIONS[cmp->type].dispose(entityId, componentId);
}
cmp->type = COMPONENT_TYPE_NULL;
}