mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
[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:
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user