1 /** 2 * This is a state machine for an entity. The state machine manages a set of states, 3 * each of which has a set of component providers. When the state machine changes the state, it removes 4 * components associated with the previous state and adds components associated with the new state. 5 */ 6 module ashd.fsm.entityStateMachine; 7 8 9 import ashd.core.entity : Entity; 10 import ashd.fsm.entityState : EntityState; 11 import ashd.fsm.IComponentProvider: IComponentProvider; 12 import ashd.fsm.ISystemProvider : ISystemProvider; 13 14 15 public class EntityStateMachine 16 { 17 private 18 { 19 Entity mEntity; // The entity whose state machine this is 20 EntityState[string] mStates; // available states 21 EntityState mCurrentState; // The current state of the state machine. 22 } 23 24 /** 25 * Constructor. Creates an EntityStateMachine. 26 */ 27 public this( Entity entity_a ) 28 { 29 mEntity = entity_a; 30 } 31 32 /** 33 * Add a state to this state machine. 34 * 35 * @param name The name of this state - used to identify it later in the changeState method call. 36 * @param state The state. 37 * @return This state machine, so methods can be chained. 38 */ 39 public EntityStateMachine addState( string name_a, EntityState state_a ) 40 { 41 mStates[name_a] = state_a; 42 return this; 43 } 44 45 /** 46 * Create a new state in this state machine. 47 * 48 * @param name The name of the new state - used to identify it later in the changeState method call. 49 * @return The new EntityState object that is the state. This will need to be configured with 50 * the appropriate component providers. 51 */ 52 public EntityState createState( string name_a ) 53 { 54 EntityState state = new EntityState(); 55 mStates[name_a] = state; 56 return state; 57 } 58 59 /** 60 * Change to a new state. The components from the old state will be removed and the components 61 * for the new state will be added. 62 * 63 * @param name The name of the state to change to. 64 */ 65 public void changeState( string name_a ) 66 { 67 if ( name_a !in mStates ) 68 { 69 throw new Exception( "State '" ~ name_a ~ "' does not exist." ); 70 } 71 72 EntityState newState = mStates[name_a]; 73 if ( newState == mCurrentState ) 74 { 75 newState = null; 76 return; 77 } 78 79 IComponentProvider[ClassInfo] toAdd = newState.providers(); 80 81 if ( mCurrentState ) 82 { 83 foreach ( ClassInfo key, IComponentProvider t; mCurrentState.providers() ) 84 { 85 IComponentProvider other; 86 if ( key in toAdd ) 87 other = toAdd[key]; 88 89 if ( other && other.identifier == mCurrentState.providers[key].identifier ) 90 { 91 toAdd.remove(key); 92 } 93 else 94 { 95 mEntity.remove( key ); 96 } 97 } 98 } 99 100 foreach ( ClassInfo key, IComponentProvider provider; toAdd ) 101 { 102 mEntity.add( provider.getComponent( key ), key ); 103 } 104 mCurrentState = newState; 105 } 106 }