133 lines
4.2 KiB
C
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;
|
|
} |