mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-02 08:12:25 +00:00
- License was intended to be GPLv3 per earlier commit of GPLv3 LICENSE FILE - This is confirmed by the inclusion of libraries that are incompatible with GPLv2 - This is also confirmed by KLS and the agreement of KLS's predecessors - Added GPLv3 license headers to the compilable source files - Removed Folly licensing in strings.h since the string functions do not match the Folly functions and are standard functions - this must have been left over from previous implementations - Removed individual contributor license headers since the project has been under the "developer" mantle for many years - Removed comments on files that were previously automatically generated since they've been manually modified multiple times and there are no automatic scripts referencing them (removed in 2023)
290 lines
12 KiB
C++
290 lines
12 KiB
C++
/* EQEmu: EQEmulator
|
|
|
|
Copyright (C) 2001-2026 EQEmu Development Team
|
|
|
|
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; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#pragma once
|
|
|
|
#include "common/dynamic_zone_lockout.h"
|
|
#include "common/eq_constants.h"
|
|
#include "common/repositories/dynamic_zone_members_repository.h"
|
|
#include "common/repositories/dynamic_zone_templates_repository.h"
|
|
#include "common/repositories/dynamic_zones_repository.h"
|
|
|
|
#include <algorithm>
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <span>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
class Database;
|
|
class ServerPacket;
|
|
|
|
// message string 8312 added in September 08 2020 Test patch (used by both dz and shared tasks)
|
|
inline constexpr char DzNotAllAdded[] = "Not all players in your {0} were added to the {1}. The {1} can take a maximum of {2} players, and your {0} has {3}.";
|
|
|
|
enum class DzLockMsg : uint8_t
|
|
{
|
|
None = 0, Close, Begin
|
|
};
|
|
|
|
enum class DynamicZoneType
|
|
{
|
|
None = 0,
|
|
Expedition,
|
|
Tutorial,
|
|
Task,
|
|
Mission, // Shared Task
|
|
Quest
|
|
};
|
|
|
|
enum class DynamicZoneMemberStatus
|
|
{
|
|
Unknown = 0,
|
|
Online,
|
|
Offline,
|
|
InDynamicZone,
|
|
LinkDead
|
|
};
|
|
|
|
struct DynamicZoneMember
|
|
{
|
|
uint32_t id = 0;
|
|
std::string name;
|
|
DynamicZoneMemberStatus status = DynamicZoneMemberStatus::Unknown;
|
|
|
|
DynamicZoneMember() = default;
|
|
DynamicZoneMember(uint32_t id, std::string name_)
|
|
: id(id), name{std::move(name_)} {}
|
|
DynamicZoneMember(uint32_t id, std::string name_, DynamicZoneMemberStatus status_)
|
|
: id(id), name{std::move(name_)}, status(status_) {}
|
|
|
|
bool IsOnline() const { return status == DynamicZoneMemberStatus::Online ||
|
|
status == DynamicZoneMemberStatus::InDynamicZone; }
|
|
bool IsValid() const { return id != 0 && !name.empty(); }
|
|
|
|
template<class Archive>
|
|
void serialize(Archive& archive)
|
|
{
|
|
archive(id, name, status);
|
|
}
|
|
};
|
|
|
|
struct DynamicZoneLocation
|
|
{
|
|
uint32_t zone_id = 0;
|
|
float x = 0.0f;
|
|
float y = 0.0f;
|
|
float z = 0.0f;
|
|
float heading = 0.0f;
|
|
|
|
DynamicZoneLocation() = default;
|
|
DynamicZoneLocation(uint32_t zone_id_, float x_, float y_, float z_, float heading_)
|
|
: zone_id(zone_id_), x(x_), y(y_), z(z_), heading(heading_) {}
|
|
|
|
template<class Archive>
|
|
void serialize(Archive& archive)
|
|
{
|
|
archive(zone_id, x, y, z, heading);
|
|
}
|
|
};
|
|
|
|
class DynamicZoneBase
|
|
{
|
|
public:
|
|
virtual ~DynamicZoneBase() = default;
|
|
DynamicZoneBase(const DynamicZoneBase&) = default;
|
|
DynamicZoneBase(DynamicZoneBase&&) = default;
|
|
DynamicZoneBase& operator=(const DynamicZoneBase&) = default;
|
|
DynamicZoneBase& operator=(DynamicZoneBase&&) = default;
|
|
DynamicZoneBase() = default;
|
|
DynamicZoneBase(uint32_t dz_id) : m_id(dz_id) {}
|
|
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;
|
|
|
|
int GetDuration() const { return static_cast<int>(m_duration.count()); }
|
|
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 GetLeaderID() const { return m_leader.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; }
|
|
int GetSwitchID() const { return m_dz_switch_id; }
|
|
DynamicZoneType GetType() const { return m_type; }
|
|
const std::string& GetLeaderName() const { return m_leader.name; }
|
|
const std::string& GetName() const { return m_name; }
|
|
const std::string& GetUUID() const { return m_uuid; }
|
|
const DynamicZoneMember& GetLeader() const { return m_leader; }
|
|
const std::vector<DzLockout>& GetLockouts() const { return m_lockouts; }
|
|
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(); }
|
|
|
|
bool AddMember(const DynamicZoneMember& add_member);
|
|
void AddMemberFromRepositoryResult(DynamicZoneMembersRepository::MemberWithName&& entry);
|
|
uint32_t GetDatabaseMemberCount();
|
|
DynamicZoneMember GetMemberData(uint32_t character_id);
|
|
DynamicZoneMember GetMemberData(const std::string& character_name);
|
|
std::vector<uint32_t> GetMemberIds();
|
|
std::ostringstream GetSerialized();
|
|
bool HasDatabaseMember(uint32_t character_id);
|
|
bool HasMember(uint32_t character_id) const;
|
|
bool HasMember(const std::string& character_name) const;
|
|
bool HasMembers() const { return !m_members.empty(); }
|
|
bool HasZoneInLocation() const { return m_has_zonein; }
|
|
bool IsExpedition() const { return m_type == DynamicZoneType::Expedition; }
|
|
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 IsLocked() const { return m_is_locked; }
|
|
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 LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template);
|
|
void RemoveAllMembers();
|
|
bool RemoveMember(uint32_t character_id);
|
|
bool RemoveMember(const std::string& character_name);
|
|
bool RemoveMember(const DynamicZoneMember& remove_member);
|
|
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 SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
|
|
void SetLeader(const DynamicZoneMember& leader, bool update_db = false);
|
|
void SetLocked(bool lock, bool update_db = false, DzLockMsg lock_msg = DzLockMsg::None, uint32_t color = Chat::Yellow);
|
|
void SetMaxPlayers(uint32_t max_players) { m_max_players = max_players; }
|
|
void SetMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
|
void SetMinPlayers(uint32_t min_players) { m_min_players = min_players; }
|
|
void SetName(const std::string& name) { m_name = name; }
|
|
void SetReplayOnJoin(bool enabled, bool update_db = false);
|
|
void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false);
|
|
void SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false);
|
|
void SetSwitchID(int dz_switch_id, bool update_db = false);
|
|
void SetType(DynamicZoneType type) { m_type = type; }
|
|
void SetUUID(std::string uuid) { m_uuid = std::move(uuid); }
|
|
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
|
|
void SetZoneInLocation(float x, float y, float z, float heading, bool update_db = false);
|
|
bool SwapMember(const DynamicZoneMember& add_member, const std::string& remove_name);
|
|
|
|
void AddLockout(const std::string& event, uint32_t seconds);
|
|
void AddLockoutDuration(const std::string& event, int seconds, bool members_only = true);
|
|
bool HasLockout(const std::string& event);
|
|
bool HasReplayLockout();
|
|
void RemoveLockout(const std::string& event);
|
|
void SyncCharacterLockouts(uint32_t char_id, std::vector<DzLockout>& lockouts);
|
|
void UpdateLockoutDuration(const std::string& event, uint32_t seconds, bool members_only = true);
|
|
|
|
protected:
|
|
virtual uint16_t GetCurrentInstanceID() const { return 0; }
|
|
virtual uint16_t GetCurrentZoneID() const { return 0; }
|
|
virtual Database& GetDatabase() = 0;
|
|
virtual void HandleLockoutDuration(const DzLockout& lockout, int seconds, bool members_only, bool insert_db);
|
|
virtual void HandleLockoutUpdate(const DzLockout& lockout, bool remove, bool members_only);
|
|
virtual void ProcessCompassChange(const DynamicZoneLocation& location) { m_compass = location; }
|
|
virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed);
|
|
virtual bool ProcessMemberStatusChange(uint32_t character_id, DynamicZoneMemberStatus status);
|
|
virtual void ProcessRemoveAllMembers() { m_members.clear(); }
|
|
virtual void ProcessSetSwitchID(int dz_switch_id) { m_dz_switch_id = dz_switch_id; }
|
|
virtual bool SendServerPacket(ServerPacket* packet) = 0;
|
|
|
|
void AddLockout(const DzLockout& lockout, bool members_only = false);
|
|
void AddInternalMember(const DynamicZoneMember& member);
|
|
uint32_t Create();
|
|
uint32_t CreateInstance();
|
|
void LoadRepositoryResult(DynamicZonesRepository::DynamicZoneInstance&& dz_entry);
|
|
void RemoveInternalMember(uint32_t character_id);
|
|
void SaveMembers(const std::vector<DynamicZoneMember>& members);
|
|
uint32_t SaveToDatabase();
|
|
bool SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
|
|
|
|
std::unique_ptr<ServerPacket> CreateServerPacket(uint16_t zone_id, uint16_t instance_id);
|
|
std::unique_ptr<ServerPacket> CreateServerDzLocationPacket(uint16_t server_opcode, const DynamicZoneLocation& location);
|
|
std::unique_ptr<ServerPacket> CreateServerDzSwitchIDPacket();
|
|
std::unique_ptr<ServerPacket> CreateServerMemberAddRemovePacket(const DynamicZoneMember& member, bool removed);
|
|
std::unique_ptr<ServerPacket> CreateServerMemberStatusPacket(uint32_t character_id, DynamicZoneMemberStatus status);
|
|
std::unique_ptr<ServerPacket> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member);
|
|
std::unique_ptr<ServerPacket> CreateServerRemoveAllMembersPacket();
|
|
std::unique_ptr<ServerPacket> CreateLockoutPacket(const DzLockout& lockout, bool remove, bool members_only = false) const;
|
|
std::unique_ptr<ServerPacket> CreateLockoutDurationPacket(const DzLockout& lockout, int seconds, bool members_only = false) const;
|
|
|
|
uint32_t m_id = 0;
|
|
uint32_t m_zone_id = 0;
|
|
uint32_t m_instance_id = 0;
|
|
uint32_t m_zone_version = 0;
|
|
uint32_t m_min_players = 0;
|
|
uint32_t m_max_players = 0;
|
|
int m_dz_switch_id = 0;
|
|
bool m_never_expires = false;
|
|
bool m_has_zonein = false;
|
|
bool m_has_member_statuses = false;
|
|
bool m_is_locked = false;
|
|
bool m_add_replay = true;
|
|
std::string m_name;
|
|
std::string m_uuid;
|
|
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;
|
|
std::vector<DzLockout> m_lockouts;
|
|
|
|
public:
|
|
void Unserialize(std::span<char> buf);
|
|
|
|
template<class Archive>
|
|
void serialize(Archive& archive)
|
|
{
|
|
archive(
|
|
m_id,
|
|
m_zone_id,
|
|
m_instance_id,
|
|
m_zone_version,
|
|
m_min_players,
|
|
m_max_players,
|
|
m_dz_switch_id,
|
|
m_never_expires,
|
|
m_has_zonein,
|
|
m_has_member_statuses,
|
|
m_is_locked,
|
|
m_add_replay,
|
|
m_name,
|
|
m_uuid,
|
|
m_leader,
|
|
m_type,
|
|
m_compass,
|
|
m_safereturn,
|
|
m_zonein,
|
|
m_duration,
|
|
m_start_time,
|
|
m_expire_time,
|
|
m_members,
|
|
m_lockouts
|
|
);
|
|
}
|
|
};
|