diff --git a/Sources/FirebladeECS/Nexus+Component.swift b/Sources/FirebladeECS/Nexus+Component.swift index 6715ab1..33f0819 100644 --- a/Sources/FirebladeECS/Nexus+Component.swift +++ b/Sources/FirebladeECS/Nexus+Component.swift @@ -24,7 +24,6 @@ extension Nexus { @discardableResult public final func assign(component: Component, to entity: Entity) -> Bool { let entityId: EntityIdentifier = entity.identifier - defer { delegate?.nexusEvent(ComponentAdded(component: component.identifier, toEntity: entity.identifier)) } return assign(component: component, entityId: entityId) } diff --git a/Sources/FirebladeECS/Nexus+ComponentsBuilder.swift b/Sources/FirebladeECS/Nexus+ComponentsBuilder.swift index 6eab2d8..e48bab5 100644 --- a/Sources/FirebladeECS/Nexus+ComponentsBuilder.swift +++ b/Sources/FirebladeECS/Nexus+ComponentsBuilder.swift @@ -85,7 +85,7 @@ extension Nexus { /// - builder: The component builder providing context. /// - Returns: The newly created entities with the provided components assigned. @discardableResult - public func createEntities(count: Int, @ComponentsBuilder using builder: (ComponentsBuilder.Context) -> [Component]) -> [Entity] { + public func createEntities(count: Int, @ComponentsBuilder using builder: (ComponentsBuilder.Context) -> [Component] = { _ in [] }) -> [Entity] { (0.. [XCTestCaseEntry] { testCase(ComponentIdentifierTests.__allTests__ComponentIdentifierTests), testCase(HashingPerformanceTests.__allTests__HashingPerformanceTests), testCase(TypeIdentifierPerformanceTests.__allTests__TypeIdentifierPerformanceTests), - testCase(TypedFamilyPerformanceTests.__allTests__TypedFamilyPerformanceTests) + testCase(TypedFamilyPerformanceTests.__allTests__TypedFamilyPerformanceTests), ] } #endif diff --git a/Tests/FirebladeECSTests/NexusEventDelegateTests.swift b/Tests/FirebladeECSTests/NexusEventDelegateTests.swift new file mode 100644 index 0000000..762d4ae --- /dev/null +++ b/Tests/FirebladeECSTests/NexusEventDelegateTests.swift @@ -0,0 +1,232 @@ +// +// NexusEventDelegateTests.swift +// +// +// Created by Christian Treffs on 25.11.20. +// + +import FirebladeECS +import XCTest + +final class NexusEventDelegateTests: XCTestCase { + lazy var nexus = Nexus() + fileprivate var delegateTester: DelegateTester! + + override func setUp() { + super.setUp() + nexus = Nexus() + delegateTester = nil + } + + func testEventEntityCreated() { + var entityCreatedEvents: [EntityCreated] = [] + delegateTester = DelegateTester(onEvent: { event in + switch event { + case let entityCreated as EntityCreated: + entityCreatedEvents.append(entityCreated) + default: + XCTFail("unexpected event \(event)") + return + } + }) + nexus.delegate = delegateTester + + XCTAssertEqual(entityCreatedEvents.count, 0) + nexus.createEntity() + XCTAssertEqual(entityCreatedEvents.count, 1) + nexus.createEntities(count: 100) + XCTAssertEqual(entityCreatedEvents.count, 101) + } + + func testEventEntityDestroyed() { + var events: [EntityDestroyed] = [] + delegateTester = DelegateTester(onEvent: { event in + switch event { + case let event as EntityDestroyed: + events.append(event) + case _ as EntityCreated: + break + default: + XCTFail("unexpected event \(event)") + return + } + }) + nexus.delegate = delegateTester + + XCTAssertEqual(events.count, 0) + nexus.createEntities(count: 100) + XCTAssertEqual(events.count, 0) + for entitiy in nexus.makeEntitiesIterator() { + entitiy.destroy() + } + XCTAssertEqual(events.count, 100) + } + + func testEventComponentAdded() { + var componentsAddedEvents: [ComponentAdded] = [] + var entityCreatedEvents: [EntityCreated] = [] + delegateTester = DelegateTester(onEvent: { event in + switch event { + case let compAdded as ComponentAdded: + componentsAddedEvents.append(compAdded) + case let entityCreated as EntityCreated: + entityCreatedEvents.append(entityCreated) + default: + XCTFail("unexpected event \(event)") + return + } + }) + nexus.delegate = delegateTester + + XCTAssertEqual(componentsAddedEvents.count, 0) + XCTAssertEqual(entityCreatedEvents.count, 0) + let entity = nexus.createEntity() + entity.assign(MyComponent(name: "0", flag: true)) + XCTAssertEqual(componentsAddedEvents.count, 1) + XCTAssertEqual(entityCreatedEvents.count, 1) + let entity2 = nexus.createEntity() + entity2.assign(MyComponent(name: "0", flag: true), YourComponent(number: 2)) + XCTAssertEqual(componentsAddedEvents.count, 3) + XCTAssertEqual(entityCreatedEvents.count, 2) + } + + func testEventComponentRemoved() { + var events: [ComponentRemoved] = [] + delegateTester = DelegateTester(onEvent: { event in + switch event { + case let event as ComponentRemoved: + events.append(event) + default: + XCTFail("unexpected event \(event)") + return + } + }) + + let entity = nexus.createEntity() + entity.assign( + MyComponent(name: "Hello", flag: false), + YourComponent(number: 3.14), + EmptyComponent() + ) + + XCTAssertEqual(entity.numComponents, 3) + XCTAssertEqual(events.count, 0) + + nexus.delegate = delegateTester + + entity.remove(MyComponent.self) + XCTAssertEqual(events.count, 1) + XCTAssertEqual(entity.numComponents, 2) + + entity.remove(EmptyComponent.self) + XCTAssertEqual(events.count, 2) + XCTAssertEqual(entity.numComponents, 1) + + entity.remove(YourComponent.self) + XCTAssertEqual(events.count, 3) + XCTAssertEqual(entity.numComponents, 0) + + } + + func testFamilyMemeberAdded() { + var eventsFamilyMemberRemoved: [FamilyMemberRemoved] = [] + var eventsComponentRemoved: [ComponentRemoved] = [] + var eventsEntityDestroyed: [EntityDestroyed] = [] + delegateTester = DelegateTester(onEvent: { event in + switch event { + case is FamilyMemberAdded, + is ComponentAdded, + is EntityCreated: + break + case let event as FamilyMemberRemoved: + eventsFamilyMemberRemoved.append(event) + case let event as ComponentRemoved: + eventsComponentRemoved.append(event) + case let event as EntityDestroyed: + eventsEntityDestroyed.append(event) + default: + XCTFail("unexpected event \(event)") + return + } + }) + + let family = nexus.family(requiresAll: MyComponent.self, YourComponent.self) + nexus.delegate = delegateTester + + family.createMember(with: (MyComponent(name: "Bla", flag: true), YourComponent(number: 85))) + family.createMember(with: (MyComponent(name: "Hello", flag: false), YourComponent(number: 05050))) + family.createMember(with: (MyComponent(name: "asdasd", flag: true), YourComponent(number: 9494949))) + + XCTAssertEqual(eventsFamilyMemberRemoved.count, 0) + XCTAssertEqual(eventsComponentRemoved.count, 0) + XCTAssertEqual(family.count, 3) + XCTAssertEqual(eventsEntityDestroyed.count, 0) + + XCTAssertTrue(family.destroyMembers()) + + XCTAssertEqual(eventsFamilyMemberRemoved.count, 3) + XCTAssertEqual(eventsComponentRemoved.count, 6) + XCTAssertEqual(family.count, 0) + XCTAssertEqual(eventsEntityDestroyed.count, 3) + } + + func testFamilyMemberRemoved() { + var eventsMemberAdded: [FamilyMemberAdded] = [] + var eventsComponentAdded: [ComponentAdded] = [] + var eventsEntityCreated: [EntityCreated] = [] + delegateTester = DelegateTester(onEvent: { event in + switch event { + case let event as FamilyMemberAdded: + eventsMemberAdded.append(event) + case let event as ComponentAdded: + eventsComponentAdded.append(event) + case let event as EntityCreated: + eventsEntityCreated.append(event) + default: + XCTFail("unexpected event \(event)") + return + } + }) + + let family = nexus.family(requiresAll: MyComponent.self, YourComponent.self) + nexus.delegate = delegateTester + + XCTAssertEqual(family.count, 0) + XCTAssertEqual(eventsMemberAdded.count, 0) + XCTAssertEqual(eventsComponentAdded.count, 0) + XCTAssertEqual(eventsEntityCreated.count, 0) + + family.createMember(with: (MyComponent(name: "Bla", flag: true), YourComponent(number: 85))) + XCTAssertEqual(family.count, 1) + XCTAssertEqual(eventsMemberAdded.count, 1) + XCTAssertEqual(eventsComponentAdded.count, 2) + XCTAssertEqual(eventsEntityCreated.count, 1) + + + family.createMember(with: (MyComponent(name: "Hello", flag: false), YourComponent(number: 05050))) + XCTAssertEqual(family.count, 2) + XCTAssertEqual(eventsMemberAdded.count, 2) + XCTAssertEqual(eventsComponentAdded.count, 4) + XCTAssertEqual(eventsEntityCreated.count, 2) + } +} + + +fileprivate class DelegateTester: NexusEventDelegate { + var onEvent: (NexusEvent) -> () + var onNonFatal: (String) -> () + + init(onEvent: @escaping (NexusEvent) -> Void = { _ in }, + onNonFatal: @escaping (String) -> Void = { _ in }) { + self.onEvent = onEvent + self.onNonFatal = onNonFatal + } + + func nexusEvent(_ event: NexusEvent) { + onEvent(event) + } + + func nexusNonFatalError(_ message: String) { + onNonFatal(message) + } +} diff --git a/Tests/FirebladeECSTests/XCTestManifests.swift b/Tests/FirebladeECSTests/XCTestManifests.swift index 8f85eb7..52a81ab 100644 --- a/Tests/FirebladeECSTests/XCTestManifests.swift +++ b/Tests/FirebladeECSTests/XCTestManifests.swift @@ -7,7 +7,7 @@ extension ComponentIdentifierTests { // to regenerate. static let __allTests__ComponentIdentifierTests = [ ("testMirrorAsStableIdentifier", testMirrorAsStableIdentifier), - ("testStringDescribingAsStableIdentifier", testStringDescribingAsStableIdentifier) + ("testStringDescribingAsStableIdentifier", testStringDescribingAsStableIdentifier), ] } @@ -18,7 +18,7 @@ extension ComponentInstanceProviderTests { static let __allTests__ComponentInstanceProviderTests = [ ("testProviderReturnsTheInstance", testProviderReturnsTheInstance), ("testProvidersWithDifferentInstanceHaveDifferentIdentifier", testProvidersWithDifferentInstanceHaveDifferentIdentifier), - ("testProvidersWithSameInstanceHaveSameIdentifier", testProvidersWithSameInstanceHaveSameIdentifier) + ("testProvidersWithSameInstanceHaveSameIdentifier", testProvidersWithSameInstanceHaveSameIdentifier), ] } @@ -30,7 +30,7 @@ extension ComponentSingletonProviderTests { ("testProviderReturnsAnInstanceOfType", testProviderReturnsAnInstanceOfType), ("testProviderReturnsSameInstanceEachTime", testProviderReturnsSameInstanceEachTime), ("testProvidersWithDifferentTypeHaveDifferentIdentifier", testProvidersWithDifferentTypeHaveDifferentIdentifier), - ("testProvidersWithSameTypeHaveDifferentIdentifier", testProvidersWithSameTypeHaveDifferentIdentifier) + ("testProvidersWithSameTypeHaveDifferentIdentifier", testProvidersWithSameTypeHaveDifferentIdentifier), ] } @@ -39,7 +39,7 @@ extension ComponentTests { // `swift test --generate-linuxmain` // to regenerate. static let __allTests__ComponentTests = [ - ("testComponentIdentifier", testComponentIdentifier) + ("testComponentIdentifier", testComponentIdentifier), ] } @@ -51,7 +51,7 @@ extension ComponentTypeProviderTests { ("testProviderReturnsAnInstanceOfType", testProviderReturnsAnInstanceOfType), ("testProviderReturnsNewInstanceEachTime", testProviderReturnsNewInstanceEachTime), ("testProvidersWithDifferentTypeHaveDifferentIdentifier", testProvidersWithDifferentTypeHaveDifferentIdentifier), - ("testProvidersWithSameTypeHaveSameIdentifier", testProvidersWithSameTypeHaveSameIdentifier) + ("testProvidersWithSameTypeHaveSameIdentifier", testProvidersWithSameTypeHaveSameIdentifier), ] } @@ -62,7 +62,7 @@ extension DynamicComponentProviderTests { static let __allTests__DynamicComponentProviderTests = [ ("testProviderReturnsTheInstance", testProviderReturnsTheInstance), ("testProvidersWithDifferentMethodsHaveDifferentIdentifier", testProvidersWithDifferentMethodsHaveDifferentIdentifier), - ("testProvidersWithSameMethodHaveSameIdentifier", testProvidersWithSameMethodHaveSameIdentifier) + ("testProvidersWithSameMethodHaveSameIdentifier", testProvidersWithSameMethodHaveSameIdentifier), ] } @@ -74,7 +74,7 @@ extension EntityCreationTests { ("testBulkCreateEntitiesMultipleComponents", testBulkCreateEntitiesMultipleComponents), ("testBulkCreateEntitiesOneComponent", testBulkCreateEntitiesOneComponent), ("testCreateEntityMultipleComponents", testCreateEntityMultipleComponents), - ("testCreateEntityOneComponent", testCreateEntityOneComponent) + ("testCreateEntityOneComponent", testCreateEntityOneComponent), ] } @@ -87,7 +87,7 @@ extension EntityIdGenTests { ("testGeneratorDefaultInit", testGeneratorDefaultInit), ("testGeneratorMarkUnused", testGeneratorMarkUnused), ("testGeneratorWithDefaultEmptyCollection", testGeneratorWithDefaultEmptyCollection), - ("testLinearIncrement", testLinearIncrement) + ("testLinearIncrement", testLinearIncrement), ] } @@ -104,7 +104,7 @@ extension EntityStateMachineTests { ("testEnterSecondStateRemovesDifferentComponentsOfSameType", testEnterSecondStateRemovesDifferentComponentsOfSameType), ("testEnterSecondStateRemovesFirstStatesComponents", testEnterSecondStateRemovesFirstStatesComponents), ("testEnterStateAddsStatesComponents", testEnterStateAddsStatesComponents), - ("testGetsDeinitedWhileBeingStronglyReferencedByComponentAssignedToEntity", testGetsDeinitedWhileBeingStronglyReferencedByComponentAssignedToEntity) + ("testGetsDeinitedWhileBeingStronglyReferencedByComponentAssignedToEntity", testGetsDeinitedWhileBeingStronglyReferencedByComponentAssignedToEntity), ] } @@ -130,7 +130,7 @@ extension EntityStateTests { ("testProviderForTypeReturnsPassedProvider", testProviderForTypeReturnsPassedProvider), ("testProviderForTypeReturnsSingletonProvider", testProviderForTypeReturnsSingletonProvider), ("testProviderForTypeReturnsTypeProvider", testProviderForTypeReturnsTypeProvider), - ("testProviderForTypeReturnsTypeProviderByDefault", testProviderForTypeReturnsTypeProviderByDefault) + ("testProviderForTypeReturnsTypeProviderByDefault", testProviderForTypeReturnsTypeProviderByDefault), ] } @@ -147,7 +147,7 @@ extension EntityTests { ("testEntityIdentifierAndIndex", testEntityIdentifierAndIndex), ("testEntityIdGenerator", testEntityIdGenerator), ("testEntitySubscripts", testEntitySubscripts), - ("testRemoveAllComponentsFromEntity", testRemoveAllComponentsFromEntity) + ("testRemoveAllComponentsFromEntity", testRemoveAllComponentsFromEntity), ] } @@ -163,7 +163,7 @@ extension Family1Tests { ("testFamilyEncoding", testFamilyEncoding), ("testFamilyFailDecoding", testFamilyFailDecoding), ("testMemberCreation", testMemberCreation), - ("testMemberCreationBuilder", testMemberCreationBuilder) + ("testMemberCreationBuilder", testMemberCreationBuilder), ] } @@ -179,7 +179,7 @@ extension Family2Tests { ("testFamilyEncoding", testFamilyEncoding), ("testFamilyFailDecoding", testFamilyFailDecoding), ("testMemberCreation", testMemberCreation), - ("testMemberCreationBuilder", testMemberCreationBuilder) + ("testMemberCreationBuilder", testMemberCreationBuilder), ] } @@ -195,7 +195,7 @@ extension Family3Tests { ("testFamilyEncoding", testFamilyEncoding), ("testFamilyFailDecoding", testFamilyFailDecoding), ("testMemberCreation", testMemberCreation), - ("testMemberCreationBuilder", testMemberCreationBuilder) + ("testMemberCreationBuilder", testMemberCreationBuilder), ] } @@ -211,7 +211,7 @@ extension Family4Tests { ("testFamilyEncoding", testFamilyEncoding), ("testFamilyFailDecoding", testFamilyFailDecoding), ("testMemberCreation", testMemberCreation), - ("testMemberCreationBuilder", testMemberCreationBuilder) + ("testMemberCreationBuilder", testMemberCreationBuilder), ] } @@ -227,7 +227,7 @@ extension Family5Tests { ("testFamilyEncoding", testFamilyEncoding), ("testFamilyFailDecoding", testFamilyFailDecoding), ("testMemberCreation", testMemberCreation), - ("testMemberCreationBuilder", testMemberCreationBuilder) + ("testMemberCreationBuilder", testMemberCreationBuilder), ] } @@ -243,7 +243,7 @@ extension Family6Tests { ("testFamilyEncoding", testFamilyEncoding), ("testFamilyFailDecoding", testFamilyFailDecoding), ("testMemberCreation", testMemberCreation), - ("testMemberCreationBuilder", testMemberCreationBuilder) + ("testMemberCreationBuilder", testMemberCreationBuilder), ] } @@ -259,7 +259,7 @@ extension Family7Tests { ("testFamilyEncoding", testFamilyEncoding), ("testFamilyFailDecoding", testFamilyFailDecoding), ("testMemberCreation", testMemberCreation), - ("testMemberCreationBuilder", testMemberCreationBuilder) + ("testMemberCreationBuilder", testMemberCreationBuilder), ] } @@ -275,7 +275,7 @@ extension Family8Tests { ("testFamilyEncoding", testFamilyEncoding), ("testFamilyFailDecoding", testFamilyFailDecoding), ("testMemberCreation", testMemberCreation), - ("testMemberCreationBuilder", testMemberCreationBuilder) + ("testMemberCreationBuilder", testMemberCreationBuilder), ] } @@ -294,7 +294,7 @@ extension FamilyCodingTests { ("testEncodeFamily4", testEncodeFamily4), ("testEncodeFamily5", testEncodeFamily5), ("testEncodingFamily1", testEncodingFamily1), - ("testFailDecodingFamily", testFailDecodingFamily) + ("testFailDecodingFamily", testFailDecodingFamily), ] } @@ -311,7 +311,7 @@ extension FamilyTests { ("testFamilyExchange", testFamilyExchange), ("testFamilyLateMember", testFamilyLateMember), ("testFamilyMemberBasicIteration", testFamilyMemberBasicIteration), - ("testFamilyReuse", testFamilyReuse) + ("testFamilyReuse", testFamilyReuse), ] } @@ -321,7 +321,7 @@ extension FamilyTraitsTests { // to regenerate. static let __allTests__FamilyTraitsTests = [ ("testTraitCommutativity", testTraitCommutativity), - ("testTraitMatching", testTraitMatching) + ("testTraitMatching", testTraitMatching), ] } @@ -331,7 +331,21 @@ extension HashingTests { // to regenerate. static let __allTests__HashingTests = [ ("testCollisionsInCritialRange", testCollisionsInCritialRange), - ("testStringHashes", testStringHashes) + ("testStringHashes", testStringHashes), + ] +} + +extension NexusEventDelegateTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__NexusEventDelegateTests = [ + ("testEventComponentAdded", testEventComponentAdded), + ("testEventComponentRemoved", testEventComponentRemoved), + ("testEventEntityCreated", testEventEntityCreated), + ("testEventEntityDestroyed", testEventEntityDestroyed), + ("testFamilyMemberRemoved", testFamilyMemberRemoved), + ("testFamilyMemeberAdded", testFamilyMemeberAdded), ] } @@ -346,7 +360,7 @@ extension NexusTests { ("testComponentUniqueness", testComponentUniqueness), ("testEntityCreate", testEntityCreate), ("testEntityDestroy", testEntityDestroy), - ("testEntityIteration", testEntityIteration) + ("testEntityIteration", testEntityIteration), ] } @@ -368,7 +382,7 @@ extension SingleTests { ("testSingleCreation", testSingleCreation), ("testSingleCreationOnExistingFamilyMember", testSingleCreationOnExistingFamilyMember), ("testSingleEntityAndComponentCreation", testSingleEntityAndComponentCreation), - ("testSingleReuse", testSingleReuse) + ("testSingleReuse", testSingleReuse), ] } @@ -390,7 +404,7 @@ extension SparseSetTests { ("testSparseSetRemoveAndAdd", testSparseSetRemoveAndAdd), ("testSparseSetRemoveNonPresent", testSparseSetRemoveNonPresent), ("testStartEndIndex", testStartEndIndex), - ("testSubscript", testSubscript) + ("testSubscript", testSubscript), ] } @@ -401,7 +415,7 @@ extension StateComponentMappingTests { static let __allTests__StateComponentMappingTests = [ ("testAddAddsProviderToState", testAddAddsProviderToState), ("testAddReturnsSameMappingForDifferentComponentTypes", testAddReturnsSameMappingForDifferentComponentTypes), - ("testAddReturnsSameMappingForSameComponentType", testAddReturnsSameMappingForSameComponentType) + ("testAddReturnsSameMappingForSameComponentType", testAddReturnsSameMappingForSameComponentType), ] } @@ -410,7 +424,7 @@ extension SystemsTests { // `swift test --generate-linuxmain` // to regenerate. static let __allTests__SystemsTests = [ - ("testSystemsUpdate", testSystemsUpdate) + ("testSystemsUpdate", testSystemsUpdate), ] } @@ -439,12 +453,13 @@ public func __allTests() -> [XCTestCaseEntry] { testCase(FamilyTests.__allTests__FamilyTests), testCase(FamilyTraitsTests.__allTests__FamilyTraitsTests), testCase(HashingTests.__allTests__HashingTests), + testCase(NexusEventDelegateTests.__allTests__NexusEventDelegateTests), testCase(NexusTests.__allTests__NexusTests), testCase(SerializationTests.__allTests__SerializationTests), testCase(SingleTests.__allTests__SingleTests), testCase(SparseSetTests.__allTests__SparseSetTests), testCase(StateComponentMappingTests.__allTests__StateComponentMappingTests), - testCase(SystemsTests.__allTests__SystemsTests) + testCase(SystemsTests.__allTests__SystemsTests), ] } #endif