#pragma once #include #include #include #include "Domain/Repositories/EntityRepositoryInterface.h" #include "../Factories/AbnormalEffectFactory.h" #include "../../../Events/AbnormalEffectChangedEvent.h" #include "../../../Events/HeroDeletedEvent.h" #include "../../../Events/EventDispatcher.h" #include "../GameStructs/NetworkHandlerWrapper.h" #include "../../../Services/EntityHandler.h" using namespace L2Bot::Domain; namespace Interlude { class AbnormalEffectRepository : public Repositories::EntityRepositoryInterface { public: const std::vector> GetEntities() override { std::unique_lock(m_Mutex); std::map skillPtrs; for (const auto& kvp : m_Effects) { skillPtrs[kvp.first] = kvp.second.get(); } const auto objects = m_EntityHandler.GetEntities(skillPtrs, [this](Entities::AbnormalEffect* item) { return std::make_unique(item); }); auto result = std::vector>(); for (const auto kvp : objects) { result.push_back(kvp.second); } return result; } AbnormalEffectRepository(const AbnormalEffectFactory& factory, EntityHandler& handler) : m_Factory(factory), m_EntityHandler(handler) { EventDispatcher::GetInstance().Subscribe(AbnormalEffectChangedEvent::name, [this](const Event& evt) { OnEffectToggled(evt); }); EventDispatcher::GetInstance().Subscribe(HeroDeletedEvent::name, [this](const Event& evt) { OnHeroDeleted(evt); }); } AbnormalEffectRepository() = delete; virtual ~AbnormalEffectRepository() { Reset(); } void Reset() override { std::shared_lock(m_Mutex); m_Effects.clear(); } void OnHeroDeleted(const Event& evt) { std::shared_lock(m_Mutex); if (evt.GetName() == HeroDeletedEvent::name) { Reset(); } } void OnEffectToggled(const Event& evt) { std::shared_lock(m_Mutex); if (evt.GetName() == AbnormalEffectChangedEvent::name) { const auto casted = static_cast(evt); const auto skillInfo = casted.GetSkillInfo(); std::map ids; for (size_t i = 0; i < skillInfo.size(); i += 3) { const auto effectId = skillInfo[i]; const auto level = skillInfo[i + 1]; auto effect = m_Factory.Create(effectId, level); m_Effects.emplace(effect->GetId(), std::move(effect)); ids[effectId] = effectId; } for (auto it = m_Effects.begin(); it != m_Effects.end();) { const auto& effect = it->second; if (ids.find(effect->GetId()) == ids.end()) { it = m_Effects.erase(it); } else { ++it; } } } } private: const AbnormalEffectFactory& m_Factory; std::map> m_Effects; std::shared_timed_mutex m_Mutex; EntityHandler& m_EntityHandler; }; }