mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 22:58:34 +00:00
[Expeditions] Create common dz abstract class (#1312)
This creates an abstract class in common so zone and world can share most of the implementation. World now has access to the same dz data and api as zone. Rename CharacterChange to AddRemoveCharacter for clarity Rename GetRemainingDuration to GetDurationRemaining for consistency Move dynamic zone queries to custom repository methods
This commit is contained in:
@@ -16,6 +16,7 @@ SET(common_sources
|
||||
database_instances.cpp
|
||||
dbcore.cpp
|
||||
deity.cpp
|
||||
dynamic_zone_base.cpp
|
||||
emu_constants.cpp
|
||||
emu_limits.cpp
|
||||
emu_opcodes.cpp
|
||||
@@ -466,6 +467,7 @@ SET(common_headers
|
||||
database_schema.h
|
||||
dbcore.h
|
||||
deity.h
|
||||
dynamic_zone_base.h
|
||||
emu_constants.h
|
||||
emu_limits.h
|
||||
emu_opcodes.h
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
#include "dynamic_zone_base.h"
|
||||
#include "database.h"
|
||||
#include "eqemu_logsys.h"
|
||||
#include "repositories/instance_list_repository.h"
|
||||
#include "repositories/instance_list_player_repository.h"
|
||||
#include "servertalk.h"
|
||||
|
||||
DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry)
|
||||
{
|
||||
LoadRepositoryResult(std::move(entry));
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::Create()
|
||||
{
|
||||
if (m_id != 0)
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
if (GetInstanceID() == 0)
|
||||
{
|
||||
CreateInstance();
|
||||
}
|
||||
|
||||
m_id = SaveToDatabase();
|
||||
|
||||
return m_id;
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::CreateInstance()
|
||||
{
|
||||
if (m_instance_id)
|
||||
{
|
||||
LogDynamicZones("CreateInstance failed, instance id [{}] already created", m_instance_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!m_zone_id)
|
||||
{
|
||||
LogDynamicZones("CreateInstance failed, invalid zone id [{}]", m_zone_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t unused_instance_id = 0;
|
||||
if (!GetDatabase().GetUnusedInstanceID(unused_instance_id)) // todo: doesn't this race with insert?
|
||||
{
|
||||
LogDynamicZones("Failed to find unused instance id");
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_start_time = std::chrono::system_clock::now();
|
||||
m_expire_time = m_start_time + m_duration;
|
||||
|
||||
auto insert_instance = InstanceListRepository::NewEntity();
|
||||
insert_instance.id = unused_instance_id;
|
||||
insert_instance.zone = m_zone_id;
|
||||
insert_instance.version = m_zone_version;
|
||||
insert_instance.start_time = static_cast<int>(std::chrono::system_clock::to_time_t(m_start_time));
|
||||
insert_instance.duration = static_cast<int>(m_duration.count());
|
||||
insert_instance.never_expires = m_never_expires;
|
||||
|
||||
auto instance = InstanceListRepository::InsertOne(GetDatabase(), insert_instance);
|
||||
if (instance.id == 0)
|
||||
{
|
||||
LogDynamicZones("Failed to create instance [{}] for zone [{}]", unused_instance_id, m_zone_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_instance_id = instance.id;
|
||||
|
||||
return m_instance_id;
|
||||
}
|
||||
|
||||
void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneInstance&& dz_entry)
|
||||
{
|
||||
m_id = dz_entry.id;
|
||||
m_instance_id = dz_entry.instance_id;
|
||||
m_type = static_cast<DynamicZoneType>(dz_entry.type);
|
||||
m_compass.zone_id = dz_entry.compass_zone_id;
|
||||
m_compass.x = dz_entry.compass_x;
|
||||
m_compass.y = dz_entry.compass_y;
|
||||
m_compass.z = dz_entry.compass_z;
|
||||
m_safereturn.zone_id = dz_entry.safe_return_zone_id;
|
||||
m_safereturn.x = dz_entry.safe_return_x;
|
||||
m_safereturn.y = dz_entry.safe_return_y;
|
||||
m_safereturn.z = dz_entry.safe_return_z;
|
||||
m_safereturn.heading = dz_entry.safe_return_heading;
|
||||
m_zonein.x = dz_entry.zone_in_x;
|
||||
m_zonein.y = dz_entry.zone_in_y;
|
||||
m_zonein.z = dz_entry.zone_in_z;
|
||||
m_zonein.heading = dz_entry.zone_in_heading;
|
||||
m_has_zonein = (dz_entry.has_zone_in != 0);
|
||||
// instance_list portion
|
||||
m_zone_id = dz_entry.zone;
|
||||
m_zone_version = dz_entry.version;
|
||||
m_start_time = std::chrono::system_clock::from_time_t(dz_entry.start_time);
|
||||
m_duration = std::chrono::seconds(dz_entry.duration);
|
||||
m_never_expires = (dz_entry.never_expires != 0);
|
||||
m_expire_time = m_start_time + m_duration;
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::SaveToDatabase()
|
||||
{
|
||||
LogDynamicZonesDetail("Saving dz instance [{}] to database", m_instance_id);
|
||||
|
||||
if (m_instance_id != 0)
|
||||
{
|
||||
auto insert_dz = DynamicZonesRepository::NewEntity();
|
||||
insert_dz.instance_id = m_instance_id,
|
||||
insert_dz.type = static_cast<int>(m_type);
|
||||
insert_dz.compass_zone_id = m_compass.zone_id;
|
||||
insert_dz.compass_x = m_compass.x;
|
||||
insert_dz.compass_y = m_compass.y;
|
||||
insert_dz.compass_z = m_compass.z;
|
||||
insert_dz.safe_return_zone_id = m_safereturn.zone_id;
|
||||
insert_dz.safe_return_x = m_safereturn.x;
|
||||
insert_dz.safe_return_y = m_safereturn.y;
|
||||
insert_dz.safe_return_z = m_safereturn.z;
|
||||
insert_dz.safe_return_heading = m_safereturn.heading;
|
||||
insert_dz.zone_in_x = m_zonein.x;
|
||||
insert_dz.zone_in_y = m_zonein.y;
|
||||
insert_dz.zone_in_z = m_zonein.z;
|
||||
insert_dz.zone_in_heading = m_zonein.heading;
|
||||
insert_dz.has_zone_in = m_has_zonein;
|
||||
|
||||
auto inserted_dz = DynamicZonesRepository::InsertOne(GetDatabase(), insert_dz);
|
||||
return inserted_dz.id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DynamicZoneBase::AddCharacter(uint32_t character_id)
|
||||
{
|
||||
GetDatabase().AddClientToInstance(m_instance_id, character_id);
|
||||
SendInstanceAddRemoveCharacter(character_id, false); // stops client kick timer
|
||||
}
|
||||
|
||||
void DynamicZoneBase::RemoveCharacter(uint32_t character_id)
|
||||
{
|
||||
GetDatabase().RemoveClientFromInstance(m_instance_id, character_id);
|
||||
SendInstanceAddRemoveCharacter(character_id, true); // start client kick timer
|
||||
}
|
||||
|
||||
void DynamicZoneBase::RemoveAllCharacters(bool enable_removal_timers)
|
||||
{
|
||||
if (GetInstanceID() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (enable_removal_timers)
|
||||
{
|
||||
SendInstanceRemoveAllCharacters();
|
||||
}
|
||||
|
||||
GetDatabase().RemoveClientsFromInstance(GetInstanceID());
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SaveInstanceMembersToDatabase(const std::vector<uint32_t>& character_ids)
|
||||
{
|
||||
LogDynamicZonesDetail("Saving [{}] members for instance [{}]", character_ids.size(), m_instance_id);
|
||||
|
||||
std::vector<InstanceListPlayerRepository::InstanceListPlayer> insert_players;
|
||||
|
||||
for (const auto& character_id : character_ids)
|
||||
{
|
||||
InstanceListPlayerRepository::InstanceListPlayer entry{};
|
||||
entry.id = static_cast<int>(m_instance_id);
|
||||
entry.charid = static_cast<int>(character_id);
|
||||
insert_players.emplace_back(entry);
|
||||
}
|
||||
|
||||
InstanceListPlayerRepository::InsertMany(GetDatabase(), insert_players);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetCompass(const DynamicZoneLocation& location, bool update_db)
|
||||
{
|
||||
ProcessCompassChange(location);
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
LogDynamicZonesDetail("Saving [{}] compass zone: [{}] xyz: ([{}], [{}], [{}])",
|
||||
m_id, m_compass.zone_id, m_compass.x, m_compass.y, m_compass.z);
|
||||
|
||||
DynamicZonesRepository::UpdateCompass(GetDatabase(),
|
||||
m_id, m_compass.zone_id, m_compass.x, m_compass.y, m_compass.z);
|
||||
|
||||
SendGlobalLocationChange(ServerOP_DzSetCompass, location);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetCompass(uint32_t zone_id, float x, float y, float z, bool update_db)
|
||||
{
|
||||
SetCompass({ zone_id, x, y, z, 0.0f }, update_db);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetSafeReturn(const DynamicZoneLocation& location, bool update_db)
|
||||
{
|
||||
m_safereturn = location;
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
LogDynamicZonesDetail("Saving [{}] safereturn zone: [{}] xyzh: ([{}], [{}], [{}], [{}])",
|
||||
m_id, m_safereturn.zone_id, m_safereturn.x, m_safereturn.y, m_safereturn.z, m_safereturn.heading);
|
||||
|
||||
DynamicZonesRepository::UpdateSafeReturn(GetDatabase(), m_id, m_safereturn.zone_id,
|
||||
m_safereturn.x, m_safereturn.y, m_safereturn.z, m_safereturn.heading);
|
||||
|
||||
SendGlobalLocationChange(ServerOP_DzSetSafeReturn, location);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db)
|
||||
{
|
||||
SetSafeReturn({ zone_id, x, y, z, heading }, update_db);
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetZoneInLocation(const DynamicZoneLocation& location, bool update_db)
|
||||
{
|
||||
m_zonein = location;
|
||||
m_has_zonein = true;
|
||||
|
||||
if (update_db)
|
||||
{
|
||||
LogDynamicZonesDetail("Saving [{}] zonein zone: [{}] xyzh: ([{}], [{}], [{}], [{}])",
|
||||
m_id, m_zone_id, m_zonein.x, m_zonein.y, m_zonein.z, m_zonein.heading);
|
||||
|
||||
DynamicZonesRepository::UpdateZoneIn(GetDatabase(), m_id, m_zone_id,
|
||||
m_zonein.x, m_zonein.y, m_zonein.z, m_zonein.heading, m_has_zonein);
|
||||
|
||||
SendGlobalLocationChange(ServerOP_DzSetZoneIn, location);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicZoneBase::SetZoneInLocation(float x, float y, float z, float heading, bool update_db)
|
||||
{
|
||||
SetZoneInLocation({ 0, x, y, z, heading }, update_db);
|
||||
}
|
||||
|
||||
uint32_t DynamicZoneBase::GetSecondsRemaining() const
|
||||
{
|
||||
auto remaining = std::chrono::duration_cast<std::chrono::seconds>(GetDurationRemaining()).count();
|
||||
return std::max(0, static_cast<int>(remaining));
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerAddRemoveCharacterPacket(
|
||||
uint32_t character_id, bool removed)
|
||||
{
|
||||
constexpr uint32_t pack_size = sizeof(ServerDzCharacter_Struct);
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_DzAddRemoveCharacter, pack_size);
|
||||
auto buf = reinterpret_cast<ServerDzCharacter_Struct*>(pack->pBuffer);
|
||||
buf->zone_id = GetZoneID();
|
||||
buf->instance_id = GetInstanceID();
|
||||
buf->remove = removed;
|
||||
buf->character_id = character_id;
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerRemoveAllCharactersPacket()
|
||||
{
|
||||
constexpr uint32_t pack_size = sizeof(ServerDzCharacter_Struct);
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_DzRemoveAllCharacters, pack_size);
|
||||
auto buf = reinterpret_cast<ServerDzCharacter_Struct*>(pack->pBuffer);
|
||||
buf->zone_id = GetZoneID();
|
||||
buf->instance_id = GetInstanceID();
|
||||
buf->remove = true;
|
||||
buf->character_id = 0;
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzLocationPacket(
|
||||
uint16_t server_opcode, const DynamicZoneLocation& location)
|
||||
{
|
||||
constexpr uint32_t pack_size = sizeof(ServerDzLocation_Struct);
|
||||
auto pack = std::make_unique<ServerPacket>(server_opcode, pack_size);
|
||||
auto buf = reinterpret_cast<ServerDzLocation_Struct*>(pack->pBuffer);
|
||||
buf->dz_id = GetID();
|
||||
buf->sender_zone_id = GetCurrentZoneID();
|
||||
buf->sender_instance_id = GetCurrentInstanceID();
|
||||
buf->zone_id = location.zone_id;
|
||||
buf->x = location.x;
|
||||
buf->y = location.y;
|
||||
buf->z = location.z;
|
||||
buf->heading = location.heading;
|
||||
|
||||
return pack;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
#ifndef COMMON_DYNAMIC_ZONE_BASE_H
|
||||
#define COMMON_DYNAMIC_ZONE_BASE_H
|
||||
|
||||
#include "eq_constants.h"
|
||||
#include "repositories/dynamic_zones_repository.h"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Database;
|
||||
class ServerPacket;
|
||||
|
||||
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_) {}
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
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 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& GetName() const { return m_name; }
|
||||
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);
|
||||
uint32_t Create();
|
||||
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 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; }
|
||||
void SetName(const std::string& name) { m_name = name; }
|
||||
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 SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
|
||||
void SetZoneInLocation(float x, float y, float z, float heading, bool update_db = false);
|
||||
|
||||
protected:
|
||||
virtual uint16_t GetCurrentInstanceID() { return 0; }
|
||||
virtual uint16_t GetCurrentZoneID() { return 0; }
|
||||
virtual Database& GetDatabase() = 0;
|
||||
virtual void ProcessCompassChange(const DynamicZoneLocation& location) { m_compass = location; }
|
||||
virtual void SendInstanceAddRemoveCharacter(uint32_t character_id, bool remove) = 0;
|
||||
virtual void SendInstanceRemoveAllCharacters() = 0;
|
||||
virtual void SendGlobalLocationChange(uint16_t server_opcode, const DynamicZoneLocation& location) = 0;
|
||||
|
||||
uint32_t CreateInstance();
|
||||
void LoadRepositoryResult(DynamicZonesRepository::DynamicZoneInstance&& dz_entry);
|
||||
uint32_t SaveToDatabase();
|
||||
|
||||
std::unique_ptr<ServerPacket> CreateServerAddRemoveCharacterPacket(uint32_t character_id, bool removed);
|
||||
std::unique_ptr<ServerPacket> CreateServerRemoveAllCharactersPacket();
|
||||
std::unique_ptr<ServerPacket> CreateServerDzLocationPacket(uint16_t server_opcode, const DynamicZoneLocation& location);
|
||||
|
||||
uint32_t m_id = 0;
|
||||
uint32_t m_zone_id = 0;
|
||||
uint32_t m_instance_id = 0;
|
||||
uint32_t m_zone_version = 0;
|
||||
bool m_never_expires = false;
|
||||
bool m_has_zonein = false;
|
||||
std::string m_name;
|
||||
std::string m_leader_name;
|
||||
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;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -65,6 +65,241 @@ public:
|
||||
|
||||
// Custom extended repository methods here
|
||||
|
||||
struct DynamicZoneInstance
|
||||
{
|
||||
uint32_t id;
|
||||
int instance_id;
|
||||
int type;
|
||||
int compass_zone_id;
|
||||
float compass_x;
|
||||
float compass_y;
|
||||
float compass_z;
|
||||
int safe_return_zone_id;
|
||||
float safe_return_x;
|
||||
float safe_return_y;
|
||||
float safe_return_z;
|
||||
float safe_return_heading;
|
||||
float zone_in_x;
|
||||
float zone_in_y;
|
||||
float zone_in_z;
|
||||
float zone_in_heading;
|
||||
int has_zone_in;
|
||||
int zone;
|
||||
int version;
|
||||
int is_global;
|
||||
uint32_t start_time;
|
||||
int duration;
|
||||
int never_expires;
|
||||
};
|
||||
|
||||
static std::string SelectDynamicZoneJoinInstance()
|
||||
{
|
||||
return std::string(SQL(
|
||||
SELECT
|
||||
dynamic_zones.id,
|
||||
dynamic_zones.instance_id,
|
||||
dynamic_zones.type,
|
||||
dynamic_zones.compass_zone_id,
|
||||
dynamic_zones.compass_x,
|
||||
dynamic_zones.compass_y,
|
||||
dynamic_zones.compass_z,
|
||||
dynamic_zones.safe_return_zone_id,
|
||||
dynamic_zones.safe_return_x,
|
||||
dynamic_zones.safe_return_y,
|
||||
dynamic_zones.safe_return_z,
|
||||
dynamic_zones.safe_return_heading,
|
||||
dynamic_zones.zone_in_x,
|
||||
dynamic_zones.zone_in_y,
|
||||
dynamic_zones.zone_in_z,
|
||||
dynamic_zones.zone_in_heading,
|
||||
dynamic_zones.has_zone_in,
|
||||
instance_list.zone,
|
||||
instance_list.version,
|
||||
instance_list.is_global,
|
||||
instance_list.start_time,
|
||||
instance_list.duration,
|
||||
instance_list.never_expires
|
||||
FROM dynamic_zones
|
||||
INNER JOIN instance_list ON dynamic_zones.instance_id = instance_list.id
|
||||
));
|
||||
}
|
||||
|
||||
static DynamicZoneInstance FillWithInstanceFromRow(MySQLRequestRow& row)
|
||||
{
|
||||
DynamicZoneInstance entry{};
|
||||
|
||||
int col = 0;
|
||||
entry.id = strtoul(row[col++], nullptr, 10);
|
||||
entry.instance_id = strtol(row[col++], nullptr, 10);
|
||||
entry.type = strtol(row[col++], nullptr, 10);
|
||||
entry.compass_zone_id = strtol(row[col++], nullptr, 10);
|
||||
entry.compass_x = strtof(row[col++], nullptr);
|
||||
entry.compass_y = strtof(row[col++], nullptr);
|
||||
entry.compass_z = strtof(row[col++], nullptr);
|
||||
entry.safe_return_zone_id = strtol(row[col++], nullptr, 10);
|
||||
entry.safe_return_x = strtof(row[col++], nullptr);
|
||||
entry.safe_return_y = strtof(row[col++], nullptr);
|
||||
entry.safe_return_z = strtof(row[col++], nullptr);
|
||||
entry.safe_return_heading = strtof(row[col++], nullptr);
|
||||
entry.zone_in_x = strtof(row[col++], nullptr);
|
||||
entry.zone_in_y = strtof(row[col++], nullptr);
|
||||
entry.zone_in_z = strtof(row[col++], nullptr);
|
||||
entry.zone_in_heading = strtof(row[col++], nullptr);
|
||||
entry.has_zone_in = strtol(row[col++], nullptr, 10) != 0;
|
||||
// from instance_list
|
||||
entry.zone = strtol(row[col++], nullptr, 10);
|
||||
entry.version = strtol(row[col++], nullptr, 10);
|
||||
entry.is_global = strtol(row[col++], nullptr, 10);
|
||||
entry.start_time = strtoul(row[col++], nullptr, 10);
|
||||
entry.duration = strtol(row[col++], nullptr, 10);
|
||||
entry.never_expires = strtol(row[col++], nullptr, 10);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static std::vector<DynamicZoneInstance> GetWithInstance(Database& db,
|
||||
const std::vector<uint32_t>& dynamic_zone_ids)
|
||||
{
|
||||
if (dynamic_zone_ids.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<DynamicZoneInstance> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(fmt::format(
|
||||
"{} WHERE dynamic_zones.id IN ({}) ORDER BY dynamic_zones.id;",
|
||||
SelectDynamicZoneJoinInstance(),
|
||||
fmt::join(dynamic_zone_ids, ",")
|
||||
));
|
||||
|
||||
if (results.Success())
|
||||
{
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
DynamicZoneInstance entry = FillWithInstanceFromRow(row);
|
||||
all_entries.emplace_back(std::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static void UpdateCompass(Database& db, uint32_t dz_id, int zone_id, float x, float y, float z)
|
||||
{
|
||||
if (dz_id != 0)
|
||||
{
|
||||
std::string query = fmt::format(SQL(
|
||||
UPDATE {} SET
|
||||
compass_zone_id = {},
|
||||
compass_x = {},
|
||||
compass_y = {},
|
||||
compass_z = {}
|
||||
WHERE {} = {};
|
||||
), TableName(), zone_id, x, y, z, PrimaryKey(), dz_id);
|
||||
|
||||
db.QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateSafeReturn(Database& db, uint32_t dz_id, int zone_id, float x, float y, float z, float heading)
|
||||
{
|
||||
if (dz_id != 0)
|
||||
{
|
||||
std::string query = fmt::format(SQL(
|
||||
UPDATE {} SET
|
||||
safe_return_zone_id = {},
|
||||
safe_return_x = {},
|
||||
safe_return_y = {},
|
||||
safe_return_z = {},
|
||||
safe_return_heading = {}
|
||||
WHERE {} = {};
|
||||
), TableName(), zone_id, x, y, z, heading, PrimaryKey(), dz_id);
|
||||
|
||||
db.QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateZoneIn(Database& db, uint32_t dz_id, uint32_t zone_id, float x, float y, float z, float heading, bool has_zone_in)
|
||||
{
|
||||
if (dz_id != 0)
|
||||
{
|
||||
std::string query = fmt::format(SQL(
|
||||
UPDATE {} SET
|
||||
zone_in_x = {},
|
||||
zone_in_y = {},
|
||||
zone_in_z = {},
|
||||
zone_in_heading = {},
|
||||
has_zone_in = {}
|
||||
WHERE {} = {};
|
||||
), TableName(), x, y, z, heading, has_zone_in, PrimaryKey(), dz_id);
|
||||
|
||||
db.QueryDatabase(query);
|
||||
}
|
||||
}
|
||||
|
||||
struct DynamicZoneInstancePlayerCount
|
||||
{
|
||||
uint32_t id;
|
||||
int type;
|
||||
int instance;
|
||||
int zone;
|
||||
int version;
|
||||
uint32_t start_time;
|
||||
int duration;
|
||||
int player_count;
|
||||
};
|
||||
|
||||
static std::string SelectDynamicZoneInstancePlayerCount()
|
||||
{
|
||||
return std::string(SQL(
|
||||
SELECT
|
||||
dynamic_zones.id,
|
||||
dynamic_zones.type,
|
||||
instance_list.id,
|
||||
instance_list.zone,
|
||||
instance_list.version,
|
||||
instance_list.start_time,
|
||||
instance_list.duration,
|
||||
COUNT(instance_list_player.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
|
||||
GROUP BY instance_list.id
|
||||
ORDER BY dynamic_zones.id;
|
||||
));
|
||||
};
|
||||
|
||||
static std::vector<DynamicZoneInstancePlayerCount> AllDzInstancePlayerCounts(Database& db)
|
||||
{
|
||||
std::vector<DynamicZoneInstancePlayerCount> all_entries;
|
||||
|
||||
auto results = db.QueryDatabase(SelectDynamicZoneInstancePlayerCount());
|
||||
if (results.Success())
|
||||
{
|
||||
all_entries.reserve(results.RowCount());
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
{
|
||||
DynamicZoneInstancePlayerCount entry{};
|
||||
|
||||
int col = 0;
|
||||
entry.id = strtoul(row[col++], nullptr, 10);
|
||||
entry.type = strtol(row[col++], nullptr, 10);
|
||||
entry.instance = strtol(row[col++], nullptr, 10);
|
||||
entry.zone = strtol(row[col++], nullptr, 10);
|
||||
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);
|
||||
|
||||
all_entries.emplace_back(std::move(entry));
|
||||
}
|
||||
}
|
||||
return all_entries;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_DYNAMIC_ZONES_REPOSITORY_H
|
||||
|
||||
+1
-1
@@ -161,7 +161,7 @@
|
||||
#define ServerOP_ExpeditionExpireWarning 0x0416
|
||||
#define ServerOP_ExpeditionChooseNewLeader 0x0417
|
||||
|
||||
#define ServerOP_DzCharacterChange 0x0450
|
||||
#define ServerOP_DzAddRemoveCharacter 0x0450
|
||||
#define ServerOP_DzRemoveAllCharacters 0x0451
|
||||
#define ServerOP_DzSetSecondsRemaining 0x0452
|
||||
#define ServerOP_DzDurationUpdate 0x0453
|
||||
|
||||
Reference in New Issue
Block a user