From eccc79e4ce02c03b41c256ac75ab8bde89884cc8 Mon Sep 17 00:00:00 2001 From: hg <4683435+hgtw@users.noreply.github.com> Date: Thu, 7 May 2020 18:38:43 -0400 Subject: [PATCH] Let dz handle client removal timers Remove all clients inside a dz, not just those assigned to instance --- common/servertalk.h | 2 ++ world/zoneserver.cpp | 1 + zone/dynamiczone.cpp | 52 ++++++++++++++++++++++++++++++++++++++++---- zone/dynamiczone.h | 2 +- zone/expedition.cpp | 11 +--------- zone/worldserver.cpp | 1 + 6 files changed, 54 insertions(+), 15 deletions(-) diff --git a/common/servertalk.h b/common/servertalk.h index 6fbe67b96..c78bdf728 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -156,6 +156,7 @@ #define ServerOP_ExpeditionDzZoneIn 0x040c #define ServerOP_DzCharacterChange 0x0450 +#define ServerOP_DzRemoveAllCharacters 0x0451 #define ServerOP_LSInfo 0x1000 #define ServerOP_LSStatus 0x1001 @@ -2072,6 +2073,7 @@ struct ServerDzLocation_Struct { }; struct ServerDzCharacter_Struct { + uint16 zone_id; uint16 instance_id; uint8 remove; // 0: added 1: removed uint32 character_id; diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index f113b0b1e..cd6a17e37 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1398,6 +1398,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { break; } case ServerOP_DzCharacterChange: + case ServerOP_DzRemoveAllCharacters: { auto buf = reinterpret_cast(pack->pBuffer); ZoneServer* instance_zs = zoneserver_list.FindByInstanceID(buf->instance_id); diff --git a/zone/dynamiczone.cpp b/zone/dynamiczone.cpp index 0fcd2b8b2..5e87e229c 100644 --- a/zone/dynamiczone.cpp +++ b/zone/dynamiczone.cpp @@ -353,13 +353,40 @@ void DynamicZone::RemoveCharacter(uint32_t character_id) SendInstanceCharacterChange(character_id, true); // start client kick timer } -void DynamicZone::RemoveAllCharacters() +void DynamicZone::RemoveAllCharacters(bool enable_removal_timers) { - // caller has to notify clients of instance change since we don't hold members here - if (m_instance_id != 0) + if (GetInstanceID() == 0) { - database.RemoveClientsFromInstance(m_instance_id); + return; } + + if (enable_removal_timers) + { + // just remove all clients in bulk instead of only characters assigned to the instance + if (IsCurrentZoneDzInstance()) + { + for (const auto& client_iter : entity_list.GetClientList()) + { + if (client_iter.second) + { + client_iter.second->SetDzRemovalTimer(true); + } + } + } + else if (GetInstanceID() != 0) + { + uint32_t packsize = sizeof(ServerDzCharacter_Struct); + auto pack = std::unique_ptr(new ServerPacket(ServerOP_DzRemoveAllCharacters, packsize)); + auto packbuf = reinterpret_cast(pack->pBuffer); + packbuf->zone_id = GetZoneID(); + packbuf->instance_id = GetInstanceID(); + packbuf->remove = true; + packbuf->character_id = 0; + worldserver.SendPacket(pack.get()); + } + } + + database.RemoveClientsFromInstance(GetInstanceID()); } void DynamicZone::SaveInstanceMembersToDatabase(const std::unordered_set character_ids) @@ -402,6 +429,7 @@ void DynamicZone::SendInstanceCharacterChange(uint32_t character_id, bool remove uint32_t packsize = sizeof(ServerDzCharacter_Struct); auto pack = std::unique_ptr(new ServerPacket(ServerOP_DzCharacterChange, packsize)); auto packbuf = reinterpret_cast(pack->pBuffer); + packbuf->zone_id = GetZoneID(); packbuf->instance_id = GetInstanceID(); packbuf->remove = removed; packbuf->character_id = character_id; @@ -503,5 +531,21 @@ void DynamicZone::HandleWorldMessage(ServerPacket* pack) } break; } + case ServerOP_DzRemoveAllCharacters: + { + auto buf = reinterpret_cast(pack->pBuffer); + if (buf->remove) + { + for (const auto& client_list_iter : entity_list.GetClientList()) + { + Client* client = client_list_iter.second; + if (client) + { + client->SetDzRemovalTimer(true); + } + } + } + break; + } } } diff --git a/zone/dynamiczone.h b/zone/dynamiczone.h index ceeef14ff..b2bf22b41 100644 --- a/zone/dynamiczone.h +++ b/zone/dynamiczone.h @@ -83,7 +83,7 @@ public: bool IsCurrentZoneDzInstance() const; bool IsInstanceID(uint32_t instance_id) const; bool IsValid() const { return m_instance_id != 0; } - void RemoveAllCharacters(); + void RemoveAllCharacters(bool enable_removal_timers = true); void RemoveCharacter(uint32_t character_id); void SendInstanceCharacterChange(uint32_t character_id, bool removed); void SetCompass(const DynamicZoneLocation& location, bool update_db = false); diff --git a/zone/expedition.cpp b/zone/expedition.cpp index 19c4de56d..7be333b0c 100644 --- a/zone/expedition.cpp +++ b/zone/expedition.cpp @@ -494,16 +494,7 @@ bool Expedition::AddMember(const std::string& add_char_name, uint32_t add_char_i void Expedition::RemoveAllMembers(bool enable_removal_timers, bool update_dz_expire_time) { - m_dynamiczone.RemoveAllCharacters(); - - if (enable_removal_timers) - { - // expedition holds member list (not dz) so inform dz members to start kick timers - for (const auto& member : m_members) - { - m_dynamiczone.SendInstanceCharacterChange(member.char_id, true); - } - } + m_dynamiczone.RemoveAllCharacters(enable_removal_timers); if (update_dz_expire_time && RuleB(Expedition, EmptyDzShutdownEnabled)) { diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index b6b3461ca..afdb9933b 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -2917,6 +2917,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) break; } case ServerOP_DzCharacterChange: + case ServerOP_DzRemoveAllCharacters: { DynamicZone::HandleWorldMessage(pack); break;