Cleanup of ScriptAggregator class.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2020-04-23 23:23:58 +02:00
parent 3a11bba913
commit dd668f2b1c
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
11 changed files with 89 additions and 75 deletions

View File

@ -85,7 +85,9 @@ bool Battle::CreatureInField(const Creature* creature) const {
void Battle::ForceRecall(uint8_t side, uint8_t index) { _sides[side]->SetCreature(nullptr, index); } void Battle::ForceRecall(uint8_t side, uint8_t index) { _sides[side]->SetCreature(nullptr, index); }
void Battle::GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) { scripts.Append(&_volatile); } void Battle::GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) {
scripts.Append(ScriptWrapper::FromSet(&_volatile));
}
void Battle::SwitchCreature(uint8_t sideIndex, uint8_t index, Creature* c) { void Battle::SwitchCreature(uint8_t sideIndex, uint8_t index, Creature* c) {
auto side = this->_sides[sideIndex]; auto side = this->_sides[sideIndex];

View File

@ -70,7 +70,7 @@ bool BattleSide::CreatureOnSide(const Creature* creature) const {
Creature* BattleSide::GetCreature(uint8_t index) const { return _creatures[index]; } Creature* BattleSide::GetCreature(uint8_t index) const { return _creatures[index]; }
void BattleSide::GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) { void BattleSide::GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) {
scripts.Append(&_volatile); scripts.Append(ScriptWrapper::FromSet(&_volatile));
_battle->GetActiveScripts(scripts); _battle->GetActiveScripts(scripts);
} }
uint8_t BattleSide::GetRandomCreatureIndex() { uint8_t BattleSide::GetRandomCreatureIndex() {

View File

@ -167,9 +167,9 @@ bool Battling::Creature::HasType(uint8_t type) const noexcept {
} }
void Battling::Creature::GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) { void Battling::Creature::GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) {
scripts.Append(&_activeTalent); scripts.Append(ScriptWrapper::FromScript(&_activeTalent));
scripts.Append(&_status); scripts.Append(ScriptWrapper::FromScript(&_status));
scripts.Append(&_volatile); scripts.Append(ScriptWrapper::FromSet(&_volatile));
if (_side != nullptr) { if (_side != nullptr) {
_side->GetActiveScripts(scripts); _side->GetActiveScripts(scripts);
} }

View File

@ -87,7 +87,7 @@ namespace CreatureLib::Battling {
protected: protected:
void GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) override { void GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) override {
scripts.Append(&_script); scripts.Append(ScriptWrapper::FromScript(&_script));
_user->GetActiveScripts(scripts); _user->GetActiveScripts(scripts);
} }
}; };

View File

