mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-14 15:41:30 +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:
parent
e8b94a11f1
commit
15328196e2
@ -177,10 +177,10 @@ SET(repositories
|
||||
repositories/base/base_discovered_items_repository.h
|
||||
repositories/base/base_doors_repository.h
|
||||
repositories/base/base_dynamic_zones_repository.h
|
||||
repositories/base/base_dynamic_zone_members_repository.h
|
||||
repositories/base/base_eventlog_repository.h
|
||||
repositories/base/base_expeditions_repository.h
|
||||
repositories/base/base_expedition_lockouts_repository.h
|
||||
repositories/base/base_expedition_members_repository.h
|
||||
repositories/base/base_faction_base_data_repository.h
|
||||
repositories/base/base_faction_list_repository.h
|
||||
repositories/base/base_faction_list_mod_repository.h
|
||||
@ -341,10 +341,10 @@ SET(repositories
|
||||
repositories/discovered_items_repository.h
|
||||
repositories/doors_repository.h
|
||||
repositories/dynamic_zones_repository.h
|
||||
repositories/dynamic_zone_members_repository.h
|
||||
repositories/eventlog_repository.h
|
||||
repositories/expeditions_repository.h
|
||||
repositories/expedition_lockouts_repository.h
|
||||
repositories/expedition_members_repository.h
|
||||
repositories/faction_base_data_repository.h
|
||||
repositories/faction_list_repository.h
|
||||
repositories/faction_list_mod_repository.h
|
||||
|
||||
@ -20,6 +20,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/string_util.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/repositories/dynamic_zone_members_repository.h"
|
||||
#include "../common/repositories/dynamic_zones_repository.h"
|
||||
|
||||
#include "database.h"
|
||||
|
||||
@ -493,8 +495,8 @@ void Database::DeleteInstance(uint16 instance_id)
|
||||
query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id);
|
||||
QueryDatabase(query);
|
||||
|
||||
query = fmt::format("DELETE FROM dynamic_zones WHERE instance_id={}", instance_id);
|
||||
QueryDatabase(query);
|
||||
DynamicZoneMembersRepository::DeleteByInstance(*this, instance_id);
|
||||
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id = {}", instance_id));
|
||||
|
||||
BuryCorpsesInInstance(instance_id);
|
||||
}
|
||||
@ -585,7 +587,8 @@ void Database::PurgeExpiredInstances()
|
||||
QueryDatabase(fmt::format("DELETE FROM respawn_times WHERE instance_id IN ({})", imploded_instance_ids));
|
||||
QueryDatabase(fmt::format("DELETE FROM spawn_condition_values WHERE instance_id IN ({})", imploded_instance_ids));
|
||||
QueryDatabase(fmt::format("UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id IN ({})", imploded_instance_ids));
|
||||
QueryDatabase(fmt::format("DELETE FROM dynamic_zones WHERE instance_id IN ({})", imploded_instance_ids));
|
||||
DynamicZoneMembersRepository::DeleteByManyInstances(*this, imploded_instance_ids);
|
||||
DynamicZonesRepository::DeleteWhere(*this, fmt::format("instance_id IN ({})", imploded_instance_ids));
|
||||
}
|
||||
|
||||
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
||||
|
||||
@ -309,10 +309,10 @@ namespace DatabaseSchema {
|
||||
"banned_ips",
|
||||
"bug_reports",
|
||||
"bugs",
|
||||
"dynamic_zone_members",
|
||||
"dynamic_zones",
|
||||
"eventlog",
|
||||
"expedition_lockouts",
|
||||
"expedition_members",
|
||||
"expeditions",
|
||||
"gm_ips",
|
||||
"group_id",
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include "eqemu_logsys.h"
|
||||
#include "repositories/instance_list_repository.h"
|
||||
#include "repositories/instance_list_player_repository.h"
|
||||
#include "rulesys.h"
|
||||
#include "servertalk.h"
|
||||
|
||||
DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry)
|
||||
@ -99,6 +100,13 @@ void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneIn
|
||||
m_expire_time = m_start_time + m_duration;
|
||||
}
|
||||
|
||||
void DynamicZoneBase::AddMemberFromRepositoryResult(
|
||||
DynamicZoneMembersRepository::MemberWithName&& entry)
|
||||
{
|
||||
auto status = DynamicZoneMemberStatus::Unknown;
|
||||
AddInternalMember({ entry.character_id, std::move(entry.character_name), status });
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::SaveToDatabase()
|
||||
{
|
||||
LogDynamicZonesDetail("Saving dz instance [{}] to database", m_instance_id);
|
||||
@ -131,12 +139,14 @@ uint32_t DynamicZoneBase::SaveToDatabase()
|
||||
|
||||
void DynamicZoneBase::AddCharacter(uint32_t character_id)
|
||||
{
|
||||
DynamicZoneMembersRepository::AddMember(GetDatabase(), m_id, character_id);
|
||||
GetDatabase().AddClientToInstance(m_instance_id, character_id);
|
||||
SendInstanceAddRemoveCharacter(character_id, false); // stops client kick timer
|
||||
}
|
||||
|
||||
void DynamicZoneBase::RemoveCharacter(uint32_t character_id)
|
||||
{
|
||||
DynamicZoneMembersRepository::RemoveMember(GetDatabase(), m_id, character_id);
|
||||
GetDatabase().RemoveClientFromInstance(m_instance_id, character_id);
|
||||
SendInstanceAddRemoveCharacter(character_id, true); // start client kick timer
|
||||
}
|
||||
@ -153,24 +163,35 @@ void DynamicZoneBase::RemoveAllCharacters(bool enable_removal_timers)
|
||||
SendInstanceRemoveAllCharacters();
|
||||
}
|
||||
|
||||
DynamicZoneMembersRepository::RemoveAllMembers(GetDatabase(), m_id);
|
||||
GetDatabase().RemoveClientsFromInstance(GetInstanceID());
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SaveInstanceMembersToDatabase(const std::vector<uint32_t>& character_ids)
|
||||
void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
|
||||
{
|
||||
LogDynamicZonesDetail("Saving [{}] members for instance [{}]", character_ids.size(), m_instance_id);
|
||||
LogDynamicZonesDetail("Saving [{}] member(s) for dz [{}]", members.size(), m_id);
|
||||
|
||||
m_members = members;
|
||||
|
||||
// the lower level instance_list_players needs to be kept updated as well
|
||||
std::vector<DynamicZoneMembersRepository::DynamicZoneMembers> insert_members;
|
||||
std::vector<InstanceListPlayerRepository::InstanceListPlayer> insert_players;
|
||||
|
||||
for (const auto& character_id : character_ids)
|
||||
for (const auto& member : m_members)
|
||||
{
|
||||
InstanceListPlayerRepository::InstanceListPlayer entry{};
|
||||
entry.id = static_cast<int>(m_instance_id);
|
||||
entry.charid = static_cast<int>(character_id);
|
||||
insert_players.emplace_back(entry);
|
||||
DynamicZoneMembersRepository::DynamicZoneMembers member_entry{};
|
||||
member_entry.dynamic_zone_id = m_id;
|
||||
member_entry.character_id = member.id;
|
||||
member_entry.is_current_member = true;
|
||||
insert_members.emplace_back(member_entry);
|
||||
|
||||
InstanceListPlayerRepository::InstanceListPlayer player_entry;
|
||||
player_entry.id = static_cast<int>(m_instance_id);
|
||||
player_entry.charid = static_cast<int>(member.id);
|
||||
insert_players.emplace_back(player_entry);
|
||||
}
|
||||
|
||||
InstanceListPlayerRepository::InsertMany(GetDatabase(), insert_players);
|
||||
DynamicZoneMembersRepository::InsertOrUpdateMany(GetDatabase(), insert_members);
|
||||
InstanceListPlayerRepository::InsertOrUpdateMany(GetDatabase(), insert_players);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetCompass(const DynamicZoneLocation& location, bool update_db)
|
||||
@ -287,3 +308,123 @@ std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzLocationPacket(
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::GetDatabaseMemberCount()
|
||||
{
|
||||
return DynamicZoneMembersRepository::GetCountWhere(GetDatabase(),
|
||||
fmt::format("dynamic_zone_id = {} AND is_current_member = TRUE", m_id));
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasDatabaseMember(uint32_t character_id)
|
||||
{
|
||||
if (character_id == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto entries = DynamicZoneMembersRepository::GetWhere(GetDatabase(), fmt::format(
|
||||
"dynamic_zone_id = {} AND character_id = {} AND is_current_member = TRUE",
|
||||
m_id, character_id
|
||||
));
|
||||
|
||||
return entries.size() != 0;
|
||||
}
|
||||
|
||||
void DynamicZoneBase::AddInternalMember(const DynamicZoneMember& member)
|
||||
{
|
||||
if (!HasMember(member.id))
|
||||
{
|
||||
m_members.emplace_back(member);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::RemoveInternalMember(uint32_t character_id)
|
||||
{
|
||||
m_members.erase(std::remove_if(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) { return member.id == character_id; }
|
||||
), m_members.end());
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasMember(uint32_t character_id)
|
||||
{
|
||||
return std::any_of(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) { return member.id == character_id; });
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::HasMember(const std::string& character_name)
|
||||
{
|
||||
return std::any_of(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) {
|
||||
return strcasecmp(member.name.c_str(), character_name.c_str()) == 0;
|
||||
});
|
||||
}
|
||||
|
||||
DynamicZoneMember DynamicZoneBase::GetMemberData(uint32_t character_id)
|
||||
{
|
||||
auto it = std::find_if(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) { return member.id == character_id; });
|
||||
|
||||
DynamicZoneMember member_data;
|
||||
if (it != m_members.end())
|
||||
{
|
||||
member_data = *it;
|
||||
}
|
||||
return member_data;
|
||||
}
|
||||
|
||||
DynamicZoneMember DynamicZoneBase::GetMemberData(const std::string& character_name)
|
||||
{
|
||||
auto it = std::find_if(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) {
|
||||
return strcasecmp(member.name.c_str(), character_name.c_str()) == 0;
|
||||
});
|
||||
|
||||
DynamicZoneMember member_data;
|
||||
if (it != m_members.end())
|
||||
{
|
||||
member_data = *it;
|
||||
}
|
||||
return member_data;
|
||||
}
|
||||
|
||||
bool DynamicZoneBase::SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status)
|
||||
{
|
||||
if (status == DynamicZoneMemberStatus::InDynamicZone && !RuleB(DynamicZone, 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;
|
||||
}
|
||||
|
||||
std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
|
||||
{
|
||||
switch (dz_type)
|
||||
{
|
||||
case DynamicZoneType::Expedition:
|
||||
return "Expedition";
|
||||
case DynamicZoneType::Tutorial:
|
||||
return "Tutorial";
|
||||
case DynamicZoneType::Task:
|
||||
return "Task";
|
||||
case DynamicZoneType::Mission:
|
||||
return "Mission";
|
||||
case DynamicZoneType::Quest:
|
||||
return "Quest";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "eq_constants.h"
|
||||
#include "repositories/dynamic_zones_repository.h"
|
||||
#include "repositories/dynamic_zone_members_repository.h"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
@ -56,27 +57,42 @@ public:
|
||||
DynamicZoneBase(DynamicZoneType type) : m_type(type) {}
|
||||
DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry);
|
||||
|
||||
static std::string GetDynamicZoneTypeName(DynamicZoneType dz_type);
|
||||
|
||||
virtual void SetSecondsRemaining(uint32_t seconds_remaining) = 0;
|
||||
|
||||
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
|
||||
uint32_t GetID() const { return m_id; }
|
||||
uint16_t GetInstanceID() const { return static_cast<uint16_t>(m_instance_id); }
|
||||
uint32_t GetMaxPlayers() const { return m_max_players; }
|
||||
uint32_t GetMemberCount() const { return static_cast<uint32_t>(m_members.size()); }
|
||||
uint32_t GetMinPlayers() const { return m_min_players; }
|
||||
uint32_t GetSecondsRemaining() const;
|
||||
uint16_t GetZoneID() const { return static_cast<uint16_t>(m_zone_id); }
|
||||
uint32_t GetZoneIndex() const { return (m_instance_id << 16) | (m_zone_id & 0xffff); }
|
||||
uint32_t GetZoneVersion() const { return m_zone_version; }
|
||||
DynamicZoneType GetType() const { return m_type; }
|
||||
const std::string& GetLeaderName() const { return m_leader_name; }
|
||||
const std::string& GetLeaderName() const { return m_leader.name; }
|
||||
const std::string& GetName() const { return m_name; }
|
||||
const DynamicZoneMember& GetLeader() const { return m_leader; }
|
||||
const std::vector<DynamicZoneMember>& GetMembers() const { return m_members; }
|
||||
const DynamicZoneLocation& GetCompassLocation() const { return m_compass; }
|
||||
const DynamicZoneLocation& GetSafeReturnLocation() const { return m_safereturn; }
|
||||
const DynamicZoneLocation& GetZoneInLocation() const { return m_zonein; }
|
||||
std::chrono::system_clock::duration GetDurationRemaining() const { return m_expire_time - std::chrono::system_clock::now(); }
|
||||
|
||||
void AddCharacter(uint32_t character_id);
|
||||
void AddInternalMember(const DynamicZoneMember& member);
|
||||
void AddMemberFromRepositoryResult(DynamicZoneMembersRepository::MemberWithName&& entry);
|
||||
void ClearInternalMembers() { m_members.clear(); }
|
||||
uint32_t Create();
|
||||
uint32_t GetDatabaseMemberCount();
|
||||
DynamicZoneMember GetMemberData(uint32_t character_id);
|
||||
DynamicZoneMember GetMemberData(const std::string& character_name);
|
||||
bool HasDatabaseMember(uint32_t character_id);
|
||||
bool HasMember(uint32_t character_id);
|
||||
bool HasMember(const std::string& character_name);
|
||||
bool HasMembers() const { return !m_members.empty(); }
|
||||
bool HasZoneInLocation() const { return m_has_zonein; }
|
||||
bool IsExpired() const { return m_expire_time < std::chrono::system_clock::now(); }
|
||||
bool IsInstanceID(uint32_t instance_id) const { return (m_instance_id != 0 && m_instance_id == instance_id); }
|
||||
@ -84,10 +100,12 @@ public:
|
||||
bool IsSameDz(uint32_t zone_id, uint32_t instance_id) const { return zone_id == m_zone_id && instance_id == m_instance_id; }
|
||||
void RemoveAllCharacters(bool enable_removal_timers = true);
|
||||
void RemoveCharacter(uint32_t character_id);
|
||||
void SaveInstanceMembersToDatabase(const std::vector<uint32_t>& character_ids);
|
||||
void RemoveInternalMember(uint32_t character_id);
|
||||
void SaveMembers(const std::vector<DynamicZoneMember>& members);
|
||||
void SetCompass(const DynamicZoneLocation& location, bool update_db = false);
|
||||
void SetCompass(uint32_t zone_id, float x, float y, float z, bool update_db = false);
|
||||
void SetLeaderName(const std::string& leader_name) { m_leader_name = leader_name; }
|
||||
bool SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
void SetLeader(const DynamicZoneMember& leader) { m_leader = leader; }
|
||||
void SetMaxPlayers(uint32_t max_players) { m_max_players = max_players; }
|
||||
void SetMinPlayers(uint32_t min_players) { m_min_players = min_players; }
|
||||
void SetName(const std::string& name) { m_name = name; }
|
||||
@ -122,7 +140,7 @@ protected:
|
||||
bool m_never_expires = false;
|
||||
bool m_has_zonein = false;
|
||||
std::string m_name;
|
||||
std::string m_leader_name;
|
||||
DynamicZoneMember m_leader;
|
||||
DynamicZoneType m_type{ DynamicZoneType::None };
|
||||
DynamicZoneLocation m_compass;
|
||||
DynamicZoneLocation m_safereturn;
|
||||
@ -130,6 +148,7 @@ protected:
|
||||
std::chrono::seconds m_duration;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_start_time;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
|
||||
std::vector<DynamicZoneMember> m_members;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#include "expedition_base.h"
|
||||
#include "repositories/expeditions_repository.h"
|
||||
#include "rulesys.h"
|
||||
|
||||
ExpeditionBase::ExpeditionBase(uint32_t id, const std::string& uuid,
|
||||
const std::string& expedition_name, const DynamicZoneMember& leader
|
||||
@ -22,92 +21,3 @@ void ExpeditionBase::LoadRepositoryResult(ExpeditionsRepository::ExpeditionWithL
|
||||
m_leader.id = entry.leader_id;
|
||||
m_leader.name = std::move(entry.leader_name);
|
||||
}
|
||||
|
||||
void ExpeditionBase::AddMemberFromRepositoryResult(
|
||||
ExpeditionMembersRepository::MemberWithName&& entry)
|
||||
{
|
||||
auto status = DynamicZoneMemberStatus::Unknown;
|
||||
AddInternalMember({ entry.character_id, std::move(entry.character_name), status });
|
||||
}
|
||||
|
||||
void ExpeditionBase::AddInternalMember(const DynamicZoneMember& member)
|
||||
{
|
||||
if (!HasMember(member.id))
|
||||
{
|
||||
m_members.emplace_back(member);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionBase::RemoveInternalMember(uint32_t character_id)
|
||||
{
|
||||
m_members.erase(std::remove_if(m_members.begin(), m_members.end(),
|
||||
[&](const DynamicZoneMember& member) { return member.id == character_id; }
|
||||
), m_members.end());
|
||||
}
|
||||
|
||||
|
||||
bool ExpeditionBase::HasMember(uint32_t character_id)
|
||||
{
|
||||
return std::any_of(m_members.begin(), m_members.end(), [&](const DynamicZoneMember& member) {
|
||||
return member.id == character_id;
|
||||
});
|
||||
}
|
||||
|
||||
bool ExpeditionBase::HasMember(const std::string& character_name)
|
||||
{
|
||||
return std::any_of(m_members.begin(), m_members.end(), [&](const DynamicZoneMember& member) {
|
||||
return (strcasecmp(member.name.c_str(), character_name.c_str()) == 0);
|
||||
});
|
||||
}
|
||||
|
||||
DynamicZoneMember ExpeditionBase::GetMemberData(uint32_t character_id)
|
||||
{
|
||||
auto it = std::find_if(m_members.begin(), m_members.end(), [&](const DynamicZoneMember& member) {
|
||||
return member.id == character_id;
|
||||
});
|
||||
|
||||
DynamicZoneMember member_data;
|
||||
if (it != m_members.end())
|
||||
{
|
||||
member_data = *it;
|
||||
}
|
||||
return member_data;
|
||||
}
|
||||
|
||||
DynamicZoneMember ExpeditionBase::GetMemberData(const std::string& character_name)
|
||||
{
|
||||
auto it = std::find_if(m_members.begin(), m_members.end(), [&](const DynamicZoneMember& member) {
|
||||
return (strcasecmp(member.name.c_str(), character_name.c_str()) == 0);
|
||||
});
|
||||
|
||||
DynamicZoneMember member_data;
|
||||
if (it != m_members.end())
|
||||
{
|
||||
member_data = *it;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3,10 +3,8 @@
|
||||
|
||||
#include "dynamic_zone_base.h"
|
||||
#include "repositories/expeditions_repository.h"
|
||||
#include "repositories/expedition_members_repository.h"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ExpeditionBase
|
||||
{
|
||||
@ -19,38 +17,24 @@ public:
|
||||
|
||||
uint32_t GetID() const { return m_id; }
|
||||
uint32_t GetLeaderID() const { return m_leader.id; }
|
||||
uint32_t GetMemberCount() const { return static_cast<uint32_t>(m_members.size()); }
|
||||
const std::string& GetName() const { return m_expedition_name; }
|
||||
const std::string& GetLeaderName() const { return m_leader.name; }
|
||||
const std::string& GetUUID() const { return m_uuid; }
|
||||
const std::vector<DynamicZoneMember>& GetMembers() const { return m_members; }
|
||||
|
||||
void AddInternalMember(const DynamicZoneMember& member);
|
||||
void ClearInternalMembers() { m_members.clear(); }
|
||||
bool HasMember(const std::string& character_name);
|
||||
bool HasMember(uint32_t character_id);
|
||||
bool IsEmpty() const { return m_members.empty(); }
|
||||
void RemoveInternalMember(uint32_t character_id);
|
||||
bool SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
||||
const DynamicZoneMember& GetLeader() const { return m_leader; }
|
||||
|
||||
void LoadRepositoryResult(ExpeditionsRepository::ExpeditionWithLeader&& entry);
|
||||
void AddMemberFromRepositoryResult(ExpeditionMembersRepository::MemberWithName&& entry);
|
||||
|
||||
protected:
|
||||
ExpeditionBase() = default;
|
||||
ExpeditionBase(uint32_t id, const std::string& uuid, const std::string& expedition_name,
|
||||
const DynamicZoneMember& leader);
|
||||
|
||||
DynamicZoneMember GetMemberData(uint32_t character_id);
|
||||
DynamicZoneMember GetMemberData(const std::string& character_name);
|
||||
|
||||
uint32_t m_id = 0;
|
||||
bool m_is_locked = false;
|
||||
bool m_add_replay_on_join = true;
|
||||
std::string m_uuid;
|
||||
std::string m_expedition_name;
|
||||
DynamicZoneMember m_leader;
|
||||
std::vector<DynamicZoneMember> m_members;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -4,22 +4,22 @@
|
||||
* This repository was automatically generated and is NOT to be modified directly.
|
||||
* Any repository modifications are meant to be made to the repository extending the base.
|
||||
* Any modifications to base repositories are to be made by the generator only
|
||||
*
|
||||
*
|
||||
* @generator ./utils/scripts/generators/repository-generator.pl
|
||||
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_BASE_EXPEDITION_MEMBERS_REPOSITORY_H
|
||||
#define EQEMU_BASE_EXPEDITION_MEMBERS_REPOSITORY_H
|
||||
#ifndef EQEMU_BASE_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H
|
||||
#define EQEMU_BASE_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H
|
||||
|
||||
#include "../../database.h"
|
||||
#include "../../string_util.h"
|
||||
|
||||
class BaseExpeditionMembersRepository {
|
||||
class BaseDynamicZoneMembersRepository {
|
||||
public:
|
||||
struct ExpeditionMembers {
|
||||
struct DynamicZoneMembers {
|
||||
int id;
|
||||
int expedition_id;
|
||||
int dynamic_zone_id;
|
||||
int character_id;
|
||||
int is_current_member;
|
||||
};
|
||||
@ -33,7 +33,7 @@ public:
|
||||
{
|
||||
return {
|
||||
"id",
|
||||
"expedition_id",
|
||||
"dynamic_zone_id",
|
||||
"character_id",
|
||||
"is_current_member",
|
||||
};
|
||||
@ -46,7 +46,7 @@ public:
|
||||
|
||||
static std::string TableName()
|
||||
{
|
||||
return std::string("expedition_members");
|
||||
return std::string("dynamic_zone_members");
|
||||
}
|
||||
|
||||
static std::string BaseSelect()
|
||||
@ -67,51 +67,51 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
static ExpeditionMembers NewEntity()
|
||||
static DynamicZoneMembers NewEntity()
|
||||
{
|
||||
ExpeditionMembers entry{};
|
||||
DynamicZoneMembers entry{};
|
||||
|
||||
entry.id = 0;
|
||||
entry.expedition_id = 0;
|
||||
entry.dynamic_zone_id = 0;
|
||||
entry.character_id = 0;
|
||||
entry.is_current_member = 1;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static ExpeditionMembers GetExpeditionMembersEntry(
|
||||
const std::vector<ExpeditionMembers> &expedition_memberss,
|
||||
int expedition_members_id
|
||||
static DynamicZoneMembers GetDynamicZoneMembersEntry(
|
||||
const std::vector<DynamicZoneMembers> &dynamic_zone_memberss,
|
||||
int dynamic_zone_members_id
|
||||
)
|
||||
{
|
||||
for (auto &expedition_members : expedition_memberss) {
|
||||
if (expedition_members.id == expedition_members_id) {
|
||||
return expedition_members;
|
||||
for (auto &dynamic_zone_members : dynamic_zone_memberss) {
|
||||
if (dynamic_zone_members.id == dynamic_zone_members_id) {
|
||||
return dynamic_zone_members;
|
||||
}
|
||||
}
|
||||
|
||||
return NewEntity();
|
||||
}
|
||||
|
||||
static ExpeditionMembers FindOne(
|
||||
static DynamicZoneMembers FindOne(
|
||||
Database& db,
|
||||
int expedition_members_id
|
||||
int dynamic_zone_members_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} WHERE id = {} LIMIT 1",
|
||||
BaseSelect(),
|
||||
expedition_members_id
|
||||
dynamic_zone_members_id
|
||||
)
|
||||
);
|
||||
|
||||
auto row = results.begin();
|
||||
if (results.RowCount() == 1) {
|
||||
ExpeditionMembers entry{};
|
||||
DynamicZoneMembers entry{};
|
||||
|
||||
entry.id = atoi(row[0]);
|
||||
entry.expedition_id = atoi(row[1]);
|
||||
entry.dynamic_zone_id = atoi(row[1]);
|
||||
entry.character_id = atoi(row[2]);
|
||||
entry.is_current_member = atoi(row[3]);
|
||||
|
||||
@ -123,7 +123,7 @@ public:
|
||||
|
||||
static int DeleteOne(
|
||||
Database& db,
|
||||
int expedition_members_id
|
||||
int dynamic_zone_members_id
|
||||
)
|
||||
{
|
||||
auto results = db.QueryDatabase(
|
||||
@ -131,7 +131,7 @@ public:
|
||||
"DELETE FROM {} WHERE {} = {}",
|
||||
TableName(),
|
||||
PrimaryKey(),
|
||||
expedition_members_id
|
||||
dynamic_zone_members_id
|
||||
)
|
||||
);
|
||||
|
||||
@ -140,16 +140,16 @@ public:
|
||||
|
||||
static int UpdateOne(
|
||||
Database& db,
|
||||
ExpeditionMembers expedition_members_entry
|
||||
DynamicZoneMembers dynamic_zone_members_entry
|
||||
)
|
||||
{
|
||||
std::vector<std::string> update_values;
|
||||
|
||||
auto columns = Columns();
|
||||
|
||||
update_values.push_back(columns[1] + " = " + std::to_string(expedition_members_entry.expedition_id));
|
||||
update_values.push_back(columns[2] + " = " + std::to_string(expedition_members_entry.character_id));
|
||||
update_values.push_back(columns[3] + " = " + std::to_string(expedition_members_entry.is_current_member));
|
||||
update_values.push_back(columns[1] + " = " + std::to_string(dynamic_zone_members_entry.dynamic_zone_id));
|
||||
update_values.push_back(columns[2] + " = " + std::to_string(dynamic_zone_members_entry.character_id));
|
||||
update_values.push_back(columns[3] + " = " + std::to_string(dynamic_zone_members_entry.is_current_member));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@ -157,24 +157,24 @@ public:
|
||||
TableName(),
|
||||
implode(", ", update_values),
|
||||
PrimaryKey(),
|
||||
expedition_members_entry.id
|
||||
dynamic_zone_members_entry.id
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static ExpeditionMembers InsertOne(
|
||||
static DynamicZoneMembers InsertOne(
|
||||
Database& db,
|
||||
ExpeditionMembers expedition_members_entry
|
||||
DynamicZoneMembers dynamic_zone_members_entry
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
insert_values.push_back(std::to_string(expedition_members_entry.id));
|
||||
insert_values.push_back(std::to_string(expedition_members_entry.expedition_id));
|
||||
insert_values.push_back(std::to_string(expedition_members_entry.character_id));
|
||||
insert_values.push_back(std::to_string(expedition_members_entry.is_current_member));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.dynamic_zone_id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.character_id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.is_current_member));
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@ -185,29 +185,29 @@ public:
|
||||
);
|
||||
|
||||
if (results.Success()) {
|
||||
expedition_members_entry.id = results.LastInsertedID();
|
||||
return expedition_members_entry;
|
||||
dynamic_zone_members_entry.id = results.LastInsertedID();
|
||||
return dynamic_zone_members_entry;
|
||||
}
|
||||
|
||||
expedition_members_entry = NewEntity();
|
||||
dynamic_zone_members_entry = NewEntity();
|
||||
|
||||
return expedition_members_entry;
|
||||
return dynamic_zone_members_entry;
|
||||
}
|
||||
|
||||
static int InsertMany(
|
||||
Database& db,
|
||||
std::vector<ExpeditionMembers> expedition_members_entries
|
||||
std::vector<DynamicZoneMembers> dynamic_zone_members_entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &expedition_members_entry: expedition_members_entries) {
|
||||
for (auto &dynamic_zone_members_entry: dynamic_zone_members_entries) {
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
insert_values.push_back(std::to_string(expedition_members_entry.id));
|
||||
insert_values.push_back(std::to_string(expedition_members_entry.expedition_id));
|
||||
insert_values.push_back(std::to_string(expedition_members_entry.character_id));
|
||||
insert_values.push_back(std::to_string(expedition_members_entry.is_current_member));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.dynamic_zone_id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.character_id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.is_current_member));
|
||||
|
||||
insert_chunks.push_back("(" + implode(",", insert_values) + ")");
|
||||
}
|
||||
@ -225,9 +225,9 @@ public:
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<ExpeditionMembers> All(Database& db)
|
||||
static std::vector<DynamicZoneMembers> All(Database& db)
|
||||
{
|
||||
std::vector<ExpeditionMembers> all_entries;
|
||||
std::vector<DynamicZoneMembers> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@ -239,10 +239,10 @@ public:
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
ExpeditionMembers entry{};
|
||||
DynamicZoneMembers entry{};
|
||||
|
||||
entry.id = atoi(row[0]);
|
||||
entry.expedition_id = atoi(row[1]);
|
||||
entry.dynamic_zone_id = atoi(row[1]);
|
||||
entry.character_id = atoi(row[2]);
|
||||
entry.is_current_member = atoi(row[3]);
|
||||
|
||||
@ -252,9 +252,9 @@ public:
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<ExpeditionMembers> GetWhere(Database& db, std::string where_filter)
|
||||
static std::vector<DynamicZoneMembers> GetWhere(Database& db, std::string where_filter)
|
||||
{
|
||||
std::vector<ExpeditionMembers> all_entries;
|
||||
std::vector<DynamicZoneMembers> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@ -267,10 +267,10 @@ public:
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
ExpeditionMembers entry{};
|
||||
DynamicZoneMembers entry{};
|
||||
|
||||
entry.id = atoi(row[0]);
|
||||
entry.expedition_id = atoi(row[1]);
|
||||
entry.dynamic_zone_id = atoi(row[1]);
|
||||
entry.character_id = atoi(row[2]);
|
||||
entry.is_current_member = atoi(row[3]);
|
||||
|
||||
@ -307,4 +307,4 @@ public:
|
||||
|
||||
};
|
||||
|
||||
#endif //EQEMU_BASE_EXPEDITION_MEMBERS_REPOSITORY_H
|
||||
#endif //EQEMU_BASE_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H
|
||||
249
common/repositories/dynamic_zone_members_repository.h
Normal file
249
common/repositories/dynamic_zone_members_repository.h
Normal file
@ -0,0 +1,249 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H
|
||||
#define EQEMU_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../string_util.h"
|
||||
#include "base/base_dynamic_zone_members_repository.h"
|
||||
|
||||
class DynamicZoneMembersRepository: public BaseDynamicZoneMembersRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* This file was auto generated and can be modified and extended upon
|
||||
*
|
||||
* Base repository methods are automatically
|
||||
* generated in the "base" version of this repository. The base repository
|
||||
* is immutable and to be left untouched, while methods in this class
|
||||
* are used as extension methods for more specific persistence-layer
|
||||
* accessors or mutators.
|
||||
*
|
||||
* Base Methods (Subject to be expanded upon in time)
|
||||
*
|
||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||
*
|
||||
* InsertOne
|
||||
* UpdateOne
|
||||
* DeleteOne
|
||||
* FindOne
|
||||
* GetWhere(std::string where_filter)
|
||||
* DeleteWhere(std::string where_filter)
|
||||
* InsertMany
|
||||
* All
|
||||
*
|
||||
* Example custom methods in a repository
|
||||
*
|
||||
* DynamicZoneMembersRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* DynamicZoneMembersRepository::GetWhereNeverExpires()
|
||||
* DynamicZoneMembersRepository::GetWhereXAndY()
|
||||
* DynamicZoneMembersRepository::DeleteWhereXAndY()
|
||||
*
|
||||
* Most of the above could be covered by base methods, but if you as a developer
|
||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||
* method and encapsulate filters there
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
struct MemberWithName {
|
||||
uint32_t id;
|
||||
uint32_t dynamic_zone_id;
|
||||
uint32_t character_id;
|
||||
int is_current_member;
|
||||
std::string character_name;
|
||||
};
|
||||
|
||||
static std::string SelectMembersWithNames()
|
||||
{
|
||||
return std::string(SQL(
|
||||
SELECT
|
||||
dynamic_zone_members.id,
|
||||
dynamic_zone_members.dynamic_zone_id,
|
||||
dynamic_zone_members.character_id,
|
||||
dynamic_zone_members.is_current_member,
|
||||
character_data.name
|
||||
FROM dynamic_zone_members
|
||||
INNER JOIN character_data ON dynamic_zone_members.character_id = character_data.id
|
||||
));
|
||||
}
|
||||
|
||||
static std::vector<MemberWithName> GetWithNames(Database& db,
|
||||
const std::vector<uint32_t>& dynamic_zone_ids)
|
||||
{
|
||||
if (dynamic_zone_ids.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<MemberWithName> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(fmt::format(SQL(
|
||||
{}
|
||||
WHERE dynamic_zone_members.dynamic_zone_id IN ({})
|
||||
AND dynamic_zone_members.is_current_member = TRUE;
|
||||
),
|
||||
SelectMembersWithNames(),
|
||||
fmt::join(dynamic_zone_ids, ",")
|
||||
));
|
||||
|
||||
if (results.Success())
|
||||
{
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
MemberWithName entry{};
|
||||
|
||||
int col = 0;
|
||||
entry.id = strtoul(row[col++], nullptr, 10);
|
||||
entry.dynamic_zone_id = strtoul(row[col++], nullptr, 10);
|
||||
entry.character_id = strtoul(row[col++], nullptr, 10);
|
||||
entry.is_current_member = strtoul(row[col++], nullptr, 10);
|
||||
entry.character_name = row[col++];
|
||||
|
||||
all_entries.emplace_back(std::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static int DeleteByInstance(Database& db, int instance_id)
|
||||
{
|
||||
auto results = db.QueryDatabase(fmt::format(SQL(
|
||||
DELETE dynamic_zone_members
|
||||
FROM dynamic_zone_members
|
||||
INNER JOIN dynamic_zones ON dynamic_zone_members.dynamic_zone_id = dynamic_zones.id
|
||||
WHERE dynamic_zones.instance_id = {}
|
||||
), instance_id));
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int DeleteByManyInstances(Database& db, const std::string& joined_instance_ids)
|
||||
{
|
||||
auto results = db.QueryDatabase(fmt::format(SQL(
|
||||
DELETE dynamic_zone_members
|
||||
FROM dynamic_zone_members
|
||||
INNER JOIN dynamic_zones ON dynamic_zone_members.dynamic_zone_id = dynamic_zones.id
|
||||
WHERE dynamic_zones.instance_id IN ({})
|
||||
), joined_instance_ids));
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static int GetCountWhere(Database& db, const std::string& where_filter)
|
||||
{
|
||||
auto results = db.QueryDatabase(fmt::format(
|
||||
"SELECT COUNT(*) FROM {} WHERE {};", TableName(), where_filter));
|
||||
|
||||
uint32_t count = 0;
|
||||
if (results.Success() && results.RowCount() > 0)
|
||||
{
|
||||
auto row = results.begin();
|
||||
count = strtoul(row[0], nullptr, 10);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void AddMember(Database& db, uint32_t dynamic_zone_id, uint32_t character_id)
|
||||
{
|
||||
db.QueryDatabase(fmt::format(SQL(
|
||||
INSERT INTO {}
|
||||
(dynamic_zone_id, character_id)
|
||||
VALUES
|
||||
({}, {})
|
||||
ON DUPLICATE KEY UPDATE is_current_member = TRUE;
|
||||
),
|
||||
TableName(),
|
||||
dynamic_zone_id,
|
||||
character_id
|
||||
));
|
||||
}
|
||||
|
||||
static void RemoveMember(Database& db, uint32_t dynamic_zone_id, uint32_t character_id)
|
||||
{
|
||||
db.QueryDatabase(fmt::format(SQL(
|
||||
UPDATE {} SET is_current_member = FALSE
|
||||
WHERE dynamic_zone_id = {} AND character_id = {};
|
||||
),
|
||||
TableName(), dynamic_zone_id, character_id
|
||||
));
|
||||
}
|
||||
|
||||
static void RemoveAllMembers(Database& db, uint32_t dynamic_zone_id)
|
||||
{
|
||||
db.QueryDatabase(fmt::format(SQL(
|
||||
UPDATE {} SET is_current_member = FALSE
|
||||
WHERE dynamic_zone_id = {};
|
||||
),
|
||||
TableName(), dynamic_zone_id
|
||||
));
|
||||
}
|
||||
|
||||
static void RemoveAllMembers(Database& db, std::vector<uint32_t> dynamic_zone_ids)
|
||||
{
|
||||
if (!dynamic_zone_ids.empty())
|
||||
{
|
||||
db.QueryDatabase(fmt::format(SQL(
|
||||
UPDATE {} SET is_current_member = FALSE
|
||||
WHERE dynamic_zone_id IN ({});
|
||||
),
|
||||
TableName(), fmt::join(dynamic_zone_ids, ",")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
static int InsertOrUpdateMany(Database& db,
|
||||
const std::vector<DynamicZoneMembers>& dynamic_zone_members_entries)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &dynamic_zone_members_entry: dynamic_zone_members_entries)
|
||||
{
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.dynamic_zone_id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.character_id));
|
||||
insert_values.push_back(std::to_string(dynamic_zone_members_entry.is_current_member));
|
||||
|
||||
insert_chunks.push_back("(" + implode(",", insert_values) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE is_current_member = TRUE;",
|
||||
TableName(),
|
||||
ColumnsRaw(),
|
||||
implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H
|
||||
@ -249,7 +249,7 @@ public:
|
||||
int version;
|
||||
uint32_t start_time;
|
||||
int duration;
|
||||
int player_count;
|
||||
int member_count;
|
||||
};
|
||||
|
||||
static std::string SelectDynamicZoneInstancePlayerCount()
|
||||
@ -263,10 +263,11 @@ public:
|
||||
instance_list.version,
|
||||
instance_list.start_time,
|
||||
instance_list.duration,
|
||||
COUNT(instance_list_player.id) member_count
|
||||
COUNT(dynamic_zone_members.character_id) member_count
|
||||
FROM dynamic_zones
|
||||
INNER JOIN instance_list ON dynamic_zones.instance_id = instance_list.id
|
||||
LEFT JOIN instance_list_player ON instance_list.id = instance_list_player.id
|
||||
LEFT JOIN dynamic_zone_members ON dynamic_zones.id = dynamic_zone_members.dynamic_zone_id
|
||||
AND dynamic_zone_members.is_current_member = TRUE
|
||||
GROUP BY instance_list.id
|
||||
ORDER BY dynamic_zones.id;
|
||||
));
|
||||
@ -293,7 +294,7 @@ public:
|
||||
entry.version = strtol(row[col++], nullptr, 10);
|
||||
entry.start_time = strtoul(row[col++], nullptr, 10);
|
||||
entry.duration = strtol(row[col++], nullptr, 10);
|
||||
entry.player_count = strtol(row[col++], nullptr, 10);
|
||||
entry.member_count = strtol(row[col++], nullptr, 10);
|
||||
|
||||
all_entries.emplace_back(std::move(entry));
|
||||
}
|
||||
|
||||
@ -1,132 +0,0 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EQEMU_EXPEDITION_MEMBERS_REPOSITORY_H
|
||||
#define EQEMU_EXPEDITION_MEMBERS_REPOSITORY_H
|
||||
|
||||
#include "../database.h"
|
||||
#include "../string_util.h"
|
||||
#include "base/base_expedition_members_repository.h"
|
||||
|
||||
class ExpeditionMembersRepository: public BaseExpeditionMembersRepository {
|
||||
public:
|
||||
|
||||
/**
|
||||
* This file was auto generated and can be modified and extended upon
|
||||
*
|
||||
* Base repository methods are automatically
|
||||
* generated in the "base" version of this repository. The base repository
|
||||
* is immutable and to be left untouched, while methods in this class
|
||||
* are used as extension methods for more specific persistence-layer
|
||||
* accessors or mutators.
|
||||
*
|
||||
* Base Methods (Subject to be expanded upon in time)
|
||||
*
|
||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
||||
*
|
||||
* InsertOne
|
||||
* UpdateOne
|
||||
* DeleteOne
|
||||
* FindOne
|
||||
* GetWhere(std::string where_filter)
|
||||
* DeleteWhere(std::string where_filter)
|
||||
* InsertMany
|
||||
* All
|
||||
*
|
||||
* Example custom methods in a repository
|
||||
*
|
||||
* ExpeditionMembersRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
||||
* ExpeditionMembersRepository::GetWhereNeverExpires()
|
||||
* ExpeditionMembersRepository::GetWhereXAndY()
|
||||
* ExpeditionMembersRepository::DeleteWhereXAndY()
|
||||
*
|
||||
* Most of the above could be covered by base methods, but if you as a developer
|
||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
||||
* method and encapsulate filters there
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
struct MemberWithName {
|
||||
uint32_t id;
|
||||
uint32_t expedition_id;
|
||||
uint32_t character_id;
|
||||
int is_current_member;
|
||||
std::string character_name;
|
||||
};
|
||||
|
||||
static std::string SelectMembersWithNames()
|
||||
{
|
||||
return std::string(SQL(
|
||||
SELECT
|
||||
expedition_members.id,
|
||||
expedition_members.expedition_id,
|
||||
expedition_members.character_id,
|
||||
expedition_members.is_current_member,
|
||||
character_data.name
|
||||
FROM expedition_members
|
||||
INNER JOIN character_data ON expedition_members.character_id = character_data.id
|
||||
));
|
||||
}
|
||||
|
||||
static std::vector<MemberWithName> GetWithNames(Database& db,
|
||||
const std::vector<uint32_t>& expedition_ids)
|
||||
{
|
||||
if (expedition_ids.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<MemberWithName> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(fmt::format(SQL(
|
||||
{}
|
||||
WHERE expedition_members.expedition_id IN ({})
|
||||
AND expedition_members.is_current_member = TRUE;
|
||||
),
|
||||
SelectMembersWithNames(),
|
||||
fmt::join(expedition_ids, ",")
|
||||
));
|
||||
|
||||
if (results.Success())
|
||||
{
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
MemberWithName entry{};
|
||||
|
||||
int col = 0;
|
||||
entry.id = strtoul(row[col++], nullptr, 10);
|
||||
entry.expedition_id = strtoul(row[col++], nullptr, 10);
|
||||
entry.character_id = strtoul(row[col++], nullptr, 10);
|
||||
entry.is_current_member = strtoul(row[col++], nullptr, 10);
|
||||
entry.character_name = row[col++];
|
||||
|
||||
all_entries.emplace_back(std::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_EXPEDITION_MEMBERS_REPOSITORY_H
|
||||
@ -184,11 +184,11 @@ public:
|
||||
character_data.name,
|
||||
MAX(expeditions.id)
|
||||
FROM character_data
|
||||
LEFT JOIN expedition_members
|
||||
ON character_data.id = expedition_members.character_id
|
||||
AND expedition_members.is_current_member = TRUE
|
||||
LEFT JOIN dynamic_zone_members
|
||||
ON character_data.id = dynamic_zone_members.character_id
|
||||
AND dynamic_zone_members.is_current_member = TRUE
|
||||
LEFT JOIN expeditions
|
||||
ON expedition_members.expedition_id = expeditions.id
|
||||
ON dynamic_zone_members.dynamic_zone_id = expeditions.dynamic_zone_id
|
||||
WHERE character_data.name IN ({})
|
||||
GROUP BY character_data.id
|
||||
ORDER BY FIELD(character_data.name, {})
|
||||
@ -214,6 +214,37 @@ public:
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
static uint32_t GetIDByMemberID(Database& db, uint32_t character_id)
|
||||
{
|
||||
if (character_id == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t expedition_id = 0;
|
||||
|
||||
auto results = db.QueryDatabase(fmt::format(SQL(
|
||||
SELECT
|
||||
expeditions.id
|
||||
FROM expeditions
|
||||
INNER JOIN dynamic_zone_members
|
||||
ON expeditions.dynamic_zone_id = dynamic_zone_members.dynamic_zone_id
|
||||
WHERE
|
||||
dynamic_zone_members.character_id = {}
|
||||
AND dynamic_zone_members.is_current_member = TRUE;
|
||||
),
|
||||
character_id
|
||||
));
|
||||
|
||||
if (results.Success() && results.RowCount() > 0)
|
||||
{
|
||||
auto row = results.begin();
|
||||
expedition_id = std::strtoul(row[0], nullptr, 10);
|
||||
}
|
||||
|
||||
return expedition_id;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_EXPEDITIONS_REPOSITORY_H
|
||||
|
||||
@ -65,6 +65,34 @@ public:
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
static int InsertOrUpdateMany(Database& db,
|
||||
const std::vector<InstanceListPlayer>& instance_list_player_entries)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &instance_list_player_entry: instance_list_player_entries)
|
||||
{
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
insert_values.push_back(std::to_string(instance_list_player_entry.id));
|
||||
insert_values.push_back(std::to_string(instance_list_player_entry.charid));
|
||||
|
||||
insert_chunks.push_back("(" + implode(",", insert_values) + ")");
|
||||
}
|
||||
|
||||
std::vector<std::string> insert_values;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = VALUES(id)",
|
||||
TableName(),
|
||||
ColumnsRaw(),
|
||||
implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_INSTANCE_LIST_PLAYER_REPOSITORY_H
|
||||
|
||||
@ -742,7 +742,6 @@ RULE_CATEGORY(Expedition)
|
||||
RULE_INT(Expedition, MinStatusToBypassPlayerCountRequirements, 80, "Minimum GM status to bypass minimum player requirements for Expedition creation")
|
||||
RULE_BOOL(Expedition, AlwaysNotifyNewLeaderOnChange, false, "Always notify clients when made expedition leader. If false (live-like) new leaders are only notified when made leader via /dzmakeleader")
|
||||
RULE_REAL(Expedition, LockoutDurationMultiplier, 1.0, "Multiplies lockout duration by this value when new lockouts are added")
|
||||
RULE_BOOL(Expedition, EnableInDynamicZoneStatus, false, "Enables the 'In Dynamic Zone' member status in expedition window. If false (live-like) players inside the dynamic zone will show as 'Online'")
|
||||
RULE_INT(Expedition, ChooseLeaderCooldownTime, 2000, "Cooldown time (milliseconds) between choosing a new leader for automatic leader changes")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
@ -750,6 +749,7 @@ RULE_CATEGORY(DynamicZone)
|
||||
RULE_INT(DynamicZone, ClientRemovalDelayMS, 60000, "Delay (milliseconds) until a client is teleported out of dynamic zone after being removed as member")
|
||||
RULE_BOOL(DynamicZone, EmptyShutdownEnabled, true, "Enable early instance shutdown for dynamic zones that have no members")
|
||||
RULE_INT(DynamicZone, EmptyShutdownDelaySeconds, 1500, "Seconds to set dynamic zone instance expiration if early shutdown enabled")
|
||||
RULE_BOOL(DynamicZone, EnableInDynamicZoneStatus, false, "Enables the 'In Dynamic Zone' member status in dynamic zone window. If false (live-like) players inside the dynamic zone will show as 'Online'")
|
||||
RULE_INT(DynamicZone, WorldProcessRate, 6000, "Timer interval (milliseconds) that systems check their dynamic zone states")
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9165
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9166
|
||||
|
||||
#ifdef BOTS
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027
|
||||
|
||||
@ -419,6 +419,7 @@
|
||||
9163|2021_04_17_zone_safe_heading_changes.sql|SHOW COLUMNS FROM `zone` LIKE 'safe_heading'|empty|
|
||||
9164|2021_04_23_character_exp_modifiers.sql|SHOW TABLES LIKE 'character_exp_modifiers'|empty|
|
||||
9165|2021_04_28_idle_pathing.sql|SHOW COLUMNS FROM `spawn2` LIKE 'path_when_zone_idle'|empty|
|
||||
9166|2021_02_12_dynamic_zone_members.sql|SHOW TABLES LIKE 'dynamic_zone_members'|empty|
|
||||
|
||||
# Upgrade conditions:
|
||||
# This won't be needed after this system is implemented, but it is used database that are not
|
||||
|
||||
11
utils/sql/git/required/2021_02_12_dynamic_zone_members.sql
Normal file
11
utils/sql/git/required/2021_02_12_dynamic_zone_members.sql
Normal file
@ -0,0 +1,11 @@
|
||||
CREATE TABLE `dynamic_zone_members` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`dynamic_zone_id` int(10) unsigned NOT NULL DEFAULT 0,
|
||||
`character_id` int(10) unsigned NOT NULL DEFAULT 0,
|
||||
`is_current_member` tinyint(3) unsigned NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `dynamic_zone_id_character_id` (`dynamic_zone_id`,`character_id`),
|
||||
KEY `character_id` (`character_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
DROP TABLE `expedition_members`;
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1717,7 +1717,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
/* Task Packets */
|
||||
LoadClientTaskState();
|
||||
|
||||
m_expedition_id = ExpeditionDatabase::GetExpeditionIDFromCharacterID(CharacterID());
|
||||
m_expedition_id = ExpeditionsRepository::GetIDByMemberID(database, CharacterID());
|
||||
|
||||
/**
|
||||
* DevTools Load Settings
|
||||
|
||||
@ -6916,7 +6916,7 @@ void command_dz(Client* c, const Seperator* sep)
|
||||
expedition->GetDynamicZone().GetZoneID(),
|
||||
expedition->GetDynamicZone().GetInstanceID(),
|
||||
expedition->GetDynamicZone().GetZoneVersion(),
|
||||
expedition->GetMemberCount(),
|
||||
expedition->GetDynamicZone().GetMemberCount(),
|
||||
seconds / 3600, // hours
|
||||
(seconds / 60) % 60, // minutes
|
||||
seconds % 60 // seconds
|
||||
@ -6982,12 +6982,12 @@ void command_dz(Client* c, const Seperator* sep)
|
||||
c->Message(Chat::White, fmt::format(
|
||||
"dz id: [{}] type: [{}] {}: [{}]:[{}]:[{}] members: [{}] remaining: [{:02}:{:02}:{:02}]",
|
||||
dz.id,
|
||||
dz.type,
|
||||
DynamicZone::GetDynamicZoneTypeName(static_cast<DynamicZoneType>(dz.type)),
|
||||
zone_saylink,
|
||||
dz.zone,
|
||||
dz.instance,
|
||||
dz.version,
|
||||
dz.player_count,
|
||||
dz.member_count,
|
||||
seconds / 3600, // hours
|
||||
(seconds / 60) % 60, // minutes
|
||||
seconds % 60 // seconds
|
||||
|
||||
@ -27,8 +27,8 @@
|
||||
#include "zonedb.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "../common/expedition_lockout_timer.h"
|
||||
#include "../common/repositories/dynamic_zone_members_repository.h"
|
||||
#include "../common/repositories/expedition_lockouts_repository.h"
|
||||
#include "../common/repositories/expedition_members_repository.h"
|
||||
#include "../common/util/uuid.h"
|
||||
|
||||
extern WorldServer worldserver;
|
||||
@ -59,7 +59,7 @@ Expedition::Expedition(
|
||||
void Expedition::SetDynamicZone(DynamicZone&& dz)
|
||||
{
|
||||
dz.SetName(GetName());
|
||||
dz.SetLeaderName(GetLeaderName());
|
||||
dz.SetLeader(GetLeader());
|
||||
|
||||
m_dynamiczone = std::move(dz);
|
||||
m_dynamiczone.RegisterOnCompassChange([this]() { SendCompassUpdateToZoneMembers(); });
|
||||
@ -125,7 +125,7 @@ Expedition* Expedition::TryCreate(
|
||||
expedition->GetDynamicZone().GetMaxPlayers()
|
||||
);
|
||||
|
||||
expedition->SaveMembers(request);
|
||||
expedition->GetDynamicZone().SaveMembers(request.GetMembers());
|
||||
expedition->SaveLockouts(request);
|
||||
|
||||
auto inserted = zone->expedition_cache.emplace(expedition_id, std::move(expedition));
|
||||
@ -165,7 +165,7 @@ void Expedition::CacheExpeditions(
|
||||
}
|
||||
|
||||
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);
|
||||
auto expedition_lockouts = ExpeditionLockoutsRepository::GetWithTimestamp(database, expedition_ids);
|
||||
|
||||
for (auto& entry : expedition_entries)
|
||||
@ -183,11 +183,11 @@ void Expedition::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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,27 +258,13 @@ void Expedition::SaveLockouts(ExpeditionRequest& request)
|
||||
ExpeditionDatabase::InsertLockouts(m_id, m_lockouts);
|
||||
}
|
||||
|
||||
void Expedition::SaveMembers(ExpeditionRequest& request)
|
||||
{
|
||||
m_members = request.GetMembers();
|
||||
|
||||
std::vector<uint32_t> member_ids;
|
||||
for (const auto& member : m_members)
|
||||
{
|
||||
member_ids.emplace_back(member.id);
|
||||
}
|
||||
|
||||
ExpeditionDatabase::InsertMembers(m_id, m_members);
|
||||
m_dynamiczone.SaveInstanceMembersToDatabase(member_ids);
|
||||
}
|
||||
|
||||
Expedition* Expedition::FindCachedExpeditionByCharacterID(uint32_t character_id)
|
||||
{
|
||||
if (zone)
|
||||
{
|
||||
for (const auto& expedition : zone->expedition_cache)
|
||||
{
|
||||
if (expedition.second->HasMember(character_id))
|
||||
if (expedition.second->GetDynamicZone().HasMember(character_id))
|
||||
{
|
||||
return expedition.second.get();
|
||||
}
|
||||
@ -293,7 +279,7 @@ Expedition* Expedition::FindCachedExpeditionByCharacterName(const std::string& c
|
||||
{
|
||||
for (const auto& expedition : zone->expedition_cache)
|
||||
{
|
||||
if (expedition.second->HasMember(char_name))
|
||||
if (expedition.second->GetDynamicZone().HasMember(char_name))
|
||||
{
|
||||
return expedition.second.get();
|
||||
}
|
||||
@ -384,7 +370,7 @@ void Expedition::AddLockout(const ExpeditionLockoutTimer& lockout, bool members_
|
||||
{
|
||||
ExpeditionDatabase::InsertLockout(m_id, lockout);
|
||||
}
|
||||
ExpeditionDatabase::InsertMembersLockout(m_members, lockout);
|
||||
ExpeditionDatabase::InsertMembersLockout(GetDynamicZone().GetMembers(), lockout);
|
||||
|
||||
ProcessLockoutUpdate(lockout, false, members_only);
|
||||
SendWorldLockoutUpdate(lockout, false, members_only);
|
||||
@ -414,7 +400,7 @@ void Expedition::AddLockoutDuration(const std::string& event_name, int seconds,
|
||||
// processing lockout duration applies multiplier again in client methods,
|
||||
// update database with modified value now but pass original on
|
||||
int modified_seconds = static_cast<int>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||
ExpeditionDatabase::AddLockoutDuration(m_members, lockout, modified_seconds);
|
||||
ExpeditionDatabase::AddLockoutDuration(GetDynamicZone().GetMembers(), lockout, modified_seconds);
|
||||
|
||||
ProcessLockoutDuration(lockout, seconds, members_only);
|
||||
SendWorldLockoutDuration(lockout, seconds, members_only);
|
||||
@ -442,7 +428,7 @@ void Expedition::UpdateLockoutDuration(
|
||||
void Expedition::RemoveLockout(const std::string& event_name)
|
||||
{
|
||||
ExpeditionDatabase::DeleteLockout(m_id, event_name);
|
||||
ExpeditionDatabase::DeleteMembersLockout(m_members, m_expedition_name, event_name);
|
||||
ExpeditionDatabase::DeleteMembersLockout(GetDynamicZone().GetMembers(), m_expedition_name, event_name);
|
||||
|
||||
ExpeditionLockoutTimer lockout{m_uuid, m_expedition_name, event_name, 0, 0};
|
||||
ProcessLockoutUpdate(lockout, true);
|
||||
@ -451,12 +437,11 @@ void Expedition::RemoveLockout(const std::string& event_name)
|
||||
|
||||
bool Expedition::AddMember(const std::string& add_char_name, uint32_t add_char_id)
|
||||
{
|
||||
if (HasMember(add_char_id))
|
||||
if (GetDynamicZone().HasMember(add_char_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ExpeditionDatabase::InsertMember(m_id, add_char_id);
|
||||
m_dynamiczone.AddCharacter(add_char_id);
|
||||
|
||||
ProcessMemberAdded(add_char_name, add_char_id);
|
||||
@ -469,23 +454,20 @@ void Expedition::RemoveAllMembers(bool enable_removal_timers)
|
||||
{
|
||||
m_dynamiczone.RemoveAllCharacters(enable_removal_timers);
|
||||
|
||||
ExpeditionDatabase::DeleteAllMembers(m_id);
|
||||
|
||||
SendUpdatesToZoneMembers(true);
|
||||
SendWorldExpeditionUpdate(ServerOP_ExpeditionMembersRemoved);
|
||||
|
||||
m_members.clear();
|
||||
GetDynamicZone().ClearInternalMembers();
|
||||
}
|
||||
|
||||
bool Expedition::RemoveMember(const std::string& remove_char_name)
|
||||
{
|
||||
auto member = GetMemberData(remove_char_name);
|
||||
auto member = GetDynamicZone().GetMemberData(remove_char_name);
|
||||
if (!member.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ExpeditionDatabase::DeleteMember(m_id, member.id);
|
||||
m_dynamiczone.RemoveCharacter(member.id);
|
||||
|
||||
ProcessMemberRemoved(member.name, member.id);
|
||||
@ -501,15 +483,13 @@ void Expedition::SwapMember(Client* add_client, const std::string& remove_char_n
|
||||
return;
|
||||
}
|
||||
|
||||
auto member = GetMemberData(remove_char_name);
|
||||
auto member = GetDynamicZone().GetMemberData(remove_char_name);
|
||||
if (!member.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// make remove and add atomic to avoid racing with separate world messages
|
||||
ExpeditionDatabase::DeleteMember(m_id, member.id);
|
||||
ExpeditionDatabase::InsertMember(m_id, add_client->CharacterID());
|
||||
m_dynamiczone.RemoveCharacter(member.id);
|
||||
m_dynamiczone.AddCharacter(add_client->CharacterID());
|
||||
|
||||
@ -529,19 +509,19 @@ void Expedition::SetMemberStatus(Client* client, DynamicZoneMemberStatus status)
|
||||
|
||||
void Expedition::SendMemberStatusToZoneMembers(uint32_t update_member_id, DynamicZoneMemberStatus status)
|
||||
{
|
||||
auto member_data = GetMemberData(update_member_id);
|
||||
auto member_data = GetDynamicZone().GetMemberData(update_member_id);
|
||||
if (!member_data.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if zone already had this member status cached avoid packet update to clients
|
||||
bool changed = SetInternalMemberStatus(update_member_id, status);
|
||||
bool changed = GetDynamicZone().SetInternalMemberStatus(update_member_id, status);
|
||||
if (changed)
|
||||
{
|
||||
member_data = GetMemberData(update_member_id); // rules may override status
|
||||
member_data = GetDynamicZone().GetMemberData(update_member_id); // rules may override status
|
||||
auto outapp_member_status = CreateMemberListStatusPacket(member_data.name, member_data.status);
|
||||
for (auto& member : m_members)
|
||||
for (auto& member : GetDynamicZone().GetMembers())
|
||||
{
|
||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||
if (member_client)
|
||||
@ -673,7 +653,7 @@ bool Expedition::ProcessAddConflicts(Client* leader_client, Client* add_client,
|
||||
// member swapping integrity is handled by invite response
|
||||
if (!swapping)
|
||||
{
|
||||
auto member_count = ExpeditionDatabase::GetMemberCount(m_id);
|
||||
auto member_count = GetDynamicZone().GetDatabaseMemberCount();
|
||||
if (member_count == 0)
|
||||
{
|
||||
has_conflict = true;
|
||||
@ -734,8 +714,8 @@ void Expedition::DzInviteResponse(Client* add_client, bool accepted, const std::
|
||||
// error if swapping and character was already removed before the accept
|
||||
if (was_swap_invite)
|
||||
{
|
||||
auto swap_member = GetMemberData(swap_remove_name);
|
||||
if (!swap_member.IsValid() || !ExpeditionDatabase::HasMember(m_id, swap_member.id))
|
||||
auto swap_member = GetDynamicZone().GetMemberData(swap_remove_name);
|
||||
if (!swap_member.IsValid() || !GetDynamicZone().HasDatabaseMember(swap_member.id))
|
||||
{
|
||||
has_conflicts = true;
|
||||
}
|
||||
@ -852,7 +832,7 @@ void Expedition::DzAddPlayer(
|
||||
}
|
||||
else
|
||||
{
|
||||
auto member_data = GetMemberData(add_char_name);
|
||||
auto member_data = GetDynamicZone().GetMemberData(add_char_name);
|
||||
if (member_data.IsValid())
|
||||
{
|
||||
// live prioritizes offline message before already a member message
|
||||
@ -950,7 +930,7 @@ void Expedition::DzSwapPlayer(
|
||||
return;
|
||||
}
|
||||
|
||||
if (remove_char_name.empty() || !HasMember(remove_char_name))
|
||||
if (remove_char_name.empty() || !GetDynamicZone().HasMember(remove_char_name))
|
||||
{
|
||||
requester->MessageString(Chat::Red, DZSWAP_CANNOT_REMOVE, FormatName(remove_char_name).c_str());
|
||||
return;
|
||||
@ -966,7 +946,7 @@ void Expedition::DzPlayerList(Client* requester)
|
||||
requester->MessageString(Chat::Yellow, EXPEDITION_LEADER, m_leader.name.c_str());
|
||||
|
||||
std::string member_names;
|
||||
for (const auto& member : m_members)
|
||||
for (const auto& member : GetDynamicZone().GetMembers())
|
||||
{
|
||||
fmt::format_to(std::back_inserter(member_names), "{}, ", member.name);
|
||||
}
|
||||
@ -1017,7 +997,7 @@ void Expedition::SetLocked(
|
||||
|
||||
void Expedition::ProcessLeaderChanged(uint32_t new_leader_id)
|
||||
{
|
||||
auto new_leader = GetMemberData(new_leader_id);
|
||||
auto new_leader = GetDynamicZone().GetMemberData(new_leader_id);
|
||||
if (!new_leader.IsValid())
|
||||
{
|
||||
LogExpeditions("Processed invalid new leader id [{}] for expedition [{}]", new_leader_id, m_id);
|
||||
@ -1027,11 +1007,11 @@ void Expedition::ProcessLeaderChanged(uint32_t new_leader_id)
|
||||
LogExpeditionsModerate("Replaced [{}] leader [{}] with [{}]", m_id, m_leader.name, new_leader.name);
|
||||
|
||||
m_leader = new_leader;
|
||||
m_dynamiczone.SetLeaderName(m_leader.name);
|
||||
m_dynamiczone.SetLeader(m_leader);
|
||||
|
||||
// update each client's expedition window in this zone
|
||||
auto outapp_leader = CreateLeaderNamePacket();
|
||||
for (const auto& member : m_members)
|
||||
for (const auto& member : GetDynamicZone().GetMembers())
|
||||
{
|
||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||
if (member_client)
|
||||
@ -1074,7 +1054,7 @@ void Expedition::ProcessMakeLeader(Client* old_leader_client, Client* new_leader
|
||||
|
||||
void Expedition::ProcessMemberAdded(const std::string& char_name, uint32_t added_char_id)
|
||||
{
|
||||
AddInternalMember({ added_char_id, char_name, DynamicZoneMemberStatus::Online });
|
||||
GetDynamicZone().AddInternalMember({ added_char_id, char_name, DynamicZoneMemberStatus::Online });
|
||||
|
||||
// adds the member to this expedition and notifies both leader and new member
|
||||
Client* leader_client = entity_list.GetClientByCharID(m_leader.id);
|
||||
@ -1097,24 +1077,22 @@ void Expedition::ProcessMemberAdded(const std::string& char_name, uint32_t added
|
||||
|
||||
void Expedition::ProcessMemberRemoved(const std::string& removed_char_name, uint32_t removed_char_id)
|
||||
{
|
||||
if (m_members.empty())
|
||||
if (GetDynamicZone().GetMembers().empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto outapp_member_name = CreateMemberListNamePacket(removed_char_name, true);
|
||||
|
||||
for (auto it = m_members.begin(); it != m_members.end();)
|
||||
for (const auto& member : GetDynamicZone().GetMembers())
|
||||
{
|
||||
bool is_removed = (it->name == removed_char_name);
|
||||
|
||||
Client* member_client = entity_list.GetClientByCharID(it->id);
|
||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||
if (member_client)
|
||||
{
|
||||
// all members receive the removed player name packet
|
||||
member_client->QueuePacket(outapp_member_name.get());
|
||||
|
||||
if (is_removed)
|
||||
if (member.id == removed_char_id)
|
||||
{
|
||||
// live doesn't clear expedition info on clients removed while inside dz.
|
||||
// it instead let's the dz kick timer do it even if character zones out
|
||||
@ -1123,17 +1101,15 @@ void Expedition::ProcessMemberRemoved(const std::string& removed_char_name, uint
|
||||
member_client->SendDzCompassUpdate();
|
||||
member_client->QueuePacket(CreateInfoPacket(true).get());
|
||||
member_client->MessageString(Chat::Yellow, EXPEDITION_REMOVED,
|
||||
it->name.c_str(), m_expedition_name.c_str());
|
||||
member.name.c_str(), m_expedition_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
it = is_removed ? m_members.erase(it) : it + 1;
|
||||
}
|
||||
|
||||
LogExpeditionsDetail(
|
||||
"Processed member [{}] ({}) removal from [{}], cache member count: [{}]",
|
||||
removed_char_name, removed_char_id, m_id, m_members.size()
|
||||
);
|
||||
GetDynamicZone().RemoveInternalMember(removed_char_id);
|
||||
|
||||
LogExpeditionsDetail("Processed member [{}] ({}) removal from [{}], cache member count: [{}]",
|
||||
removed_char_name, removed_char_id, m_id, GetDynamicZone().GetMemberCount());
|
||||
}
|
||||
|
||||
void Expedition::ProcessLockoutDuration(
|
||||
@ -1152,7 +1128,7 @@ void Expedition::ProcessLockoutDuration(
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& member : m_members)
|
||||
for (const auto& member : GetDynamicZone().GetMembers())
|
||||
{
|
||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||
if (member_client)
|
||||
@ -1205,7 +1181,7 @@ void Expedition::ProcessLockoutUpdate(
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& member : m_members)
|
||||
for (const auto& member : GetDynamicZone().GetMembers())
|
||||
{
|
||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||
if (member_client)
|
||||
@ -1254,7 +1230,7 @@ void Expedition::SendMemberListToZoneMembers()
|
||||
{
|
||||
auto outapp_members = CreateMemberListPacket(false);
|
||||
|
||||
for (const auto& member : m_members)
|
||||
for (const auto& member : GetDynamicZone().GetMembers())
|
||||
{
|
||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||
if (member_client)
|
||||
@ -1266,12 +1242,12 @@ void Expedition::SendMemberListToZoneMembers()
|
||||
|
||||
void Expedition::SendUpdatesToZoneMembers(bool clear, bool message_on_clear)
|
||||
{
|
||||
if (!m_members.empty())
|
||||
if (GetDynamicZone().HasMembers())
|
||||
{
|
||||
auto outapp_info = CreateInfoPacket(clear);
|
||||
auto outapp_members = CreateMemberListPacket(clear);
|
||||
|
||||
for (const auto& member : m_members)
|
||||
for (const auto& member : GetDynamicZone().GetMembers())
|
||||
{
|
||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||
if (member_client)
|
||||
@ -1351,7 +1327,7 @@ std::unique_ptr<EQApplicationPacket> Expedition::CreateInvitePacket(
|
||||
|
||||
std::unique_ptr<EQApplicationPacket> Expedition::CreateMemberListPacket(bool clear)
|
||||
{
|
||||
uint32_t member_count = clear ? 0 : static_cast<uint32_t>(m_members.size());
|
||||
uint32_t member_count = clear ? 0 : static_cast<uint32_t>(GetDynamicZone().GetMemberCount());
|
||||
uint32_t member_entries_size = sizeof(DynamicZoneMemberEntry_Struct) * member_count;
|
||||
uint32_t outsize = sizeof(DynamicZoneMemberList_Struct) + member_entries_size;
|
||||
auto outapp = std::make_unique<EQApplicationPacket>(OP_DzMemberList, outsize);
|
||||
@ -1361,10 +1337,11 @@ std::unique_ptr<EQApplicationPacket> Expedition::CreateMemberListPacket(bool cle
|
||||
|
||||
if (!clear)
|
||||
{
|
||||
for (auto i = 0; i < m_members.size(); ++i)
|
||||
const auto& members = GetDynamicZone().GetMembers();
|
||||
for (auto i = 0; i < members.size(); ++i)
|
||||
{
|
||||
strn0cpy(buf->members[i].name, m_members[i].name.c_str(), sizeof(buf->members[i].name));
|
||||
buf->members[i].online_status = static_cast<uint8_t>(m_members[i].status);
|
||||
strn0cpy(buf->members[i].name, members[i].name.c_str(), sizeof(buf->members[i].name));
|
||||
buf->members[i].online_status = static_cast<uint8_t>(members[i].status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1662,7 +1639,7 @@ void Expedition::HandleWorldMessage(ServerPacket* pack)
|
||||
if (expedition)
|
||||
{
|
||||
expedition->SendUpdatesToZoneMembers(true);
|
||||
expedition->m_members.clear();
|
||||
expedition->GetDynamicZone().ClearInternalMembers();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1785,7 +1762,7 @@ void Expedition::HandleWorldMessage(ServerPacket* pack)
|
||||
for (uint32_t i = 0; i < buf->count; ++i)
|
||||
{
|
||||
auto status = static_cast<DynamicZoneMemberStatus>(buf->entries[i].online_status);
|
||||
expedition->SetInternalMemberStatus(buf->entries[i].character_id, status);
|
||||
expedition->GetDynamicZone().SetInternalMemberStatus(buf->entries[i].character_id, status);
|
||||
}
|
||||
expedition->SendMemberListToZoneMembers();
|
||||
}
|
||||
@ -1865,7 +1842,7 @@ void Expedition::HandleWorldMessage(ServerPacket* pack)
|
||||
|
||||
void Expedition::SendCompassUpdateToZoneMembers()
|
||||
{
|
||||
for (const auto& member : m_members)
|
||||
for (const auto& member : GetDynamicZone().GetMembers())
|
||||
{
|
||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||
if (member_client)
|
||||
@ -1979,7 +1956,7 @@ void Expedition::SendMembersExpireWarning(uint32_t minutes_remaining)
|
||||
{
|
||||
// expeditions warn members in all zones not just the dz
|
||||
auto outapp = CreateExpireWarningPacket(minutes_remaining);
|
||||
for (const auto& member : m_members)
|
||||
for (const auto& member : GetDynamicZone().GetMembers())
|
||||
{
|
||||
Client* member_client = entity_list.GetClientByCharID(member.id);
|
||||
if (member_client)
|
||||
|
||||
@ -142,7 +142,6 @@ private:
|
||||
void ProcessMemberAdded(const std::string& added_char_name, uint32_t added_char_id);
|
||||
void ProcessMemberRemoved(const std::string& removed_char_name, uint32_t removed_char_id);
|
||||
void SaveLockouts(ExpeditionRequest& request);
|
||||
void SaveMembers(ExpeditionRequest& request);
|
||||
void SendClientExpeditionInvite(
|
||||
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,
|
||||
|
||||
@ -213,67 +213,6 @@ void ExpeditionDatabase::DeleteLockout(uint32_t expedition_id, const std::string
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
uint32_t ExpeditionDatabase::GetExpeditionIDFromCharacterID(uint32_t character_id)
|
||||
{
|
||||
LogExpeditionsDetail("Getting expedition id for character [{}]", character_id);
|
||||
|
||||
uint32_t expedition_id = 0;
|
||||
auto query = fmt::format(SQL(
|
||||
SELECT expedition_id FROM expedition_members
|
||||
WHERE character_id = {} AND is_current_member = TRUE;
|
||||
), character_id);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (results.Success() && results.RowCount() > 0)
|
||||
{
|
||||
auto row = results.begin();
|
||||
expedition_id = strtoul(row[0], nullptr, 10);
|
||||
}
|
||||
return expedition_id;
|
||||
}
|
||||
|
||||
uint32_t ExpeditionDatabase::GetMemberCount(uint32_t expedition_id)
|
||||
{
|
||||
LogExpeditionsDetail("Getting expedition [{}] member count from db", expedition_id);
|
||||
|
||||
uint32_t member_count = 0;
|
||||
if (expedition_id != 0)
|
||||
{
|
||||
auto query = fmt::format(SQL(
|
||||
SELECT COUNT(*)
|
||||
FROM expedition_members
|
||||
WHERE expedition_id = {} AND is_current_member = TRUE;
|
||||
), expedition_id);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (results.Success() && results.RowCount() > 0)
|
||||
{
|
||||
auto row = results.begin();
|
||||
member_count = strtoul(row[0], nullptr, 10);
|
||||
}
|
||||
}
|
||||
return member_count;
|
||||
}
|
||||
|
||||
bool ExpeditionDatabase::HasMember(uint32_t expedition_id, uint32_t character_id)
|
||||
{
|
||||
LogExpeditionsDetail("Checking db expedition [{}] for character [{}]", expedition_id, character_id);
|
||||
|
||||
if (expedition_id == 0 || character_id == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
SELECT id
|
||||
FROM expedition_members
|
||||
WHERE expedition_id = {} AND character_id = {} AND is_current_member = TRUE;
|
||||
), expedition_id, character_id);
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
return (results.Success() && results.RowCount() > 0);
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::InsertCharacterLockouts(uint32_t character_id,
|
||||
const std::vector<ExpeditionLockoutTimer>& lockouts)
|
||||
{
|
||||
@ -415,50 +354,6 @@ void ExpeditionDatabase::InsertLockouts(
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::InsertMember(uint32_t expedition_id, uint32_t character_id)
|
||||
{
|
||||
LogExpeditionsDetail("Inserting character [{}] into expedition [{}]", character_id, expedition_id);
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
INSERT INTO expedition_members
|
||||
(expedition_id, character_id)
|
||||
VALUES
|
||||
({}, {})
|
||||
ON DUPLICATE KEY UPDATE is_current_member = TRUE;
|
||||
), expedition_id, character_id);
|
||||
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::InsertMembers(
|
||||
uint32_t expedition_id, const std::vector<DynamicZoneMember>& members)
|
||||
{
|
||||
LogExpeditionsDetail("Inserting characters into expedition [{}]", expedition_id);
|
||||
|
||||
std::string insert_values;
|
||||
for (const auto& member : members)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(insert_values),
|
||||
"({}, {}),",
|
||||
expedition_id, member.id
|
||||
);
|
||||
}
|
||||
|
||||
if (!insert_values.empty())
|
||||
{
|
||||
insert_values.pop_back(); // trailing comma
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
INSERT INTO expedition_members
|
||||
(expedition_id, character_id)
|
||||
VALUES {}
|
||||
ON DUPLICATE KEY UPDATE is_current_member = TRUE;
|
||||
), insert_values);
|
||||
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::UpdateLockState(uint32_t expedition_id, bool is_locked)
|
||||
{
|
||||
LogExpeditionsDetail("Updating lock state [{}] for expedition [{}]", is_locked, expedition_id);
|
||||
@ -470,29 +365,6 @@ void ExpeditionDatabase::UpdateLockState(uint32_t expedition_id, bool is_locked)
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::DeleteMember(uint32_t expedition_id, uint32_t character_id)
|
||||
{
|
||||
LogExpeditionsDetail("Removing member [{}] from expedition [{}]", character_id, expedition_id);
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
UPDATE expedition_members SET is_current_member = FALSE
|
||||
WHERE expedition_id = {} AND character_id = {};
|
||||
), expedition_id, character_id);
|
||||
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::DeleteAllMembers(uint32_t expedition_id)
|
||||
{
|
||||
LogExpeditionsDetail("Removing all members of expedition [{}]", expedition_id);
|
||||
|
||||
auto query = fmt::format(SQL(
|
||||
UPDATE expedition_members SET is_current_member = FALSE WHERE expedition_id = {};
|
||||
), expedition_id);
|
||||
|
||||
database.QueryDatabase(query);
|
||||
}
|
||||
|
||||
void ExpeditionDatabase::UpdateReplayLockoutOnJoin(uint32_t expedition_id, bool add_on_join)
|
||||
{
|
||||
LogExpeditionsDetail("Updating replay lockout on join [{}] for expedition [{}]", add_on_join, expedition_id);
|
||||
|
||||
@ -41,8 +41,6 @@ namespace ExpeditionDatabase
|
||||
std::vector<ExpeditionLockoutTimer> LoadCharacterLockouts(uint32_t character_id);
|
||||
std::vector<ExpeditionLockoutTimer> LoadCharacterLockouts(uint32_t character_id,
|
||||
const std::string& expedition_name);
|
||||
void DeleteAllMembers(uint32_t expedition_id);
|
||||
void DeleteMember(uint32_t expedition_id, uint32_t character_id);
|
||||
void DeleteAllCharacterLockouts(uint32_t character_id);
|
||||
void DeleteAllCharacterLockouts(uint32_t character_id, const std::string& expedition_name);
|
||||
void DeleteCharacterLockout(uint32_t character_id, const std::string& expedition_name,
|
||||
@ -50,9 +48,6 @@ namespace ExpeditionDatabase
|
||||
void DeleteLockout(uint32_t expedition_id, const std::string& event_name);
|
||||
void DeleteMembersLockout(const std::vector<DynamicZoneMember>& members,
|
||||
const std::string& expedition_name, const std::string& event_name);
|
||||
uint32_t GetExpeditionIDFromCharacterID(uint32_t character_id);
|
||||
uint32_t GetMemberCount(uint32_t expedition_id);
|
||||
bool HasMember(uint32_t expedition_id, uint32_t character_id);
|
||||
void InsertCharacterLockouts(uint32_t character_id,
|
||||
const std::vector<ExpeditionLockoutTimer>& lockouts);
|
||||
void InsertMembersLockout(const std::vector<DynamicZoneMember>& members,
|
||||
@ -60,8 +55,6 @@ namespace ExpeditionDatabase
|
||||
void InsertLockout(uint32_t expedition_id, const ExpeditionLockoutTimer& lockout);
|
||||
void InsertLockouts(uint32_t expedition_id,
|
||||
const std::unordered_map<std::string, ExpeditionLockoutTimer>& lockouts);
|
||||
void InsertMember(uint32_t expedition_id, uint32_t character_id);
|
||||
void InsertMembers(uint32_t expedition_id, const std::vector<DynamicZoneMember>& members);
|
||||
void UpdateLockState(uint32_t expedition_id, bool is_locked);
|
||||
void UpdateReplayLockoutOnJoin(uint32_t expedition_id, bool add_on_join);
|
||||
void AddLockoutDuration(const std::vector<DynamicZoneMember>& members,
|
||||
|
||||
@ -47,8 +47,8 @@ public:
|
||||
const std::string& GetNotAllAddedMessage() const { return m_not_all_added_msg; }
|
||||
uint32_t GetMinPlayers() const { return m_min_players; }
|
||||
uint32_t GetMaxPlayers() const { return m_max_players; }
|
||||
std::vector<DynamicZoneMember> GetMembers() const { return m_members; }
|
||||
std::unordered_map<std::string, ExpeditionLockoutTimer> GetLockouts() const { return m_lockouts; }
|
||||
const std::vector<DynamicZoneMember>& GetMembers() const { return m_members; }
|
||||
const std::unordered_map<std::string, ExpeditionLockoutTimer>& GetLockouts() const { return m_lockouts; }
|
||||
|
||||
private:
|
||||
bool CanMembersJoin(const std::vector<std::string>& member_names);
|
||||
|
||||
@ -104,7 +104,7 @@ std::string Lua_Expedition::GetLootEventBySpawnID(uint32_t spawn_id) {
|
||||
|
||||
uint32_t Lua_Expedition::GetMemberCount() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetMemberCount();
|
||||
return self->GetDynamicZone().GetMemberCount();
|
||||
}
|
||||
|
||||
luabind::object Lua_Expedition::GetMembers(lua_State* L) {
|
||||
@ -113,7 +113,7 @@ luabind::object Lua_Expedition::GetMembers(lua_State* L) {
|
||||
if (d_)
|
||||
{
|
||||
auto self = reinterpret_cast<NativeType*>(d_);
|
||||
for (const auto& member : self->GetMembers())
|
||||
for (const auto& member : self->GetDynamicZone().GetMembers())
|
||||
{
|
||||
lua_table[member.name] = member.id;
|
||||
}
|
||||
|
||||
@ -247,7 +247,7 @@ XS(XS_Expedition_GetMemberCount) {
|
||||
Expedition* THIS = nullptr;
|
||||
VALIDATE_THIS_IS_EXPEDITION;
|
||||
|
||||
XSRETURN_UV(THIS->GetMemberCount());
|
||||
XSRETURN_UV(THIS->GetDynamicZone().GetMemberCount());
|
||||
}
|
||||
|
||||
XS(XS_Expedition_GetMembers);
|
||||
@ -262,8 +262,7 @@ XS(XS_Expedition_GetMembers) {
|
||||
|
||||
HV* hash = newHV();
|
||||
|
||||
auto members = THIS->GetMembers();
|
||||
for (const auto& member : members)
|
||||
for (const auto& member : THIS->GetDynamicZone().GetMembers())
|
||||
{
|
||||
hv_store(hash, member.name.c_str(), static_cast<uint32_t>(member.name.size()),
|
||||
newSVuv(member.id), 0);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user