diff --git a/L2BotCore/Domain/Services/IncomingMessageProcessor.h b/L2BotCore/Domain/Services/IncomingMessageProcessor.h new file mode 100644 index 0000000..0edf915 --- /dev/null +++ b/L2BotCore/Domain/Services/IncomingMessageProcessor.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include "../Serializers/IncomingMessageFactoryInterface.h" +#include "HeroServiceInterface.h" + +namespace L2Bot::Domain::Services +{ + class IncomingMessageProcessor + { + public: + IncomingMessageProcessor( + const Serializers::IncomingMessageFactoryInterface& factory, + HeroServiceInterface& heroService + ) : + m_Factory(factory), + m_HeroService(heroService) + { + } + virtual ~IncomingMessageProcessor() = default; + + const Serializers::IncomingMessage::Type Process(const std::wstring& incomingMessge) const + { + const auto message = m_Factory.CreateMessage(incomingMessge); + switch (message.GetType()) + { + case Serializers::IncomingMessage::Type::move: + m_HeroService.Move(message.GetRawContent()); + break; + case Serializers::IncomingMessage::Type::acquireTarget: + m_HeroService.AcquireTarget(message.GetRawContent()); + break; + case Serializers::IncomingMessage::Type::attack: + m_HeroService.Attack(message.GetRawContent()); + break; + case Serializers::IncomingMessage::Type::pickup: + m_HeroService.Pickup(message.GetRawContent()); + break; + case Serializers::IncomingMessage::Type::useSkill: + m_HeroService.UseSkill(message.GetRawContent(), false, false); + break; + case Serializers::IncomingMessage::Type::useItem: + m_HeroService.UseItem(message.GetRawContent()); + break; + case Serializers::IncomingMessage::Type::toggleSoulshot: + m_HeroService.ToggleAutouseSoulshot(message.GetRawContent()); + break; + case Serializers::IncomingMessage::Type::sit: + m_HeroService.Sit(); + break; + case Serializers::IncomingMessage::Type::stand: + m_HeroService.Stand(); + break; + } + + return message.GetType(); + } + + private: + const L2Bot::Domain::Serializers::IncomingMessageFactoryInterface& m_Factory; + Services::HeroServiceInterface& m_HeroService; + }; +} \ No newline at end of file diff --git a/L2BotCore/Domain/Services/OutgoingMessageBuilder.h b/L2BotCore/Domain/Services/OutgoingMessageBuilder.h new file mode 100644 index 0000000..8656c41 --- /dev/null +++ b/L2BotCore/Domain/Services/OutgoingMessageBuilder.h @@ -0,0 +1,104 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "../Entities/EntityInterface.h" +#include "../Enums/EntityStateEnum.h" +#include "../Serializers/Node.h" + +namespace L2Bot::Domain::Services +{ + class OutgoingMessageBuilder + { + public: + OutgoingMessageBuilder() = default; + virtual ~OutgoingMessageBuilder() = default; + + const std::vector > Build(const std::wstring& name, const std::unordered_map>& entities) + { + std::vector > result; + + const auto& states = GetStates(name, entities); + for (const auto& kvp : states) { + const auto id = kvp.first; + + std::vector message; + + std::wstring operation = L"none"; + switch (kvp.second) + { + case Enums::EntityStateEnum::created: + operation = L"create"; + break; + case Enums::EntityStateEnum::updated: + operation = L"update"; + break; + case Enums::EntityStateEnum::deleted: + operation = L"delete"; + } + + message.push_back({ L"type", name }); + message.push_back({ L"operation", operation }); + if (entities.find(id) != entities.end()) { + message.push_back({ L"content", entities.at(id)->BuildSerializationNodes() }); + } + else { + message.push_back({ L"content", {Serializers::Node{ L"id", std::to_wstring(id) }} }); + } + + result.push_back(message); + } + + return result; + } + + private: + const std::unordered_map GetStates(const std::wstring& name, const std::unordered_map>& entities) + { + std::unordered_map result; + + auto& hashes = m_Hashes[name]; + + for (const auto& kvp : entities) { + const auto& entity = kvp.second; + + if (hashes.size() == 0) { + result[entity->GetId()] = Enums::EntityStateEnum::created; + } + else + { + if (hashes.find(entity->GetId()) == hashes.end()) { + result[entity->GetId()] = Enums::EntityStateEnum::created; + } + else if (hashes[entity->GetId()] != entity->GetHash()) { + result[entity->GetId()] = Enums::EntityStateEnum::updated; + } + } + + hashes[entity->GetId()] = entity->GetHash(); + } + + + for (auto it = hashes.begin(); it != hashes.end();) + { + if (entities.find(it->first) == entities.end()) + { + result[it->first] = Enums::EntityStateEnum::deleted; + it = hashes.erase(it); + } + else + { + ++it; + } + } + + return result; + } + + private: + std::unordered_map > m_Hashes; + }; +} \ No newline at end of file diff --git a/L2BotCore/Domain/Services/UnitOfWork.h b/L2BotCore/Domain/Services/UnitOfWork.h deleted file mode 100644 index 1110c9c..0000000 --- a/L2BotCore/Domain/Services/UnitOfWork.h +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include "../Entities/EntityInterface.h" -#include "../Enums/EntityStateEnum.h" - -namespace L2Bot::Domain::Services -{ - class UnitOfWork - { - public: - const std::unordered_map ConnectEntities(const std::wstring& name, const std::unordered_map>& entites) - { - std::unordered_map result; - - auto& hashes = m_Hashes[name]; - - for (const auto& kvp : entites) { - const auto &entity = kvp.second; - - if (hashes.size() == 0) { - result[entity->GetId()] = Enums::EntityStateEnum::created; - } - else - { - if (hashes.find(entity->GetId()) == hashes.end()) { - result[entity->GetId()] = Enums::EntityStateEnum::created; - } - else if (hashes[entity->GetId()] != entity->GetHash()) { - result[entity->GetId()] = Enums::EntityStateEnum::updated; - } - } - - hashes[entity->GetId()] = entity->GetHash(); - } - - - for (auto it = hashes.begin(); it != hashes.end();) - { - if (entites.find(it->first) == entites.end()) - { - result[it->first] = Enums::EntityStateEnum::deleted; - it = hashes.erase(it); - } - else - { - ++it; - } - } - - return result; - } - - private: - std::unordered_map > m_Hashes; - }; -} \ No newline at end of file diff --git a/L2BotCore/Domain/Services/WorldHandler.h b/L2BotCore/Domain/Services/WorldHandler.h new file mode 100644 index 0000000..a1f8365 --- /dev/null +++ b/L2BotCore/Domain/Services/WorldHandler.h @@ -0,0 +1,183 @@ +#pragma once + +#include +#include +#include +#include +#include "../Serializers/SerializerInterface.h" +#include "../Repositories/EntityRepositoryInterface.h" +#include "../Transports/TransportInterface.h" +#include "../DTO/Message.h" +#include "../Services/IncomingMessageProcessor.h" +#include "../Services/OutgoingMessageBuilder.h" + +namespace L2Bot::Domain::Services +{ + class WorldHandler + { + public: + WorldHandler( + Repositories::EntityRepositoryInterface& heroRepository, + Repositories::EntityRepositoryInterface& dropRepository, + Repositories::EntityRepositoryInterface& npcRepository, + Repositories::EntityRepositoryInterface& playerRepository, + Repositories::EntityRepositoryInterface& skillRepository, + Repositories::EntityRepositoryInterface& itemRepository, + Repositories::EntityRepositoryInterface& abnormalEffectRepository, + Repositories::EntityRepositoryInterface& chatMessageRepository, + const Serializers::SerializerInterface& serializer, + const Services::IncomingMessageProcessor& incomingMessageProcessor, + Transports::TransportInterface& transport + ) : + m_HeroRepository(heroRepository), + m_DropRepository(dropRepository), + m_NPCRepository(npcRepository), + m_PlayerRepository(playerRepository), + m_SkillRepository(skillRepository), + m_ItemRepository(itemRepository), + m_AbnormalEffectRepository(abnormalEffectRepository), + m_ChatMessageRepository(chatMessageRepository), + m_Serializer(serializer), + m_IncomingMessageProcessor(incomingMessageProcessor), + m_Transport(transport) + { + + } + + void Start() + { + m_ConnectingThread = std::thread(&WorldHandler::Connect, this); + m_SendingThread = std::thread(&WorldHandler::Send, this); + m_ReceivingThread = std::thread(&WorldHandler::Receive, this); + } + + void Stop() + { + m_Stopped = true; + if (m_ConnectingThread.joinable()) + { + m_ConnectingThread.join(); + } + if (m_SendingThread.joinable()) + { + m_SendingThread.join(); + } + if (m_ReceivingThread.joinable()) + { + m_ReceivingThread.join(); + } + } + + virtual ~WorldHandler() + { + Stop(); + } + + private: + void Send() + { + while (!m_Stopped) + { + const auto& messages = GetOutgoingMessages(); + + if (m_Transport.IsConnected()) + { + for (const auto& message : messages) + { + m_Transport.Send( + m_Serializer.Serialize(message) + ); + } + } + + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + } + + void Receive() + { + while (!m_Stopped) + { + if (m_Transport.IsConnected()) + { + const auto messageType = m_IncomingMessageProcessor.Process(m_Transport.Receive()); + + if (messageType == Serializers::IncomingMessage::Type::invalidate) { + Invalidate(); + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + } + + void Connect() + { + while (!m_Stopped) + { + if (!m_Transport.IsConnected()) + { + m_Transport.Connect(); + } + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + } + + const std::vector> GetOutgoingMessages() + { + std::map handlers + { + {L"hero", m_HeroRepository}, + {L"drop", m_DropRepository}, + {L"npc", m_NPCRepository}, + {L"player", m_PlayerRepository}, + {L"skill", m_SkillRepository}, + {L"item", m_ItemRepository}, + {L"abnormalEffect", m_AbnormalEffectRepository}, + {L"chat", m_ChatMessageRepository} + }; + + std::vector> result; + + for (const auto& kvp : handlers) + { + auto& entities = kvp.second.GetEntities(); + + const auto& messages = m_OutgoingMessageBuilder.Build(kvp.first, entities); + result.insert(result.end(), messages.begin(), messages.end()); + } + + return result; + } + + void Invalidate() + { + m_DropRepository.Reset(); + m_HeroRepository.Reset(); + m_NPCRepository.Reset(); + m_PlayerRepository.Reset(); + m_SkillRepository.Reset(); + m_ItemRepository.Reset(); + m_AbnormalEffectRepository.Reset(); + } + + private: + Repositories::EntityRepositoryInterface& m_DropRepository; + Repositories::EntityRepositoryInterface& m_HeroRepository; + Repositories::EntityRepositoryInterface& m_NPCRepository; + Repositories::EntityRepositoryInterface& m_PlayerRepository; + Repositories::EntityRepositoryInterface& m_SkillRepository; + Repositories::EntityRepositoryInterface& m_ItemRepository; + Repositories::EntityRepositoryInterface& m_AbnormalEffectRepository; + Repositories::EntityRepositoryInterface& m_ChatMessageRepository; + const Serializers::SerializerInterface& m_Serializer; + const Services::IncomingMessageProcessor m_IncomingMessageProcessor; + Services::OutgoingMessageBuilder m_OutgoingMessageBuilder; + + Transports::TransportInterface& m_Transport; + bool m_Stopped = false; + std::thread m_ConnectingThread; + std::thread m_SendingThread; + std::thread m_ReceivingThread; + }; + +} \ No newline at end of file diff --git a/L2BotCore/L2BotCore.vcxproj b/L2BotCore/L2BotCore.vcxproj index 53d9e04..54d29fd 100644 --- a/L2BotCore/L2BotCore.vcxproj +++ b/L2BotCore/L2BotCore.vcxproj @@ -179,7 +179,9 @@ - + + + diff --git a/L2BotCore/L2BotCore.vcxproj.filters b/L2BotCore/L2BotCore.vcxproj.filters index 6d606c8..3fe16e7 100644 --- a/L2BotCore/L2BotCore.vcxproj.filters +++ b/L2BotCore/L2BotCore.vcxproj.filters @@ -156,7 +156,13 @@ Header Files - + + Header Files + + + Header Files + + Header Files diff --git a/L2BotDll/Application.h b/L2BotDll/Application.h index 4d6218d..d1ea49c 100644 --- a/L2BotDll/Application.h +++ b/L2BotDll/Application.h @@ -3,11 +3,11 @@ #include #include -#include "Services/WorldHandler.h" +#include "Domain/Services/WorldHandler.h" +#include "Domain/Services/IncomingMessageProcessor.h" #include "Serializers/JsonSerializer.h" #include "Serializers/JsonIncomingMessageFactory.h" #include "Transports/NamedPipeTransport.h" - #include "Versions/VersionAbstractFactory.h" using namespace L2Bot::Domain; @@ -29,8 +29,7 @@ public: m_AbstractFactory.GetAbnormalEffectRepository(), m_AbstractFactory.GetChatMessageRepository(), m_Serializer, - m_MessageFactory, - m_AbstractFactory.GetHeroService(), + Services::IncomingMessageProcessor(m_MessageFactory, m_AbstractFactory.GetHeroService()), m_Transport ) { @@ -61,7 +60,7 @@ public: private: const VersionAbstractFactory& m_AbstractFactory; - WorldHandler m_WorldHandler; + Services::WorldHandler m_WorldHandler; JsonSerializer m_Serializer; JsonIncomingMessageFactory m_MessageFactory; NamedPipeTransport m_Transport; diff --git a/L2BotDll/L2BotDll.vcxproj b/L2BotDll/L2BotDll.vcxproj index 6ff9057..f2554a8 100644 --- a/L2BotDll/L2BotDll.vcxproj +++ b/L2BotDll/L2BotDll.vcxproj @@ -187,7 +187,6 @@ - diff --git a/L2BotDll/L2BotDll.vcxproj.filters b/L2BotDll/L2BotDll.vcxproj.filters index 3bf6805..d1ced81 100644 --- a/L2BotDll/L2BotDll.vcxproj.filters +++ b/L2BotDll/L2BotDll.vcxproj.filters @@ -90,9 +90,6 @@ Header Files - - Header Files - Header Files diff --git a/L2BotDll/Services/WorldHandler.h b/L2BotDll/Services/WorldHandler.h deleted file mode 100644 index 5859e51..0000000 --- a/L2BotDll/Services/WorldHandler.h +++ /dev/null @@ -1,244 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include "Domain/Services/HeroServiceInterface.h" -#include "Domain/Serializers/SerializerInterface.h" -#include "Domain/Serializers/IncomingMessageFactoryInterface.h" -#include "Domain/Repositories/EntityRepositoryInterface.h" -#include "Domain/Transports/TransportInterface.h" -#include "Domain/DTO/Message.h" -#include "Domain/Services/UnitOfWork.h" - -using namespace L2Bot::Domain; - -class WorldHandler -{ -public: - WorldHandler( - Repositories::EntityRepositoryInterface& heroRepository, - Repositories::EntityRepositoryInterface& dropRepository, - Repositories::EntityRepositoryInterface& npcRepository, - Repositories::EntityRepositoryInterface& playerRepository, - Repositories::EntityRepositoryInterface& skillRepository, - Repositories::EntityRepositoryInterface& itemRepository, - Repositories::EntityRepositoryInterface& abnormalEffectRepository, - Repositories::EntityRepositoryInterface& chatMessageRepository, - const Serializers::SerializerInterface& serializer, - const Serializers::IncomingMessageFactoryInterface& incomingMessageFactory, - Services::HeroServiceInterface& heroService, - Transports::TransportInterface& transport - ) : - m_HeroRepository(heroRepository), - m_DropRepository(dropRepository), - m_NPCRepository(npcRepository), - m_PlayerRepository(playerRepository), - m_SkillRepository(skillRepository), - m_ItemRepository(itemRepository), - m_AbnormalEffectRepository(abnormalEffectRepository), - m_ChatMessageRepository(chatMessageRepository), - m_Serializer(serializer), - m_IncomingMessageFactory(incomingMessageFactory), - m_HeroService(heroService), - m_Transport(transport) - { - - } - - void Start() - { - m_ConnectingThread = std::thread(&WorldHandler::Connect, this); - m_SendingThread = std::thread(&WorldHandler::Send, this); - m_ReceivingThread = std::thread(&WorldHandler::Receive, this); - } - - void Stop() - { - m_Stopped = true; - if (m_ConnectingThread.joinable()) - { - m_ConnectingThread.join(); - } - if (m_SendingThread.joinable()) - { - m_SendingThread.join(); - } - if (m_ReceivingThread.joinable()) - { - m_ReceivingThread.join(); - } - } - - virtual ~WorldHandler() - { - Stop(); - } - -private: - void Send() - { - while (!m_Stopped) - { - const auto& data = GetData(); - - if (m_Transport.IsConnected()) - { - for (const auto& item : data) - { - m_Transport.Send( - m_Serializer.Serialize(item) - ); - } - } - - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } - } - - void Receive() - { - while (!m_Stopped) - { - if (m_Transport.IsConnected()) - { - const auto message = m_IncomingMessageFactory.CreateMessage(m_Transport.Receive()); - switch (message.GetType()) - { - case Serializers::IncomingMessage::Type::invalidate: - Invalidate(); - break; - case Serializers::IncomingMessage::Type::move: - m_HeroService.Move(message.GetRawContent()); - break; - case Serializers::IncomingMessage::Type::acquireTarget: - m_HeroService.AcquireTarget(message.GetRawContent()); - break; - case Serializers::IncomingMessage::Type::attack: - m_HeroService.Attack(message.GetRawContent()); - break; - case Serializers::IncomingMessage::Type::pickup: - m_HeroService.Pickup(message.GetRawContent()); - break; - case Serializers::IncomingMessage::Type::useSkill: - m_HeroService.UseSkill(message.GetRawContent(), false, false); - break; - case Serializers::IncomingMessage::Type::useItem: - m_HeroService.UseItem(message.GetRawContent()); - break; - case Serializers::IncomingMessage::Type::toggleSoulshot: - m_HeroService.ToggleAutouseSoulshot(message.GetRawContent()); - break; - case Serializers::IncomingMessage::Type::sit: - m_HeroService.Sit(); - break; - case Serializers::IncomingMessage::Type::stand: - m_HeroService.Stand(); - break; - } - } - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } - } - - void Connect() - { - while (!m_Stopped) - { - if (!m_Transport.IsConnected()) - { - m_Transport.Connect(); - } - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } - } - - const std::vector> GetData() - { - std::map handlers - { - {L"hero", m_HeroRepository}, - {L"drop", m_DropRepository}, - {L"npc", m_NPCRepository}, - {L"player", m_PlayerRepository}, - {L"skill", m_SkillRepository}, - {L"item", m_ItemRepository}, - {L"abnormalEffect", m_AbnormalEffectRepository}, - {L"chat", m_ChatMessageRepository} - }; - - std::vector> result; - - for (const auto& kvp : handlers) - { - auto& entities = kvp.second.GetEntities(); - const auto& changes = m_UnitOfWork.ConnectEntities(kvp.first, entities); - - for (const auto &changeKvp : changes) { - const auto id = changeKvp.first; - - std::wstring operation = L"none"; - switch (changeKvp.second) - { - case Enums::EntityStateEnum::created: - operation = L"create"; - break; - case Enums::EntityStateEnum::updated: - operation = L"update"; - break; - case Enums::EntityStateEnum::deleted: - operation = L"delete"; - } - - if (entities.find(id) != entities.end()) { - result.push_back({ - Serializers::Node{ L"type", kvp.first }, - Serializers::Node{ L"operation", operation }, - Serializers::Node{ L"content", entities.at(id)->BuildSerializationNodes()} - }); - } - else { - result.push_back({ - Serializers::Node{ L"type", kvp.first }, - Serializers::Node{ L"operation", operation }, - Serializers::Node{ L"content", {Serializers::Node{ L"id", std::to_wstring(id) }}} - }); - } - } - } - - return result; - } - - void Invalidate() - { - m_DropRepository.Reset(); - m_HeroRepository.Reset(); - m_NPCRepository.Reset(); - m_PlayerRepository.Reset(); - m_SkillRepository.Reset(); - m_ItemRepository.Reset(); - m_AbnormalEffectRepository.Reset(); - } - -private: - Repositories::EntityRepositoryInterface& m_DropRepository; - Repositories::EntityRepositoryInterface& m_HeroRepository; - Repositories::EntityRepositoryInterface& m_NPCRepository; - Repositories::EntityRepositoryInterface& m_PlayerRepository; - Repositories::EntityRepositoryInterface& m_SkillRepository; - Repositories::EntityRepositoryInterface& m_ItemRepository; - Repositories::EntityRepositoryInterface& m_AbnormalEffectRepository; - Repositories::EntityRepositoryInterface& m_ChatMessageRepository; - const Serializers::SerializerInterface& m_Serializer; - const Serializers::IncomingMessageFactoryInterface& m_IncomingMessageFactory; - Services::HeroServiceInterface& m_HeroService; - Transports::TransportInterface& m_Transport; - bool m_Stopped = false; - std::thread m_ConnectingThread; - std::thread m_SendingThread; - std::thread m_ReceivingThread; - - Services::UnitOfWork m_UnitOfWork; -}; diff --git a/L2BotDll/dllmain.cpp b/L2BotDll/dllmain.cpp index 6d7ee47..a13210b 100644 --- a/L2BotDll/dllmain.cpp +++ b/L2BotDll/dllmain.cpp @@ -18,7 +18,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, case DLL_PROCESS_ATTACH: injector.SetHook(hModule); if (processName == "l2.exe") { - MessageBox(0, L"A", L"B", MB_OK); InjectLibrary::StopCurrentProcess(); application.Start(); InjectLibrary::StartCurrentProcess();