#ifndef STATE_MACHINE_HPP #define STATE_MACHINE_HPP #include #include #include #include #include "state_factory.hpp" using json = nlohmann::json; template class StateMachine { public: StateMachine(T &owner, const StateFactory &factory) : owner(owner), factory(factory) {}; void ChangeState(const std::string &id) { auto new_state = factory.Get(id); if (!new_state) return; if (strict_transition && current_state) { bool allowed = false; for (const auto &transition : current_state->GetTransitions()) { if (transition.target_state == id && (!transition.condition || transition.condition(owner))) { allowed = true; break; } } if (!allowed) return; } if (current_state) { current_state->OnExit(owner); history.push_back(current_state->Id()); } current_state = std::move(new_state); current_state->OnEnter(owner); }; void SetState(const std::string &id) { auto new_state = factory.Get(id); if (!new_state) return; if (current_state) current_state->OnExit(owner); current_state = std::move(new_state); current_state->OnEnter(owner); } void RevertState() { if (history.empty()) return; std::string last = history.back(); history.pop_back(); ChangeState(last); } void Update() { if (!current_state) return; for (const auto &transition : current_state->GetTransitions()) if (auto_transition && transition.condition(owner)) { ChangeState(transition.target_state); return; } current_state->OnUpdate(owner); } const std::vector &GetHistory() const { return history; } void SetHistory(const std::vector history) { this->history = history; } void ReplayHistory() { for (const std::string &stateId : history) ChangeState(stateId); } const std::string GetCurrentStateId() const { static const std::string nullState = "null"; return current_state ? current_state->Id() : nullState; } void SetStrictTransitions(bool enabled) { this->strict_transition = enabled; } bool GetStrictTransitions() const { return strict_transition; } void SetAutoTransitions(bool enabled) { this->auto_transition = enabled; } bool GetAutoTransitions() const { return auto_transition; } private: T &owner; const StateFactory &factory; std::shared_ptr> current_state; bool strict_transition = false; bool auto_transition = false; std::vector history; }; #endif // STATE_MACHINE_HPP