src/state-manager.mjs
import { Logger } from './vendor/logger.min.mjs';
class StateManager {
/**
* An object containing all the registered states.
*
* @private
* @type {Object<string, State>}
*/
states = {};
/**
* The current state of the state machine.
*
* @private
* @type {State|null}
*/
currentState = null;
/**
* The version of the module.
*/
version = "VERSION_REPLACE_ME";
/**
* Creates a new state machine manager.
*
* @param {Object<State>} pStates - Array of state objects to register.
*/
constructor(pStates) {
/** The logger module this module uses to log errors / logs.
* @private
* @type {Object}
*/
this.logger = new Logger();
this.logger.registerType('StateManager-Module', '#ff6600');
// Loop passed states and register them. {'name': foo, 'state': state}
if (typeof (pStates) === 'object' && !Array.isArray(pStates)) {
for (const state in pStates) {
this.registerState();
}
}
}
/**
* Registers a new state with the state machine.
*
* @param {string} pName - The name of the state.
* @param {State} pState - The state object.
*/
registerState(pName, pState) {
if (typeof (pName) === 'string') {
if (pState instanceof State) {
pState.name = pName;
this.states[pName] = pState;
pState.manager = this;
} else {
this.logger.prefix('StateManager-Module').error(`${pState} is not a valid state.`);
}
} else {
this.logger.prefix('StateManager-Module').error('Invalid name for state.');
}
}
/**
* Sets the current state of the state machine.
*
* @param {string} pName - The name of the state to set.
* @param {*} pRest - The arguments that were passed when setting this state.
*/
setState(pName, ...pRest) {
const state = this.states[pName];
if (!state) {
this.logger.prefix('StateManager-Module').warn(`State ${pName} not found.`);
return;
}
if (this.currentState) {
this.currentState.exit();
}
this.currentState = state;
this.currentState.enter(...pRest);
}
/**
* Gets the current state.
*/
getCurrentState() {
return this.currentState ? this.currentState.name : null;
}
/**
* Updates the current state of the state machine.
*
* @param {number} pDelta - The delta time since the last update in seconds.
*/
update(pDelta) {
if (this.currentState) {
this.currentState.update(pDelta);
}
}
}
/**
* A class representing a state.
*/
class State {
/**
* Called when entering the state.
*/
enter() { }
/**
* Called when executing the state.
*
* @param {number} pDelta - The delta time since the last update in seconds.
*/
update(pDelta) { }
/**
* Called when exiting the state.
*/
exit() { }
}
export { StateManager, State };