From 1d0dbf86c37baa779e66ebc06d4922b14b341402 Mon Sep 17 00:00:00 2001 From: k0t9i Date: Wed, 25 Jan 2023 14:55:38 +0400 Subject: [PATCH] feat: remove outdated items and skills --- L2BotDll/Events/GameEngineTickedEvent.h | 18 ++++++++ L2BotDll/L2BotDll.vcxproj | 1 + L2BotDll/L2BotDll.vcxproj.filters | 3 ++ .../GameStructs/GameEngineWrapper.cpp | 43 +++++++++---------- .../Interlude/GameStructs/GameEngineWrapper.h | 11 +++-- .../Interlude/Repositories/ItemRepository.h | 43 +++++++++++++++++-- .../Interlude/Repositories/SkillRepository.h | 36 ++++++++++++++++ 7 files changed, 122 insertions(+), 33 deletions(-) create mode 100644 L2BotDll/Events/GameEngineTickedEvent.h diff --git a/L2BotDll/Events/GameEngineTickedEvent.h b/L2BotDll/Events/GameEngineTickedEvent.h new file mode 100644 index 0000000..2ba1683 --- /dev/null +++ b/L2BotDll/Events/GameEngineTickedEvent.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include "Event.h" + +class GameEngineTickedEvent : public Event +{ +public: + static constexpr const char* name = "gameEngineTicked"; + + const std::string GetName() const + { + return std::string(name); + } + + GameEngineTickedEvent() = default; + virtual ~GameEngineTickedEvent() = default; +}; \ No newline at end of file diff --git a/L2BotDll/L2BotDll.vcxproj b/L2BotDll/L2BotDll.vcxproj index ab42159..0e74d42 100644 --- a/L2BotDll/L2BotDll.vcxproj +++ b/L2BotDll/L2BotDll.vcxproj @@ -168,6 +168,7 @@ + diff --git a/L2BotDll/L2BotDll.vcxproj.filters b/L2BotDll/L2BotDll.vcxproj.filters index a8fec70..af3291f 100644 --- a/L2BotDll/L2BotDll.vcxproj.filters +++ b/L2BotDll/L2BotDll.vcxproj.filters @@ -180,6 +180,9 @@ Header Files + + Header Files + diff --git a/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.cpp b/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.cpp index 3e582a5..83f17c5 100644 --- a/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.cpp +++ b/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.cpp @@ -11,14 +11,13 @@ #include "../../../Events/ItemUpdatedEvent.h" #include "../../../Events/ItemDeletedEvent.h" #include "../../../Events/ItemAutousedEvent.h" +#include "../../../Events/GameEngineTickedEvent.h" #include "../../../DTO/ItemData.h" namespace Interlude { - void* GameEngineWrapper::originalInitAddress = 0; GameEngineWrapper::GameEngine* GameEngineWrapper::_target = 0; - void(__thiscall* GameEngineWrapper::__Init)(GameEngine*, float_t) = 0; void(__thiscall* GameEngineWrapper::__OnSkillListPacket)(GameEngine*, L2ParamStack&) = 0; int(__thiscall* GameEngineWrapper::__OnReceiveMagicSkillUse)(GameEngine*, User*, User*, L2ParamStack&) = 0; void(__thiscall* GameEngineWrapper::__OnReceiveMagicSkillCanceled)(GameEngine*, User*) = 0; @@ -26,14 +25,14 @@ namespace Interlude void(__thiscall* GameEngineWrapper::__AddInventoryItem)(GameEngine*, ItemInfo&) = 0; void(__thiscall* GameEngineWrapper::__OnReceiveUpdateItemList)(GameEngine*, UpdateItemListActionType, ItemInfo&) = 0; void(__thiscall* GameEngineWrapper::__OnExAutoSoulShot)(GameEngine*, L2ParamStack&) = 0; + void(__thiscall* GameEngineWrapper::__Tick)(GameEngine*, float_t) = 0; void GameEngineWrapper::Init(HMODULE hModule) { - void* initAddress = GetProcAddress(hModule, "?Tick@UGameEngine@@UAEXM@Z"); - originalInitAddress = splice(initAddress, __Init_hook); - (FARPROC&)__Init = (FARPROC)initAddress; - + (FARPROC&)__Tick = (FARPROC)splice( + GetProcAddress(hModule, "?Tick@UGameEngine@@UAEXM@Z"), __Tick_hook + ); (FARPROC&)__OnSkillListPacket = (FARPROC)splice( GetProcAddress(hModule, "?OnSkillListPacket@UGameEngine@@UAEXAAVL2ParamStack@@@Z"), __OnSkillListPacket_hook ); @@ -59,7 +58,6 @@ namespace Interlude void GameEngineWrapper::Restore() { - restore(originalInitAddress); restore((void*&)__OnSkillListPacket); restore((void*&)__OnReceiveMagicSkillUse); restore((void*&)__OnReceiveMagicSkillCanceled); @@ -69,19 +67,6 @@ namespace Interlude restore((void*&)__OnExAutoSoulShot); } - void __fastcall GameEngineWrapper::__Init_hook(GameEngine* This, uint32_t /*edx*/, float_t unk) - { - if (_target == 0) { - _target = This; - - InjectLibrary::StopCurrentProcess(); - restore(originalInitAddress); - InjectLibrary::StartCurrentProcess(); - - (*__Init)(This, unk); - } - } - void __fastcall GameEngineWrapper::__OnSkillListPacket_hook(GameEngine* This, uint32_t, L2ParamStack& stack) { EventDispatcher::GetInstance().Dispatch(SkillCreatedEvent{stack.GetBufferAsVector()}); @@ -106,7 +91,7 @@ namespace Interlude (*__AddAbnormalStatus)(This, stack); } - void __fastcall GameEngineWrapper::__AddInventoryItem_hook(GameEngine* This, int, ItemInfo& itemInfo) + void __fastcall GameEngineWrapper::__AddInventoryItem_hook(GameEngine* This, uint32_t, ItemInfo& itemInfo) { EventDispatcher::GetInstance().Dispatch( ItemCreatedEvent @@ -126,7 +111,7 @@ namespace Interlude (*__AddInventoryItem)(This, itemInfo); } - void __fastcall GameEngineWrapper::__OnReceiveUpdateItemList_hook(GameEngine* This, int, UpdateItemListActionType actionType, ItemInfo& itemInfo) + void __fastcall GameEngineWrapper::__OnReceiveUpdateItemList_hook(GameEngine* This, uint32_t, UpdateItemListActionType actionType, ItemInfo& itemInfo) { const ItemData itemData { @@ -154,9 +139,21 @@ namespace Interlude (*__OnReceiveUpdateItemList)(This, actionType, itemInfo); } - void __fastcall GameEngineWrapper::__OnExAutoSoulShot_hook(GameEngine* This, int, L2ParamStack& stack) + void __fastcall GameEngineWrapper::__OnExAutoSoulShot_hook(GameEngine* This, uint32_t, L2ParamStack& stack) { EventDispatcher::GetInstance().Dispatch(ItemAutousedEvent{ stack.GetBufferAsVector() }); (*__OnExAutoSoulShot)(This, stack); } + + void __fastcall GameEngineWrapper::__Tick_hook(GameEngine* This, uint32_t, float_t deltaTime) + { + if (_target == 0) + { + _target = This; + } + + (*__Tick)(This, deltaTime); + + EventDispatcher::GetInstance().Dispatch(GameEngineTickedEvent{}); + } } \ No newline at end of file diff --git a/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.h b/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.h index dce82da..a9db089 100644 --- a/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.h +++ b/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.h @@ -19,7 +19,6 @@ namespace Interlude void Restore() override; private: - static void(__thiscall* __Init)(GameEngine*, float_t); static void(__thiscall* __OnSkillListPacket)(GameEngine*, L2ParamStack& stack); static int(__thiscall* __OnReceiveMagicSkillUse)(GameEngine*, User*, User*, L2ParamStack&); static void(__thiscall* __OnReceiveMagicSkillCanceled)(GameEngine*, User*); @@ -27,18 +26,18 @@ namespace Interlude static void(__thiscall* __AddInventoryItem)(GameEngine*, ItemInfo&); static void(__thiscall* __OnReceiveUpdateItemList)(GameEngine*, UpdateItemListActionType, ItemInfo&); static void(__thiscall* __OnExAutoSoulShot)(GameEngine*, L2ParamStack&); + static void(__thiscall* __Tick)(GameEngine*, float_t); - static void __fastcall __Init_hook(GameEngine* This, uint32_t /*edx*/, float_t unk); static void __fastcall __OnSkillListPacket_hook(GameEngine* This, uint32_t /*edx*/, L2ParamStack& stack); static int __fastcall __OnReceiveMagicSkillUse_hook(GameEngine* This, uint32_t /*edx*/, User* u1, User* u2, L2ParamStack& stack); static void __fastcall __OnReceiveMagicSkillCanceled_hook(GameEngine* This, uint32_t /*edx*/, User* user); static void __fastcall __AddAbnormalStatus_hook(GameEngine* This, uint32_t /*edx*/, L2ParamStack& stack); - static void __fastcall __AddInventoryItem_hook(GameEngine* This, int /*edx*/, ItemInfo& itemInfo); - static void __fastcall __OnReceiveUpdateItemList_hook(GameEngine* This, int /*edx*/, UpdateItemListActionType actionType, ItemInfo& itemInfo); - static void __fastcall __OnExAutoSoulShot_hook(GameEngine* This, int /*edx*/, L2ParamStack& stack); + static void __fastcall __AddInventoryItem_hook(GameEngine* This, uint32_t /*edx*/, ItemInfo& itemInfo); + static void __fastcall __OnReceiveUpdateItemList_hook(GameEngine* This, uint32_t /*edx*/, UpdateItemListActionType actionType, ItemInfo& itemInfo); + static void __fastcall __OnExAutoSoulShot_hook(GameEngine* This, uint32_t /*edx*/, L2ParamStack& stack); + static void __fastcall __Tick_hook(GameEngine* This, uint32_t /*edx*/, float_t unk); private: - static void* originalInitAddress; static GameEngine* _target; }; } \ No newline at end of file diff --git a/L2BotDll/Versions/Interlude/Repositories/ItemRepository.h b/L2BotDll/Versions/Interlude/Repositories/ItemRepository.h index 652a5bd..bc4ebf8 100644 --- a/L2BotDll/Versions/Interlude/Repositories/ItemRepository.h +++ b/L2BotDll/Versions/Interlude/Repositories/ItemRepository.h @@ -12,6 +12,7 @@ #include "../../../Events/ItemDeletedEvent.h" #include "../../../Events/HeroDeletedEvent.h" #include "../../../Events/ItemAutousedEvent.h" +#include "../../../Events/GameEngineTickedEvent.h" #include "../../../Events/EventDispatcher.h" using namespace L2Bot::Domain; @@ -65,8 +66,32 @@ namespace Interlude EventDispatcher::GetInstance().Subscribe(ItemAutousedEvent::name, [this](const Event& evt) { OnItemAutoused(evt); }); + EventDispatcher::GetInstance().Subscribe(GameEngineTickedEvent::name, [this](const Event& evt) { + OnGameEngineTicked(evt); + }); } + void OnGameEngineTicked(const Event& evt) + { + std::shared_lock(m_Mutex); + if (evt.GetName() == GameEngineTickedEvent::name) + { + for (auto it = m_Items.begin(); it != m_Items.end();) + { + if (m_NewItems.find(it->first) == m_NewItems.end()) + { + it = m_Items.erase(it); + } + else + { + ++it; + } + } + + m_IsNewCycle = true; + } + } + void OnHeroDeleted(const Event& evt) { std::shared_lock(m_Mutex); @@ -87,11 +112,11 @@ namespace Interlude const auto itemId = data[0]; const bool isEnabled = data[1] > 0; - for (const auto& item : m_Items) + for (const auto& kvp : m_Items) { - if (item.second->GetItemId() == itemId) + if (kvp.second->GetItemId() == itemId) { - auto ptr = dynamic_cast(item.second.get()); + auto ptr = dynamic_cast(kvp.second.get()); if (ptr) { ptr->Autouse(isEnabled); @@ -101,12 +126,17 @@ namespace Interlude } } - //todo need to delete items if they are not exists in create "queue" void OnItemCreated(const Event& evt) { std::shared_lock(m_Mutex); if (evt.GetName() == ItemCreatedEvent::name) { + if (m_IsNewCycle) + { + m_IsNewCycle = false; + m_NewItems.clear(); + } + const auto casted = static_cast(evt); const auto& data = casted.GetItemData(); @@ -120,6 +150,7 @@ namespace Interlude // When equip/unequip accessories m_Items[data.objectId]->Update(item.get()); } + m_NewItems[data.objectId] = data.objectId; } } @@ -163,12 +194,16 @@ namespace Interlude void Reset() override { std::shared_lock(m_Mutex); + m_IsNewCycle = false; + m_NewItems.clear(); m_Items.clear(); } private: const ItemFactory& m_Factory; std::map> m_Items; + std::map m_NewItems; + bool m_IsNewCycle = true; uint32_t m_UsedSkillId = 0; const NetworkHandlerWrapper& m_NetworkHandler; std::shared_timed_mutex m_Mutex; diff --git a/L2BotDll/Versions/Interlude/Repositories/SkillRepository.h b/L2BotDll/Versions/Interlude/Repositories/SkillRepository.h index adeef40..09a18f3 100644 --- a/L2BotDll/Versions/Interlude/Repositories/SkillRepository.h +++ b/L2BotDll/Versions/Interlude/Repositories/SkillRepository.h @@ -10,6 +10,7 @@ #include "../../../Events/SkillCancelledEvent.h" #include "../../../Events/AbnormalEffectChangedEvent.h" #include "../../../Events/HeroDeletedEvent.h" +#include "../../../Events/GameEngineTickedEvent.h" #include "../../../Events/EventDispatcher.h" #include "../GameStructs/NetworkHandlerWrapper.h" #include "../../../Common/TimerMap.h" @@ -66,6 +67,9 @@ namespace Interlude EventDispatcher::GetInstance().Subscribe(HeroDeletedEvent::name, [this](const Event& evt) { OnHeroDeleted(evt); }); + EventDispatcher::GetInstance().Subscribe(GameEngineTickedEvent::name, [this](const Event& evt) { + OnGameEngineTicked(evt); + }); } SkillRepository() = delete; @@ -78,6 +82,29 @@ namespace Interlude { std::shared_lock(m_Mutex); m_Skills.clear(); + m_IsNewCycle = false; + m_NewSkills.clear(); + } + + void OnGameEngineTicked(const Event& evt) + { + std::shared_lock(m_Mutex); + if (evt.GetName() == GameEngineTickedEvent::name) + { + for (auto it = m_Skills.begin(); it != m_Skills.end();) + { + if (m_NewSkills.find(it->first) == m_NewSkills.end()) + { + it = m_Skills.erase(it); + } + else + { + ++it; + } + } + + m_IsNewCycle = true; + } } void OnHeroDeleted(const Event& evt) @@ -97,6 +124,12 @@ namespace Interlude std::shared_lock(m_Mutex); if (evt.GetName() == SkillCreatedEvent::name) { + if (m_IsNewCycle) + { + m_IsNewCycle = false; + m_NewSkills.clear(); + } + const auto casted = static_cast(evt); const auto skillInfo = casted.GetSkillInfo(); const auto skillId = skillInfo[2]; @@ -115,6 +148,7 @@ namespace Interlude { m_Skills[skillId]->UpdateLevel(skillInfo[1]); } + m_NewSkills[skillId] = skillId; } } void OnSkillUsed(const Event& evt) @@ -213,6 +247,8 @@ namespace Interlude private: const SkillFactory& m_Factory; std::map> m_Skills; + std::map m_NewSkills; + bool m_IsNewCycle = true; uint32_t m_UsedSkillId = 0; const NetworkHandlerWrapper& m_NetworkHandler; TimerMap m_ReloadingTimers;