[Expeditions] Move expedition code into DynamicZone (#4672)

This removes the separate Expedition class and moves lockout code and
/dz command handlers into DynamicZone classes. It also refactors some
code to reduce bloat and some database usage.

This completes the effort of moving everything to DynamicZone that
started when implementing shared tasks. It also makes sense to do this
since expeditions are just dynamic zones internally despite dzs being
used for other types. Expedition specific things are just handled with
dz type checks.

Functionally nothing should change. This is mainly internal refactoring
and moving code around along with some bug fixes and reduced database
usage.

Main changes:

 - The `expeditions` database table has been removed

 - Expeditions no longer use a separate id, the expedition id is just the dz id

 - Expedition lock state and replay timer option were moved to the
   `dynamic_zones` table

 - Expeditions no longer have a separate cache from dynamic zones

 - Expedition creation no longer has every zone query the database to cache it

 - Expedition internal lockouts are now stored on DynamicZone

 - The `expedition_lockouts` table has been renamed to `dynamic_zone_lockouts`

 - Fixed a small bug with the UpdateLockoutDuration api where the
   internal lockout would get the time added twice in memory in the
   initiating zone (this api is likely rarely used)

 - Fixed an issue where use of the group/raid DoesAnyMemberHaveExpeditionLockout
   api would query once for every out of zone character.

   - This api now checks all members in the current zone first and only
     performs a single bulk query for out of zone members if that check
     is exhausted

 - Deprecated the max_check_count param of DoesAnyMemberHaveExpeditionLockout,
   the quest api still exists to avoid api break but a passed arg has no effect
This commit is contained in:
hg 2025-02-15 19:40:35 -05:00 committed by GitHub
parent ab4e1191ef
commit 55155ff800
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
78 changed files with 2889 additions and 4778 deletions

View File

@ -22,6 +22,7 @@ SET(common_sources
dbcore.cpp
deity.cpp
dynamic_zone_base.cpp
dynamic_zone_lockout.cpp
emu_constants.cpp
emu_limits.cpp
emu_opcodes.cpp
@ -40,7 +41,6 @@ SET(common_sources
events/player_event_logs.cpp
events/player_event_discord_formatter.cpp
evolving_items.cpp
expedition_lockout_timer.cpp
extprofile.cpp
discord/discord_manager.cpp
faction.cpp
@ -213,10 +213,9 @@ 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_lockouts_repository.h
repositories/base/base_dynamic_zone_members_repository.h
repositories/base/base_dynamic_zone_templates_repository.h
repositories/base/base_expeditions_repository.h
repositories/base/base_expedition_lockouts_repository.h
repositories/base/base_faction_association_repository.h
repositories/base/base_faction_base_data_repository.h
repositories/base/base_faction_list_repository.h
@ -410,10 +409,9 @@ SET(repositories
repositories/discovered_items_repository.h
repositories/doors_repository.h
repositories/dynamic_zones_repository.h
repositories/dynamic_zone_lockouts_repository.h
repositories/dynamic_zone_members_repository.h
repositories/dynamic_zone_templates_repository.h
repositories/expeditions_repository.h
repositories/expedition_lockouts_repository.h
repositories/faction_association_repository.h
repositories/faction_base_data_repository.h
repositories/faction_list_repository.h
@ -561,6 +559,7 @@ SET(common_headers
discord/discord.h
discord/discord_manager.h
dynamic_zone_base.h
dynamic_zone_lockout.h
emu_constants.h
emu_limits.h
emu_opcodes.h
@ -587,7 +586,6 @@ SET(common_headers
events/player_events.h
event_sub.h
evolving_items.h
expedition_lockout_timer.h
extprofile.h
faction.h
file.h

View File

@ -6812,7 +6812,32 @@ ALTER TABLE `guild_bank`
ALTER TABLE `guild_bank`
ADD INDEX `guild_id` (`guild_id`);
)"
}
},
ManifestEntry{
.version = 9305,
.description = "2024_12_01_expedition_dz_merge.sql",
.check = "SHOW COLUMNS FROM `dynamic_zones` LIKE 'is_locked'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `dynamic_zones`
ADD COLUMN `is_locked` TINYINT NOT NULL DEFAULT '0' AFTER `has_zone_in`,
ADD COLUMN `add_replay` TINYINT NOT NULL DEFAULT '1' AFTER `is_locked`;
ALTER TABLE `expedition_lockouts`
CHANGE COLUMN `expedition_id` `dynamic_zone_id` INT(10) UNSIGNED NOT NULL AFTER `id`,
DROP INDEX `expedition_id_event_name`,
ADD UNIQUE INDEX `dz_id_event_name` (`dynamic_zone_id`, `event_name`) USING BTREE;
UPDATE expedition_lockouts lockouts
INNER JOIN expeditions ON lockouts.dynamic_zone_id = expeditions.id
SET lockouts.dynamic_zone_id = expeditions.dynamic_zone_id;
DROP TABLE `expeditions`;
RENAME TABLE `expedition_lockouts` TO `dynamic_zone_lockouts`;
)"
},
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
// .version = 9228,

View File

@ -311,10 +311,9 @@ namespace DatabaseSchema {
"completed_shared_task_members",
"completed_shared_tasks",
"discord_webhooks",
"dynamic_zone_lockouts",
"dynamic_zone_members",
"dynamic_zones",
"expedition_lockouts",
"expeditions",
"gm_ips",
"group_id",
"group_leaders",

View File

@ -1,11 +1,13 @@
#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 "rulesys.h"
#include "servertalk.h"
#include "util/uuid.h"
#include "repositories/character_expedition_lockouts_repository.h"
#include "repositories/dynamic_zone_lockouts_repository.h"
#include "repositories/instance_list_repository.h"
#include "repositories/instance_list_player_repository.h"
DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry)
{
@ -93,13 +95,15 @@ void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneIn
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);
m_has_zonein = dz_entry.has_zone_in != 0;
m_is_locked = dz_entry.is_locked;
m_add_replay = dz_entry.add_replay;
// 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_never_expires = dz_entry.never_expires != 0;
m_expire_time = m_start_time + m_duration;
}
@ -119,37 +123,40 @@ void DynamicZoneBase::AddMemberFromRepositoryResult(
uint32_t DynamicZoneBase::SaveToDatabase()
{
LogDynamicZonesDetail("Saving dz instance [{}] to database", m_instance_id);
if (m_instance_id != 0)
if (m_instance_id == 0)
{
auto insert_dz = DynamicZonesRepository::NewEntity();
insert_dz.uuid = m_uuid;
insert_dz.name = m_name;
insert_dz.leader_id = m_leader.id;
insert_dz.min_players = m_min_players;
insert_dz.max_players = m_max_players;
insert_dz.instance_id = m_instance_id,
insert_dz.type = static_cast<int>(m_type);
insert_dz.dz_switch_id = m_dz_switch_id;
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;
}
return 0;
auto dz = DynamicZonesRepository::NewEntity();
dz.uuid = m_uuid;
dz.name = m_name;
dz.leader_id = m_leader.id;
dz.min_players = m_min_players;
dz.max_players = m_max_players;
dz.instance_id = static_cast<int32_t>(m_instance_id),
dz.type = static_cast<uint8_t>(m_type);
dz.dz_switch_id = m_dz_switch_id;
dz.compass_zone_id = m_compass.zone_id;
dz.compass_x = m_compass.x;
dz.compass_y = m_compass.y;
dz.compass_z = m_compass.z;
dz.safe_return_zone_id = m_safereturn.zone_id;
dz.safe_return_x = m_safereturn.x;
dz.safe_return_y = m_safereturn.y;
dz.safe_return_z = m_safereturn.z;
dz.safe_return_heading = m_safereturn.heading;
dz.zone_in_x = m_zonein.x;
dz.zone_in_y = m_zonein.y;
dz.zone_in_z = m_zonein.z;
dz.zone_in_heading = m_zonein.heading;
dz.has_zone_in = static_cast<uint8_t>(m_has_zonein);
dz.is_locked = static_cast<int8_t>(m_is_locked);
dz.add_replay = static_cast<int8_t>(m_add_replay);
dz = DynamicZonesRepository::InsertOne(GetDatabase(), std::move(dz));
return dz.id;
}
bool DynamicZoneBase::AddMember(const DynamicZoneMember& add_member)
@ -196,10 +203,9 @@ bool DynamicZoneBase::RemoveMember(const DynamicZoneMember& remove_member)
return true;
}
bool DynamicZoneBase::SwapMember(
const DynamicZoneMember& add_member, const std::string& remove_char_name)
bool DynamicZoneBase::SwapMember(const DynamicZoneMember& add_member, const std::string& remove_name)
{
auto remove_member = GetMemberData(remove_char_name);
auto remove_member = GetMemberData(remove_name);
if (!add_member.IsValid() || !remove_member.IsValid())
{
return false;
@ -230,9 +236,18 @@ void DynamicZoneBase::RemoveAllMembers()
void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
{
if (members.empty())
{
return;
}
LogDynamicZonesDetail("Saving [{}] member(s) for dz [{}]", members.size(), m_id);
m_members = members;
if (m_members.size() > m_max_players)
{
m_members.resize(m_max_players);
}
// the lower level instance_list_players needs to be kept updated as well
std::vector<DynamicZoneMembersRepository::DynamicZoneMembers> insert_members;
@ -242,12 +257,12 @@ void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
DynamicZoneMembersRepository::DynamicZoneMembers member_entry{};
member_entry.dynamic_zone_id = m_id;
member_entry.character_id = member.id;
insert_members.emplace_back(member_entry);
insert_members.push_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::InstanceListPlayer player_entry{};
player_entry.id = m_instance_id;
player_entry.charid = member.id;
insert_players.push_back(player_entry);
}
DynamicZoneMembersRepository::InsertOrUpdateMany(GetDatabase(), insert_members);
@ -339,6 +354,44 @@ void DynamicZoneBase::SetLeader(const DynamicZoneMember& new_leader, bool update
}
}
void DynamicZoneBase::SetLocked(bool lock, bool update_db, DzLockMsg lock_msg, uint32_t color)
{
m_is_locked = lock;
if (update_db)
{
DynamicZonesRepository::UpdateLocked(GetDatabase(), m_id, lock);
ServerPacket pack(ServerOP_DzLock, sizeof(ServerDzLock_Struct));
auto buf = reinterpret_cast<ServerDzLock_Struct*>(pack.pBuffer);
buf->dz_id = GetID();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->lock = m_is_locked;
buf->lock_msg = static_cast<uint8_t>(lock_msg);
buf->color = color;
SendServerPacket(&pack);
}
}
void DynamicZoneBase::SetReplayOnJoin(bool enabled, bool update_db)
{
m_add_replay = enabled;
if (update_db)
{
DynamicZonesRepository::UpdateReplayOnJoin(GetDatabase(), m_id, enabled);
ServerPacket pack(ServerOP_DzReplayOnJoin, sizeof(ServerDzBool_Struct));
auto buf = reinterpret_cast<ServerDzBool_Struct*>(pack.pBuffer);
buf->dz_id = GetID();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->enabled = enabled;
SendServerPacket(&pack);
}
}
uint32_t DynamicZoneBase::GetSecondsRemaining() const
{
auto remaining = std::chrono::duration_cast<std::chrono::seconds>(GetDurationRemaining()).count();
@ -478,13 +531,13 @@ void DynamicZoneBase::RemoveInternalMember(uint32_t character_id)
), m_members.end());
}
bool DynamicZoneBase::HasMember(uint32_t character_id)
bool DynamicZoneBase::HasMember(uint32_t character_id) const
{
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)
bool DynamicZoneBase::HasMember(const std::string& character_name) const
{
return std::any_of(m_members.begin(), m_members.end(),
[&](const DynamicZoneMember& member) {
@ -590,35 +643,34 @@ std::string DynamicZoneBase::GetDynamicZoneTypeName(DynamicZoneType dz_type)
}
}
EQ::Net::DynamicPacket DynamicZoneBase::GetSerializedDzPacket()
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerPacket(uint16_t zone_id, uint16_t instance_id)
{
EQ::Net::DynamicPacket dyn_pack;
dyn_pack.PutSerialize(0, *this);
std::ostringstream ss = GetSerialized();
std::string_view sv = ss.view();
LogDynamicZonesDetail("Serialized server dz size [{}]", dyn_pack.Length());
return dyn_pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateServerDzCreatePacket(
uint16_t origin_zone_id, uint16_t origin_instance_id)
{
EQ::Net::DynamicPacket dyn_pack = GetSerializedDzPacket();
auto pack_size = sizeof(ServerDzCreateSerialized_Struct) + dyn_pack.Length();
auto pack_size = sizeof(ServerDzCreate_Struct) + sv.size();
auto pack = std::make_unique<ServerPacket>(ServerOP_DzCreated, static_cast<uint32_t>(pack_size));
auto buf = reinterpret_cast<ServerDzCreateSerialized_Struct*>(pack->pBuffer);
buf->origin_zone_id = origin_zone_id;
buf->origin_instance_id = origin_instance_id;
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length());
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length());
auto buf = reinterpret_cast<ServerDzCreate_Struct*>(pack->pBuffer);
buf->origin_zone_id = zone_id;
buf->origin_instance_id = instance_id;
buf->dz_id = GetID();
buf->cereal_size = static_cast<uint32_t>(sv.size());
memcpy(buf->cereal_data, sv.data(), sv.size());
return pack;
}
void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size)
std::ostringstream DynamicZoneBase::GetSerialized()
{
LogDynamicZonesDetail("Deserializing server dz size [{}]", cereal_size);
EQ::Util::MemoryStreamReader ss(cereal_data, cereal_size);
std::ostringstream ss;
cereal::BinaryOutputArchive archive(ss);
archive(*this);
return ss;
}
void DynamicZoneBase::Unserialize(std::span<char> buf)
{
EQ::Util::MemoryStreamReader ss(buf.data(), buf.size());
cereal::BinaryInputArchive archive(ss);
archive(*this);
}
@ -647,3 +699,180 @@ void DynamicZoneBase::LoadTemplate(const DynamicZoneTemplatesRepository::Dynamic
m_zonein.z = dz_template.zone_in_z;
m_zonein.heading = dz_template.zone_in_h;
}
std::vector<uint32_t> DynamicZoneBase::GetMemberIds()
{
std::vector<uint32_t> ids;
ids.reserve(m_members.size());
for (const auto& member : m_members)
{
ids.push_back(member.id);
}
return ids;
}
bool DynamicZoneBase::HasLockout(const std::string& event)
{
return std::ranges::any_of(m_lockouts, [&](const auto& l) { return l.IsEvent(event); });
}
bool DynamicZoneBase::HasReplayLockout()
{
return HasLockout(DzLockout::ReplayTimer);
}
void DynamicZoneBase::AddLockout(const std::string& event, uint32_t seconds)
{
auto lockout = DzLockout::Create(m_name, event, seconds, m_uuid);
AddLockout(lockout);
}
void DynamicZoneBase::AddLockout(const DzLockout& lockout, bool members_only)
{
if (!members_only)
{
DynamicZoneLockoutsRepository::InsertLockouts(GetDatabase(), GetID(), { lockout });
}
CharacterExpeditionLockoutsRepository::InsertLockout(GetDatabase(), GetMemberIds(), lockout);
HandleLockoutUpdate(lockout, false, members_only);
SendServerPacket(CreateLockoutPacket(lockout, false, members_only).get());
}
void DynamicZoneBase::AddLockoutDuration(const std::string& event, int seconds, bool members_only)
{
auto lockout = DzLockout::Create(m_name, event, std::max(0, seconds), m_uuid);
// lockout has unsigned duration, pass original seconds to support reducing existing timers
int secs = static_cast<int>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
CharacterExpeditionLockoutsRepository::AddLockoutDuration(GetDatabase(), GetMemberIds(), lockout, secs);
HandleLockoutDuration(lockout, seconds, members_only, true);
SendServerPacket(CreateLockoutDurationPacket(lockout, seconds, members_only).get());
}
void DynamicZoneBase::UpdateLockoutDuration(const std::string& event, uint32_t seconds, bool members_only)
{
// some live expeditions update existing lockout timers during progression
auto it = std::ranges::find_if(m_lockouts, [&](const auto& l) { return l.IsEvent(event); });
if (it != m_lockouts.end())
{
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
DzLockout lockout(m_uuid, m_name, event, it->GetStartTime() + seconds, seconds);
AddLockout(lockout, members_only);
}
}
void DynamicZoneBase::RemoveLockout(const std::string& event)
{
DynamicZoneLockoutsRepository::DeleteWhere(GetDatabase(), fmt::format(
"dynamic_zone_id = {} AND event_name = '{}'", GetID(), Strings::Escape(event)));
CharacterExpeditionLockoutsRepository::DeleteWhere(GetDatabase(), fmt::format(
"character_id IN ({}) AND expedition_name = '{}' AND event_name = '{}'",
fmt::join(GetMemberIds(), ","), Strings::Escape(m_name), Strings::Escape(event)));
DzLockout lockout{m_uuid, m_name, event, 0, 0};
HandleLockoutUpdate(lockout, true, false);
SendServerPacket(CreateLockoutPacket(lockout, true).get());
}
void DynamicZoneBase::HandleLockoutUpdate(const DzLockout& lockout, bool remove, bool members_only)
{
if (!members_only)
{
std::erase_if(m_lockouts, [&](const auto& l) { return l.IsEvent(lockout.Event()); });
if (!remove)
{
m_lockouts.push_back(lockout);
}
}
}
void DynamicZoneBase::HandleLockoutDuration(const DzLockout& lockout, int seconds, bool members_only, bool insert_db)
{
if (!members_only)
{
auto it = std::ranges::find_if(m_lockouts, [&](const auto& l) { return l.IsEvent(lockout.Event()); });
if (it != m_lockouts.end())
{
it->AddLockoutTime(seconds);
}
else
{
it = m_lockouts.insert(m_lockouts.end(), lockout);
}
if (insert_db)
{
DynamicZoneLockoutsRepository::InsertLockouts(GetDatabase(), GetID(), { *it });
}
}
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateLockoutPacket(const DzLockout& lockout, bool remove, bool members_only) const
{
uint32_t pack_size = sizeof(ServerDzLockout_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzLockout, pack_size);
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->expire_time = lockout.GetExpireTime();
buf->duration = lockout.GetDuration();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->remove = remove;
buf->members_only = members_only;
strn0cpy(buf->event_name, lockout.Event().c_str(), sizeof(buf->event_name));
return pack;
}
std::unique_ptr<ServerPacket> DynamicZoneBase::CreateLockoutDurationPacket(const DzLockout& lockout, int seconds, bool members_only) const
{
uint32_t pack_size = sizeof(ServerDzLockout_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_DzLockoutDuration, pack_size);
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
buf->dz_id = GetID();
buf->expire_time = lockout.GetExpireTime();
buf->duration = lockout.GetDuration();
buf->sender_zone_id = GetCurrentZoneID();
buf->sender_instance_id = GetCurrentInstanceID();
buf->members_only = members_only;
buf->seconds = seconds;
strn0cpy(buf->event_name, lockout.Event().c_str(), sizeof(buf->event_name));
return pack;
}
void DynamicZoneBase::SyncCharacterLockouts(uint32_t char_id, std::vector<DzLockout>& lockouts)
{
// adds missing event lockouts to client for this expedition and updates
// client timers that are both shorter and from another expedition
bool modified = false;
for (const auto& lockout : m_lockouts)
{
if (lockout.IsReplay() || lockout.IsExpired() || lockout.UUID() != m_uuid)
{
continue;
}
auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const DzLockout& l) { return l.IsSame(lockout); });
if (it == lockouts.end())
{
modified = true;
lockouts.push_back(lockout); // insert missing
}
else if (it->GetSecondsRemaining() < lockout.GetSecondsRemaining() && it->UUID() != m_uuid)
{
// only update lockout timer not uuid so loot event apis still work
modified = true;
it->SetDuration(lockout.GetDuration());
it->SetExpireTime(lockout.GetExpireTime());
}
}
if (modified)
{
CharacterExpeditionLockoutsRepository::InsertLockouts(GetDatabase(), char_id, lockouts);
}
}

View File

@ -1,8 +1,8 @@
#ifndef COMMON_DYNAMIC_ZONE_BASE_H
#define COMMON_DYNAMIC_ZONE_BASE_H
#include "dynamic_zone_lockout.h"
#include "eq_constants.h"
#include "net/packet.h"
#include "repositories/dynamic_zones_repository.h"
#include "repositories/dynamic_zone_members_repository.h"
#include "repositories/dynamic_zone_templates_repository.h"
@ -10,12 +10,40 @@
#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;
@ -93,6 +121,7 @@ public:
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; }
@ -104,31 +133,34 @@ public:
uint32_t GetDatabaseMemberCount();
DynamicZoneMember GetMemberData(uint32_t character_id);
DynamicZoneMember GetMemberData(const std::string& character_name);
EQ::Net::DynamicPacket GetSerializedDzPacket();
std::vector<uint32_t> GetMemberIds();
std::ostringstream GetSerialized();
bool HasDatabaseMember(uint32_t character_id);
bool HasMember(uint32_t character_id);
bool HasMember(const std::string& character_name);
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 LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size);
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 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 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);
@ -136,34 +168,48 @@ public:
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_char_name);
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() { return 0; }
virtual uint16_t GetCurrentZoneID() { return 0; }
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 member_id, DynamicZoneMemberStatus status);
virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); }
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> CreateServerDzCreatePacket(uint16_t origin_zone_id, uint16_t origin_instance_id);
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;
@ -175,6 +221,8 @@ protected:
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;
@ -182,12 +230,15 @@ protected:
DynamicZoneLocation m_compass;
DynamicZoneLocation m_safereturn;
DynamicZoneLocation m_zonein;
std::chrono::seconds m_duration;
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)
{
@ -202,6 +253,8 @@ public:
m_never_expires,
m_has_zonein,
m_has_member_statuses,
m_is_locked,
m_add_replay,
m_name,
m_uuid,
m_leader,
@ -212,7 +265,8 @@ public:
m_duration,
m_start_time,
m_expire_time,
m_members
m_members,
m_lockouts
);
}
};

View File

@ -0,0 +1,92 @@
#include "dynamic_zone_lockout.h"
#include "strings.h"
#include "rulesys.h"
#include "util/uuid.h"
#include <fmt/format.h>
#include <cereal/types/chrono.hpp>
DzLockout::DzLockout(std::string uuid, std::string expedition, std::string event, uint64_t expire_time, uint32_t duration)
: m_uuid(std::move(uuid))
, m_name(std::move(expedition))
, m_event(std::move(event))
, m_expire_time(std::chrono::system_clock::from_time_t(expire_time))
, m_duration(duration)
{
m_is_replay = m_event == ReplayTimer;
}
DzLockout::DzLockout(std::string_view name, BaseDynamicZoneLockoutsRepository::DynamicZoneLockouts&& lockout)
: m_uuid(std::move(lockout.from_expedition_uuid))
, m_name(name)
, m_event(std::move(lockout.event_name))
, m_expire_time(std::chrono::system_clock::from_time_t(lockout.expire_time))
, m_duration(lockout.duration)
{
m_is_replay = m_event == ReplayTimer;
}
DzLockout DzLockout::Create(const std::string& expedition, const std::string& event, uint32_t seconds, std::string uuid)
{
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
if (uuid.empty())
{
uuid = EQ::Util::UUID::Generate().ToString();
}
DzLockout lockout{uuid, expedition, event, 0, seconds};
lockout.Reset(); // sets expire time
return lockout;
}
uint32_t DzLockout::GetSecondsRemaining() const
{
auto now = std::chrono::system_clock::now();
if (m_expire_time > now)
{
auto remaining = m_expire_time - now;
return static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(remaining).count());
}
return 0;
}
DzLockout::TimeStrings DzLockout::GetTimeRemainingStrs() const
{
auto seconds = GetSecondsRemaining();
return DzLockout::TimeStrings{
fmt::format_int(seconds / 86400).str(), // days
fmt::format_int(seconds / 3600 % 24).str(), // hours
fmt::format_int(seconds / 60 % 60).str(), // minutes
fmt::format_int(seconds % 60).str() // seconds
};
}
bool DzLockout::IsSame(const DzLockout& other) const
{
return other.IsSame(m_name, m_event);
}
bool DzLockout::IsSame(const std::string& expedition, const std::string& event) const
{
return m_name == expedition && m_event == event;
}
void DzLockout::AddLockoutTime(int seconds)
{
seconds = static_cast<int>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
auto new_duration = std::max(0, static_cast<int>(m_duration.count()) + seconds);
auto start_time = m_expire_time - m_duration;
m_duration = std::chrono::seconds(new_duration);
m_expire_time = start_time + m_duration;
}
template <typename T>
void DzLockout::serialize(T& archive)
{
archive(m_is_replay, m_uuid, m_name, m_event, m_duration, m_expire_time);
}
template void DzLockout::serialize(cereal::BinaryOutputArchive&);
template void DzLockout::serialize(cereal::BinaryInputArchive&);

View File

@ -0,0 +1,56 @@
#pragma once
#include <chrono>
#include <string>
#include "repositories/base/base_dynamic_zone_lockouts_repository.h"
class DzLockout
{
public:
DzLockout() = default;
DzLockout(std::string uuid, std::string expedition, std::string event, uint64_t expire_time, uint32_t duration);
DzLockout(std::string_view name, BaseDynamicZoneLockoutsRepository::DynamicZoneLockouts&& lockout);
static constexpr char ReplayTimer[] = "Replay Timer";
static DzLockout Create(const std::string& expedition, const std::string& event, uint32_t seconds, std::string uuid = {});
struct TimeStrings
{
std::string days;
std::string hours;
std::string mins;
std::string secs;
};
void AddLockoutTime(int seconds);
uint32_t GetDuration() const { return static_cast<uint32_t>(m_duration.count()); }
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
uint64_t GetStartTime() const { return std::chrono::system_clock::to_time_t(m_expire_time - m_duration); }
uint32_t GetSecondsRemaining() const;
TimeStrings GetTimeRemainingStrs() const;
const std::string& DzName() const { return m_name; }
const std::string& Event() const { return m_event; }
const std::string& UUID() const { return m_uuid; }
bool IsEvent(std::string_view event) const { return m_event == event; }
bool IsExpired() const { return GetSecondsRemaining() == 0; }
bool IsReplay() const { return m_is_replay; }
bool IsSame(const DzLockout& other) const;
bool IsSame(const std::string& expedition, const std::string& event) const;
bool IsUUID(const std::string& uuid) const { return uuid == m_uuid; }
void Reset() { m_expire_time = std::chrono::system_clock::now() + m_duration; }
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
void SetExpireTime(uint64_t expire_time) { m_expire_time = std::chrono::system_clock::from_time_t(expire_time); }
void SetUUID(const std::string& uuid) { m_uuid = uuid; }
template <typename T>
void serialize(T& archive);
private:
bool m_is_replay = false;
std::string m_uuid; // dz received in
std::string m_name;
std::string m_event;
std::chrono::seconds m_duration = {};
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
};

View File

@ -974,25 +974,6 @@ namespace ZoneBlockedSpellTypes {
const uint8 Region = 2;
};
enum class DynamicZoneType
{
None = 0,
Expedition,
Tutorial,
Task,
Mission, // Shared Task
Quest
};
enum class DynamicZoneMemberStatus : uint8_t
{
Unknown = 0,
Online,
Offline,
InDynamicZone,
LinkDead
};
enum StartZoneIndex {
Odus = 0,
Qeynos,

View File

@ -1,101 +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
*
*/
#include "expedition_lockout_timer.h"
#include "../common/strings.h"
#include "../common/rulesys.h"
#include "../common/util/uuid.h"
#include <fmt/format.h>
const char* const DZ_REPLAY_TIMER_NAME = "Replay Timer"; // see December 14, 2016 patch notes
ExpeditionLockoutTimer::ExpeditionLockoutTimer(
std::string expedition_uuid, std::string expedition_name,
std::string event_name, uint64_t expire_time, uint32_t duration
) :
m_expedition_uuid{std::move(expedition_uuid)},
m_expedition_name{std::move(expedition_name)},
m_event_name{std::move(event_name)},
m_expire_time(std::chrono::system_clock::from_time_t(expire_time)),
m_duration(duration)
{
if (m_event_name == DZ_REPLAY_TIMER_NAME)
{
m_is_replay_timer = true;
}
}
ExpeditionLockoutTimer ExpeditionLockoutTimer::CreateLockout(
const std::string& expedition_name, const std::string& event_name, uint32_t seconds, std::string uuid)
{
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
if (uuid.empty())
{
uuid = EQ::Util::UUID::Generate().ToString();
}
ExpeditionLockoutTimer lockout{uuid, expedition_name, event_name, 0, seconds};
lockout.Reset(); // sets expire time
return lockout;
}
uint32_t ExpeditionLockoutTimer::GetSecondsRemaining() const
{
auto now = std::chrono::system_clock::now();
if (m_expire_time > now)
{
auto remaining = m_expire_time - now;
return static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(remaining).count());
}
return 0;
}
ExpeditionLockoutTimer::DaysHoursMinutes ExpeditionLockoutTimer::GetDaysHoursMinutesRemaining() const
{
auto seconds = GetSecondsRemaining();
return ExpeditionLockoutTimer::DaysHoursMinutes{
fmt::format_int(seconds / 86400).str(), // days
fmt::format_int((seconds / 3600) % 24).str(), // hours
fmt::format_int((seconds / 60) % 60).str() // minutes
};
}
bool ExpeditionLockoutTimer::IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const
{
return compare_lockout.IsSameLockout(GetExpeditionName(), GetEventName());
}
bool ExpeditionLockoutTimer::IsSameLockout(
const std::string& expedition_name, const std::string& event_name) const
{
return GetExpeditionName() == expedition_name && GetEventName() == event_name;
}
void ExpeditionLockoutTimer::AddLockoutTime(int seconds)
{
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
auto new_duration = std::max(0, static_cast<int>(m_duration.count()) + seconds);
auto start_time = m_expire_time - m_duration;
m_duration = std::chrono::seconds(new_duration);
m_expire_time = start_time + m_duration;
}

View File

@ -1,76 +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 EXPEDITION_LOCKOUT_TIMER_H
#define EXPEDITION_LOCKOUT_TIMER_H
#include <chrono>
#include <string>
extern const char* const DZ_REPLAY_TIMER_NAME;
class ExpeditionLockoutTimer
{
public:
ExpeditionLockoutTimer() = default;
ExpeditionLockoutTimer(
std::string expedition_uuid, std::string expedition_name,
std::string event_name, uint64_t expire_time, uint32_t duration);
static ExpeditionLockoutTimer CreateLockout(
const std::string& expedition_name, const std::string& event_name,
uint32_t seconds, std::string uuid = {});
struct DaysHoursMinutes
{
std::string days;
std::string hours;
std::string mins;
};
void AddLockoutTime(int seconds);
uint32_t GetDuration() const { return static_cast<uint32_t>(m_duration.count()); }
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
uint64_t GetStartTime() const { return std::chrono::system_clock::to_time_t(m_expire_time - m_duration); }
uint32_t GetSecondsRemaining() const;
DaysHoursMinutes GetDaysHoursMinutesRemaining() const;
const std::string& GetExpeditionName() const { return m_expedition_name; }
const std::string& GetExpeditionUUID() const { return m_expedition_uuid; }
const std::string& GetEventName() const { return m_event_name; }
bool IsExpired() const { return GetSecondsRemaining() == 0; }
bool IsFromExpedition(const std::string& uuid) const { return uuid == m_expedition_uuid; }
bool IsReplayTimer() const { return m_is_replay_timer; }
bool IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const;
bool IsSameLockout(const std::string& expedition_name, const std::string& event_name) const;
void Reset() { m_expire_time = std::chrono::system_clock::now() + m_duration; }
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
void SetExpireTime(uint64_t expire_time) { m_expire_time = std::chrono::system_clock::from_time_t(expire_time); }
void SetUUID(const std::string& uuid) { m_expedition_uuid = uuid; }
private:
bool m_is_replay_timer = false;
std::string m_expedition_uuid; // expedition received in
std::string m_expedition_name;
std::string m_event_name;
std::chrono::seconds m_duration;
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
};
#endif

View File

