mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 05:21:29 +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:
parent
26d374d52a
commit
0ce7c11d36
@ -25,6 +25,8 @@ struct DynamicZoneMember
|
|||||||
DynamicZoneMember(uint32_t id, std::string name_, DynamicZoneMemberStatus status_)
|
DynamicZoneMember(uint32_t id, std::string name_, DynamicZoneMemberStatus status_)
|
||||||
: id(id), name{std::move(name_)}, status(status_) {}
|
: id(id), name{std::move(name_)}, status(status_) {}
|
||||||
|
|
||||||
|
bool IsOnline() const { return status == DynamicZoneMemberStatus::Online ||
|
||||||
|
status == DynamicZoneMemberStatus::InDynamicZone; }
|
||||||
bool IsValid() const { return id != 0 && !name.empty(); }
|
bool IsValid() const { return id != 0 && !name.empty(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "expedition_base.h"
|
#include "expedition_base.h"
|
||||||
#include "repositories/expeditions_repository.h"
|
#include "repositories/expeditions_repository.h"
|
||||||
|
#include "rulesys.h"
|
||||||
|
|
||||||
ExpeditionBase::ExpeditionBase(uint32_t id, const std::string& uuid,
|
ExpeditionBase::ExpeditionBase(uint32_t id, const std::string& uuid,
|
||||||
const std::string& expedition_name, const DynamicZoneMember& leader,
|
const std::string& expedition_name, const DynamicZoneMember& leader,
|
||||||
@ -91,3 +92,27 @@ DynamicZoneMember ExpeditionBase::GetMemberData(const std::string& character_nam
|
|||||||
}
|
}
|
||||||
return member_data;
|
return member_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExpeditionBase::SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status)
|
||||||
|
{
|
||||||
|
if (status == DynamicZoneMemberStatus::InDynamicZone && !RuleB(Expedition, EnableInDynamicZoneStatus))
|
||||||
|
{
|
||||||
|
status = DynamicZoneMemberStatus::Online;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character_id == m_leader.id)
|
||||||
|
{
|
||||||
|
m_leader.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = std::find_if(m_members.begin(), m_members.end(),
|
||||||
|
[&](const DynamicZoneMember& member) { return member.id == character_id; });
|
||||||
|
|
||||||
|
if (it != m_members.end() && it->status != status)
|
||||||
|
{
|
||||||
|
it->status = status;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@ -33,6 +33,7 @@ public:
|
|||||||
bool HasMember(uint32_t character_id);
|
bool HasMember(uint32_t character_id);
|
||||||
bool IsEmpty() const { return m_members.empty(); }
|
bool IsEmpty() const { return m_members.empty(); }
|
||||||
void RemoveInternalMember(uint32_t character_id);
|
void RemoveInternalMember(uint32_t character_id);
|
||||||
|
bool SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||||
|
|
||||||
void LoadRepositoryResult(ExpeditionsRepository::ExpeditionWithLeader&& entry);
|
void LoadRepositoryResult(ExpeditionsRepository::ExpeditionWithLeader&& entry);
|
||||||
void AddMemberFromRepositoryResult(ExpeditionMembersRepository::MemberWithName&& entry);
|
void AddMemberFromRepositoryResult(ExpeditionMembersRepository::MemberWithName&& entry);
|
||||||
|
|||||||
@ -148,7 +148,7 @@
|
|||||||
#define ServerOP_ExpeditionMemberChange 0x0404
|
#define ServerOP_ExpeditionMemberChange 0x0404
|
||||||
#define ServerOP_ExpeditionMemberSwap 0x0405
|
#define ServerOP_ExpeditionMemberSwap 0x0405
|
||||||
#define ServerOP_ExpeditionMemberStatus 0x0406
|
#define ServerOP_ExpeditionMemberStatus 0x0406
|
||||||
#define ServerOP_ExpeditionGetOnlineMembers 0x0407
|
#define ServerOP_ExpeditionGetMemberStatuses 0x0407
|
||||||
#define ServerOP_ExpeditionDzAddPlayer 0x0408
|
#define ServerOP_ExpeditionDzAddPlayer 0x0408
|
||||||
#define ServerOP_ExpeditionDzMakeLeader 0x0409
|
#define ServerOP_ExpeditionDzMakeLeader 0x0409
|
||||||
#define ServerOP_ExpeditionCharacterLockout 0x040d
|
#define ServerOP_ExpeditionCharacterLockout 0x040d
|
||||||
@ -159,7 +159,6 @@
|
|||||||
#define ServerOP_ExpeditionMembersRemoved 0x0412
|
#define ServerOP_ExpeditionMembersRemoved 0x0412
|
||||||
#define ServerOP_ExpeditionLockoutDuration 0x0414
|
#define ServerOP_ExpeditionLockoutDuration 0x0414
|
||||||
#define ServerOP_ExpeditionExpireWarning 0x0416
|
#define ServerOP_ExpeditionExpireWarning 0x0416
|
||||||
#define ServerOP_ExpeditionChooseNewLeader 0x0417
|
|
||||||
|
|
||||||
#define ServerOP_DzAddRemoveCharacter 0x0450
|
#define ServerOP_DzAddRemoveCharacter 0x0450
|
||||||
#define ServerOP_DzRemoveAllCharacters 0x0451
|
#define ServerOP_DzRemoveAllCharacters 0x0451
|
||||||
@ -2035,19 +2034,15 @@ struct ServerExpeditionMemberStatus_Struct {
|
|||||||
uint32 character_id;
|
uint32 character_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerExpeditionCharacterEntry_Struct {
|
struct ServerExpeditionMemberStatusEntry_Struct {
|
||||||
uint32 expedition_id;
|
|
||||||
uint32 character_id;
|
uint32 character_id;
|
||||||
uint32 character_zone_id;
|
uint8 online_status; // 0: unknown 1: Online 2: Offline 3: In Dynamic Zone 4: Link Dead
|
||||||
uint16 character_instance_id;
|
|
||||||
uint8 character_online; // 0: offline 1: online
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerExpeditionCharacters_Struct {
|
struct ServerExpeditionMemberStatuses_Struct {
|
||||||
uint32 sender_zone_id;
|
uint32 expedition_id;
|
||||||
uint16 sender_instance_id;
|
|
||||||
uint32 count;
|
uint32 count;
|
||||||
ServerExpeditionCharacterEntry_Struct entries[0];
|
ServerExpeditionMemberStatusEntry_Struct entries[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerExpeditionLockout_Struct {
|
struct ServerExpeditionLockout_Struct {
|
||||||
|
|||||||
@ -62,10 +62,8 @@ void Expedition::ChooseNewLeader()
|
|||||||
return;
|
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) {
|
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);
|
auto member_cle = client_list.FindCLEByCharacterID(member.id);
|
||||||
return (member_cle && member_cle->GetOnline() == CLE_Status::InZone);
|
return (member_cle && member_cle->GetOnline() == CLE_Status::InZone);
|
||||||
}
|
}
|
||||||
@ -171,3 +169,62 @@ bool Expedition::Process()
|
|||||||
|
|
||||||
return false;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -32,16 +32,18 @@ public:
|
|||||||
Expedition();
|
Expedition();
|
||||||
|
|
||||||
void RemoveMember(uint32_t character_id);
|
void RemoveMember(uint32_t character_id);
|
||||||
|
void CacheMemberStatuses();
|
||||||
void CheckExpireWarning();
|
void CheckExpireWarning();
|
||||||
void CheckLeader();
|
void CheckLeader();
|
||||||
void ChooseNewLeader();
|
void ChooseNewLeader();
|
||||||
DynamicZone& GetDynamicZone() { return m_dynamic_zone; }
|
DynamicZone& GetDynamicZone() { return m_dynamic_zone; }
|
||||||
bool Process();
|
bool Process();
|
||||||
|
void SendZoneMemberStatuses(uint16_t zone_id, uint16_t instance_id);
|
||||||
void SendZonesExpeditionDeleted();
|
void SendZonesExpeditionDeleted();
|
||||||
void SendZonesExpireWarning(uint32_t minutes_remaining);
|
void SendZonesExpireWarning(uint32_t minutes_remaining);
|
||||||
void SetDynamicZone(DynamicZone&& dz);
|
void SetDynamicZone(DynamicZone&& dz);
|
||||||
bool SetNewLeader(const DynamicZoneMember& member);
|
bool SetNewLeader(const DynamicZoneMember& member);
|
||||||
|
void UpdateMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SendZonesLeaderChanged();
|
void SendZonesLeaderChanged();
|
||||||
|
|||||||
@ -35,11 +35,6 @@ void ExpeditionMessage::HandleZoneMessage(ServerPacket* pack)
|
|||||||
{
|
{
|
||||||
switch (pack->opcode)
|
switch (pack->opcode)
|
||||||
{
|
{
|
||||||
case ServerOP_ExpeditionChooseNewLeader:
|
|
||||||
{
|
|
||||||
ExpeditionMessage::ChooseNewLeader(pack);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ServerOP_ExpeditionCreate:
|
case ServerOP_ExpeditionCreate:
|
||||||
{
|
{
|
||||||
auto buf = reinterpret_cast<ServerExpeditionID_Struct*>(pack->pBuffer);
|
auto buf = reinterpret_cast<ServerExpeditionID_Struct*>(pack->pBuffer);
|
||||||
@ -69,9 +64,21 @@ void ExpeditionMessage::HandleZoneMessage(ServerPacket* pack)
|
|||||||
zoneserver_list.SendPacket(pack);
|
zoneserver_list.SendPacket(pack);
|
||||||
break;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case ServerOP_ExpeditionDzAddPlayer:
|
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);
|
auto buf = reinterpret_cast<ServerExpeditionID_Struct*>(pack->pBuffer);
|
||||||
|
auto expedition = expedition_state.GetExpedition(buf->expedition_id);
|
||||||
// not efficient but only requested during caching
|
if (expedition)
|
||||||
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 it = std::find_if(all_clients.begin(), all_clients.end(), [&](const ClientListEntry* cle) {
|
expedition->SendZoneMemberStatuses(buf->sender_zone_id, buf->sender_instance_id);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zoneserver_list.SendPacket(buf->sender_zone_id, buf->sender_instance_id, pack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpeditionMessage::SaveInvite(ServerPacket* 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
|
namespace ExpeditionMessage
|
||||||
{
|
{
|
||||||
void AddPlayer(ServerPacket* pack);
|
void AddPlayer(ServerPacket* pack);
|
||||||
void ChooseNewLeader(ServerPacket* pack);
|
void GetMemberStatuses(ServerPacket* pack);
|
||||||
void GetOnlineMembers(ServerPacket* pack);
|
|
||||||
void HandleZoneMessage(ServerPacket* pack);
|
void HandleZoneMessage(ServerPacket* pack);
|
||||||
void MakeLeader(ServerPacket* pack);
|
void MakeLeader(ServerPacket* pack);
|
||||||
void RequestInvite(ServerPacket* pack);
|
void RequestInvite(ServerPacket* pack);
|
||||||
|
|||||||
@ -110,6 +110,8 @@ void ExpeditionState::CacheExpeditions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expedition->CacheMemberStatuses();
|
||||||
|
|
||||||
m_expeditions.emplace_back(std::move(expedition));
|
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_ExpeditionLockout:
|
||||||
case ServerOP_ExpeditionLockoutDuration:
|
case ServerOP_ExpeditionLockoutDuration:
|
||||||
case ServerOP_ExpeditionLockState:
|
case ServerOP_ExpeditionLockState:
|
||||||
case ServerOP_ExpeditionMemberStatus:
|
|
||||||
case ServerOP_ExpeditionReplayOnJoin:
|
case ServerOP_ExpeditionReplayOnJoin:
|
||||||
case ServerOP_ExpeditionExpireWarning:
|
case ServerOP_ExpeditionExpireWarning:
|
||||||
{
|
{
|
||||||
zoneserver_list.SendPacket(pack);
|
zoneserver_list.SendPacket(pack);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ServerOP_ExpeditionChooseNewLeader:
|
|
||||||
case ServerOP_ExpeditionCreate:
|
case ServerOP_ExpeditionCreate:
|
||||||
case ServerOP_ExpeditionGetOnlineMembers:
|
case ServerOP_ExpeditionGetMemberStatuses:
|
||||||
case ServerOP_ExpeditionMemberChange:
|
case ServerOP_ExpeditionMemberChange:
|
||||||
|
case ServerOP_ExpeditionMemberStatus:
|
||||||
case ServerOP_ExpeditionMemberSwap:
|
case ServerOP_ExpeditionMemberSwap:
|
||||||
case ServerOP_ExpeditionMembersRemoved:
|
case ServerOP_ExpeditionMembersRemoved:
|
||||||
case ServerOP_ExpeditionDzAddPlayer:
|
case ServerOP_ExpeditionDzAddPlayer:
|
||||||
|
|||||||
@ -167,8 +167,6 @@ void Expedition::CacheExpeditions(
|
|||||||
auto expedition_members = ExpeditionMembersRepository::GetWithNames(database, expedition_ids);
|
auto expedition_members = ExpeditionMembersRepository::GetWithNames(database, expedition_ids);
|
||||||
auto expedition_lockouts = ExpeditionLockoutsRepository::GetWithTimestamp(database, expedition_ids);
|
auto expedition_lockouts = ExpeditionLockoutsRepository::GetWithTimestamp(database, expedition_ids);
|
||||||
|
|
||||||
std::vector<std::pair<uint32_t, uint32_t>> expedition_character_ids; // for online status request
|
|
||||||
|
|
||||||
for (auto& entry : expedition_entries)
|
for (auto& entry : expedition_entries)
|
||||||
{
|
{
|
||||||
auto expedition = std::make_unique<Expedition>();
|
auto expedition = std::make_unique<Expedition>();
|
||||||
@ -189,7 +187,6 @@ void Expedition::CacheExpeditions(
|
|||||||
if (member.expedition_id == expedition->GetID())
|
if (member.expedition_id == expedition->GetID())
|
||||||
{
|
{
|
||||||
expedition->AddMemberFromRepositoryResult(std::move(member));
|
expedition->AddMemberFromRepositoryResult(std::move(member));
|
||||||
expedition_character_ids.emplace_back(expedition->GetID(), member.character_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,12 +207,11 @@ void Expedition::CacheExpeditions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expedition->SendWorldExpeditionUpdate(ServerOP_ExpeditionGetMemberStatuses);
|
||||||
|
|
||||||
auto inserted = zone->expedition_cache.emplace(entry.id, std::move(expedition));
|
auto inserted = zone->expedition_cache.emplace(entry.id, std::move(expedition));
|
||||||
inserted.first->second->SendUpdatesToZoneMembers();
|
inserted.first->second->SendUpdatesToZoneMembers();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ask world for online members from all cached expeditions at once
|
|
||||||
Expedition::SendWorldGetOnlineMembers(expedition_character_ids);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Expedition::CacheFromDatabase(uint32_t expedition_id)
|
void Expedition::CacheFromDatabase(uint32_t expedition_id)
|
||||||
@ -521,19 +517,12 @@ void Expedition::SetMemberStatus(Client* client, DynamicZoneMemberStatus status)
|
|||||||
{
|
{
|
||||||
if (client)
|
if (client)
|
||||||
{
|
{
|
||||||
UpdateMemberStatus(client->CharacterID(), status);
|
SendMemberStatusToZoneMembers(client->CharacterID(), status);
|
||||||
SendWorldMemberStatus(client->CharacterID(), status);
|
SendWorldMemberStatus(client->CharacterID(), status);
|
||||||
|
|
||||||
// world could detect this itself but it'd have to process member status updates
|
|
||||||
// a member coming online will trigger a leader change if all members were offline
|
|
||||||
if (m_leader.status == DynamicZoneMemberStatus::Offline)
|
|
||||||
{
|
|
||||||
SendWorldExpeditionUpdate(ServerOP_ExpeditionChooseNewLeader);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Expedition::UpdateMemberStatus(uint32_t update_member_id, DynamicZoneMemberStatus status)
|
void Expedition::SendMemberStatusToZoneMembers(uint32_t update_member_id, DynamicZoneMemberStatus status)
|
||||||
{
|
{
|
||||||
auto member_data = GetMemberData(update_member_id);
|
auto member_data = GetMemberData(update_member_id);
|
||||||
if (!member_data.IsValid())
|
if (!member_data.IsValid())
|
||||||
@ -541,35 +530,19 @@ void Expedition::UpdateMemberStatus(uint32_t update_member_id, DynamicZoneMember
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == DynamicZoneMemberStatus::InDynamicZone && !RuleB(Expedition, EnableInDynamicZoneStatus))
|
|
||||||
{
|
|
||||||
status = DynamicZoneMemberStatus::Online;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (update_member_id == m_leader.id)
|
|
||||||
{
|
|
||||||
m_leader.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if zone already had this member status cached avoid packet update to clients
|
// if zone already had this member status cached avoid packet update to clients
|
||||||
if (member_data.status == status)
|
bool changed = SetInternalMemberStatus(update_member_id, status);
|
||||||
|
if (changed)
|
||||||
{
|
{
|
||||||
return;
|
member_data = GetMemberData(update_member_id); // rules may override status
|
||||||
}
|
auto outapp_member_status = CreateMemberListStatusPacket(member_data.name, member_data.status);
|
||||||
|
for (auto& member : m_members)
|
||||||
auto outapp_member_status = CreateMemberListStatusPacket(member_data.name, status);
|
|
||||||
|
|
||||||
for (auto& member : m_members)
|
|
||||||
{
|
|
||||||
if (member.id == update_member_id)
|
|
||||||
{
|
{
|
||||||
member.status = status;
|
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||||
}
|
if (member_client)
|
||||||
|
{
|
||||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
member_client->QueuePacket(outapp_member_status.get());
|
||||||
if (member_client)
|
}
|
||||||
{
|
|
||||||
member_client->QueuePacket(outapp_member_status.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1095,6 +1068,8 @@ void Expedition::ProcessMakeLeader(Client* old_leader_client, Client* new_leader
|
|||||||
|
|
||||||
void Expedition::ProcessMemberAdded(const std::string& char_name, uint32_t added_char_id)
|
void Expedition::ProcessMemberAdded(const std::string& char_name, uint32_t added_char_id)
|
||||||
{
|
{
|
||||||
|
AddInternalMember({ added_char_id, char_name, DynamicZoneMemberStatus::Online });
|
||||||
|
|
||||||
// adds the member to this expedition and notifies both leader and new member
|
// adds the member to this expedition and notifies both leader and new member
|
||||||
Client* leader_client = entity_list.GetClientByCharID(m_leader.id);
|
Client* leader_client = entity_list.GetClientByCharID(m_leader.id);
|
||||||
if (leader_client)
|
if (leader_client)
|
||||||
@ -1102,18 +1077,16 @@ void Expedition::ProcessMemberAdded(const std::string& char_name, uint32_t added
|
|||||||
leader_client->MessageString(Chat::Yellow, EXPEDITION_MEMBER_ADDED, char_name.c_str(), m_expedition_name.c_str());
|
leader_client->MessageString(Chat::Yellow, EXPEDITION_MEMBER_ADDED, char_name.c_str(), m_expedition_name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
AddInternalMember({ added_char_id, char_name, DynamicZoneMemberStatus::Online });
|
|
||||||
|
|
||||||
Client* member_client = entity_list.GetClientByCharID(added_char_id);
|
Client* member_client = entity_list.GetClientByCharID(added_char_id);
|
||||||
if (member_client)
|
if (member_client)
|
||||||
{
|
{
|
||||||
member_client->SetExpeditionID(GetID());
|
member_client->SetExpeditionID(GetID());
|
||||||
member_client->SendDzCompassUpdate();
|
member_client->SendDzCompassUpdate();
|
||||||
SendClientExpeditionInfo(member_client);
|
member_client->QueuePacket(CreateInfoPacket().get());
|
||||||
member_client->MessageString(Chat::Yellow, EXPEDITION_MEMBER_ADDED, char_name.c_str(), m_expedition_name.c_str());
|
member_client->MessageString(Chat::Yellow, EXPEDITION_MEMBER_ADDED, char_name.c_str(), m_expedition_name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SendNewMemberAddedToZoneMembers(char_name);
|
SendMemberListToZoneMembers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Expedition::ProcessMemberRemoved(const std::string& removed_char_name, uint32_t removed_char_id)
|
void Expedition::ProcessMemberRemoved(const std::string& removed_char_name, uint32_t removed_char_id)
|
||||||
@ -1271,23 +1244,16 @@ void Expedition::AddLockoutClients(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Expedition::SendNewMemberAddedToZoneMembers(const std::string& added_name)
|
void Expedition::SendMemberListToZoneMembers()
|
||||||
{
|
{
|
||||||
// live only sends MemberListName when members are added from a swap, otherwise
|
|
||||||
// it sends expedition info (unnecessary) and the full member list
|
|
||||||
// we send a full member list update for both cases since MemberListName adds as
|
|
||||||
// "unknown" status (either due to unknown packet fields or future client change)
|
|
||||||
auto outapp_members = CreateMemberListPacket(false);
|
auto outapp_members = CreateMemberListPacket(false);
|
||||||
|
|
||||||
for (const auto& member : m_members)
|
for (const auto& member : m_members)
|
||||||
{
|
{
|
||||||
if (member.name != added_name) // new member already updated
|
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||||
|
if (member_client)
|
||||||
{
|
{
|
||||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
member_client->QueuePacket(outapp_members.get());
|
||||||
if (member_client)
|
|
||||||
{
|
|
||||||
member_client->QueuePacket(outapp_members.get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1562,29 +1528,6 @@ void Expedition::SendWorldSettingChanged(uint16_t server_opcode, bool setting_va
|
|||||||
worldserver.SendPacket(pack.get());
|
worldserver.SendPacket(pack.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Expedition::SendWorldGetOnlineMembers(
|
|
||||||
const std::vector<std::pair<uint32_t, uint32_t>>& expedition_character_ids)
|
|
||||||
{
|
|
||||||
// request online status of characters
|
|
||||||
uint32_t count = static_cast<uint32_t>(expedition_character_ids.size());
|
|
||||||
uint32_t entries_size = sizeof(ServerExpeditionCharacterEntry_Struct) * count;
|
|
||||||
uint32_t pack_size = sizeof(ServerExpeditionCharacters_Struct) + entries_size;
|
|
||||||
auto pack = std::make_unique<ServerPacket>(ServerOP_ExpeditionGetOnlineMembers, pack_size);
|
|
||||||
auto buf = reinterpret_cast<ServerExpeditionCharacters_Struct*>(pack->pBuffer);
|
|
||||||
buf->sender_zone_id = zone ? zone->GetZoneID() : 0;
|
|
||||||
buf->sender_instance_id = zone ? zone->GetInstanceID() : 0;
|
|
||||||
buf->count = count;
|
|
||||||
for (uint32_t i = 0; i < buf->count; ++i)
|
|
||||||
{
|
|
||||||
buf->entries[i].expedition_id = expedition_character_ids[i].first;
|
|
||||||
buf->entries[i].character_id = expedition_character_ids[i].second;
|
|
||||||
buf->entries[i].character_zone_id = 0;
|
|
||||||
buf->entries[i].character_instance_id = 0;
|
|
||||||
buf->entries[i].character_online = false;
|
|
||||||
}
|
|
||||||
worldserver.SendPacket(pack.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Expedition::SendWorldCharacterLockout(
|
void Expedition::SendWorldCharacterLockout(
|
||||||
uint32_t character_id, const ExpeditionLockoutTimer& lockout, bool remove)
|
uint32_t character_id, const ExpeditionLockoutTimer& lockout, bool remove)
|
||||||
{
|
{
|
||||||
@ -1794,7 +1737,8 @@ void Expedition::HandleWorldMessage(ServerPacket* pack)
|
|||||||
auto expedition = Expedition::FindCachedExpeditionByID(buf->expedition_id);
|
auto expedition = Expedition::FindCachedExpeditionByID(buf->expedition_id);
|
||||||
if (expedition)
|
if (expedition)
|
||||||
{
|
{
|
||||||
expedition->UpdateMemberStatus(buf->character_id, static_cast<DynamicZoneMemberStatus>(buf->status));
|
auto status = static_cast<DynamicZoneMemberStatus>(buf->status);
|
||||||
|
expedition->SendMemberStatusToZoneMembers(buf->character_id, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1825,24 +1769,19 @@ void Expedition::HandleWorldMessage(ServerPacket* pack)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ServerOP_ExpeditionGetOnlineMembers:
|
case ServerOP_ExpeditionGetMemberStatuses:
|
||||||
{
|
{
|
||||||
// reply from world for online member statuses request (for multiple expeditions)
|
// reply from world for online member statuses request
|
||||||
auto buf = reinterpret_cast<ServerExpeditionCharacters_Struct*>(pack->pBuffer);
|
auto buf = reinterpret_cast<ServerExpeditionMemberStatuses_Struct*>(pack->pBuffer);
|
||||||
for (uint32_t i = 0; i < buf->count; ++i)
|
auto expedition = Expedition::FindCachedExpeditionByID(buf->expedition_id);
|
||||||
|
if (expedition)
|
||||||
{
|
{
|
||||||
auto member = reinterpret_cast<ServerExpeditionCharacterEntry_Struct*>(&buf->entries[i]);
|
for (uint32_t i = 0; i < buf->count; ++i)
|
||||||
auto expedition = Expedition::FindCachedExpeditionByID(member->expedition_id);
|
|
||||||
if (expedition)
|
|
||||||
{
|
{
|
||||||
auto is_online = member->character_online;
|
auto status = static_cast<DynamicZoneMemberStatus>(buf->entries[i].online_status);
|
||||||
auto status = is_online ? DynamicZoneMemberStatus::Online : DynamicZoneMemberStatus::Offline;
|
expedition->SetInternalMemberStatus(buf->entries[i].character_id, status);
|
||||||
if (is_online && expedition->GetDynamicZone().IsInstanceID(member->character_instance_id))
|
|
||||||
{
|
|
||||||
status = DynamicZoneMemberStatus::InDynamicZone;
|
|
||||||
}
|
|
||||||
expedition->UpdateMemberStatus(member->character_id, status);
|
|
||||||
}
|
}
|
||||||
|
expedition->SendMemberListToZoneMembers();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,7 +128,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static void CacheExpeditions(std::vector<ExpeditionsRepository::ExpeditionWithLeader>&& expeditions);
|
static void CacheExpeditions(std::vector<ExpeditionsRepository::ExpeditionWithLeader>&& expeditions);
|
||||||
static void SendWorldGetOnlineMembers(const std::vector<std::pair<uint32_t, uint32_t>>& expedition_character_ids);
|
|
||||||
static void SendWorldCharacterLockout(uint32_t character_id, const ExpeditionLockoutTimer& lockout, bool remove);
|
static void SendWorldCharacterLockout(uint32_t character_id, const ExpeditionLockoutTimer& lockout, bool remove);
|
||||||
|
|
||||||
void AddLockout(const ExpeditionLockoutTimer& lockout, bool members_only = false);
|
void AddLockout(const ExpeditionLockoutTimer& lockout, bool members_only = false);
|
||||||
@ -148,8 +147,9 @@ private:
|
|||||||
Client* client, const std::string& inviter_name, const std::string& swap_remove_name);
|
Client* client, const std::string& inviter_name, const std::string& swap_remove_name);
|
||||||
void SendLeaderMessage(Client* leader_client, uint16_t chat_type, uint32_t string_id,
|
void SendLeaderMessage(Client* leader_client, uint16_t chat_type, uint32_t string_id,
|
||||||
const std::initializer_list<std::string>& args = {});
|
const std::initializer_list<std::string>& args = {});
|
||||||
|
void SendMemberListToZoneMembers();
|
||||||
|
void SendMemberStatusToZoneMembers(uint32_t update_character_id, DynamicZoneMemberStatus status);
|
||||||
void SendMembersExpireWarning(uint32_t minutes);
|
void SendMembersExpireWarning(uint32_t minutes);
|
||||||
void SendNewMemberAddedToZoneMembers(const std::string& added_name);
|
|
||||||
void SendUpdatesToZoneMembers(bool clear = false, bool message_on_clear = true);
|
void SendUpdatesToZoneMembers(bool clear = false, bool message_on_clear = true);
|
||||||
void SendCompassUpdateToZoneMembers();
|
void SendCompassUpdateToZoneMembers();
|
||||||
void SendWorldExpeditionUpdate(uint16_t server_opcode);
|
void SendWorldExpeditionUpdate(uint16_t server_opcode);
|
||||||
@ -167,7 +167,6 @@ private:
|
|||||||
void SetDynamicZone(DynamicZone&& dz);
|
void SetDynamicZone(DynamicZone&& dz);
|
||||||
void TryAddClient(Client* add_client, const std::string& inviter_name,
|
void TryAddClient(Client* add_client, const std::string& inviter_name,
|
||||||
const std::string& swap_remove_name, Client* leader_client = nullptr);
|
const std::string& swap_remove_name, Client* leader_client = nullptr);
|
||||||
void UpdateMemberStatus(uint32_t update_character_id, DynamicZoneMemberStatus status);
|
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
@ -2905,7 +2905,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
|||||||
case ServerOP_ExpeditionMemberStatus:
|
case ServerOP_ExpeditionMemberStatus:
|
||||||
case ServerOP_ExpeditionMembersRemoved:
|
case ServerOP_ExpeditionMembersRemoved:
|
||||||
case ServerOP_ExpeditionReplayOnJoin:
|
case ServerOP_ExpeditionReplayOnJoin:
|
||||||
case ServerOP_ExpeditionGetOnlineMembers:
|
case ServerOP_ExpeditionGetMemberStatuses:
|
||||||
case ServerOP_ExpeditionDzAddPlayer:
|
case ServerOP_ExpeditionDzAddPlayer:
|
||||||
case ServerOP_ExpeditionDzMakeLeader:
|
case ServerOP_ExpeditionDzMakeLeader:
|
||||||
case ServerOP_ExpeditionCharacterLockout:
|
case ServerOP_ExpeditionCharacterLockout:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user