From 4dcacc733f69dba5f5bd9ff5bbc21036b5053d15 Mon Sep 17 00:00:00 2001 From: Egor Gavrilov <55379903+che6a@users.noreply.github.com> Date: Sat, 30 Sep 2023 01:45:25 +0500 Subject: [PATCH] feat(skymp5-server): add id to timers (#1622) --- .../server_guest_lib/ActiveMagicEffectsMap.h | 1 + .../cpp/server_guest_lib/MpActor.cpp | 22 +++---- .../cpp/server_guest_lib/WorldState.cpp | 22 +++---- .../cpp/server_guest_lib/WorldState.h | 13 ++-- viet/CMakeLists.txt | 2 + viet/include/Timer.h | 15 +++-- viet/src/Timer.cpp | 60 ++++++++++++------- 7 files changed, 75 insertions(+), 60 deletions(-) diff --git a/skymp5-server/cpp/server_guest_lib/ActiveMagicEffectsMap.h b/skymp5-server/cpp/server_guest_lib/ActiveMagicEffectsMap.h index 0ec633e8d6..0565491ffa 100644 --- a/skymp5-server/cpp/server_guest_lib/ActiveMagicEffectsMap.h +++ b/skymp5-server/cpp/server_guest_lib/ActiveMagicEffectsMap.h @@ -11,6 +11,7 @@ class ActiveMagicEffectsMap public: struct Entry { + uint32_t timerId = -1; espm::Effects::Effect data; std::chrono::system_clock::time_point endTime; }; diff --git a/skymp5-server/cpp/server_guest_lib/MpActor.cpp b/skymp5-server/cpp/server_guest_lib/MpActor.cpp index e395dbf0ae..6b94964795 100644 --- a/skymp5-server/cpp/server_guest_lib/MpActor.cpp +++ b/skymp5-server/cpp/server_guest_lib/MpActor.cpp @@ -835,10 +835,8 @@ void MpActor::ApplyMagicEffect(espm::Effects::Effect& effect, bool hasSweetpie, } if (isRate || isMult) { - if (hasSweetpie) { - if (!CanActorValueBeRestored(av)) { - return; - } + if (hasSweetpie && !CanActorValueBeRestored(av)) { + return; } MpChangeForm changeForm = GetChangeForm(); BaseActorValues baseValues = @@ -868,11 +866,18 @@ void MpActor::ApplyMagicEffect(espm::Effects::Effect& effect, bool hasSweetpie, duration = Viet::TimeUtils::To(effect.duration); } - ActiveMagicEffectsMap::Entry entry{ effect, endTime }; + uint32_t timerId; + worldState->SetEffectTimer(duration, &timerId) + .Then([formId, actorValue = av, worldState](Viet::Void) { + auto& actor = worldState->GetFormAt(formId); + actor.RemoveMagicEffect(actorValue); + }); + + ActiveMagicEffectsMap::Entry entry{ timerId, effect, endTime }; if (activeEffects.Has(av)) { const ActiveMagicEffectsMap::Entry& entry = activeEffects.Get(av).value().get(); - worldState->RemoveEffectTimer(entry.endTime); + worldState->RemoveEffectTimer(entry.timerId); } EditChangeForm([av, pEntry = &entry](MpChangeForm& changeForm) { changeForm.activeMagicEffects.Add(av, *pEntry); @@ -898,11 +903,6 @@ void MpActor::ApplyMagicEffect(espm::Effects::Effect& effect, bool hasSweetpie, mult, baseValue * mult); SetActorValue(av, baseValue * mult); } - worldState->SetEffectTimer(std::cref(endTime)) - .Then([formId, actorValue = av, worldState](Viet::Void) { - auto& actor = worldState->GetFormAt(formId); - actor.RemoveMagicEffect(actorValue); - }); } } diff --git a/skymp5-server/cpp/server_guest_lib/WorldState.cpp b/skymp5-server/cpp/server_guest_lib/WorldState.cpp index 153a50351b..e740907b11 100644 --- a/skymp5-server/cpp/server_guest_lib/WorldState.cpp +++ b/skymp5-server/cpp/server_guest_lib/WorldState.cpp @@ -219,18 +219,6 @@ void WorldState::RequestSave(MpObjectReference& ref) } } -Viet::Promise WorldState::SetTimer( - std::reference_wrapper wrapper) -{ - return timerRegular.SetTimer(wrapper.get()); -} - -Viet::Promise WorldState::SetEffectTimer( - std::reference_wrapper wrapper) -{ - return timerEffects.SetTimer(wrapper.get()); -} - const std::shared_ptr& WorldState::LookupFormById(uint32_t formId) { static const std::shared_ptr kNullForm; @@ -810,10 +798,14 @@ void WorldState::SetNpcSettings( npcSettings = settings; } -bool WorldState::RemoveEffectTimer( - const std::chrono::system_clock::time_point& endTime) +bool WorldState::RemoveTimer(uint32_t timerId) +{ + return timerRegular.RemoveTimer(timerId); +} + +bool WorldState::RemoveEffectTimer(uint32_t timerId) { - return timerEffects.RemoveTimer(endTime); + return timerEffects.RemoveTimer(timerId); } void WorldState::SetForbiddenRelootTypes(const std::set& types) diff --git a/skymp5-server/cpp/server_guest_lib/WorldState.h b/skymp5-server/cpp/server_guest_lib/WorldState.h index a88254354d..cdfa791ce9 100644 --- a/skymp5-server/cpp/server_guest_lib/WorldState.h +++ b/skymp5-server/cpp/server_guest_lib/WorldState.h @@ -76,15 +76,17 @@ class WorldState bool HasEspmFile(std::string_view filename) const noexcept; template - Viet::Promise SetTimer(T&& duration) + Viet::Promise SetTimer(T&& duration, + uint32_t* outTimerId = nullptr) { - return timerRegular.SetTimer(std::forward(duration)); + return timerRegular.SetTimer(std::forward(duration), outTimerId); } template - Viet::Promise SetEffectTimer(T&& duration) + Viet::Promise SetEffectTimer(T&& duration, + uint32_t* outTimerId = nullptr) { - return timerEffects.SetTimer(std::forward(duration)); + return timerEffects.SetTimer(std::forward(duration), outTimerId); } template @@ -97,13 +99,14 @@ class WorldState }); } + bool RemoveTimer(uint32_t timerId); Viet::Promise SetTimer( std::reference_wrapper wrapper); Viet::Promise SetEffectTimer( std::reference_wrapper wrapper); - bool RemoveEffectTimer(const std::chrono::system_clock::time_point& endTime); + bool RemoveEffectTimer(uint32_t timerId); const std::shared_ptr& LookupFormById(uint32_t formId); diff --git a/viet/CMakeLists.txt b/viet/CMakeLists.txt index 29c3c23cc0..d66b47fc07 100644 --- a/viet/CMakeLists.txt +++ b/viet/CMakeLists.txt @@ -1,7 +1,9 @@ include(${CMAKE_SOURCE_DIR}/cmake/apply_default_settings.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/link_vcpkg_dependencies.cmake) file(GLOB_RECURSE viet_sources "${CMAKE_CURRENT_SOURCE_DIR}/src/*" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") add_library(viet STATIC ${viet_sources}) target_include_directories(viet PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src") target_include_directories(viet PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") apply_default_settings(TARGETS viet) +link_vcpkg_dependencies(TARGETS viet) diff --git a/viet/include/Timer.h b/viet/include/Timer.h index 2ed19c6528..d496a75d2a 100644 --- a/viet/include/Timer.h +++ b/viet/include/Timer.h @@ -3,30 +3,29 @@ #include namespace Viet { + class Timer { public: Timer(); template - Viet::Promise SetTimer(T&& duration) + Promise SetTimer(T&& duration, uint32_t* outTimerId) { auto endTime = std::chrono::system_clock::now() + duration; - return Set(endTime); + return Set(endTime, outTimerId); }; - Viet::Promise SetTimer( - const std::chrono::system_clock::time_point& endTime); - [[maybe_unused]] bool RemoveTimer( - const std::chrono::system_clock::time_point& endTime); + [[maybe_unused]] bool RemoveTimer(uint32_t timerId); void TickTimers(); private: - Viet::Promise Set( - const std::chrono::system_clock::time_point& endTime); + Promise Set(const std::chrono::system_clock::time_point& endTime, + uint32_t* outTimerId); private: struct Impl; std::shared_ptr pImpl; }; + } diff --git a/viet/src/Timer.cpp b/viet/src/Timer.cpp index 4c719e99e9..ceb4963d78 100644 --- a/viet/src/Timer.cpp +++ b/viet/src/Timer.cpp @@ -1,34 +1,44 @@ #include "Timer.h" +#include #include #include #include +#include +#include +#include #include +namespace Viet { + namespace { struct TimerEntry { - Viet::Promise promise; + uint32_t id; + Promise promise; std::chrono::system_clock::time_point finish; }; } -struct Viet::Timer::Impl +struct Timer::Impl { std::deque timers; + const std::unique_ptr idGenerator = + std::make_unique(std::numeric_limits::max()); + + void DestroyID(const TimerEntry& entry); }; -Viet::Timer::Timer() +void Timer::Impl::DestroyID(const TimerEntry& entry) { - pImpl = std::make_shared(); + idGenerator->DestroyID(entry.id); } -Viet::Promise Viet::Timer::SetTimer( - const std::chrono::system_clock::time_point& endTime) +Timer::Timer() { - return Set(endTime); + pImpl = std::make_shared(); } -void Viet::Timer::TickTimers() +void Timer::TickTimers() { auto now = std::chrono::system_clock::now(); @@ -36,20 +46,17 @@ void Viet::Timer::TickTimers() while (!timers.empty() && now >= timers.front().finish) { auto front = std::move(timers.front()); timers.pop_front(); - front.promise.Resolve(Viet::Void()); + front.promise.Resolve(Void()); + pImpl->DestroyID(front); } } -bool Viet::Timer::RemoveTimer( - const std::chrono::system_clock::time_point& endTime) +bool Timer::RemoveTimer(const uint32_t timerId) { auto& timers = pImpl->timers; - auto it = - std::lower_bound(timers.begin(), timers.end(), endTime, - [](const TimerEntry& entry, - const std::chrono::system_clock::time_point& target) { - return entry.finish < target; - }); + auto it = std::find_if( + timers.begin(), timers.end(), + [timerId](const TimerEntry& entry) { return entry.id == timerId; }); if (it != timers.end()) { timers.erase(it); return true; @@ -57,14 +64,23 @@ bool Viet::Timer::RemoveTimer( return false; } -Viet::Promise Viet::Timer::Set( - const std::chrono::system_clock::time_point& endTime) +Promise Timer::Set(const std::chrono::system_clock::time_point& endTime, + uint32_t* outTimerId) { - Viet::Promise promise; + Promise promise; bool sortRequired = !pImpl->timers.empty() && endTime > pImpl->timers.front().finish; - pImpl->timers.push_front({ promise, endTime }); + uint32_t timerId; + bool created = pImpl->idGenerator->CreateID(timerId); + if (!created) { + spdlog::critical("MakeID was not able to Create Id for a timer"); + std::terminate(); + } + pImpl->timers.push_front({ timerId, promise, endTime }); + if (outTimerId) { + *outTimerId = timerId; + } if (sortRequired) { std::sort(pImpl->timers.begin(), pImpl->timers.end(), @@ -74,3 +90,5 @@ Viet::Promise Viet::Timer::Set( } return promise; } + +}