67 lines
2.0 KiB
C++
67 lines
2.0 KiB
C++
|
#ifndef CREATURELIB_SCRIPTAGGREGATOR_HPP
|
||
|
#define CREATURELIB_SCRIPTAGGREGATOR_HPP
|
||
|
|
||
|
#include <any>
|
||
|
#include <queue>
|
||
|
#include "Script.hpp"
|
||
|
#include "ScriptSet.hpp"
|
||
|
|
||
|
namespace CreatureLib::Battling{
|
||
|
class ScriptAggregator{
|
||
|
std::queue<std::any> _queue;
|
||
|
bool _isSetSet = false;
|
||
|
std::__detail::_Node_iterator<std::pair<const std::string, Script *>, false, true> _setIterator;
|
||
|
std::__detail::_Node_iterator<std::pair<const std::string, Script *>, false, true> _setEnd;
|
||
|
public:
|
||
|
ScriptAggregator() = default;
|
||
|
|
||
|
void Add(Script* script){
|
||
|
_queue.push(script);
|
||
|
}
|
||
|
|
||
|
void Add(ScriptSet* scriptSet){
|
||
|
_queue.push(scriptSet);
|
||
|
}
|
||
|
|
||
|
bool HasNext(){
|
||
|
return !_queue.empty() || _isSetSet;
|
||
|
}
|
||
|
|
||
|
Script* GetNext(){
|
||
|
// We can probably do this in a cleaner version once C++ 20 drops with Coroutine support.
|
||
|
if (_isSetSet){
|
||
|
if (_setIterator == _setEnd){
|
||
|
_isSetSet = false;
|
||
|
return GetNext();
|
||
|
}
|
||
|
auto s = _setIterator->second;
|
||
|
_setIterator.operator++();
|
||
|
if (_setIterator == _setEnd){
|
||
|
_isSetSet = false;
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
if (_queue.empty())
|
||
|
return nullptr;
|
||
|
auto next = _queue.front();
|
||
|
_queue.pop();
|
||
|
if (next.type() == typeid(Script*)){
|
||
|
return std::any_cast<Script*>(next);
|
||
|
}
|
||
|
else{
|
||
|
auto set = std::any_cast<ScriptSet*>(next);
|
||
|
if (set->Count() == 0)
|
||
|
return GetNext();
|
||
|
auto it = set->GetIterator();
|
||
|
_setIterator = it->begin();
|
||
|
_setEnd = it->end();
|
||
|
_isSetSet = true;
|
||
|
return GetNext();
|
||
|
}
|
||
|
throw NotReachableException();
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
#endif //CREATURELIB_SCRIPTAGGREGATOR_HPP
|