Let world shutdown dz early for empty expeditions

Since world now tracks empty expeditions it can determine when to
shutdown dynamic zone instances when the rule is enabled rather than
letting zones do it.
This commit is contained in:
hg
2020-05-27 23:26:47 -04:00
parent 4699a303c0
commit ca2c1171a1
11 changed files with 93 additions and 67 deletions
+53
View File
@@ -54,6 +54,42 @@ void Expedition::SendZonesExpeditionDeleted()
zoneserver_list.SendPacket(pack.get());
}
void Expedition::SendZonesDurationUpdate()
{
uint32_t packsize = sizeof(ServerExpeditionUpdateDuration_Struct);
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_ExpeditionDzDuration, packsize));
auto packbuf = reinterpret_cast<ServerExpeditionUpdateDuration_Struct*>(pack->pBuffer);
packbuf->expedition_id = GetID();
packbuf->new_duration_seconds = m_duration;
zoneserver_list.SendPacket(pack.get());
}
void Expedition::UpdateDzSecondsRemaining(uint32_t seconds_remaining)
{
auto now = std::chrono::system_clock::now();
auto update_time = std::chrono::seconds(seconds_remaining);
auto current_remaining = m_expire_time - now;
if (current_remaining > update_time) // reduce only
{
LogExpeditionsDetail(
"Updating expedition [{}] dz instance [{}] seconds remaining to [{}]s",
GetID(), GetInstanceID(), seconds_remaining
);
// preserve original start time and adjust duration instead
auto new_expire_time = now + update_time;
auto new_duration = std::chrono::system_clock::to_time_t(new_expire_time) - m_start_time;
m_duration = static_cast<uint32_t>(new_duration);
m_expire_time = std::chrono::system_clock::from_time_t(m_start_time + m_duration);
ExpeditionDatabase::UpdateDzDuration(GetInstanceID(), m_duration);
// update zone level caches and update the actual dz instance's timer
SendZonesDurationUpdate();
}
}
void ExpeditionCache::LoadActiveExpeditions()
{
BenchTimer benchmark;
@@ -151,6 +187,13 @@ void ExpeditionCache::Process()
it->SendZonesExpeditionDeleted();
is_deleted = true;
}
if (it->IsEmpty() && !it->IsPendingDelete() && RuleB(Expedition, EmptyDzShutdownEnabled))
{
it->UpdateDzSecondsRemaining(RuleI(Expedition, EmptyDzShutdownDelaySeconds));
}
it->SetPendingDelete(true);
}
it = is_deleted ? m_expeditions.erase(it) : it + 1;
@@ -334,6 +377,16 @@ void ExpeditionDatabase::DeleteExpeditions(const std::vector<uint32_t>& expediti
}
}
void ExpeditionDatabase::UpdateDzDuration(uint16_t instance_id, uint32_t new_duration)
{
std::string query = fmt::format(
"UPDATE instance_list SET duration = {} WHERE id = {};",
new_duration, instance_id
);
database.QueryDatabase(query);
}
void ExpeditionMessage::HandleZoneMessage(ServerPacket* pack)
{
switch (pack->opcode)
+6
View File
@@ -39,6 +39,7 @@ namespace ExpeditionDatabase
std::vector<Expedition> LoadExpeditions();
Expedition LoadExpedition(uint32_t expedition_id);
void DeleteExpeditions(const std::vector<uint32_t>& expedition_ids);
void UpdateDzDuration(uint16_t instance_id, uint32_t new_duration);
};
namespace ExpeditionMessage
@@ -82,7 +83,11 @@ public:
uint16_t GetZoneID() const { return static_cast<uint16_t>(m_dz_zone_id); }
bool IsEmpty() const { return m_member_ids.empty(); }
bool IsExpired() const { return m_expire_time < std::chrono::system_clock::now(); }
bool IsPendingDelete() const { return m_pending_delete; }
void SendZonesDurationUpdate();
void SendZonesExpeditionDeleted();
void SetPendingDelete(bool pending) { m_pending_delete = pending; }
void UpdateDzSecondsRemaining(uint32_t seconds_remaining);
private:
uint32_t m_expedition_id = 0;
@@ -90,6 +95,7 @@ private:
uint32_t m_dz_zone_id = 0;
uint32_t m_start_time = 0;
uint32_t m_duration = 0;
bool m_pending_delete = false;
std::unordered_set<uint32_t> m_member_ids;
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
};