@ -9,18 +9,18 @@
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H
#define EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H
#ifndef EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
#define EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseExpeditionLockoutsRepository {
class BaseDynamicZoneLockoutsRepository {
public:
struct ExpeditionLockouts {
struct DynamicZoneLockouts {
uint32_t id;
uint32_t expedition_id;
uint32_t dynamic_zone_id;
std::string event_name;
time_t expire_time;
uint32_t duration;
@ -36,7 +36,7 @@ public:
{
return {
"id",
"expedition_id",
"dynamic_zone_id",
"event_name",
"expire_time",
"duration",
@ -48,7 +48,7 @@ public:
{
return {
"id",
"expedition_id",
"dynamic_zone_id",
"event_name",
"UNIX_TIMESTAMP(expire_time)",
"duration",
@ -68,7 +68,7 @@ public:
static std::string TableName()
{
return std::string("expedition_lockouts");
return std::string("dynamic_zone_lockouts");
}
static std::string BaseSelect()
@ -89,12 +89,12 @@ public:
);
}
static ExpeditionLockouts NewEntity()
static DynamicZoneLockouts NewEntity()
{
ExpeditionLockouts e{};
DynamicZoneLockouts e{};
e.id = 0;
e.expedition_id = 0;
e.dynamic_zone_id = 0;
e.event_name = "";
e.expire_time = std::time(nullptr);
e.duration = 0;
@ -103,23 +103,23 @@ public:
return e;
}
static ExpeditionLockouts GetExpeditionLockouts(
const std::vector<ExpeditionLockouts> &expedition_lockoutss,
int expedition_lockouts_id
static DynamicZoneLockouts GetDynamicZoneLockouts(
const std::vector<DynamicZoneLockouts> &dynamic_zone_lockoutss,
int dynamic_zone_lockouts_id
)
{
for (auto &expedition_lockouts : expedition_lockoutss) {
if (expedition_lockouts.id == expedition_lockouts_id) {
return expedition_lockouts;
for (auto &dynamic_zone_lockouts : dynamic_zone_lockoutss) {
if (dynamic_zone_lockouts.id == dynamic_zone_lockouts_id) {
return dynamic_zone_lockouts;
}
}
return NewEntity();
}
static ExpeditionLockouts FindOne(
static DynamicZoneLockouts FindOne(
Database& db,
int expedition_lockouts_id
int dynamic_zone_lockouts_id
)
{
auto results = db.QueryDatabase(
@ -127,16 +127,16 @@ public:
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
expedition_lockouts_id
dynamic_zone_lockouts_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
ExpeditionLockouts e{};
DynamicZoneLockouts e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.expedition_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.event_name = row[2] ? row[2] : "";
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
@ -150,7 +150,7 @@ public:
static int DeleteOne(
Database& db,
int expedition_lockouts_id
int dynamic_zone_lockouts_id
)
{
auto results = db.QueryDatabase(
@ -158,7 +158,7 @@ public:
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
expedition_lockouts_id
dynamic_zone_lockouts_id
)
);
@ -167,14 +167,14 @@ public:
static int UpdateOne(
Database& db,
const ExpeditionLockouts &e
const DynamicZoneLockouts &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.expedition_id));
v.push_back(columns[1] + " = " + std::to_string(e.dynamic_zone_id));
v.push_back(columns[2] + " = '" + Strings::Escape(e.event_name) + "'");
v.push_back(columns[3] + " = FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
v.push_back(columns[4] + " = " + std::to_string(e.duration));
@ -193,15 +193,15 @@ public:
return (results.Success() ? results.RowsAffected() : 0);
}
static ExpeditionLockouts InsertOne(
static DynamicZoneLockouts InsertOne(
Database& db,
ExpeditionLockouts e
DynamicZoneLockouts e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.expedition_id));
v.push_back(std::to_string(e.dynamic_zone_id));
v.push_back("'" + Strings::Escape(e.event_name) + "'");
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
v.push_back(std::to_string(e.duration));
@ -227,7 +227,7 @@ public:
static int InsertMany(
Database& db,
const std::vector<ExpeditionLockouts> &entries
const std::vector<DynamicZoneLockouts> &entries
)
{
std::vector<std::string> insert_chunks;
@ -236,7 +236,7 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.expedition_id));
v.push_back(std::to_string(e.dynamic_zone_id));
v.push_back("'" + Strings::Escape(e.event_name) + "'");
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
v.push_back(std::to_string(e.duration));
@ -258,9 +258,9 @@ public:
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<ExpeditionLockouts> All(Database& db)
static std::vector<DynamicZoneLockouts> All(Database& db)
{
std::vector<ExpeditionLockouts> all_entries;
std::vector<DynamicZoneLockouts> all_entries;
auto results = db.QueryDatabase(
fmt::format(
@ -272,10 +272,10 @@ public:
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
ExpeditionLockouts e{};
DynamicZoneLockouts e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.expedition_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.event_name = row[2] ? row[2] : "";
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
@ -287,9 +287,9 @@ public:
return all_entries;
}
static std::vector<ExpeditionLockouts> GetWhere(Database& db, const std::string &where_filter)
static std::vector<DynamicZoneLockouts> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<ExpeditionLockouts> all_entries;
std::vector<DynamicZoneLockouts> all_entries;
auto results = db.QueryDatabase(
fmt::format(
@ -302,10 +302,10 @@ public:
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
ExpeditionLockouts e{};
DynamicZoneLockouts e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.expedition_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.event_name = row[2] ? row[2] : "";
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10);
e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
@ -379,13 +379,13 @@ public:
static int ReplaceOne(
Database& db,
const ExpeditionLockouts &e
const DynamicZoneLockouts &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.expedition_id));
v.push_back(std::to_string(e.dynamic_zone_id));
v.push_back("'" + Strings::Escape(e.event_name) + "'");
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
v.push_back(std::to_string(e.duration));
@ -404,7 +404,7 @@ public:
static int ReplaceMany(
Database& db,
const std::vector<ExpeditionLockouts> &entries
const std::vector<DynamicZoneLockouts> &entries
)
{
std::vector<std::string> insert_chunks;
@ -413,7 +413,7 @@ public:
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.expedition_id));
v.push_back(std::to_string(e.dynamic_zone_id));
v.push_back("'" + Strings::Escape(e.event_name) + "'");
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
v.push_back(std::to_string(e.duration));
@ -436,4 +436,4 @@ public:
}
};
#endif //EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H
#endif //EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H

View File

@ -42,6 +42,8 @@ public:
float zone_in_z;
float zone_in_heading;
uint8_t has_zone_in;
int8_t is_locked;
int8_t add_replay;
};
static std::string PrimaryKey()
@ -75,6 +77,8 @@ public:
"zone_in_z",
"zone_in_heading",
"has_zone_in",
"is_locked",
"add_replay",
};
}
@ -104,6 +108,8 @@ public:
"zone_in_z",
"zone_in_heading",
"has_zone_in",
"is_locked",
"add_replay",
};
}
@ -167,6 +173,8 @@ public:
e.zone_in_z = 0;
e.zone_in_heading = 0;
e.has_zone_in = 0;
e.is_locked = 0;
e.add_replay = 1;
return e;
}
@ -226,6 +234,8 @@ public:
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
e.zone_in_heading = row[21] ? strtof(row[21], nullptr) : 0;
e.has_zone_in = row[22] ? static_cast<uint8_t>(strtoul(row[22], nullptr, 10)) : 0;
e.is_locked = row[23] ? static_cast<int8_t>(atoi(row[23])) : 0;
e.add_replay = row[24] ? static_cast<int8_t>(atoi(row[24])) : 1;
return e;
}
@ -281,6 +291,8 @@ public:
v.push_back(columns[20] + " = " + std::to_string(e.zone_in_z));
v.push_back(columns[21] + " = " + std::to_string(e.zone_in_heading));
v.push_back(columns[22] + " = " + std::to_string(e.has_zone_in));
v.push_back(columns[23] + " = " + std::to_string(e.is_locked));
v.push_back(columns[24] + " = " + std::to_string(e.add_replay));
auto results = db.QueryDatabase(
fmt::format(
@ -325,6 +337,8 @@ public:
v.push_back(std::to_string(e.zone_in_z));
v.push_back(std::to_string(e.zone_in_heading));
v.push_back(std::to_string(e.has_zone_in));
v.push_back(std::to_string(e.is_locked));
v.push_back(std::to_string(e.add_replay));
auto results = db.QueryDatabase(
fmt::format(
@ -377,6 +391,8 @@ public:
v.push_back(std::to_string(e.zone_in_z));
v.push_back(std::to_string(e.zone_in_heading));
v.push_back(std::to_string(e.has_zone_in));
v.push_back(std::to_string(e.is_locked));
v.push_back(std::to_string(e.add_replay));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@ -433,6 +449,8 @@ public:
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
e.zone_in_heading = row[21] ? strtof(row[21], nullptr) : 0;
e.has_zone_in = row[22] ? static_cast<uint8_t>(strtoul(row[22], nullptr, 10)) : 0;
e.is_locked = row[23] ? static_cast<int8_t>(atoi(row[23])) : 0;
e.add_replay = row[24] ? static_cast<int8_t>(atoi(row[24])) : 1;
all_entries.push_back(e);
}
@ -480,6 +498,8 @@ public:
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
e.zone_in_heading = row[21] ? strtof(row[21], nullptr) : 0;
e.has_zone_in = row[22] ? static_cast<uint8_t>(strtoul(row[22], nullptr, 10)) : 0;
e.is_locked = row[23] ? static_cast<int8_t>(atoi(row[23])) : 0;
e.add_replay = row[24] ? static_cast<int8_t>(atoi(row[24])) : 1;
all_entries.push_back(e);
}
@ -577,6 +597,8 @@ public:
v.push_back(std::to_string(e.zone_in_z));
v.push_back(std::to_string(e.zone_in_heading));
v.push_back(std::to_string(e.has_zone_in));
v.push_back(std::to_string(e.is_locked));
v.push_back(std::to_string(e.add_replay));
auto results = db.QueryDatabase(
fmt::format(
@ -622,6 +644,8 @@ public:
v.push_back(std::to_string(e.zone_in_z));
v.push_back(std::to_string(e.zone_in_heading));
v.push_back(std::to_string(e.has_zone_in));
v.push_back(std::to_string(e.is_locked));
v.push_back(std::to_string(e.add_replay));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}

View File

@ -1,415 +0,0 @@
/**
* DO NOT MODIFY THIS FILE
*
* 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://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_EXPEDITIONS_REPOSITORY_H
#define EQEMU_BASE_EXPEDITIONS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseExpeditionsRepository {
public:
struct Expeditions {
uint32_t id;
uint32_t dynamic_zone_id;
uint8_t add_replay_on_join;
uint8_t is_locked;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"dynamic_zone_id",
"add_replay_on_join",
"is_locked",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"dynamic_zone_id",
"add_replay_on_join",
"is_locked",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("expeditions");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static Expeditions NewEntity()
{
Expeditions e{};
e.id = 0;
e.dynamic_zone_id = 0;
e.add_replay_on_join = 1;
e.is_locked = 0;
return e;
}
static Expeditions GetExpeditions(
const std::vector<Expeditions> &expeditionss,
int expeditions_id
)
{
for (auto &expeditions : expeditionss) {
if (expeditions.id == expeditions_id) {
return expeditions;
}
}
return NewEntity();
}
static Expeditions FindOne(
Database& db,
int expeditions_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
expeditions_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
Expeditions e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.add_replay_on_join = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 1;
e.is_locked = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int expeditions_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
expeditions_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const Expeditions &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = " + std::to_string(e.dynamic_zone_id));
v.push_back(columns[2] + " = " + std::to_string(e.add_replay_on_join));
v.push_back(columns[3] + " = " + std::to_string(e.is_locked));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static Expeditions InsertOne(
Database& db,
Expeditions e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.dynamic_zone_id));
v.push_back(std::to_string(e.add_replay_on_join));
v.push_back(std::to_string(e.is_locked));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<Expeditions> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.dynamic_zone_id));
v.push_back(std::to_string(e.add_replay_on_join));
v.push_back(std::to_string(e.is_locked));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<Expeditions> All(Database& db)
{
std::vector<Expeditions> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Expeditions e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.add_replay_on_join = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 1;
e.is_locked = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<Expeditions> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<Expeditions> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
Expeditions e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.dynamic_zone_id = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.add_replay_on_join = row[2] ? static_cast<uint8_t>(strtoul(row[2], nullptr, 10)) : 1;
e.is_locked = row[3] ? static_cast<uint8_t>(strtoul(row[3], nullptr, 10)) : 0;
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const Expeditions &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.dynamic_zone_id));
v.push_back(std::to_string(e.add_replay_on_join));
v.push_back(std::to_string(e.is_locked));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<Expeditions> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.dynamic_zone_id));
v.push_back(std::to_string(e.add_replay_on_join));
v.push_back(std::to_string(e.is_locked));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_EXPEDITIONS_REPOSITORY_H

View File

@ -2,7 +2,7 @@
#define EQEMU_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H
#include "../database.h"
#include "../expedition_lockout_timer.h"
#include "../dynamic_zone_lockout.h"
#include "../strings.h"
#include "base/base_character_expedition_lockouts_repository.h"
#include <unordered_map>
@ -47,33 +47,8 @@ public:
// Custom extended repository methods here
struct CharacterExpeditionLockoutsTimeStamp {
int id;
int character_id;
std::string expedition_name;
std::string event_name;
time_t expire_time;
int duration;
std::string from_expedition_uuid;
};
static ExpeditionLockoutTimer GetExpeditionLockoutTimerFromEntry(
CharacterExpeditionLockoutsTimeStamp&& entry)
{
ExpeditionLockoutTimer lockout_timer{
std::move(entry.from_expedition_uuid),
std::move(entry.expedition_name),
std::move(entry.event_name),
static_cast<uint64_t>(entry.expire_time),
static_cast<uint32_t>(entry.duration)
};
return lockout_timer;
}
static std::unordered_map<uint32_t, std::vector<ExpeditionLockoutTimer>> GetManyCharacterLockoutTimers(
Database& db, const std::vector<uint32_t>& character_ids,
const std::string& expedition_name, const std::string& ordered_event_name)
static std::unordered_map<uint32_t, std::vector<DzLockout>> GetLockouts(
Database& db, const std::vector<uint32_t>& char_ids, const std::string& expedition)
{
auto results = db.QueryDatabase(fmt::format(SQL(
SELECT
@ -84,39 +59,171 @@ public:
from_expedition_uuid
FROM character_expedition_lockouts
WHERE
character_id IN ({})
character_id IN ({0})
AND expire_time > NOW()
AND expedition_name = '{}'
AND expedition_name = '{1}'
ORDER BY
FIELD(character_id, {}),
FIELD(event_name, '{}') DESC
FIELD(character_id, {0}),
FIELD(event_name, '{2}') DESC
),
fmt::join(character_ids, ","),
Strings::Escape(expedition_name),
fmt::join(character_ids, ","),
Strings::Escape(ordered_event_name)
fmt::join(char_ids, ","),
Strings::Escape(expedition),
Strings::Escape(DzLockout::ReplayTimer)
));
std::unordered_map<uint32_t, std::vector<ExpeditionLockoutTimer>> lockouts;
std::unordered_map<uint32_t, std::vector<DzLockout>> lockouts;
for (auto row = results.begin(); row != results.end(); ++row)
{
CharacterExpeditionLockoutsTimeStamp entry{};
int col = 0;
entry.character_id = std::strtoul(row[col++], nullptr, 10);
entry.expire_time = std::strtoull(row[col++], nullptr, 10);
entry.duration = std::strtoul(row[col++], nullptr, 10);
entry.event_name = row[col++];
entry.expedition_name = expedition_name;
entry.from_expedition_uuid = row[col++];
uint32_t char_id = std::strtoul(row[col++], nullptr, 10);
time_t expire_time = std::strtoull(row[col++], nullptr, 10);
uint32_t duration = std::strtoul(row[col++], nullptr, 10);
std::string event = row[col++];
std::string uuid = row[col++];
auto lockout = GetExpeditionLockoutTimerFromEntry(std::move(entry));
lockouts[entry.character_id].emplace_back(std::move(lockout));
lockouts[char_id].emplace_back(std::move(uuid), expedition, std::move(event), expire_time, duration);
}
return lockouts;
}
static std::vector<DzLockout> GetLockouts(Database& db, uint32_t char_id)
{
std::vector<DzLockout> lockouts;
auto rows = GetWhere(db, fmt::format("character_id = {} AND expire_time > NOW()", char_id));
lockouts.reserve(rows.size());
for (auto& row : rows)
{
lockouts.emplace_back(
std::move(row.from_expedition_uuid),
std::move(row.expedition_name),
std::move(row.event_name),
row.expire_time,
row.duration
);
}
return lockouts;
}
static std::vector<CharacterExpeditionLockouts> GetLockouts(Database& db, const std::vector<std::string>& names, const std::string& expedition, const std::string& event)
{
if (names.empty())
{
return {};
}
return GetWhere(db, fmt::format(
"character_id IN (select id from character_data where name IN ('{}')) AND expire_time > NOW() AND expedition_name = '{}' AND event_name = '{}' LIMIT 1",
fmt::join(names, "','"), Strings::Escape(expedition), Strings::Escape(event)));
}
static void InsertLockouts(Database& db, uint32_t char_id, const std::vector<DzLockout>& lockouts)
{
std::string insert_values;
for (const auto& lockout : lockouts)
{
fmt::format_to(std::back_inserter(insert_values),
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
char_id,
lockout.GetExpireTime(),
lockout.GetDuration(),
Strings::Escape(lockout.UUID()),
Strings::Escape(lockout.DzName()),
Strings::Escape(lockout.Event())
);
}
if (!insert_values.empty())
{
insert_values.pop_back(); // trailing comma
auto query = fmt::format(SQL(
INSERT INTO character_expedition_lockouts
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
VALUES {}
ON DUPLICATE KEY UPDATE
from_expedition_uuid = VALUES(from_expedition_uuid),
expire_time = VALUES(expire_time),
duration = VALUES(duration);
), insert_values);
db.QueryDatabase(query);
}
}
static void InsertLockout(Database& db, const std::vector<uint32_t>& char_ids, const DzLockout& lockout)
{
std::string insert_values;
for (const auto& char_id : char_ids)
{
fmt::format_to(std::back_inserter(insert_values),
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
char_id,
lockout.GetExpireTime(),
lockout.GetDuration(),
Strings::Escape(lockout.UUID()),
Strings::Escape(lockout.DzName()),
Strings::Escape(lockout.Event())
);
}
if (!insert_values.empty())
{
insert_values.pop_back(); // trailing comma
auto query = fmt::format(SQL(
INSERT INTO character_expedition_lockouts
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
VALUES {}
ON DUPLICATE KEY UPDATE
from_expedition_uuid = VALUES(from_expedition_uuid),
expire_time = VALUES(expire_time),
duration = VALUES(duration);
), insert_values);
db.QueryDatabase(query);
}
}
// inserts a new lockout or updates existing lockout with seconds added to current time
static void AddLockoutDuration(Database& db, const std::vector<uint32_t>& char_ids, const DzLockout& lockout, int seconds)
{
std::string insert_values;
for (const auto& char_id : char_ids)
{
fmt::format_to(std::back_inserter(insert_values),
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
char_id,
lockout.GetExpireTime(),
lockout.GetDuration(),
Strings::Escape(lockout.UUID()),
Strings::Escape(lockout.DzName()),
Strings::Escape(lockout.Event())
);
}
if (!insert_values.empty())
{
insert_values.pop_back(); // trailing comma
auto query = fmt::format(SQL(
INSERT INTO character_expedition_lockouts
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
VALUES {0}
ON DUPLICATE KEY UPDATE
from_expedition_uuid = VALUES(from_expedition_uuid),
expire_time = DATE_ADD(expire_time, INTERVAL {1} SECOND),
duration = GREATEST(0, CAST(duration AS SIGNED) + {1});
), insert_values, seconds);
db.QueryDatabase(query);
}
}
};
#endif //EQEMU_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H

View File

@ -0,0 +1,84 @@
#ifndef EQEMU_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
#define EQEMU_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "../dynamic_zone_lockout.h"
#include "base/base_dynamic_zone_lockouts_repository.h"
class DynamicZoneLockoutsRepository: public BaseDynamicZoneLockoutsRepository {
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
*
* DynamicZoneLockoutsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* DynamicZoneLockoutsRepository::GetWhereNeverExpires()
* DynamicZoneLockoutsRepository::GetWhereXAndY()
* DynamicZoneLockoutsRepository::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
static void InsertLockouts(Database& db, uint32_t dz_id, const std::vector<DzLockout>& lockouts)
{
std::string insert_values;
for (const auto& lockout : lockouts)
{
fmt::format_to(std::back_inserter(insert_values),
"({}, '{}', '{}', FROM_UNIXTIME({}), {}),",
dz_id,
Strings::Escape(lockout.UUID()),
Strings::Escape(lockout.Event()),
lockout.GetExpireTime(),
lockout.GetDuration()
);
}
if (!insert_values.empty())
{
insert_values.pop_back(); // trailing comma
auto query = fmt::format(SQL(
INSERT INTO dynamic_zone_lockouts
(dynamic_zone_id, from_expedition_uuid, event_name, expire_time, duration)
VALUES {}
ON DUPLICATE KEY UPDATE
from_expedition_uuid = VALUES(from_expedition_uuid),
expire_time = VALUES(expire_time),
duration = VALUES(duration);
), insert_values);
db.QueryDatabase(query);
}
}
};
#endif //EQEMU_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H

View File

@ -65,7 +65,7 @@ public:
));
}
static std::vector<MemberWithName> GetAllWithNames(Database& db)
static std::vector<MemberWithName> AllWithNames(Database& db)
{
std::vector<MemberWithName> all_entries;
@ -146,65 +146,34 @@ public:
static void RemoveMember(Database& db, uint32_t dynamic_zone_id, uint32_t character_id)
{
db.QueryDatabase(fmt::format(SQL(
DELETE FROM {}
WHERE dynamic_zone_id = {} AND character_id = {};
),
TableName(), dynamic_zone_id, character_id
));
DeleteWhere(db, fmt::format("dynamic_zone_id = {} AND character_id = {}", dynamic_zone_id, character_id));
}
static void RemoveAllMembers(Database& db, uint32_t dynamic_zone_id)
{
db.QueryDatabase(fmt::format(SQL(
DELETE FROM {}
WHERE dynamic_zone_id = {};
),
TableName(), dynamic_zone_id
));
DeleteWhere(db, fmt::format("dynamic_zone_id = {}", dynamic_zone_id));
}
static void RemoveAllMembers(Database& db, std::vector<uint32_t> dynamic_zone_ids)
static uint32_t InsertOrUpdateMany(Database& db, const std::vector<DynamicZoneMembers>& entries)
{
if (!dynamic_zone_ids.empty())
if (entries.empty())
{
db.QueryDatabase(fmt::format(SQL(
DELETE FROM {}
WHERE dynamic_zone_id IN ({});
),
TableName(), Strings::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_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")");
return 0;
}
std::vector<std::string> insert_values;
std::vector<std::string> values;
values.reserve(entries.size());
auto results = db.QueryDatabase(
fmt::format(
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = id;",
TableName(),
ColumnsRaw(),
Strings::Implode(",", insert_chunks)
)
);
for (const auto& entry : entries)
{
values.push_back(fmt::format("({},{},{})", entry.id, entry.dynamic_zone_id, entry.character_id));
}
return (results.Success() ? results.RowsAffected() : 0);
auto results = db.QueryDatabase(fmt::format(
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = id;",
TableName(), ColumnsRaw(), fmt::join(values, ",")));
return results.Success() ? results.RowsAffected() : 0;
}
};

View File

@ -70,6 +70,8 @@ public:
float zone_in_z;
float zone_in_heading;
int has_zone_in;
int8_t is_locked;
int8_t add_replay;
int zone;
int version;
int is_global;
@ -105,6 +107,8 @@ public:
dynamic_zones.zone_in_z,
dynamic_zones.zone_in_heading,
dynamic_zones.has_zone_in,
dynamic_zones.is_locked,
dynamic_zones.add_replay,
instance_list.zone,
instance_list.version,
instance_list.is_global,
@ -144,6 +148,8 @@ public:
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;
entry.is_locked = static_cast<int8_t>(strtol(row[col++], nullptr, 10));
entry.add_replay = static_cast<int8_t>(strtol(row[col++], nullptr, 10));
// from instance_list
entry.zone = strtol(row[col++], nullptr, 10);
entry.version = strtol(row[col++], nullptr, 10);
@ -244,6 +250,22 @@ public:
}
}
static void UpdateLocked(Database& db, uint32_t dz_id, bool lock)
{
if (dz_id != 0)
{
db.QueryDatabase(fmt::format("UPDATE dynamic_zones SET is_locked = {} WHERE id = {}", lock, dz_id));
}
}
static void UpdateReplayOnJoin(Database& db, uint32_t dz_id, bool enabled)
{
if (dz_id != 0)
{
db.QueryDatabase(fmt::format("UPDATE dynamic_zones SET add_replay = {} WHERE id = {}", enabled, dz_id));
}
}
static void UpdateSwitchID(Database& db, uint32_t dz_id, int dz_switch_id)
{
if (dz_id != 0)
@ -351,6 +373,59 @@ public:
return all_entries;
}
struct CharacterDz
{
uint32_t id;
std::string name;
uint32_t dz_id;
};
// get character ids with possible active dz id by type
static std::vector<CharacterDz> GetCharactersWithDz(Database& db, const std::vector<std::string>& names, int type)
{
if (names.empty())
{
return {};
}
std::vector<CharacterDz> entries;
entries.reserve(names.size());
auto results = db.QueryDatabase(fmt::format(SQL(
SELECT
character_data.id,
character_data.name,
MAX(dynamic_zones.id)
FROM character_data
LEFT JOIN dynamic_zone_members
ON character_data.id = dynamic_zone_members.character_id
LEFT JOIN dynamic_zones
ON dynamic_zone_members.dynamic_zone_id = dynamic_zones.id
AND dynamic_zones.`type` = {0}
WHERE character_data.name IN ('{1}')
GROUP BY character_data.id
ORDER BY FIELD(character_data.name, '{1}')
),
type,
fmt::join(names, "','")
));
if (results.Success())
{
for (auto row = results.begin(); row != results.end(); ++row)
{
CharacterDz entry{};
entry.id = std::strtoul(row[0], nullptr, 10);
entry.name = row[1];
entry.dz_id = row[2] ? std::strtoul(row[2], nullptr, 10) : 0;
entries.push_back(std::move(entry));
}
}
return entries;
}
};
#endif //EQEMU_DYNAMIC_ZONES_REPOSITORY_H

View File

@ -1,102 +0,0 @@
#ifndef EQEMU_EXPEDITION_LOCKOUTS_REPOSITORY_H
#define EQEMU_EXPEDITION_LOCKOUTS_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_expedition_lockouts_repository.h"
class ExpeditionLockoutsRepository: public BaseExpeditionLockoutsRepository {
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
*
* ExpeditionLockoutsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* ExpeditionLockoutsRepository::GetWhereNeverExpires()
* ExpeditionLockoutsRepository::GetWhereXAndY()
* ExpeditionLockoutsRepository::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 ExpeditionLockoutsWithTimestamp {
uint32_t id;
uint32_t expedition_id;
std::string event_name;
time_t expire_time;
int duration;
std::string from_expedition_uuid;
};
static std::vector<ExpeditionLockoutsWithTimestamp> GetWithTimestamp(
Database& db, const std::vector<uint32_t>& expedition_ids)
{
if (expedition_ids.empty())
{
return {};
}
std::vector<ExpeditionLockoutsWithTimestamp> all_entries;
auto results = db.QueryDatabase(fmt::format(SQL(
SELECT
id,
expedition_id,
event_name,
UNIX_TIMESTAMP(expire_time),
duration,
from_expedition_uuid
FROM expedition_lockouts
WHERE expedition_id IN ({})
),
Strings::Join(expedition_ids, ",")
));
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row)
{
ExpeditionLockoutsWithTimestamp entry{};
int col = 0;
entry.id = strtoul(row[col++], nullptr, 10);
entry.expedition_id = strtoul(row[col++], nullptr, 10);
entry.event_name = row[col++];
entry.expire_time = strtoull(row[col++], nullptr, 10);
entry.duration = strtol(row[col++], nullptr, 10);
entry.from_expedition_uuid = row[col++];
all_entries.emplace_back(std::move(entry));
}
return all_entries;
}
};
#endif //EQEMU_EXPEDITION_LOCKOUTS_REPOSITORY_H

View File

@ -1,134 +0,0 @@
#ifndef EQEMU_EXPEDITIONS_REPOSITORY_H
#define EQEMU_EXPEDITIONS_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_expeditions_repository.h"
class ExpeditionsRepository: public BaseExpeditionsRepository {
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
*
* ExpeditionsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* ExpeditionsRepository::GetWhereNeverExpires()
* ExpeditionsRepository::GetWhereXAndY()
* ExpeditionsRepository::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 CharacterExpedition
{
uint32_t id;
std::string name;
uint32_t expedition_id;
};
static std::vector<CharacterExpedition> GetCharactersWithExpedition(
Database& db, const std::vector<std::string>& character_names)
{
if (character_names.empty())
{
return {};
}
std::vector<CharacterExpedition> entries;
auto joined_character_names = fmt::format("'{}'", Strings::Join(character_names, "','"));
auto results = db.QueryDatabase(fmt::format(SQL(
SELECT
character_data.id,
character_data.name,
MAX(expeditions.id)
FROM character_data
LEFT JOIN dynamic_zone_members
ON character_data.id = dynamic_zone_members.character_id
LEFT JOIN expeditions
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, {})
),
joined_character_names,
joined_character_names
));
if (results.Success())
{
entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row)
{
CharacterExpedition entry{};
entry.id = std::strtoul(row[0], nullptr, 10);
entry.name = row[1];
entry.expedition_id = row[2] ? std::strtoul(row[2], nullptr, 10) : 0;
entries.emplace_back(std::move(entry));
}
}
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 = {}
),
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

View File

@ -45,33 +45,26 @@ public:
// Custom extended repository methods here
static int InsertOrUpdateMany(Database& db,
const std::vector<InstanceListPlayer>& instance_list_player_entries)
static uint32_t InsertOrUpdateMany(Database& db, const std::vector<InstanceListPlayer>& entries)
{
std::vector<std::string> insert_chunks;
for (auto &instance_list_player_entry: instance_list_player_entries)
if (entries.empty())
{
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("(" + Strings::Implode(",", insert_values) + ")");
return 0;
}
std::vector<std::string> insert_values;
std::vector<std::string> values;
values.reserve(entries.size());
auto results = db.QueryDatabase(
fmt::format(
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = VALUES(id)",
TableName(),
ColumnsRaw(),
Strings::Implode(",", insert_chunks)
)
);
for (const auto& entry : entries)
{
values.push_back(fmt::format("({},{})", entry.id, entry.charid));
}
return (results.Success() ? results.RowsAffected() : 0);
auto results = db.QueryDatabase(fmt::format(
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = VALUES(id)",
TableName(), ColumnsRaw(), fmt::join(values, ",")));
return results.Success() ? results.RowsAffected() : 0;
}
static bool ReplaceOne(Database& db, InstanceListPlayer e)

View File

@ -170,18 +170,6 @@
#define ServerOP_LFPMatches 0x0214
#define ServerOP_ClientVersionSummary 0x0215
// expedition
#define ServerOP_ExpeditionCreate 0x0400
#define ServerOP_ExpeditionLockout 0x0403
#define ServerOP_ExpeditionDzAddPlayer 0x0408
#define ServerOP_ExpeditionDzMakeLeader 0x0409
#define ServerOP_ExpeditionCharacterLockout 0x040d
#define ServerOP_ExpeditionSaveInvite 0x040e
#define ServerOP_ExpeditionRequestInvite 0x040f
#define ServerOP_ExpeditionReplayOnJoin 0x0410
#define ServerOP_ExpeditionLockState 0x0411
#define ServerOP_ExpeditionLockoutDuration 0x0414
// dz
#define ServerOP_DzAddRemoveMember 0x0450
#define ServerOP_DzRemoveAllMembers 0x0451
@ -199,6 +187,15 @@
#define ServerOP_DzDeleted 0x045d
#define ServerOP_DzSetSwitchID 0x045e
#define ServerOP_DzMovePC 0x045f
#define ServerOP_DzLock 0x0460
#define ServerOP_DzReplayOnJoin 0x0461
#define ServerOP_DzLockout 0x0462
#define ServerOP_DzLockoutDuration 0x0463
#define ServerOP_DzCharacterLockout 0x0464
#define ServerOP_DzAddPlayer 0x0465
#define ServerOP_DzSaveInvite 0x0466
#define ServerOP_DzRequestInvite 0x0467
#define ServerOP_DzMakeLeader 0x0468
#define ServerOP_LSInfo 0x1000
#define ServerOP_LSStatus 0x1001
@ -1543,10 +1540,8 @@ struct UCSServerStatus_Struct {
};
};
struct ServerExpeditionID_Struct {
uint32 expedition_id;
uint32 sender_zone_id;
uint32 sender_instance_id;
struct ServerCharacterID_Struct {
uint32_t char_id;
};
struct ServerDzLeaderID_Struct {
@ -1580,45 +1575,42 @@ struct ServerDzMovePC_Struct {
uint32 character_id;
};
struct ServerExpeditionLockout_Struct {
uint32 expedition_id;
struct ServerDzLockout_Struct {
uint32 dz_id;
uint64 expire_time;
uint32 duration;
uint32 sender_zone_id;
uint16 sender_instance_id;
uint8 remove;
uint8 members_only;
int seconds_adjust;
int seconds;
char event_name[256];
};
struct ServerExpeditionLockState_Struct {
uint32 expedition_id;
struct ServerDzLock_Struct {
uint32 dz_id;
uint32 sender_zone_id;
uint16 sender_instance_id;
uint8 enabled;
bool lock;
uint8 lock_msg; // 0: none, 1: closing 2: trial begin
uint32 color;
};
struct ServerExpeditionSetting_Struct {
uint32 expedition_id;
struct ServerDzBool_Struct {
uint32 dz_id;
uint32 sender_zone_id;
uint16 sender_instance_id;
uint8 enabled;
bool enabled;
};
struct ServerExpeditionCharacterLockout_Struct {
struct ServerDzCharacterLockout_Struct {
uint8 remove;
uint32 character_id;
uint32 char_id;
uint64 expire_time;
uint32 duration;
char uuid[37];
char expedition_name[128];
char event_name[256];
};
struct ServerExpeditionCharacterID_Struct {
uint32_t character_id;
char expedition[128];
char event[256];
};
struct ServerDzExpireWarning_Struct {
@ -1627,7 +1619,7 @@ struct ServerDzExpireWarning_Struct {
};
struct ServerDzCommand_Struct {
uint32 expedition_id;
uint32 dz_id;
uint8 is_char_online; // 0: target name is offline, 1: online
char requester_name[64];
char target_name[64];
@ -1696,11 +1688,12 @@ struct ServerDzSetDuration_Struct {
uint32 seconds;
};
struct ServerDzCreateSerialized_Struct {
struct ServerDzCreate_Struct {
uint16_t origin_zone_id;
uint16_t origin_instance_id;
uint32_t dz_id;
uint32_t cereal_size;
char cereal_data[0];
char cereal_data[1];
};
struct ServerSendPlayerEvent_Struct {

View File

@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9304
#define CURRENT_BINARY_DATABASE_VERSION 9305
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054
#endif

View File

@ -11,8 +11,6 @@ SET(world_sources
dynamic_zone_manager.cpp
eql_config.cpp
eqemu_api_world_data_service.cpp
expedition_database.cpp
expedition_message.cpp
launcher_link.cpp
launcher_list.cpp
lfplist.cpp
@ -48,8 +46,6 @@ SET(world_headers
dynamic_zone_manager.h
eql_config.h
eqemu_api_world_data_service.h
expedition_database.h
expedition_message.h
launcher_link.h
launcher_list.h
lfplist.h

View File

@ -127,8 +127,8 @@ public:
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
void ProcessTellQueue();
void SetPendingExpeditionInvite(ServerPacket* pack) { p_pending_expedition_invite.reset(pack->Copy()); };
std::unique_ptr<ServerPacket> GetPendingExpeditionInvite() { return std::move(p_pending_expedition_invite); }
void SetPendingDzInvite(ServerPacket* pack) { m_dz_invite.reset(pack->Copy()); };
std::unique_ptr<ServerPacket> GetPendingDzInvite() { return std::move(m_dz_invite); }
private:
void ClearVars(bool iAll = false);
@ -176,7 +176,7 @@ private:
// Tell Queue -- really a vector :D
std::vector<ServerChannelMessage_Struct *> tell_queue;
std::unique_ptr<ServerPacket> p_pending_expedition_invite = nullptr;
std::unique_ptr<ServerPacket> m_dz_invite;
};
#endif /*CLIENTENTRY_H_*/

View File

@ -1717,13 +1717,13 @@ void ClientList::SendCharacterMessageID(ClientListEntry* character,
return;
}
SerializeBuffer serialized_args;
SerializeBuffer argbuf;
for (const auto& arg : args)
{
serialized_args.WriteString(arg);
argbuf.WriteString(arg);
}
uint32_t args_size = static_cast<uint32_t>(serialized_args.size());
uint32_t args_size = static_cast<uint32_t>(argbuf.size());
uint32_t pack_size = sizeof(CZClientMessageString_Struct) + args_size;
auto pack = std::make_unique<ServerPacket>(ServerOP_CZClientMessageString, pack_size);
auto buf = reinterpret_cast<CZClientMessageString_Struct*>(pack->pBuffer);
@ -1731,7 +1731,10 @@ void ClientList::SendCharacterMessageID(ClientListEntry* character,
buf->chat_type = chat_type;
strn0cpy(buf->client_name, character->name(), sizeof(buf->client_name));
buf->args_size = args_size;
memcpy(buf->args, serialized_args.buffer(), serialized_args.size());
if (argbuf.size() > 0)
{
memcpy(buf->args, argbuf.buffer(), argbuf.size());
}
character->Server()->SendPacket(pack.get());
}

View File

@ -164,132 +164,6 @@ void DynamicZone::SendZonesLeaderChanged()
zoneserver_list.SendPacket(pack.get());
}
void DynamicZone::HandleZoneMessage(ServerPacket* pack)
{
switch (pack->opcode)
{
case ServerOP_DzCreated:
{
dynamic_zone_manager.CacheNewDynamicZone(pack);
break;
}
case ServerOP_DzSetCompass:
case ServerOP_DzSetSafeReturn:
case ServerOP_DzSetZoneIn:
{
auto buf = reinterpret_cast<ServerDzLocation_Struct*>(pack->pBuffer);
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz)
{
if (pack->opcode == ServerOP_DzSetCompass)
{
dz->SetCompass(buf->zone_id, buf->x, buf->y, buf->z, false);
}
else if (pack->opcode == ServerOP_DzSetSafeReturn)
{
dz->SetSafeReturn(buf->zone_id, buf->x, buf->y, buf->z, buf->heading, false);
}
else if (pack->opcode == ServerOP_DzSetZoneIn)
{
dz->SetZoneInLocation(buf->x, buf->y, buf->z, buf->heading, false);
}
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzSetSwitchID:
{
auto buf = reinterpret_cast<ServerDzSwitchID_Struct*>(pack->pBuffer);
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz)
{
dz->ProcessSetSwitchID(buf->dz_switch_id);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzAddRemoveMember:
{
auto buf = reinterpret_cast<ServerDzMember_Struct*>(pack->pBuffer);
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz)
{
auto status = static_cast<DynamicZoneMemberStatus>(buf->character_status);
dz->ProcessMemberAddRemove({ buf->character_id, buf->character_name, status }, buf->removed);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzSwapMembers:
{
auto buf = reinterpret_cast<ServerDzMemberSwap_Struct*>(pack->pBuffer);
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz)
{
// we add first in world so new member can be chosen if leader is removed
auto status = static_cast<DynamicZoneMemberStatus>(buf->add_character_status);
dz->ProcessMemberAddRemove({ buf->add_character_id, buf->add_character_name, status }, false);
dz->ProcessMemberAddRemove({ buf->remove_character_id, buf->remove_character_name }, true);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzRemoveAllMembers:
{
auto buf = reinterpret_cast<ServerDzID_Struct*>(pack->pBuffer);
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz)
{
dz->ProcessRemoveAllMembers();
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzSetSecondsRemaining:
{
auto buf = reinterpret_cast<ServerDzSetDuration_Struct*>(pack->pBuffer);
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz)
{
dz->SetSecondsRemaining(buf->seconds);
}
break;
}
case ServerOP_DzGetMemberStatuses:
{
auto buf = reinterpret_cast<ServerDzID_Struct*>(pack->pBuffer);
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz)
{
dz->SendZoneMemberStatuses(buf->sender_zone_id, buf->sender_instance_id);
}
break;
}
case ServerOP_DzUpdateMemberStatus:
{
auto buf = reinterpret_cast<ServerDzMemberStatus_Struct*>(pack->pBuffer);
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz)
{
auto status = static_cast<DynamicZoneMemberStatus>(buf->status);
dz->ProcessMemberStatusChange(buf->character_id, status);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzMovePC:
{
auto buf = reinterpret_cast<ServerDzMovePC_Struct*>(pack->pBuffer);
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz && dz->HasMember(buf->character_id))
{
zoneserver_list.SendPacket(buf->sender_zone_id, buf->sender_instance_id, pack);
}
break;
}
};
}
void DynamicZone::ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed)
{
DynamicZoneBase::ProcessMemberAddRemove(member, removed);
@ -345,13 +219,13 @@ void DynamicZone::SendZoneMemberStatuses(uint16_t zone_id, uint16_t instance_id)
void DynamicZone::CacheMemberStatuses()
{
if (m_has_member_statuses)
if (m_has_member_statuses || m_members.empty())
{
return;
}
// called when a new dz is cached to fill member statuses
std::string zone_name{};
std::string zone_name;
std::vector<ClientListEntry*> all_clients;
all_clients.reserve(client_list.GetClientCount());
client_list.GetClients(zone_name.c_str(), all_clients);

View File

@ -22,7 +22,6 @@ public:
using DynamicZoneBase::DynamicZoneBase; // inherit base constructors
static DynamicZone* FindDynamicZoneByID(uint32_t dz_id);
static void HandleZoneMessage(ServerPacket* pack);
void SetSecondsRemaining(uint32_t seconds_remaining) override;
@ -33,7 +32,7 @@ public:
protected:
Database& GetDatabase() override;
void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed) override;
bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status) override;
bool ProcessMemberStatusChange(uint32_t character_id, DynamicZoneMemberStatus status) override;
bool SendServerPacket(ServerPacket* packet) override;
private:

View File

@ -1,12 +1,14 @@
#include "dynamic_zone_manager.h"
#include "dynamic_zone.h"
#include "cliententry.h"
#include "clientlist.h"
#include "worlddb.h"
#include "zonelist.h"
#include "zoneserver.h"
#include "../common/rulesys.h"
#include "../common/repositories/expeditions_repository.h"
#include "../common/repositories/expedition_lockouts_repository.h"
#include "../common/repositories/dynamic_zone_lockouts_repository.h"
extern ClientList client_list;
extern ZSList zoneserver_list;
DynamicZoneManager dynamic_zone_manager;
@ -27,6 +29,8 @@ void DynamicZoneManager::PurgeExpiredDynamicZones()
{
LogDynamicZones("Purging [{}] dynamic zone(s)", dz_ids.size());
DynamicZoneLockoutsRepository::DeleteWhere(database,
fmt::format("dynamic_zone_id IN ({})", fmt::join(dz_ids, ",")));
DynamicZoneMembersRepository::DeleteWhere(database,
fmt::format("dynamic_zone_id IN ({})", Strings::Join(dz_ids, ",")));
DynamicZonesRepository::DeleteWhere(database,
@ -34,8 +38,7 @@ void DynamicZoneManager::PurgeExpiredDynamicZones()
}
}
DynamicZone* DynamicZoneManager::CreateNew(
DynamicZone& dz_request, const std::vector<DynamicZoneMember>& members)
DynamicZone* DynamicZoneManager::TryCreate(DynamicZone& dz_request, const std::vector<DynamicZoneMember>& members)
{
// this creates a new dz instance and saves it to both db and cache
uint32_t dz_id = dz_request.Create();
@ -46,15 +49,12 @@ DynamicZone* DynamicZoneManager::CreateNew(
}
auto dz = std::make_unique<DynamicZone>(dz_request);
if (!members.empty())
{
dz->SaveMembers(members);
dz->CacheMemberStatuses();
}
dz->SaveMembers(members);
dz->CacheMemberStatuses();
LogDynamicZones("Created new dz [{}] for zone [{}]", dz_id, dz_request.GetZoneID());
auto pack = dz->CreateServerDzCreatePacket(0, 0);
auto pack = dz->CreateServerPacket(0, 0);
zoneserver_list.SendPacket(pack.get());
auto inserted = dynamic_zone_cache.emplace(dz_id, std::move(dz));
@ -63,18 +63,17 @@ DynamicZone* DynamicZoneManager::CreateNew(
void DynamicZoneManager::CacheNewDynamicZone(ServerPacket* pack)
{
auto buf = reinterpret_cast<ServerDzCreateSerialized_Struct*>(pack->pBuffer);
auto buf = reinterpret_cast<ServerDzCreate_Struct*>(pack->pBuffer);
auto new_dz = std::make_unique<DynamicZone>();
new_dz->LoadSerializedDzPacket(buf->cereal_data, buf->cereal_size);
new_dz->Unserialize({ buf->cereal_data, buf->cereal_size });
new_dz->CacheMemberStatuses();
// reserialize with member statuses cached before forwarding (restore origin zone)
auto repack = new_dz->CreateServerDzCreatePacket(buf->origin_zone_id, buf->origin_instance_id);
auto repack = new_dz->CreateServerPacket(buf->origin_zone_id, buf->origin_instance_id);
uint32_t dz_id = new_dz->GetID();
dynamic_zone_cache.emplace(dz_id, std::move(new_dz));
LogDynamicZones("Cached new dynamic zone [{}]", dz_id);
dynamic_zone_cache.emplace(buf->dz_id, std::move(new_dz));
LogDynamicZones("Cached new dynamic zone [{}]", buf->dz_id);
zoneserver_list.SendPacket(repack.get());
}
@ -83,18 +82,19 @@ void DynamicZoneManager::CacheAllFromDatabase()
{
BenchTimer bench;
auto dynamic_zones = DynamicZonesRepository::AllWithInstanceNotExpired(database);
auto dynamic_zone_members = DynamicZoneMembersRepository::GetAllWithNames(database);
auto dzs = DynamicZonesRepository::AllWithInstanceNotExpired(database);
auto members = DynamicZoneMembersRepository::AllWithNames(database);
auto lockouts = DynamicZoneLockoutsRepository::All(database);
dynamic_zone_cache.clear();
dynamic_zone_cache.reserve(dynamic_zones.size());
dynamic_zone_cache.reserve(dzs.size());
for (auto& entry : dynamic_zones)
for (auto& entry : dzs)
{
uint32_t dz_id = entry.id;
auto dz = std::make_unique<DynamicZone>(std::move(entry));
for (auto& member : dynamic_zone_members)
for (auto& member : members)
{
if (member.dynamic_zone_id == dz_id)
{
@ -102,6 +102,14 @@ void DynamicZoneManager::CacheAllFromDatabase()
}
}
for (auto& lockout : lockouts)
{
if (lockout.dynamic_zone_id == dz->GetID())
{
dz->m_lockouts.emplace_back(dz->GetName(), std::move(lockout));
}
}
// note leader status won't be updated here until leader is set by owning system (expeditions)
dz->CacheMemberStatuses();
@ -142,24 +150,10 @@ void DynamicZoneManager::Process()
dynamic_zone_cache.erase(dz_id);
}
// need to look up expedition ids until lockouts are moved to dynamic zones
std::vector<uint32_t> expedition_ids;
auto expeditions = ExpeditionsRepository::GetWhere(database,
fmt::format("dynamic_zone_id IN ({})", Strings::Join(dynamic_zone_ids, ",")));
if (!expeditions.empty())
{
for (const auto& expedition : expeditions)
{
expedition_ids.emplace_back(expedition.id);
}
ExpeditionLockoutsRepository::DeleteWhere(database,
fmt::format("expedition_id IN ({})", Strings::Join(expedition_ids, ",")));
}
ExpeditionsRepository::DeleteWhere(database,
fmt::format("dynamic_zone_id IN ({})", Strings::Join(dynamic_zone_ids, ",")));
DynamicZoneMembersRepository::RemoveAllMembers(database, dynamic_zone_ids);
DynamicZoneLockoutsRepository::DeleteWhere(database,
fmt::format("dynamic_zone_id IN ({})", fmt::join(dynamic_zone_ids, ",")));
DynamicZoneMembersRepository::DeleteWhere(database,
fmt::format("dynamic_zone_id IN ({})", fmt::join(dynamic_zone_ids, ",")));
DynamicZonesRepository::DeleteWhere(database,
fmt::format("id IN ({})", Strings::Join(dynamic_zone_ids, ",")));
}
@ -174,3 +168,250 @@ void DynamicZoneManager::LoadTemplates()
m_dz_templates[dz_template.id] = dz_template;
}
}
void DynamicZoneManager::HandleZoneMessage(ServerPacket* pack)
{
switch (pack->opcode)
{
case ServerOP_DzCreated:
{
CacheNewDynamicZone(pack);
break;
}
case ServerOP_DzAddPlayer:
{
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
ClientListEntry* cle = client_list.FindCharacter(buf->target_name);
if (cle && cle->Server())
{
// continue in the add target's zone
buf->is_char_online = true;
cle->Server()->SendPacket(pack);
}
else
{
// add target not online, return to inviter
ClientListEntry* inviter_cle = client_list.FindCharacter(buf->requester_name);
if (inviter_cle && inviter_cle->Server())
{
inviter_cle->Server()->SendPacket(pack);
}
}
break;
}
case ServerOP_DzSaveInvite:
{
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
if (ClientListEntry* cle = client_list.FindCharacter(buf->target_name))
{
// store packet on cle and re-send it when client requests it
buf->is_char_online = true;
pack->opcode = ServerOP_DzAddPlayer;
cle->SetPendingDzInvite(pack);
}
break;
}
case ServerOP_DzRequestInvite:
{
auto buf = reinterpret_cast<ServerCharacterID_Struct*>(pack->pBuffer);
if (ClientListEntry* cle = client_list.FindCLEByCharacterID(buf->char_id))
{
auto invite_pack = cle->GetPendingDzInvite();
if (invite_pack && cle->Server())
{
cle->Server()->SendPacket(invite_pack.get());
}
}
break;
}
case ServerOP_DzMakeLeader:
{
auto buf = reinterpret_cast<ServerDzCommandMakeLeader_Struct*>(pack->pBuffer);
// notify requester (old leader) and new leader of the result
ZoneServer* new_leader_zs = nullptr;
ClientListEntry* leader_cle = client_list.FindCharacter(buf->new_leader_name);
if (leader_cle && leader_cle->Server())
{
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz && dz->GetLeaderID() == buf->requester_id)
{
buf->is_success = dz->SetNewLeader(leader_cle->CharID());
}
buf->is_online = true;
new_leader_zs = leader_cle->Server();
new_leader_zs->SendPacket(pack);
}
// if old and new leader are in the same zone only send one message
ClientListEntry* requester_cle = client_list.FindCLEByCharacterID(buf->requester_id);
if (requester_cle && requester_cle->Server() && requester_cle->Server() != new_leader_zs)
{
requester_cle->Server()->SendPacket(pack);
}
break;
}
case ServerOP_DzSetCompass:
case ServerOP_DzSetSafeReturn:
case ServerOP_DzSetZoneIn:
{
auto buf = reinterpret_cast<ServerDzLocation_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
if (pack->opcode == ServerOP_DzSetCompass)
{
dz->SetCompass(buf->zone_id, buf->x, buf->y, buf->z, false);
}
else if (pack->opcode == ServerOP_DzSetSafeReturn)
{
dz->SetSafeReturn(buf->zone_id, buf->x, buf->y, buf->z, buf->heading, false);
}
else if (pack->opcode == ServerOP_DzSetZoneIn)
{
dz->SetZoneInLocation(buf->x, buf->y, buf->z, buf->heading, false);
}
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzSetSwitchID:
{
auto buf = reinterpret_cast<ServerDzSwitchID_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
dz->ProcessSetSwitchID(buf->dz_switch_id);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzAddRemoveMember:
{
auto buf = reinterpret_cast<ServerDzMember_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
auto status = static_cast<DynamicZoneMemberStatus>(buf->character_status);
dz->ProcessMemberAddRemove({ buf->character_id, buf->character_name, status }, buf->removed);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzSwapMembers:
{
auto buf = reinterpret_cast<ServerDzMemberSwap_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
// we add first in world so new member can be chosen if leader is removed
auto status = static_cast<DynamicZoneMemberStatus>(buf->add_character_status);
dz->ProcessMemberAddRemove({ buf->add_character_id, buf->add_character_name, status }, false);
dz->ProcessMemberAddRemove({ buf->remove_character_id, buf->remove_character_name }, true);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzRemoveAllMembers:
{
auto buf = reinterpret_cast<ServerDzID_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
dz->ProcessRemoveAllMembers();
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzSetSecondsRemaining:
{
auto buf = reinterpret_cast<ServerDzSetDuration_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
dz->SetSecondsRemaining(buf->seconds);
}
break;
}
case ServerOP_DzGetMemberStatuses:
{
auto buf = reinterpret_cast<ServerDzID_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
dz->SendZoneMemberStatuses(buf->sender_zone_id, buf->sender_instance_id);
}
break;
}
case ServerOP_DzUpdateMemberStatus:
{
auto buf = reinterpret_cast<ServerDzMemberStatus_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
auto status = static_cast<DynamicZoneMemberStatus>(buf->status);
dz->ProcessMemberStatusChange(buf->character_id, status);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzMovePC:
{
auto buf = reinterpret_cast<ServerDzMovePC_Struct*>(pack->pBuffer);
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz && dz->HasMember(buf->character_id))
{
zoneserver_list.SendPacket(buf->sender_zone_id, buf->sender_instance_id, pack);
}
break;
}
case ServerOP_DzLock:
{
auto buf = reinterpret_cast<ServerDzLock_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
dz->SetLocked(buf->lock);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzReplayOnJoin:
{
auto buf = reinterpret_cast<ServerDzBool_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
dz->SetReplayOnJoin(buf->enabled);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzLockout:
{
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
DzLockout lockout{ dz->GetUUID(), dz->GetName(), buf->event_name, buf->expire_time, buf->duration };
dz->HandleLockoutUpdate(lockout, buf->remove, buf->members_only);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzLockoutDuration:
{
auto buf = reinterpret_cast<ServerDzLockout_Struct*>(pack->pBuffer);
if (auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id))
{
DzLockout lockout{ dz->GetUUID(), dz->GetName(), buf->event_name, buf->expire_time, buf->duration };
dz->HandleLockoutDuration(lockout, buf->seconds, buf->members_only, false);
}
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DzCharacterLockout:
{
auto buf = reinterpret_cast<ServerDzCharacterLockout_Struct*>(pack->pBuffer);
auto cle = client_list.FindCLEByCharacterID(buf->char_id);
if (cle && cle->Server())
{
cle->Server()->SendPacket(pack);
}
break;
}
default:
break;
};
}

View File

@ -20,7 +20,8 @@ public:
void CacheAllFromDatabase();
void CacheNewDynamicZone(ServerPacket* pack);
DynamicZone* CreateNew(DynamicZone& dz_request, const std::vector<DynamicZoneMember>& members);
DynamicZone* TryCreate(DynamicZone& dz_request, const std::vector<DynamicZoneMember>& members);
void HandleZoneMessage(ServerPacket* pack);
void LoadTemplates();
void Process();
void PurgeExpiredDynamicZones();

View File

@ -1,78 +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
*
*/
#include "expedition_database.h"
#include "worlddb.h"
#include "../common/repositories/expeditions_repository.h"
#include "../common/repositories/expedition_lockouts_repository.h"
#include "../common/repositories/dynamic_zone_members_repository.h"
void ExpeditionDatabase::PurgeExpiredExpeditions()
{
std::string query = SQL(
SELECT
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 dynamic_zone_id, COUNT(*) 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 dynamic_zone_members.member_count IS NULL
OR dynamic_zone_members.member_count = 0
OR (instance_list.start_time + instance_list.duration) <= UNIX_TIMESTAMP();
);
auto results = database.QueryDatabase(query);
if (results.Success())
{
std::vector<std::string> expedition_ids;
std::vector<uint32_t> dynamic_zone_ids;
for (auto row = results.begin(); row != results.end(); ++row)
{
expedition_ids.emplace_back(row[0]);
dynamic_zone_ids.emplace_back(static_cast<uint32_t>(strtoul(row[1], nullptr, 10)));
}
if (!expedition_ids.empty())
{
ExpeditionsRepository::DeleteWhere(database, fmt::format("id IN ({})", fmt::join(expedition_ids, ",")));
ExpeditionLockoutsRepository::DeleteWhere(database, fmt::format("expedition_id IN ({})", fmt::join(expedition_ids, ",")));
DynamicZoneMembersRepository::RemoveAllMembers(database, dynamic_zone_ids);
}
}
}
void ExpeditionDatabase::PurgeExpiredCharacterLockouts()
{
std::string query = SQL(
DELETE FROM character_expedition_lockouts
WHERE expire_time <= NOW();
);
database.QueryDatabase(query);
}

View File

@ -1,35 +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 WORLD_EXPEDITION_DATABASE_H
#define WORLD_EXPEDITION_DATABASE_H
#include <cstdint>
#include <vector>
class Expedition;
namespace ExpeditionDatabase
{
void PurgeExpiredExpeditions();
void PurgeExpiredCharacterLockouts();
};
#endif

View File

@ -1,151 +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
*
*/
#include "dynamic_zone.h"
#include "expedition_message.h"
#include "cliententry.h"
#include "clientlist.h"
#include "zonelist.h"
#include "zoneserver.h"
#include "../common/servertalk.h"
#include <algorithm>
extern ClientList client_list;
extern ZSList zoneserver_list;
void ExpeditionMessage::HandleZoneMessage(ServerPacket* pack)
{
switch (pack->opcode)
{
case ServerOP_ExpeditionCreate:
{
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_ExpeditionDzAddPlayer:
{
ExpeditionMessage::AddPlayer(pack);
break;
}
case ServerOP_ExpeditionDzMakeLeader:
{
ExpeditionMessage::MakeLeader(pack);
break;
}
case ServerOP_ExpeditionCharacterLockout:
{
auto buf = reinterpret_cast<ServerExpeditionCharacterLockout_Struct*>(pack->pBuffer);
auto cle = client_list.FindCLEByCharacterID(buf->character_id);
if (cle && cle->Server())
{
cle->Server()->SendPacket(pack);
}
break;
}
case ServerOP_ExpeditionSaveInvite:
{
ExpeditionMessage::SaveInvite(pack);
break;
}
case ServerOP_ExpeditionRequestInvite:
{
ExpeditionMessage::RequestInvite(pack);
break;
}
}
}
void ExpeditionMessage::AddPlayer(ServerPacket* pack)
{
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
ClientListEntry* invited_cle = client_list.FindCharacter(buf->target_name);
if (invited_cle && invited_cle->Server())
{
// continue in the add target's zone
buf->is_char_online = true;
invited_cle->Server()->SendPacket(pack);
}
else
{
// add target not online, return to inviter
ClientListEntry* inviter_cle = client_list.FindCharacter(buf->requester_name);
if (inviter_cle && inviter_cle->Server())
{
inviter_cle->Server()->SendPacket(pack);
}
}
}
void ExpeditionMessage::MakeLeader(ServerPacket* pack)
{
auto buf = reinterpret_cast<ServerDzCommandMakeLeader_Struct*>(pack->pBuffer);
// notify requester (old leader) and new leader of the result
ZoneServer* new_leader_zs = nullptr;
ClientListEntry* new_leader_cle = client_list.FindCharacter(buf->new_leader_name);
if (new_leader_cle && new_leader_cle->Server())
{
auto dz = DynamicZone::FindDynamicZoneByID(buf->dz_id);
if (dz && dz->GetLeaderID() == buf->requester_id)
{
buf->is_success = dz->SetNewLeader(new_leader_cle->CharID());
}
buf->is_online = true;
new_leader_zs = new_leader_cle->Server();
new_leader_zs->SendPacket(pack);
}
// if old and new leader are in the same zone only send one message
ClientListEntry* requester_cle = client_list.FindCLEByCharacterID(buf->requester_id);
if (requester_cle && requester_cle->Server() && requester_cle->Server() != new_leader_zs)
{
requester_cle->Server()->SendPacket(pack);
}
}
void ExpeditionMessage::SaveInvite(ServerPacket* pack)
{
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
ClientListEntry* invited_cle = client_list.FindCharacter(buf->target_name);
if (invited_cle)
{
// store packet on cle and re-send it when client requests it
buf->is_char_online = true;
pack->opcode = ServerOP_ExpeditionDzAddPlayer;
invited_cle->SetPendingExpeditionInvite(pack);
}
}
void ExpeditionMessage::RequestInvite(ServerPacket* pack)
{
auto buf = reinterpret_cast<ServerExpeditionCharacterID_Struct*>(pack->pBuffer);
ClientListEntry* cle = client_list.FindCLEByCharacterID(buf->character_id);
if (cle)
{
auto invite_pack = cle->GetPendingExpeditionInvite();
if (invite_pack && cle->Server())
{
cle->Server()->SendPacket(invite_pack.get());
}
}
}

View File

@ -1,35 +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 WORLD_EXPEDITION_MESSAGE_H
#define WORLD_EXPEDITION_MESSAGE_H
class ServerPacket;
namespace ExpeditionMessage
{
void AddPlayer(ServerPacket* pack);
void HandleZoneMessage(ServerPacket* pack);
void MakeLeader(ServerPacket* pack);
void RequestInvite(ServerPacket* pack);
void SaveInvite(ServerPacket* pack);
};
#endif

View File

@ -76,10 +76,10 @@
#include "web_interface.h"
#include "console.h"
#include "dynamic_zone_manager.h"
#include "expedition_database.h"
#include "world_server_cli.h"
#include "../common/content/world_content_service.h"
#include "../common/repositories/character_expedition_lockouts_repository.h"
#include "../common/repositories/character_task_timers_repository.h"
#include "../common/zone_store.h"
#include "world_event_scheduler.h"
@ -449,7 +449,7 @@ int main(int argc, char **argv)
if (PurgeInstanceTimer.Check()) {
database.PurgeExpiredInstances();
database.PurgeAllDeletedDataBuckets();
ExpeditionDatabase::PurgeExpiredCharacterLockouts();
CharacterExpeditionLockoutsRepository::DeleteWhere(database, "expire_time <= NOW()");
CharacterTaskTimersRepository::DeleteWhere(database, "expire_time <= NOW()");
}

View File

@ -1172,7 +1172,7 @@ void SharedTaskManager::CreateDynamicZone(SharedTask *shared_task, DynamicZone &
}
}
auto new_dz = dynamic_zone_manager.CreateNew(dz_request, dz_members);
auto new_dz = dynamic_zone_manager.TryCreate(dz_request, dz_members);
if (new_dz) {
auto shared_task_dz = SharedTaskDynamicZonesRepository::NewEntity();
shared_task_dz.shared_task_id = shared_task->GetDbSharedTask().id;

View File

@ -283,7 +283,7 @@ void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack)
auto t = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(buf->task_id, buf->source_character_id);
if (t) {
DynamicZone dz;
dz.LoadSerializedDzPacket(buf->cereal_data, buf->cereal_size);
dz.Unserialize({ buf->cereal_data, buf->cereal_size });
shared_task_manager.CreateDynamicZone(t, dz);
}

View File

@ -5,12 +5,12 @@
#include "../common/http/uri.h"
#include "../common/net/console_server.h"
#include "../common/net/servertalk_server.h"
#include "../common/repositories/character_expedition_lockouts_repository.h"
#include "../common/repositories/character_task_timers_repository.h"
#include "../common/rulesys.h"
#include "../common/strings.h"
#include "adventure_manager.h"
#include "dynamic_zone_manager.h"
#include "expedition_database.h"
#include "login_server_list.h"
#include "shared_task_manager.h"
#include "ucs.h"
@ -367,9 +367,8 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
LogInfo("Purging expired dynamic zones and members");
dynamic_zone_manager.PurgeExpiredDynamicZones();
LogInfo("Purging expired expeditions");
ExpeditionDatabase::PurgeExpiredExpeditions();
ExpeditionDatabase::PurgeExpiredCharacterLockouts();
LogInfo("Purging expired character expedition lockouts");
CharacterExpeditionLockoutsRepository::DeleteWhere(database, "expire_time <= NOW()");
LogInfo("Purging expired character task timers");
CharacterTaskTimersRepository::DeleteWhere(database, "expire_time <= NOW()");

View File

@ -39,7 +39,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/zone_store.h"
#include "dynamic_zone.h"
#include "dynamic_zone_manager.h"
#include "expedition_message.h"
#include "shared_task_world_messaging.h"
#include "../common/shared_tasks.h"
#include "shared_task_manager.h"
@ -1375,10 +1374,6 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
case ServerOP_Consent:
case ServerOP_DepopAllPlayersCorpses:
case ServerOP_DepopPlayerCorpse:
case ServerOP_ExpeditionLockState:
case ServerOP_ExpeditionLockout:
case ServerOP_ExpeditionLockoutDuration:
case ServerOP_ExpeditionReplayOnJoin:
case ServerOP_GuildRankUpdate:
case ServerOP_ItemStatus:
case ServerOP_KickPlayer:
@ -1532,16 +1527,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
SharedTaskWorldMessaging::HandleZoneMessage(pack);
break;
}
case ServerOP_ExpeditionCreate:
case ServerOP_ExpeditionDzAddPlayer:
case ServerOP_ExpeditionDzMakeLeader:
case ServerOP_ExpeditionCharacterLockout:
case ServerOP_ExpeditionSaveInvite:
case ServerOP_ExpeditionRequestInvite: {
ExpeditionMessage::HandleZoneMessage(pack);
break;
}
case ServerOP_DzCreated:
case ServerOP_DzAddPlayer:
case ServerOP_DzSaveInvite:
case ServerOP_DzRequestInvite:
case ServerOP_DzMakeLeader:
case ServerOP_DzAddRemoveMember:
case ServerOP_DzSwapMembers:
case ServerOP_DzRemoveAllMembers:
@ -1552,8 +1542,13 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
case ServerOP_DzSetZoneIn:
case ServerOP_DzSetSwitchID:
case ServerOP_DzMovePC:
case ServerOP_DzLock:
case ServerOP_DzReplayOnJoin:
case ServerOP_DzLockout:
case ServerOP_DzLockoutDuration:
case ServerOP_DzCharacterLockout:
case ServerOP_DzUpdateMemberStatus: {
DynamicZone::HandleZoneMessage(pack);
dynamic_zone_manager.HandleZoneMessage(pack);
break;
}
case ServerOP_GuildTributeUpdate: {

View File

@ -36,8 +36,6 @@ SET(zone_sources
encounter.cpp
entity.cpp
exp.cpp
expedition.cpp
expedition_database.cpp
expedition_request.cpp
fastmath.cpp
fearpath.cpp
@ -205,8 +203,6 @@ SET(zone_headers
encounter.h
entity.h
event_codes.h
expedition.h
expedition_database.h
expedition_request.h
fastmath.h
forage.h

View File

@ -40,8 +40,7 @@ extern volatile bool RunLoops;
#include "../common/data_verification.h"
#include "../common/profanity_manager.h"
#include "data_bucket.h"
#include "expedition.h"
#include "expedition_database.h"
#include "dynamic_zone.h"
#include "expedition_request.h"
#include "position.h"
#include "worldserver.h"
@ -61,6 +60,7 @@ extern volatile bool RunLoops;
#include "lua_parser.h"
#include "../common/repositories/character_alternate_abilities_repository.h"
#include "../common/repositories/character_expedition_lockouts_repository.h"
#include "../common/repositories/account_flags_repository.h"
#include "../common/repositories/bug_reports_repository.h"
#include "../common/repositories/char_recipe_list_repository.h"
@ -10024,13 +10024,13 @@ void Client::SendCrossZoneMessageString(
return;
}
SerializeBuffer argument_buffer;
SerializeBuffer argbuf;
for (const auto& argument : arguments)
{
argument_buffer.WriteString(argument);
argbuf.WriteString(argument);
}
uint32_t args_size = static_cast<uint32_t>(argument_buffer.size());
uint32_t args_size = static_cast<uint32_t>(argbuf.size());
uint32_t pack_size = sizeof(CZClientMessageString_Struct) + args_size;
auto pack = std::make_unique<ServerPacket>(ServerOP_CZClientMessageString, pack_size);
auto buf = reinterpret_cast<CZClientMessageString_Struct*>(pack->pBuffer);
@ -10038,7 +10038,10 @@ void Client::SendCrossZoneMessageString(
buf->chat_type = chat_type;
strn0cpy(buf->client_name, character_name.c_str(), sizeof(buf->client_name));
buf->args_size = args_size;
memcpy(buf->args, argument_buffer.buffer(), argument_buffer.size());
if (argbuf.size() > 0)
{
memcpy(buf->args, argbuf.buffer(), argbuf.size());
}
if (client)
{
@ -10056,56 +10059,52 @@ void Client::SendDynamicZoneUpdates()
SendDzCompassUpdate();
SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::Online);
m_expedition_lockouts = ExpeditionDatabase::LoadCharacterLockouts(CharacterID());
m_dz_lockouts = CharacterExpeditionLockoutsRepository::GetLockouts(database, CharacterID());
// expeditions are the only dz type that keep the window updated
auto expedition = GetExpedition();
if (expedition)
if (DynamicZone* dz = GetExpedition())
{
expedition->GetDynamicZone()->SendClientWindowUpdate(this);
dz->SendClientWindowUpdate(this);
// live synchronizes lockouts obtained during the active expedition to
// members once they zone into the expedition's dynamic zone instance
if (expedition->GetDynamicZone()->IsCurrentZoneDzInstance())
if (dz->IsCurrentZoneDz())
{
expedition->SyncCharacterLockouts(CharacterID(), m_expedition_lockouts);
dz->SyncCharacterLockouts(CharacterID(), m_dz_lockouts);
}
}
SendExpeditionLockoutTimers();
SendDzLockoutTimers();
// ask world for any pending invite we saved from a previous zone
RequestPendingExpeditionInvite();
RequestPendingDzInvite();
}
Expedition* Client::CreateExpedition(DynamicZone& dz, bool disable_messages)
DynamicZone* Client::CreateExpedition(DynamicZone& dz, bool silent)
{
return Expedition::TryCreate(this, dz, disable_messages);
return DynamicZone::TryCreate(*this, dz, silent);
}
Expedition* Client::CreateExpedition(
const std::string& zone_name, uint32 version, uint32 duration, const std::string& expedition_name,
uint32 min_players, uint32 max_players, bool disable_messages)
DynamicZone* Client::CreateExpedition(uint32 zone, uint32 version, uint32 duration, const std::string& name, uint32 min_players, uint32 max_players, bool silent)
{
DynamicZone dz{ ZoneID(zone_name), version, duration, DynamicZoneType::Expedition };
dz.SetName(expedition_name);
DynamicZone dz{ zone, version, duration, DynamicZoneType::Expedition };
dz.SetName(name);
dz.SetMinPlayers(min_players);
dz.SetMaxPlayers(max_players);
return Expedition::TryCreate(this, dz, disable_messages);
return DynamicZone::TryCreate(*this, dz, silent);
}
Expedition* Client::CreateExpeditionFromTemplate(uint32_t dz_template_id)
DynamicZone* Client::CreateExpeditionFromTemplate(uint32_t dz_template_id)
{
Expedition* expedition = nullptr;
auto it = zone->dz_template_cache.find(dz_template_id);
if (it != zone->dz_template_cache.end())
{
DynamicZone dz(DynamicZoneType::Expedition);
dz.LoadTemplate(it->second);
expedition = Expedition::TryCreate(this, dz, false);
return DynamicZone::TryCreate(*this, dz, false);
}
return expedition;
return nullptr;
}
void Client::CreateTaskDynamicZone(int task_id, DynamicZone& dz_request)
@ -10116,57 +10115,58 @@ void Client::CreateTaskDynamicZone(int task_id, DynamicZone& dz_request)
}
}
Expedition* Client::GetExpedition() const
DynamicZone* Client::GetExpedition() const
{
if (zone && m_expedition_id)
if (zone)
{
auto expedition_cache_iter = zone->expedition_cache.find(m_expedition_id);
if (expedition_cache_iter != zone->expedition_cache.end())
for (uint32_t dz_id : m_dynamic_zone_ids)
{
return expedition_cache_iter->second.get();
auto it = zone->dynamic_zone_cache.find(dz_id);
if (it != zone->dynamic_zone_cache.end() && it->second->IsExpedition())
{
return it->second.get();
}
}
}
return nullptr;
}
void Client::AddExpeditionLockout(const ExpeditionLockoutTimer& lockout, bool update_db)
uint32_t Client::GetExpeditionID() const
{
if (const DynamicZone* dz = GetExpedition())
{
return dz->GetID();
}
return 0;
}
void Client::AddDzLockout(const DzLockout& lockout, bool update_db)
{
// todo: support for account based lockouts like live AoC expeditions
// if client already has this lockout, we're replacing it with the new one
m_expedition_lockouts.erase(std::remove_if(m_expedition_lockouts.begin(), m_expedition_lockouts.end(),
[&](const ExpeditionLockoutTimer& existing_lockout) {
return existing_lockout.IsSameLockout(lockout);
}
), m_expedition_lockouts.end());
std::erase_if(m_dz_lockouts, [&](const DzLockout& l) { return l.IsSame(lockout); });
m_expedition_lockouts.emplace_back(lockout);
m_dz_lockouts.push_back(lockout);
if (update_db) // for quest api
{
ExpeditionDatabase::InsertCharacterLockouts(CharacterID(), { lockout });
CharacterExpeditionLockoutsRepository::InsertLockouts(database, CharacterID(), { lockout });
}
SendExpeditionLockoutTimers();
SendDzLockoutTimers();
}
void Client::AddNewExpeditionLockout(
const std::string& expedition_name, const std::string& event_name, uint32_t seconds, std::string uuid)
void Client::AddDzLockout(const std::string& expedition, const std::string& event, uint32_t seconds, std::string uuid)
{
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds, uuid);
AddExpeditionLockout(lockout, true);
auto lockout = DzLockout::Create(expedition, event, seconds, uuid);
AddDzLockout(lockout, true);
}
void Client::AddExpeditionLockoutDuration(
const std::string& expedition_name, const std::string& event_name, int seconds,
const std::string& uuid, bool update_db)
void Client::AddDzLockoutDuration(const DzLockout& lockout, int seconds, const std::string& uuid, bool update_db)
{
auto it = std::find_if(m_expedition_lockouts.begin(), m_expedition_lockouts.end(),
[&](const ExpeditionLockoutTimer& lockout) {
return lockout.IsSameLockout(expedition_name, event_name);
});
if (it != m_expedition_lockouts.end())
auto it = std::ranges::find_if(m_dz_lockouts, [&](const DzLockout& l) { return l.IsSame(lockout); });
if (it != m_dz_lockouts.end())
{
it->AddLockoutTime(seconds);
@ -10177,98 +10177,86 @@ void Client::AddExpeditionLockoutDuration(
if (update_db)
{
ExpeditionDatabase::InsertCharacterLockouts(CharacterID(), { *it });
CharacterExpeditionLockoutsRepository::InsertLockouts(database, CharacterID(), { *it });
}
SendExpeditionLockoutTimers();
SendDzLockoutTimers();
}
else if (seconds > 0) // missing lockouts inserted for reductions would be instantly expired
{
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds, uuid);
AddExpeditionLockout(lockout, update_db);
AddDzLockout(lockout, update_db);
}
}
void Client::RemoveExpeditionLockout(
const std::string& expedition_name, const std::string& event_name, bool update_db)
void Client::RemoveDzLockout(const std::string& expedition, const std::string& event, bool update_db)
{
m_expedition_lockouts.erase(std::remove_if(m_expedition_lockouts.begin(), m_expedition_lockouts.end(),
[&](const ExpeditionLockoutTimer& lockout) {
return lockout.IsSameLockout(expedition_name, event_name);
}
), m_expedition_lockouts.end());
std::erase_if(m_dz_lockouts, [&](const DzLockout& l) { return l.IsSame(expedition, event); });
if (update_db) // for quest api
{
ExpeditionDatabase::DeleteCharacterLockout(CharacterID(), expedition_name, event_name);
CharacterExpeditionLockoutsRepository::DeleteWhere(database, fmt::format(
"character_id = {} AND expedition_name = '{}' AND event_name = '{}'",
CharacterID(), Strings::Escape(expedition), Strings::Escape(event)));
}
SendExpeditionLockoutTimers();
SendDzLockoutTimers();
}
void Client::RemoveAllExpeditionLockouts(const std::string& expedition_name, bool update_db)
void Client::RemoveDzLockouts(const std::string& expedition, bool update_db)
{
if (expedition_name.empty())
if (expedition.empty())
{
if (update_db)
{
ExpeditionDatabase::DeleteAllCharacterLockouts(CharacterID());
CharacterExpeditionLockoutsRepository::DeleteWhere(database, fmt::format(
"character_id = {}", CharacterID()));
}
m_expedition_lockouts.clear();
m_dz_lockouts.clear();
}
else
{
if (update_db)
{
ExpeditionDatabase::DeleteAllCharacterLockouts(CharacterID(), expedition_name);
CharacterExpeditionLockoutsRepository::DeleteWhere(database, fmt::format(
"character_id = {} AND expedition_name = '{}'", CharacterID(), Strings::Escape(expedition)));
}
m_expedition_lockouts.erase(std::remove_if(m_expedition_lockouts.begin(), m_expedition_lockouts.end(),
[&](const ExpeditionLockoutTimer& lockout) {
return lockout.GetExpeditionName() == expedition_name;
}
), m_expedition_lockouts.end());
std::erase_if(m_dz_lockouts, [&](const DzLockout& l) { return l.DzName() == expedition; });
}
SendExpeditionLockoutTimers();
SendDzLockoutTimers();
}
const ExpeditionLockoutTimer* Client::GetExpeditionLockout(
const std::string& expedition_name, const std::string& event_name, bool include_expired) const
const DzLockout* Client::GetDzLockout(const std::string& expedition, const std::string& event) const
{
for (const auto& expedition_lockout : m_expedition_lockouts)
for (const auto& lockout : m_dz_lockouts)
{
if ((include_expired || !expedition_lockout.IsExpired()) &&
expedition_lockout.IsSameLockout(expedition_name, event_name))
if (!lockout.IsExpired() && lockout.IsSame(expedition, event))
{
return &expedition_lockout;
return &lockout;
}
}
return nullptr;
}
std::vector<ExpeditionLockoutTimer> Client::GetExpeditionLockouts(
const std::string& expedition_name, bool include_expired)
std::vector<DzLockout> Client::GetDzLockouts(const std::string& expedition)
{
std::vector<ExpeditionLockoutTimer> lockouts;
for (const auto& lockout : m_expedition_lockouts)
std::vector<DzLockout> lockouts;
for (const auto& lockout : m_dz_lockouts)
{
if ((include_expired || !lockout.IsExpired()) &&
lockout.GetExpeditionName() == expedition_name)
if (!lockout.IsExpired() && lockout.DzName() == expedition)
{
lockouts.emplace_back(lockout);
lockouts.push_back(lockout);
}
}
return lockouts;
}
bool Client::HasExpeditionLockout(
const std::string& expedition_name, const std::string& event_name, bool include_expired)
bool Client::HasDzLockout(const std::string& expedition, const std::string& event) const
{
return (GetExpeditionLockout(expedition_name, event_name, include_expired) != nullptr);
return GetDzLockout(expedition, event) != nullptr;
}
void Client::SendExpeditionLockoutTimers()
void Client::SendDzLockoutTimers()
{
std::vector<ExpeditionLockoutTimerEntry_Struct> lockout_entries;
@ -10277,20 +10265,20 @@ void Client::SendExpeditionLockoutTimers()
constexpr uint32_t rounding_seconds = 60;
// erases expired lockouts while building lockout timer list
for (auto it = m_expedition_lockouts.begin(); it != m_expedition_lockouts.end();)
for (auto it = m_dz_lockouts.begin(); it != m_dz_lockouts.end();)
{
uint32_t seconds_remaining = it->GetSecondsRemaining();
if (seconds_remaining == 0)
{
it = m_expedition_lockouts.erase(it);
it = m_dz_lockouts.erase(it);
}
else
{
ExpeditionLockoutTimerEntry_Struct lockout;
strn0cpy(lockout.expedition_name, it->GetExpeditionName().c_str(), sizeof(lockout.expedition_name));
ExpeditionLockoutTimerEntry_Struct lockout{};
strn0cpy(lockout.expedition_name, it->DzName().c_str(), sizeof(lockout.expedition_name));
lockout.seconds_remaining = seconds_remaining + rounding_seconds;
lockout.event_type = it->IsReplayTimer() ? Expedition::REPLAY_TIMER_ID : Expedition::EVENT_TIMER_ID;
strn0cpy(lockout.event_name, it->GetEventName().c_str(), sizeof(lockout.event_name));
lockout.event_type = it->IsReplay() ? DynamicZone::ReplayTimerID : DynamicZone::EventTimerID;
strn0cpy(lockout.event_name, it->Event().c_str(), sizeof(lockout.event_name));
lockout_entries.emplace_back(lockout);
++it;
@ -10310,38 +10298,31 @@ void Client::SendExpeditionLockoutTimers()
QueuePacket(outapp.get());
}
void Client::RequestPendingExpeditionInvite()
void Client::RequestPendingDzInvite() const
{
uint32_t packsize = sizeof(ServerExpeditionCharacterID_Struct);
auto pack = std::make_unique<ServerPacket>(ServerOP_ExpeditionRequestInvite, packsize);
auto packbuf = reinterpret_cast<ServerExpeditionCharacterID_Struct*>(pack->pBuffer);
packbuf->character_id = CharacterID();
worldserver.SendPacket(pack.get());
ServerPacket pack(ServerOP_DzRequestInvite, static_cast<uint32_t>(sizeof(ServerCharacterID_Struct)));
auto packbuf = reinterpret_cast<ServerCharacterID_Struct*>(pack.pBuffer);
packbuf->char_id = CharacterID();
worldserver.SendPacket(&pack);
}
void Client::DzListTimers()
{
// only lists player's current replay timer lockouts, not all event lockouts
bool found = false;
for (const auto& lockout : m_expedition_lockouts)
for (const auto& lockout : m_dz_lockouts)
{
if (lockout.IsReplayTimer())
if (lockout.IsReplay())
{
found = true;
auto time_remaining = lockout.GetDaysHoursMinutesRemaining();
MessageString(
Chat::Yellow, DZLIST_REPLAY_TIMER,
time_remaining.days.c_str(),
time_remaining.hours.c_str(),
time_remaining.mins.c_str(),
lockout.GetExpeditionName().c_str()
);
auto time = lockout.GetTimeRemainingStrs();
MessageString(Chat::Yellow, DZ_TIMER, time.days.c_str(), time.hours.c_str(), time.mins.c_str(), lockout.DzName().c_str());
}
}
if (!found)
{
MessageString(Chat::Yellow, EXPEDITION_NO_TIMERS);
MessageString(Chat::Yellow, DZ_NO_TIMERS);
}
}
@ -10447,7 +10428,10 @@ std::unique_ptr<EQApplicationPacket> Client::CreateCompassPacket(
auto outapp = std::make_unique<EQApplicationPacket>(OP_DzCompass, outsize);
auto outbuf = reinterpret_cast<DynamicZoneCompass_Struct*>(outapp->pBuffer);
outbuf->count = count;
memcpy(outbuf->entries, compass_entries.data(), entries_size);
if (!compass_entries.empty())
{
memcpy(outbuf->entries, compass_entries.data(), entries_size);
}
return outapp;
}
@ -10456,7 +10440,7 @@ void Client::GoToDzSafeReturnOrBind(const DynamicZone* dynamic_zone)
{
if (dynamic_zone)
{
auto safereturn = dynamic_zone->GetSafeReturnLocation();
const auto& safereturn = dynamic_zone->GetSafeReturnLocation();
if (safereturn.zone_id != 0)
{
LogDynamicZonesDetail("Sending [{}] to safereturn zone [{}]", CharacterID(), safereturn.zone_id);
@ -10513,7 +10497,7 @@ void Client::SetDynamicZoneMemberStatus(DynamicZoneMemberStatus status)
for (auto& dz : GetDynamicZones())
{
// the rule to disable this status is handled internally by the dz
if (status == DynamicZoneMemberStatus::Online && dz->IsCurrentZoneDzInstance())
if (status == DynamicZoneMemberStatus::Online && dz->IsCurrentZoneDz())
{
status = DynamicZoneMemberStatus::InDynamicZone;
}
@ -10534,7 +10518,7 @@ void Client::MovePCDynamicZone(uint32 zone_id, int zone_version, bool msg_if_inv
{
if (msg_if_invalid)
{
MessageString(Chat::Red, DYNAMICZONE_WAY_IS_BLOCKED); // unconfirmed message
MessageString(Chat::Red, DZ_WAY_IS_BLOCKED); // unconfirmed message
}
}
else if (client_dzs.size() == 1)

View File

@ -21,8 +21,7 @@
class Client;
class EQApplicationPacket;
class DynamicZone;
class Expedition;
class ExpeditionLockoutTimer;
class DzLockout;
class ExpeditionRequest;
class Group;
class NPC;
@ -32,6 +31,7 @@ class Seperator;
class ServerPacket;
struct DynamicZoneLocation;
enum WaterRegionType : int;
enum class DynamicZoneMemberStatus;
namespace EQ
{
@ -248,6 +248,13 @@ struct ClientReward
uint32 amount;
};
struct ExpeditionInvite
{
uint32_t dz_id;
std::string inviter_name;
std::string swap_name;
};
class Client : public Mob
{
public:
@ -1565,32 +1572,24 @@ public:
Client* client, const std::string& client_name, uint16_t chat_type,
uint32_t string_id, const std::initializer_list<std::string>& arguments = {});
void AddExpeditionLockout(const ExpeditionLockoutTimer& lockout, bool update_db = false);
void AddExpeditionLockoutDuration(const std::string& expedition_name,
const std::string& event_Name, int seconds, const std::string& uuid = {}, bool update_db = false);
void AddNewExpeditionLockout(const std::string& expedition_name,
const std::string& event_name, uint32_t duration, std::string uuid = {});
Expedition* CreateExpedition(DynamicZone& dz, bool disable_messages = false);
Expedition* CreateExpedition(const std::string& zone_name,
uint32 version, uint32 duration, const std::string& expedition_name,
uint32 min_players, uint32 max_players, bool disable_messages = false);
Expedition* CreateExpeditionFromTemplate(uint32_t dz_template_id);
Expedition* GetExpedition() const;
uint32 GetExpeditionID() const { return m_expedition_id; }
const ExpeditionLockoutTimer* GetExpeditionLockout(
const std::string& expedition_name, const std::string& event_name, bool include_expired = false) const;
const std::vector<ExpeditionLockoutTimer>& GetExpeditionLockouts() const { return m_expedition_lockouts; };
std::vector<ExpeditionLockoutTimer> GetExpeditionLockouts(const std::string& expedition_name, bool include_expired = false);
uint32 GetPendingExpeditionInviteID() const { return m_pending_expedition_invite.expedition_id; }
bool HasExpeditionLockout(const std::string& expedition_name, const std::string& event_name, bool include_expired = false);
bool IsInExpedition() const { return m_expedition_id != 0; }
void RemoveAllExpeditionLockouts(const std::string& expedition_name, bool update_db = false);
void RemoveExpeditionLockout(const std::string& expedition_name,
const std::string& event_name, bool update_db = false);
void RequestPendingExpeditionInvite();
void SendExpeditionLockoutTimers();
void SetExpeditionID(uint32 expedition_id) { m_expedition_id = expedition_id; };
void SetPendingExpeditionInvite(ExpeditionInvite&& invite) { m_pending_expedition_invite = invite; }
void AddDzLockout(const DzLockout& lockout, bool update_db = false);
void AddDzLockout(const std::string& expedition, const std::string& event, uint32_t duration, std::string uuid = {});
void AddDzLockoutDuration(const DzLockout& lockout, int seconds, const std::string& uuid = {}, bool update_db = false);
DynamicZone* CreateExpedition(DynamicZone& dz, bool silent = false);
DynamicZone* CreateExpedition(uint32 zone_id, uint32 version, uint32 duration, const std::string& name, uint32 min_players, uint32 max_players, bool silent = false);
DynamicZone* CreateExpeditionFromTemplate(uint32_t dz_template_id);
DynamicZone* GetExpedition() const;
uint32 GetExpeditionID() const;
const DzLockout* GetDzLockout(const std::string& expedition, const std::string& event) const;
const std::vector<DzLockout>& GetDzLockouts() const { return m_dz_lockouts; };
std::vector<DzLockout> GetDzLockouts(const std::string& expedition);
uint32 GetPendingDzInviteID() const { return m_dz_invite.dz_id; }
void SetPendingDzInvite(const ExpeditionInvite& invite) { m_dz_invite = invite; }
void RequestPendingDzInvite() const;
bool HasDzLockout(const std::string& expedition, const std::string& event) const;
void RemoveDzLockouts(const std::string& expedition, bool update_db = false);
void RemoveDzLockout(const std::string& expedition, const std::string& event, bool update_db = false);
void SendDzLockoutTimers();
void DzListTimers();
void SetDzRemovalTimer(bool enable_timer);
void SendDzCompassUpdate();
@ -2285,9 +2284,8 @@ private:
uint8 client_max_level;
uint32 m_expedition_id = 0;
ExpeditionInvite m_pending_expedition_invite { 0 };
std::vector<ExpeditionLockoutTimer> m_expedition_lockouts;
ExpeditionInvite m_dz_invite = {};
std::vector<DzLockout> m_dz_lockouts;
glm::vec3 m_quest_compass;
bool m_has_quest_compass = false;
std::vector<uint32_t> m_dynamic_zone_ids;

View File

@ -43,8 +43,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/data_verification.h"
#include "../common/rdtsc.h"
#include "data_bucket.h"
#include "dynamic_zone.h"
#include "event_codes.h"
#include "expedition.h"
#include "guild_mgr.h"
#include "merc.h"
#include "petitions.h"
@ -1781,8 +1781,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
m_dynamic_zone_ids.emplace_back(entry.dynamic_zone_id);
}
m_expedition_id = ExpeditionsRepository::GetIDByMemberID(database, CharacterID());
auto dz = zone->GetDynamicZone();
if (dz && dz->GetSafeReturnLocation().zone_id != 0)
{
@ -6055,8 +6053,8 @@ void Client::Handle_OP_DzAddPlayer(const EQApplicationPacket *app)
}
else
{
// the only /dz command that sends an error message if no active expedition
Message(Chat::System, DZ_YOU_NOT_ASSIGNED);
// message string 8271 (not in emu clients) is the only /dz command that sends an error if no active expedition
Message(Chat::System, "You could not use this command because you are not currently assigned to a dynamic zone.");
}
}
@ -6089,14 +6087,14 @@ void Client::Handle_OP_DzChooseZoneReply(const EQApplicationPacket *app)
void Client::Handle_OP_DzExpeditionInviteResponse(const EQApplicationPacket *app)
{
auto expedition = Expedition::FindCachedExpeditionByID(m_pending_expedition_invite.expedition_id);
std::string swap_remove_name = m_pending_expedition_invite.swap_remove_name;
m_pending_expedition_invite = { 0 }; // clear before re-validating
auto expedition = DynamicZone::FindDynamicZoneByID(m_dz_invite.dz_id);
std::string swap_name = m_dz_invite.swap_name;
m_dz_invite = {}; // clear before re-validating
if (expedition)
{
auto dzmsg = reinterpret_cast<ExpeditionInviteResponse_Struct*>(app->pBuffer);
expedition->DzInviteResponse(this, dzmsg->accepted, swap_remove_name);
expedition->DzInviteResponse(this, dzmsg->accepted, swap_name);
}
}

View File

@ -39,8 +39,8 @@
#include "../common/skills.h"
#include "../common/spdat.h"
#include "../common/strings.h"
#include "dynamic_zone.h"
#include "event_codes.h"
#include "expedition.h"
#include "guild_mgr.h"
#include "map.h"
#include "petitions.h"

View File

@ -22,7 +22,6 @@
#include "data_bucket.h"
#include "command.h"
#include "dynamic_zone.h"
#include "expedition.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "titles.h"

View File

@ -862,13 +862,6 @@ struct DamageHitInfo {
EQ::skills::SkillType skill;
};
struct ExpeditionInvite
{
uint32_t expedition_id;
std::string inviter_name;
std::string swap_remove_name;
};
struct DataBucketCache
{
uint64_t bucket_id;

View File

@ -16,8 +16,8 @@
#include "../common/say_link.h"
#include "corpse.h"
#include "dynamic_zone.h"
#include "entity.h"
#include "expedition.h"
#include "groups.h"
#include "mob.h"
#include "raids.h"

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,15 @@ class Client;
class Database;
class EQApplicationPacket;
class ServerPacket;
struct ExpeditionInvite;
struct DzLootEvent
{
enum class Type { NpcType = 0, Entity };
uint32_t id = 0;
std::string event;
Type type = Type::NpcType;
};
class DynamicZone : public DynamicZoneBase
{
@ -40,53 +49,92 @@ public:
DynamicZone() = default;
DynamicZone(uint32_t zone_id, uint32_t version, uint32_t duration, DynamicZoneType type);
static constexpr int32_t EventTimerID = 1;
static constexpr int32_t ReplayTimerID = -1;
static void CacheAllFromDatabase();
static void CacheNewDynamicZone(ServerPacket* pack);
static DynamicZone* CreateNew(DynamicZone& dz_details, const std::vector<DynamicZoneMember>& members);
static DynamicZone* FindDynamicZoneByID(uint32_t dz_id);
static DynamicZone* TryCreate(Client& client, DynamicZone& dzinfo, bool silent = false);
static DynamicZone* FindDynamicZoneByID(uint32_t dz_id, DynamicZoneType type = DynamicZoneType::None);
static DynamicZone* FindExpeditionByCharacter(uint32_t char_id);
static DynamicZone* FindExpeditionByZone(uint32_t zone_id, uint32_t instance_id);
static void HandleWorldMessage(ServerPacket* pack);
static void AddClientsLockout(const DzLockout& lockout);
static void AddCharacterLockout(uint32_t char_id, const std::string& expedition, const std::string& event, uint32_t seconds, const std::string& uuid = {});
static void AddCharacterLockout(const std::string& char_name, const std::string& expedition, const std::string& event, uint32_t seconds, const std::string& uuid = {});
static bool HasCharacterLockout(uint32_t char_id, const std::string& expedition, const std::string& event);
static bool HasCharacterLockout(const std::string& char_name, const std::string& expedition, const std::string& event);
static void RemoveCharacterLockouts(uint32_t char_id, const std::string& expedition = {}, const std::string& event = {});
static void RemoveCharacterLockouts(const std::string& char_name, const std::string& expedition = {}, const std::string& event = {});
static std::vector<DzLockout> GetCharacterLockouts(uint32_t char_id);
void DzAddPlayer(Client* client, const std::string& add_name, const std::string& swap_name = {});
void DzAddPlayerContinue(std::string inviter, std::string add_name, std::string swap_name = {});
void DzInviteResponse(Client* client, bool accepted, const std::string& swap_name);
void DzMakeLeader(Client* client, std::string leader_name);
void DzPlayerList(Client* client);
void DzRemovePlayer(Client* client, std::string name);
void DzSwapPlayer(Client* client, std::string rem_name, std::string add_name);
void DzQuit(Client* client);
void DzKickPlayers(Client* client);
void SendWorldMakeLeaderRequest(uint32_t char_id, const std::string& leader_name);
void SendWorldPendingInvite(const ExpeditionInvite& invite, const std::string& add_name);
void SetSecondsRemaining(uint32_t seconds_remaining) override;
void DoAsyncZoneMemberUpdates();
bool CanClientLootCorpse(Client* client, uint32_t npc_type_id, uint32_t entity_id);
bool IsCurrentZoneDzInstance() const;
bool IsCurrentZoneDz() const;
void MovePCInto(Client* client, bool world_verify = false) const;
void RegisterOnClientAddRemove(std::function<void(Client* client, bool removed, bool silent)> on_client_addremove);
void SendClientWindowUpdate(Client* client);
void SendLeaderNameToZoneMembers();
void SendMemberListToZoneMembers();
void SendMemberListNameToZoneMembers(const std::string& char_name, bool remove);
void SendMemberListStatusToZoneMembers(const DynamicZoneMember& member);
void SendRemoveAllMembersToZoneMembers(bool silent) { ProcessRemoveAllMembers(silent); }
void SendMemberNameToZoneMembers(const std::string& char_name, bool remove);
void SendMemberStatusToZoneMembers(const DynamicZoneMember& member);
void SetLocked(bool lock, bool update_db = false, DzLockMsg lock_msg = DzLockMsg::None, uint32_t color = Chat::Yellow);
void UpdateMembers();
std::unique_ptr<EQApplicationPacket> CreateExpireWarningPacket(uint32_t minutes_remaining);
std::unique_ptr<EQApplicationPacket> CreateInfoPacket(bool clear = false);
std::unique_ptr<EQApplicationPacket> CreateLeaderNamePacket();
std::unique_ptr<EQApplicationPacket> CreateMemberListPacket(bool clear = false);
std::unique_ptr<EQApplicationPacket> CreateMemberListNamePacket(const std::string& name, bool remove_name);
std::unique_ptr<EQApplicationPacket> CreateMemberListStatusPacket(const std::string& name, DynamicZoneMemberStatus status);
protected:
uint16_t GetCurrentInstanceID() override;
uint16_t GetCurrentZoneID() override;
Database& GetDatabase() override;
void ProcessCompassChange(const DynamicZoneLocation& location) override;
void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed) override;
bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status) override;
void ProcessRemoveAllMembers(bool silent = false) override;
void ProcessSetSwitchID(int dz_switch_id) override;
bool SendServerPacket(ServerPacket* packet) override;
std::string GetLootEvent(uint32_t id, DzLootEvent::Type type) const;
void SetLootEvent(uint32_t id, const std::string& event, DzLootEvent::Type type);
private:
static void StartAllClientRemovalTimers();
uint16_t GetCurrentInstanceID() const override;
uint16_t GetCurrentZoneID() const override;
Database& GetDatabase() override;
void HandleLockoutDuration(const DzLockout& lockout, int seconds, bool members_only, bool insert_db) override;
void HandleLockoutUpdate(const DzLockout& lockout, bool remove, bool members_only) override;
void ProcessCompassChange(const DynamicZoneLocation& location) override;
void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed) override;
bool ProcessMemberStatusChange(uint32_t character_id, DynamicZoneMemberStatus status) override;
void ProcessRemoveAllMembers() override;
void ProcessSetSwitchID(int dz_switch_id) override;
bool SendServerPacket(ServerPacket* packet) override;
bool ConfirmLeaderCommand(Client* client);
bool ProcessAddConflicts(Client* leader, Client* client, bool swapping);
void ProcessLeaderChanged(uint32_t new_leader_id);
void SaveLockouts(const std::vector<DzLockout>& lockouts);
void SendClientInvite(Client* client, const std::string& inviter, const std::string& swap_name);
void SendCompassUpdateToZoneMembers();
void SendLeaderMessage(Client* leader, uint16_t type, const std::string& msg);
void SendLeaderMessage(Client* leader, uint16_t type, uint32_t str_id, std::initializer_list<std::string> args = {});
void SendMembersExpireWarning(uint32_t minutes);
void SendUpdatesToZoneMembers(bool removing_all = false, bool silent = true);
void SendWorldPlayerInvite(const std::string& inviter, const std::string& swap_name, const std::string& add_name, bool pending = false);
void SetUpdatedDuration(uint32_t seconds);
void TryAddClient(Client* add_client, const std::string& inviter, const std::string& swap_name, Client* leader = nullptr);
std::function<void(Client*, bool, bool)> m_on_client_addremove;
std::unique_ptr<EQApplicationPacket> CreateExpireWarningPacket(uint32_t minutes_remaining);
std::unique_ptr<EQApplicationPacket> CreateInfoPacket(bool clear = false);
std::unique_ptr<EQApplicationPacket> CreateInvitePacket(const std::string& inviter, const std::string& swap_name);
std::unique_ptr<EQApplicationPacket> CreateLeaderNamePacket();
std::unique_ptr<EQApplicationPacket> CreateMemberListPacket(bool clear = false);
std::unique_ptr<EQApplicationPacket> CreateMemberNamePacket(const std::string& name, bool remove);
std::unique_ptr<EQApplicationPacket> CreateMemberStatusPacket(const std::string& name, DynamicZoneMemberStatus status);
std::vector<DzLootEvent> m_loot_events; // only valid inside dz zone
};
#endif

View File

@ -27,9 +27,9 @@
#include "../common/misc_functions.h"
#include "dialogue_window.h"
#include "dynamic_zone.h"
#include "embperl.h"
#include "entity.h"
#include "expedition.h"
#include "queryserv.h"
#include "questmgr.h"
#include "zone.h"
@ -2779,45 +2779,45 @@ void Perl__SetContentFlag(std::string flag_name, bool enabled)
zone->ReloadContentFlags();
}
Expedition* Perl__get_expedition()
DynamicZone* Perl__get_expedition()
{
if (zone && zone->GetInstanceID() != 0)
{
return Expedition::FindCachedExpeditionByZoneInstance(zone->GetZoneID(), zone->GetInstanceID());
return DynamicZone::FindExpeditionByZone(zone->GetZoneID(), zone->GetInstanceID());
}
return nullptr;
}
Expedition* Perl__get_expedition_by_char_id(uint32 char_id)
DynamicZone* Perl__get_expedition_by_char_id(uint32 char_id)
{
return Expedition::FindCachedExpeditionByCharacterID(char_id);
return DynamicZone::FindExpeditionByCharacter(char_id);
}
Expedition* Perl__get_expedition_by_dz_id(uint32 dz_id)
DynamicZone* Perl__get_expedition_by_dz_id(uint32 dz_id)
{
return Expedition::FindCachedExpeditionByDynamicZoneID(dz_id);
return DynamicZone::FindDynamicZoneByID(dz_id, DynamicZoneType::Expedition);
}
Expedition* Perl__get_expedition_by_zone_instance(uint32 zone_id, uint32 instance_id)
DynamicZone* Perl__get_expedition_by_zone_instance(uint32 zone_id, uint32 instance_id)
{
return Expedition::FindCachedExpeditionByZoneInstance(zone_id, instance_id);
return DynamicZone::FindExpeditionByZone(zone_id, instance_id);
}
perl::reference Perl__get_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name)
{
perl::hash table;
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id);
auto lockouts = DynamicZone::GetCharacterLockouts(char_id);
auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const ExpeditionLockoutTimer& lockout) {
return lockout.IsSameLockout(expedition_name, event_name);
auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const DzLockout& lockout) {
return lockout.IsSame(expedition_name, event_name);
});
if (it != lockouts.end())
{
table["remaining"] = it->GetSecondsRemaining();
table["uuid"] = it->GetExpeditionUUID();
table["uuid"] = it->UUID();
}
return perl::reference(table);
@ -2827,23 +2827,23 @@ perl::reference Perl__get_expedition_lockouts_by_char_id(uint32 char_id)
{
perl::hash table;
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id);
auto lockouts = DynamicZone::GetCharacterLockouts(char_id);
for (const auto& lockout : lockouts)
{
if (!table.exists(lockout.GetExpeditionName()))
if (!table.exists(lockout.DzName()))
{
table[lockout.GetExpeditionName()] = perl::reference(perl::hash());
table[lockout.DzName()] = perl::reference(perl::hash());
}
perl::hash expedition_table = table[lockout.GetExpeditionName()];
if (!expedition_table.exists(lockout.GetEventName()))
perl::hash expedition_table = table[lockout.DzName()];
if (!expedition_table.exists(lockout.Event()))
{
expedition_table[lockout.GetEventName()] = perl::reference(perl::hash());
expedition_table[lockout.Event()] = perl::reference(perl::hash());
}
perl::hash event_table = expedition_table[lockout.GetEventName()];
perl::hash event_table = expedition_table[lockout.Event()];
event_table["remaining"] = lockout.GetSecondsRemaining();
event_table["uuid"] = lockout.GetExpeditionUUID();
event_table["uuid"] = lockout.UUID();
}
return perl::reference(table);
@ -2853,18 +2853,18 @@ perl::reference Perl__get_expedition_lockouts_by_char_id(uint32 char_id, std::st
{
perl::hash table;
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id);
auto lockouts = DynamicZone::GetCharacterLockouts(char_id);
for (const auto& lockout : lockouts)
{
if (lockout.GetExpeditionName() == expedition_name)
if (lockout.DzName() == expedition_name)
{
if (!table.exists(lockout.GetEventName()))
if (!table.exists(lockout.Event()))
{
table[lockout.GetEventName()] = perl::reference(perl::hash());
table[lockout.Event()] = perl::reference(perl::hash());
}
perl::hash event_table = table[lockout.GetEventName()];
perl::hash event_table = table[lockout.Event()];
event_table["remaining"] = lockout.GetSecondsRemaining();
event_table["uuid"] = lockout.GetExpeditionUUID();
event_table["uuid"] = lockout.UUID();
}
}
@ -2873,39 +2873,39 @@ perl::reference Perl__get_expedition_lockouts_by_char_id(uint32 char_id, std::st
void Perl__add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds)
{
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds);
Expedition::AddLockoutClients(lockout);
auto lockout = DzLockout::Create(expedition_name, event_name, seconds);
DynamicZone::AddClientsLockout(lockout);
}
void Perl__add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid)
{
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds, uuid);
Expedition::AddLockoutClients(lockout);
auto lockout = DzLockout::Create(expedition_name, event_name, seconds, uuid);
DynamicZone::AddClientsLockout(lockout);
}
void Perl__add_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name, uint32 seconds)
{
Expedition::AddLockoutByCharacterID(char_id, expedition_name, event_name, seconds);
DynamicZone::AddCharacterLockout(char_id, expedition_name, event_name, seconds);
}
void Perl__add_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid)
{
Expedition::AddLockoutByCharacterID(char_id, expedition_name, event_name, seconds, uuid);
DynamicZone::AddCharacterLockout(char_id, expedition_name, event_name, seconds, uuid);
}
void Perl__remove_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name)
{
Expedition::RemoveLockoutsByCharacterID(char_id, expedition_name, event_name);
DynamicZone::RemoveCharacterLockouts(char_id, expedition_name, event_name);
}
void Perl__remove_all_expedition_lockouts_by_char_id(uint32 char_id)
{
Expedition::RemoveLockoutsByCharacterID(char_id);
DynamicZone::RemoveCharacterLockouts(char_id);
}
void Perl__remove_all_expedition_lockouts_by_char_id(uint32 char_id, std::string expedition_name)
{
Expedition::RemoveLockoutsByCharacterID(char_id, expedition_name);
DynamicZone::RemoveCharacterLockouts(char_id, expedition_name);
}
EQ::ItemInstance* Perl__createitem(uint32 item_id)

View File

@ -5506,7 +5506,7 @@ void EntityList::ExpeditionWarning(uint32 minutes_left)
auto it = client_list.begin();
while (it != client_list.end()) {
it->second->MessageString(Chat::Yellow, EXPEDITION_MIN_REMAIN, itoa((int)minutes_left));
it->second->MessageString(Chat::Yellow, DZ_MINUTES_REMAIN, itoa((int)minutes_left));
it->second->QueuePacket(outapp);
++it;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,169 +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 EXPEDITION_H
#define EXPEDITION_H
#include "dynamic_zone.h"
#include "../common/expedition_lockout_timer.h"
#include "../common/repositories/expeditions_repository.h"
#include <cstdint>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <cassert>
class Client;
class EQApplicationPacket;
struct ExpeditionInvite;
class ExpeditionRequest;
class ServerPacket;
extern const char* const DZ_YOU_NOT_ASSIGNED;
enum class ExpeditionLockMessage : uint8_t
{
None = 0,
Close,
Begin
};
class Expedition
{
public:
Expedition() = delete;
Expedition(DynamicZone* dz);
Expedition(DynamicZone* dz, uint32_t id, uint32_t dz_id);
static Expedition* TryCreate(Client* requester, DynamicZone& dynamiczone, bool disable_messages);
static void CacheFromDatabase(uint32_t expedition_id);
static bool CacheAllFromDatabase();
static Expedition* FindCachedExpeditionByCharacterID(uint32_t character_id);
static Expedition* FindCachedExpeditionByCharacterName(const std::string& char_name);
static Expedition* FindCachedExpeditionByDynamicZoneID(uint32_t dz_id);
static Expedition* FindCachedExpeditionByID(uint32_t expedition_id);
static Expedition* FindCachedExpeditionByZoneInstance(uint32_t zone_id, uint32_t instance_id);
static std::vector<ExpeditionLockoutTimer> GetExpeditionLockoutsByCharacterID(uint32_t character_id);
static void HandleWorldMessage(ServerPacket* pack);
static void AddLockoutByCharacterID(uint32_t character_id, const std::string& expedition_name,
const std::string& event_name, uint32_t seconds, const std::string& uuid = {});
static void AddLockoutByCharacterName(const std::string& character_name, const std::string& expedition_name,
const std::string& event_name, uint32_t seconds, const std::string& uuid = {});
static bool HasLockoutByCharacterID(uint32_t character_id,
const std::string& expedition_name, const std::string& event_name);
static bool HasLockoutByCharacterName(const std::string& character_name,
const std::string& expedition_name, const std::string& event_name);
static void RemoveLockoutsByCharacterID(uint32_t character_id,
const std::string& expedition_name = {}, const std::string& event_name = {});
static void RemoveLockoutsByCharacterName(const std::string& character_name,
const std::string& expedition_name = {}, const std::string& event_name = {});
static void AddLockoutClients(const ExpeditionLockoutTimer& lockout, uint32_t exclude_id = 0);
uint32_t GetID() const { return m_id; }
uint32_t GetDynamicZoneID() const { return m_dynamic_zone_id; }
DynamicZone* GetDynamicZone() const { return m_dynamic_zone; }
const DynamicZoneMember& GetLeader() { return GetDynamicZone()->GetLeader(); }
uint32_t GetLeaderID() { return GetDynamicZone()->GetLeaderID(); }
const std::string& GetLeaderName() { return GetDynamicZone()->GetLeaderName(); }
const std::unordered_map<std::string, ExpeditionLockoutTimer>& GetLockouts() const { return m_lockouts; }
const std::string& GetName() { return GetDynamicZone()->GetName(); }
void RegisterDynamicZoneCallbacks();
bool IsLocked() const { return m_is_locked; }
void SetLocked(bool lock_expedition, ExpeditionLockMessage lock_msg,
bool update_db = false, uint32_t msg_color = Chat::Yellow);
void AddLockout(const std::string& event_name, uint32_t seconds);
void AddLockoutDuration(const std::string& event_name, int seconds, bool members_only = true);
void AddReplayLockout(uint32_t seconds);
void AddReplayLockoutDuration(int seconds, bool members_only = true);
bool HasLockout(const std::string& event_name);
bool HasReplayLockout();
void RemoveLockout(const std::string& event_name);
void SetReplayLockoutOnMemberJoin(bool add_on_join, bool update_db = false);
void SyncCharacterLockouts(uint32_t character_id, std::vector<ExpeditionLockoutTimer>& client_lockouts);
void UpdateLockoutDuration(const std::string& event_name, uint32_t seconds, bool members_only = true);
bool CanClientLootCorpse(Client* client, uint32_t npc_type_id, uint32_t spawn_id);
std::string GetLootEventByNPCTypeID(uint32_t npc_id);
std::string GetLootEventBySpawnID(uint32_t spawn_id);
void SetLootEventByNPCTypeID(uint32_t npc_type_id, const std::string& event_name);
void SetLootEventBySpawnID(uint32_t spawn_id, const std::string& event_name);
void SendWorldMakeLeaderRequest(uint32_t requester_id, const std::string& new_leader_name);
void SendWorldPendingInvite(const ExpeditionInvite& invite, const std::string& add_name);
void DzAddPlayer(Client* requester, const std::string& add_char_name, const std::string& swap_remove_name = {});
void DzAddPlayerContinue(std::string leader_name, std::string add_char_name, std::string swap_remove_name = {});
void DzInviteResponse(Client* add_client, bool accepted, const std::string& swap_remove_name);
void DzMakeLeader(Client* requester, std::string new_leader_name);
void DzPlayerList(Client* requester);
void DzRemovePlayer(Client* requester, std::string remove_char_name);
void DzSwapPlayer(Client* requester, std::string remove_char_name, std::string add_char_name);
void DzQuit(Client* requester);
void DzKickPlayers(Client* requester);
static const int32_t REPLAY_TIMER_ID;
static const int32_t EVENT_TIMER_ID;
private:
static void CacheExpeditions(std::vector<ExpeditionsRepository::Expeditions>&& expeditions);
static void SendWorldCharacterLockout(uint32_t character_id, const ExpeditionLockoutTimer& lockout, bool remove);
void AddLockout(const ExpeditionLockoutTimer& lockout, bool members_only = false);
void AddLockoutDurationClients(const ExpeditionLockoutTimer& lockout, int seconds, uint32_t exclude_id = 0);
bool ConfirmLeaderCommand(Client* requester);
void OnClientAddRemove(Client* client, bool removed, bool silent);
void LoadRepositoryResult(const ExpeditionsRepository::Expeditions& entry);
bool ProcessAddConflicts(Client* leader_client, Client* add_client, bool swapping);
void ProcessLockoutDuration(const ExpeditionLockoutTimer& lockout, int seconds, bool members_only = false);
void ProcessLockoutUpdate(const ExpeditionLockoutTimer& lockout, bool remove, bool members_only = false);
void SaveLockouts(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,
const std::initializer_list<std::string>& args = {});
void SendWorldExpeditionUpdate(uint16_t server_opcode);
void SendWorldAddPlayerInvite(const std::string& inviter_name, const std::string& swap_remove_name,
const std::string& add_name, bool pending = false);
void SendWorldLockoutDuration(
const ExpeditionLockoutTimer& lockout, int seconds, bool members_only = false);
void SendWorldLockoutUpdate(
const ExpeditionLockoutTimer& lockout, bool remove, bool members_only = false);
void SendWorldSettingChanged(uint16_t server_opcode, bool setting_value);
void SetDynamicZone(DynamicZone&& dz);
void TryAddClient(Client* add_client, const std::string& inviter_name,
const std::string& swap_remove_name, Client* leader_client = nullptr);
std::unique_ptr<EQApplicationPacket> CreateInvitePacket(const std::string& inviter_name, const std::string& swap_remove_name);
uint32_t m_id = 0;
uint32_t m_dynamic_zone_id = 0;
bool m_is_locked = false;
bool m_add_replay_on_join = true;
DynamicZone* m_dynamic_zone = nullptr; // should never be null, will exist for lifetime of expedition
std::unordered_map<std::string, ExpeditionLockoutTimer> m_lockouts;
std::unordered_map<uint32_t, std::string> m_npc_loot_events; // only valid inside dz zone
std::unordered_map<uint32_t, std::string> m_spawn_loot_events; // only valid inside dz zone
};
#endif

View File

@ -1,409 +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
*
*/
#include "expedition_database.h"
#include "expedition.h"
#include "zonedb.h"
#include <fmt/core.h>
uint32_t ExpeditionDatabase::InsertExpedition(uint32_t dz_id)
{
LogExpeditionsDetail("Inserting new expedition dz [{}]", dz_id);
std::string query = fmt::format(SQL(
INSERT INTO expeditions
(dynamic_zone_id)
VALUES
({});
), dz_id);
auto results = database.QueryDatabase(query);
if (!results.Success())
{
LogExpeditions("Failed to obtain an expedition id for dz [{}]", dz_id);
return 0;
}
return results.LastInsertedID();
}
std::vector<ExpeditionLockoutTimer> ExpeditionDatabase::LoadCharacterLockouts(uint32_t character_id)
{
LogExpeditionsDetail("Loading character [{}] lockouts", character_id);
std::vector<ExpeditionLockoutTimer> lockouts;
auto query = fmt::format(SQL(
SELECT
from_expedition_uuid,
expedition_name,
event_name,
UNIX_TIMESTAMP(expire_time),
duration
FROM character_expedition_lockouts
WHERE character_id = {} AND expire_time > NOW();
), character_id);
auto results = database.QueryDatabase(query);
if (results.Success())
{
for (auto row = results.begin(); row != results.end(); ++row)
{
lockouts.emplace_back(
row[0], // expedition_uuid
row[1], // expedition_name
row[2], // event_name
strtoull(row[3], nullptr, 10), // expire_time
static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) // duration
);
}
}
return lockouts;
}
std::vector<ExpeditionLockoutTimer> ExpeditionDatabase::LoadCharacterLockouts(
uint32_t character_id, const std::string& expedition_name)
{
LogExpeditionsDetail("Loading character [{}] lockouts for [{}]", character_id, expedition_name);
std::vector<ExpeditionLockoutTimer> lockouts;
auto query = fmt::format(SQL(
SELECT
from_expedition_uuid,
event_name,
UNIX_TIMESTAMP(expire_time),
duration
FROM character_expedition_lockouts
WHERE
character_id = {}
AND expire_time > NOW()
AND expedition_name = '{}';
), character_id, Strings::Escape(expedition_name));
auto results = database.QueryDatabase(query);
if (results.Success())
{
for (auto row = results.begin(); row != results.end(); ++row)
{
lockouts.emplace_back(
row[0], // expedition_uuid
expedition_name,
row[1], // event_name
strtoull(row[2], nullptr, 10), // expire_time
static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) // duration
);
}
}
return lockouts;
}
void ExpeditionDatabase::DeleteAllCharacterLockouts(uint32_t character_id)
{
LogExpeditionsDetail("Deleting all character [{}] lockouts", character_id);
if (character_id != 0)
{
std::string query = fmt::format(SQL(
DELETE FROM character_expedition_lockouts
WHERE character_id = {};
), character_id);
database.QueryDatabase(query);
}
}
void ExpeditionDatabase::DeleteAllCharacterLockouts(
uint32_t character_id, const std::string& expedition_name)
{
LogExpeditionsDetail("Deleting all character [{}] lockouts for [{}]", character_id, expedition_name);
if (character_id != 0 && !expedition_name.empty())
{
std::string query = fmt::format(SQL(
DELETE FROM character_expedition_lockouts
WHERE character_id = {} AND expedition_name = '{}';
), character_id, Strings::Escape(expedition_name));
database.QueryDatabase(query);
}
}
void ExpeditionDatabase::DeleteCharacterLockout(
uint32_t character_id, const std::string& expedition_name, const std::string& event_name)
{
LogExpeditionsDetail(
"Deleting character [{}] lockout: [{}]:[{}]", character_id, expedition_name, event_name
);
auto query = fmt::format(SQL(
DELETE FROM character_expedition_lockouts
WHERE
character_id = {}
AND expedition_name = '{}'
AND event_name = '{}';
), character_id, Strings::Escape(expedition_name), Strings::Escape(event_name));
database.QueryDatabase(query);
}
void ExpeditionDatabase::DeleteMembersLockout(
const std::vector<DynamicZoneMember>& members,
const std::string& expedition_name, const std::string& event_name)
{
LogExpeditionsDetail("Deleting members lockout: [{}]:[{}]", expedition_name, event_name);
std::string query_character_ids;
for (const auto& member : members)
{
fmt::format_to(std::back_inserter(query_character_ids), "{},", member.id);
}
if (!query_character_ids.empty())
{
query_character_ids.pop_back(); // trailing comma
auto query = fmt::format(SQL(
DELETE FROM character_expedition_lockouts
WHERE character_id
IN ({})
AND expedition_name = '{}'
AND event_name = '{}';
), query_character_ids, Strings::Escape(expedition_name), Strings::Escape(event_name));
database.QueryDatabase(query);
}
}
void ExpeditionDatabase::DeleteLockout(uint32_t expedition_id, const std::string& event_name)
{
LogExpeditionsDetail("Deleting expedition [{}] lockout event [{}]", expedition_id, event_name);
auto query = fmt::format(SQL(
DELETE FROM expedition_lockouts
WHERE expedition_id = {} AND event_name = '{}';
), expedition_id, Strings::Escape(event_name));
database.QueryDatabase(query);
}
void ExpeditionDatabase::InsertCharacterLockouts(uint32_t character_id,
const std::vector<ExpeditionLockoutTimer>& lockouts)
{
LogExpeditionsDetail("Inserting [{}] lockouts for character [{}]", lockouts.size(), character_id);
std::string insert_values;
for (const auto& lockout : lockouts)
{
fmt::format_to(std::back_inserter(insert_values),
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
character_id,
lockout.GetExpireTime(),
lockout.GetDuration(),
lockout.GetExpeditionUUID(),
Strings::Escape(lockout.GetExpeditionName()),
Strings::Escape(lockout.GetEventName())
);
}
if (!insert_values.empty())
{
insert_values.pop_back(); // trailing comma
auto query = fmt::format(SQL(
INSERT INTO character_expedition_lockouts
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
VALUES {}
ON DUPLICATE KEY UPDATE
from_expedition_uuid = VALUES(from_expedition_uuid),
expire_time = VALUES(expire_time),
duration = VALUES(duration);
), insert_values);
database.QueryDatabase(query);
}
}
void ExpeditionDatabase::InsertMembersLockout(
const std::vector<DynamicZoneMember>& members, const ExpeditionLockoutTimer& lockout)
{
LogExpeditionsDetail(
"Inserting members lockout [{}]:[{}] with expire time [{}]",
lockout.GetExpeditionName(), lockout.GetEventName(), lockout.GetExpireTime()
);
std::string insert_values;
for (const auto& member : members)
{
fmt::format_to(std::back_inserter(insert_values),
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
member.id,
lockout.GetExpireTime(),
lockout.GetDuration(),
lockout.GetExpeditionUUID(),
Strings::Escape(lockout.GetExpeditionName()),
Strings::Escape(lockout.GetEventName())
);
}
if (!insert_values.empty())
{
insert_values.pop_back(); // trailing comma
auto query = fmt::format(SQL(
INSERT INTO character_expedition_lockouts
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
VALUES {}
ON DUPLICATE KEY UPDATE
from_expedition_uuid = VALUES(from_expedition_uuid),
expire_time = VALUES(expire_time),
duration = VALUES(duration);
), insert_values);
database.QueryDatabase(query);
}
}
void ExpeditionDatabase::InsertLockout(
uint32_t expedition_id, const ExpeditionLockoutTimer& lockout)
{
LogExpeditionsDetail(
"Inserting expedition [{}] lockout: [{}]:[{}] expire time: [{}]",
expedition_id, lockout.GetExpeditionName(), lockout.GetEventName(), lockout.GetExpireTime()
);
auto query = fmt::format(SQL(
INSERT INTO expedition_lockouts
(expedition_id, from_expedition_uuid, event_name, expire_time, duration)
VALUES
({}, '{}', '{}', FROM_UNIXTIME({}), {})
ON DUPLICATE KEY UPDATE
from_expedition_uuid = VALUES(from_expedition_uuid),
expire_time = VALUES(expire_time),
duration = VALUES(duration);
),
expedition_id,
lockout.GetExpeditionUUID(),
Strings::Escape(lockout.GetEventName()),
lockout.GetExpireTime(),
lockout.GetDuration()
);
database.QueryDatabase(query);
}
void ExpeditionDatabase::InsertLockouts(
uint32_t expedition_id, const std::unordered_map<std::string, ExpeditionLockoutTimer>& lockouts)
{
LogExpeditionsDetail("Inserting expedition [{}] lockouts", expedition_id);
std::string insert_values;
for (const auto& lockout : lockouts)
{
fmt::format_to(std::back_inserter(insert_values),
"({}, '{}', '{}', FROM_UNIXTIME({}), {}),",
expedition_id,
lockout.second.GetExpeditionUUID(),
Strings::Escape(lockout.second.GetEventName()),
lockout.second.GetExpireTime(),
lockout.second.GetDuration()
);
}
if (!insert_values.empty())
{
insert_values.pop_back(); // trailing comma
auto query = fmt::format(SQL(
INSERT INTO expedition_lockouts
(expedition_id, from_expedition_uuid, event_name, expire_time, duration)
VALUES {}
ON DUPLICATE KEY UPDATE
from_expedition_uuid = VALUES(from_expedition_uuid),
expire_time = VALUES(expire_time),
duration = VALUES(duration);
), 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);
auto query = fmt::format(SQL(
UPDATE expeditions SET is_locked = {} WHERE id = {};
), is_locked, 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);
auto query = fmt::format(SQL(
UPDATE expeditions SET add_replay_on_join = {} WHERE id = {};
), add_on_join, expedition_id);
database.QueryDatabase(query);
}
void ExpeditionDatabase::AddLockoutDuration(const std::vector<DynamicZoneMember>& members,
const ExpeditionLockoutTimer& lockout, int seconds)
{
LogExpeditionsDetail(
"Adding duration [{}] seconds to members lockouts [{}]:[{}]",
seconds, lockout.GetExpeditionName(), lockout.GetEventName());
std::string insert_values;
for (const auto& member : members)
{
fmt::format_to(std::back_inserter(insert_values),
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
member.id,
lockout.GetExpireTime(),
lockout.GetDuration(),
lockout.GetExpeditionUUID(),
Strings::Escape(lockout.GetExpeditionName()),
Strings::Escape(lockout.GetEventName())
);
}
if (!insert_values.empty())
{
insert_values.pop_back(); // trailing comma
auto query = fmt::format(SQL(
INSERT INTO character_expedition_lockouts
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
VALUES {}
ON DUPLICATE KEY UPDATE
from_expedition_uuid = VALUES(from_expedition_uuid),
expire_time = DATE_ADD(expire_time, INTERVAL {} SECOND),
duration = GREATEST(0, CAST(duration AS SIGNED) + {});
), insert_values, seconds, seconds);
database.QueryDatabase(query);
}
}

View File

@ -1,62 +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 EXPEDITION_DATABASE_H
#define EXPEDITION_DATABASE_H
#include <cstdint>
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
class Expedition;
class ExpeditionLockoutTimer;
struct DynamicZoneMember;
class MySQLRequestResult;
namespace ExpeditionDatabase
{
uint32_t InsertExpedition(uint32_t dz_id);
std::vector<ExpeditionLockoutTimer> LoadCharacterLockouts(uint32_t character_id);
std::vector<ExpeditionLockoutTimer> LoadCharacterLockouts(uint32_t character_id,
const std::string& expedition_name);
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,
const std::string& event_name);
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);
void InsertCharacterLockouts(uint32_t character_id,
const std::vector<ExpeditionLockoutTimer>& lockouts);
void InsertMembersLockout(const std::vector<DynamicZoneMember>& members,
const ExpeditionLockoutTimer& lockout);
void InsertLockout(uint32_t expedition_id, const ExpeditionLockoutTimer& lockout);
void InsertLockouts(uint32_t expedition_id,
const std::unordered_map<std::string, ExpeditionLockoutTimer>& lockouts);
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,
const ExpeditionLockoutTimer& lockout, int seconds);
};
#endif

