#ifndef CREATURELIB_SCRIPTSET_HPP #define CREATURELIB_SCRIPTSET_HPP #include #include #include "BattleScript.hpp" namespace CreatureLib::Battling { class ScriptSet { ArbUt::UniquePtrList _scripts; ArbUt::Dictionary _lookup; public: ~ScriptSet() = default; static constexpr size_t defaultCapacity = 8; ScriptSet() : _scripts(defaultCapacity), _lookup(defaultCapacity){}; void Clone(const ArbUt::OptionalBorrowedPtr& owner, ScriptSet& s) const { for (auto* script : _scripts) { s.Add(script->Clone(owner)); } } BattleScript* non_null Add(BattleScript* non_null script) { auto v = _lookup.TryGet(script->GetName()); if (v.has_value()) { _scripts[v.value()]->Stack(); delete script; return _scripts[v.value()]; } _scripts.Append(script); _lookup.Insert(script->GetName(), _scripts.Count() - 1); return script; } ArbUt::OptionalBorrowedPtr Get(const ArbUt::BasicStringView& key) const { return Get(key.GetHash()); } ArbUt::OptionalBorrowedPtr Get(u32 keyHash) const noexcept { auto v = _lookup.TryGet(keyHash); if (v.has_value()) { return _scripts[v.value()].GetRaw(); } return {}; } void Remove(const ArbUt::BasicStringView& key) { Remove(key.GetHash()); } void Remove(u32 keyHash) { auto v = _lookup.TryGet(keyHash); if (v.has_value()) { auto index = v.value(); auto script = _scripts[index]; script->OnRemove(); _scripts.Remove(v.value()); // This is extremely inefficient. We need to do something better for this. ResetLookup(); } } void ResetLookup() { _lookup.Clear(); for (size_t i = 0; i < _scripts.Count(); ++i) { _lookup.Insert(_scripts[i]->GetName(), i); } } void Clear() { for (auto s : _scripts) { s->OnRemove(); } _scripts.Clear(); _lookup.Clear(); } bool Has(const ArbUt::BasicStringView& key) const { return _lookup.Has(key); } bool Has(u32 keyHash) const { return _lookup.Has(keyHash); } inline size_t Count() const { return _scripts.Count(); } inline const ArbUt::UniquePtrList& GetIterator() const { return _scripts; } }; } #endif // CREATURELIB_SCRIPTSET_HPP