diff --git a/L2BotCore/Domain/Entities/AbnormalEffect.h b/L2BotCore/Domain/Entities/AbnormalEffect.h new file mode 100644 index 0000000..c0d525c --- /dev/null +++ b/L2BotCore/Domain/Entities/AbnormalEffect.h @@ -0,0 +1,95 @@ +#pragma once +#include +#include +#include +#include "EntityInterface.h" + +namespace L2Bot::Domain::Entities +{ + class AbnormalEffect : public EntityInterface + { + public: + const uint32_t GetId() const override + { + return m_SkillId; + } + + void Update(const EntityInterface* other) override + { + const AbnormalEffect* casted = static_cast(other); + SaveState(); + + m_SkillId = casted->m_SkillId; + m_Level = casted->m_Level; + m_Name = casted->m_Name; + m_Description = casted->m_Description; + m_IconName = casted->m_IconName; + } + void SaveState() override + { + m_IsNewState = false; + } + const bool IsEqual(const EntityInterface* other) const override + { + const AbnormalEffect* casted = static_cast(other); + return m_SkillId == casted->m_SkillId && + m_Level == casted->m_Level && + m_Name == casted->m_Name && + m_Description == casted->m_Description && + m_IconName == casted->m_IconName; + } + + const std::vector BuildSerializationNodes() const override + { + std::vector result; + + result.push_back({ "skillId", std::to_string(m_SkillId) }); + result.push_back({ "level", std::to_string(m_Level) }); + + if (m_IsNewState) + { + result.push_back({ "name", m_Name }); + result.push_back({ "iconName", m_IconName }); + result.push_back({ "description", m_Description }); + } + + return result; + } + + AbnormalEffect( + const uint32_t skillId, + const uint8_t level, + const std::string& name, + const std::string& description, + const std::string& iconName + ) : + m_SkillId(skillId), + m_Level(level), + m_Name(name), + m_Description(description), + m_IconName(iconName) + { + + } + + AbnormalEffect(const AbnormalEffect* other) : + m_SkillId(other->m_SkillId), + m_Level(other->m_Level), + m_Name(other->m_Name), + m_Description(other->m_Description), + m_IconName(other->m_IconName) + { + } + + AbnormalEffect() = default; + virtual ~AbnormalEffect() = default; + + private: + uint32_t m_SkillId = 0; + uint8_t m_Level = 0; + std::string m_Name = ""; + std::string m_Description = ""; + std::string m_IconName = ""; + bool m_IsNewState = true; + }; +} diff --git a/L2BotCore/L2BotCore.vcxproj b/L2BotCore/L2BotCore.vcxproj index 6f559f4..ace4452 100644 --- a/L2BotCore/L2BotCore.vcxproj +++ b/L2BotCore/L2BotCore.vcxproj @@ -160,6 +160,7 @@ + diff --git a/L2BotCore/L2BotCore.vcxproj.filters b/L2BotCore/L2BotCore.vcxproj.filters index c3d762a..993d2af 100644 --- a/L2BotCore/L2BotCore.vcxproj.filters +++ b/L2BotCore/L2BotCore.vcxproj.filters @@ -135,6 +135,9 @@ Header Files + + Header Files + diff --git a/L2BotDll/Application.h b/L2BotDll/Application.h index 1e655fe..ba1ab3c 100644 --- a/L2BotDll/Application.h +++ b/L2BotDll/Application.h @@ -25,6 +25,7 @@ public: m_AbstractFactory.GetPlayerRepository(), m_AbstractFactory.GetSkillRepository(), m_AbstractFactory.GetItemRepository(), + m_AbstractFactory.GetAbnormalEffectRepository(), m_Serializer, m_Transport ) diff --git a/L2BotDll/L2BotDll.vcxproj b/L2BotDll/L2BotDll.vcxproj index 521853c..ab42159 100644 --- a/L2BotDll/L2BotDll.vcxproj +++ b/L2BotDll/L2BotDll.vcxproj @@ -186,6 +186,7 @@ + @@ -195,6 +196,7 @@ + diff --git a/L2BotDll/L2BotDll.vcxproj.filters b/L2BotDll/L2BotDll.vcxproj.filters index 6b37801..a8fec70 100644 --- a/L2BotDll/L2BotDll.vcxproj.filters +++ b/L2BotDll/L2BotDll.vcxproj.filters @@ -174,6 +174,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/L2BotDll/Services/WorldHandler.h b/L2BotDll/Services/WorldHandler.h index c3a4fb3..cffb982 100644 --- a/L2BotDll/Services/WorldHandler.h +++ b/L2BotDll/Services/WorldHandler.h @@ -22,6 +22,7 @@ public: Repositories::EntityRepositoryInterface& playerRepository, Repositories::EntityRepositoryInterface& skillRepository, Repositories::EntityRepositoryInterface& itemRepository, + Repositories::EntityRepositoryInterface& abnormalEffectService, const Serializers::SerializerInterface& serializer, Transports::TransportInterface& transport ) : @@ -31,6 +32,7 @@ public: m_PlayerService(Services::EntityService(playerRepository)), m_SkillService(Services::EntityService(skillRepository)), m_ItemService(Services::EntityService(itemRepository)), + m_AbnormalEffectService(Services::EntityService(abnormalEffectService)), m_Serializer(serializer), m_Transport(transport) { @@ -125,6 +127,7 @@ private: Serializers::SerializableStateContainer{m_PlayerService.GetEntities(), "player"}, Serializers::SerializableStateContainer{m_SkillService.GetEntities(), "skill"}, Serializers::SerializableStateContainer{m_ItemService.GetEntities(), "item"}, + Serializers::SerializableStateContainer{m_AbnormalEffectService.GetEntities(), "abnormalEffect"}, }; std::vector result; @@ -147,6 +150,7 @@ private: m_PlayerService.Invalidate(); m_SkillService.Invalidate(); m_ItemService.Invalidate(); + m_AbnormalEffectService.Invalidate(); } private: @@ -156,6 +160,7 @@ private: Services::EntityService m_PlayerService; Services::EntityService m_SkillService; Services::EntityService m_ItemService; + Services::EntityService m_AbnormalEffectService; const Serializers::SerializerInterface& m_Serializer; Transports::TransportInterface& m_Transport; bool m_Stopped = false; diff --git a/L2BotDll/Versions/Interlude/AbstractFactory.h b/L2BotDll/Versions/Interlude/AbstractFactory.h index dd9c7b1..e786c46 100644 --- a/L2BotDll/Versions/Interlude/AbstractFactory.h +++ b/L2BotDll/Versions/Interlude/AbstractFactory.h @@ -7,12 +7,14 @@ #include "Factories/PlayerFactory.h" #include "Factories/SkillFactory.h" #include "Factories/ItemFactory.h" +#include "Factories/AbnormalEffectFactory.h" #include "Repositories/DropRepository.h" #include "Repositories/HeroRepository.h" #include "Repositories/NPCRepository.h" #include "Repositories/PlayerRepository.h" #include "Repositories/SkillRepository.h" #include "Repositories/ItemRepository.h" +#include "Repositories/AbnormalEffectRepository.h" #include "GameStructs/NetworkHandlerWrapper.h" #include "GameStructs/GameEngineWrapper.h" #include "GameStructs/L2GameDataWrapper.h" @@ -101,6 +103,16 @@ namespace Interlude ); return result; } + AbnormalEffectRepository& GetAbnormalEffectRepository() const override + { + static auto factory = AbnormalEffectFactory(GetL2GameData(), GetFName()); + static EntityHandler handler; + static auto result = AbnormalEffectRepository( + factory, + handler + ); + return result; + } NetworkHandlerWrapper& GetNetworkHandler() const override { static NetworkHandlerWrapper result; diff --git a/L2BotDll/Versions/Interlude/Factories/AbnormalEffectFactory.h b/L2BotDll/Versions/Interlude/Factories/AbnormalEffectFactory.h new file mode 100644 index 0000000..9e4e3f0 --- /dev/null +++ b/L2BotDll/Versions/Interlude/Factories/AbnormalEffectFactory.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include "../GameStructs/L2GameDataWrapper.h" +#include "../GameStructs/FName.h" +#include "../../../Common/Common.h" +#include "Domain/Entities/AbnormalEffect.h" + +using namespace L2Bot::Domain; + +namespace Interlude +{ + class AbnormalEffectFactory + { + public: + AbnormalEffectFactory(const L2GameDataWrapper& l2GameData, const FName& fName) : + m_L2GameData(l2GameData), + m_FName(fName) + { + } + + AbnormalEffectFactory() = delete; + virtual ~AbnormalEffectFactory() = default; + + std::unique_ptr Create(const uint32_t skillId, const uint32_t level) const + { + const auto data = m_L2GameData.GetMSData(skillId, level); + + const auto name = data && data->name ? data->name : L""; + const auto description = data && data->description ? data->description : L""; + const auto iconEntry = data ? m_FName.GetEntry(data->iconNameIndex) : nullptr; + + return std::make_unique( + skillId, + static_cast(level), + ConvertFromWideChar(name), + ConvertFromWideChar(description), + iconEntry ? ConvertFromWideChar(iconEntry->value) : "" + ); + } + + private: + const L2GameDataWrapper& m_L2GameData; + const FName& m_FName; + }; +} \ No newline at end of file diff --git a/L2BotDll/Versions/Interlude/Repositories/AbnormalEffectRepository.h b/L2BotDll/Versions/Interlude/Repositories/AbnormalEffectRepository.h new file mode 100644 index 0000000..8c37e5b --- /dev/null +++ b/L2BotDll/Versions/Interlude/Repositories/AbnormalEffectRepository.h @@ -0,0 +1,120 @@ +#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; + }; +} \ No newline at end of file diff --git a/L2BotDll/Versions/Interlude/Repositories/SkillRepository.h b/L2BotDll/Versions/Interlude/Repositories/SkillRepository.h index 0090878..adeef40 100644 --- a/L2BotDll/Versions/Interlude/Repositories/SkillRepository.h +++ b/L2BotDll/Versions/Interlude/Repositories/SkillRepository.h @@ -190,9 +190,9 @@ namespace Interlude ids[skillInfo[i]] = skillInfo[i + 2]; } - for (auto it = m_Skills.begin(); it != m_Skills.end();) + for (const auto& kvp : m_Skills) { - const auto& skill = it->second; + const auto& skill = kvp.second; const auto needToToggle = ids.find(skill->GetId()) != ids.end(); // buff time less than zero means this is a aura @@ -206,10 +206,6 @@ namespace Interlude { skill->UpdateToggle(true); } - else - { - ++it; - } } } } diff --git a/L2BotDll/Versions/VersionAbstractFactory.h b/L2BotDll/Versions/VersionAbstractFactory.h index 6bd7bd4..26298a2 100644 --- a/L2BotDll/Versions/VersionAbstractFactory.h +++ b/L2BotDll/Versions/VersionAbstractFactory.h @@ -22,6 +22,7 @@ public: virtual Repositories::EntityRepositoryInterface& GetPlayerRepository() const = 0; virtual Repositories::EntityRepositoryInterface& GetSkillRepository() const = 0; virtual Repositories::EntityRepositoryInterface& GetItemRepository() const = 0; + virtual Repositories::EntityRepositoryInterface& GetAbnormalEffectRepository() const = 0; virtual NetworkHandlerInterface& GetNetworkHandler() const = 0; virtual GameEngineInterface& GetGameEngine() const = 0; virtual L2GameDataInterface& GetL2GameData() const = 0;