#include #include #include #include #include #include #include #include #include EntityID g_entity_manager_id = 0; void InitEntityManager(World* world) { Assert(world != NULL); EntityManager* newManager = ArenaPushStruct(world->WorldArena, EntityManager); newManager->next_local_counter = 1ULL; world->EntityManager = newManager; VectorArenaCreate(&newManager->Entities, Entity, world->WorldArena, 100000 JULIET_DEBUG_PARAM("Entities")); ArenaParams by_type_params = { .ReserveSize = Kilobytes(1), .CommitSize = Kilobytes(1), .Name = "" JULIET_DEBUG_ONLY(, .DoNotReserveMore = true) }; for (uint8 i = 0; i < ENTITY(Count); ++i) { by_type_params.Name = kEntity_type_names[i]; newManager->by_type[i].arena = ArenaAllocate(by_type_params); newManager->by_type[i].array = NULL; newManager->by_type[i].count = 0; } } void ShutdownEntityManager(void) { EntityManager* manager = GetEntityManager(); for (uint8 i = 0; i < ENTITY(Count); ++i) { ArenaRelease(manager->by_type[i].arena); } vector_arena_destroy(&manager->Entities); } EntityManager* GetEntityManager(void) { EntityManager* entityManager = GetGameState()->World->EntityManager; Assert(entityManager != NULL); return entityManager; } EntityID generate_next_entity_id(EntityManager* manager) { Assert(manager != NULL); UserID user = get_local_user_id(); Assert(user != kInvalid_user_id); Assert(manager->next_local_counter != kEntityID_user_id_mask); EntityID new_id = make_entity_id(user, manager->next_local_counter); manager->next_local_counter += 1ULL; return new_id; } EntityTemplate* RegisterEntity(EntityManager* manager, Entity* base, DerivedType entity) { Assert(manager != NULL); Assert(base != NULL); base->ID = g_entity_manager_id++; base->derived = entity; VectorArenaPushPtr(Entity, &manager->Entities, base); EntityTemplate* ptr = (EntityTemplate*)ArenaPushSize( manager->by_type[base->derived_kind->kind].arena, base->derived_kind->size_of, base->derived_kind->alignment, false JULIET_DEBUG_PARAM(kEntity_type_names[base->derived_kind->kind])); MemCopy(ptr, entity, base->derived_kind->size_of); manager->by_type[base->derived_kind->kind].count += 1; ptr->base = VectorArenaBack(Entity, &manager->Entities); if (manager->by_type[base->derived_kind->kind].array == NULL) { manager->by_type[base->derived_kind->kind].array = ptr; } return ptr; } Entity* allocate_entity(EntityManager* manager, const Class* derived_type_class) { Assert(manager != NULL); Assert(derived_type_class != NULL); Assert(derived_type_class->kind < ENTITY(Count)); Assert(derived_type_class->size_of >= sizeof(EntityTemplate)); Assert(derived_type_class->alignment > 0); Assert(derived_type_class->initialize_fct != NULL); Entity base_template = { 0 }; base_template.derived_kind = derived_type_class; base_template.is_dirty = true; VectorArenaPushPtr(Entity, &manager->Entities, &base_template); Entity* base_ptr = VectorArenaBack(Entity, &manager->Entities); Assert(base_ptr != NULL); typed_entity_array* typed_array = &manager->by_type[derived_type_class->kind]; Assert(typed_array->arena != NULL); void* derived = ArenaPushSize(typed_array->arena, derived_type_class->size_of, derived_type_class->alignment, false JULIET_DEBUG_PARAM(kEntity_type_names[derived_type_class->kind])); Assert(derived != NULL); derived_type_class->initialize_fct(derived); EntityTemplate* derived_template = (EntityTemplate*)derived; base_ptr->derived = derived; derived_template->base = base_ptr; if (typed_array->array == NULL) { typed_array->array = derived_template; } typed_array->count += 1; return base_ptr; } void UpdateEntityManager(EntityManager* manager) { Assert(manager != NULL); // Todo : inert by definition dont move, but this is for test typed_entity_array* by_type = &manager->by_type[ENTITY(Inert)]; for (index_t i = 0; i < by_type->count; ++i) { Inert* inert = ((Inert*)by_type->array) + i; if (inert->MeshInstance != indexMax) { Matrix transform = MatrixTranslation(inert->base->position.x, inert->base->position.y, inert->base->position.z); SetMeshInstanceTransform(inert->MeshInstance, &transform); } } } Entity* deserialize_entity(Archive* ar, EntityManager* manager) { Assert(ar != NULL); Assert(manager != NULL); Assert(ar->loading); String class_name = { 0 }; SERIALIZE_STR(ar, Class, &class_name); const Class* class_ptr = find_class_by_name(class_name); Assert(class_ptr != NULL); Entity* entity_base = allocate_entity(manager, class_ptr); Assert(entity_base != NULL); serialize_entity(ar, entity_base); if (entity_base->ID >= g_entity_manager_id) { g_entity_manager_id = entity_base->ID + 1; } entity_base->is_dirty = false; return entity_base; } void update_local_counter(EntityManager* manager, EntityID entity_id) { Assert(manager != NULL); uint8 user_id = get_local_user_id(); if (get_user_id(entity_id) == user_id) { uint64 counter = get_local_counter(entity_id); if (counter >= manager->next_local_counter) { manager->next_local_counter = counter + 1ULL; } } }