// // Nexus.swift // FirebladeECS // // Created by Christian Treffs on 09.10.17. // public final class Nexus { /// Static version string. public static let version: String = "1.0.0" /// Main entity storage. /// Entities are tightly packed by EntityIdentifier. @usableFromInline final var entityStorage: UnorderedSparseSet /// Entity ids that are currently not used. @usableFromInline final var freeEntities: [EntityIdentifier] /// - Key: ComponentIdentifier aka component type. /// - Value: Array of component instances of same type (uniform). /// New component instances are appended. @usableFromInline final var componentsByType: [ComponentIdentifier: UnorderedSparseSet] /// - Key: EntityIdentifier aka entity index /// - Value: Set of unique component types (ComponentIdentifier). /// Each element is a component identifier associated with this entity. @usableFromInline final var componentIdsByEntity: [EntityIdentifier: Set] /// - Key: A parent entity id. /// - Value: Adjacency Set of all associated children. @usableFromInline final var childrenByParentEntity: [EntityIdentifier: Set] /// - Key: FamilyTraitSet aka component types that make up one distinct family. /// - Value: Tightly packed EntityIdentifiers that represent the association of an entity to the family. @usableFromInline final var familyMembersByTraits: [FamilyTraitSet: UnorderedSparseSet] public final weak var delegate: NexusEventDelegate? public convenience init() { self.init(entityStorage: UnorderedSparseSet(), componentsByType: [:], componentsByEntity: [:], freeEntities: [], familyMembersByTraits: [:], childrenByParentEntity: [:]) } internal init(entityStorage: UnorderedSparseSet, componentsByType: [ComponentIdentifier: UnorderedSparseSet], componentsByEntity: [EntityIdentifier: Set], freeEntities: [EntityIdentifier], familyMembersByTraits: [FamilyTraitSet: UnorderedSparseSet], childrenByParentEntity: [EntityIdentifier: Set]) { self.entityStorage = entityStorage self.componentsByType = componentsByType self.componentIdsByEntity = componentsByEntity self.freeEntities = freeEntities self.familyMembersByTraits = familyMembersByTraits self.childrenByParentEntity = childrenByParentEntity } deinit { clear() } public final func clear() { entityStorage.forEach { destroy(entityId: $0) } entityStorage.removeAll() freeEntities.removeAll() componentsByType.removeAll() componentIdsByEntity.removeAll() familyMembersByTraits.removeAll() childrenByParentEntity.removeAll() } public static var knownUniqueComponentTypes: Set { return Set(componentDecoderMap.keys) } internal static var componentDecoderMap: [ComponentIdentifier: (Decoder) throws -> Component] = [:] /// Register a component type uniquely with the Nexus implementation. /// - Parameters: /// - componentType: The component meta type. /// - identifier: The unique identifier. internal static func register(component componentType: C.Type, using identifier: ComponentIdentifier) where C: Component { precondition(componentDecoderMap[identifier] == nil, "Component type collision: \(identifier) already in use.") componentDecoderMap[identifier] = { try C(from: $0) } } } // MARK: - Errors extension Nexus { public enum Error: Swift.Error { case versionMismatch(required: String, provided: String) } } // MARK: - Equatable extension Nexus: Equatable { @inlinable public static func == (lhs: Nexus, rhs: Nexus) -> Bool { return lhs.entityStorage == rhs.entityStorage && lhs.componentIdsByEntity == rhs.componentIdsByEntity && lhs.freeEntities == rhs.freeEntities && lhs.familyMembersByTraits == rhs.familyMembersByTraits && lhs.componentsByType.keys == rhs.componentsByType.keys && lhs.childrenByParentEntity == rhs.childrenByParentEntity // NOTE: components are not equatable (yet) } } // MARK: - CustomDebugStringConvertible extension Nexus: CustomDebugStringConvertible { public var debugDescription: String { return "" } }