diff --git a/zone/client.cpp b/zone/client.cpp index f53e4997a..9dd8c9969 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9726,16 +9726,10 @@ bool Client::HasExpeditionLockout( void Client::LoadAllExpeditionLockouts() { - auto results = ExpeditionDatabase::LoadCharacterLockouts(CharacterID()); - if (results.Success()) + auto lockouts = ExpeditionDatabase::LoadCharacterLockouts(CharacterID()); + for (const auto& lockout : lockouts) { - for (auto row = results.begin(); row != results.end(); ++row) - { - auto expire_time = strtoull(row[0], nullptr, 10); - auto original_duration = static_cast(strtoul(row[1], nullptr, 10)); - ExpeditionLockoutTimer lockout{ row[2], row[3], expire_time, original_duration }; - AddExpeditionLockout(lockout, false, false); - } + AddExpeditionLockout(lockout, false, false); } SendExpeditionLockoutTimers(); } diff --git a/zone/expedition_database.cpp b/zone/expedition_database.cpp index 27b634acf..2e0816d97 100644 --- a/zone/expedition_database.cpp +++ b/zone/expedition_database.cpp @@ -94,33 +94,51 @@ MySQLRequestResult ExpeditionDatabase::LoadAllExpeditions() return database.QueryDatabase(query); } -MySQLRequestResult ExpeditionDatabase::LoadCharacterLockouts(uint32_t character_id) +std::vector ExpeditionDatabase::LoadCharacterLockouts(uint32_t character_id) { LogExpeditionsDetail("Loading character [{}] lockouts", character_id); + std::vector lockouts; + auto query = fmt::format(SQL( SELECT - UNIX_TIMESTAMP(expire_time), - duration, expedition_name, - event_name + event_name, + UNIX_TIMESTAMP(expire_time), + duration FROM expedition_character_lockouts WHERE character_id = {} AND is_pending = FALSE AND expire_time > NOW(); ), character_id); - return database.QueryDatabase(query); + auto results = database.QueryDatabase(query); + if (results.Success()) + { + for (auto row = results.begin(); row != results.end(); ++row) + { + lockouts.emplace_back(ExpeditionLockoutTimer{ + row[0], // expedition_name + row[1], // event_name + strtoull(row[2], nullptr, 10), // expire_time + static_cast(strtoul(row[3], nullptr, 10)) // duration + }); + } + } + + return lockouts; } -MySQLRequestResult ExpeditionDatabase::LoadCharacterLockouts( +std::vector ExpeditionDatabase::LoadCharacterLockouts( uint32_t character_id, const std::string& expedition_name) { LogExpeditionsDetail("Loading character [{}] lockouts for [{}]", character_id, expedition_name); + std::vector lockouts; + auto query = fmt::format(SQL( SELECT + event_name, UNIX_TIMESTAMP(expire_time), - duration, - event_name + duration FROM expedition_character_lockouts WHERE character_id = {} @@ -129,7 +147,21 @@ MySQLRequestResult ExpeditionDatabase::LoadCharacterLockouts( AND expedition_name = '{}'; ), character_id, expedition_name); - return database.QueryDatabase(query); + auto results = database.QueryDatabase(query); + if (results.Success()) + { + for (auto row = results.begin(); row != results.end(); ++row) + { + lockouts.emplace_back(ExpeditionLockoutTimer{ + expedition_name, + row[0], // event_name + strtoull(row[1], nullptr, 10), // expire_time + static_cast(strtoul(row[2], nullptr, 10)) // duration + }); + } + } + + return lockouts; } std::unordered_map> diff --git a/zone/expedition_database.h b/zone/expedition_database.h index ba9f99c3d..470840225 100644 --- a/zone/expedition_database.h +++ b/zone/expedition_database.h @@ -41,10 +41,10 @@ namespace ExpeditionDatabase std::string LoadExpeditionsSelectQuery(); MySQLRequestResult LoadExpedition(uint32_t expedition_id); MySQLRequestResult LoadAllExpeditions(); - MySQLRequestResult LoadCharacterLockouts(uint32_t character_id); - MySQLRequestResult LoadCharacterLockouts(uint32_t character_id, const std::string& expedition_name); MySQLRequestResult LoadMembersForCreateRequest( const std::vector& character_names, const std::string& expedition_name); + std::vector LoadCharacterLockouts(uint32_t character_id); + std::vector LoadCharacterLockouts(uint32_t character_id, const std::string& expedition_name); std::unordered_map> LoadMultipleExpeditionLockouts(const std::vector& expedition_ids); void DeleteAllCharacterLockouts(uint32_t character_id); diff --git a/zone/expedition_request.cpp b/zone/expedition_request.cpp index 8cc0eead0..1f9375153 100644 --- a/zone/expedition_request.cpp +++ b/zone/expedition_request.cpp @@ -116,7 +116,6 @@ bool ExpeditionRequest::CanGroupRequest(Group* group) m_leader_name = m_leader ? m_leader->GetName() : GetGroupLeaderName(group->GetID()); // group->GetLeaderName(); m_leader_id = m_leader ? m_leader->CharacterID() : database.GetCharacterID(m_leader_name.c_str()); - uint32_t count = 0; std::vector member_names; for (int i = 0; i < MAX_GROUP_MEMBERS; ++i) { @@ -163,20 +162,13 @@ bool ExpeditionRequest::ValidateMembers(const std::vector& member_n bool ExpeditionRequest::LoadLeaderLockouts() { // leader's lockouts are used to check member conflicts and later stored in expedition - auto results = ExpeditionDatabase::LoadCharacterLockouts(m_leader_id, m_expedition_name); - if (!results.Success()) - { - LogExpeditions("Failed to load leader id [{}] lockouts ([{}])", m_leader_id, m_leader_name); - return false; - } + auto lockouts = ExpeditionDatabase::LoadCharacterLockouts(m_leader_id, m_expedition_name); auto leeway_seconds = static_cast(RuleI(Expedition, RequestExpiredLockoutLeewaySeconds)); - for (auto row = results.begin(); row != results.end(); ++row) + for (auto& lockout : lockouts) { - uint64_t expire_time = strtoull(row[0], nullptr, 10); - uint32_t duration = strtoul(row[1], nullptr, 10); - ExpeditionLockoutTimer lockout{m_expedition_name, row[2], expire_time, duration, true}; + lockout.SetInherited(true); // client window hides timers with less than 60s remaining, optionally count them as expired if (lockout.GetSecondsRemaining() <= leeway_seconds) @@ -188,10 +180,10 @@ bool ExpeditionRequest::LoadLeaderLockouts() } else { - m_lockouts.emplace(row[2], lockout); + m_lockouts.emplace(lockout.GetEventName(), lockout); // on live if leader has a replay lockout it never bothers checking for event conflicts - if (m_check_event_lockouts && m_has_replay_timer && strcmp(row[2], DZ_REPLAY_TIMER_NAME) == 0) + if (m_check_event_lockouts && m_has_replay_timer && lockout.IsReplayTimer()) { m_check_event_lockouts = false; } @@ -256,10 +248,9 @@ bool ExpeditionRequest::CheckMembersForConflicts(const std::vector& if (row[3] && row[4] && row[5]) { auto expire_time = strtoull(row[3], nullptr, 10); - auto original_duration = strtoul(row[4], nullptr, 10); - std::string event_name(row[5]); + auto duration = static_cast(strtoul(row[4], nullptr, 10)); - ExpeditionLockoutTimer lockout(m_expedition_name, event_name, expire_time, original_duration); + ExpeditionLockoutTimer lockout{m_expedition_name, row[5], expire_time, duration}; // client window hides timers with less than 60s remaining, optionally count them as expired if (lockout.GetSecondsRemaining() <= leeway_seconds) @@ -272,14 +263,14 @@ bool ExpeditionRequest::CheckMembersForConflicts(const std::vector& else { // replay timer conflict messages always show up before event conflicts - if (/*m_has_replay_timer && */event_name == DZ_REPLAY_TIMER_NAME) + if (/*m_has_replay_timer && */lockout.IsReplayTimer()) { has_conflicts = true; SendLeaderMemberReplayLockout(character_name, lockout, is_solo); } else if (m_check_event_lockouts && character_id != m_leader_id) { - if (m_lockouts.find(event_name) == m_lockouts.end()) + if (m_lockouts.find(lockout.GetEventName()) == m_lockouts.end()) { // leader doesn't have this lockout. queue instead of messaging // now so message comes after any replay lockout messages