@ -11,54 +11,54 @@ using namespace Arbutils::Collections;
namespace CreatureLib::Battling { namespace CreatureLib::Battling {
class ScriptAggregator { class ScriptAggregator {
List<ScriptWrapper> _scripts; const ScriptWrapper* _scripts;
size_t _size;
size_t _index = 0; size_t _index = 0;
bool _isSetSet = false;
const List<Script*>* _setScripts = nullptr;
size_t _setIndex = 0; size_t _setIndex = 0;
public: public:
ScriptAggregator(){}; ScriptAggregator(){};
explicit ScriptAggregator(const List<ScriptWrapper>& scripts) : _scripts(scripts){}; explicit ScriptAggregator(const List<ScriptWrapper>& scripts)
: _scripts(scripts.RawData()), _size(scripts.Count()){};
void Reset() { inline void Reset() {
_index = 0; _index = 0;
_isSetSet = false;
_setIndex = 0; _setIndex = 0;
} }
bool HasNext() { return _index < _scripts.Count() || (_isSetSet && _setIndex < _setScripts->Count()); } inline bool HasNext() { return _index < _size; }
Script* GetNextNotNull() {
while (HasNext()) {
auto s = GetNext();
if (s != nullptr) {
return s;
}
}
return nullptr;
}
Script* GetNext() { Script* GetNext() {
// We can probably do this in a cleaner version once C++ 20 drops with Coroutine support. auto& current = _scripts[_index];
if (_isSetSet) { if (!current.IsSet()) {
if (_setIndex >= _setScripts->Count()) { _index++;
_isSetSet = false; auto s = current.GetScript();
return GetNext(); if (s == nullptr)
} return nullptr;
auto s = _setScripts->At(_setIndex); return *s;
_setIndex++;
if (_setIndex >= _setScripts->Count()) {
_isSetSet = false;
}
return s;
}
if (_index >= _scripts.Count())
return nullptr;
auto& next = _scripts[_index];
_index++;
if (!next.IsSet()) {
auto scriptPtr = next.GetScript();
if (scriptPtr == nullptr)
return GetNext();
return *scriptPtr;
} else { } else {
auto set = next.GetScriptSet(); auto& set = *current.GetScriptSet()->GetIterator();
if (set->Count() == 0) auto count = set.Count();
return GetNext(); if (_setIndex >= count) {
_setScripts = set->GetIterator(); _index++;
_isSetSet = true; _setIndex = 0;
_setIndex = 0; return nullptr;
return GetNext(); }
auto v = set[_setIndex++];
if (_setIndex >= count) {
_index++;
_setIndex = 0;
}
return v;
} }
} }
}; };

View File

@ -66,7 +66,7 @@ namespace CreatureLib::Battling {
bool Has(uint32_t keyHash) const { return _lookup.Has(keyHash); } bool Has(uint32_t keyHash) const { return _lookup.Has(keyHash); }
size_t Count() const { return _scripts.Count(); } inline size_t Count() const { return _scripts.Count(); }
const Arbutils::Collections::List<Script*>* GetIterator() const { return &_scripts; } const Arbutils::Collections::List<Script*>* GetIterator() const { return &_scripts; }
}; };

View File

@ -8,7 +8,8 @@
namespace CreatureLib::Battling { namespace CreatureLib::Battling {
class ScriptSource { class ScriptSource {
bool _areScriptsInitialized = false; bool _areScriptsInitialized = false;
ScriptAggregator _scripts; List<ScriptWrapper> _scripts;
ScriptAggregator _scriptsIterator;
protected: protected:
virtual void GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) = 0; virtual void GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) = 0;
@ -17,12 +18,11 @@ namespace CreatureLib::Battling {
public: public:
const ScriptAggregator& GetScriptIterator() { const ScriptAggregator& GetScriptIterator() {
if (!_areScriptsInitialized) { if (!_areScriptsInitialized) {
List<ScriptWrapper> scripts; GetActiveScripts(_scripts);
GetActiveScripts(scripts); _scriptsIterator = ScriptAggregator(_scripts);
_scripts = ScriptAggregator(scripts);
_areScriptsInitialized = true; _areScriptsInitialized = true;
} }
return _scripts; return _scriptsIterator;
} }
}; };
} }

View File

@ -7,20 +7,24 @@
namespace CreatureLib::Battling { namespace CreatureLib::Battling {
class ScriptWrapper { class ScriptWrapper {
union {
Script** _script;
ScriptSet* _scriptSet;
};
bool _isSet; bool _isSet;
union {
Script* const* _script;
const ScriptSet* _scriptSet;
};
ScriptWrapper(Script** s, bool isSet) : _isSet(isSet), _script(s){};
ScriptWrapper(ScriptSet* s, bool isSet) : _isSet(isSet), _scriptSet(s){};
public: public:
ScriptWrapper(Script** s) : _script(s), _isSet(false) {} static inline ScriptWrapper FromScript(Script** s) { return ScriptWrapper(s, false); }
ScriptWrapper(ScriptSet* s) : _scriptSet(s), _isSet(true) {} static inline ScriptWrapper FromSet(ScriptSet* s) { return ScriptWrapper(s, true); }
bool IsSet() const { return _isSet; } bool IsSet() const { return _isSet; }
Script** GetScript() const { return _script; } inline Script* const* GetScript() const { return _script; }
ScriptSet* GetScriptSet() const { return _scriptSet; } inline const ScriptSet* GetScriptSet() const { return _scriptSet; }
}; };
} }

View File

@ -56,7 +56,7 @@ namespace CreatureLib::Battling {
protected: protected:
void GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) override { void GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) override {
scripts.Append(&_attackScript); scripts.Append(ScriptWrapper::FromScript(&_attackScript));
GetUser()->GetActiveScripts(scripts); GetUser()->GetActiveScripts(scripts);
} }
}; };

View File

