Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Expeditions] Store members on dynamic zone #1358

Merged
merged 1 commit into from
May 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions common/database_instances.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion common/database_schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
159 changes: 150 additions & 9 deletions common/dynamic_zone_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
}
Expand All @@ -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);

std::vector<InstanceListPlayerRepository::InstanceListPlayer> insert_players;
m_members = members;

for (const auto& character_id : character_ids)
// 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& 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)
Expand Down Expand Up @@ -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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dig it

{
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";
}
27 changes: 23 additions & 4 deletions common/dynamic_zone_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -56,38 +57,55 @@ class DynamicZoneBase
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); }
bool IsValid() const { return m_instance_id != 0; }
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; }
Expand Down Expand Up @@ -122,14 +140,15 @@ class DynamicZoneBase
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;
DynamicZoneLocation m_zonein;
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
Loading