mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 06:21:28 +00:00
Sync character lockouts when entering dz
This removes the is_pending column from character lockouts table Synchronizing character lockout timers with the expedition's when zoning into the dynamic zone simplifies adding missing lockouts to new members. This also matches live behavior that replaces any character lockout timers from another expedition with ones from the current expedition
This commit is contained in:
parent
fc7d8a82e5
commit
4f9eaf7574
@ -48,7 +48,6 @@ CREATE TABLE `character_expedition_lockouts` (
|
||||
`expire_time` DATETIME NOT NULL DEFAULT current_timestamp(),
|
||||
`duration` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`from_expedition_uuid` VARCHAR(36) NOT NULL,
|
||||
`is_pending` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `character_id_expedition_name_event_name` (`character_id`, `expedition_name`, `event_name`)
|
||||
)
|
||||
|
||||
@ -9563,16 +9563,18 @@ void Client::UpdateExpeditionInfoAndLockouts()
|
||||
// this is processed by client after entering a zone
|
||||
SendDzCompassUpdate();
|
||||
|
||||
m_expedition_lockouts = ExpeditionDatabase::LoadCharacterLockouts(CharacterID());
|
||||
|
||||
auto expedition = GetExpedition();
|
||||
if (expedition)
|
||||
{
|
||||
expedition->SendClientExpeditionInfo(this);
|
||||
|
||||
// live only adds lockouts obtained during the active expedition to new
|
||||
// live synchronizes lockouts obtained during the active expedition to
|
||||
// members once they zone into the expedition's dynamic zone instance
|
||||
if (expedition->GetDynamicZone().IsCurrentZoneDzInstance())
|
||||
{
|
||||
ExpeditionDatabase::AssignPendingLockouts(CharacterID(), expedition->GetName());
|
||||
expedition->SyncCharacterLockouts(CharacterID(), m_expedition_lockouts);
|
||||
expedition->SetMemberStatus(this, ExpeditionMemberStatus::InDynamicZone);
|
||||
}
|
||||
else
|
||||
@ -9581,7 +9583,7 @@ void Client::UpdateExpeditionInfoAndLockouts()
|
||||
}
|
||||
}
|
||||
|
||||
LoadAllExpeditionLockouts();
|
||||
SendExpeditionLockoutTimers();
|
||||
|
||||
// ask world for any pending invite we saved from a previous zone
|
||||
RequestPendingExpeditionInvite();
|
||||
@ -9629,7 +9631,7 @@ void Client::AddExpeditionLockout(const ExpeditionLockoutTimer& lockout, bool up
|
||||
|
||||
if (update_db) // for quest api
|
||||
{
|
||||
ExpeditionDatabase::InsertCharacterLockouts(CharacterID(), { lockout }, true);
|
||||
ExpeditionDatabase::InsertCharacterLockouts(CharacterID(), { lockout });
|
||||
}
|
||||
|
||||
SendExpeditionLockoutTimers();
|
||||
@ -9662,7 +9664,7 @@ void Client::AddExpeditionLockoutDuration(
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
ExpeditionDatabase::InsertCharacterLockouts(CharacterID(), { *it }, true);
|
||||
ExpeditionDatabase::InsertCharacterLockouts(CharacterID(), { *it });
|
||||
}
|
||||
|
||||
SendExpeditionLockoutTimers();
|
||||
@ -9753,12 +9755,6 @@ bool Client::HasExpeditionLockout(
|
||||
return (GetExpeditionLockout(expedition_name, event_name, include_expired) != nullptr);
|
||||
}
|
||||
|
||||
void Client::LoadAllExpeditionLockouts()
|
||||
{
|
||||
m_expedition_lockouts = ExpeditionDatabase::LoadCharacterLockouts(CharacterID());
|
||||
SendExpeditionLockoutTimers();
|
||||
}
|
||||
|
||||
void Client::SendExpeditionLockoutTimers()
|
||||
{
|
||||
std::vector<ExpeditionLockoutTimerEntry_Struct> lockout_entries;
|
||||
|
||||
@ -1143,7 +1143,6 @@ public:
|
||||
void SendExpeditionLockoutTimers();
|
||||
void SetExpeditionID(uint32 expedition_id) { m_expedition_id = expedition_id; };
|
||||
void SetPendingExpeditionInvite(ExpeditionInvite&& invite) { m_pending_expedition_invite = invite; }
|
||||
void LoadAllExpeditionLockouts();
|
||||
void UpdateExpeditionInfoAndLockouts();
|
||||
void DzListTimers();
|
||||
void SetDzRemovalTimer(bool enable_timer);
|
||||
|
||||
@ -298,7 +298,6 @@ void Expedition::SaveMembers(ExpeditionRequest& request)
|
||||
}
|
||||
|
||||
ExpeditionDatabase::InsertMembers(m_id, m_members);
|
||||
ExpeditionDatabase::DeleteAllMembersPendingLockouts(m_members);
|
||||
m_dynamiczone.SaveInstanceMembersToDatabase(member_ids);
|
||||
}
|
||||
|
||||
@ -555,7 +554,6 @@ void Expedition::RemoveAllMembers(bool enable_removal_timers)
|
||||
{
|
||||
m_dynamiczone.RemoveAllCharacters(enable_removal_timers);
|
||||
|
||||
ExpeditionDatabase::DeleteAllMembersPendingLockouts(m_members);
|
||||
ExpeditionDatabase::DeleteAllMembers(m_id);
|
||||
|
||||
SendUpdatesToZoneMembers(true);
|
||||
@ -849,39 +847,20 @@ void Expedition::DzInviteResponse(Client* add_client, bool accepted, const std::
|
||||
{
|
||||
SendLeaderMessage(leader_client, Chat::Yellow, EXPEDITION_INVITE_ACCEPTED, { add_client->GetName() });
|
||||
|
||||
// insert pending lockouts client will receive when entering dynamic zone.
|
||||
// only lockouts missing from client when they join are added. client may
|
||||
// have a lockout that expires after joining and shouldn't receive it again
|
||||
ExpeditionDatabase::DeletePendingLockouts(add_client->CharacterID());
|
||||
|
||||
std::vector<ExpeditionLockoutTimer> pending_lockouts;
|
||||
for (const auto& lockout_iter : m_lockouts)
|
||||
// replay timers are optionally added to new members on join with fresh expire time
|
||||
if (m_add_replay_on_join)
|
||||
{
|
||||
const ExpeditionLockoutTimer& lockout = lockout_iter.second;
|
||||
if (lockout.IsFromExpedition(m_uuid) &&
|
||||
!add_client->HasExpeditionLockout(m_expedition_name, lockout.GetEventName()))
|
||||
auto replay_lockout = m_lockouts.find(DZ_REPLAY_TIMER_NAME);
|
||||
if (replay_lockout != m_lockouts.end() &&
|
||||
replay_lockout->second.IsFromExpedition(m_uuid) &&
|
||||
!add_client->HasExpeditionLockout(m_expedition_name, DZ_REPLAY_TIMER_NAME))
|
||||
{
|
||||
// replay timers are optionally added to new members immediately on
|
||||
// join with a fresh expire time using the original duration.
|
||||
if (lockout.IsReplayTimer())
|
||||
{
|
||||
if (m_add_replay_on_join)
|
||||
{
|
||||
ExpeditionLockoutTimer replay_timer = lockout;
|
||||
replay_timer.Reset();
|
||||
add_client->AddExpeditionLockout(replay_timer, true);
|
||||
}
|
||||
}
|
||||
else if (!lockout.IsExpired())
|
||||
{
|
||||
pending_lockouts.emplace_back(lockout);
|
||||
}
|
||||
ExpeditionLockoutTimer replay_timer = replay_lockout->second; // copy
|
||||
replay_timer.Reset();
|
||||
add_client->AddExpeditionLockout(replay_timer, true);
|
||||
}
|
||||
}
|
||||
|
||||
ExpeditionDatabase::InsertCharacterLockouts(
|
||||
add_client->CharacterID(), pending_lockouts, false, true);
|
||||
|
||||
if (was_swap_invite)
|
||||
{
|
||||
SwapMember(add_client, swap_remove_name);
|
||||
@ -1237,7 +1216,6 @@ void Expedition::ProcessMemberRemoved(const std::string& removed_char_name, uint
|
||||
// live doesn't clear expedition info on clients removed while inside dz.
|
||||
// it instead let's the dz kick timer do it even if character zones out
|
||||
// before it triggers. for simplicity we'll always clear immediately
|
||||
ExpeditionDatabase::DeletePendingLockouts(member_client->CharacterID());
|
||||
member_client->SetExpeditionID(0);
|
||||
member_client->SendDzCompassUpdate();
|
||||
member_client->QueuePacket(CreateInfoPacket(true).get());
|
||||
@ -1734,7 +1712,7 @@ void Expedition::AddLockoutByCharacterID(
|
||||
if (character_id)
|
||||
{
|
||||
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds, uuid);
|
||||
ExpeditionDatabase::InsertCharacterLockouts(character_id, { lockout }, true);
|
||||
ExpeditionDatabase::InsertCharacterLockouts(character_id, { lockout });
|
||||
SendWorldCharacterLockout(character_id, lockout, false);
|
||||
}
|
||||
}
|
||||
@ -2256,3 +2234,47 @@ void Expedition::SendMembersExpireWarning(uint32_t minutes_remaining)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Expedition::SyncCharacterLockouts(
|
||||
uint32_t character_id, std::vector<ExpeditionLockoutTimer>& client_lockouts)
|
||||
{
|
||||
// adds missing event lockouts to client for this expedition and replaces
|
||||
// client timers that are both shorter and from another expedition
|
||||
BenchTimer benchmark;
|
||||
|
||||
bool modified = false;
|
||||
|
||||
for (const auto& lockout_iter : m_lockouts)
|
||||
{
|
||||
const ExpeditionLockoutTimer& lockout = lockout_iter.second;
|
||||
if (lockout.IsReplayTimer() || lockout.IsExpired() || lockout.GetExpeditionUUID() != m_uuid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto client_lockout_iter = std::find_if(client_lockouts.begin(), client_lockouts.end(),
|
||||
[&](const ExpeditionLockoutTimer& client_lockout) {
|
||||
return client_lockout.IsSameLockout(lockout);
|
||||
});
|
||||
|
||||
if (client_lockout_iter == client_lockouts.end())
|
||||
{
|
||||
modified = true;
|
||||
client_lockouts.emplace_back(lockout); // insert missing
|
||||
}
|
||||
else if (client_lockout_iter->GetSecondsRemaining() < lockout.GetSecondsRemaining() &&
|
||||
client_lockout_iter->GetExpeditionUUID() != m_uuid)
|
||||
{
|
||||
modified = true;
|
||||
client_lockouts.erase(client_lockout_iter);
|
||||
client_lockouts.emplace_back(lockout); // replaced existing
|
||||
}
|
||||
}
|
||||
|
||||
if (modified)
|
||||
{
|
||||
ExpeditionDatabase::InsertCharacterLockouts(character_id, client_lockouts);
|
||||
}
|
||||
|
||||
LogExpeditionsDetail("Syncing character lockouts with expedition took [{}] s", benchmark.elapsed());
|
||||
}
|
||||
|
||||
@ -136,6 +136,7 @@ public:
|
||||
bool HasReplayLockout();
|
||||
void RemoveLockout(const std::string& event_name);
|
||||
void SetReplayLockoutOnMemberJoin(bool add_on_join, bool update_db = false);
|
||||
void SyncCharacterLockouts(uint32_t character_id, std::vector<ExpeditionLockoutTimer>& client_lockouts);
|
||||
void UpdateLockoutDuration(const std::string& event_name, uint32_t seconds, bool members_only = true);
|
||||
|
||||
bool CanClientLootCorpse(Client* client, uint32_t npc_type_id, uint32_t spawn_id);
|
||||
|
||||
@ -110,7 +110,7 @@ std::vector<ExpeditionLockoutTimer> ExpeditionDatabase::LoadCharacterLockouts(ui
|
||||
UNIX_TIMESTAMP(expire_time),
|
||||
duration
|
||||
FROM character_expedition_lockouts
|
||||
WHERE character_id = {} AND is_pending = FALSE AND expire_time > NOW();
|
||||
WHERE character_id = {} AND expire_time > NOW();
|
||||
), character_id);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
@ -147,7 +147,6 @@ std::vector<ExpeditionLockoutTimer> ExpeditionDatabase::LoadCharacterLockouts(
|
||||
FROM character_expedition_lockouts
|
||||
WHERE
|
||||
character_id = {}
|
||||
AND is_pending = FALSE
|
||||
AND expire_time > NOW()
|
||||
AND expedition_name = '{}';
|
||||
), character_id, EscapeString(expedition_name));
|
||||
@ -250,7 +249,6 @@ MySQLRequestResult ExpeditionDatabase::LoadMembersForCreateRequest(
|
||||
FROM character_data
|
||||
LEFT JOIN character_expedition_lockouts lockout
|
||||
ON character_data.id = lockout.character_id
|
||||
AND lockout.is_pending = FALSE
|
||||
AND lockout.expire_time > NOW()
|
||||
AND lockout.expedition_name = '{}'
|
||||
LEFT JOIN expedition_members member ON character_data.id = member.character_id
|
||||
@ -306,7 +304,6 @@ void ExpeditionDatabase::DeleteCharacterLockout(
|
||||
DELETE FROM character_expedition_lockouts
|
||||
WHERE
|
||||
character_id = {}
|
||||
AND is_pending = FALSE
|
||||
AND expedition_name = '{}'
|
||||
AND event_name = '{}';
|
||||
), character_id, EscapeString(expedition_name), EscapeString(event_name));
|
||||
@ -334,7 +331,6 @@ void ExpeditionDatabase::DeleteMembersLockout(
|
||||
DELETE FROM character_expedition_lockouts
|
||||
WHERE character_id
|
||||
IN ({})
|
||||
AND is_pending = FALSE
|
||||
AND expedition_name = '{}'
|
||||
AND event_name = '{}';
|
||||
), query_character_ids, EscapeString(expedition_name), EscapeString(event_name));
|
||||
@ -343,57 +339,6 @@ void ExpeditionDatabase::DeleteMembersLockout(
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::AssignPendingLockouts(uint32_t character_id, const std::string& expedition_name)
|
||||
{
|
||||
LogExpeditionsDetail("Assigning character [{}] pending lockouts [{}]", character_id, expedition_name);
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
UPDATE character_expedition_lockouts
|
||||
SET is_pending = FALSE
|
||||
WHERE
|
||||
character_id = {}
|
||||
AND is_pending = TRUE
|
||||
AND expedition_name = '{}';
|
||||
), character_id, EscapeString(expedition_name));
|
||||
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::DeletePendingLockouts(uint32_t character_id)
|
||||
{
|
||||
LogExpeditionsDetail("Deleting character [{}] pending lockouts", character_id);
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
DELETE FROM character_expedition_lockouts
|
||||
WHERE character_id = {} AND is_pending = TRUE;
|
||||
), character_id);
|
||||
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::DeleteAllMembersPendingLockouts(const std::vector<ExpeditionMember>& members)
|
||||
{
|
||||
LogExpeditionsDetail("Deleting pending lockouts for [{}] characters", members.size());
|
||||
|
||||
std::string query_character_ids;
|
||||
for (const auto& member : members)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(query_character_ids), "{},", member.char_id);
|
||||
}
|
||||
|
||||
if (!query_character_ids.empty())
|
||||
{
|
||||
query_character_ids.pop_back(); // trailing comma
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
DELETE FROM character_expedition_lockouts
|
||||
WHERE character_id IN ({}) AND is_pending = TRUE;
|
||||
), query_character_ids);
|
||||
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::DeleteLockout(uint32_t expedition_id, const std::string& event_name)
|
||||
{
|
||||
LogExpeditionsDetail("Deleting expedition [{}] lockout event [{}]", expedition_id, event_name);
|
||||
@ -424,9 +369,8 @@ uint32_t ExpeditionDatabase::GetExpeditionIDFromCharacterID(uint32_t character_i
|
||||
return expedition_id;
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::InsertCharacterLockouts(
|
||||
uint32_t character_id, const std::vector<ExpeditionLockoutTimer>& lockouts,
|
||||
bool replace_timer, bool is_pending)
|
||||
void ExpeditionDatabase::InsertCharacterLockouts(uint32_t character_id,
|
||||
const std::vector<ExpeditionLockoutTimer>& lockouts)
|
||||
{
|
||||
LogExpeditionsDetail("Inserting [{}] lockouts for character [{}]", lockouts.size(), character_id);
|
||||
|
||||
@ -434,14 +378,13 @@ void ExpeditionDatabase::InsertCharacterLockouts(
|
||||
for (const auto& lockout : lockouts)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(insert_values),
|
||||
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}', {}),",
|
||||
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
|
||||
character_id,
|
||||
lockout.GetExpireTime(),
|
||||
lockout.GetDuration(),
|
||||
lockout.GetExpeditionUUID(),
|
||||
EscapeString(lockout.GetExpeditionName()),
|
||||
EscapeString(lockout.GetEventName()),
|
||||
is_pending
|
||||
EscapeString(lockout.GetEventName())
|
||||
);
|
||||
}
|
||||
|
||||
@ -449,34 +392,15 @@ void ExpeditionDatabase::InsertCharacterLockouts(
|
||||
{
|
||||
insert_values.pop_back(); // trailing comma
|
||||
|
||||
std::string on_duplicate;
|
||||
if (replace_timer)
|
||||
{
|
||||
on_duplicate = SQL(
|
||||
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||
expire_time = VALUES(expire_time),
|
||||
duration = VALUES(duration)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
on_duplicate = "character_id = VALUES(character_id)";
|
||||
}
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
INSERT INTO character_expedition_lockouts
|
||||
(
|
||||
character_id,
|
||||
expire_time,
|
||||
duration,
|
||||
from_expedition_uuid,
|
||||
expedition_name,
|
||||
event_name,
|
||||
is_pending
|
||||
)
|
||||
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
|
||||
VALUES {}
|
||||
ON DUPLICATE KEY UPDATE {};
|
||||
), insert_values, on_duplicate);
|
||||
ON DUPLICATE KEY UPDATE
|
||||
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||
expire_time = VALUES(expire_time),
|
||||
duration = VALUES(duration);
|
||||
), insert_values);
|
||||
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
@ -52,23 +52,22 @@ namespace ExpeditionDatabase
|
||||
void DeleteMember(uint32_t expedition_id, uint32_t character_id);
|
||||
void DeleteAllCharacterLockouts(uint32_t character_id);
|
||||
void DeleteAllCharacterLockouts(uint32_t character_id, const std::string& expedition_name);
|
||||
void DeleteCharacterLockout(uint32_t character_id, const std::string& expedition_name, const std::string& event_name);
|
||||
void DeleteCharacterLockout(uint32_t character_id, const std::string& expedition_name,
|
||||
const std::string& event_name);
|
||||
void DeleteLockout(uint32_t expedition_id, const std::string& event_name);
|
||||
void DeleteMembersLockout(
|
||||
const std::vector<ExpeditionMember>& members, const std::string& expedition_name, const std::string& event_name);
|
||||
void AssignPendingLockouts(uint32_t character_id, const std::string& expedition_name);
|
||||
void DeletePendingLockouts(uint32_t character_id);
|
||||
void DeleteAllMembersPendingLockouts(const std::vector<ExpeditionMember>& members);
|
||||
void DeleteMembersLockout(const std::vector<ExpeditionMember>& members,
|
||||
const std::string& expedition_name, const std::string& event_name);
|
||||
uint32_t GetExpeditionIDFromCharacterID(uint32_t character_id);
|
||||
std::pair<std::vector<ExpeditionLockoutTimer>, std::vector<uint32_t>> GetMembersLockout(
|
||||
const std::vector<ExpeditionMember>& members, const std::string& expedition_name,
|
||||
const std::string& event_name);
|
||||
void InsertCharacterLockouts(
|
||||
uint32_t character_id, const std::vector<ExpeditionLockoutTimer>& lockouts,
|
||||
bool replace_timer, bool is_pending = false);
|
||||
void InsertMembersLockout(const std::vector<ExpeditionMember>& members, const ExpeditionLockoutTimer& lockout);
|
||||
void InsertCharacterLockouts(uint32_t character_id,
|
||||
const std::vector<ExpeditionLockoutTimer>& lockouts);
|
||||
void InsertMembersLockout(const std::vector<ExpeditionMember>& members,
|
||||
const ExpeditionLockoutTimer& lockout);
|
||||
void InsertLockout(uint32_t expedition_id, const ExpeditionLockoutTimer& lockout);
|
||||
void InsertLockouts(uint32_t expedition_id, const std::unordered_map<std::string, ExpeditionLockoutTimer>& lockouts);
|
||||
void InsertLockouts(uint32_t expedition_id,
|
||||
const std::unordered_map<std::string, ExpeditionLockoutTimer>& lockouts);
|
||||
void InsertMember(uint32_t expedition_id, uint32_t character_id);
|
||||
void InsertMembers(uint32_t expedition_id, const std::vector<ExpeditionMember>& members);
|
||||
void UpdateLockState(uint32_t expedition_id, bool is_locked);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user