@ -21,7 +21,7 @@ public:
TEST_CASE("Script Aggregator properly iterates containing script.", "[Battling, Scripting]") { TEST_CASE("Script Aggregator properly iterates containing script.", "[Battling, Scripting]") {
Script* script = new TestScript("test"); Script* script = new TestScript("test");
auto ran = 0; auto ran = 0;
auto vec = Arbutils::Collections::List<ScriptWrapper>{&script}; auto vec = Arbutils::Collections::List<ScriptWrapper>{ScriptWrapper::FromScript(&script)};
auto aggr = ScriptAggregator(vec); auto aggr = ScriptAggregator(vec);
while (aggr.HasNext()) { while (aggr.HasNext()) {
auto next = aggr.GetNext(); auto next = aggr.GetNext();
@ -37,7 +37,8 @@ TEST_CASE("Script Aggregator properly iterates multiple scripts.", "[Battling, S
Script* script2 = new TestScript("test2"); Script* script2 = new TestScript("test2");
Script* script3 = new TestScript("test3"); Script* script3 = new TestScript("test3");
auto ran = 0; auto ran = 0;
auto vec = Arbutils::Collections::List<ScriptWrapper>{&script, &script2, &script3}; auto vec = Arbutils::Collections::List<ScriptWrapper>{
ScriptWrapper::FromScript(&script), ScriptWrapper::FromScript(&script2), ScriptWrapper::FromScript(&script3)};
auto aggr = ScriptAggregator(vec); auto aggr = ScriptAggregator(vec);
while (aggr.HasNext()) { while (aggr.HasNext()) {
auto next = aggr.GetNext(); auto next = aggr.GetNext();
@ -59,10 +60,10 @@ TEST_CASE("Script Aggregator properly iterates Script Set.", "[Battling, Scripti
set.Add(script); set.Add(script);
set.Add(script2); set.Add(script2);
set.Add(script3); set.Add(script3);
auto vec = Arbutils::Collections::List<ScriptWrapper>{&set}; auto vec = Arbutils::Collections::List<ScriptWrapper>{ScriptWrapper::FromSet(&set)};
auto aggr = ScriptAggregator(vec); auto aggr = ScriptAggregator(vec);
while (aggr.HasNext()) { while (aggr.HasNext()) {
auto next = aggr.GetNext(); auto next = aggr.GetNextNotNull();
REQUIRE(next != nullptr); REQUIRE(next != nullptr);
dynamic_cast<TestScript*>(next)->TestMethod(ran); dynamic_cast<TestScript*>(next)->TestMethod(ran);
} }
@ -77,10 +78,11 @@ TEST_CASE("Script Aggregator properly iterates data of Script Set and Script.",
auto set = ScriptSet(); auto set = ScriptSet();
set.Add(script2); set.Add(script2);
set.Add(script3); set.Add(script3);
auto vec = Arbutils::Collections::List<ScriptWrapper>{&set, &script}; auto vec =
Arbutils::Collections::List<ScriptWrapper>{ScriptWrapper::FromSet(&set), ScriptWrapper::FromScript(&script)};
auto aggr = ScriptAggregator(vec); auto aggr = ScriptAggregator(vec);
while (aggr.HasNext()) { while (aggr.HasNext()) {
auto next = aggr.GetNext(); auto next = aggr.GetNextNotNull();
REQUIRE(next != nullptr); REQUIRE(next != nullptr);
dynamic_cast<TestScript*>(next)->TestMethod(ran); dynamic_cast<TestScript*>(next)->TestMethod(ran);
} }
@ -96,10 +98,11 @@ TEST_CASE("Script Aggregator properly iterates data of Script and Script Set.",
auto set = ScriptSet(); auto set = ScriptSet();
set.Add(script2); set.Add(script2);
set.Add(script3); set.Add(script3);
auto vec = Arbutils::Collections::List<ScriptWrapper>{&script, &set}; auto vec =
Arbutils::Collections::List<ScriptWrapper>{ScriptWrapper::FromScript(&script), ScriptWrapper::FromSet(&set)};
auto aggr = ScriptAggregator(vec); auto aggr = ScriptAggregator(vec);
while (aggr.HasNext()) { while (aggr.HasNext()) {
auto next = aggr.GetNext(); auto next = aggr.GetNextNotNull();
REQUIRE(next != nullptr); REQUIRE(next != nullptr);
dynamic_cast<TestScript*>(next)->TestMethod(ran); dynamic_cast<TestScript*>(next)->TestMethod(ran);
} }
@ -116,10 +119,11 @@ TEST_CASE("Script Aggregator properly iterates data of Script, Script Set and Sc
auto set = ScriptSet(); auto set = ScriptSet();
set.Add(script2); set.Add(script2);
set.Add(script3); set.Add(script3);
auto vec = Arbutils::Collections::List<ScriptWrapper>{&script, &set, &script4}; auto vec = Arbutils::Collections::List<ScriptWrapper>{
ScriptWrapper::FromScript(&script), ScriptWrapper::FromSet(&set), ScriptWrapper::FromScript(&script4)};
auto aggr = ScriptAggregator(vec); auto aggr = ScriptAggregator(vec);
while (aggr.HasNext()) { while (aggr.HasNext()) {
auto next = aggr.GetNext(); auto next = aggr.GetNextNotNull();
REQUIRE(next != nullptr); REQUIRE(next != nullptr);
dynamic_cast<TestScript*>(next)->TestMethod(ran); dynamic_cast<TestScript*>(next)->TestMethod(ran);
} }
@ -141,7 +145,7 @@ TEST_CASE("Script Aggregator properly iterates when empty.", "[Battling, Scripti
TEST_CASE("Script Aggregator properly iterates empty Script Set.", "[Battling, Scripting]") { TEST_CASE("Script Aggregator properly iterates empty Script Set.", "[Battling, Scripting]") {
auto ran = 0; auto ran = 0;
auto set = ScriptSet(); auto set = ScriptSet();
auto vec = Arbutils::Collections::List<ScriptWrapper>{&set}; auto vec = Arbutils::Collections::List<ScriptWrapper>{ScriptWrapper::FromSet(&set)};
auto aggr = ScriptAggregator(vec); auto aggr = ScriptAggregator(vec);
while (aggr.HasNext()) { while (aggr.HasNext()) {
auto next = aggr.GetNext(); auto next = aggr.GetNext();

View File

@ -24,7 +24,9 @@ public:
Script* ScriptPtr = nullptr; Script* ScriptPtr = nullptr;
protected: protected:
void GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) override { scripts.Append(&ScriptPtr); } void GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) override {
scripts.Append(ScriptWrapper::FromScript(&ScriptPtr));
}
}; };
class ScriptSourceWithScriptSet : public ScriptSource { class ScriptSourceWithScriptSet : public ScriptSource {
@ -32,7 +34,9 @@ public:
ScriptSet Set; ScriptSet Set;
protected: protected:
void GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) override { scripts.Append(&Set); } void GetActiveScripts(Arbutils::Collections::List<ScriptWrapper>& scripts) override {
scripts.Append(ScriptWrapper::FromSet(&Set));
}
}; };
TEST_CASE("Script source with unset script ptr.", "[Battling, Scripting]") { TEST_CASE("Script source with unset script ptr.", "[Battling, Scripting]") {
@ -75,7 +79,7 @@ TEST_CASE("Script source with single item script set.", "[Battling, Scripting]")
auto s = new TestScript("foobar"); auto s = new TestScript("foobar");
source.Set.Add(s); source.Set.Add(s);
auto scripts = source.GetScriptIterator(); auto scripts = source.GetScriptIterator();
auto first = scripts.GetNext(); auto first = scripts.GetNextNotNull();
CHECK(first != nullptr); CHECK(first != nullptr);
CHECK(first->GetName() == "foobar"); CHECK(first->GetName() == "foobar");
} }
@ -87,11 +91,11 @@ TEST_CASE("Script source with multiple item script set.", "[Battling, Scripting]
source.Set.Add(s); source.Set.Add(s);
source.Set.Add(s2); source.Set.Add(s2);
auto scripts = source.GetScriptIterator(); auto scripts = source.GetScriptIterator();
auto first = scripts.GetNext(); auto first = scripts.GetNextNotNull();
CHECK(first != nullptr); REQUIRE(first != nullptr);
CHECK(first->GetName() == "foobar"); CHECK(first->GetName() == "foobar");
auto second = scripts.GetNext(); auto second = scripts.GetNextNotNull();
CHECK(second != nullptr); REQUIRE(second != nullptr);
CHECK(second->GetName() == "foobar2"); CHECK(second->GetName() == "foobar2");
} }