mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 14:41:28 +00:00
[DynamicZones] Bulk request dz member statuses on zone boot (#4769)
When dynamic zones are cached on zone boot each dz requests member statuses from world separately. This causes a lot of network traffic between world and booted zones when there are a lot of active dzs. This changes it to make a single request to world on zone boot and a single bulk reply back.
This commit is contained in:
parent
84708edccf
commit
051ce3736f
@ -196,6 +196,7 @@
|
|||||||
#define ServerOP_DzSaveInvite 0x0466
|
#define ServerOP_DzSaveInvite 0x0466
|
||||||
#define ServerOP_DzRequestInvite 0x0467
|
#define ServerOP_DzRequestInvite 0x0467
|
||||||
#define ServerOP_DzMakeLeader 0x0468
|
#define ServerOP_DzMakeLeader 0x0468
|
||||||
|
#define ServerOP_DzGetBulkMemberStatuses 0x0469
|
||||||
|
|
||||||
#define ServerOP_LSInfo 0x1000
|
#define ServerOP_LSInfo 0x1000
|
||||||
#define ServerOP_LSStatus 0x1001
|
#define ServerOP_LSStatus 0x1001
|
||||||
@ -1555,6 +1556,13 @@ struct ServerDzMemberStatuses_Struct {
|
|||||||
ServerDzMemberStatusEntry_Struct entries[0];
|
ServerDzMemberStatusEntry_Struct entries[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ServerDzCerealData_Struct {
|
||||||
|
uint16_t zone_id;
|
||||||
|
uint16_t inst_id;
|
||||||
|
uint32_t cereal_size;
|
||||||
|
char cereal_data[1];
|
||||||
|
};
|
||||||
|
|
||||||
struct ServerDzMovePC_Struct {
|
struct ServerDzMovePC_Struct {
|
||||||
uint32 dz_id;
|
uint32 dz_id;
|
||||||
uint16 sender_zone_id;
|
uint16 sender_zone_id;
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "zoneserver.h"
|
#include "zoneserver.h"
|
||||||
#include "../common/rulesys.h"
|
#include "../common/rulesys.h"
|
||||||
#include "../common/repositories/dynamic_zone_lockouts_repository.h"
|
#include "../common/repositories/dynamic_zone_lockouts_repository.h"
|
||||||
|
#include <cereal/types/utility.hpp>
|
||||||
|
|
||||||
extern ClientList client_list;
|
extern ClientList client_list;
|
||||||
extern ZSList zoneserver_list;
|
extern ZSList zoneserver_list;
|
||||||
@ -169,6 +170,33 @@ void DynamicZoneManager::LoadTemplates()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicZoneManager::SendBulkMemberStatuses(uint32_t zone_id, uint16_t inst_id)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<uint32_t, std::vector<DynamicZoneMember>>> dzs;
|
||||||
|
dzs.reserve(dynamic_zone_cache.size());
|
||||||
|
|
||||||
|
for (const auto& [dz_id, dz] : dynamic_zone_cache)
|
||||||
|
{
|
||||||
|
dzs.emplace_back(dz_id, dz->GetMembers());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream ss;
|
||||||
|
{
|
||||||
|
cereal::BinaryOutputArchive archive(ss);
|
||||||
|
archive(dzs);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view sv = ss.view();
|
||||||
|
|
||||||
|
size_t size = sizeof(ServerDzCerealData_Struct) + sv.size();
|
||||||
|
ServerPacket pack(ServerOP_DzGetBulkMemberStatuses, static_cast<uint32_t>(size));
|
||||||
|
auto buf = reinterpret_cast<ServerDzCerealData_Struct*>(pack.pBuffer);
|
||||||
|
buf->cereal_size = static_cast<uint32_t>(sv.size());
|
||||||
|
memcpy(buf->cereal_data, sv.data(), sv.size());
|
||||||
|
|
||||||
|
zoneserver_list.SendPacket(zone_id, inst_id, &pack);
|
||||||
|
}
|
||||||
|
|
||||||
void DynamicZoneManager::HandleZoneMessage(ServerPacket* pack)
|
void DynamicZoneManager::HandleZoneMessage(ServerPacket* pack)
|
||||||
{
|
{
|
||||||
switch (pack->opcode)
|
switch (pack->opcode)
|
||||||
@ -338,6 +366,15 @@ void DynamicZoneManager::HandleZoneMessage(ServerPacket* pack)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ServerOP_DzGetBulkMemberStatuses:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerDzCerealData_Struct*>(pack->pBuffer);
|
||||||
|
if (buf->zone_id != 0 && !dynamic_zone_cache.empty())
|
||||||
|
{
|
||||||
|
SendBulkMemberStatuses(buf->zone_id, buf->inst_id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ServerOP_DzUpdateMemberStatus:
|
case ServerOP_DzUpdateMemberStatus:
|
||||||
{
|
{
|
||||||
auto buf = reinterpret_cast<ServerDzMemberStatus_Struct*>(pack->pBuffer);
|
auto buf = reinterpret_cast<ServerDzMemberStatus_Struct*>(pack->pBuffer);
|
||||||
|
|||||||
@ -30,6 +30,8 @@ public:
|
|||||||
std::unordered_map<uint32_t, std::unique_ptr<DynamicZone>> dynamic_zone_cache;
|
std::unordered_map<uint32_t, std::unique_ptr<DynamicZone>> dynamic_zone_cache;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SendBulkMemberStatuses(uint32_t zone_id, uint16_t inst_id);
|
||||||
|
|
||||||
Timer m_process_throttle_timer{};
|
Timer m_process_throttle_timer{};
|
||||||
std::unordered_map<uint32_t, DynamicZoneTemplatesRepository::DynamicZoneTemplates> m_dz_templates;
|
std::unordered_map<uint32_t, DynamicZoneTemplatesRepository::DynamicZoneTemplates> m_dz_templates;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1480,6 +1480,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
case ServerOP_DzSwapMembers:
|
case ServerOP_DzSwapMembers:
|
||||||
case ServerOP_DzRemoveAllMembers:
|
case ServerOP_DzRemoveAllMembers:
|
||||||
case ServerOP_DzGetMemberStatuses:
|
case ServerOP_DzGetMemberStatuses:
|
||||||
|
case ServerOP_DzGetBulkMemberStatuses:
|
||||||
case ServerOP_DzSetSecondsRemaining:
|
case ServerOP_DzSetSecondsRemaining:
|
||||||
case ServerOP_DzSetCompass:
|
case ServerOP_DzSetCompass:
|
||||||
case ServerOP_DzSetSafeReturn:
|
case ServerOP_DzSetSafeReturn:
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
#include "../common/repositories/character_expedition_lockouts_repository.h"
|
#include "../common/repositories/character_expedition_lockouts_repository.h"
|
||||||
#include "../common/repositories/dynamic_zone_lockouts_repository.h"
|
#include "../common/repositories/dynamic_zone_lockouts_repository.h"
|
||||||
|
#include <cereal/types/utility.hpp>
|
||||||
|
|
||||||
extern WorldServer worldserver;
|
extern WorldServer worldserver;
|
||||||
|
|
||||||
@ -162,14 +163,28 @@ void DynamicZone::CacheAllFromDatabase()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dz->UpdateMembers();
|
|
||||||
zone->dynamic_zone_cache.emplace(dz_id, std::move(dz));
|
zone->dynamic_zone_cache.emplace(dz_id, std::move(dz));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!zone->dynamic_zone_cache.empty())
|
||||||
|
{
|
||||||
|
RequestMemberStatuses();
|
||||||
|
}
|
||||||
|
|
||||||
LogInfo("Loaded [{}] dynamic zone(s)", Strings::Commify(zone->dynamic_zone_cache.size()));
|
LogInfo("Loaded [{}] dynamic zone(s)", Strings::Commify(zone->dynamic_zone_cache.size()));
|
||||||
LogDynamicZones("Caching [{}] dynamic zone(s) took [{}s]", zone->dynamic_zone_cache.size(), bench.elapsed());
|
LogDynamicZones("Caching [{}] dynamic zone(s) took [{}s]", zone->dynamic_zone_cache.size(), bench.elapsed());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicZone::RequestMemberStatuses()
|
||||||
|
{
|
||||||
|
ServerPacket pack(ServerOP_DzGetBulkMemberStatuses, sizeof(ServerDzCerealData_Struct));
|
||||||
|
auto buf = reinterpret_cast<ServerDzCerealData_Struct*>(pack.pBuffer);
|
||||||
|
buf->zone_id = static_cast<uint16_t>(zone->GetZoneID());
|
||||||
|
buf->inst_id = static_cast<uint16_t>(zone->GetInstanceID());
|
||||||
|
|
||||||
|
worldserver.SendPacket(&pack);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
DynamicZone* FindDynamicZone(T pred)
|
DynamicZone* FindDynamicZone(T pred)
|
||||||
{
|
{
|
||||||
@ -849,6 +864,34 @@ void DynamicZone::HandleWorldMessage(ServerPacket* pack)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ServerOP_DzGetBulkMemberStatuses:
|
||||||
|
{
|
||||||
|
if (zone)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<uint32_t, std::vector<DynamicZoneMember>>> dzs;
|
||||||
|
dzs.reserve(zone->dynamic_zone_cache.size());
|
||||||
|
|
||||||
|
auto buf = reinterpret_cast<ServerDzCerealData_Struct*>(pack->pBuffer);
|
||||||
|
EQ::Util::MemoryStreamReader ss(buf->cereal_data, buf->cereal_size);
|
||||||
|
{
|
||||||
|
cereal::BinaryInputArchive archive(ss);
|
||||||
|
archive(dzs);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [dz_id, members] : dzs)
|
||||||
|
{
|
||||||
|
if (auto dz = DynamicZone::FindDynamicZoneByID(dz_id))
|
||||||
|
{
|
||||||
|
for (const auto& member : members)
|
||||||
|
{
|
||||||
|
dz->SetInternalMemberStatus(member.id, member.status);
|
||||||
|
}
|
||||||
|
dz->m_has_member_statuses = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ServerOP_DzUpdateMemberStatus:
|
case ServerOP_DzUpdateMemberStatus:
|
||||||
{
|
{
|
||||||
auto buf = reinterpret_cast<ServerDzMemberStatus_Struct*>(pack->pBuffer);
|
auto buf = reinterpret_cast<ServerDzMemberStatus_Struct*>(pack->pBuffer);
|
||||||
|
|||||||
@ -92,13 +92,13 @@ public:
|
|||||||
void SendMemberNameToZoneMembers(const std::string& char_name, bool remove);
|
void SendMemberNameToZoneMembers(const std::string& char_name, bool remove);
|
||||||
void SendMemberStatusToZoneMembers(const DynamicZoneMember& member);
|
void SendMemberStatusToZoneMembers(const DynamicZoneMember& member);
|
||||||
void SetLocked(bool lock, bool update_db = false, DzLockMsg lock_msg = DzLockMsg::None, uint32_t color = Chat::Yellow);
|
void SetLocked(bool lock, bool update_db = false, DzLockMsg lock_msg = DzLockMsg::None, uint32_t color = Chat::Yellow);
|
||||||
void UpdateMembers();
|
|
||||||
|
|
||||||
std::string GetLootEvent(uint32_t id, DzLootEvent::Type type) const;
|
std::string GetLootEvent(uint32_t id, DzLootEvent::Type type) const;
|
||||||
void SetLootEvent(uint32_t id, const std::string& event, DzLootEvent::Type type);
|
void SetLootEvent(uint32_t id, const std::string& event, DzLootEvent::Type type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void StartAllClientRemovalTimers();
|
static void StartAllClientRemovalTimers();
|
||||||
|
static void RequestMemberStatuses();
|
||||||
|
|
||||||
uint16_t GetCurrentInstanceID() const override;
|
uint16_t GetCurrentInstanceID() const override;
|
||||||
uint16_t GetCurrentZoneID() const override;
|
uint16_t GetCurrentZoneID() const override;
|
||||||
@ -125,6 +125,7 @@ private:
|
|||||||
void SendWorldPlayerInvite(const std::string& inviter, const std::string& swap_name, const std::string& add_name, bool pending = false);
|
void SendWorldPlayerInvite(const std::string& inviter, const std::string& swap_name, const std::string& add_name, bool pending = false);
|
||||||
void SetUpdatedDuration(uint32_t seconds);
|
void SetUpdatedDuration(uint32_t seconds);
|
||||||
void TryAddClient(Client* add_client, const std::string& inviter, const std::string& swap_name, Client* leader = nullptr);
|
void TryAddClient(Client* add_client, const std::string& inviter, const std::string& swap_name, Client* leader = nullptr);
|
||||||
|
void UpdateMembers();
|
||||||
|
|
||||||
std::unique_ptr<EQApplicationPacket> CreateExpireWarningPacket(uint32_t minutes_remaining);
|
std::unique_ptr<EQApplicationPacket> CreateExpireWarningPacket(uint32_t minutes_remaining);
|
||||||
std::unique_ptr<EQApplicationPacket> CreateInfoPacket(bool clear = false);
|
std::unique_ptr<EQApplicationPacket> CreateInfoPacket(bool clear = false);
|
||||||
|
|||||||
@ -3410,6 +3410,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
|||||||
case ServerOP_DzRemoveAllMembers:
|
case ServerOP_DzRemoveAllMembers:
|
||||||
case ServerOP_DzDurationUpdate:
|
case ServerOP_DzDurationUpdate:
|
||||||
case ServerOP_DzGetMemberStatuses:
|
case ServerOP_DzGetMemberStatuses:
|
||||||
|
case ServerOP_DzGetBulkMemberStatuses:
|
||||||
case ServerOP_DzSetCompass:
|
case ServerOP_DzSetCompass:
|
||||||
case ServerOP_DzSetSafeReturn:
|
case ServerOP_DzSetSafeReturn:
|
||||||
case ServerOP_DzSetZoneIn:
|
case ServerOP_DzSetZoneIn:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user