mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-11 11:48:37 +00:00
[Expeditions] Track DZ member status in world (#1341)
World now caches and tracks member statuses so it can send them to zones that request them on startup. Prior to this the cle would be searched in world for every zone startup caching request, now it's only searched once when a new expedition is created. Bulk loading statuses removed since it would only be needed on world startup now and likely have no clients in the client list anyway. This also lets world choose non-linkdead members on expedition leader changes and better detect when a leader change needs to occur
This commit is contained in:
+60
-3
@@ -62,10 +62,8 @@ void Expedition::ChooseNewLeader()
|
||||
return;
|
||||
}
|
||||
|
||||
// we don't track expedition member status in world so may choose a linkdead member
|
||||
// this is fine since it will trigger another change when that member goes offline
|
||||
auto it = std::find_if(m_members.begin(), m_members.end(), [&](const DynamicZoneMember& member) {
|
||||
if (member.id != m_leader.id) {
|
||||
if (member.id != m_leader.id && member.IsOnline()) {
|
||||
auto member_cle = client_list.FindCLEByCharacterID(member.id);
|
||||
return (member_cle && member_cle->GetOnline() == CLE_Status::InZone);
|
||||
}
|
||||
@@ -171,3 +169,62 @@ bool Expedition::Process()
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Expedition::UpdateMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status)
|
||||
{
|
||||
SetInternalMemberStatus(character_id, status);
|
||||
|
||||
// any member status update will trigger a leader fix if leader was offline
|
||||
if (m_leader.status == DynamicZoneMemberStatus::Offline)
|
||||
{
|
||||
ChooseNewLeader();
|
||||
}
|
||||
}
|
||||
|
||||
void Expedition::SendZoneMemberStatuses(uint16_t zone_id, uint16_t instance_id)
|
||||
{
|
||||
const auto& members = GetMembers();
|
||||
|
||||
uint32_t members_count = static_cast<uint32_t>(members.size());
|
||||
uint32_t entries_size = sizeof(ServerExpeditionMemberStatusEntry_Struct) * members_count;
|
||||
uint32_t pack_size = sizeof(ServerExpeditionMemberStatuses_Struct) + entries_size;
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_ExpeditionGetMemberStatuses, pack_size);
|
||||
auto buf = reinterpret_cast<ServerExpeditionMemberStatuses_Struct*>(pack->pBuffer);
|
||||
buf->expedition_id = GetID();
|
||||
buf->count = members_count;
|
||||
|
||||
for (int i = 0; i < members.size(); ++i)
|
||||
{
|
||||
buf->entries[i].character_id = members[i].id;
|
||||
buf->entries[i].online_status = static_cast<uint8_t>(members[i].status);
|
||||
}
|
||||
|
||||
zoneserver_list.SendPacket(zone_id, instance_id, pack.get());
|
||||
}
|
||||
|
||||
void Expedition::CacheMemberStatuses()
|
||||
{
|
||||
// called when a new expedition is cached to fill member statuses
|
||||
std::string zone_name{};
|
||||
std::vector<ClientListEntry*> all_clients;
|
||||
all_clients.reserve(client_list.GetClientCount());
|
||||
client_list.GetClients(zone_name.c_str(), all_clients);
|
||||
|
||||
for (const auto& member : m_members)
|
||||
{
|
||||
auto it = std::find_if(all_clients.begin(), all_clients.end(),
|
||||
[&](const ClientListEntry* cle) { return (cle && cle->CharID() == member.id); });
|
||||
|
||||
auto status = DynamicZoneMemberStatus::Offline;
|
||||
if (it != all_clients.end())
|
||||
{
|
||||
status = DynamicZoneMemberStatus::Online;
|
||||
if (GetDynamicZone().IsSameDz((*it)->zone(), (*it)->instance()))
|
||||
{
|
||||
status = DynamicZoneMemberStatus::InDynamicZone;
|
||||
}
|
||||
}
|
||||
|
||||
SetInternalMemberStatus(member.id, status);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user