add changes proposed during code review

This commit is contained in:
Igor Kravchenko 2020-10-08 01:45:10 +03:00
parent 2902b096a5
commit 1c2bb78dc4
2 changed files with 115 additions and 101 deletions

View File

@ -1,10 +1,17 @@
/// Requires initializer with no arguments. //
/// In case of component - makes sure it can be instantiated by component provider // FSM.swift
public protocol EmptyInitializable { // FirebladeECS
//
// Created by Igor Kravchenko on 29.09.2020.
//
/// Requires initializer with default values.
/// In case of component - makes sure it can be instantiated by component provider
public protocol DefaultInitializable {
init() init()
} }
public typealias ComponentInitializable = Component & EmptyInitializable public typealias ComponentInitializable = Component & DefaultInitializable
/// This is the Interface for component providers. Component providers are used to supply components /// This is the Interface for component providers. Component providers are used to supply components
/// for states within an EntityStateMachine. FirebladeECS includes three standard component providers, /// for states within an EntityStateMachine. FirebladeECS includes three standard component providers,
@ -20,7 +27,7 @@ public protocol ComponentProvider {
/// is not removed. If they are different, the component from the old state is removed /// is not removed. If they are different, the component from the old state is removed
/// and a component for the new state is added. /// and a component for the new state is added.
/// - Returns: struct/class instance that confirms to Hashable protocol /// - Returns: struct/class instance that conforms to Hashable protocol
var identifier: AnyHashable { get } var identifier: AnyHashable { get }
/// Used to request a component from the provider. /// Used to request a component from the provider.
@ -32,7 +39,7 @@ public protocol ComponentProvider {
/// This component provider always returns the same instance of the component. The instance /// This component provider always returns the same instance of the component. The instance
/// is passed to the provider at initialisation. /// is passed to the provider at initialisation.
public class ComponentInstanceProvider { public final class ComponentInstanceProvider {
private var instance: Component private var instance: Component
/// Initializer /// Initializer
@ -61,7 +68,7 @@ extension ComponentInstanceProvider: ComponentProvider {
/// This component provider always returns a new instance of a component. An instance /// This component provider always returns a new instance of a component. An instance
/// is created when requested and is of the type passed in to the initializer. /// is created when requested and is of the type passed in to the initializer.
public class ComponentTypeProvider { public final class ComponentTypeProvider {
private var componentType: ComponentInitializable.Type private var componentType: ComponentInitializable.Type
/// Used to compare this provider with others. Any ComponentTypeProvider that returns /// Used to compare this provider with others. Any ComponentTypeProvider that returns
@ -89,7 +96,7 @@ extension ComponentTypeProvider: ComponentProvider {
/// This component provider always returns the same instance of the component. The instance /// This component provider always returns the same instance of the component. The instance
/// is created when first required and is of the type passed in to the initializer. /// is created when first required and is of the type passed in to the initializer.
public class ComponentSingletonProvider { public final class ComponentSingletonProvider {
private lazy var instance: Component = { private lazy var instance: Component = {
componentType.init() componentType.init()
}() }()
@ -122,9 +129,9 @@ extension ComponentSingletonProvider: ComponentProvider {
/// This component provider calls a function to get the component instance. The function must /// This component provider calls a function to get the component instance. The function must
/// return a single component of the appropriate type. /// return a single component of the appropriate type.
public class DynamicComponentProvider<C: Component> { public final class DynamicComponentProvider<C: Component> {
/// Wrapper for closure to make it hashable via ObjectIdentifier /// Wrapper for closure to make it hashable via ObjectIdentifier
public class Closure { public final class Closure {
let provideComponent: () -> C let provideComponent: () -> C
/// Initializer /// Initializer
@ -168,26 +175,26 @@ public class EntityState {
public init() {} public init() {}
/// Add a new ComponentMapping to this state. The mapping is a utility class that is used to /// Add a new StateComponentMapping to this state. The mapping is a utility class that is used to
/// map a component type to the provider that provides the component. /// map a component type to the provider that provides the component.
/// - Parameter type: The type of component to be mapped /// - Parameter type: The type of component to be mapped
/// - Returns: The component mapping to use when setting the provider for the component /// - Returns: The component mapping to use when setting the provider for the component
@discardableResult @discardableResult
public func add(_ type: ComponentInitializable.Type) -> StateComponentMapping { public func addMapping(for type: ComponentInitializable.Type) -> StateComponentMapping {
StateComponentMapping(creatingState: self, type: type) StateComponentMapping(creatingState: self, type: type)
} }
/// Get the ComponentProvider for a particular component type. /// Get the ComponentProvider for a particular component type.
/// - Parameter type: The type of component to get the provider for /// - Parameter type: The type of component to get the provider for
/// - Returns: The ComponentProvider /// - Returns: The ComponentProvider
public func get(_ type: ComponentInitializable.Type) -> ComponentProvider? { public func provider(for type: ComponentInitializable.Type) -> ComponentProvider? {
providers[type.identifier] providers[type.identifier]
} }
/// To determine whether this state has a provider for a specific component type. /// To determine whether this state has a provider for a specific component type.
/// - Parameter type: The type of component to look for a provider for /// - Parameter type: The type of component to look for a provider for
/// - Returns: true if there is a provider for the given type, false otherwise /// - Returns: true if there is a provider for the given type, false otherwise
public func has(_ type: ComponentInitializable.Type) -> Bool { public func hasProvider(for type: ComponentInitializable.Type) -> Bool {
providers[type.identifier] != nil providers[type.identifier] != nil
} }
} }
@ -202,7 +209,7 @@ extension EntityState {
@discardableResult @discardableResult
@inline(__always) @inline(__always)
public func addInstance<C: ComponentInitializable>(_ component: C) -> Self { public func addInstance<C: ComponentInitializable>(_ component: C) -> Self {
add(C.self).withInstance(component) addMapping(for: C.self).withInstance(component)
return self return self
} }
@ -213,7 +220,7 @@ extension EntityState {
@inline(__always) @inline(__always)
@discardableResult @discardableResult
public func addType(_ type: ComponentInitializable.Type) -> Self { public func addType(_ type: ComponentInitializable.Type) -> Self {
add(type).withType(type) addMapping(for: type).withType(type)
return self return self
} }
@ -225,7 +232,7 @@ extension EntityState {
@inline(__always) @inline(__always)
@discardableResult @discardableResult
public func addSingleton(_ type: ComponentInitializable.Type) -> Self { public func addSingleton(_ type: ComponentInitializable.Type) -> Self {
add(type).withSingleton(type) addMapping(for: type).withSingleton(type)
return self return self
} }
@ -236,7 +243,7 @@ extension EntityState {
@inline(__always) @inline(__always)
@discardableResult @discardableResult
public func addMethod<C: ComponentInitializable>(closure: DynamicComponentProvider<C>.Closure) -> Self { public func addMethod<C: ComponentInitializable>(closure: DynamicComponentProvider<C>.Closure) -> Self {
add(C.self).withMethod(closure) addMapping(for: C.self).withMethod(closure)
return self return self
} }
@ -247,7 +254,7 @@ extension EntityState {
@inline(__always) @inline(__always)
@discardableResult @discardableResult
public func addProvider<C: ComponentInitializable>(type: C.Type, provider: ComponentProvider) -> Self { public func addProvider<C: ComponentInitializable>(type: C.Type, provider: ComponentProvider) -> Self {
add(type).withProvider(provider) addMapping(for: type).withProvider(provider)
return self return self
} }
} }
@ -325,13 +332,13 @@ public class StateComponentMapping {
return self return self
} }
/// Maps through to the add method of the EntityState that this mapping belongs to /// Maps through to the addMapping method of the EntityState that this mapping belongs to
/// so that a fluent interface can be used when configuring entity states. /// so that a fluent interface can be used when configuring entity states.
/// - Parameter type: The type of component to add a mapping to the state for /// - Parameter type: The type of component to add a mapping to the state for
/// - Returns: The new ComponentMapping for that type /// - Returns: The new ComponentMapping for that type
@discardableResult @discardableResult
public func add(_ type: ComponentInitializable.Type) -> StateComponentMapping { public func add(_ type: ComponentInitializable.Type) -> StateComponentMapping {
creatingState.add(type) creatingState.addMapping(for: type)
} }
private func setProvider(_ provider: ComponentProvider) { private func setProvider(_ provider: ComponentProvider) {
@ -345,9 +352,9 @@ public class StateComponentMapping {
/// This is a state machine for an entity. The state machine manages a set of states, /// This is a state machine for an entity. The state machine manages a set of states,
/// each of which has a set of component providers. When the state machine changes the state, it removes /// each of which has a set of component providers. When the state machine changes the state, it removes
/// components associated with the previous state and adds components associated with the new state. /// components associated with the previous state and adds components associated with the new state.
/// - Parameter StateName: Generic hashable state name type /// - Parameter StateIdentifier: Generic hashable state name type
public class EntityStateMachine<StateName: Hashable> { public class EntityStateMachine<StateIdentifier: Hashable> {
private var states: [StateName: EntityState] private var states: [StateIdentifier: EntityState]
/// The current state of the state machine. /// The current state of the state machine.
private var currentState: EntityState? private var currentState: EntityState?
@ -366,7 +373,7 @@ public class EntityStateMachine<StateName: Hashable> {
/// - Parameter state: The state. /// - Parameter state: The state.
/// - Returns: This state machine, so methods can be chained. /// - Returns: This state machine, so methods can be chained.
@discardableResult @discardableResult
public func addState(name: StateName, state: EntityState) -> Self { public func addState(name: StateIdentifier, state: EntityState) -> Self {
states[name] = state states[name] = state
return self return self
} }
@ -375,7 +382,7 @@ public class EntityStateMachine<StateName: Hashable> {
/// - Parameter name: The name of the new state - used to identify it later in the changeState method call. /// - Parameter name: The name of the new state - used to identify it later in the changeState method call.
/// - Returns: The new EntityState object that is the state. This will need to be configured with /// - Returns: The new EntityState object that is the state. This will need to be configured with
/// the appropriate component providers. /// the appropriate component providers.
public func createState(name: StateName) -> EntityState { public func createState(name: StateIdentifier) -> EntityState {
let state = EntityState() let state = EntityState()
states[name] = state states[name] = state
return state return state
@ -384,7 +391,7 @@ public class EntityStateMachine<StateName: Hashable> {
/// Change to a new state. The components from the old state will be removed and the components /// Change to a new state. The components from the old state will be removed and the components
/// for the new state will be added. /// for the new state will be added.
/// - Parameter name: The name of the state to change to. /// - Parameter name: The name of the state to change to.
public func changeState(name: StateName) { public func changeState(name: StateIdentifier) {
guard let newState = states[name] else { guard let newState = states[name] else {
assertionFailure("Entity state '\(name)' doesn't exist") assertionFailure("Entity state '\(name)' doesn't exist")
return return

View File

@ -1,3 +1,10 @@
//
// FSMTests.swift
// FirebladeECSTests
//
// Created by Igor Kravchenko on 29.09.2020.
//
import FirebladeECS import FirebladeECS
import XCTest import XCTest
@ -59,19 +66,19 @@ class ComponentTypeProviderTests: XCTestCase {
XCTAssertNotEqual(provider1.identifier, provider2.identifier) XCTAssertNotEqual(provider1.identifier, provider2.identifier)
} }
class MockComponent: Component, EmptyInitializable { class MockComponent: Component, DefaultInitializable {
var value: String var value: String
required init() { required init() {
self.value = "" value = ""
} }
} }
class MockComponent2: Component, EmptyInitializable { class MockComponent2: Component, DefaultInitializable {
var value: Bool var value: Bool
required init() { required init() {
self.value = false value = false
} }
} }
} }
@ -105,19 +112,19 @@ class ComponentSingletonProviderTests: XCTestCase {
XCTAssertNotEqual(provider1.identifier, provider2.identifier) XCTAssertNotEqual(provider1.identifier, provider2.identifier)
} }
class MockComponent: Component, EmptyInitializable { class MockComponent: Component, DefaultInitializable {
var value: Int var value: Int
required init() { required init() {
self.value = 0 value = 0
} }
} }
class MockComponent2: Component, EmptyInitializable { class MockComponent2: Component, DefaultInitializable {
var value: String var value: String
required init() { required init() {
self.value = "" value = ""
} }
} }
} }
@ -174,135 +181,135 @@ class EntityStateTests: XCTestCase {
state = EntityState() state = EntityState()
} }
func testAddWithNoQualifierCreatesTypeProvider() { func testAddMappingWithNoQualifierCreatesTypeProvider() {
state.add(MockComponent.self) state.addMapping(for: MockComponent.self)
let provider = state.providers[MockComponent.identifier] let provider = state.providers[MockComponent.identifier]
XCTAssertNotNil(provider) XCTAssertNotNil(provider)
XCTAssertTrue(provider is ComponentTypeProvider?) XCTAssertTrue(provider is ComponentTypeProvider?)
XCTAssertTrue(provider?.getComponent() is MockComponent?) XCTAssertTrue(provider?.getComponent() is MockComponent?)
} }
func testAddWithTypeQualifierCreatesTypeProvider() { func testAddMappingWithTypeQualifierCreatesTypeProvider() {
state.add(MockComponent.self).withType(MockComponent2.self) state.addMapping(for: MockComponent.self).withType(MockComponent2.self)
let provider = state.providers[MockComponent.identifier] let provider = state.providers[MockComponent.identifier]
XCTAssertNotNil(provider) XCTAssertNotNil(provider)
XCTAssertTrue(provider is ComponentTypeProvider?) XCTAssertTrue(provider is ComponentTypeProvider?)
XCTAssertTrue(provider?.getComponent() is MockComponent2?) XCTAssertTrue(provider?.getComponent() is MockComponent2?)
} }
func testAddWithInstanceQualifierCreatesInstanceProvider() { func testAddMappingWithInstanceQualifierCreatesInstanceProvider() {
let component = MockComponent() let component = MockComponent()
state.add(MockComponent.self).withInstance(component) state.addMapping(for: MockComponent.self).withInstance(component)
let provider = state.providers[MockComponent.identifier] let provider = state.providers[MockComponent.identifier]
XCTAssertTrue(provider is ComponentInstanceProvider?) XCTAssertTrue(provider is ComponentInstanceProvider?)
XCTAssertTrue(provider?.getComponent() === component) XCTAssertTrue(provider?.getComponent() === component)
} }
func testAddWithSingletonQualifierCreatesSingletonProvider() { func testAddMappingWithSingletonQualifierCreatesSingletonProvider() {
state.add(MockComponent.self).withSingleton(MockComponent.self) state.addMapping(for: MockComponent.self).withSingleton(MockComponent.self)
let provider = state.providers[MockComponent.identifier] let provider = state.providers[MockComponent.identifier]
XCTAssertTrue(provider is ComponentSingletonProvider?) XCTAssertTrue(provider is ComponentSingletonProvider?)
XCTAssertTrue(provider?.getComponent() is MockComponent?) XCTAssertTrue(provider?.getComponent() is MockComponent?)
} }
func testAddWithMethodQualifierCreatesDynamicProvider() { func testAddMappingWithMethodQualifierCreatesDynamicProvider() {
let dynamickProvider = DynamicComponentProvider.Closure { let dynamickProvider = DynamicComponentProvider.Closure {
MockComponent() MockComponent()
} }
state.add(MockComponent.self).withMethod(dynamickProvider) state.addMapping(for: MockComponent.self).withMethod(dynamickProvider)
let provider = state.providers[MockComponent.identifier] let provider = state.providers[MockComponent.identifier]
XCTAssertNotNil(provider) XCTAssertNotNil(provider)
XCTAssertTrue(provider is DynamicComponentProvider<MockComponent>?) XCTAssertTrue(provider is DynamicComponentProvider<MockComponent>?)
XCTAssertTrue(provider?.getComponent() is MockComponent) XCTAssertTrue(provider?.getComponent() is MockComponent)
} }
func testGetReturnsTypeProviderByDefault() { func testProviderForTypeReturnsTypeProviderByDefault() {
state.add(MockComponent.self) state.addMapping(for: MockComponent.self)
let provider = state.get(MockComponent.self) let provider = state.provider(for: MockComponent.self)
XCTAssertNotNil(provider) XCTAssertNotNil(provider)
XCTAssertTrue(provider is ComponentTypeProvider?) XCTAssertTrue(provider is ComponentTypeProvider?)
} }
func testGetReturnsInstanceProvider() { func testProviderForTypeReturnsInstanceProvider() {
let component = MockComponent() let component = MockComponent()
state.add(MockComponent.self).withInstance(component) state.addMapping(for: MockComponent.self).withInstance(component)
let provider = state.get(MockComponent.self) let provider = state.provider(for: MockComponent.self)
XCTAssertNotNil(provider) XCTAssertNotNil(provider)
XCTAssertTrue(provider is ComponentInstanceProvider?) XCTAssertTrue(provider is ComponentInstanceProvider?)
} }
func testGetReturnsSingletonProvider() { func testProviderForTypeReturnsSingletonProvider() {
state.add(MockComponent.self).withSingleton(MockComponent.self) state.addMapping(for: MockComponent.self).withSingleton(MockComponent.self)
let provider = state.get(MockComponent.self) let provider = state.provider(for: MockComponent.self)
XCTAssertNotNil(provider) XCTAssertNotNil(provider)
XCTAssertTrue(provider is ComponentSingletonProvider?) XCTAssertTrue(provider is ComponentSingletonProvider?)
} }
func testGetReturnsDynamicProvider() { func testProviderForTypeReturnsDynamicProvider() {
state.add(MockComponent.self).withMethod(.init { MockComponent() }) state.addMapping(for: MockComponent.self).withMethod(.init { MockComponent() })
let provider = state.get(MockComponent.self) let provider = state.provider(for: MockComponent.self)
XCTAssertNotNil(provider) XCTAssertNotNil(provider)
XCTAssertTrue(provider is DynamicComponentProvider<MockComponent>?) XCTAssertTrue(provider is DynamicComponentProvider<MockComponent>?)
} }
func testGetReturnsTypeProvider() { func testProviderForTypeReturnsTypeProvider() {
state.add(MockComponent.self).withType(MockComponent.self) state.addMapping(for: MockComponent.self).withType(MockComponent.self)
let provider = state.get(MockComponent.self) let provider = state.provider(for: MockComponent.self)
XCTAssertNotNil(provider) XCTAssertNotNil(provider)
XCTAssertTrue(provider is ComponentTypeProvider?) XCTAssertTrue(provider is ComponentTypeProvider?)
} }
func testGetReturnsPassedProvider() { func testProviderForTypeReturnsPassedProvider() {
let singletonProvider = ComponentSingletonProvider(type: MockComponent.self) let singletonProvider = ComponentSingletonProvider(type: MockComponent.self)
state.add(MockComponent.self).withProvider(singletonProvider) state.addMapping(for: MockComponent.self).withProvider(singletonProvider)
let provider = state.get(MockComponent.self) as? ComponentSingletonProvider let provider = state.provider(for: MockComponent.self) as? ComponentSingletonProvider
XCTAssertNotNil(provider) XCTAssertNotNil(provider)
XCTAssertTrue(provider === singletonProvider) XCTAssertTrue(provider === singletonProvider)
} }
func testHasReturnsFalseForNotCreatedProvider() { func testHasProviderReturnsFalseForNotCreatedProvider() {
XCTAssertFalse(state.has(MockComponent.self)) XCTAssertFalse(state.hasProvider(for: MockComponent.self))
} }
func testHasReturnsTrueForCreatedProvider() { func testHasProviderReturnsTrueForCreatedProvider() {
state.add(MockComponent.self) state.addMapping(for: MockComponent.self)
XCTAssertTrue(state.has(MockComponent.self)) XCTAssertTrue(state.hasProvider(for: MockComponent.self))
} }
func testAddInstanceCreatesMappingAndSetsInstanceProviderForInstanceType() { func testAddInstanceCreatesMappingAndSetsInstanceProviderForInstanceType() {
let component = MockComponent() let component = MockComponent()
state.addInstance(component) state.addInstance(component)
XCTAssertTrue(state.get(MockComponent.self) is ComponentInstanceProvider?) XCTAssertTrue(state.provider(for: MockComponent.self) is ComponentInstanceProvider?)
XCTAssert(state.get(MockComponent.self)?.getComponent() === component) XCTAssert(state.provider(for: MockComponent.self)?.getComponent() === component)
} }
func testAddTypeCreatesMappingAndSetsTypeProviderForType() { func testAddTypeCreatesMappingAndSetsTypeProviderForType() {
state.addType(MockComponent.self) state.addType(MockComponent.self)
XCTAssertTrue(state.get(MockComponent.self) is ComponentTypeProvider?) XCTAssertTrue(state.provider(for: MockComponent.self) is ComponentTypeProvider?)
XCTAssertNotNil(state.get(MockComponent.self)?.getComponent()) XCTAssertNotNil(state.provider(for: MockComponent.self)?.getComponent())
XCTAssertTrue(state.get(MockComponent.self)?.getComponent() is MockComponent?) XCTAssertTrue(state.provider(for: MockComponent.self)?.getComponent() is MockComponent?)
} }
func testAddSingletonCreatesMappingAndSetsSingletonProviderForType() { func testAddSingletonCreatesMappingAndSetsSingletonProviderForType() {
state.addSingleton(MockComponent.self) state.addSingleton(MockComponent.self)
XCTAssertTrue(state.get(MockComponent.self) is ComponentSingletonProvider?) XCTAssertTrue(state.provider(for: MockComponent.self) is ComponentSingletonProvider?)
XCTAssertNotNil(state.get(MockComponent.self)?.getComponent()) XCTAssertNotNil(state.provider(for: MockComponent.self)?.getComponent())
XCTAssertTrue(state.get(MockComponent.self)?.getComponent() is MockComponent?) XCTAssertTrue(state.provider(for: MockComponent.self)?.getComponent() is MockComponent?)
} }
func testAddMethodCreatesMappingAndSetsDynamicProviderForType() { func testAddMethodCreatesMappingAndSetsDynamicProviderForType() {
let component = MockComponent() let component = MockComponent()
state.addMethod(closure: .init { component }) state.addMethod(closure: .init { component })
XCTAssertTrue(state.get(MockComponent.self) is DynamicComponentProvider<MockComponent>?) XCTAssertTrue(state.provider(for: MockComponent.self) is DynamicComponentProvider<MockComponent>?)
XCTAssertTrue(state.get(MockComponent.self)?.getComponent() === component) XCTAssertTrue(state.provider(for: MockComponent.self)?.getComponent() === component)
} }
func testAddProviderCreatesMappingAndSetsProvider() { func testAddProviderCreatesMappingAndSetsProvider() {
let provider = ComponentSingletonProvider(type: MockComponent.self) let provider = ComponentSingletonProvider(type: MockComponent.self)
state.addProvider(type: MockComponent.self, provider: provider) state.addProvider(type: MockComponent.self, provider: provider)
XCTAssert(state.get(MockComponent.self) is ComponentSingletonProvider?) XCTAssert(state.provider(for: MockComponent.self) is ComponentSingletonProvider?)
XCTAssertNotNil(state.get(MockComponent.self)) XCTAssertNotNil(state.provider(for: MockComponent.self))
} }
class MockComponent: ComponentInitializable { class MockComponent: ComponentInitializable {
@ -313,7 +320,7 @@ class EntityStateTests: XCTestCase {
} }
required init() { required init() {
self.value = 0 value = 0
} }
} }
@ -336,7 +343,7 @@ class EntityStateMachineTests: XCTestCase {
func testEnterStateAddsStatesComponents() { func testEnterStateAddsStatesComponents() {
let state = EntityState() let state = EntityState()
let component = MockComponent() let component = MockComponent()
state.add(MockComponent.self).withInstance(component) state.addMapping(for: MockComponent.self).withInstance(component)
fsm.addState(name: "test", state: state) fsm.addState(name: "test", state: state)
fsm.changeState(name: "test") fsm.changeState(name: "test")
XCTAssertTrue(entity.get(component: MockComponent.self) === component) XCTAssertTrue(entity.get(component: MockComponent.self) === component)
@ -345,12 +352,12 @@ class EntityStateMachineTests: XCTestCase {
func testEnterSecondStateAddsSecondStatesComponents() { func testEnterSecondStateAddsSecondStatesComponents() {
let state1 = EntityState() let state1 = EntityState()
let component1 = MockComponent() let component1 = MockComponent()
state1.add(MockComponent.self).withInstance(component1) state1.addMapping(for: MockComponent.self).withInstance(component1)
fsm.addState(name: "test1", state: state1) fsm.addState(name: "test1", state: state1)
let state2 = EntityState() let state2 = EntityState()
let component2 = MockComponent2() let component2 = MockComponent2()
state2.add(MockComponent2.self).withInstance(component2) state2.addMapping(for: MockComponent2.self).withInstance(component2)
fsm.addState(name: "test2", state: state2) fsm.addState(name: "test2", state: state2)
fsm.changeState(name: "test2") fsm.changeState(name: "test2")
@ -360,13 +367,13 @@ class EntityStateMachineTests: XCTestCase {
func testEnterSecondStateRemovesFirstStatesComponents() { func testEnterSecondStateRemovesFirstStatesComponents() {
let state1 = EntityState() let state1 = EntityState()
let component1 = MockComponent() let component1 = MockComponent()
state1.add(MockComponent.self).withInstance(component1) state1.addMapping(for: MockComponent.self).withInstance(component1)
fsm.addState(name: "test1", state: state1) fsm.addState(name: "test1", state: state1)
fsm.changeState(name: "test1") fsm.changeState(name: "test1")
let state2 = EntityState() let state2 = EntityState()
let component2 = MockComponent2() let component2 = MockComponent2()
state2.add(MockComponent2.self).withInstance(component2) state2.addMapping(for: MockComponent2.self).withInstance(component2)
fsm.addState(name: "test2", state: state2) fsm.addState(name: "test2", state: state2)
fsm.changeState(name: "test2") fsm.changeState(name: "test2")
@ -387,14 +394,14 @@ class EntityStateMachineTests: XCTestCase {
nexus.delegate = delgate nexus.delegate = delgate
let state1 = EntityState() let state1 = EntityState()
let component1 = MockComponent() let component1 = MockComponent()
state1.add(MockComponent.self).withInstance(component1) state1.addMapping(for: MockComponent.self).withInstance(component1)
fsm.addState(name: "test1", state: state1) fsm.addState(name: "test1", state: state1)
fsm.changeState(name: "test1") fsm.changeState(name: "test1")
let state2 = EntityState() let state2 = EntityState()
let component2 = MockComponent2() let component2 = MockComponent2()
state2.add(MockComponent.self).withInstance(component1) state2.addMapping(for: MockComponent.self).withInstance(component1)
state2.add(MockComponent2.self).withInstance(component2) state2.addMapping(for: MockComponent2.self).withInstance(component2)
fsm.addState(name: "test2", state: state2) fsm.addState(name: "test2", state: state2)
fsm.changeState(name: "test2") fsm.changeState(name: "test2")
@ -404,15 +411,15 @@ class EntityStateMachineTests: XCTestCase {
func testEnterSecondStateRemovesDifferentComponentsOfSameType() { func testEnterSecondStateRemovesDifferentComponentsOfSameType() {
let state1 = EntityState() let state1 = EntityState()
let component1 = MockComponent() let component1 = MockComponent()
state1.add(MockComponent.self).withInstance(component1) state1.addMapping(for: MockComponent.self).withInstance(component1)
fsm.addState(name: "test1", state: state1) fsm.addState(name: "test1", state: state1)
fsm.changeState(name: "test1") fsm.changeState(name: "test1")
let state2 = EntityState() let state2 = EntityState()
let component3 = MockComponent() let component3 = MockComponent()
let component2 = MockComponent2() let component2 = MockComponent2()
state2.add(MockComponent.self).withInstance(component3) state2.addMapping(for: MockComponent.self).withInstance(component3)
state2.add(MockComponent2.self).withInstance(component2) state2.addMapping(for: MockComponent2.self).withInstance(component2)
fsm.addState(name: "test2", state: state2) fsm.addState(name: "test2", state: state2)
fsm.changeState(name: "test2") fsm.changeState(name: "test2")
@ -422,7 +429,7 @@ class EntityStateMachineTests: XCTestCase {
func testCreateStateAddsState() { func testCreateStateAddsState() {
let state = fsm.createState(name: "test") let state = fsm.createState(name: "test")
let component = MockComponent() let component = MockComponent()
state.add(MockComponent.self).withInstance(component) state.addMapping(for: MockComponent.self).withInstance(component)
fsm.changeState(name: "test") fsm.changeState(name: "test")
XCTAssertTrue(entity.get(component: MockComponent.self) === component) XCTAssertTrue(entity.get(component: MockComponent.self) === component)
} }
@ -430,7 +437,7 @@ class EntityStateMachineTests: XCTestCase {
func testCreateStateDoesNotChangeState() { func testCreateStateDoesNotChangeState() {
let state = fsm.createState(name: "test") let state = fsm.createState(name: "test")
let component = MockComponent() let component = MockComponent()
state.add(MockComponent.self).withInstance(component) state.addMapping(for: MockComponent.self).withInstance(component)
XCTAssertNil(entity.get(component: MockComponent.self)) XCTAssertNil(entity.get(component: MockComponent.self))
} }
@ -438,8 +445,8 @@ class EntityStateMachineTests: XCTestCase {
let state = fsm.createState(name: "test") let state = fsm.createState(name: "test")
let component1 = MockComponent() let component1 = MockComponent()
let component2 = MockComponent2() let component2 = MockComponent2()
state.add(MockComponent.self).withInstance(component1) state.addMapping(for: MockComponent.self).withInstance(component1)
state.add(MockComponent2.self).withInstance(component2) state.addMapping(for: MockComponent2.self).withInstance(component2)
let name = "test" let name = "test"
fsm.changeState(name: name) fsm.changeState(name: name)
XCTAssertTrue(entity.get(component: MockComponent.self) === component1) XCTAssertTrue(entity.get(component: MockComponent.self) === component1)
@ -478,7 +485,7 @@ class EntityStateMachineTests: XCTestCase {
} }
required init() { required init() {
self.value = 0 value = 0
} }
} }
@ -500,21 +507,21 @@ class EntityStateMachineTests: XCTestCase {
class StateComponentMappingTests: XCTestCase { class StateComponentMappingTests: XCTestCase {
func testAddReturnsSameMappingForSameComponentType() { func testAddReturnsSameMappingForSameComponentType() {
let state = EntityState() let state = EntityState()
let mapping = state.add(MockComponent.self) let mapping = state.addMapping(for: MockComponent.self)
XCTAssertFalse(mapping === mapping.add(MockComponent.self)) XCTAssertFalse(mapping === mapping.add(MockComponent.self))
} }
func testAddReturnsSameMappingForDifferentComponentTypes() { func testAddReturnsSameMappingForDifferentComponentTypes() {
let state = EntityState() let state = EntityState()
let mapping = state.add(MockComponent.self) let mapping = state.addMapping(for: MockComponent.self)
XCTAssertFalse(mapping === mapping.add(MockComponent2.self)) XCTAssertFalse(mapping === mapping.add(MockComponent2.self))
} }
func testAddAddsProviderToState() { func testAddAddsProviderToState() {
let state = EntityState() let state = EntityState()
let mapping = state.add(MockComponent.self) let mapping = state.addMapping(for: MockComponent.self)
mapping.add(MockComponent2.self) mapping.add(MockComponent2.self)
XCTAssertTrue(state.has(MockComponent.self)) XCTAssertTrue(state.hasProvider(for: MockComponent.self))
} }
class MockComponent: ComponentInitializable { class MockComponent: ComponentInitializable {