mirror of
https://github.com/EQEmu/Server.git
synced 2026-08-28 20:07:56 +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);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -32,16 +32,18 @@ public:
|
||||
Expedition();
|
||||
|
||||
void RemoveMember(uint32_t character_id);
|
||||
void CacheMemberStatuses();
|
||||
void CheckExpireWarning();
|
||||
void CheckLeader();
|
||||
void ChooseNewLeader();
|
||||
DynamicZone& GetDynamicZone() { return m_dynamic_zone; }
|
||||
bool Process();
|
||||
|
||||
void SendZoneMemberStatuses(uint16_t zone_id, uint16_t instance_id);
|
||||
void SendZonesExpeditionDeleted();
|
||||
void SendZonesExpireWarning(uint32_t minutes_remaining);
|
||||
void SetDynamicZone(DynamicZone&& dz);
|
||||
bool SetNewLeader(const DynamicZoneMember& member);
|
||||
void UpdateMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
|
||||
private:
|
||||
void SendZonesLeaderChanged();
|
||||
|
||||
@@ -35,11 +35,6 @@ void ExpeditionMessage::HandleZoneMessage(ServerPacket* pack)
|
||||
{
|
||||
switch (pack->opcode)
|
||||
{
|
||||
case ServerOP_ExpeditionChooseNewLeader:
|
||||
{
|
||||
ExpeditionMessage::ChooseNewLeader(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionCreate:
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerExpeditionID_Struct*>(pack->pBuffer);
|
||||
@@ -69,9 +64,21 @@ void ExpeditionMessage::HandleZoneMessage(ServerPacket* pack)
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionGetOnlineMembers:
|
||||
case ServerOP_ExpeditionMemberStatus:
|
||||
{
|
||||
ExpeditionMessage::GetOnlineMembers(pack);
|
||||
auto buf = reinterpret_cast<ServerExpeditionMemberStatus_Struct*>(pack->pBuffer);
|
||||
auto expedition = expedition_state.GetExpedition(buf->expedition_id);
|
||||
if (expedition)
|
||||
{
|
||||
auto status = static_cast<DynamicZoneMemberStatus>(buf->status);
|
||||
expedition->UpdateMemberStatus(buf->character_id, status);
|
||||
}
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionGetMemberStatuses:
|
||||
{
|
||||
ExpeditionMessage::GetMemberStatuses(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionDzAddPlayer:
|
||||
@@ -157,31 +164,14 @@ void ExpeditionMessage::MakeLeader(ServerPacket* pack)
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionMessage::GetOnlineMembers(ServerPacket* pack)
|
||||
void ExpeditionMessage::GetMemberStatuses(ServerPacket* pack)
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerExpeditionCharacters_Struct*>(pack->pBuffer);
|
||||
|
||||
// not efficient but only requested during caching
|
||||
char zone_name[64] = {0};
|
||||
std::vector<ClientListEntry*> all_clients;
|
||||
all_clients.reserve(client_list.GetClientCount());
|
||||
client_list.GetClients(zone_name, all_clients);
|
||||
|
||||
for (uint32_t i = 0; i < buf->count; ++i)
|
||||
auto buf = reinterpret_cast<ServerExpeditionID_Struct*>(pack->pBuffer);
|
||||
auto expedition = expedition_state.GetExpedition(buf->expedition_id);
|
||||
if (expedition)
|
||||
{
|
||||
auto it = std::find_if(all_clients.begin(), all_clients.end(), [&](const ClientListEntry* cle) {
|
||||
return (cle && cle->CharID() == buf->entries[i].character_id);
|
||||
});
|
||||
|
||||
if (it != all_clients.end())
|
||||
{
|
||||
buf->entries[i].character_zone_id = (*it)->zone();
|
||||
buf->entries[i].character_instance_id = (*it)->instance();
|
||||
buf->entries[i].character_online = true;
|
||||
}
|
||||
expedition->SendZoneMemberStatuses(buf->sender_zone_id, buf->sender_instance_id);
|
||||
}
|
||||
|
||||
zoneserver_list.SendPacket(buf->sender_zone_id, buf->sender_instance_id, pack);
|
||||
}
|
||||
|
||||
void ExpeditionMessage::SaveInvite(ServerPacket* pack)
|
||||
@@ -211,13 +201,3 @@ void ExpeditionMessage::RequestInvite(ServerPacket* pack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionMessage::ChooseNewLeader(ServerPacket* pack)
|
||||
{
|
||||
auto buf = reinterpret_cast<ServerExpeditionID_Struct*>(pack->pBuffer);
|
||||
auto expedition = expedition_state.GetExpedition(buf->expedition_id);
|
||||
if (expedition)
|
||||
{
|
||||
expedition->ChooseNewLeader();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@ class ServerPacket;
|
||||
namespace ExpeditionMessage
|
||||
{
|
||||
void AddPlayer(ServerPacket* pack);
|
||||
void ChooseNewLeader(ServerPacket* pack);
|
||||
void GetOnlineMembers(ServerPacket* pack);
|
||||
void GetMemberStatuses(ServerPacket* pack);
|
||||
void HandleZoneMessage(ServerPacket* pack);
|
||||
void MakeLeader(ServerPacket* pack);
|
||||
void RequestInvite(ServerPacket* pack);
|
||||
|
||||
@@ -110,6 +110,8 @@ void ExpeditionState::CacheExpeditions(
|
||||
}
|
||||
}
|
||||
|
||||
expedition->CacheMemberStatuses();
|
||||
|
||||
m_expeditions.emplace_back(std::move(expedition));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1366,17 +1366,16 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
case ServerOP_ExpeditionLockout:
|
||||
case ServerOP_ExpeditionLockoutDuration:
|
||||
case ServerOP_ExpeditionLockState:
|
||||
case ServerOP_ExpeditionMemberStatus:
|
||||
case ServerOP_ExpeditionReplayOnJoin:
|
||||
case ServerOP_ExpeditionExpireWarning:
|
||||
{
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ExpeditionChooseNewLeader:
|
||||
case ServerOP_ExpeditionCreate:
|
||||
case ServerOP_ExpeditionGetOnlineMembers:
|
||||
case ServerOP_ExpeditionGetMemberStatuses:
|
||||
case ServerOP_ExpeditionMemberChange:
|
||||
case ServerOP_ExpeditionMemberStatus:
|
||||
case ServerOP_ExpeditionMemberSwap:
|
||||
case ServerOP_ExpeditionMembersRemoved:
|
||||
case ServerOP_ExpeditionDzAddPlayer:
|
||||
|
||||
Reference in New Issue
Block a user