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
This commit is contained in:
hg 2020-06-01 18:21:12 -04:00
parent 4284624096
commit f9eafa52f9
5 changed files with 33 additions and 26 deletions

View File

@ -9613,19 +9613,6 @@ Expedition* Client::GetExpedition() const
return nullptr;
}
std::vector<ExpeditionLockoutTimer> Client::GetExpeditionLockouts(const std::string& expedition_name)
{
std::vector<ExpeditionLockoutTimer> 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<ExpeditionLockoutTimer> Client::GetExpeditionLockouts(
const std::string& expedition_name, bool include_expired)
{
std::vector<ExpeditionLockoutTimer> 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)
{

View File

@ -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<ExpeditionLockoutTimer>& GetExpeditionLockouts() const { return m_expedition_lockouts; };
std::vector<ExpeditionLockoutTimer> GetExpeditionLockouts(const std::string& expedition_name);
std::vector<ExpeditionLockoutTimer> 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; };

View File

@ -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

View File

@ -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;

View File

@ -194,6 +194,8 @@ bool ExpeditionRequest::LoadLeaderLockouts()
return false;
}
auto leeway_seconds = static_cast<uint32_t>(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<ExpeditionRequestConflict> member_lockout_conflicts;
auto leeway_seconds = static_cast<uint32_t>(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