View File

@ -20,48 +20,30 @@
#include "expedition_request.h"
#include "client.h"
#include "expedition.h"
#include "groups.h"
#include "raids.h"
#include "string_ids.h"
#include "../common/repositories/character_expedition_lockouts_repository.h"
constexpr char SystemName[] = "expedition";
// message string 8312 added in September 08 2020 Test patch (used by both dz and shared tasks)
constexpr const char* CREATE_NOT_ALL_ADDED = "Not all players in your {} were added to the {}. The {} can take a maximum of {} players, and your {} has {}.";
// message string 9265 (not in emu clients)
constexpr const char* EXPEDITION_OTHER_BELONGS = "{} attempted to create an expedition but {} already belongs to one.";
ExpeditionRequest::ExpeditionRequest(const DynamicZone& dz, bool disable_messages) :
m_expedition_name(dz.GetName()),
m_min_players(dz.GetMinPlayers()),
m_max_players(dz.GetMaxPlayers()),
m_disable_messages(disable_messages)
ExpeditionRequest::ExpeditionRequest(const DynamicZone& dz, Client& client, bool silent)
: m_dz(&dz), m_requester(&client), m_silent(silent)
{
}
bool ExpeditionRequest::Validate(Client* requester)
bool ExpeditionRequest::Validate()
{
m_requester = requester;
if (!m_requester)
{
return false;
}
// a message is sent to leader for every member that fails a requirement
BenchTimer benchmark;
bool requirements_met = false;
Raid* raid = m_requester->GetRaid();
Group* group = m_requester->GetGroup();
if (raid)
if (Raid* raid = m_requester->GetRaid())
{
m_is_raid = true;
requirements_met = CanRaidRequest(raid);
}
else if (group)
else if (Group* group = m_requester->GetGroup())
{
requirements_met = CanGroupRequest(group);
}
@ -89,21 +71,15 @@ bool ExpeditionRequest::CanRaidRequest(Raid* raid)
// expedition max. members are added up to the max ordered by group number.
auto raid_members = raid->GetMembers();
if (raid_members.size() > m_max_players)
if (raid_members.size() > m_dz->GetMaxPlayers())
{
// stable_sort not needed, order within a raid group may not be what is displayed
// leader first then raid group, order within a raid group may not be what is displayed
std::sort(raid_members.begin(), raid_members.end(),
[&](const RaidMember& lhs, const RaidMember& rhs) {
if (m_leader_name == lhs.member_name) { // leader always added first
return true;
} else if (m_leader_name == rhs.member_name) {
return false;
}
if (m_leader_name == lhs.member_name) { return true; }
if (m_leader_name == rhs.member_name) { return false; }
return lhs.group_number < rhs.group_number;
});
m_not_all_added_msg = fmt::format(CREATE_NOT_ALL_ADDED, "raid", SystemName,
SystemName, m_max_players, "raid", raid_members.size());
}
// live still performs conflict checks for all members even those beyond max
@ -139,12 +115,6 @@ bool ExpeditionRequest::CanGroupRequest(Group* group)
}
}
if (member_names.size() > m_max_players)
{
m_not_all_added_msg = fmt::format(CREATE_NOT_ALL_ADDED, "group", SystemName,
SystemName, m_max_players, "group", member_names.size());
}
return CanMembersJoin(member_names);
}
@ -172,7 +142,7 @@ bool ExpeditionRequest::CanMembersJoin(const std::vector<std::string>& member_na
return requirements_met;
}
bool ExpeditionRequest::SaveLeaderLockouts(const std::vector<ExpeditionLockoutTimer>& lockouts)
bool ExpeditionRequest::SaveLeaderLockouts(const std::vector<DzLockout>& lockouts)
{
bool has_replay_lockout = false;
@ -180,9 +150,10 @@ bool ExpeditionRequest::SaveLeaderLockouts(const std::vector<ExpeditionLockoutTi
{
if (!lockout.IsExpired())
{
m_lockouts[lockout.GetEventName()] = lockout;
// db prevents duplicate event names
m_lockouts.push_back(lockout);
if (lockout.IsReplayTimer())
if (lockout.IsReplay())
{
has_replay_lockout = true;
}
@ -195,7 +166,7 @@ bool ExpeditionRequest::SaveLeaderLockouts(const std::vector<ExpeditionLockoutTi
bool ExpeditionRequest::CheckMembersForConflicts(const std::vector<std::string>& member_names)
{
// order of member_names is preserved by queries for use with max member truncation
auto entries = ExpeditionsRepository::GetCharactersWithExpedition(database, member_names);
auto entries = DynamicZonesRepository::GetCharactersWithDz(database, member_names, static_cast<int>(DynamicZoneType::Expedition));
if (entries.empty())
{
LogExpeditions("Failed to load members for expedition request");
@ -205,10 +176,10 @@ bool ExpeditionRequest::CheckMembersForConflicts(const std::vector<std::string>&
bool is_solo = (member_names.size() == 1);
bool has_conflicts = false;
std::vector<uint32_t> character_ids;
std::vector<uint32_t> char_ids;
for (const auto& character : entries)
{
if (is_solo && character.expedition_id != 0)
if (is_solo && character.dz_id != 0)
{
// live doesn't bother checking replay lockout here
SendLeaderMemberInExpedition(character.name, is_solo);
@ -216,43 +187,43 @@ bool ExpeditionRequest::CheckMembersForConflicts(const std::vector<std::string>&
}
m_members.emplace_back(character.id, character.name, DynamicZoneMemberStatus::Online);
character_ids.emplace_back(character.id);
char_ids.push_back(character.id);
}
auto member_lockouts = CharacterExpeditionLockoutsRepository::GetManyCharacterLockoutTimers(
database, character_ids, m_expedition_name, DZ_REPLAY_TIMER_NAME);
auto lockouts = CharacterExpeditionLockoutsRepository::GetLockouts(database, char_ids, m_dz->GetName());
// on live if leader has a replay lockout it never checks for event conflicts
bool leader_has_replay_lockout = false;
auto lockout_iter = member_lockouts.find(m_leader_id);
if (lockout_iter != member_lockouts.end())
bool leader_replay = false;
auto it = lockouts.find(m_leader_id);
if (it != lockouts.end())
{
leader_has_replay_lockout = SaveLeaderLockouts(lockout_iter->second);
leader_replay = SaveLeaderLockouts(it->second);
}
for (const auto& character : entries)
{
if (character.expedition_id != 0)
if (character.dz_id != 0)
{
has_conflicts = true;
SendLeaderMemberInExpedition(character.name, is_solo);
}
auto lockout_iter = member_lockouts.find(character.id);
if (lockout_iter != member_lockouts.end())
auto it = lockouts.find(character.id);
if (it != lockouts.end())
{
for (const auto& lockout : lockout_iter->second)
for (const auto& lockout : it->second)
{
if (!lockout.IsExpired())
{
auto is_event = [&](const auto& l) { return l.IsEvent(lockout.Event()); };
// replay timers were sorted by query so they show up before event conflicts
if (lockout.IsReplayTimer())
if (lockout.IsReplay())
{
has_conflicts = true;
SendLeaderMemberReplayLockout(character.name, lockout, is_solo);
}
else if (!leader_has_replay_lockout && character.id != m_leader_id &&
m_lockouts.find(lockout.GetEventName()) == m_lockouts.end())
else if (!leader_replay && character.id != m_leader_id && std::ranges::none_of(m_lockouts, is_event))
{
// leader doesn't have this lockout
has_conflicts = true;
@ -266,73 +237,60 @@ bool ExpeditionRequest::CheckMembersForConflicts(const std::vector<std::string>&
return has_conflicts;
}
void ExpeditionRequest::SendLeaderMessage(
uint16_t chat_type, uint32_t string_id, const std::initializer_list<std::string>& args)
void ExpeditionRequest::SendLeaderMessage(uint16_t chat_type, uint32_t string_id, std::initializer_list<std::string> args)
{
if (!m_disable_messages)
if (!m_silent)
{
Client::SendCrossZoneMessageString(m_leader, m_leader_name, chat_type, string_id, args);
}
}
void ExpeditionRequest::SendLeaderMemberInExpedition(const std::string& member_name, bool is_solo)
void ExpeditionRequest::SendLeaderMemberInExpedition(const std::string& name, bool is_solo)
{
if (m_disable_messages)
if (m_silent)
{
return;
}
if (is_solo)
{
SendLeaderMessage(Chat::Red, EXPEDITION_YOU_BELONG);
SendLeaderMessage(Chat::Red, DZ_YOU_BELONG);
}
else if (m_requester)
{
std::string message = fmt::format(EXPEDITION_OTHER_BELONGS, m_requester->GetName(), member_name);
Client::SendCrossZoneMessage(m_leader, m_leader_name, Chat::Red, message);
// message string 9265 (not in emu clients)
Client::SendCrossZoneMessage(m_leader, m_leader_name, Chat::Red, fmt::format(
"{} attempted to create an expedition but {} already belongs to one.", m_requester->GetName(), name));
}
}
void ExpeditionRequest::SendLeaderMemberReplayLockout(
const std::string& member_name, const ExpeditionLockoutTimer& lockout, bool is_solo)
void ExpeditionRequest::SendLeaderMemberReplayLockout(const std::string& name, const DzLockout& lockout, bool is_solo)
{
if (m_disable_messages)
if (m_silent)
{
return;
}
auto time_remaining = lockout.GetDaysHoursMinutesRemaining();
auto time = lockout.GetTimeRemainingStrs();
if (is_solo)
{
SendLeaderMessage(Chat::Red, EXPEDITION_YOU_PLAYED_HERE, {
time_remaining.days, time_remaining.hours, time_remaining.mins
});
SendLeaderMessage(Chat::Red, DZ_REPLAY_YOU, { time.days, time.hours, time.mins });
}
else
{
SendLeaderMessage(Chat::Red, EXPEDITION_REPLAY_TIMER, {
member_name, time_remaining.days, time_remaining.hours, time_remaining.mins
});
SendLeaderMessage(Chat::Red, DZ_REPLAY_OTHER, { name, time.days, time.hours, time.mins });
}
}
void ExpeditionRequest::SendLeaderMemberEventLockout(
const std::string& member_name, const ExpeditionLockoutTimer& lockout)
void ExpeditionRequest::SendLeaderMemberEventLockout(const std::string& name, const DzLockout& lockout)
{
if (m_disable_messages)
if (m_silent)
{
return;
}
auto time_remaining = lockout.GetDaysHoursMinutesRemaining();
SendLeaderMessage(Chat::Red, EXPEDITION_EVENT_TIMER, {
member_name,
lockout.GetEventName(),
time_remaining.days,
time_remaining.hours,
time_remaining.mins,
lockout.GetEventName()
});
auto time = lockout.GetTimeRemainingStrs();
SendLeaderMessage(Chat::Red, DZ_EVENT_TIMER, { name, lockout.Event(), time.days, time.hours, time.mins });
}
bool ExpeditionRequest::IsPlayerCountValidated()
@ -343,19 +301,14 @@ bool ExpeditionRequest::IsPlayerCountValidated()
auto bypass_status = RuleI(Expedition, MinStatusToBypassPlayerCountRequirements);
auto gm_bypass = (m_requester && m_requester->GetGM() && m_requester->Admin() >= bypass_status);
if (m_members.size() > m_max_players)
{
// members were sorted at start, truncate after conflict checks to act like live
m_members.resize(m_max_players);
}
else if (!gm_bypass && m_members.size() < m_min_players)
if (!gm_bypass && m_members.size() < m_dz->GetMinPlayers())
{
requirements_met = false;
SendLeaderMessage(Chat::System, REQUIRED_PLAYER_COUNT, {
SendLeaderMessage(Chat::System, DZ_PLAYER_COUNT, {
fmt::format_int(m_members.size()).str(),
fmt::format_int(m_min_players).str(),
fmt::format_int(m_max_players).str()
fmt::format_int(m_dz->GetMinPlayers()).str(),
fmt::format_int(m_dz->GetMaxPlayers()).str()
});
}

View File

@ -21,12 +21,11 @@
#ifndef EXPEDITION_REQUEST_H
#define EXPEDITION_REQUEST_H
#include "expedition.h"
#include "../common/expedition_lockout_timer.h"
#include "dynamic_zone.h"
#include "../common/dynamic_zone_lockout.h"
#include <cstdint>
#include <string>
#include <vector>
#include <unordered_map>
class Client;
class Group;
@ -35,19 +34,16 @@ class Raid;
class ExpeditionRequest
{
public:
ExpeditionRequest(const DynamicZone& dz, bool disable_messages = false);
ExpeditionRequest(const DynamicZone& dz, Client& client, bool silent = false);
bool Validate(Client* requester);
bool Validate();
const std::string& GetExpeditionName() const { return m_expedition_name; }
Client* GetLeaderClient() const { return m_leader; }
uint32_t GetLeaderID() const { return m_leader_id; }
const std::string& GetLeaderName() const { return m_leader_name; }
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; }
const std::vector<DynamicZoneMember>& GetMembers() const { return m_members; }
const std::unordered_map<std::string, ExpeditionLockoutTimer>& GetLockouts() const { return m_lockouts; }
const std::vector<DzLockout>& GetLockouts() const { return m_lockouts; }
bool IsRaid() const { return m_is_raid; }
private:
bool CanMembersJoin(const std::vector<std::string>& member_names);
@ -55,23 +51,21 @@ private:
bool CanGroupRequest(Group* group);
bool CheckMembersForConflicts(const std::vector<std::string>& member_names);
bool IsPlayerCountValidated();
bool SaveLeaderLockouts(const std::vector<ExpeditionLockoutTimer>& leader_lockouts);
void SendLeaderMemberInExpedition(const std::string& member_name, bool is_solo);
void SendLeaderMemberReplayLockout(const std::string& member_name, const ExpeditionLockoutTimer& lockout, bool is_solo);
void SendLeaderMemberEventLockout(const std::string& member_name, const ExpeditionLockoutTimer& lockout);
void SendLeaderMessage(uint16_t chat_type, uint32_t string_id, const std::initializer_list<std::string>& args = {});
bool SaveLeaderLockouts(const std::vector<DzLockout>& leader_lockouts);
void SendLeaderMemberInExpedition(const std::string& name, bool is_solo);
void SendLeaderMemberReplayLockout(const std::string& name, const DzLockout& lockout, bool is_solo);
void SendLeaderMemberEventLockout(const std::string& name, const DzLockout& lockout);
void SendLeaderMessage(uint16_t chat_type, uint32_t string_id, std::initializer_list<std::string> args = {});
const DynamicZone* m_dz = nullptr;
Client* m_requester = nullptr;
Client* m_leader = nullptr;
uint32_t m_leader_id = 0;
uint32_t m_min_players = 0;
uint32_t m_max_players = 0;
bool m_disable_messages = false;
std::string m_expedition_name;
bool m_silent = false;
bool m_is_raid = false;
std::string m_leader_name;
std::string m_not_all_added_msg;
std::vector<DynamicZoneMember> m_members;
std::unordered_map<std::string, ExpeditionLockoutTimer> m_lockouts;
std::vector<DzLockout> m_lockouts;
};
#endif

View File

@ -1,5 +1,5 @@
#include "../client.h"
#include "../expedition.h"
#include "../dynamic_zone.h"
void command_dz(Client *c, const Seperator *sep)
{
@ -10,151 +10,43 @@ void command_dz(Client *c, const Seperator *sep)
if (strcasecmp(sep->arg[1], "cache") == 0) {
if (strcasecmp(sep->arg[2], "reload") == 0) {
DynamicZone::CacheAllFromDatabase();
Expedition::CacheAllFromDatabase();
c->Message(
Chat::White, fmt::format(
"Reloaded [{}] dynamic zone(s) and [{}] expedition(s) from database",
zone->dynamic_zone_cache.size(), zone->expedition_cache.size()
).c_str());
c->Message(Chat::White, fmt::format("Reloaded [{}] dynamic zone(s) from database", zone->dynamic_zone_cache.size()).c_str());
}
}
else if (strcasecmp(sep->arg[1], "expedition") == 0) {
if (strcasecmp(sep->arg[2], "list") == 0) {
std::vector<Expedition *> expeditions;
for (const auto &expedition : zone->expedition_cache) {
expeditions.emplace_back(expedition.second.get());
}
std::sort(
expeditions.begin(), expeditions.end(),
[](const Expedition *lhs, const Expedition *rhs) {
return lhs->GetID() < rhs->GetID();
}
);
c->Message(Chat::White, fmt::format("Total Active Expeditions: [{}]", expeditions.size()).c_str());
for (const auto &expedition : expeditions) {
auto dz = expedition->GetDynamicZone();
if (!dz) {
LogExpeditions("Expedition [{}] has an invalid dz [{}] in cache",
expedition->GetID(),
expedition->GetDynamicZoneID());
continue;
}
auto leader_saylink = Saylink::Silent(
fmt::format(
"#goto {}",
expedition->GetLeaderName()
),
expedition->GetLeaderName()
);
auto zone_saylink = Saylink::Silent(
fmt::format(
"#zoneinstance {}",
dz->GetInstanceID()
),
"zone"
);
auto seconds = dz->GetSecondsRemaining();
c->Message(
Chat::White, fmt::format(
"expedition id: [{}] dz id: [{}] name: [{}] leader: [{}] {}: [{}]:[{}]:[{}]:[{}] members: [{}] remaining: [{:02}:{:02}:{:02}]",
expedition->GetID(),
expedition->GetDynamicZoneID(),
expedition->GetName(),
leader_saylink,
zone_saylink,
ZoneName(dz->GetZoneID()),
dz->GetZoneID(),
dz->GetInstanceID(),
dz->GetZoneVersion(),
dz->GetMemberCount(),
seconds / 3600, // hours
(seconds / 60) % 60, // minutes
seconds % 60 // seconds
).c_str());
}
else if (strcasecmp(sep->arg[1], "destroy") == 0 && sep->IsNumber(2)) {
auto dz_id = std::strtoul(sep->arg[2], nullptr, 10);
if (auto dz = DynamicZone::FindDynamicZoneByID(dz_id)) {
c->Message(Chat::White, fmt::format("Destroying dz [{}] ({})", dz_id, dz->GetName()).c_str());
dz->RemoveAllMembers();
}
else if (strcasecmp(sep->arg[2], "reload") == 0) {
Expedition::CacheAllFromDatabase();
c->Message(
Chat::White, fmt::format(
"Reloaded [{}] expeditions to cache from database.", zone->expedition_cache.size()
).c_str());
}
else if (strcasecmp(sep->arg[2], "destroy") == 0 && sep->IsNumber(3)) {
auto expedition_id = std::strtoul(sep->arg[3], nullptr, 10);
auto expedition = Expedition::FindCachedExpeditionByID(expedition_id);
if (expedition) {
c->Message(
Chat::White, fmt::format(
"Destroying expedition [{}] ({})",
expedition_id, expedition->GetName()).c_str());
expedition->GetDynamicZone()->RemoveAllMembers();
}
else {
c->Message(Chat::Red, fmt::format("Failed to destroy expedition [{}]", sep->arg[3]).c_str());
}
}
else if (strcasecmp(sep->arg[2], "unlock") == 0 && sep->IsNumber(3)) {
auto expedition_id = std::strtoul(sep->arg[3], nullptr, 10);
auto expedition = Expedition::FindCachedExpeditionByID(expedition_id);
if (expedition) {
c->Message(Chat::White, fmt::format("Unlocking expedition [{}]", expedition_id).c_str());
expedition->SetLocked(false, ExpeditionLockMessage::None, true);
}
else {
c->Message(Chat::Red, fmt::format("Failed to find expedition [{}]", sep->arg[3]).c_str());
}
else {
c->Message(Chat::Red, fmt::format("Failed to destroy dz [{}]", sep->arg[3]).c_str());
}
}
else if (strcasecmp(sep->arg[1], "list") == 0) {
c->Message(
Chat::White,
fmt::format("Total Dynamic Zones (cache): [{}]", zone->dynamic_zone_cache.size()).c_str());
std::vector<DynamicZone *> dynamic_zones;
for (const auto &dz : zone->dynamic_zone_cache) {
dynamic_zones.emplace_back(dz.second.get());
std::vector<DynamicZone*> dynamic_zones;
for (const auto& it : zone->dynamic_zone_cache) {
dynamic_zones.push_back(it.second.get());
}
std::sort(
dynamic_zones.begin(), dynamic_zones.end(),
[](const DynamicZone *lhs, const DynamicZone *rhs) {
return lhs->GetID() < rhs->GetID();
}
);
for (const auto &dz : dynamic_zones) {
auto seconds = dz->GetSecondsRemaining();
auto zone_saylink = Saylink::Silent(
fmt::format(
"#zoneinstance {}",
dz->GetInstanceID()
),
"zone"
);
std::string aligned_type = fmt::format(
"[{}]",
DynamicZone::GetDynamicZoneTypeName(static_cast<DynamicZoneType>(dz->GetType())));
c->Message(
Chat::White, fmt::format(
"id: [{}] type: {:>10} {}: [{}]:[{}]:[{}] members: [{}] remaining: [{:02}:{:02}:{:02}]",
dz->GetID(),
aligned_type,
zone_saylink,
dz->GetZoneID(),
dz->GetInstanceID(),
dz->GetZoneVersion(),
dz->GetMemberCount(),
seconds / 3600, // hours
(seconds / 60) % 60, // minutes
seconds % 60 // seconds
).c_str());
std::ranges::sort(dynamic_zones, {}, &DynamicZone::GetID);
c->Message(Chat::White, fmt::format("Total Dynamic Zones (cache): [{}]", dynamic_zones.size()).c_str());
for (const DynamicZone* dz : dynamic_zones) {
uint32_t seconds = dz->GetSecondsRemaining();
c->Message(Chat::White, fmt::format(
"id: [{}] - [{}] - {}: [{}:{}:{}] members: [{}] expires: [{:02}:{:02}:{:02}] leader: [{}]",
dz->GetID(),
DynamicZone::GetDynamicZoneTypeName(dz->GetType()),
Saylink::Silent(fmt::format("#zoneinstance {}", dz->GetInstanceID()), "zone"),
dz->GetZoneID(),
dz->GetInstanceID(),
dz->GetZoneVersion(),
dz->GetMemberCount(),
seconds / 3600, // hours
seconds / 60 % 60, // minutes
seconds % 60, // seconds
Saylink::Silent(fmt::format("#goto {}", dz->GetLeaderName()), dz->GetLeaderName())
).c_str());
}
}
else if (strcasecmp(sep->arg[1], "listdb") == 0) {
@ -163,97 +55,70 @@ void command_dz(Client *c, const Seperator *sep)
auto now = std::chrono::system_clock::now();
for (const auto &dz : dz_list) {
auto expire_time = std::chrono::system_clock::from_time_t(dz.start_time + dz.duration);
auto remaining = std::chrono::duration_cast<std::chrono::seconds>(expire_time - now);
auto seconds = std::max(0, static_cast<int>(remaining.count()));
for (const auto& dz : dz_list) {
auto expire_time = std::chrono::system_clock::from_time_t(static_cast<time_t>(dz.start_time) + dz.duration);
bool is_expired = now > expire_time;
if (!is_expired || strcasecmp(sep->arg[2], "all") == 0) {
auto zone_saylink = is_expired ? "zone" : Saylink::Silent(
fmt::format(
"#zoneinstance {}",
dz.instance
),
"zone"
);
c->Message(
Chat::White, fmt::format(
"id: [{}] type: [{}] {}: [{}]:[{}]:[{}] members: [{}] remaining: [{:02}:{:02}:{:02}]",
dz.id,
DynamicZone::GetDynamicZoneTypeName(static_cast<DynamicZoneType>(dz.type)),
zone_saylink,
dz.zone,
dz.instance,
dz.version,
dz.member_count,
seconds / 3600, // hours
(seconds / 60) % 60, // minutes
seconds % 60 // seconds
).c_str());
auto seconds = std::max(0, static_cast<int>(std::chrono::duration_cast<std::chrono::seconds>(expire_time - now).count()));
c->Message(Chat::White, fmt::format(
"id: [{}] - [{}] - {}: [{}:{}:{}] members: [{}] expires: [{:02}:{:02}:{:02}]",
dz.id,
DynamicZone::GetDynamicZoneTypeName(static_cast<DynamicZoneType>(dz.type)),
is_expired ? "zone" : Saylink::Silent(fmt::format("#zoneinstance {}", dz.instance), "zone"),
dz.zone,
dz.instance,
dz.version,
dz.member_count,
seconds / 3600, // hours
seconds / 60 % 60, // minutes
seconds % 60 // seconds
).c_str());
}
}
}
else if (strcasecmp(sep->arg[1], "lockouts") == 0) {
if (strcasecmp(sep->arg[2], "remove") == 0 && sep->arg[3][0] != '\0') {
if (sep->arg[5][0] == '\0') {
c->Message(
Chat::White, fmt::format(
"Removing [{}] lockouts on [{}].", sep->arg[4][0] ? sep->arg[4] : "all", sep->arg[3]
).c_str());
c->Message(Chat::White, fmt::format("Removing [{}] lockouts on [{}].", sep->arg[4][0] ? sep->arg[4] : "all", sep->arg[3]).c_str());
}
else {
c->Message(
Chat::White, fmt::format(
"Removing [{}]:[{}] lockout on [{}].", sep->arg[4], sep->arg[5], sep->arg[3]
).c_str());
c->Message(Chat::White, fmt::format("Removing [{}]:[{}] lockout on [{}].", sep->arg[4], sep->arg[5], sep->arg[3]).c_str());
}
Expedition::RemoveLockoutsByCharacterName(sep->arg[3], sep->arg[4], sep->arg[5]);
DynamicZone::RemoveCharacterLockouts(sep->arg[3], sep->arg[4], sep->arg[5]);
}
}
else if (strcasecmp(sep->arg[1], "makeleader") == 0 && sep->IsNumber(2) && sep->arg[3][0] != '\0') {
auto expedition_id = std::strtoul(sep->arg[2], nullptr, 10);
auto expedition = Expedition::FindCachedExpeditionByID(expedition_id);
if (expedition) {
auto char_name = FormatName(sep->arg[3]);
c->Message(
Chat::White,
fmt::format("Setting expedition [{}] leader to [{}]", expedition_id, char_name).c_str());
expedition->SendWorldMakeLeaderRequest(c->CharacterID(), char_name);
uint32_t dz_id = std::strtoul(sep->arg[2], nullptr, 10);
if (auto dz = DynamicZone::FindDynamicZoneByID(dz_id)) {
std::string name = FormatName(sep->arg[3]);
c->Message(Chat::White, fmt::format("Setting expedition [{}] leader to [{}]", dz_id, name).c_str());
dz->SendWorldMakeLeaderRequest(c->CharacterID(), name);
}
else {
c->Message(Chat::Red, fmt::format("Failed to find expedition [{}]", expedition_id).c_str());
c->Message(Chat::Red, fmt::format("Failed to find expedition [{}]", dz_id).c_str());
}
}
else if (strcasecmp(sep->arg[1], "unlock") == 0 && sep->IsNumber(2)) {
uint32_t dz_id = std::strtoul(sep->arg[2], nullptr, 10);
if (auto dz = DynamicZone::FindDynamicZoneByID(dz_id)) {
c->Message(Chat::White, fmt::format("Unlocking expedition dz [{}]", dz_id).c_str());
dz->SetLocked(false, true);
}
else {
c->Message(Chat::Red, fmt::format("Failed to find dz [{}]", sep->arg[2]).c_str());
}
}
else {
c->Message(Chat::White, "#dz usage:");
c->Message(
Chat::White,
"#dz cache reload - reload the current zone cache from db (also reloads expedition cache dependency)"
);
c->Message(Chat::White, "#dz expedition list - list expeditions in current zone cache");
c->Message(Chat::White, "#dz expedition reload - reload expedition zone cache from database");
c->Message(
Chat::White,
"#dz expedition destroy <expedition_id> - destroy expedition globally (must be in cache)"
);
c->Message(Chat::White, "#dz expedition unlock <expedition_id> - unlock expedition");
c->Message(Chat::White, "#dz list - list all dynamic zone instances from current zone cache");
c->Message(
Chat::White,
"#dz listdb [all] - list dynamic zone instances from database -- 'all' includes expired"
);
c->Message(Chat::White, "#dz cache reload - reload current zone cache from db (also reloads expedition cache)");
c->Message(Chat::White, "#dz destroy <dz_id> - destroy dz globally (must be in cache)");
c->Message(Chat::White, "#dz list - list dynamic zones in current zone cache");
c->Message(Chat::White, "#dz listdb [all] - list dynamic zones in database -- 'all' includes expired");
c->Message(Chat::White, "#dz lockouts remove <char_name> - delete all of character's expedition lockouts");
c->Message(
Chat::White,
"#dz lockouts remove <char_name> \"<expedition_name>\" - delete lockouts by expedition"
);
c->Message(
Chat::White,
"#dz lockouts remove <char_name> \"<expedition_name>\" \"<event_name>\" - delete lockout by expedition event"
);
c->Message(Chat::White, "#dz makeleader <expedition_id> <character_name> - set new expedition leader");
c->Message(Chat::White, "#dz lockouts remove <char_name> \"<expedition_name>\" - delete lockouts by expedition");
c->Message(Chat::White, "#dz lockouts remove <char_name> \"<expedition_name>\" \"<event_name>\" - delete expedition event lockout");
c->Message(Chat::White, "#dz makeleader <dz_id> <character_name> - set new expedition leader");
c->Message(Chat::White, "#dz unlock <dz_id> - unlock expedition");
}
}

View File

@ -1,13 +1,11 @@
#include "../client.h"
#include "../expedition.h"
void command_dzkickplayers(Client *c, const Seperator *sep)
{
if (c) {
auto expedition = c->GetExpedition();
if (expedition) {
expedition->DzKickPlayers(c);
auto dz = c->GetExpedition();
if (dz) {
dz->DzKickPlayers(c);
}
}
}

View File

@ -18,11 +18,12 @@
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "expedition.h"
#include "dynamic_zone.h"
#include "masterentity.h"
#include "worldserver.h"
#include "string_ids.h"
#include "../common/events/player_event_logs.h"
#include "../common/repositories/character_expedition_lockouts_repository.h"
#include "../common/repositories/group_id_repository.h"
#include "../common/repositories/group_leaders_repository.h"
#include "queryserv.h"
@ -2515,25 +2516,21 @@ void Group::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_r
}
}
bool Group::DoesAnyMemberHaveExpeditionLockout(
const std::string& expedition_name, const std::string& event_name, int max_check_count)
bool Group::AnyMemberHasDzLockout(const std::string& expedition, const std::string& event)
{
if (max_check_count <= 0)
std::vector<std::string> names;
for (int i = 0; i < MAX_GROUP_MEMBERS; ++i)
{
max_check_count = MAX_GROUP_MEMBERS;
}
for (int i = 0; i < MAX_GROUP_MEMBERS && i < max_check_count; ++i)
{
if (membername[i][0])
if (!members[i] && membername[i][0])
{
if (Expedition::HasLockoutByCharacterName(membername[i], expedition_name, event_name))
{
return true;
}
names.emplace_back(membername[i]); // out of zone member
}
else if (members[i] && members[i]->IsClient() && members[i]->CastToClient()->HasDzLockout(expedition, event))
{
return true;
}
}
return false;
return !CharacterExpeditionLockoutsRepository::GetLockouts(database, names, expedition, event).empty();
}
bool Group::IsLeader(const char* name) {

View File

@ -161,7 +161,7 @@ public:
inline int GetMentorPercent() { return mentor_percent; }
inline Client *GetMentoree() { return mentoree; }
bool DoesAnyMemberHaveExpeditionLockout(const std::string& expedition_name, const std::string& event_name, int max_check_count = 0);
bool AnyMemberHasDzLockout(const std::string& expedition, const std::string& event);
Mob* members[MAX_GROUP_MEMBERS] {nullptr};
char membername[MAX_GROUP_MEMBERS][64] {""};

View File

@ -1944,12 +1944,12 @@ Lua_Expedition Lua_Client::CreateExpedition(luabind::object expedition_table) {
Lua_Expedition Lua_Client::CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players) {
Lua_Safe_Call_Class(Lua_Expedition);
return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players);
return self->CreateExpedition(ZoneID(zone_name), version, duration, expedition_name, min_players, max_players);
}
Lua_Expedition Lua_Client::CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players, bool disable_messages) {
Lua_Safe_Call_Class(Lua_Expedition);
return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players, disable_messages);
return self->CreateExpedition(ZoneID(zone_name), version, duration, expedition_name, min_players, max_players, disable_messages);
}
Lua_Expedition Lua_Client::CreateExpeditionFromTemplate(uint32_t dz_template_id) {
@ -1968,16 +1968,15 @@ luabind::object Lua_Client::GetExpeditionLockouts(lua_State* L)
if (d_)
{
auto self = reinterpret_cast<NativeType*>(d_);
auto lockouts = self->GetExpeditionLockouts();
const auto& lockouts = self->GetDzLockouts();
for (const auto& lockout : lockouts)
{
auto lockout_table = lua_table[lockout.GetExpeditionName()];
auto lockout_table = lua_table[lockout.DzName()];
if (luabind::type(lockout_table) != LUA_TTABLE)
{
lockout_table = luabind::newtable(L);
}
lockout_table[lockout.GetEventName()] = lockout.GetSecondsRemaining();
lockout_table[lockout.Event()] = lockout.GetSecondsRemaining();
}
}
return lua_table;
@ -1989,13 +1988,12 @@ luabind::object Lua_Client::GetExpeditionLockouts(lua_State* L, std::string expe
if (d_)
{
auto self = reinterpret_cast<NativeType*>(d_);
auto lockouts = self->GetExpeditionLockouts();
const auto& lockouts = self->GetDzLockouts();
for (const auto& lockout : lockouts)
{
if (lockout.GetExpeditionName() == expedition_name)
if (lockout.DzName() == expedition_name)
{
lua_table[lockout.GetEventName()] = lockout.GetSecondsRemaining();
lua_table[lockout.Event()] = lockout.GetSecondsRemaining();
}
}
}
@ -2005,52 +2003,54 @@ luabind::object Lua_Client::GetExpeditionLockouts(lua_State* L, std::string expe
std::string Lua_Client::GetLockoutExpeditionUUID(std::string expedition_name, std::string event_name) {
Lua_Safe_Call_String();
std::string uuid;
auto lockout = self->GetExpeditionLockout(expedition_name, event_name);
auto lockout = self->GetDzLockout(expedition_name, event_name);
if (lockout)
{
uuid = lockout->GetExpeditionUUID();
uuid = lockout->UUID();
}
return uuid;
}
void Lua_Client::AddExpeditionLockout(std::string expedition_name, std::string event_name, uint32 seconds) {
Lua_Safe_Call_Void();
self->AddNewExpeditionLockout(expedition_name, event_name, seconds);
self->AddDzLockout(expedition_name, event_name, seconds);
}
void Lua_Client::AddExpeditionLockout(std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) {
Lua_Safe_Call_Void();
self->AddNewExpeditionLockout(expedition_name, event_name, seconds, uuid);
self->AddDzLockout(expedition_name, event_name, seconds, uuid);
}
void Lua_Client::AddExpeditionLockoutDuration(std::string expedition_name, std::string event_name, int seconds) {
Lua_Safe_Call_Void();
self->AddExpeditionLockoutDuration(expedition_name, event_name, seconds, {}, true);
auto lockout = DzLockout::Create(expedition_name, event_name, seconds);
self->AddDzLockoutDuration(lockout, seconds, {}, true);
}
void Lua_Client::AddExpeditionLockoutDuration(std::string expedition_name, std::string event_name, int seconds, std::string uuid) {
Lua_Safe_Call_Void();
self->AddExpeditionLockoutDuration(expedition_name, event_name, seconds, uuid, true);
auto lockout = DzLockout::Create(expedition_name, event_name, seconds, uuid);
self->AddDzLockoutDuration(lockout, seconds, uuid, true);
}
void Lua_Client::RemoveAllExpeditionLockouts() {
Lua_Safe_Call_Void();
self->RemoveAllExpeditionLockouts({}, true);
self->RemoveDzLockouts({}, true);
}
void Lua_Client::RemoveAllExpeditionLockouts(std::string expedition_name) {
Lua_Safe_Call_Void();
self->RemoveAllExpeditionLockouts(expedition_name, true);
self->RemoveDzLockouts(expedition_name, true);
}
void Lua_Client::RemoveExpeditionLockout(std::string expedition_name, std::string event_name) {
Lua_Safe_Call_Void();
self->RemoveExpeditionLockout(expedition_name, event_name, true);
self->RemoveDzLockout(expedition_name, event_name, true);
}
bool Lua_Client::HasExpeditionLockout(std::string expedition_name, std::string event_name) {
Lua_Safe_Call_Bool();
return self->HasExpeditionLockout(expedition_name, event_name);
return self->HasDzLockout(expedition_name, event_name);
}
void Lua_Client::MovePCDynamicZone(uint32 zone_id) {

View File

@ -1,7 +1,7 @@
#ifdef LUA_EQEMU
#include "lua_expedition.h"
#include "expedition.h"
#include "dynamic_zone.h"
#include "../common/zone_store.h"
#include "lua.hpp"
#include <luabind/luabind.hpp>
@ -24,22 +24,17 @@ void Lua_Expedition::AddLockoutDuration(std::string event_name, int seconds, boo
void Lua_Expedition::AddReplayLockout(uint32_t seconds) {
Lua_Safe_Call_Void();
self->AddReplayLockout(seconds);
self->AddLockout(DzLockout::ReplayTimer, seconds);
}
void Lua_Expedition::AddReplayLockoutDuration(int seconds) {
Lua_Safe_Call_Void();
self->AddReplayLockoutDuration(seconds);
self->AddLockoutDuration(DzLockout::ReplayTimer, seconds);
}
void Lua_Expedition::AddReplayLockoutDuration(int seconds, bool members_only) {
Lua_Safe_Call_Void();
self->AddReplayLockoutDuration(seconds, members_only);
}
uint32_t Lua_Expedition::GetDynamicZoneID() {
Lua_Safe_Call_Int();
return self->GetDynamicZoneID();
self->AddLockoutDuration(DzLockout::ReplayTimer, seconds, members_only);
}
uint32_t Lua_Expedition::GetID() {
@ -49,7 +44,7 @@ uint32_t Lua_Expedition::GetID() {
int Lua_Expedition::GetInstanceID() {
Lua_Safe_Call_Int();
return self->GetDynamicZone()->GetInstanceID();
return self->GetInstanceID();
}
std::string Lua_Expedition::GetLeaderName() {
@ -63,10 +58,10 @@ luabind::object Lua_Expedition::GetLockouts(lua_State* L) {
if (d_)
{
auto self = reinterpret_cast<NativeType*>(d_);
auto lockouts = self->GetLockouts();
const auto& lockouts = self->GetLockouts();
for (const auto& lockout : lockouts)
{
lua_table[lockout.first] = lockout.second.GetSecondsRemaining();
lua_table[lockout.Event()] = lockout.GetSecondsRemaining();
}
}
return lua_table;
@ -74,17 +69,17 @@ luabind::object Lua_Expedition::GetLockouts(lua_State* L) {
std::string Lua_Expedition::GetLootEventByNPCTypeID(uint32_t npc_type_id) {
Lua_Safe_Call_String();
return self->GetLootEventByNPCTypeID(npc_type_id);
return self->GetLootEvent(npc_type_id, DzLootEvent::Type::NpcType);
}
std::string Lua_Expedition::GetLootEventBySpawnID(uint32_t spawn_id) {
Lua_Safe_Call_String();
return self->GetLootEventBySpawnID(spawn_id);
return self->GetLootEvent(spawn_id, DzLootEvent::Type::Entity);
}
uint32_t Lua_Expedition::GetMemberCount() {
Lua_Safe_Call_Int();
return self->GetDynamicZone()->GetMemberCount();
return self->GetMemberCount();
}
luabind::object Lua_Expedition::GetMembers(lua_State* L) {
@ -93,7 +88,7 @@ luabind::object Lua_Expedition::GetMembers(lua_State* L) {
if (d_)
{
auto self = reinterpret_cast<NativeType*>(d_);
for (const auto& member : self->GetDynamicZone()->GetMembers())
for (const auto& member : self->GetMembers())
{
lua_table[member.name] = member.id;
}
@ -108,27 +103,27 @@ std::string Lua_Expedition::GetName() {
int Lua_Expedition::GetSecondsRemaining() {
Lua_Safe_Call_Int();
return self->GetDynamicZone()->GetSecondsRemaining();
return self->GetSecondsRemaining();
}
std::string Lua_Expedition::GetUUID() {
Lua_Safe_Call_String();
return self->GetDynamicZone()->GetUUID();
return self->GetUUID();
}
int Lua_Expedition::GetZoneID() {
Lua_Safe_Call_Int();
return self->GetDynamicZone()->GetZoneID();
return self->GetZoneID();
}
std::string Lua_Expedition::GetZoneName() {
Lua_Safe_Call_String();
return ZoneName(self->GetDynamicZone()->GetZoneID());
return ZoneName(self->GetZoneID());
}
int Lua_Expedition::GetZoneVersion() {
Lua_Safe_Call_Int();
return self->GetDynamicZone()->GetZoneVersion();
return self->GetZoneVersion();
}
bool Lua_Expedition::HasLockout(std::string event_name) {
@ -148,7 +143,7 @@ bool Lua_Expedition::IsLocked() {
void Lua_Expedition::RemoveCompass() {
Lua_Safe_Call_Void();
self->GetDynamicZone()->SetCompass(0, 0, 0, 0, true);
self->SetCompass(0, 0, 0, 0, true);
}
void Lua_Expedition::RemoveLockout(std::string event_name) {
@ -158,69 +153,69 @@ void Lua_Expedition::RemoveLockout(std::string event_name) {
void Lua_Expedition::SetCompass(uint32_t zone_id, float x, float y, float z) {
Lua_Safe_Call_Void();
self->GetDynamicZone()->SetCompass(zone_id, x, y, z, true);
self->SetCompass(zone_id, x, y, z, true);
}
void Lua_Expedition::SetCompass(std::string zone_name, float x, float y, float z) {
Lua_Safe_Call_Void();
self->GetDynamicZone()->SetCompass(ZoneID(zone_name), x, y, z, true);
self->SetCompass(ZoneID(zone_name), x, y, z, true);
}
void Lua_Expedition::SetLocked(bool lock_expedition) {
Lua_Safe_Call_Void();
self->SetLocked(lock_expedition, ExpeditionLockMessage::None, true);
self->SetLocked(lock_expedition, true);
}
void Lua_Expedition::SetLocked(bool lock_expedition, int lock_msg) {
Lua_Safe_Call_Void();
self->SetLocked(lock_expedition, static_cast<ExpeditionLockMessage>(lock_msg), true);
self->SetLocked(lock_expedition, true, static_cast<DzLockMsg>(lock_msg));
}
void Lua_Expedition::SetLocked(bool lock_expedition, int lock_msg, uint32_t msg_color) {
Lua_Safe_Call_Void();
self->SetLocked(lock_expedition, static_cast<ExpeditionLockMessage>(lock_msg), true, msg_color);
self->SetLocked(lock_expedition, true, static_cast<DzLockMsg>(lock_msg), msg_color);
}
void Lua_Expedition::SetLootEventByNPCTypeID(uint32_t npc_type_id, std::string event_name) {
Lua_Safe_Call_Void();
self->SetLootEventByNPCTypeID(npc_type_id, event_name);
self->SetLootEvent(npc_type_id, event_name, DzLootEvent::Type::NpcType);
}
void Lua_Expedition::SetLootEventBySpawnID(uint32_t spawn_id, std::string event_name) {
Lua_Safe_Call_Void();
self->SetLootEventBySpawnID(spawn_id, event_name);
self->SetLootEvent(spawn_id, event_name, DzLootEvent::Type::Entity);
}
void Lua_Expedition::SetReplayLockoutOnMemberJoin(bool enable) {
Lua_Safe_Call_Void();
self->SetReplayLockoutOnMemberJoin(enable, true);
self->SetReplayOnJoin(enable, true);
}
void Lua_Expedition::SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading) {
Lua_Safe_Call_Void();
self->GetDynamicZone()->SetSafeReturn(zone_id, x, y, z, heading, true);
self->SetSafeReturn(zone_id, x, y, z, heading, true);
}
void Lua_Expedition::SetSafeReturn(std::string zone_name, float x, float y, float z, float heading) {
Lua_Safe_Call_Void();
self->GetDynamicZone()->SetSafeReturn(ZoneID(zone_name), x, y, z, heading, true);
self->SetSafeReturn(ZoneID(zone_name), x, y, z, heading, true);
}
void Lua_Expedition::SetSecondsRemaining(uint32_t seconds_remaining)
{
Lua_Safe_Call_Void();
self->GetDynamicZone()->SetSecondsRemaining(seconds_remaining);
self->SetSecondsRemaining(seconds_remaining);
}
void Lua_Expedition::SetSwitchID(int dz_switch_id)
{
Lua_Safe_Call_Void();
self->GetDynamicZone()->SetSwitchID(dz_switch_id, true);
self->SetSwitchID(dz_switch_id, true);
}
void Lua_Expedition::SetZoneInLocation(float x, float y, float z, float heading) {
Lua_Safe_Call_Void();
self->GetDynamicZone()->SetZoneInLocation(x, y, z, heading, true);
self->SetZoneInLocation(x, y, z, heading, true);
}
void Lua_Expedition::UpdateLockoutDuration(std::string event_name, uint32_t duration) {
@ -244,7 +239,7 @@ luabind::scope lua_register_expedition() {
.def("AddReplayLockout", (void(Lua_Expedition::*)(uint32_t))&Lua_Expedition::AddReplayLockout)
.def("AddReplayLockoutDuration", (void(Lua_Expedition::*)(int))&Lua_Expedition::AddReplayLockoutDuration)
.def("AddReplayLockoutDuration", (void(Lua_Expedition::*)(int, bool))&Lua_Expedition::AddReplayLockoutDuration)
.def("GetDynamicZoneID", &Lua_Expedition::GetDynamicZoneID)
.def("GetDynamicZoneID", &Lua_Expedition::GetID)
.def("GetID", (uint32_t(Lua_Expedition::*)(void))&Lua_Expedition::GetID)
.def("GetInstanceID", (int(Lua_Expedition::*)(void))&Lua_Expedition::GetInstanceID)
.def("GetLeaderName", (std::string(Lua_Expedition::*)(void))&Lua_Expedition::GetLeaderName)
@ -282,12 +277,12 @@ luabind::scope lua_register_expedition() {
}
luabind::scope lua_register_expedition_lock_messages() {
return luabind::class_<ExpeditionLockMessage>("ExpeditionLockMessage")
return luabind::class_<DzLockMsg>("ExpeditionLockMessage")
.enum_("constants")
[(
luabind::value("None", static_cast<int>(ExpeditionLockMessage::None)),
luabind::value("Close", static_cast<int>(ExpeditionLockMessage::Close)),
luabind::value("Begin", static_cast<int>(ExpeditionLockMessage::Begin))
luabind::value("None", static_cast<int>(DzLockMsg::None)),
luabind::value("Close", static_cast<int>(DzLockMsg::Close)),
luabind::value("Begin", static_cast<int>(DzLockMsg::Begin))
)];
}

View File

@ -26,7 +26,7 @@
#include "../common/types.h"
#include <string>
class Expedition;
class DynamicZone;
class Lua_Client;
struct lua_State;
@ -41,16 +41,16 @@ namespace luabind {
luabind::scope lua_register_expedition();
luabind::scope lua_register_expedition_lock_messages();
class Lua_Expedition : public Lua_Ptr<Expedition>
class Lua_Expedition : public Lua_Ptr<DynamicZone>
{
typedef Expedition NativeType;
typedef DynamicZone NativeType;
public:
Lua_Expedition() : Lua_Ptr(nullptr) { }
Lua_Expedition(Expedition *d) : Lua_Ptr(d) { }
Lua_Expedition(DynamicZone* d) : Lua_Ptr(d) { }
virtual ~Lua_Expedition() { }
operator Expedition*() {
return reinterpret_cast<Expedition*>(GetLuaPtrData());
operator DynamicZone*() {
return reinterpret_cast<DynamicZone*>(GetLuaPtrData());
}
void AddLockout(std::string event_name, uint32_t seconds);
@ -59,7 +59,6 @@ public:
void AddReplayLockout(uint32_t seconds);
void AddReplayLockoutDuration(int seconds);
void AddReplayLockoutDuration(int seconds, bool members_only);
uint32_t GetDynamicZoneID();
uint32_t GetID();
int GetInstanceID();
std::string GetLeaderName();

View File

@ -25,8 +25,8 @@
#include "encounter.h"
#include "lua_encounter.h"
#include "data_bucket.h"
#include "expedition.h"
#include "dialogue_window.h"
#include "dynamic_zone.h"
#include "../common/events/player_event_logs.h"
#include "worldserver.h"
#include "zone.h"
@ -1828,36 +1828,36 @@ void lua_set_content_flag(std::string flag_name, bool enabled){
Lua_Expedition lua_get_expedition() {
if (zone && zone->GetInstanceID() != 0)
{
return Expedition::FindCachedExpeditionByZoneInstance(zone->GetZoneID(), zone->GetInstanceID());
return DynamicZone::FindExpeditionByZone(zone->GetZoneID(), zone->GetInstanceID());
}
return nullptr;
}
Lua_Expedition lua_get_expedition_by_char_id(uint32 char_id) {
return Expedition::FindCachedExpeditionByCharacterID(char_id);
return DynamicZone::FindExpeditionByCharacter(char_id);
}
Lua_Expedition lua_get_expedition_by_dz_id(uint32 dz_id) {
return Expedition::FindCachedExpeditionByDynamicZoneID(dz_id);
return DynamicZone::FindDynamicZoneByID(dz_id, DynamicZoneType::Expedition);
}
Lua_Expedition lua_get_expedition_by_zone_instance(uint32 zone_id, uint32 instance_id) {
return Expedition::FindCachedExpeditionByZoneInstance(zone_id, instance_id);
return DynamicZone::FindExpeditionByZone(zone_id, instance_id);
}
luabind::object lua_get_expedition_lockout_by_char_id(lua_State* L, uint32 char_id, std::string expedition_name, std::string event_name) {
luabind::adl::object lua_table = luabind::newtable(L);
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id);
auto lockouts = DynamicZone::GetCharacterLockouts(char_id);
auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const ExpeditionLockoutTimer& lockout) {
return lockout.IsSameLockout(expedition_name, event_name);
auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const DzLockout& lockout) {
return lockout.IsSame(expedition_name, event_name);
});
if (it != lockouts.end())
{
lua_table["remaining"] = it->GetSecondsRemaining();
lua_table["uuid"] = it->GetExpeditionUUID();
lua_table["uuid"] = it->UUID();
}
return lua_table;
@ -1866,23 +1866,23 @@ luabind::object lua_get_expedition_lockout_by_char_id(lua_State* L, uint32 char_
luabind::object lua_get_expedition_lockouts_by_char_id(lua_State* L, uint32 char_id) {
luabind::adl::object lua_table = luabind::newtable(L);
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id);
auto lockouts = DynamicZone::GetCharacterLockouts(char_id);
for (const auto& lockout : lockouts)
{
auto lockout_table = lua_table[lockout.GetExpeditionName()];
auto lockout_table = lua_table[lockout.DzName()];
if (luabind::type(lockout_table) != LUA_TTABLE)
{
lockout_table = luabind::newtable(L);
}
auto event_table = lockout_table[lockout.GetEventName()];
auto event_table = lockout_table[lockout.Event()];
if (luabind::type(event_table) != LUA_TTABLE)
{
event_table = luabind::newtable(L);
}
event_table["remaining"] = lockout.GetSecondsRemaining();
event_table["uuid"] = lockout.GetExpeditionUUID();
event_table["uuid"] = lockout.UUID();
}
return lua_table;
}
@ -1890,51 +1890,51 @@ luabind::object lua_get_expedition_lockouts_by_char_id(lua_State* L, uint32 char
luabind::object lua_get_expedition_lockouts_by_char_id(lua_State* L, uint32 char_id, std::string expedition_name) {
luabind::adl::object lua_table = luabind::newtable(L);
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id);
auto lockouts = DynamicZone::GetCharacterLockouts(char_id);
for (const auto& lockout : lockouts)
{
if (lockout.GetExpeditionName() == expedition_name)
if (lockout.DzName() == expedition_name)
{
auto event_table = lua_table[lockout.GetEventName()];
auto event_table = lua_table[lockout.Event()];
if (luabind::type(event_table) != LUA_TTABLE)
{
event_table = luabind::newtable(L);
}
event_table["remaining"] = lockout.GetSecondsRemaining();
event_table["uuid"] = lockout.GetExpeditionUUID();
event_table["uuid"] = lockout.UUID();
}
}
return lua_table;
}
void lua_add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds) {
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds);
Expedition::AddLockoutClients(lockout);
auto lockout = DzLockout::Create(expedition_name, event_name, seconds);
DynamicZone::AddClientsLockout(lockout);
}
void lua_add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) {
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds, uuid);
Expedition::AddLockoutClients(lockout);
auto lockout = DzLockout::Create(expedition_name, event_name, seconds, uuid);
DynamicZone::AddClientsLockout(lockout);
}
void lua_add_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name, uint32 seconds) {
Expedition::AddLockoutByCharacterID(char_id, expedition_name, event_name, seconds);
DynamicZone::AddCharacterLockout(char_id, expedition_name, event_name, seconds);
}
void lua_add_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) {
Expedition::AddLockoutByCharacterID(char_id, expedition_name, event_name, seconds, uuid);
DynamicZone::AddCharacterLockout(char_id, expedition_name, event_name, seconds, uuid);
}
void lua_remove_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name) {
Expedition::RemoveLockoutsByCharacterID(char_id, expedition_name, event_name);
DynamicZone::RemoveCharacterLockouts(char_id, expedition_name, event_name);
}
void lua_remove_all_expedition_lockouts_by_char_id(uint32 char_id) {
Expedition::RemoveLockoutsByCharacterID(char_id);
DynamicZone::RemoveCharacterLockouts(char_id);
}
void lua_remove_all_expedition_lockouts_by_char_id(uint32 char_id, std::string expedition_name) {
Expedition::RemoveLockoutsByCharacterID(char_id, expedition_name);
DynamicZone::RemoveCharacterLockouts(char_id, expedition_name);
}
std::string lua_seconds_to_time(int duration) {

View File

@ -125,13 +125,13 @@ Lua_Mob Lua_Group::GetMember(int member_index) {
bool Lua_Group::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name)
{
Lua_Safe_Call_Bool();
return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name);
return self->AnyMemberHasDzLockout(expedition_name, event_name);
}
bool Lua_Group::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name, int max_check_count)
{
Lua_Safe_Call_Bool();
return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count);
return self->AnyMemberHasDzLockout(expedition_name, event_name); // max_check_count deprecated
}
uint32 Lua_Group::GetAverageLevel() {

View File

@ -157,13 +157,13 @@ int Lua_Raid::GetGroupNumber(int member_index) {
bool Lua_Raid::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name)
{
Lua_Safe_Call_Bool();
return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name);
return self->AnyMemberHasDzLockout(expedition_name, event_name);
}
bool Lua_Raid::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name, int max_check_count)
{
Lua_Safe_Call_Bool();
return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count);
return self->AnyMemberHasDzLockout(expedition_name, event_name); // max_check_count deprecated
}
luabind::scope lua_register_raid() {

View File

@ -5,7 +5,7 @@
#include "../common/global_define.h"
#include "embperl.h"
#include "client.h"
#include "expedition.h"
#include "dynamic_zone.h"
#include "titles.h"
#include "dialogue_window.h"
@ -1775,7 +1775,7 @@ DynamicZoneLocation GetDynamicZoneLocationFromHash(perl::hash table)
return { zone_id, x, y, z, h };
}
Expedition* Perl_Client_CreateExpedition(Client* self, perl::reference table_ref)
DynamicZone* Perl_Client_CreateExpedition(Client* self, perl::reference table_ref)
{
perl::hash table = table_ref;
perl::hash expedition = table["expedition"];
@ -1822,17 +1822,17 @@ Expedition* Perl_Client_CreateExpedition(Client* self, perl::reference table_ref
return self->CreateExpedition(dz);
}
Expedition* Perl_Client_CreateExpedition(Client* self, std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players)
DynamicZone* Perl_Client_CreateExpedition(Client* self, std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players)
{
return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players);
return self->CreateExpedition(ZoneID(zone_name), version, duration, expedition_name, min_players, max_players);
}
Expedition* Perl_Client_CreateExpedition(Client* self, std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players, bool disable_messages)
DynamicZone* Perl_Client_CreateExpedition(Client* self, std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players, bool disable_messages)
{
return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players, disable_messages);
return self->CreateExpedition(ZoneID(zone_name), version, duration, expedition_name, min_players, max_players, disable_messages);
}
Expedition* Perl_Client_CreateExpeditionFromTemplate(Client* self, uint32_t dz_template_id)
DynamicZone* Perl_Client_CreateExpeditionFromTemplate(Client* self, uint32_t dz_template_id)
{
return self->CreateExpeditionFromTemplate(dz_template_id);
}
@ -1875,7 +1875,7 @@ void Perl_Client_CreateTaskDynamicZone(Client* self, int task_id, perl::referenc
self->CreateTaskDynamicZone(task_id, dz);
}
Expedition* Perl_Client_GetExpedition(Client* self)
DynamicZone* Perl_Client_GetExpedition(Client* self)
{
return self->GetExpedition();
}
@ -1884,15 +1884,15 @@ perl::reference Perl_Client_GetExpeditionLockouts(Client* self)
{
perl::hash lockout_hash;
auto lockouts = self->GetExpeditionLockouts();
const auto& lockouts = self->GetDzLockouts();
for (const auto& lockout : lockouts)
{
if (!lockout_hash.exists(lockout.GetExpeditionName()))
if (!lockout_hash.exists(lockout.DzName()))
{
lockout_hash[lockout.GetExpeditionName()] = perl::reference(perl::hash());
lockout_hash[lockout.DzName()] = perl::reference(perl::hash());
}
perl::hash events = lockout_hash[lockout.GetExpeditionName()]; // nested
events[lockout.GetEventName()] = lockout.GetSecondsRemaining();
perl::hash events = lockout_hash[lockout.DzName()]; // nested
events[lockout.Event()] = lockout.GetSecondsRemaining();
}
return perl::reference(lockout_hash);
@ -1902,10 +1902,10 @@ perl::reference Perl_Client_GetExpeditionLockouts(Client* self, std::string expe
{
perl::hash event_hash;
auto lockouts = self->GetExpeditionLockouts(expedition_name);
auto lockouts = self->GetDzLockouts(expedition_name);
for (const auto& lockout : lockouts)
{
event_hash[lockout.GetEventName()] = lockout.GetSecondsRemaining();
event_hash[lockout.Event()] = lockout.GetSecondsRemaining();
}
return perl::reference(event_hash);
@ -1913,48 +1913,50 @@ perl::reference Perl_Client_GetExpeditionLockouts(Client* self, std::string expe
std::string Perl_Client_GetLockoutExpeditionUUID(Client* self, std::string expedition_name, std::string event_name)
{
auto lockout = self->GetExpeditionLockout(expedition_name, event_name);
return lockout ? lockout->GetExpeditionUUID() : std::string{};
auto lockout = self->GetDzLockout(expedition_name, event_name);
return lockout ? lockout->UUID() : std::string{};
}
void Perl_Client_AddExpeditionLockout(Client* self, std::string expedition_name, std::string event_name, uint32 seconds)
{
self->AddNewExpeditionLockout(expedition_name, event_name, seconds);
self->AddDzLockout(expedition_name, event_name, seconds);
}
void Perl_Client_AddExpeditionLockout(Client* self, std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid)
{
self->AddNewExpeditionLockout(expedition_name, event_name, seconds, uuid);
self->AddDzLockout(expedition_name, event_name, seconds, uuid);
}
void Perl_Client_AddExpeditionLockoutDuration(Client* self, std::string expedition_name, std::string event_name, int seconds)
{
self->AddExpeditionLockoutDuration(expedition_name, event_name, seconds, {}, true);
auto lockout = DzLockout::Create(expedition_name, event_name, seconds);
self->AddDzLockoutDuration(lockout, seconds, {}, true);
}
void Perl_Client_AddExpeditionLockoutDuration(Client* self, std::string expedition_name, std::string event_name, int seconds, std::string uuid)
{
self->AddExpeditionLockoutDuration(expedition_name, event_name, seconds, uuid, true);
auto lockout = DzLockout::Create(expedition_name, event_name, seconds, uuid);
self->AddDzLockoutDuration(lockout, seconds, uuid, true);
}
void Perl_Client_RemoveAllExpeditionLockouts(Client* self)
{
self->RemoveAllExpeditionLockouts({}, true);
self->RemoveDzLockouts({}, true);
}
void Perl_Client_RemoveAllExpeditionLockouts(Client* self, std::string expedition_name)
{
self->RemoveAllExpeditionLockouts(expedition_name, true);
self->RemoveDzLockouts(expedition_name, true);
}
void Perl_Client_RemoveExpeditionLockout(Client* self, std::string expedition_name, std::string event_name)
{
self->RemoveExpeditionLockout(expedition_name, event_name, true);
self->RemoveDzLockout(expedition_name, event_name, true);
}
bool Perl_Client_HasExpeditionLockout(Client* self, std::string expedition_name, std::string event_name)
{
return self->HasExpeditionLockout(expedition_name, event_name);
return self->HasDzLockout(expedition_name, event_name);
}
void Perl_Client_MovePCDynamicZone(Client* self, perl::scalar zone)
@ -3389,9 +3391,9 @@ void perl_register_client()
package.add("CountAugmentEquippedByID", &Perl_Client_CountAugmentEquippedByID);
package.add("CountItem", &Perl_Client_CountItem);
package.add("CountItemEquippedByID", &Perl_Client_CountItemEquippedByID);
package.add("CreateExpedition", (Expedition*(*)(Client*, perl::reference))&Perl_Client_CreateExpedition);
package.add("CreateExpedition", (Expedition*(*)(Client*, std::string, uint32, uint32, std::string, uint32, uint32))&Perl_Client_CreateExpedition);
package.add("CreateExpedition", (Expedition*(*)(Client*, std::string, uint32, uint32, std::string, uint32, uint32, bool))&Perl_Client_CreateExpedition);
package.add("CreateExpedition", (DynamicZone*(*)(Client*, perl::reference))&Perl_Client_CreateExpedition);
package.add("CreateExpedition", (DynamicZone*(*)(Client*, std::string, uint32, uint32, std::string, uint32, uint32))&Perl_Client_CreateExpedition);
package.add("CreateExpedition", (DynamicZone*(*)(Client*, std::string, uint32, uint32, std::string, uint32, uint32, bool))&Perl_Client_CreateExpedition);
package.add("CreateExpeditionFromTemplate", &Perl_Client_CreateExpeditionFromTemplate);
package.add("CreateTaskDynamicZone", &Perl_Client_CreateTaskDynamicZone);
package.add("DecreaseByID", &Perl_Client_DecreaseByID);

View File

@ -3,214 +3,209 @@
#ifdef EMBPERL_XS_CLASSES
#include "embperl.h"
#include "expedition.h"
#include "dynamic_zone.h"
#include "../common/zone_store.h"
#include "../common/global_define.h"
void Perl_Expedition_AddLockout(Expedition* self, std::string event_name, uint32_t seconds)
void Perl_Expedition_AddLockout(DynamicZone* self, std::string event_name, uint32_t seconds)
{
self->AddLockout(event_name, seconds);
}
void Perl_Expedition_AddLockoutDuration(Expedition* self, std::string event_name, int seconds)
void Perl_Expedition_AddLockoutDuration(DynamicZone* self, std::string event_name, int seconds)
{
self->AddLockoutDuration(event_name, seconds);
}
void Perl_Expedition_AddLockoutDuration(Expedition* self, std::string event_name, int seconds, bool members_only)
void Perl_Expedition_AddLockoutDuration(DynamicZone* self, std::string event_name, int seconds, bool members_only)
{
self->AddLockoutDuration(event_name, seconds, members_only);
}
void Perl_Expedition_AddReplayLockout(Expedition* self, uint32_t seconds)
void Perl_Expedition_AddReplayLockout(DynamicZone* self, uint32_t seconds)
{
self->AddReplayLockout(seconds);
self->AddLockout(DzLockout::ReplayTimer, seconds);
}
void Perl_Expedition_AddReplayLockoutDuration(Expedition* self, int seconds)
void Perl_Expedition_AddReplayLockoutDuration(DynamicZone* self, int seconds)
{
self->AddReplayLockoutDuration(seconds);
self->AddLockoutDuration(DzLockout::ReplayTimer, seconds);;
}
void Perl_Expedition_AddReplayLockoutDuration(Expedition* self, int seconds, bool members_only)
void Perl_Expedition_AddReplayLockoutDuration(DynamicZone* self, int seconds, bool members_only)
{
self->AddReplayLockoutDuration(seconds, members_only);
self->AddLockoutDuration(DzLockout::ReplayTimer, seconds, members_only);
}
uint32_t Perl_Expedition_GetDynamicZoneID(Expedition* self)
{
return self->GetDynamicZone()->GetID();
}
uint32_t Perl_Expedition_GetID(Expedition* self)
uint32_t Perl_Expedition_GetID(DynamicZone* self)
{
return self->GetID();
}
uint16_t Perl_Expedition_GetInstanceID(Expedition* self)
uint16_t Perl_Expedition_GetInstanceID(DynamicZone* self)
{
return self->GetDynamicZone()->GetInstanceID();
return self->GetInstanceID();
}
std::string Perl_Expedition_GetLeaderName(Expedition* self)
std::string Perl_Expedition_GetLeaderName(DynamicZone* self)
{
return self->GetLeaderName();
}
perl::reference Perl_Expedition_GetLockouts(Expedition* self)
perl::reference Perl_Expedition_GetLockouts(DynamicZone* self)
{
perl::hash table;
auto lockouts = self->GetLockouts();
const auto& lockouts = self->GetLockouts();
for (const auto& lockout : lockouts)
{
table[lockout.first] = lockout.second.GetSecondsRemaining();
table[lockout.Event()] = lockout.GetSecondsRemaining();
}
return perl::reference(table);
}
std::string Perl_Expedition_GetLootEventByNPCTypeID(Expedition* self, uint32_t npc_type_id)
std::string Perl_Expedition_GetLootEventByNPCTypeID(DynamicZone* self, uint32_t npc_type_id)
{
return self->GetLootEventByNPCTypeID(npc_type_id);
return self->GetLootEvent(npc_type_id, DzLootEvent::Type::NpcType);
}
std::string Perl_Expedition_GetLootEventBySpawnID(Expedition* self, uint32_t spawn_id)
std::string Perl_Expedition_GetLootEventBySpawnID(DynamicZone* self, uint32_t spawn_id)
{
return self->GetLootEventBySpawnID(spawn_id);
return self->GetLootEvent(spawn_id, DzLootEvent::Type::Entity);
}
uint32_t Perl_Expedition_GetMemberCount(Expedition* self)
uint32_t Perl_Expedition_GetMemberCount(DynamicZone* self)
{
return self->GetDynamicZone()->GetMemberCount();
return self->GetMemberCount();
}
perl::reference Perl_Expedition_GetMembers(Expedition* self)
perl::reference Perl_Expedition_GetMembers(DynamicZone* self)
{
perl::hash table;
for (const auto& member : self->GetDynamicZone()->GetMembers())
for (const auto& member : self->GetMembers())
{
table[member.name] = member.id;
}
return perl::reference(table);
}
std::string Perl_Expedition_GetName(Expedition* self)
std::string Perl_Expedition_GetName(DynamicZone* self)
{
return self->GetName();
}
uint32_t Perl_Expedition_GetSecondsRemaining(Expedition* self)
uint32_t Perl_Expedition_GetSecondsRemaining(DynamicZone* self)
{
return self->GetDynamicZone()->GetSecondsRemaining();
return self->GetSecondsRemaining();
}
std::string Perl_Expedition_GetUUID(Expedition* self)
std::string Perl_Expedition_GetUUID(DynamicZone* self)
{
return self->GetDynamicZone()->GetUUID();
return self->GetUUID();
}
uint16_t Perl_Expedition_GetZoneID(Expedition* self)
uint16_t Perl_Expedition_GetZoneID(DynamicZone* self)
{
return self->GetDynamicZone()->GetZoneID();
return self->GetZoneID();
}
std::string Perl_Expedition_GetZoneName(Expedition* self)
std::string Perl_Expedition_GetZoneName(DynamicZone* self)
{
return ZoneName(self->GetDynamicZone()->GetZoneID());
return ZoneName(self->GetZoneID());
}
uint32_t Perl_Expedition_GetZoneVersion(Expedition* self)
uint32_t Perl_Expedition_GetZoneVersion(DynamicZone* self)
{
return self->GetDynamicZone()->GetZoneVersion();
return self->GetZoneVersion();
}
bool Perl_Expedition_HasLockout(Expedition* self, std::string event_name)
bool Perl_Expedition_HasLockout(DynamicZone* self, std::string event_name)
{
return self->HasLockout(event_name);
}
bool Perl_Expedition_HasReplayLockout(Expedition* self)
bool Perl_Expedition_HasReplayLockout(DynamicZone* self)
{
return self->HasReplayLockout();
}
bool Perl_Expedition_IsLocked(Expedition* self)
bool Perl_Expedition_IsLocked(DynamicZone* self)
{
return self->IsLocked();
}
void Perl_Expedition_RemoveCompass(Expedition* self)
void Perl_Expedition_RemoveCompass(DynamicZone* self)
{
self->GetDynamicZone()->SetCompass(0, 0, 0, 0, true);
self->SetCompass(0, 0, 0, 0, true);
}
void Perl_Expedition_RemoveLockout(Expedition* self, std::string event_name)
void Perl_Expedition_RemoveLockout(DynamicZone* self, std::string event_name)
{
self->RemoveLockout(event_name);
}
void Perl_Expedition_SetCompass(Expedition* self, perl::scalar zone, float x, float y, float z)
void Perl_Expedition_SetCompass(DynamicZone* self, perl::scalar zone, float x, float y, float z)
{
uint32_t zone_id = zone.is_string() ? ZoneID(zone.c_str()) : zone.as<uint32_t>();
self->GetDynamicZone()->SetCompass(zone_id, x, y, z, true);
self->SetCompass(zone_id, x, y, z, true);
}
void Perl_Expedition_SetLocked(Expedition* self, bool locked)
void Perl_Expedition_SetLocked(DynamicZone* self, bool locked)
{
self->SetLocked(locked, ExpeditionLockMessage::None);
self->SetLocked(locked, true);
}
void Perl_Expedition_SetLocked(Expedition* self, bool locked, int lock_msg)
void Perl_Expedition_SetLocked(DynamicZone* self, bool locked, int lock_msg)
{
self->SetLocked(locked, static_cast<ExpeditionLockMessage>(lock_msg), true);
self->SetLocked(locked, true, static_cast<DzLockMsg>(lock_msg));
}
void Perl_Expedition_SetLocked(Expedition* self, bool locked, int lock_msg, uint32_t color)
void Perl_Expedition_SetLocked(DynamicZone* self, bool locked, int lock_msg, uint32_t color)
{
self->SetLocked(locked, static_cast<ExpeditionLockMessage>(lock_msg), true, color);
self->SetLocked(locked, true, static_cast<DzLockMsg>(lock_msg), color);
}
void Perl_Expedition_SetLootEventByNPCTypeID(Expedition* self, uint32_t npc_type_id, std::string event_name)
void Perl_Expedition_SetLootEventByNPCTypeID(DynamicZone* self, uint32_t npc_type_id, std::string event_name)
{
self->SetLootEventByNPCTypeID(npc_type_id, event_name);
self->SetLootEvent(npc_type_id, event_name, DzLootEvent::Type::NpcType);
}
void Perl_Expedition_SetLootEventBySpawnID(Expedition* self, uint32_t entity_id, std::string event_name)
void Perl_Expedition_SetLootEventBySpawnID(DynamicZone* self, uint32_t entity_id, std::string event_name)
{
self->SetLootEventBySpawnID(entity_id, event_name);
self->SetLootEvent(entity_id, event_name, DzLootEvent::Type::Entity);
}
void Perl_Expedition_SetReplayLockoutOnMemberJoin(Expedition* self, bool enable)
void Perl_Expedition_SetReplayLockoutOnMemberJoin(DynamicZone* self, bool enable)
{
self->SetReplayLockoutOnMemberJoin(enable, true);
self->SetReplayOnJoin(enable, true);
}
void Perl_Expedition_SetSafeReturn(Expedition* self, perl::scalar zone, float x, float y, float z, float heading)
void Perl_Expedition_SetSafeReturn(DynamicZone* self, perl::scalar zone, float x, float y, float z, float heading)
{
uint32_t zone_id = zone.is_string() ? ZoneID(zone.c_str()) : zone.as<uint32_t>();
self->GetDynamicZone()->SetSafeReturn(zone_id, x, y, z, heading, true);
self->SetSafeReturn(zone_id, x, y, z, heading, true);
}
void Perl_Expedition_SetSecondsRemaining(Expedition* self, uint32_t seconds_remaining)
void Perl_Expedition_SetSecondsRemaining(DynamicZone* self, uint32_t seconds_remaining)
{
self->GetDynamicZone()->SetSecondsRemaining(seconds_remaining);
self->SetSecondsRemaining(seconds_remaining);
}
void Perl_Expedition_SetSwitchID(Expedition* self, int dz_switch_id)
void Perl_Expedition_SetSwitchID(DynamicZone* self, int dz_switch_id)
{
self->GetDynamicZone()->SetSwitchID(dz_switch_id, true);
self->SetSwitchID(dz_switch_id, true);
}
void Perl_Expedition_SetZoneInLocation(Expedition* self, float x, float y, float z, float heading)
void Perl_Expedition_SetZoneInLocation(DynamicZone* self, float x, float y, float z, float heading)
{
self->GetDynamicZone()->SetZoneInLocation(x, y, z, heading, true);
self->SetZoneInLocation(x, y, z, heading, true);
}
void Perl_Expedition_UpdateLockoutDuration(Expedition* self, std::string event_name, uint32_t seconds)
void Perl_Expedition_UpdateLockoutDuration(DynamicZone* self, std::string event_name, uint32_t seconds)
{
self->UpdateLockoutDuration(event_name, seconds);
}
void Perl_Expedition_UpdateLockoutDuration(Expedition* self, std::string event_name, uint32_t seconds, bool members_only)
void Perl_Expedition_UpdateLockoutDuration(DynamicZone* self, std::string event_name, uint32_t seconds, bool members_only)
{
self->UpdateLockoutDuration(event_name, seconds, members_only);
}
@ -219,14 +214,14 @@ void perl_register_expedition()
{
perl::interpreter perl(PERL_GET_THX);
auto package = perl.new_class<Expedition>("Expedition");
auto package = perl.new_class<DynamicZone>("Expedition");
package.add("AddLockout", &Perl_Expedition_AddLockout);
package.add("AddLockoutDuration", (void(*)(Expedition*, std::string, int))&Perl_Expedition_AddLockoutDuration);
package.add("AddLockoutDuration", (void(*)(Expedition*, std::string, int, bool))&Perl_Expedition_AddLockoutDuration);
package.add("AddLockoutDuration", (void(*)(DynamicZone*, std::string, int))&Perl_Expedition_AddLockoutDuration);
package.add("AddLockoutDuration", (void(*)(DynamicZone*, std::string, int, bool))&Perl_Expedition_AddLockoutDuration);
package.add("AddReplayLockout", &Perl_Expedition_AddReplayLockout);
package.add("AddReplayLockoutDuration", (void(*)(Expedition*, int))&Perl_Expedition_AddReplayLockoutDuration);
package.add("AddReplayLockoutDuration", (void(*)(Expedition*, int, bool))&Perl_Expedition_AddReplayLockoutDuration);
package.add("GetDynamicZoneID", &Perl_Expedition_GetDynamicZoneID);
package.add("AddReplayLockoutDuration", (void(*)(DynamicZone*, int))&Perl_Expedition_AddReplayLockoutDuration);
package.add("AddReplayLockoutDuration", (void(*)(DynamicZone*, int, bool))&Perl_Expedition_AddReplayLockoutDuration);
package.add("GetDynamicZoneID", &Perl_Expedition_GetID);
package.add("GetID", &Perl_Expedition_GetID);
package.add("GetInstanceID", &Perl_Expedition_GetInstanceID);
package.add("GetLeaderName", &Perl_Expedition_GetLeaderName);
@ -247,9 +242,9 @@ void perl_register_expedition()
package.add("RemoveCompass", &Perl_Expedition_RemoveCompass);
package.add("RemoveLockout", &Perl_Expedition_RemoveLockout);
package.add("SetCompass", &Perl_Expedition_SetCompass);
package.add("SetLocked", (void(*)(Expedition*, bool))&Perl_Expedition_SetLocked);
package.add("SetLocked", (void(*)(Expedition*, bool, int))&Perl_Expedition_SetLocked);
package.add("SetLocked", (void(*)(Expedition*, bool, int, uint32_t))&Perl_Expedition_SetLocked);
package.add("SetLocked", (void(*)(DynamicZone*, bool))&Perl_Expedition_SetLocked);
package.add("SetLocked", (void(*)(DynamicZone*, bool, int))&Perl_Expedition_SetLocked);
package.add("SetLocked", (void(*)(DynamicZone*, bool, int, uint32_t))&Perl_Expedition_SetLocked);
package.add("SetLootEventByNPCTypeID", &Perl_Expedition_SetLootEventByNPCTypeID);
package.add("SetLootEventBySpawnID", &Perl_Expedition_SetLootEventBySpawnID);
package.add("SetReplayLockoutOnMemberJoin", &Perl_Expedition_SetReplayLockoutOnMemberJoin);
@ -257,8 +252,8 @@ void perl_register_expedition()
package.add("SetSecondsRemaining", &Perl_Expedition_SetSecondsRemaining);
package.add("SetSwitchID", &Perl_Expedition_SetSwitchID);
package.add("SetZoneInLocation", &Perl_Expedition_SetZoneInLocation);
package.add("UpdateLockoutDuration", (void(*)(Expedition*, std::string, uint32_t))&Perl_Expedition_UpdateLockoutDuration);
package.add("UpdateLockoutDuration", (void(*)(Expedition*, std::string, uint32_t, bool))&Perl_Expedition_UpdateLockoutDuration);
package.add("UpdateLockoutDuration", (void(*)(DynamicZone*, std::string, uint32_t))&Perl_Expedition_UpdateLockoutDuration);
package.add("UpdateLockoutDuration", (void(*)(DynamicZone*, std::string, uint32_t, bool))&Perl_Expedition_UpdateLockoutDuration);
}
void perl_register_expedition_lock_messages()
@ -266,9 +261,9 @@ void perl_register_expedition_lock_messages()
perl::interpreter perl(PERL_GET_THX);
auto package = perl.new_package("ExpeditionLockMessage");
package.add_const("None", static_cast<int>(ExpeditionLockMessage::None));
package.add_const("Close", static_cast<int>(ExpeditionLockMessage::Close));
package.add_const("Begin", static_cast<int>(ExpeditionLockMessage::Begin));
package.add_const("None", static_cast<int>(DzLockMsg::None));
package.add_const("Close", static_cast<int>(DzLockMsg::Close));
package.add_const("Begin", static_cast<int>(DzLockMsg::Begin));
}
#endif //EMBPERL_XS_CLASSES

View File

@ -129,12 +129,12 @@ Client* Perl_Group_GetMember(Group* self, int member_index) // @categories Accou
bool Perl_Group_DoesAnyMemberHaveExpeditionLockout(Group* self, std::string expedition_name, std::string event_name)
{
return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name);
return self->AnyMemberHasDzLockout(expedition_name, event_name);
}
bool Perl_Group_DoesAnyMemberHaveExpeditionLockout(Group* self, std::string expedition_name, std::string event_name, int max_check_count)
{
return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count);
return self->AnyMemberHasDzLockout(expedition_name, event_name); // max_check_count deprecated
}
uint32_t Perl_Group_GetLowestLevel(Group* self) // @categories Script Utility, Group

View File

@ -139,12 +139,12 @@ Client* Perl_Raid_GetMember(Raid* self, int member_index) // @categories Raid
bool Perl_Raid_DoesAnyMemberHaveExpeditionLockout(Raid* self, std::string expedition_name, std::string event_name)
{
return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name);
return self->AnyMemberHasDzLockout(expedition_name, event_name);
}
bool Perl_Raid_DoesAnyMemberHaveExpeditionLockout(Raid* self, std::string expedition_name, std::string event_name, int max_check_count)
{
return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count);
return self->AnyMemberHasDzLockout(expedition_name, event_name); // max_check_count deprecated
}
int Perl_Raid_GetGroupNumber(Raid* self, int member_index) {

View File

@ -18,14 +18,15 @@
#include "../common/strings.h"
#include "../common/events/player_event_logs.h"
#include "../common/repositories/character_expedition_lockouts_repository.h"
#include "../common/repositories/raid_details_repository.h"
#include "../common/repositories/raid_members_repository.h"
#include "../common/raid.h"
#include "client.h"
#include "dynamic_zone.h"
#include "entity.h"
#include "expedition.h"
#include "groups.h"
#include "mob.h"
#include "raids.h"
@ -2138,28 +2139,21 @@ std::vector<RaidMember> Raid::GetMembers() const
return raid_members;
}
bool Raid::DoesAnyMemberHaveExpeditionLockout(const std::string& expedition_name, const std::string& event_name, int max_check_count)
bool Raid::AnyMemberHasDzLockout(const std::string& expedition, const std::string& event)
{
auto raid_members = GetMembers();
if (max_check_count > 0) {
// priority is leader, group number, then ungrouped members
std::sort(raid_members.begin(), raid_members.end(),
[&](const RaidMember& lhs, const RaidMember& rhs) {
if (lhs.is_raid_leader) {
return true;
} else if (rhs.is_raid_leader) {
return false;
}
return lhs.group_number < rhs.group_number;
});
raid_members.resize(max_check_count);
std::vector<std::string> names;
for (const auto& mbr : members)
{
if (!mbr.member && !mbr.is_bot && mbr.member_name[0])
{
names.emplace_back(mbr.member_name); // out of zone member
}
else if (mbr.member && !mbr.is_bot && mbr.member->HasDzLockout(expedition, event))
{
return true;
}
}
return std::any_of(raid_members.begin(), raid_members.end(), [&](const RaidMember& raid_member) {
return Expedition::HasLockoutByCharacterName(raid_member.member_name, expedition_name, event_name);
});
return !CharacterExpeditionLockoutsRepository::GetLockouts(database, names, expedition, event).empty();
}
Mob* Raid::GetRaidMainAssistOne()

View File

@ -271,7 +271,7 @@ public:
void QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required = true, bool ignore_sender = true, float distance = 0, bool group_only = true);
bool DoesAnyMemberHaveExpeditionLockout(const std::string& expedition_name, const std::string& event_name, int max_check_count = 0);
bool AnyMemberHasDzLockout(const std::string& expedition, const std::string& event);
std::vector<RaidMember> GetMembers() const;
std::vector<RaidMember> GetRaidGroupMembers(uint32 gid);

View File

@ -328,42 +328,42 @@
#define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1!
#define TASK_UPDATED 3471 //Your task '%1' has been updated.
#define YOU_ASSIGNED_TASK 3472 //You have been assigned the task '%1'.
#define EXPEDITION_YOU_BELONG 3500 //You cannot create this expedition since you already belong to another.
#define EXPEDITION_YOU_PLAYED_HERE 3501 //You cannot create this expedition for another %1d:%2h:%3m since you have recently played here.
#define REQUIRED_PLAYER_COUNT 3503 //You do not meet the player count requirement. You have %1 players. You must have at least %2 and no more than %3.
#define EXPEDITION_REPLAY_TIMER 3504 //%1 cannot be added to this expedition for another %2D:%3H:%4M since they have recently played in this area.
#define EXPEDITION_AVAILABLE 3507 //%1 is now available to you.
#define DZ_YOU_BELONG 3500 //You cannot create this expedition since you already belong to another.
#define DZ_REPLAY_YOU 3501 //You cannot create this expedition for another %1d:%2h:%3m since you have recently played here.
#define DZ_PLAYER_COUNT 3503 //You do not meet the player count requirement. You have %1 players. You must have at least %2 and no more than %3.
#define DZ_REPLAY_OTHER 3504 //%1 cannot be added to this expedition for another %2D:%3H:%4M since they have recently played in this area.
#define DZ_AVAILABLE 3507 //%1 is now available to you.
#define DZADD_INVITE 3508 //Sending an invitation to: %1.
#define DZ_PREVENT_ENTERING 3510 //A strange magical presence prevents you from entering. It's too dangerous to enter at the moment.
#define DZADD_INVITE_FAIL 3511 //%1 could not be invited to join you.
#define UNABLE_RETRIEVE_LEADER 3512 //Unable to retrieve information on the leader to check permissions.
#define EXPEDITION_NOT_LEADER 3513 //You are not the expedition leader, only %1 can issue this command.
#define EXPEDITION_NOT_MEMBER 3514 //%1 is not a member of this expedition.
#define EXPEDITION_REMOVED 3516 //%1 has been removed from %2.
#define DZ_NO_LEADER_INFO 3512 //Unable to retrieve information on the leader to check permissions.
#define DZ_NOT_LEADER 3513 //You are not the expedition leader, only %1 can issue this command.
#define DZ_NOT_MEMBER 3514 //%1 is not a member of this expedition.
#define DZ_REMOVED 3516 //%1 has been removed from %2.
#define DZSWAP_INVITE 3517 //Sending an invitation to: %1. They must accept in order to swap party members.
#define DZMAKELEADER_NOT_ONLINE 3518 //%1 is not currently online. You can only transfer leadership to an online member of the expedition you are in.
#define DZLIST_REPLAY_TIMER 3519 //You have %1d:%2h:%3m remaining until you may enter %4.
#define DZMAKELEADER_NAME 3520 //%1 has been made the leader for this expedition.
#define DZMAKELEADER_YOU 3521 //You have been made the leader of this expedition.
#define EXPEDITION_INVITE_ACCEPTED 3522 //%1 has accepted your offer to join your expedition.
#define EXPEDITION_MEMBER_ADDED 3523 //%1 has been added to %2.
#define EXPEDITION_INVITE_ERROR 3524 //%1 accepted your offer to join your expedition but could not due to error(s).
#define EXPEDITION_INVITE_DECLINED 3525 //%1 has declined your offer to join your expedition.
#define EXPEDITION_ASKED_TO_JOIN 3527 //%1 has asked you to join the expedition: %2. Would you like to join?
#define DYNAMICZONE_WAY_IS_BLOCKED 3528 //The way is blocked to you. Perhaps you would be able to enter if there was a reason to come here.
#define EXPEDITION_NO_TIMERS 3529 //You have no outstanding timers.
#define EXPEDITION_MIN_REMAIN 3551 //You only have %1 minutes remaining before this expedition comes to an end.
#define EXPEDITION_LEADER 3552 //Expedition Leader: %1
#define EXPEDITION_MEMBERS 3553 //Expedition Members: %1
#define EXPEDITION_EVENT_TIMER 3561 //%1 cannot be added to this expedition since they have recently experienced %2. They must wait another %3D:%4H:%5M until they can experience it again. They may be added to the expedition later, once %2 has been completed.
#define DZ_LEADER_OFFLINE 3518 //%1 is not currently online. You can only transfer leadership to an online member of the expedition you are in.
#define DZ_TIMER 3519 //You have %1d:%2h:%3m remaining until you may enter %4.
#define DZ_LEADER_NAME 3520 //%1 has been made the leader for this expedition.
#define DZ_LEADER_YOU 3521 //You have been made the leader of this expedition.
#define DZ_INVITE_ACCEPTED 3522 //%1 has accepted your offer to join your expedition.
#define DZ_ADDED 3523 //%1 has been added to %2.
#define DZ_INVITE_ERROR 3524 //%1 accepted your offer to join your expedition but could not due to error(s).
#define DZ_INVITE_DECLINED 3525 //%1 has declined your offer to join your expedition.
#define DZ_INVITED 3527 //%1 has asked you to join the expedition: %2. Would you like to join?
#define DZ_WAY_IS_BLOCKED 3528 //The way is blocked to you. Perhaps you would be able to enter if there was a reason to come here.
#define DZ_NO_TIMERS 3529 //You have no outstanding timers.
#define DZ_MINUTES_REMAIN 3551 //You only have %1 minutes remaining before this expedition comes to an end.
#define DZ_LEADER 3552 //Expedition Leader: %1
#define DZ_MEMBERS 3553 //Expedition Members: %1
#define DZ_EVENT_TIMER 3561 //%1 cannot be added to this expedition since they have recently experienced %2. They must wait another %3D:%4H:%5M until they can experience it again. They may be added to the expedition later, once %2 has been completed.
#define LOOT_NOT_ALLOWED 3562 //You are not allowed to loot the item: %1.
#define DZ_UNABLE_RETRIEVE_LEADER 3583 //Unable to retrieve dynamic zone leader to check permissions.
#define DZADD_NOT_ALLOWING 3585 //The expedition is not allowing players to be added.
#define DZADD_NOT_ONLINE 3586 //%1 is not currently online. A player needs to be online to be added to a Dynamic Zone
#define DZADD_EXCEED_MAX 3587 //You can not add another player since you currently have the maximum number of players allowed (%1) in this zone.
#define DZADD_ALREADY_PART 3588 //You can not add %1 since they are already part of this zone.
#define DZADD_LEAVE_ZONE_FIRST 3589 //You can not add %1 since they first need to leave the zone before being allowed back in.
#define DZADD_ALREADY_ASSIGNED 3590 //%1 can not be added to this dynamic zone since they are already assigned to another dynamic zone.
#define DZADD_LEAVE_ZONE 3589 //You can not add %1 since they first need to leave the zone before being allowed back in.
#define DZADD_ALREADY_OTHER 3590 //%1 can not be added to this dynamic zone since they are already assigned to another dynamic zone.
#define DZADD_REPLAY_TIMER 3591 //%1 can not be added to this dynamic zone for another %2D:%3H:%4M since they have recently played this zone.
#define DZADD_EVENT_TIMER 3592 //%1 can not be added to this dynamic zone since they have recently experienced %2. They must wait for another %3D:%4H:%5M, or until event %2 has occurred.
#define DZADD_PENDING 3593 //%1 currently has an outstanding invitation to join this Dynamic Zone.

View File

@ -2288,12 +2288,10 @@ void ClientTaskState::CreateTaskDynamicZone(Client* client, int task_id, Dynamic
dz_request.SetMinPlayers(task->min_players);
dz_request.SetMaxPlayers(task->max_players);
// a task might create a dz from an objective so override dz duration to time remaining
// live probably creates the dz with the shared task and just adds members for objectives
// a task might create a dz from an element so override dz duration to time remaining
std::chrono::seconds seconds(TaskTimeLeft(task_id));
if (task->duration == 0 || seconds.count() < 0)
{
// todo: maybe add a rule for duration
// cap unlimited duration tasks so instance isn't held indefinitely
// expected behavior is to re-acquire any unlimited tasks that have an expired dz
seconds = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::hours(24));
@ -2301,32 +2299,21 @@ void ClientTaskState::CreateTaskDynamicZone(Client* client, int task_id, Dynamic
dz_request.SetDuration(static_cast<uint32_t>(seconds.count()));
if (task->type == TaskType::Task || task->type == TaskType::Quest)
{
if (task->type == TaskType::Task) {
dz_request.SetType(DynamicZoneType::Task);
} else {
dz_request.SetType(DynamicZoneType::Quest);
}
// todo: can enable non-shared task dz creation when dz ids are persisted for them (db also)
//DynamicZoneMember solo_member{ client->CharacterID(), client->GetCleanName() };
//DynamicZone::CreateNew(dz_request, { solo_member });
}
else if (task->type == TaskType::Shared)
if (task->type == TaskType::Shared)
{
dz_request.SetType(DynamicZoneType::Mission);
// shared task missions are created in world
EQ::Net::DynamicPacket dyn_pack = dz_request.GetSerializedDzPacket();
std::ostringstream ss = dz_request.GetSerialized();
std::string_view sv = ss.view();
auto pack_size = sizeof(ServerSharedTaskCreateDynamicZone_Struct) + dyn_pack.Length();
auto pack_size = sizeof(ServerSharedTaskCreateDynamicZone_Struct) + sv.size();
auto pack = std::make_unique<ServerPacket>(ServerOP_SharedTaskCreateDynamicZone, static_cast<uint32_t>(pack_size));
auto buf = reinterpret_cast<ServerSharedTaskCreateDynamicZone_Struct*>(pack->pBuffer);
buf->source_character_id = client->CharacterID();
buf->task_id = task_id;
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length());
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length());
buf->cereal_size = static_cast<uint32_t>(sv.size());
memcpy(buf->cereal_data, sv.data(), sv.size());
worldserver.SendPacket(pack.get());
}

View File

@ -40,8 +40,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "client.h"
#include "command.h"
#include "corpse.h"
#include "dynamic_zone.h"
#include "entity.h"
#include "expedition.h"
#include "quest_parser_collection.h"
#include "guild_mgr.h"
#include "mob.h"
@ -3601,20 +3601,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
break;
}
case ServerOP_ExpeditionCreate:
case ServerOP_ExpeditionLockout:
case ServerOP_ExpeditionLockoutDuration:
case ServerOP_ExpeditionLockState:
case ServerOP_ExpeditionReplayOnJoin:
case ServerOP_ExpeditionDzAddPlayer:
case ServerOP_ExpeditionDzMakeLeader:
case ServerOP_ExpeditionCharacterLockout:
{
Expedition::HandleWorldMessage(pack);
break;
}
case ServerOP_DzCreated:
case ServerOP_DzDeleted:
case ServerOP_DzAddPlayer:
case ServerOP_DzMakeLeader:
case ServerOP_DzAddRemoveMember:
case ServerOP_DzSwapMembers:
case ServerOP_DzRemoveAllMembers:
@ -3628,6 +3618,11 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
case ServerOP_DzLeaderChanged:
case ServerOP_DzExpireWarning:
case ServerOP_DzMovePC:
case ServerOP_DzLock:
case ServerOP_DzReplayOnJoin:
case ServerOP_DzLockout:
case ServerOP_DzLockoutDuration:
case ServerOP_DzCharacterLockout:
{
DynamicZone::HandleWorldMessage(pack);
break;

View File

@ -36,7 +36,7 @@
#include "../common/strings.h"
#include "../common/eqemu_logsys.h"
#include "expedition.h"
#include "dynamic_zone.h"
#include "guild_mgr.h"
#include "map.h"
#include "npc.h"
@ -1161,7 +1161,6 @@ bool Zone::Init(bool is_static) {
LoadDynamicZoneTemplates();
DynamicZone::CacheAllFromDatabase();
Expedition::CacheAllFromDatabase();
content_db.LoadGlobalLoot();
@ -1622,7 +1621,7 @@ bool Zone::Process() {
if (minutes_warning > 0)
{
// expedition expire warnings are handled by world
auto expedition = Expedition::FindCachedExpeditionByZoneInstance(GetZoneID(), GetInstanceID());
auto expedition = DynamicZone::FindExpeditionByZone(GetZoneID(), GetInstanceID());
if (!expedition)
{
entity_list.ExpeditionWarning(minutes_warning);

View File

@ -93,7 +93,6 @@ struct ZoneEXPModInfo {
};
class Client;
class Expedition;
class Map;
class Mob;
class WaterMap;
@ -236,7 +235,6 @@ public:
std::vector<GridEntriesRepository::GridEntries> zone_grid_entries;
std::unordered_map<uint32, std::unique_ptr<DynamicZone>> dynamic_zone_cache;
std::unordered_map<uint32, std::unique_ptr<Expedition>> expedition_cache;
std::unordered_map<uint32, DynamicZoneTemplatesRepository::DynamicZoneTemplates> dz_template_cache;
std::unordered_map<uint32, EXPModifier> exp_modifiers;

View File

@ -21,7 +21,7 @@
#include "../common/rulesys.h"
#include "../common/strings.h"
#include "expedition.h"
#include "dynamic_zone.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
@ -495,13 +495,12 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc
if(GetPet())
entity_list.RemoveFromHateLists(GetPet());
if (GetPendingExpeditionInviteID() != 0)
if (GetPendingDzInviteID() != 0)
{
// live re-invites if client zoned with a pending invite, save pending invite info in world
auto expedition = Expedition::FindCachedExpeditionByID(GetPendingExpeditionInviteID());
if (expedition)
if (auto dz = DynamicZone::FindDynamicZoneByID(GetPendingDzInviteID(), DynamicZoneType::Expedition))
{
expedition->SendWorldPendingInvite(m_pending_expedition_invite, GetName());
dz->SendWorldPendingInvite(m_dz_invite, GetName());
}
}