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 148af3edfc
commit 9164073d14
11 changed files with 93 additions and 67 deletions
+12 -26
View File
@@ -437,32 +437,6 @@ void DynamicZone::SendInstanceCharacterChange(uint32_t character_id, bool remove
}
}
void DynamicZone::UpdateExpireTime(uint32_t seconds, bool reduce_only)
{
if (GetInstanceID() == 0 || (reduce_only && GetSecondsRemaining() < seconds))
{
return;
}
m_expire_time = std::chrono::system_clock::now() + std::chrono::seconds(seconds);
m_duration = std::chrono::system_clock::to_time_t(m_expire_time) - m_start_time;
std::string query = fmt::format(SQL(
UPDATE instance_list SET duration = {} WHERE id = {};
), m_duration, GetInstanceID());
auto results = database.QueryDatabase(query);
if (results.Success())
{
uint32_t packsize = sizeof(ServerInstanceUpdateTime_Struct);
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_InstanceUpdateTime, packsize));
auto packbuf = reinterpret_cast<ServerInstanceUpdateTime_Struct*>(pack->pBuffer);
packbuf->instance_id = GetInstanceID();
packbuf->new_duration = seconds;
worldserver.SendPacket(pack.get());
}
}
void DynamicZone::SetCompass(const DynamicZoneLocation& location, bool update_db)
{
m_compass = location;
@@ -515,6 +489,18 @@ uint32_t DynamicZone::GetSecondsRemaining() const
return 0;
}
void DynamicZone::SetUpdatedDuration(uint32_t new_duration)
{
// preserves original start time, just modifies duration and expire time
m_duration = new_duration;
m_expire_time = std::chrono::system_clock::from_time_t(m_start_time + m_duration);
if (zone && IsCurrentZoneDzInstance())
{
zone->SetInstanceTimer(GetSecondsRemaining());
}
}
void DynamicZone::HandleWorldMessage(ServerPacket* pack)
{
switch (pack->opcode)
+1 -1
View File
@@ -89,7 +89,7 @@ public:
void SetCompass(const DynamicZoneLocation& location, bool update_db = false);
void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false);
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
void UpdateExpireTime(uint32_t seconds, bool reduce_only = true);
void SetUpdatedDuration(uint32_t seconds);
void LoadFromDatabase(uint32_t instance_id);
uint32_t SaveToDatabase();
+11 -18
View File
@@ -477,15 +477,10 @@ bool Expedition::AddMember(const std::string& add_char_name, uint32_t add_char_i
return true;
}
void Expedition::RemoveAllMembers(bool enable_removal_timers, bool update_dz_expire_time)
void Expedition::RemoveAllMembers(bool enable_removal_timers)
{
m_dynamiczone.RemoveAllCharacters(enable_removal_timers);
if (update_dz_expire_time && RuleB(Expedition, EmptyDzShutdownEnabled))
{
m_dynamiczone.UpdateExpireTime(RuleI(Expedition, EmptyDzShutdownDelaySeconds));
}
ExpeditionDatabase::UpdateAllMembersRemoved(m_id);
SendUpdatesToZoneMembers(true);
@@ -512,18 +507,6 @@ bool Expedition::RemoveMember(const std::string& remove_char_name)
ChooseNewLeader();
}
// we can't check for empty member count via cache because if other zones
// remove members at the same time then we race. cache member count won't
// be accurate until the world messages from other zones are processed
uint32_t member_count = ExpeditionDatabase::GetExpeditionMemberCount(m_id);
if (member_count == 0)
{
if (RuleB(Expedition, EmptyDzShutdownEnabled))
{
m_dynamiczone.UpdateExpireTime(RuleI(Expedition, EmptyDzShutdownDelaySeconds));
}
}
return true;
}
@@ -1813,6 +1796,16 @@ void Expedition::HandleWorldMessage(ServerPacket* pack)
}
break;
}
case ServerOP_ExpeditionDzDuration:
{
auto buf = reinterpret_cast<ServerExpeditionUpdateDuration_Struct*>(pack->pBuffer);
auto expedition = Expedition::FindCachedExpeditionByID(buf->expedition_id);
if (expedition)
{
expedition->SetDzDuration(buf->new_duration_seconds);
}
break;
}
}
}
+2 -1
View File
@@ -102,7 +102,7 @@ public:
bool AddMember(const std::string& add_char_name, uint32_t add_char_id);
bool HasMember(const std::string& character_name);
bool HasMember(uint32_t character_id);
void RemoveAllMembers(bool enable_removal_timers = true, bool update_dz_expire_time = true);
void RemoveAllMembers(bool enable_removal_timers = true);
bool RemoveMember(const std::string& remove_char_name);
void SetMemberStatus(Client* client, ExpeditionMemberStatus status);
void SetNewLeader(uint32_t new_leader_id, const std::string& new_leader_name);
@@ -134,6 +134,7 @@ public:
void SetDzSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false);
void SetDzSafeReturn(const std::string& zone_name, float x, float y, float z, float heading, bool update_db = false);
void SetDzZoneInLocation(float x, float y, float z, float heading, bool update_db = false);
void SetDzDuration(uint32_t new_duration) { m_dynamiczone.SetUpdatedDuration(new_duration); }
static const uint32_t REPLAY_TIMER_ID;
static const uint32_t EVENT_TIMER_ID;
-19
View File
@@ -395,25 +395,6 @@ ExpeditionMember ExpeditionDatabase::GetExpeditionLeader(uint32_t expedition_id)
return leader;
}
uint32_t ExpeditionDatabase::GetExpeditionMemberCount(uint32_t expedition_id)
{
auto query = fmt::format(SQL(
SELECT COUNT(IF(is_current_member = TRUE, 1, NULL)) member_count
FROM expedition_members
WHERE expedition_id = {};
), expedition_id);
auto results = database.QueryDatabase(query);
uint32_t member_count = 0;
if (results.Success() && results.RowCount() > 0)
{
auto row = results.begin();
member_count = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
}
return member_count;
}
void ExpeditionDatabase::InsertCharacterLockouts(
uint32_t character_id, const std::vector<ExpeditionLockoutTimer>& lockouts,
bool update_expire_times, bool is_pending)
-1
View File
@@ -55,7 +55,6 @@ namespace ExpeditionDatabase
uint32_t GetExpeditionIDFromCharacterID(uint32_t character_id);
uint32_t GetExpeditionIDFromInstanceID(uint32_t instance_id);
ExpeditionMember GetExpeditionLeader(uint32_t expedition_id);
uint32_t GetExpeditionMemberCount(uint32_t expedition_id);
void InsertCharacterLockouts(
uint32_t character_id, const std::vector<ExpeditionLockoutTimer>& lockouts,
bool update_expire_times, bool is_pending = false);
+1
View File
@@ -2915,6 +2915,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
case ServerOP_ExpeditionDzCompass:
case ServerOP_ExpeditionDzSafeReturn:
case ServerOP_ExpeditionDzZoneIn:
case ServerOP_ExpeditionDzDuration:
case ServerOP_ExpeditionRemoveCharLockouts:
{
Expedition::HandleWorldMessage(pack);
+1 -1
View File
@@ -1495,7 +1495,7 @@ bool Zone::Process() {
Expedition* expedition = Expedition::FindExpeditionByInstanceID(GetInstanceID());
if (expedition)
{
expedition->RemoveAllMembers(false, false); // entity list will teleport clients out immediately
expedition->RemoveAllMembers(false); // entity list will teleport clients out immediately
}
// todo: move corpses to non-instanced version of dz at same coords (if no graveyard)
entity_list.GateAllClientsToSafeReturn();