From f9eafa52f961998de0235148bb4ed6285ebe9169 Mon Sep 17 00:00:00 2001 From: hg <4683435+hgtw@users.noreply.github.com> Date: Mon, 1 Jun 2020 18:21:12 -0400 Subject: [PATCH] Ignore expired lockouts on expedition invite This fixes an edge case with client invites sometimes failing because an expired lockout hasn't been removed from client yet Clients no longer receive expired lockouts from expeditions when joining --- zone/client.cpp | 30 ++++++++++++++++-------------- zone/client.h | 5 +++-- zone/expedition.cpp | 6 +++--- zone/expedition_lockout_timer.h | 2 +- zone/expedition_request.cpp | 16 ++++++++++------ 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index e946559ed..f53e4997a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9613,19 +9613,6 @@ Expedition* Client::GetExpedition() const return nullptr; } -std::vector Client::GetExpeditionLockouts(const std::string& expedition_name) -{ - std::vector lockouts; - for (const auto& lockout : m_expedition_lockouts) - { - if (lockout.GetExpeditionName() == expedition_name) - { - lockouts.emplace_back(lockout); - } - } - return lockouts; -} - void Client::AddExpeditionLockout(const ExpeditionLockoutTimer& lockout, bool update_db, bool update_client) { // todo: support for account based lockouts like live AoC expeditions @@ -9707,7 +9694,7 @@ const ExpeditionLockoutTimer* Client::GetExpeditionLockout( { for (const auto& expedition_lockout : m_expedition_lockouts) { - if ((include_expired || expedition_lockout.GetSecondsRemaining() > 0) && + if ((include_expired || !expedition_lockout.IsExpired()) && expedition_lockout.IsSameLockout(expedition_name, event_name)) { return &expedition_lockout; @@ -9716,6 +9703,21 @@ const ExpeditionLockoutTimer* Client::GetExpeditionLockout( return nullptr; } +std::vector Client::GetExpeditionLockouts( + const std::string& expedition_name, bool include_expired) +{ + std::vector lockouts; + for (const auto& lockout : m_expedition_lockouts) + { + if ((include_expired || !lockout.IsExpired()) && + lockout.GetExpeditionName() == expedition_name) + { + lockouts.emplace_back(lockout); + } + } + return lockouts; +} + bool Client::HasExpeditionLockout( const std::string& expedition_name, const std::string& event_name, bool include_expired) { diff --git a/zone/client.h b/zone/client.h index c12f5f26b..09b2f8020 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1128,12 +1128,13 @@ public: const ExpeditionLockoutTimer* GetExpeditionLockout( const std::string& expedition_name, const std::string& event_name, bool include_expired = false) const; const std::vector& GetExpeditionLockouts() const { return m_expedition_lockouts; }; - std::vector GetExpeditionLockouts(const std::string& expedition_name); + std::vector GetExpeditionLockouts(const std::string& expedition_name, bool include_expired = false); uint32 GetPendingExpeditionInviteID() const { return m_pending_expedition_invite.expedition_id; } bool HasExpeditionLockout(const std::string& expedition_name, const std::string& event_name, bool include_expired = false); bool IsInExpedition() const { return m_expedition_id != 0; } void RemoveAllExpeditionLockouts(std::string expedition_name = {}); - void RemoveExpeditionLockout(const std::string& expedition_name, const std::string& event_name, bool update_db = false, bool update_client = true); + void RemoveExpeditionLockout( + const std::string& expedition_name, const std::string& event_name, bool update_db = false, bool update_client = true); void RequestPendingExpeditionInvite(); void SendExpeditionLockoutTimers(); void SetExpeditionID(uint32 expedition_id) { m_expedition_id = expedition_id; }; diff --git a/zone/expedition.cpp b/zone/expedition.cpp index 5057bcaa3..d326131b3 100644 --- a/zone/expedition.cpp +++ b/zone/expedition.cpp @@ -613,7 +613,7 @@ void Expedition::SendClientExpeditionInvite( { // live doesn't issue a warning for the dz's replay timer const ExpeditionLockoutTimer& lockout = lockout_iter.second; - if (!lockout.IsInherited() && !lockout.IsReplayTimer() && + if (!lockout.IsInherited() && !lockout.IsExpired() && !lockout.IsReplayTimer() && !client->HasExpeditionLockout(m_expedition_name, lockout.GetEventName())) { if (!warned) @@ -680,7 +680,7 @@ bool Expedition::ProcessAddConflicts(Client* leader_client, Client* add_client, } } - // check any extra event lockouts for this expedition that the client has and leader doesn't + // check any extra event lockouts for this expedition that the client has and expedition doesn't auto client_lockouts = add_client->GetExpeditionLockouts(m_expedition_name); for (const auto& client_lockout : client_lockouts) { @@ -776,7 +776,7 @@ void Expedition::DzInviteResponse(Client* add_client, bool accepted, const std:: for (const auto& lockout_iter : m_lockouts) { const ExpeditionLockoutTimer& lockout = lockout_iter.second; - if (!lockout.IsInherited() && + if (!lockout.IsInherited() && !lockout.IsExpired() && !add_client->HasExpeditionLockout(m_expedition_name, lockout.GetEventName())) { // replay timers are optionally added to new members immediately on diff --git a/zone/expedition_lockout_timer.h b/zone/expedition_lockout_timer.h index ff70864c4..45155a111 100644 --- a/zone/expedition_lockout_timer.h +++ b/zone/expedition_lockout_timer.h @@ -25,7 +25,6 @@ extern const char* const DZ_REPLAY_TIMER_NAME; -// DynamicZoneEventTimer and DynamicZoneReplayTimer in client class ExpeditionLockoutTimer { public: @@ -47,6 +46,7 @@ public: const std::string& GetEventName() const { return m_event_name; } void SetExpireTime(uint64_t expire_time) { m_expire_time = expire_time; } void SetInherited(bool is_inherited) { m_is_inherited = is_inherited; } + bool IsExpired() const { return GetSecondsRemaining() == 0; } bool IsInherited() const { return m_is_inherited; } bool IsReplayTimer() const { return m_is_replay_timer; } bool IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const; diff --git a/zone/expedition_request.cpp b/zone/expedition_request.cpp index 77bdaa884..0474c18e6 100644 --- a/zone/expedition_request.cpp +++ b/zone/expedition_request.cpp @@ -194,6 +194,8 @@ bool ExpeditionRequest::LoadLeaderLockouts() return false; } + auto leeway_seconds = static_cast(RuleI(Expedition, RequestExpiredLockoutLeewaySeconds)); + for (auto row = results.begin(); row != results.end(); ++row) { uint64_t expire_time = strtoull(row[0], nullptr, 10); @@ -201,11 +203,11 @@ bool ExpeditionRequest::LoadLeaderLockouts() ExpeditionLockoutTimer lockout{m_expedition_name, row[2], expire_time, duration, true}; // client window hides timers with less than 60s remaining, optionally count them as expired - if (lockout.GetSecondsRemaining() <= RuleI(Expedition, RequestExpiredLockoutLeewaySeconds)) + if (lockout.GetSecondsRemaining() <= leeway_seconds) { LogExpeditionsModerate( - "Ignoring leader [{}] lockout [{}] with [{}] seconds remaining due to expired leeway rule", - m_leader_id, lockout.GetEventName(), lockout.GetSecondsRemaining() + "Ignoring leader [{}] lockout [{}] with [{}s] remaining due to leeway rule [{}s]", + m_leader_id, lockout.GetEventName(), lockout.GetSecondsRemaining(), leeway_seconds ); } else @@ -230,6 +232,8 @@ bool ExpeditionRequest::CheckMembersForConflicts(MySQLRequestResult& results, bo std::vector member_lockout_conflicts; + auto leeway_seconds = static_cast(RuleI(Expedition, RequestExpiredLockoutLeewaySeconds)); + bool leader_processed = false; uint32_t last_character_id = 0; for (auto row = results.begin(); row != results.end(); ++row) @@ -275,11 +279,11 @@ bool ExpeditionRequest::CheckMembersForConflicts(MySQLRequestResult& results, bo ExpeditionLockoutTimer lockout(m_expedition_name, event_name, expire_time, original_duration); // client window hides timers with less than 60s remaining, optionally count them as expired - if (lockout.GetSecondsRemaining() <= RuleI(Expedition, RequestExpiredLockoutLeewaySeconds)) + if (lockout.GetSecondsRemaining() <= leeway_seconds) { LogExpeditionsModerate( - "Ignoring character [{}] lockout [{}] with [{}] seconds remaining due to expired leeway rule", - character_id, lockout.GetEventName(), lockout.GetSecondsRemaining() + "Ignoring character [{}] lockout [{}] with [{}s] remaining due to leeway rule [{}s]", + character_id, lockout.GetEventName(), lockout.GetSecondsRemaining(), leeway_seconds ); } else