#include "RUStateMachine.h" #include "RUState.h" #include "RUMetaState.h" #include "RUStateTransition.h" NS_RU_BEGIN StateMachine* StateMachine::create(const std::string& stateMachineName, const std::string& initStateName, const std::unordered_map& states, const std::vector& transitions, const std::map& params) { StateMachine * ret = new (std::nothrow) StateMachine(); ret->autorelease(); ret->retain(); ret->_name = stateMachineName; ret->_initStateName = initStateName; ret->_states = states; ret->_transitions = transitions; ret->_parameters = params; return ret; } void StateMachine::runMachine(const std::function& runningCb) { if(_running){ FSMLOG("%s : 已处于运行状态,直接返回", (_indent+_name).c_str()); CCASSERT(false, "已处于运行状态"); if(runningCb) { runningCb(); } return; } FSMLOG("%s : 开始运行", (_indent+_name).c_str()); _running = true; if(_runningStateName.empty() == true){ //状态机未提前设置好运行状态(有可能是切入到分层状态机) setRunningStateName(_initStateName); State* runningState = getState(_runningStateName); auto execHandleEventCb = [=](void){ handleIfStateChanged(runningCb); }; runningState->entry(execHandleEventCb); }else{ //已提前设置好运行状态(存档方式指定) State* runningState = getState(_runningStateName); runningState->idle(runningCb); } } void StateMachine::stopMachine(const std::function& stoppedCb) { auto exitCb = [=](void){ _runningStateName = ""; _running = false; if (stoppedCb) { stoppedCb(); } }; State* state = getState(_runningStateName); state->exit(exitCb); _cntAutoTrans2Hdl = 0; } void StateMachine::stopMachineImmediately() { State* state = getState(_runningStateName); if (state->getStateType() == kStateType::META) { MetaState* metaState = dynamic_cast(state); metaState->stopMachineImmediately(); } _runningStateName = ""; _historyRunningStateName = ""; _running = false; _cntAutoTrans2Hdl = 0; } void StateMachine::forceToStateNames(const std::vector& stateNames, const std::function& forcedCb) { CCASSERT(_running == true, "如果当前不是运行运行态,不应该调用这个函数"); stopMachineImmediately(); setRunningStateNames(stateNames); runMachine(forcedCb); } std::vector StateMachine::getInitStateNames() { std::vector ret; ret.push_back(_initStateName); State* initState = getState(_initStateName); if (initState->getStateType() == kStateType::META) { MetaState* metaState = dynamic_cast(initState); std::vector metaInitStateNames = metaState->getInitStateNames(); ret.insert(ret.end(), metaInitStateNames.begin(),metaInitStateNames.end()); } return ret; } void StateMachine::setRunningStateName(const std::string& stateName) { CCASSERT(_states.find(stateName) != _states.end(), "没有这个状态"); FSMLOG("%s : 设置状态->\"%s\"", (_indent+_name).c_str(), stateName.c_str()); _runningStateName = stateName; _historyRunningStateName = _runningStateName; } void StateMachine::setRunningStateNames(std::vector stateNames) { CCASSERT(stateNames.size() > 0 , "传个空的?"); std::string stateName = stateNames.at(0); setRunningStateName(stateName); stateNames.erase(stateNames.begin()); if (stateNames.size() > 0) { State* runningState = getState(stateName); CCASSERT(runningState->getStateType() == kStateType::META, "wft??"); MetaState* metaState = dynamic_cast(runningState); metaState->setRunningStateNames(stateNames); } } std::vector StateMachine::getRunningStateNames() { std::vector runningStateNames; if (_running) { runningStateNames.push_back(_runningStateName); State* runningState = getState(_runningStateName); if (runningState->getStateType() == kStateType::META) { MetaState* metaState = dynamic_cast(runningState); std::vector metaRunningStateNames = metaState->getRunningStateNames(); runningStateNames.insert(runningStateNames.end(), metaRunningStateNames.begin(),metaRunningStateNames.end()); } } return runningStateNames; } std::vector StateMachine::getHistoryRunningStateNames() { if(_running){ return getRunningStateNames(); }else{ std::vector historyRunningStateNames; std::string historyRunningStateName; if (_historyRunningStateName.empty()) { historyRunningStateName = _initStateName; }else{ historyRunningStateName = _historyRunningStateName; } historyRunningStateNames.push_back(historyRunningStateName); State* historyRunningState = getState(historyRunningStateName); if (historyRunningState->getStateType() == kStateType::META) { MetaState* metaState = dynamic_cast(historyRunningState); std::vector metaHistoryRunningStateNames = metaState->getHistoryRunningStateNames(); historyRunningStateNames.insert(historyRunningStateNames.end(), metaHistoryRunningStateNames.begin(),metaHistoryRunningStateNames.end()); } return historyRunningStateNames; } } bool StateMachine::canResponseEvent(const std::string& eventName) { bool canResponse = false; // 当前运行状态是否是MetaState(分层状态,状态本身就是个状态机),如果是,该分层状态能否响应该事件 State* runningState = getState(_runningStateName); kStateType stateType = runningState->getStateType(); if(stateType == kStateType::META){ MetaState* metaState = dynamic_cast(runningState) ; canResponse = metaState->canResponseEvent(eventName); } if (canResponse == false) { const FsmTransition* pTransition = _getFsmTransition(_runningStateName, eventName); if (pTransition) { canResponse = true; } } return canResponse; } void StateMachine::handleEvent(const std::string& eventName, std::function handleEventCb) { handleEvent(eventName,{},handleEventCb); } void StateMachine::handleEvent(const std::string& eventName, const std::map& eventParams, std::function handleEventCb) { // 不能响应事件的话直接返回 if (_running == false || canResponseEvent(eventName) == false) { FSMLOG("%s : 不能响应事件:\"%s\",状态机是否运行:\"%s\",当前状态:\"%s\"]", (_indent+_name).c_str(), eventName.c_str(), cocos2d::Value(_running).asString().c_str(), _getRunningStateStr4Debug().c_str()); if (handleEventCb) { handleEventCb(); } return; } FSMLOG("%s : 响应事件:\"%s\",状态机是否运行:\"%s\",当前状态:\"%s\"]", (_indent+_name).c_str(), eventName.c_str(), cocos2d::Value(_running).asString().c_str(), _getRunningStateStr4Debug().c_str()); // 当前运行状态如果为分层状态,优先分层状态处理该事件。 State* runningState = getState(_runningStateName); kStateType stateType = runningState->getStateType(); if(stateType == kStateType::META){ MetaState* metaState = dynamic_cast(runningState); if(metaState->canResponseEvent(eventName) == true){ metaState->handleEvent(eventName, eventParams, handleEventCb); return; } } // 有新的事件,所以去掉自动转移 _cntAutoTrans2Hdl = 0; if (_transitionDoing != nullptr) { _transitionDoing->interrupt(); } const FsmTransition* pTransition = _getFsmTransition(_runningStateName, eventName); if (pTransition) { _transitionDoing = StateTransition::create(this, pTransition, [=](StateTransition* trans, std::function cb, bool bInterrupted) { if (!bInterrupted) { handleIfStateChanged(cb); } else if (cb != nullptr) { cb(); } trans->release(); // 防止是被打断的情况 if (trans == _transitionDoing) { _transitionDoing = nullptr; } }); _transitionDoing->setEvent(eventName, eventParams, handleEventCb); _transitionDoing->execute(); } } void StateMachine::handleIfStateChanged(std::function handleEventCb) { const FsmTransition* pTransition = _getFsmTransition(_runningStateName, AUTO_EVENT_NAME); if (pTransition) { /// 存在自动转换事件 /// 自动事件和分发事件都不应该有事件参数,因为这个是状态机本身的行为,不是外部传递的 if (_runningStateName == DISPATCH_STATE_NAME) { // 虚拟分发的时候先进行分发,后回调 handleEvent(AUTO_EVENT_NAME, {}, handleEventCb); } else { _cntAutoTrans2Hdl += 1; if (handleEventCb) { handleEventCb(); } if (_cntAutoTrans2Hdl > 0) { _cntAutoTrans2Hdl -= 1; handleEvent(AUTO_EVENT_NAME, {}, nullptr); } } }else{ if (handleEventCb) { handleEventCb(); } } } const std::vector& StateMachine::getIdleActInfosByStateFullPath(const std::vector& stateNames) { CCASSERT(stateNames.size() > 0, "stateNames大小不能为零"); State* state = getState(stateNames.at(0)); if(stateNames.size() == 1){ return state->getIdleActInfos(); }else{ CCASSERT(state->getStateType() == kStateType::META, "当前状态机一定是分层状态机,请检查"); MetaState* metaState = dynamic_cast(state) ; std::vector states; states.insert(states.begin(), stateNames.begin() + 1, stateNames.end()); return metaState->getIdleActInfosByStateFullPath(states); } } State* StateMachine::getState(const std::string& stateName) { State* ret = nullptr; auto iter = _states.find(stateName); if (iter != _states.end()) { ret = iter->second; } return ret; } bool StateMachine::chekcStateNamesValidity(std::vector stateNames) { bool ret = true; if (stateNames.empty()) { ret = false; } else { State* state = getState(stateNames.at(0)); if (state) { if (state->getStateType() == kStateType::META) { MetaState* metaState = dynamic_cast(state); stateNames.erase(stateNames.begin()); ret = metaState->chekcStateNamesValidity(stateNames); } } else { ret = false; } } return ret; } const FsmTransition* StateMachine::_getFsmTransition(const std::string& formState, const std::string& eventName) { const FsmTransition* pTransition = nullptr; for (const FsmTransition& transition : _transitions) { if (transition.fromState == formState && isEventNameMatched(eventName, transition.eventName)) { if (transition.conditions.size() > 0) { for (auto conds : transition.conditions) { if (checkConditonGroup(conds)) { pTransition = &transition; break; } } } else { pTransition = &transition; } } if (pTransition) { break; } } return pTransition; } bool StateMachine::isEventNameMatched(const std::string& name, const std::string& pattern) { /// eventName 支持字符串 "*" 匹配:全匹配、前半部分匹配、后半部分匹配;不支持中间部分匹配 /// * 最多只有一个 if (name == pattern) { return true; } if (name == AUTO_EVENT_NAME) { // 自动转移事件不参与匹配 return false; } auto pos = pattern.find("*"); if (pos == 0) { if (pattern.size() == 1) { // 全匹配 return true; } // 前半部分匹配 auto suffix = pattern.substr(1); auto pos1 = name.find(suffix); if ((pos1 + suffix.size()) == name.size()) { return true; } return false; } else if (pos == (pattern.size()-1)) { // 后半部分匹配 auto suffix = pattern.substr(0, pattern.size()-1); if (name.find(suffix) == 0) { return true; } return false; } return false; } template bool checkParameter(T v1, std::string op, T v2) { if (op == "=") { return v1 == v2; } else if (op == "!=") { return v1 != v2; } else if (op == "<") { return v1 < v2; } else if (op == ">") { return v1 > v2; } else if (op == "<=") { return v1 < v2; } else if (op == ">=") { return v1 > v2; } return false; } bool StateMachine::checkConditonGroup(const std::list& conditions) { bool bRet = true; for (auto& cond : conditions) { auto it = _parameters.find(cond.name); if (it != _parameters.end()) { switch (it->second.type) { case PARAM_T_INT: bRet &= checkParameter(it->second.iv, cond.op, cocos2d::Value(cond.v).asInt()); break; case PARAM_T_FLOAT: bRet &= checkParameter(it->second.fv, cond.op, cocos2d::Value(cond.v).asFloat()); break; case PARAM_T_STRING: bRet &= checkParameter(it->second.sv, cond.op, cocos2d::Value(cond.v).asString()); break; case PARAM_T_TRIGGER: CCASSERT(false, "[fsm] trigger 还没有实现"); break; } } } return bRet; } void StateMachine::setParam(const std::string& name, const std::string& v) { auto it = _parameters.find(name); if (it != _parameters.end()) { switch (it->second.type) { case PARAM_T_INT: it->second.iv = cocos2d::Value(v).asInt(); break; case PARAM_T_FLOAT: it->second.fv = cocos2d::Value(v).asFloat(); break; case PARAM_T_STRING: it->second.sv = cocos2d::Value(v).asString(); break; case PARAM_T_TRIGGER: CCASSERT(false, "[fsm] trigger 还没有实现"); break; } } // 遍历查找子子状态机 for (auto st : _states) { auto stMeta = dynamic_cast(st.second); if (stMeta) { stMeta->setParam(name, v); } } } void StateMachine::debugInfo() { CCLOG("状态机信息: %s", _name.c_str()); CCLOG("{"); CCLOG(" \"initStateName\":\"%s\",",_initStateName.c_str()); CCLOG(" \"states\":{"); for(auto state : _states) { state.second->debugInfo(); } CCLOG(" },"); auto getActionsInfo = [=](std::vector actinfos){ std::string actions_str = "["; for(StateActInfo action : actinfos){ actions_str = actions_str + "{\"type\":\""+ action.actType + "\",\"params\":{"; for(auto paramIter : action.actParams){ actions_str = actions_str + "\""+ paramIter.first + "\":\"" + paramIter.second + "\","; } actions_str = actions_str + "}"; } actions_str = actions_str + "]"; return actions_str; }; auto getTransitionInfo = [=](FsmTransition transition){ std::string transition_str; transition_str = transition_str + " {"; transition_str = transition_str + "\n \"fromState\":\"" + transition.fromState + "\","; transition_str = transition_str + "\n \"toState\":\"" + transition.toState+ "\","; transition_str = transition_str + "\n \"eventName\":\"" + transition.eventName+ "\","; transition_str = transition_str + "\n \"before_switch_actions\":" + getActionsInfo(transition.beforeSwitchActInfos); transition_str = transition_str + ",\n \"after_switch_actions\":" + getActionsInfo(transition.afterSwitchActInfos); transition_str = transition_str + "\n },"; return transition_str; }; CCLOG(" \"transitions\":["); for(FsmTransition transition : _transitions){ CCLOG("%s",getTransitionInfo(transition).c_str()); } CCLOG(" ],"); CCLOG("}"); //打印子状态机信息 for(auto state : _states){ if (state.second->getStateType() == kStateType::META) { MetaState* metaState = dynamic_cast(state.second); metaState->debugStateMachineInfo(); } } } void StateMachine::setName(const std::string& name) { _name = name; } void StateMachine::setIndent4Dbg(const std::string& indent) { _indent = indent; std::vector runnintStates = getRunningStateNames(); std::string str = " " + indent; for (auto& st : _states) { st.second->setIndent4Dbg(" " + indent); } } void StateMachine::runMachine4Dbg() { _running = true; if(_runningStateName.empty() == true){ //状态机未提前设置好运行状态(有可能是切入到分层状态机) if(_initStateName.empty()){ CCASSERT(false, "fff"); } setRunningStateName(_initStateName); } } void StateMachine::handleEvent4Dbg(const std::string& eventName) { // 不能响应事件的话直接返回 if (canResponseEvent(eventName) == false) { return; } State* runningState = getState(_runningStateName); kStateType stateType = runningState->getStateType(); if(stateType == kStateType::META){ MetaState* metaState = dynamic_cast(runningState); if(metaState->canResponseEvent(eventName) == true){ metaState->handleEvent4Dbg(eventName); return; } } const FsmTransition* pTransition = _getFsmTransition(_runningStateName, eventName); setRunningStateName(pTransition->toState); State* toState = getState(pTransition->toState); if(toState->getStateType() == kStateType::META){ MetaState* toMetaState = dynamic_cast(toState); toMetaState->runMachine4Dbg(); } } std::string StateMachine::_getRunningStateStr4Debug() { std::vector runnintStates = getRunningStateNames(); std::string str; for (int i = 0; i < runnintStates.size(); i++) { if (i == runnintStates.size() - 1) { str = str + runnintStates[i]; }else{ str = str + runnintStates[i] + "#"; } } return str; } NS_RU_END