[Expeditions] Store members on dynamic zone (#1358)

This moves members from expeditions so other systems can use them

Replace expedition_members table with dynamic_zone_members

Move 'EnableInDynamicZoneStatus' rule to DynamicZone namespace

Modify #dz list to show dz members (not instance players) and type name

Move various queries to repository methods
This commit is contained in:
hg
2021-05-24 22:14:32 -04:00
committed by GitHub
parent e8b94a11f1
commit 15328196e2
31 changed files with 683 additions and 585 deletions
+4 -3
View File
@@ -25,11 +25,12 @@ DynamicZone* DynamicZone::FindDynamicZoneByID(uint32_t dz_id)
return nullptr;
}
DynamicZoneStatus DynamicZone::Process(bool force_expire)
DynamicZoneStatus DynamicZone::Process()
{
DynamicZoneStatus status = DynamicZoneStatus::Normal;
if (force_expire || IsExpired())
// force expire if no members
if (!HasMembers() || IsExpired())
{
status = DynamicZoneStatus::Expired;
@@ -38,7 +39,7 @@ DynamicZoneStatus DynamicZone::Process(bool force_expire)
{
status = DynamicZoneStatus::ExpiredEmpty;
if (force_expire && !m_is_pending_early_shutdown && RuleB(DynamicZone, EmptyShutdownEnabled))
if (!HasMembers() && !m_is_pending_early_shutdown && RuleB(DynamicZone, EmptyShutdownEnabled))
{
SetSecondsRemaining(RuleI(DynamicZone, EmptyShutdownDelaySeconds));
m_is_pending_early_shutdown = true;
+1 -1
View File
@@ -24,7 +24,7 @@ public:
void SetSecondsRemaining(uint32_t seconds_remaining) override;
DynamicZoneStatus Process(bool force_expire);
DynamicZoneStatus Process();
protected:
Database& GetDatabase() override;
+21 -14
View File
@@ -39,14 +39,14 @@ Expedition::Expedition() :
void Expedition::SetDynamicZone(DynamicZone&& dz)
{
dz.SetName(GetName());
dz.SetLeaderName(GetLeaderName());
dz.SetLeader(GetLeader());
m_dynamic_zone = std::move(dz);
}
void Expedition::RemoveMember(uint32_t character_id)
{
RemoveInternalMember(character_id);
GetDynamicZone().RemoveInternalMember(character_id);
if (character_id == m_leader.id)
{
@@ -56,13 +56,14 @@ void Expedition::RemoveMember(uint32_t character_id)
void Expedition::ChooseNewLeader()
{
if (m_members.empty() || !m_choose_leader_cooldown_timer.Check())
const auto& members = GetDynamicZone().GetMembers();
if (members.empty() || !m_choose_leader_cooldown_timer.Check())
{
m_choose_leader_needed = true;
return;
}
auto it = std::find_if(m_members.begin(), m_members.end(), [&](const DynamicZoneMember& member) {
auto it = std::find_if(members.begin(), members.end(), [&](const DynamicZoneMember& member) {
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);
@@ -70,14 +71,14 @@ void Expedition::ChooseNewLeader()
return false;
});
if (it == m_members.end())
if (it == members.end())
{
// no online members found, fallback to choosing any member
it = std::find_if(m_members.begin(), m_members.end(),
it = std::find_if(members.begin(), members.end(),
[&](const DynamicZoneMember& member) { return (member.id != m_leader.id); });
}
if (it != m_members.end() && SetNewLeader(*it))
if (it != members.end() && SetNewLeader(*it))
{
m_choose_leader_needed = false;
}
@@ -85,7 +86,7 @@ void Expedition::ChooseNewLeader()
bool Expedition::SetNewLeader(const DynamicZoneMember& member)
{
if (!HasMember(member.id))
if (!GetDynamicZone().HasMember(member.id))
{
return false;
}
@@ -93,7 +94,7 @@ bool Expedition::SetNewLeader(const DynamicZoneMember& member)
LogExpeditionsModerate("Replacing [{}] leader [{}] with [{}]", m_id, m_leader.name, member.name);
ExpeditionDatabase::UpdateLeaderID(m_id, member.id);
m_leader = member;
m_dynamic_zone.SetLeaderName(m_leader.name);
m_dynamic_zone.SetLeader(m_leader);
SendZonesLeaderChanged();
return true;
}
@@ -156,7 +157,7 @@ bool Expedition::Process()
{
// returns true if expedition needs to be deleted from world cache and db
// expedition is not deleted until its dz has no clients to prevent exploits
auto status = m_dynamic_zone.Process(IsEmpty()); // force expire if no members
auto status = m_dynamic_zone.Process();
if (status == DynamicZoneStatus::ExpiredEmpty)
{
LogExpeditions("Expedition [{}] expired or empty, notifying zones and deleting", GetID());
@@ -172,7 +173,13 @@ bool Expedition::Process()
void Expedition::UpdateMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status)
{
SetInternalMemberStatus(character_id, status);
GetDynamicZone().SetInternalMemberStatus(character_id, status);
// temporary until move to using dz leader object completely
if (character_id == m_leader.id)
{
m_leader.status = GetDynamicZone().GetLeader().status;
}
// any member status update will trigger a leader fix if leader was offline
if (m_leader.status == DynamicZoneMemberStatus::Offline)
@@ -183,7 +190,7 @@ void Expedition::UpdateMemberStatus(uint32_t character_id, DynamicZoneMemberStat
void Expedition::SendZoneMemberStatuses(uint16_t zone_id, uint16_t instance_id)
{
const auto& members = GetMembers();
const auto& members = GetDynamicZone().GetMembers();
uint32_t members_count = static_cast<uint32_t>(members.size());
uint32_t entries_size = sizeof(ServerExpeditionMemberStatusEntry_Struct) * members_count;
@@ -210,7 +217,7 @@ void Expedition::CacheMemberStatuses()
all_clients.reserve(client_list.GetClientCount());
client_list.GetClients(zone_name.c_str(), all_clients);
for (const auto& member : m_members)
for (const auto& member : GetDynamicZone().GetMembers())
{
auto it = std::find_if(all_clients.begin(), all_clients.end(),
[&](const ClientListEntry* cle) { return (cle && cle->CharID() == member.id); });
@@ -225,6 +232,6 @@ void Expedition::CacheMemberStatuses()
}
}
SetInternalMemberStatus(member.id, status);
GetDynamicZone().SetInternalMemberStatus(member.id, status);
}
}
+15 -13
View File
@@ -21,26 +21,28 @@
#include "expedition_database.h"
#include "expedition.h"
#include "worlddb.h"
#include "../common/repositories/dynamic_zone_members_repository.h"
void ExpeditionDatabase::PurgeExpiredExpeditions()
{
std::string query = SQL(
SELECT
expeditions.id
expeditions.id,
expeditions.dynamic_zone_id
FROM expeditions
LEFT JOIN dynamic_zones ON expeditions.dynamic_zone_id = dynamic_zones.id
LEFT JOIN instance_list ON dynamic_zones.instance_id = instance_list.id
LEFT JOIN
(
SELECT expedition_id, COUNT(IF(is_current_member = TRUE, 1, NULL)) member_count
FROM expedition_members
GROUP BY expedition_id
) expedition_members
ON expedition_members.expedition_id = expeditions.id
SELECT dynamic_zone_id, COUNT(IF(is_current_member = TRUE, 1, NULL)) member_count
FROM dynamic_zone_members
GROUP BY dynamic_zone_id
) dynamic_zone_members
ON dynamic_zone_members.dynamic_zone_id = expeditions.dynamic_zone_id
WHERE
instance_list.id IS NULL
OR expedition_members.member_count IS NULL
OR expedition_members.member_count = 0
OR dynamic_zone_members.member_count IS NULL
OR dynamic_zone_members.member_count = 0
OR (instance_list.start_time + instance_list.duration) <= UNIX_TIMESTAMP();
);
@@ -48,15 +50,18 @@ void ExpeditionDatabase::PurgeExpiredExpeditions()
if (results.Success())
{
std::vector<uint32_t> expedition_ids;
std::vector<uint32_t> dynamic_zone_ids;
for (auto row = results.begin(); row != results.end(); ++row)
{
expedition_ids.emplace_back(static_cast<uint32_t>(strtoul(row[0], nullptr, 10)));
dynamic_zone_ids.emplace_back(static_cast<uint32_t>(strtoul(row[1], nullptr, 10)));
}
if (!expedition_ids.empty())
{
ExpeditionDatabase::MoveMembersToSafeReturn(expedition_ids);
ExpeditionDatabase::DeleteExpeditions(expedition_ids);
DynamicZoneMembersRepository::RemoveAllMembers(database, dynamic_zone_ids);
}
}
}
@@ -82,9 +87,6 @@ void ExpeditionDatabase::DeleteExpeditions(const std::vector<uint32_t>& expediti
auto query = fmt::format("DELETE FROM expeditions WHERE id IN ({});", expedition_ids_query);
database.QueryDatabase(query);
query = fmt::format("DELETE FROM expedition_members WHERE expedition_id IN ({});", expedition_ids_query);
database.QueryDatabase(query);
query = fmt::format("DELETE FROM expedition_lockouts WHERE expedition_id IN ({});", expedition_ids_query);
database.QueryDatabase(query);
}
@@ -108,8 +110,8 @@ void ExpeditionDatabase::MoveMembersToSafeReturn(const std::vector<uint32_t>& ex
// only offline members still in expired dz zones should be updated here
std::string query = fmt::format(SQL(
UPDATE character_data
INNER JOIN expedition_members ON character_data.id = expedition_members.character_id
INNER JOIN expeditions ON expedition_members.expedition_id = expeditions.id
INNER JOIN dynamic_zone_members ON character_data.id = dynamic_zone_members.character_id
INNER JOIN expeditions ON dynamic_zone_members.dynamic_zone_id = expeditions.dynamic_zone_id
INNER JOIN dynamic_zones ON expeditions.dynamic_zone_id = dynamic_zones.id
INNER JOIN instance_list ON dynamic_zones.instance_id = instance_list.id
AND character_data.zone_instance = instance_list.id
+11 -9
View File
@@ -22,8 +22,9 @@
#include "expedition.h"
#include "expedition_database.h"
#include "worlddb.h"
#include "../common/dynamic_zone_base.h"
#include "../common/eqemu_logsys.h"
#include "../common/repositories/expedition_members_repository.h"
#include "../common/repositories/dynamic_zone_members_repository.h"
#include <algorithm>
ExpeditionState expedition_state;
@@ -76,16 +77,14 @@ void ExpeditionState::CacheExpeditions(
std::vector<ExpeditionsRepository::ExpeditionWithLeader>&& expedition_entries)
{
// bulk load expedition dzs and members before caching
std::vector<uint32_t> expedition_ids;
std::vector<uint32_t> dynamic_zone_ids;
for (const auto& entry : expedition_entries)
{
expedition_ids.emplace_back(entry.id);
dynamic_zone_ids.emplace_back(entry.dynamic_zone_id);
}
auto dynamic_zones = DynamicZonesRepository::GetWithInstance(database, dynamic_zone_ids);
auto expedition_members = ExpeditionMembersRepository::GetWithNames(database, expedition_ids);
auto dynamic_zone_members = DynamicZoneMembersRepository::GetWithNames(database, dynamic_zone_ids);
for (auto& entry : expedition_entries)
{
@@ -102,11 +101,11 @@ void ExpeditionState::CacheExpeditions(
expedition->SetDynamicZone(std::move(*dz_entry_iter));
}
for (auto& member : expedition_members)
for (auto& member : dynamic_zone_members)
{
if (member.expedition_id == expedition->GetID())
if (member.dynamic_zone_id == entry.dynamic_zone_id)
{
expedition->AddMemberFromRepositoryResult(std::move(member));
expedition->GetDynamicZone().AddMemberFromRepositoryResult(std::move(member));
}
}
@@ -129,7 +128,7 @@ void ExpeditionState::MemberChange(
if (remove) {
expedition->RemoveMember(member.id);
} else {
expedition->AddInternalMember(member);
expedition->GetDynamicZone().AddInternalMember(member);
}
}
}
@@ -139,7 +138,7 @@ void ExpeditionState::RemoveAllMembers(uint32_t expedition_id)
auto expedition = GetExpedition(expedition_id);
if (expedition)
{
expedition->ClearInternalMembers();
expedition->GetDynamicZone().ClearInternalMembers();
}
}
@@ -151,6 +150,7 @@ void ExpeditionState::Process()
}
std::vector<uint32_t> expedition_ids;
std::vector<uint32_t> dynamic_zone_ids;
for (auto it = m_expeditions.begin(); it != m_expeditions.end();)
{
@@ -158,6 +158,7 @@ void ExpeditionState::Process()
if (is_deleted)
{
expedition_ids.emplace_back((*it)->GetID());
dynamic_zone_ids.emplace_back((*it)->GetDynamicZone().GetID());
}
it = is_deleted ? m_expeditions.erase(it) : it + 1;
}
@@ -166,5 +167,6 @@ void ExpeditionState::Process()
{
ExpeditionDatabase::MoveMembersToSafeReturn(expedition_ids);
ExpeditionDatabase::DeleteExpeditions(expedition_ids);
DynamicZoneMembersRepository::RemoveAllMembers(database, dynamic_zone_ids);
}
}