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

View File

@ -6812,7 +6812,32 @@ ALTER TABLE `guild_bank`
ALTER TABLE `guild_bank` ALTER TABLE `guild_bank`
ADD INDEX `guild_id` (`guild_id`); 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 // -- template; copy/paste this when you need to create a new entry
// ManifestEntry{ // ManifestEntry{
// .version = 9228, // .version = 9228,

View File

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

View File

@ -1,11 +1,13 @@
#include "dynamic_zone_base.h" #include "dynamic_zone_base.h"
#include "database.h" #include "database.h"
#include "eqemu_logsys.h" #include "eqemu_logsys.h"
#include "repositories/instance_list_repository.h"
#include "repositories/instance_list_player_repository.h"
#include "rulesys.h" #include "rulesys.h"
#include "servertalk.h" #include "servertalk.h"
#include "util/uuid.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) DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry)
{ {
@ -93,13 +95,15 @@ void DynamicZoneBase::LoadRepositoryResult(DynamicZonesRepository::DynamicZoneIn
m_zonein.y = dz_entry.zone_in_y; m_zonein.y = dz_entry.zone_in_y;
m_zonein.z = dz_entry.zone_in_z; m_zonein.z = dz_entry.zone_in_z;
m_zonein.heading = dz_entry.zone_in_heading; 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 // instance_list portion
m_zone_id = dz_entry.zone; m_zone_id = dz_entry.zone;
m_zone_version = dz_entry.version; m_zone_version = dz_entry.version;
m_start_time = std::chrono::system_clock::from_time_t(dz_entry.start_time); m_start_time = std::chrono::system_clock::from_time_t(dz_entry.start_time);
m_duration = std::chrono::seconds(dz_entry.duration); 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; m_expire_time = m_start_time + m_duration;
} }
@ -119,37 +123,40 @@ void DynamicZoneBase::AddMemberFromRepositoryResult(
uint32_t DynamicZoneBase::SaveToDatabase() uint32_t DynamicZoneBase::SaveToDatabase()
{ {
LogDynamicZonesDetail("Saving dz instance [{}] to database", m_instance_id); LogDynamicZonesDetail("Saving dz instance [{}] to database", m_instance_id);
if (m_instance_id == 0)
if (m_instance_id != 0)
{ {
auto insert_dz = DynamicZonesRepository::NewEntity(); return 0;
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;
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) bool DynamicZoneBase::AddMember(const DynamicZoneMember& add_member)
@ -196,10 +203,9 @@ bool DynamicZoneBase::RemoveMember(const DynamicZoneMember& remove_member)
return true; return true;
} }
bool DynamicZoneBase::SwapMember( bool DynamicZoneBase::SwapMember(const DynamicZoneMember& add_member, const std::string& remove_name)
const DynamicZoneMember& add_member, const std::string& remove_char_name)
{ {
auto remove_member = GetMemberData(remove_char_name); auto remove_member = GetMemberData(remove_name);
if (!add_member.IsValid() || !remove_member.IsValid()) if (!add_member.IsValid() || !remove_member.IsValid())
{ {
return false; return false;
@ -230,9 +236,18 @@ void DynamicZoneBase::RemoveAllMembers()
void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members) void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
{ {
if (members.empty())
{
return;
}
LogDynamicZonesDetail("Saving [{}] member(s) for dz [{}]", members.size(), m_id); LogDynamicZonesDetail("Saving [{}] member(s) for dz [{}]", members.size(), m_id);
m_members = members; 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 // the lower level instance_list_players needs to be kept updated as well
std::vector<DynamicZoneMembersRepository::DynamicZoneMembers> insert_members; std::vector<DynamicZoneMembersRepository::DynamicZoneMembers> insert_members;
@ -242,12 +257,12 @@ void DynamicZoneBase::SaveMembers(const std::vector<DynamicZoneMember>& members)
DynamicZoneMembersRepository::DynamicZoneMembers member_entry{}; DynamicZoneMembersRepository::DynamicZoneMembers member_entry{};
member_entry.dynamic_zone_id = m_id; member_entry.dynamic_zone_id = m_id;
member_entry.character_id = member.id; member_entry.character_id = member.id;
insert_members.emplace_back(member_entry); insert_members.push_back(member_entry);
InstanceListPlayerRepository::InstanceListPlayer player_entry; InstanceListPlayerRepository::InstanceListPlayer player_entry{};
player_entry.id = static_cast<int>(m_instance_id); player_entry.id = m_instance_id;
player_entry.charid = static_cast<int>(member.id); player_entry.charid = member.id;
insert_players.emplace_back(player_entry); insert_players.push_back(player_entry);
} }
DynamicZoneMembersRepository::InsertOrUpdateMany(GetDatabase(), insert_members); 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 uint32_t DynamicZoneBase::GetSecondsRemaining() const
{ {
auto remaining = std::chrono::duration_cast<std::chrono::seconds>(GetDurationRemaining()).count(); 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()); ), 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(), return std::any_of(m_members.begin(), m_members.end(),
[&](const DynamicZoneMember& member) { return member.id == character_id; }); [&](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(), return std::any_of(m_members.begin(), m_members.end(),
[&](const DynamicZoneMember& member) { [&](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; std::ostringstream ss = GetSerialized();
dyn_pack.PutSerialize(0, *this); std::string_view sv = ss.view();
LogDynamicZonesDetail("Serialized server dz size [{}]", dyn_pack.Length()); auto pack_size = sizeof(ServerDzCreate_Struct) + sv.size();
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 = std::make_unique<ServerPacket>(ServerOP_DzCreated, static_cast<uint32_t>(pack_size)); auto pack = std::make_unique<ServerPacket>(ServerOP_DzCreated, static_cast<uint32_t>(pack_size));
auto buf = reinterpret_cast<ServerDzCreateSerialized_Struct*>(pack->pBuffer); auto buf = reinterpret_cast<ServerDzCreate_Struct*>(pack->pBuffer);
buf->origin_zone_id = origin_zone_id; buf->origin_zone_id = zone_id;
buf->origin_instance_id = origin_instance_id; buf->origin_instance_id = instance_id;
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length()); buf->dz_id = GetID();
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());
return pack; return pack;
} }
void DynamicZoneBase::LoadSerializedDzPacket(char* cereal_data, uint32_t cereal_size) std::ostringstream DynamicZoneBase::GetSerialized()
{ {
LogDynamicZonesDetail("Deserializing server dz size [{}]", cereal_size); std::ostringstream ss;
EQ::Util::MemoryStreamReader ss(cereal_data, cereal_size); 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); cereal::BinaryInputArchive archive(ss);
archive(*this); archive(*this);
} }
@ -647,3 +699,180 @@ void DynamicZoneBase::LoadTemplate(const DynamicZoneTemplatesRepository::Dynamic
m_zonein.z = dz_template.zone_in_z; m_zonein.z = dz_template.zone_in_z;
m_zonein.heading = dz_template.zone_in_h; 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 #ifndef COMMON_DYNAMIC_ZONE_BASE_H
#define COMMON_DYNAMIC_ZONE_BASE_H #define COMMON_DYNAMIC_ZONE_BASE_H
#include "dynamic_zone_lockout.h"
#include "eq_constants.h" #include "eq_constants.h"
#include "net/packet.h"
#include "repositories/dynamic_zones_repository.h" #include "repositories/dynamic_zones_repository.h"
#include "repositories/dynamic_zone_members_repository.h" #include "repositories/dynamic_zone_members_repository.h"
#include "repositories/dynamic_zone_templates_repository.h" #include "repositories/dynamic_zone_templates_repository.h"
@ -10,12 +10,40 @@
#include <chrono> #include <chrono>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <span>
#include <string> #include <string>
#include <vector> #include <vector>
class Database; class Database;
class ServerPacket; 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 struct DynamicZoneMember
{ {
uint32_t id = 0; uint32_t id = 0;
@ -93,6 +121,7 @@ public:
const std::string& GetName() const { return m_name; } const std::string& GetName() const { return m_name; }
const std::string& GetUUID() const { return m_uuid; } const std::string& GetUUID() const { return m_uuid; }
const DynamicZoneMember& GetLeader() const { return m_leader; } 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 std::vector<DynamicZoneMember>& GetMembers() const { return m_members; }
const DynamicZoneLocation& GetCompassLocation() const { return m_compass; } const DynamicZoneLocation& GetCompassLocation() const { return m_compass; }
const DynamicZoneLocation& GetSafeReturnLocation() const { return m_safereturn; } const DynamicZoneLocation& GetSafeReturnLocation() const { return m_safereturn; }
@ -104,31 +133,34 @@ public:
uint32_t GetDatabaseMemberCount(); uint32_t GetDatabaseMemberCount();
DynamicZoneMember GetMemberData(uint32_t character_id); DynamicZoneMember GetMemberData(uint32_t character_id);
DynamicZoneMember GetMemberData(const std::string& character_name); 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 HasDatabaseMember(uint32_t character_id);
bool HasMember(uint32_t character_id); bool HasMember(uint32_t character_id) const;
bool HasMember(const std::string& character_name); bool HasMember(const std::string& character_name) const;
bool HasMembers() const { return !m_members.empty(); } bool HasMembers() const { return !m_members.empty(); }
bool HasZoneInLocation() const { return m_has_zonein; } 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 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 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 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; } 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 LoadTemplate(const DynamicZoneTemplatesRepository::DynamicZoneTemplates& dz_template);
void RemoveAllMembers(); void RemoveAllMembers();
bool RemoveMember(uint32_t character_id); bool RemoveMember(uint32_t character_id);
bool RemoveMember(const std::string& character_name); bool RemoveMember(const std::string& character_name);
bool RemoveMember(const DynamicZoneMember& remove_member); bool RemoveMember(const DynamicZoneMember& remove_member);
void SaveMembers(const std::vector<DynamicZoneMember>& members);
void SetCompass(const DynamicZoneLocation& location, bool update_db = false); 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 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 SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
void SetLeader(const DynamicZoneMember& leader, bool update_db = false); 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 SetMaxPlayers(uint32_t max_players) { m_max_players = max_players; }
void SetMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status); void SetMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status);
void SetMinPlayers(uint32_t min_players) { m_min_players = min_players; } void SetMinPlayers(uint32_t min_players) { m_min_players = min_players; }
void SetName(const std::string& name) { m_name = name; } 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(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 SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false);
void SetSwitchID(int dz_switch_id, bool update_db = false); void 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 SetUUID(std::string uuid) { m_uuid = std::move(uuid); }
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false); void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
void SetZoneInLocation(float x, float y, float z, float heading, bool update_db = false); 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: protected:
virtual uint16_t GetCurrentInstanceID() { return 0; } virtual uint16_t GetCurrentInstanceID() const { return 0; }
virtual uint16_t GetCurrentZoneID() { return 0; } virtual uint16_t GetCurrentZoneID() const { return 0; }
virtual Database& GetDatabase() = 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 ProcessCompassChange(const DynamicZoneLocation& location) { m_compass = location; }
virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed); virtual void ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed);
virtual bool ProcessMemberStatusChange(uint32_t member_id, DynamicZoneMemberStatus status); virtual bool ProcessMemberStatusChange(uint32_t character_id, DynamicZoneMemberStatus status);
virtual void ProcessRemoveAllMembers(bool silent = false) { m_members.clear(); } virtual void ProcessRemoveAllMembers() { m_members.clear(); }
virtual void ProcessSetSwitchID(int dz_switch_id) { m_dz_switch_id = dz_switch_id; } virtual void ProcessSetSwitchID(int dz_switch_id) { m_dz_switch_id = dz_switch_id; }
virtual bool SendServerPacket(ServerPacket* packet) = 0; virtual bool SendServerPacket(ServerPacket* packet) = 0;
void AddLockout(const DzLockout& lockout, bool members_only = false);
void AddInternalMember(const DynamicZoneMember& member); void AddInternalMember(const DynamicZoneMember& member);
uint32_t Create(); uint32_t Create();
uint32_t CreateInstance(); uint32_t CreateInstance();
void LoadRepositoryResult(DynamicZonesRepository::DynamicZoneInstance&& dz_entry); void LoadRepositoryResult(DynamicZonesRepository::DynamicZoneInstance&& dz_entry);
void RemoveInternalMember(uint32_t character_id); void RemoveInternalMember(uint32_t character_id);
void SaveMembers(const std::vector<DynamicZoneMember>& members);
uint32_t SaveToDatabase(); uint32_t SaveToDatabase();
bool SetInternalMemberStatus(uint32_t character_id, DynamicZoneMemberStatus status); 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> CreateServerDzLocationPacket(uint16_t server_opcode, const DynamicZoneLocation& location);
std::unique_ptr<ServerPacket> CreateServerDzSwitchIDPacket(); std::unique_ptr<ServerPacket> CreateServerDzSwitchIDPacket();
std::unique_ptr<ServerPacket> CreateServerMemberAddRemovePacket(const DynamicZoneMember& member, bool removed); 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> CreateServerMemberStatusPacket(uint32_t character_id, DynamicZoneMemberStatus status);
std::unique_ptr<ServerPacket> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member); std::unique_ptr<ServerPacket> CreateServerMemberSwapPacket(const DynamicZoneMember& remove_member, const DynamicZoneMember& add_member);
std::unique_ptr<ServerPacket> CreateServerRemoveAllMembersPacket(); 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_id = 0;
uint32_t m_zone_id = 0; uint32_t m_zone_id = 0;
@ -175,6 +221,8 @@ protected:
bool m_never_expires = false; bool m_never_expires = false;
bool m_has_zonein = false; bool m_has_zonein = false;
bool m_has_member_statuses = false; bool m_has_member_statuses = false;
bool m_is_locked = false;
bool m_add_replay = true;
std::string m_name; std::string m_name;
std::string m_uuid; std::string m_uuid;
DynamicZoneMember m_leader; DynamicZoneMember m_leader;
@ -182,12 +230,15 @@ protected:
DynamicZoneLocation m_compass; DynamicZoneLocation m_compass;
DynamicZoneLocation m_safereturn; DynamicZoneLocation m_safereturn;
DynamicZoneLocation m_zonein; 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_start_time;
std::chrono::time_point<std::chrono::system_clock> m_expire_time; std::chrono::time_point<std::chrono::system_clock> m_expire_time;
std::vector<DynamicZoneMember> m_members; std::vector<DynamicZoneMember> m_members;
std::vector<DzLockout> m_lockouts;
public: public:
void Unserialize(std::span<char> buf);
template<class Archive> template<class Archive>
void serialize(Archive& archive) void serialize(Archive& archive)
{ {
@ -202,6 +253,8 @@ public:
m_never_expires, m_never_expires,
m_has_zonein, m_has_zonein,
m_has_member_statuses, m_has_member_statuses,
m_is_locked,
m_add_replay,
m_name, m_name,
m_uuid, m_uuid,
m_leader, m_leader,
@ -212,7 +265,8 @@ public:
m_duration, m_duration,
m_start_time, m_start_time,
m_expire_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; 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 { enum StartZoneIndex {
Odus = 0, Odus = 0,
Qeynos, 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 * @docs https://docs.eqemu.io/developer/repositories
*/ */
#ifndef EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H #ifndef EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
#define EQEMU_BASE_EXPEDITION_LOCKOUTS_REPOSITORY_H #define EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H
#include "../../database.h" #include "../../database.h"
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseExpeditionLockoutsRepository { class BaseDynamicZoneLockoutsRepository {
public: public:
struct ExpeditionLockouts { struct DynamicZoneLockouts {
uint32_t id; uint32_t id;
uint32_t expedition_id; uint32_t dynamic_zone_id;
std::string event_name; std::string event_name;
time_t expire_time; time_t expire_time;
uint32_t duration; uint32_t duration;
@ -36,7 +36,7 @@ public:
{ {
return { return {
"id", "id",
"expedition_id", "dynamic_zone_id",
"event_name", "event_name",
"expire_time", "expire_time",
"duration", "duration",
@ -48,7 +48,7 @@ public:
{ {
return { return {
"id", "id",
"expedition_id", "dynamic_zone_id",
"event_name", "event_name",
"UNIX_TIMESTAMP(expire_time)", "UNIX_TIMESTAMP(expire_time)",
"duration", "duration",
@ -68,7 +68,7 @@ public:
static std::string TableName() static std::string TableName()
{ {
return std::string("expedition_lockouts"); return std::string("dynamic_zone_lockouts");
} }
static std::string BaseSelect() static std::string BaseSelect()
@ -89,12 +89,12 @@ public:
); );
} }
static ExpeditionLockouts NewEntity() static DynamicZoneLockouts NewEntity()
{ {
ExpeditionLockouts e{}; DynamicZoneLockouts e{};
e.id = 0; e.id = 0;
e.expedition_id = 0; e.dynamic_zone_id = 0;
e.event_name = ""; e.event_name = "";
e.expire_time = std::time(nullptr); e.expire_time = std::time(nullptr);
e.duration = 0; e.duration = 0;
@ -103,23 +103,23 @@ public:
return e; return e;
} }
static ExpeditionLockouts GetExpeditionLockouts( static DynamicZoneLockouts GetDynamicZoneLockouts(
const std::vector<ExpeditionLockouts> &expedition_lockoutss, const std::vector<DynamicZoneLockouts> &dynamic_zone_lockoutss,
int expedition_lockouts_id int dynamic_zone_lockouts_id
) )
{ {
for (auto &expedition_lockouts : expedition_lockoutss) { for (auto &dynamic_zone_lockouts : dynamic_zone_lockoutss) {
if (expedition_lockouts.id == expedition_lockouts_id) { if (dynamic_zone_lockouts.id == dynamic_zone_lockouts_id) {
return expedition_lockouts; return dynamic_zone_lockouts;
} }
} }
return NewEntity(); return NewEntity();
} }
static ExpeditionLockouts FindOne( static DynamicZoneLockouts FindOne(
Database& db, Database& db,
int expedition_lockouts_id int dynamic_zone_lockouts_id
) )
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
@ -127,16 +127,16 @@ public:
"{} WHERE {} = {} LIMIT 1", "{} WHERE {} = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(), PrimaryKey(),
expedition_lockouts_id dynamic_zone_lockouts_id
) )
); );
auto row = results.begin(); auto row = results.begin();
if (results.RowCount() == 1) { if (results.RowCount() == 1) {
ExpeditionLockouts e{}; DynamicZoneLockouts e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0; 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.event_name = row[2] ? row[2] : "";
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); 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; e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
@ -150,7 +150,7 @@ public:
static int DeleteOne( static int DeleteOne(
Database& db, Database& db,
int expedition_lockouts_id int dynamic_zone_lockouts_id
) )
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
@ -158,7 +158,7 @@ public:
"DELETE FROM {} WHERE {} = {}", "DELETE FROM {} WHERE {} = {}",
TableName(), TableName(),
PrimaryKey(), PrimaryKey(),
expedition_lockouts_id dynamic_zone_lockouts_id
) )
); );
@ -167,14 +167,14 @@ public:
static int UpdateOne( static int UpdateOne(
Database& db, Database& db,
const ExpeditionLockouts &e const DynamicZoneLockouts &e
) )
{ {
std::vector<std::string> v; std::vector<std::string> v;
auto columns = Columns(); 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[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[3] + " = FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
v.push_back(columns[4] + " = " + std::to_string(e.duration)); v.push_back(columns[4] + " = " + std::to_string(e.duration));
@ -193,15 +193,15 @@ public:
return (results.Success() ? results.RowsAffected() : 0); return (results.Success() ? results.RowsAffected() : 0);
} }
static ExpeditionLockouts InsertOne( static DynamicZoneLockouts InsertOne(
Database& db, Database& db,
ExpeditionLockouts e DynamicZoneLockouts e
) )
{ {
std::vector<std::string> v; std::vector<std::string> v;
v.push_back(std::to_string(e.id)); 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("'" + Strings::Escape(e.event_name) + "'");
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
v.push_back(std::to_string(e.duration)); v.push_back(std::to_string(e.duration));
@ -227,7 +227,7 @@ public:
static int InsertMany( static int InsertMany(
Database& db, Database& db,
const std::vector<ExpeditionLockouts> &entries const std::vector<DynamicZoneLockouts> &entries
) )
{ {
std::vector<std::string> insert_chunks; std::vector<std::string> insert_chunks;
@ -236,7 +236,7 @@ public:
std::vector<std::string> v; std::vector<std::string> v;
v.push_back(std::to_string(e.id)); 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("'" + Strings::Escape(e.event_name) + "'");
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
v.push_back(std::to_string(e.duration)); v.push_back(std::to_string(e.duration));
@ -258,9 +258,9 @@ public:
return (results.Success() ? results.RowsAffected() : 0); 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( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -272,10 +272,10 @@ public:
all_entries.reserve(results.RowCount()); all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) { 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.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.event_name = row[2] ? row[2] : "";
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); 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; e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
@ -287,9 +287,9 @@ public:
return all_entries; 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( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -302,10 +302,10 @@ public:
all_entries.reserve(results.RowCount()); all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) { 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.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.event_name = row[2] ? row[2] : "";
e.expire_time = strtoll(row[3] ? row[3] : "-1", nullptr, 10); 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; e.duration = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
@ -379,13 +379,13 @@ public:
static int ReplaceOne( static int ReplaceOne(
Database& db, Database& db,
const ExpeditionLockouts &e const DynamicZoneLockouts &e
) )
{ {
std::vector<std::string> v; std::vector<std::string> v;
v.push_back(std::to_string(e.id)); 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("'" + Strings::Escape(e.event_name) + "'");
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
v.push_back(std::to_string(e.duration)); v.push_back(std::to_string(e.duration));
@ -404,7 +404,7 @@ public:
static int ReplaceMany( static int ReplaceMany(
Database& db, Database& db,
const std::vector<ExpeditionLockouts> &entries const std::vector<DynamicZoneLockouts> &entries
) )
{ {
std::vector<std::string> insert_chunks; std::vector<std::string> insert_chunks;
@ -413,7 +413,7 @@ public:
std::vector<std::string> v; std::vector<std::string> v;
v.push_back(std::to_string(e.id)); 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("'" + Strings::Escape(e.event_name) + "'");
v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")"); v.push_back("FROM_UNIXTIME(" + (e.expire_time > 0 ? std::to_string(e.expire_time) : "null") + ")");
v.push_back(std::to_string(e.duration)); 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_z;
float zone_in_heading; float zone_in_heading;
uint8_t has_zone_in; uint8_t has_zone_in;
int8_t is_locked;
int8_t add_replay;
}; };
static std::string PrimaryKey() static std::string PrimaryKey()
@ -75,6 +77,8 @@ public:
"zone_in_z", "zone_in_z",
"zone_in_heading", "zone_in_heading",
"has_zone_in", "has_zone_in",
"is_locked",
"add_replay",
}; };
} }
@ -104,6 +108,8 @@ public:
"zone_in_z", "zone_in_z",
"zone_in_heading", "zone_in_heading",
"has_zone_in", "has_zone_in",
"is_locked",
"add_replay",
}; };
} }
@ -167,6 +173,8 @@ public:
e.zone_in_z = 0; e.zone_in_z = 0;
e.zone_in_heading = 0; e.zone_in_heading = 0;
e.has_zone_in = 0; e.has_zone_in = 0;
e.is_locked = 0;
e.add_replay = 1;
return e; return e;
} }
@ -226,6 +234,8 @@ public:
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0; e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
e.zone_in_heading = row[21] ? strtof(row[21], 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.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; return e;
} }
@ -281,6 +291,8 @@ public:
v.push_back(columns[20] + " = " + std::to_string(e.zone_in_z)); 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[21] + " = " + std::to_string(e.zone_in_heading));
v.push_back(columns[22] + " = " + std::to_string(e.has_zone_in)); 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( auto results = db.QueryDatabase(
fmt::format( 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_z));
v.push_back(std::to_string(e.zone_in_heading)); 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.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( auto results = db.QueryDatabase(
fmt::format( 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_z));
v.push_back(std::to_string(e.zone_in_heading)); 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.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) + ")"); 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_z = row[20] ? strtof(row[20], nullptr) : 0;
e.zone_in_heading = row[21] ? strtof(row[21], 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.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); all_entries.push_back(e);
} }
@ -480,6 +498,8 @@ public:
e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0; e.zone_in_z = row[20] ? strtof(row[20], nullptr) : 0;
e.zone_in_heading = row[21] ? strtof(row[21], 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.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); 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_z));
v.push_back(std::to_string(e.zone_in_heading)); 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.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( auto results = db.QueryDatabase(
fmt::format( 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_z));
v.push_back(std::to_string(e.zone_in_heading)); 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.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) + ")"); 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 #define EQEMU_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H
#include "../database.h" #include "../database.h"
#include "../expedition_lockout_timer.h" #include "../dynamic_zone_lockout.h"
#include "../strings.h" #include "../strings.h"
#include "base/base_character_expedition_lockouts_repository.h" #include "base/base_character_expedition_lockouts_repository.h"
#include <unordered_map> #include <unordered_map>
@ -47,33 +47,8 @@ public:
// Custom extended repository methods here // Custom extended repository methods here
struct CharacterExpeditionLockoutsTimeStamp { static std::unordered_map<uint32_t, std::vector<DzLockout>> GetLockouts(
int id; Database& db, const std::vector<uint32_t>& char_ids, const std::string& expedition)
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)
{ {
auto results = db.QueryDatabase(fmt::format(SQL( auto results = db.QueryDatabase(fmt::format(SQL(
SELECT SELECT
@ -84,39 +59,171 @@ public:
from_expedition_uuid from_expedition_uuid
FROM character_expedition_lockouts FROM character_expedition_lockouts
WHERE WHERE
character_id IN ({}) character_id IN ({0})
AND expire_time > NOW() AND expire_time > NOW()
AND expedition_name = '{}' AND expedition_name = '{1}'
ORDER BY ORDER BY
FIELD(character_id, {}), FIELD(character_id, {0}),
FIELD(event_name, '{}') DESC FIELD(event_name, '{2}') DESC
), ),
fmt::join(character_ids, ","), fmt::join(char_ids, ","),
Strings::Escape(expedition_name), Strings::Escape(expedition),
fmt::join(character_ids, ","), Strings::Escape(DzLockout::ReplayTimer)
Strings::Escape(ordered_event_name)
)); ));
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) for (auto row = results.begin(); row != results.end(); ++row)
{ {
CharacterExpeditionLockoutsTimeStamp entry{};
int col = 0; int col = 0;
entry.character_id = std::strtoul(row[col++], nullptr, 10); uint32_t char_id = std::strtoul(row[col++], nullptr, 10);
entry.expire_time = std::strtoull(row[col++], nullptr, 10); time_t expire_time = std::strtoull(row[col++], nullptr, 10);
entry.duration = std::strtoul(row[col++], nullptr, 10); uint32_t duration = std::strtoul(row[col++], nullptr, 10);
entry.event_name = row[col++]; std::string event = row[col++];
entry.expedition_name = expedition_name; std::string uuid = row[col++];
entry.from_expedition_uuid = row[col++];
auto lockout = GetExpeditionLockoutTimerFromEntry(std::move(entry)); lockouts[char_id].emplace_back(std::move(uuid), expedition, std::move(event), expire_time, duration);
lockouts[entry.character_id].emplace_back(std::move(lockout));
} }
return lockouts; 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 #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; std::vector<MemberWithName> all_entries;
@ -146,65 +146,34 @@ public:
static void RemoveMember(Database& db, uint32_t dynamic_zone_id, uint32_t character_id) static void RemoveMember(Database& db, uint32_t dynamic_zone_id, uint32_t character_id)
{ {
db.QueryDatabase(fmt::format(SQL( DeleteWhere(db, fmt::format("dynamic_zone_id = {} AND character_id = {}", dynamic_zone_id, character_id));
DELETE FROM {}
WHERE dynamic_zone_id = {} AND character_id = {};
),
TableName(), dynamic_zone_id, character_id
));
} }
static void RemoveAllMembers(Database& db, uint32_t dynamic_zone_id) static void RemoveAllMembers(Database& db, uint32_t dynamic_zone_id)
{ {
db.QueryDatabase(fmt::format(SQL( DeleteWhere(db, fmt::format("dynamic_zone_id = {}", dynamic_zone_id));
DELETE FROM {}
WHERE dynamic_zone_id = {};
),
TableName(), 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( return 0;
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) + ")");
} }
std::vector<std::string> insert_values; std::vector<std::string> values;
values.reserve(entries.size());
auto results = db.QueryDatabase( for (const auto& entry : entries)
fmt::format( {
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = id;", values.push_back(fmt::format("({},{},{})", entry.id, entry.dynamic_zone_id, entry.character_id));
TableName(), }
ColumnsRaw(),
Strings::Implode(",", insert_chunks)
)
);
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_z;
float zone_in_heading; float zone_in_heading;
int has_zone_in; int has_zone_in;
int8_t is_locked;
int8_t add_replay;
int zone; int zone;
int version; int version;
int is_global; int is_global;
@ -105,6 +107,8 @@ public:
dynamic_zones.zone_in_z, dynamic_zones.zone_in_z,
dynamic_zones.zone_in_heading, dynamic_zones.zone_in_heading,
dynamic_zones.has_zone_in, dynamic_zones.has_zone_in,
dynamic_zones.is_locked,
dynamic_zones.add_replay,
instance_list.zone, instance_list.zone,
instance_list.version, instance_list.version,
instance_list.is_global, instance_list.is_global,
@ -144,6 +148,8 @@ public:
entry.zone_in_z = strtof(row[col++], nullptr); entry.zone_in_z = strtof(row[col++], nullptr);
entry.zone_in_heading = strtof(row[col++], nullptr); entry.zone_in_heading = strtof(row[col++], nullptr);
entry.has_zone_in = strtol(row[col++], nullptr, 10) != 0; 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 // from instance_list
entry.zone = strtol(row[col++], nullptr, 10); entry.zone = strtol(row[col++], nullptr, 10);
entry.version = 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) static void UpdateSwitchID(Database& db, uint32_t dz_id, int dz_switch_id)
{ {
if (dz_id != 0) if (dz_id != 0)
@ -351,6 +373,59 @@ public:
return all_entries; 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 #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 // Custom extended repository methods here
static int InsertOrUpdateMany(Database& db, static uint32_t InsertOrUpdateMany(Database& db, const std::vector<InstanceListPlayer>& entries)
const std::vector<InstanceListPlayer>& instance_list_player_entries)
{ {
std::vector<std::string> insert_chunks; if (entries.empty())
for (auto &instance_list_player_entry: instance_list_player_entries)
{ {
std::vector<std::string> insert_values; return 0;
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) + ")");
} }
std::vector<std::string> insert_values; std::vector<std::string> values;
values.reserve(entries.size());
auto results = db.QueryDatabase( for (const auto& entry : entries)
fmt::format( {
"INSERT INTO {} ({}) VALUES {} ON DUPLICATE KEY UPDATE id = VALUES(id)", values.push_back(fmt::format("({},{})", entry.id, entry.charid));
TableName(), }
ColumnsRaw(),
Strings::Implode(",", insert_chunks)
)
);
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) static bool ReplaceOne(Database& db, InstanceListPlayer e)

View File

@ -170,18 +170,6 @@
#define ServerOP_LFPMatches 0x0214 #define ServerOP_LFPMatches 0x0214
#define ServerOP_ClientVersionSummary 0x0215 #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 // dz
#define ServerOP_DzAddRemoveMember 0x0450 #define ServerOP_DzAddRemoveMember 0x0450
#define ServerOP_DzRemoveAllMembers 0x0451 #define ServerOP_DzRemoveAllMembers 0x0451
@ -199,6 +187,15 @@
#define ServerOP_DzDeleted 0x045d #define ServerOP_DzDeleted 0x045d
#define ServerOP_DzSetSwitchID 0x045e #define ServerOP_DzSetSwitchID 0x045e
#define ServerOP_DzMovePC 0x045f #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_LSInfo 0x1000
#define ServerOP_LSStatus 0x1001 #define ServerOP_LSStatus 0x1001
@ -1543,10 +1540,8 @@ struct UCSServerStatus_Struct {
}; };
}; };
struct ServerExpeditionID_Struct { struct ServerCharacterID_Struct {
uint32 expedition_id; uint32_t char_id;
uint32 sender_zone_id;
uint32 sender_instance_id;
}; };
struct ServerDzLeaderID_Struct { struct ServerDzLeaderID_Struct {
@ -1580,45 +1575,42 @@ struct ServerDzMovePC_Struct {
uint32 character_id; uint32 character_id;
}; };
struct ServerExpeditionLockout_Struct { struct ServerDzLockout_Struct {
uint32 expedition_id; uint32 dz_id;
uint64 expire_time; uint64 expire_time;
uint32 duration; uint32 duration;
uint32 sender_zone_id; uint32 sender_zone_id;
uint16 sender_instance_id; uint16 sender_instance_id;
uint8 remove; uint8 remove;
uint8 members_only; uint8 members_only;
int seconds_adjust; int seconds;
char event_name[256]; char event_name[256];
}; };
struct ServerExpeditionLockState_Struct { struct ServerDzLock_Struct {
uint32 expedition_id; uint32 dz_id;
uint32 sender_zone_id; uint32 sender_zone_id;
uint16 sender_instance_id; uint16 sender_instance_id;
uint8 enabled; bool lock;
uint8 lock_msg; // 0: none, 1: closing 2: trial begin uint8 lock_msg; // 0: none, 1: closing 2: trial begin
uint32 color;
}; };
struct ServerExpeditionSetting_Struct { struct ServerDzBool_Struct {
uint32 expedition_id; uint32 dz_id;
uint32 sender_zone_id; uint32 sender_zone_id;
uint16 sender_instance_id; uint16 sender_instance_id;
uint8 enabled; bool enabled;
}; };
struct ServerExpeditionCharacterLockout_Struct { struct ServerDzCharacterLockout_Struct {
uint8 remove; uint8 remove;
uint32 character_id; uint32 char_id;
uint64 expire_time; uint64 expire_time;
uint32 duration; uint32 duration;
char uuid[37]; char uuid[37];
char expedition_name[128]; char expedition[128];
char event_name[256]; char event[256];
};
struct ServerExpeditionCharacterID_Struct {
uint32_t character_id;
}; };
struct ServerDzExpireWarning_Struct { struct ServerDzExpireWarning_Struct {
@ -1627,7 +1619,7 @@ struct ServerDzExpireWarning_Struct {
}; };
struct ServerDzCommand_Struct { struct ServerDzCommand_Struct {
uint32 expedition_id; uint32 dz_id;
uint8 is_char_online; // 0: target name is offline, 1: online uint8 is_char_online; // 0: target name is offline, 1: online
char requester_name[64]; char requester_name[64];
char target_name[64]; char target_name[64];
@ -1696,11 +1688,12 @@ struct ServerDzSetDuration_Struct {
uint32 seconds; uint32 seconds;
}; };
struct ServerDzCreateSerialized_Struct { struct ServerDzCreate_Struct {
uint16_t origin_zone_id; uint16_t origin_zone_id;
uint16_t origin_instance_id; uint16_t origin_instance_id;
uint32_t dz_id;
uint32_t cereal_size; uint32_t cereal_size;
char cereal_data[0]; char cereal_data[1];
}; };
struct ServerSendPlayerEvent_Struct { struct ServerSendPlayerEvent_Struct {

View File

@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt * 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 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054
#endif #endif

View File

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

View File

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

View File

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

View File

@ -164,132 +164,6 @@ void DynamicZone::SendZonesLeaderChanged()
zoneserver_list.SendPacket(pack.get()); 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) void DynamicZone::ProcessMemberAddRemove(const DynamicZoneMember& member, bool removed)
{ {
DynamicZoneBase::ProcessMemberAddRemove(member, removed); DynamicZoneBase::ProcessMemberAddRemove(member, removed);
@ -345,13 +219,13 @@ void DynamicZone::SendZoneMemberStatuses(uint16_t zone_id, uint16_t instance_id)
void DynamicZone::CacheMemberStatuses() void DynamicZone::CacheMemberStatuses()
{ {
if (m_has_member_statuses) if (m_has_member_statuses || m_members.empty())
{ {
return; return;
} }
// called when a new dz is cached to fill member statuses // called when a new dz is cached to fill member statuses
std::string zone_name{}; std::string zone_name;
std::vector<ClientListEntry*> all_clients; std::vector<ClientListEntry*> all_clients;
all_clients.reserve(client_list.GetClientCount()); all_clients.reserve(client_list.GetClientCount());
client_list.GetClients(zone_name.c_str(), all_clients); client_list.GetClients(zone_name.c_str(), all_clients);

View File

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

View File

@ -1,12 +1,14 @@
#include "dynamic_zone_manager.h" #include "dynamic_zone_manager.h"
#include "dynamic_zone.h" #include "dynamic_zone.h"
#include "cliententry.h"
#include "clientlist.h"
#include "worlddb.h" #include "worlddb.h"
#include "zonelist.h" #include "zonelist.h"
#include "zoneserver.h" #include "zoneserver.h"
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include "../common/repositories/expeditions_repository.h" #include "../common/repositories/dynamic_zone_lockouts_repository.h"
#include "../common/repositories/expedition_lockouts_repository.h"
extern ClientList client_list;
extern ZSList zoneserver_list; extern ZSList zoneserver_list;
DynamicZoneManager dynamic_zone_manager; DynamicZoneManager dynamic_zone_manager;
@ -27,6 +29,8 @@ void DynamicZoneManager::PurgeExpiredDynamicZones()
{ {
LogDynamicZones("Purging [{}] dynamic zone(s)", dz_ids.size()); LogDynamicZones("Purging [{}] dynamic zone(s)", dz_ids.size());
DynamicZoneLockoutsRepository::DeleteWhere(database,
fmt::format("dynamic_zone_id IN ({})", fmt::join(dz_ids, ",")));
DynamicZoneMembersRepository::DeleteWhere(database, DynamicZoneMembersRepository::DeleteWhere(database,
fmt::format("dynamic_zone_id IN ({})", Strings::Join(dz_ids, ","))); fmt::format("dynamic_zone_id IN ({})", Strings::Join(dz_ids, ",")));
DynamicZonesRepository::DeleteWhere(database, DynamicZonesRepository::DeleteWhere(database,
@ -34,8 +38,7 @@ void DynamicZoneManager::PurgeExpiredDynamicZones()
} }
} }
DynamicZone* DynamicZoneManager::CreateNew( DynamicZone* DynamicZoneManager::TryCreate(DynamicZone& dz_request, const std::vector<DynamicZoneMember>& members)
DynamicZone& dz_request, const std::vector<DynamicZoneMember>& members)
{ {
// this creates a new dz instance and saves it to both db and cache // this creates a new dz instance and saves it to both db and cache
uint32_t dz_id = dz_request.Create(); uint32_t dz_id = dz_request.Create();
@ -46,15 +49,12 @@ DynamicZone* DynamicZoneManager::CreateNew(
} }
auto dz = std::make_unique<DynamicZone>(dz_request); 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()); 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()); zoneserver_list.SendPacket(pack.get());
auto inserted = dynamic_zone_cache.emplace(dz_id, std::move(dz)); auto inserted = dynamic_zone_cache.emplace(dz_id, std::move(dz));
@ -63,18 +63,17 @@ DynamicZone* DynamicZoneManager::CreateNew(
void DynamicZoneManager::CacheNewDynamicZone(ServerPacket* pack) 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>(); 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(); new_dz->CacheMemberStatuses();
// reserialize with member statuses cached before forwarding (restore origin zone) // 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(buf->dz_id, std::move(new_dz));
dynamic_zone_cache.emplace(dz_id, std::move(new_dz)); LogDynamicZones("Cached new dynamic zone [{}]", buf->dz_id);
LogDynamicZones("Cached new dynamic zone [{}]", dz_id);
zoneserver_list.SendPacket(repack.get()); zoneserver_list.SendPacket(repack.get());
} }
@ -83,18 +82,19 @@ void DynamicZoneManager::CacheAllFromDatabase()
{ {
BenchTimer bench; BenchTimer bench;
auto dynamic_zones = DynamicZonesRepository::AllWithInstanceNotExpired(database); auto dzs = DynamicZonesRepository::AllWithInstanceNotExpired(database);
auto dynamic_zone_members = DynamicZoneMembersRepository::GetAllWithNames(database); auto members = DynamicZoneMembersRepository::AllWithNames(database);
auto lockouts = DynamicZoneLockoutsRepository::All(database);
dynamic_zone_cache.clear(); 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; uint32_t dz_id = entry.id;
auto dz = std::make_unique<DynamicZone>(std::move(entry)); 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) 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) // note leader status won't be updated here until leader is set by owning system (expeditions)
dz->CacheMemberStatuses(); dz->CacheMemberStatuses();
@ -142,24 +150,10 @@ void DynamicZoneManager::Process()
dynamic_zone_cache.erase(dz_id); dynamic_zone_cache.erase(dz_id);
} }
// need to look up expedition ids until lockouts are moved to dynamic zones DynamicZoneLockoutsRepository::DeleteWhere(database,
std::vector<uint32_t> expedition_ids; fmt::format("dynamic_zone_id IN ({})", fmt::join(dynamic_zone_ids, ",")));
auto expeditions = ExpeditionsRepository::GetWhere(database, DynamicZoneMembersRepository::DeleteWhere(database,
fmt::format("dynamic_zone_id IN ({})", Strings::Join(dynamic_zone_ids, ","))); fmt::format("dynamic_zone_id IN ({})", fmt::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);
DynamicZonesRepository::DeleteWhere(database, DynamicZonesRepository::DeleteWhere(database,
fmt::format("id IN ({})", Strings::Join(dynamic_zone_ids, ","))); fmt::format("id IN ({})", Strings::Join(dynamic_zone_ids, ",")));
} }
@ -174,3 +168,250 @@ void DynamicZoneManager::LoadTemplates()
m_dz_templates[dz_template.id] = dz_template; 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 CacheAllFromDatabase();
void CacheNewDynamicZone(ServerPacket* pack); 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 LoadTemplates();
void Process(); void Process();
void PurgeExpiredDynamicZones(); 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 "web_interface.h"
#include "console.h" #include "console.h"
#include "dynamic_zone_manager.h" #include "dynamic_zone_manager.h"
#include "expedition_database.h"
#include "world_server_cli.h" #include "world_server_cli.h"
#include "../common/content/world_content_service.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/repositories/character_task_timers_repository.h"
#include "../common/zone_store.h" #include "../common/zone_store.h"
#include "world_event_scheduler.h" #include "world_event_scheduler.h"
@ -449,7 +449,7 @@ int main(int argc, char **argv)
if (PurgeInstanceTimer.Check()) { if (PurgeInstanceTimer.Check()) {
database.PurgeExpiredInstances(); database.PurgeExpiredInstances();
database.PurgeAllDeletedDataBuckets(); database.PurgeAllDeletedDataBuckets();
ExpeditionDatabase::PurgeExpiredCharacterLockouts(); CharacterExpeditionLockoutsRepository::DeleteWhere(database, "expire_time <= NOW()");
CharacterTaskTimersRepository::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) { if (new_dz) {
auto shared_task_dz = SharedTaskDynamicZonesRepository::NewEntity(); auto shared_task_dz = SharedTaskDynamicZonesRepository::NewEntity();
shared_task_dz.shared_task_id = shared_task->GetDbSharedTask().id; 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); auto t = shared_task_manager.FindSharedTaskByTaskIdAndCharacterId(buf->task_id, buf->source_character_id);
if (t) { if (t) {
DynamicZone dz; DynamicZone dz;
dz.LoadSerializedDzPacket(buf->cereal_data, buf->cereal_size); dz.Unserialize({ buf->cereal_data, buf->cereal_size });
shared_task_manager.CreateDynamicZone(t, dz); shared_task_manager.CreateDynamicZone(t, dz);
} }

View File

@ -5,12 +5,12 @@
#include "../common/http/uri.h" #include "../common/http/uri.h"
#include "../common/net/console_server.h" #include "../common/net/console_server.h"
#include "../common/net/servertalk_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/repositories/character_task_timers_repository.h"
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include "../common/strings.h" #include "../common/strings.h"
#include "adventure_manager.h" #include "adventure_manager.h"
#include "dynamic_zone_manager.h" #include "dynamic_zone_manager.h"
#include "expedition_database.h"
#include "login_server_list.h" #include "login_server_list.h"
#include "shared_task_manager.h" #include "shared_task_manager.h"
#include "ucs.h" #include "ucs.h"
@ -367,9 +367,8 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
LogInfo("Purging expired dynamic zones and members"); LogInfo("Purging expired dynamic zones and members");
dynamic_zone_manager.PurgeExpiredDynamicZones(); dynamic_zone_manager.PurgeExpiredDynamicZones();
LogInfo("Purging expired expeditions"); LogInfo("Purging expired character expedition lockouts");
ExpeditionDatabase::PurgeExpiredExpeditions(); CharacterExpeditionLockoutsRepository::DeleteWhere(database, "expire_time <= NOW()");
ExpeditionDatabase::PurgeExpiredCharacterLockouts();
LogInfo("Purging expired character task timers"); LogInfo("Purging expired character task timers");
CharacterTaskTimersRepository::DeleteWhere(database, "expire_time <= NOW()"); 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 "../common/zone_store.h"
#include "dynamic_zone.h" #include "dynamic_zone.h"
#include "dynamic_zone_manager.h" #include "dynamic_zone_manager.h"
#include "expedition_message.h"
#include "shared_task_world_messaging.h" #include "shared_task_world_messaging.h"
#include "../common/shared_tasks.h" #include "../common/shared_tasks.h"
#include "shared_task_manager.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_Consent:
case ServerOP_DepopAllPlayersCorpses: case ServerOP_DepopAllPlayersCorpses:
case ServerOP_DepopPlayerCorpse: case ServerOP_DepopPlayerCorpse:
case ServerOP_ExpeditionLockState:
case ServerOP_ExpeditionLockout:
case ServerOP_ExpeditionLockoutDuration:
case ServerOP_ExpeditionReplayOnJoin:
case ServerOP_GuildRankUpdate: case ServerOP_GuildRankUpdate:
case ServerOP_ItemStatus: case ServerOP_ItemStatus:
case ServerOP_KickPlayer: case ServerOP_KickPlayer:
@ -1532,16 +1527,11 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
SharedTaskWorldMessaging::HandleZoneMessage(pack); SharedTaskWorldMessaging::HandleZoneMessage(pack);
break; 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_DzCreated:
case ServerOP_DzAddPlayer:
case ServerOP_DzSaveInvite:
case ServerOP_DzRequestInvite:
case ServerOP_DzMakeLeader:
case ServerOP_DzAddRemoveMember: case ServerOP_DzAddRemoveMember:
case ServerOP_DzSwapMembers: case ServerOP_DzSwapMembers:
case ServerOP_DzRemoveAllMembers: case ServerOP_DzRemoveAllMembers:
@ -1552,8 +1542,13 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
case ServerOP_DzSetZoneIn: case ServerOP_DzSetZoneIn:
case ServerOP_DzSetSwitchID: case ServerOP_DzSetSwitchID:
case ServerOP_DzMovePC: case ServerOP_DzMovePC:
case ServerOP_DzLock:
case ServerOP_DzReplayOnJoin:
case ServerOP_DzLockout:
case ServerOP_DzLockoutDuration:
case ServerOP_DzCharacterLockout:
case ServerOP_DzUpdateMemberStatus: { case ServerOP_DzUpdateMemberStatus: {
DynamicZone::HandleZoneMessage(pack); dynamic_zone_manager.HandleZoneMessage(pack);
break; break;
} }
case ServerOP_GuildTributeUpdate: { case ServerOP_GuildTributeUpdate: {

View File

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

View File

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

View File

@ -21,8 +21,7 @@
class Client; class Client;
class EQApplicationPacket; class EQApplicationPacket;
class DynamicZone; class DynamicZone;
class Expedition; class DzLockout;
class ExpeditionLockoutTimer;
class ExpeditionRequest; class ExpeditionRequest;
class Group; class Group;
class NPC; class NPC;
@ -32,6 +31,7 @@ class Seperator;
class ServerPacket; class ServerPacket;
struct DynamicZoneLocation; struct DynamicZoneLocation;
enum WaterRegionType : int; enum WaterRegionType : int;
enum class DynamicZoneMemberStatus;
namespace EQ namespace EQ
{ {
@ -248,6 +248,13 @@ struct ClientReward
uint32 amount; uint32 amount;
}; };
struct ExpeditionInvite
{
uint32_t dz_id;
std::string inviter_name;
std::string swap_name;
};
class Client : public Mob class Client : public Mob
{ {
public: public:
@ -1565,32 +1572,24 @@ public:
Client* client, const std::string& client_name, uint16_t chat_type, Client* client, const std::string& client_name, uint16_t chat_type,
uint32_t string_id, const std::initializer_list<std::string>& arguments = {}); uint32_t string_id, const std::initializer_list<std::string>& arguments = {});
void AddExpeditionLockout(const ExpeditionLockoutTimer& lockout, bool update_db = false); void AddDzLockout(const DzLockout& lockout, bool update_db = false);
void AddExpeditionLockoutDuration(const std::string& expedition_name, void AddDzLockout(const std::string& expedition, const std::string& event, uint32_t duration, std::string uuid = {});
const std::string& event_Name, int seconds, const std::string& uuid = {}, bool update_db = false); void AddDzLockoutDuration(const DzLockout& lockout, int seconds, const std::string& uuid = {}, bool update_db = false);
void AddNewExpeditionLockout(const std::string& expedition_name, DynamicZone* CreateExpedition(DynamicZone& dz, bool silent = false);
const std::string& event_name, uint32_t duration, std::string uuid = {}); DynamicZone* CreateExpedition(uint32 zone_id, uint32 version, uint32 duration, const std::string& name, uint32 min_players, uint32 max_players, bool silent = false);
Expedition* CreateExpedition(DynamicZone& dz, bool disable_messages = false); DynamicZone* CreateExpeditionFromTemplate(uint32_t dz_template_id);
Expedition* CreateExpedition(const std::string& zone_name, DynamicZone* GetExpedition() const;
uint32 version, uint32 duration, const std::string& expedition_name, uint32 GetExpeditionID() const;
uint32 min_players, uint32 max_players, bool disable_messages = false); const DzLockout* GetDzLockout(const std::string& expedition, const std::string& event) const;
Expedition* CreateExpeditionFromTemplate(uint32_t dz_template_id); const std::vector<DzLockout>& GetDzLockouts() const { return m_dz_lockouts; };
Expedition* GetExpedition() const; std::vector<DzLockout> GetDzLockouts(const std::string& expedition);
uint32 GetExpeditionID() const { return m_expedition_id; } uint32 GetPendingDzInviteID() const { return m_dz_invite.dz_id; }
const ExpeditionLockoutTimer* GetExpeditionLockout( void SetPendingDzInvite(const ExpeditionInvite& invite) { m_dz_invite = invite; }
const std::string& expedition_name, const std::string& event_name, bool include_expired = false) const; void RequestPendingDzInvite() const;
const std::vector<ExpeditionLockoutTimer>& GetExpeditionLockouts() const { return m_expedition_lockouts; }; bool HasDzLockout(const std::string& expedition, const std::string& event) const;
std::vector<ExpeditionLockoutTimer> GetExpeditionLockouts(const std::string& expedition_name, bool include_expired = false); void RemoveDzLockouts(const std::string& expedition, bool update_db = false);
uint32 GetPendingExpeditionInviteID() const { return m_pending_expedition_invite.expedition_id; } void RemoveDzLockout(const std::string& expedition, const std::string& event, bool update_db = false);
bool HasExpeditionLockout(const std::string& expedition_name, const std::string& event_name, bool include_expired = false); void SendDzLockoutTimers();
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 DzListTimers(); void DzListTimers();
void SetDzRemovalTimer(bool enable_timer); void SetDzRemovalTimer(bool enable_timer);
void SendDzCompassUpdate(); void SendDzCompassUpdate();
@ -2285,9 +2284,8 @@ private:
uint8 client_max_level; uint8 client_max_level;
uint32 m_expedition_id = 0; ExpeditionInvite m_dz_invite = {};
ExpeditionInvite m_pending_expedition_invite { 0 }; std::vector<DzLockout> m_dz_lockouts;
std::vector<ExpeditionLockoutTimer> m_expedition_lockouts;
glm::vec3 m_quest_compass; glm::vec3 m_quest_compass;
bool m_has_quest_compass = false; bool m_has_quest_compass = false;
std::vector<uint32_t> m_dynamic_zone_ids; 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/data_verification.h"
#include "../common/rdtsc.h" #include "../common/rdtsc.h"
#include "data_bucket.h" #include "data_bucket.h"
#include "dynamic_zone.h"
#include "event_codes.h" #include "event_codes.h"
#include "expedition.h"
#include "guild_mgr.h" #include "guild_mgr.h"
#include "merc.h" #include "merc.h"
#include "petitions.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_dynamic_zone_ids.emplace_back(entry.dynamic_zone_id);
} }
m_expedition_id = ExpeditionsRepository::GetIDByMemberID(database, CharacterID());
auto dz = zone->GetDynamicZone(); auto dz = zone->GetDynamicZone();
if (dz && dz->GetSafeReturnLocation().zone_id != 0) if (dz && dz->GetSafeReturnLocation().zone_id != 0)
{ {
@ -6055,8 +6053,8 @@ void Client::Handle_OP_DzAddPlayer(const EQApplicationPacket *app)
} }
else else
{ {
// the only /dz command that sends an error message if no active expedition // message string 8271 (not in emu clients) is the only /dz command that sends an error if no active expedition
Message(Chat::System, DZ_YOU_NOT_ASSIGNED); 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) void Client::Handle_OP_DzExpeditionInviteResponse(const EQApplicationPacket *app)
{ {
auto expedition = Expedition::FindCachedExpeditionByID(m_pending_expedition_invite.expedition_id); auto expedition = DynamicZone::FindDynamicZoneByID(m_dz_invite.dz_id);
std::string swap_remove_name = m_pending_expedition_invite.swap_remove_name; std::string swap_name = m_dz_invite.swap_name;
m_pending_expedition_invite = { 0 }; // clear before re-validating m_dz_invite = {}; // clear before re-validating
if (expedition) if (expedition)
{ {
auto dzmsg = reinterpret_cast<ExpeditionInviteResponse_Struct*>(app->pBuffer); 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/skills.h"
#include "../common/spdat.h" #include "../common/spdat.h"
#include "../common/strings.h" #include "../common/strings.h"
#include "dynamic_zone.h"
#include "event_codes.h" #include "event_codes.h"
#include "expedition.h"
#include "guild_mgr.h" #include "guild_mgr.h"
#include "map.h" #include "map.h"
#include "petitions.h" #include "petitions.h"

View File

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

View File

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

View File

@ -16,8 +16,8 @@
#include "../common/say_link.h" #include "../common/say_link.h"
#include "corpse.h" #include "corpse.h"
#include "dynamic_zone.h"
#include "entity.h" #include "entity.h"
#include "expedition.h"
#include "groups.h" #include "groups.h"
#include "mob.h" #include "mob.h"
#include "raids.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 Database;
class EQApplicationPacket; class EQApplicationPacket;
class ServerPacket; 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 class DynamicZone : public DynamicZoneBase
{ {
@ -40,53 +49,92 @@ public:
DynamicZone() = default; DynamicZone() = default;
DynamicZone(uint32_t zone_id, uint32_t version, uint32_t duration, DynamicZoneType type); 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 CacheAllFromDatabase();
static void CacheNewDynamicZone(ServerPacket* pack); static void CacheNewDynamicZone(ServerPacket* pack);
static DynamicZone* CreateNew(DynamicZone& dz_details, const std::vector<DynamicZoneMember>& members); static DynamicZone* TryCreate(Client& client, DynamicZone& dzinfo, bool silent = false);
static DynamicZone* FindDynamicZoneByID(uint32_t dz_id); 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 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 SetSecondsRemaining(uint32_t seconds_remaining) override;
void DoAsyncZoneMemberUpdates();
bool CanClientLootCorpse(Client* client, uint32_t npc_type_id, uint32_t entity_id); 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 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 SendClientWindowUpdate(Client* client);
void SendLeaderNameToZoneMembers(); void SendLeaderNameToZoneMembers();
void SendMemberListToZoneMembers(); void SendMemberListToZoneMembers();
void SendMemberListNameToZoneMembers(const std::string& char_name, bool remove); void SendMemberNameToZoneMembers(const std::string& char_name, bool remove);
void SendMemberListStatusToZoneMembers(const DynamicZoneMember& member); void SendMemberStatusToZoneMembers(const DynamicZoneMember& member);
void SendRemoveAllMembersToZoneMembers(bool silent) { ProcessRemoveAllMembers(silent); } 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::string GetLootEvent(uint32_t id, DzLootEvent::Type type) const;
std::unique_ptr<EQApplicationPacket> CreateInfoPacket(bool clear = false); void SetLootEvent(uint32_t id, const std::string& event, DzLootEvent::Type type);
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;
private: private:
static void StartAllClientRemovalTimers(); 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 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 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 SendMembersExpireWarning(uint32_t minutes);
void SendUpdatesToZoneMembers(bool removing_all = false, bool silent = true); 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 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 #endif

View File

@ -27,9 +27,9 @@
#include "../common/misc_functions.h" #include "../common/misc_functions.h"
#include "dialogue_window.h" #include "dialogue_window.h"
#include "dynamic_zone.h"
#include "embperl.h" #include "embperl.h"
#include "entity.h" #include "entity.h"
#include "expedition.h"
#include "queryserv.h" #include "queryserv.h"
#include "questmgr.h" #include "questmgr.h"
#include "zone.h" #include "zone.h"
@ -2779,45 +2779,45 @@ void Perl__SetContentFlag(std::string flag_name, bool enabled)
zone->ReloadContentFlags(); zone->ReloadContentFlags();
} }
Expedition* Perl__get_expedition() DynamicZone* Perl__get_expedition()
{ {
if (zone && zone->GetInstanceID() != 0) if (zone && zone->GetInstanceID() != 0)
{ {
return Expedition::FindCachedExpeditionByZoneInstance(zone->GetZoneID(), zone->GetInstanceID()); return DynamicZone::FindExpeditionByZone(zone->GetZoneID(), zone->GetInstanceID());
} }
return nullptr; 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::reference Perl__get_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name)
{ {
perl::hash table; 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) { auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const DzLockout& lockout) {
return lockout.IsSameLockout(expedition_name, event_name); return lockout.IsSame(expedition_name, event_name);
}); });
if (it != lockouts.end()) if (it != lockouts.end())
{ {
table["remaining"] = it->GetSecondsRemaining(); table["remaining"] = it->GetSecondsRemaining();
table["uuid"] = it->GetExpeditionUUID(); table["uuid"] = it->UUID();
} }
return perl::reference(table); return perl::reference(table);
@ -2827,23 +2827,23 @@ perl::reference Perl__get_expedition_lockouts_by_char_id(uint32 char_id)
{ {
perl::hash table; perl::hash table;
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id); auto lockouts = DynamicZone::GetCharacterLockouts(char_id);
for (const auto& lockout : lockouts) 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()]; perl::hash expedition_table = table[lockout.DzName()];
if (!expedition_table.exists(lockout.GetEventName())) 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["remaining"] = lockout.GetSecondsRemaining();
event_table["uuid"] = lockout.GetExpeditionUUID(); event_table["uuid"] = lockout.UUID();
} }
return perl::reference(table); 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; perl::hash table;
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id); auto lockouts = DynamicZone::GetCharacterLockouts(char_id);
for (const auto& lockout : lockouts) 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["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) 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); auto lockout = DzLockout::Create(expedition_name, event_name, seconds);
Expedition::AddLockoutClients(lockout); DynamicZone::AddClientsLockout(lockout);
} }
void Perl__add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) 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); auto lockout = DzLockout::Create(expedition_name, event_name, seconds, uuid);
Expedition::AddLockoutClients(lockout); DynamicZone::AddClientsLockout(lockout);
} }
void Perl__add_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name, uint32 seconds) 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) 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) 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) 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) 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) EQ::ItemInstance* Perl__createitem(uint32 item_id)

View File

@ -5506,7 +5506,7 @@ void EntityList::ExpeditionWarning(uint32 minutes_left)
auto it = client_list.begin(); auto it = client_list.begin();
while (it != client_list.end()) { 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->second->QueuePacket(outapp);
++it; ++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 "expedition_request.h"
#include "client.h" #include "client.h"
#include "expedition.h"
#include "groups.h" #include "groups.h"
#include "raids.h" #include "raids.h"
#include "string_ids.h" #include "string_ids.h"
#include "../common/repositories/character_expedition_lockouts_repository.h" #include "../common/repositories/character_expedition_lockouts_repository.h"
constexpr char SystemName[] = "expedition"; ExpeditionRequest::ExpeditionRequest(const DynamicZone& dz, Client& client, bool silent)
: m_dz(&dz), m_requester(&client), m_silent(silent)
// 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)
{ {
} }
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 // a message is sent to leader for every member that fails a requirement
BenchTimer benchmark; BenchTimer benchmark;
bool requirements_met = false; bool requirements_met = false;
Raid* raid = m_requester->GetRaid(); if (Raid* raid = m_requester->GetRaid())
Group* group = m_requester->GetGroup();
if (raid)
{ {
m_is_raid = true;
requirements_met = CanRaidRequest(raid); requirements_met = CanRaidRequest(raid);
} }
else if (group) else if (Group* group = m_requester->GetGroup())
{ {
requirements_met = CanGroupRequest(group); 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. // expedition max. members are added up to the max ordered by group number.
auto raid_members = raid->GetMembers(); 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(), std::sort(raid_members.begin(), raid_members.end(),
[&](const RaidMember& lhs, const RaidMember& rhs) { [&](const RaidMember& lhs, const RaidMember& rhs) {
if (m_leader_name == lhs.member_name) { // leader always added first if (m_leader_name == lhs.member_name) { return true; }
return true; if (m_leader_name == rhs.member_name) { return false; }
} else if (m_leader_name == rhs.member_name) {
return false;
}
return lhs.group_number < rhs.group_number; 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 // 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); return CanMembersJoin(member_names);
} }
@ -172,7 +142,7 @@ bool ExpeditionRequest::CanMembersJoin(const std::vector<std::string>& member_na
return requirements_met; return requirements_met;
} }
bool ExpeditionRequest::SaveLeaderLockouts(const std::vector<ExpeditionLockoutTimer>& lockouts) bool ExpeditionRequest::SaveLeaderLockouts(const std::vector<DzLockout>& lockouts)
{ {
bool has_replay_lockout = false; bool has_replay_lockout = false;
@ -180,9 +150,10 @@ bool ExpeditionRequest::SaveLeaderLockouts(const std::vector<ExpeditionLockoutTi
{ {
if (!lockout.IsExpired()) 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; 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) bool ExpeditionRequest::CheckMembersForConflicts(const std::vector<std::string>& member_names)
{ {
// order of member_names is preserved by queries for use with max member truncation // 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()) if (entries.empty())
{ {
LogExpeditions("Failed to load members for expedition request"); 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 is_solo = (member_names.size() == 1);
bool has_conflicts = false; bool has_conflicts = false;
std::vector<uint32_t> character_ids; std::vector<uint32_t> char_ids;
for (const auto& character : entries) 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 // live doesn't bother checking replay lockout here
SendLeaderMemberInExpedition(character.name, is_solo); 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); 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( auto lockouts = CharacterExpeditionLockoutsRepository::GetLockouts(database, char_ids, m_dz->GetName());
database, character_ids, m_expedition_name, DZ_REPLAY_TIMER_NAME);
// on live if leader has a replay lockout it never checks for event conflicts // on live if leader has a replay lockout it never checks for event conflicts
bool leader_has_replay_lockout = false; bool leader_replay = false;
auto lockout_iter = member_lockouts.find(m_leader_id); auto it = lockouts.find(m_leader_id);
if (lockout_iter != member_lockouts.end()) if (it != lockouts.end())
{ {
leader_has_replay_lockout = SaveLeaderLockouts(lockout_iter->second); leader_replay = SaveLeaderLockouts(it->second);
} }
for (const auto& character : entries) for (const auto& character : entries)
{ {
if (character.expedition_id != 0) if (character.dz_id != 0)
{ {
has_conflicts = true; has_conflicts = true;
SendLeaderMemberInExpedition(character.name, is_solo); SendLeaderMemberInExpedition(character.name, is_solo);
} }
auto lockout_iter = member_lockouts.find(character.id); auto it = lockouts.find(character.id);
if (lockout_iter != member_lockouts.end()) if (it != lockouts.end())
{ {
for (const auto& lockout : lockout_iter->second) for (const auto& lockout : it->second)
{ {
if (!lockout.IsExpired()) 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 // replay timers were sorted by query so they show up before event conflicts
if (lockout.IsReplayTimer()) if (lockout.IsReplay())
{ {
has_conflicts = true; has_conflicts = true;
SendLeaderMemberReplayLockout(character.name, lockout, is_solo); SendLeaderMemberReplayLockout(character.name, lockout, is_solo);
} }
else if (!leader_has_replay_lockout && character.id != m_leader_id && else if (!leader_replay && character.id != m_leader_id && std::ranges::none_of(m_lockouts, is_event))
m_lockouts.find(lockout.GetEventName()) == m_lockouts.end())
{ {
// leader doesn't have this lockout // leader doesn't have this lockout
has_conflicts = true; has_conflicts = true;
@ -266,73 +237,60 @@ bool ExpeditionRequest::CheckMembersForConflicts(const std::vector<std::string>&
return has_conflicts; return has_conflicts;
} }
void ExpeditionRequest::SendLeaderMessage( void ExpeditionRequest::SendLeaderMessage(uint16_t chat_type, uint32_t string_id, std::initializer_list<std::string> args)
uint16_t chat_type, uint32_t string_id, const 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); 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; return;
} }
if (is_solo) if (is_solo)
{ {
SendLeaderMessage(Chat::Red, EXPEDITION_YOU_BELONG); SendLeaderMessage(Chat::Red, DZ_YOU_BELONG);
} }
else if (m_requester) else if (m_requester)
{ {
std::string message = fmt::format(EXPEDITION_OTHER_BELONGS, m_requester->GetName(), member_name); // message string 9265 (not in emu clients)
Client::SendCrossZoneMessage(m_leader, m_leader_name, Chat::Red, message); 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( void ExpeditionRequest::SendLeaderMemberReplayLockout(const std::string& name, const DzLockout& lockout, bool is_solo)
const std::string& member_name, const ExpeditionLockoutTimer& lockout, bool is_solo)
{ {
if (m_disable_messages) if (m_silent)
{ {
return; return;
} }
auto time_remaining = lockout.GetDaysHoursMinutesRemaining(); auto time = lockout.GetTimeRemainingStrs();
if (is_solo) if (is_solo)
{ {
SendLeaderMessage(Chat::Red, EXPEDITION_YOU_PLAYED_HERE, { SendLeaderMessage(Chat::Red, DZ_REPLAY_YOU, { time.days, time.hours, time.mins });
time_remaining.days, time_remaining.hours, time_remaining.mins
});
} }
else else
{ {
SendLeaderMessage(Chat::Red, EXPEDITION_REPLAY_TIMER, { SendLeaderMessage(Chat::Red, DZ_REPLAY_OTHER, { name, time.days, time.hours, time.mins });
member_name, time_remaining.days, time_remaining.hours, time_remaining.mins
});
} }
} }
void ExpeditionRequest::SendLeaderMemberEventLockout( void ExpeditionRequest::SendLeaderMemberEventLockout(const std::string& name, const DzLockout& lockout)
const std::string& member_name, const ExpeditionLockoutTimer& lockout)
{ {
if (m_disable_messages) if (m_silent)
{ {
return; return;
} }
auto time_remaining = lockout.GetDaysHoursMinutesRemaining(); auto time = lockout.GetTimeRemainingStrs();
SendLeaderMessage(Chat::Red, EXPEDITION_EVENT_TIMER, { SendLeaderMessage(Chat::Red, DZ_EVENT_TIMER, { name, lockout.Event(), time.days, time.hours, time.mins });
member_name,
lockout.GetEventName(),
time_remaining.days,
time_remaining.hours,
time_remaining.mins,
lockout.GetEventName()
});
} }
bool ExpeditionRequest::IsPlayerCountValidated() bool ExpeditionRequest::IsPlayerCountValidated()
@ -343,19 +301,14 @@ bool ExpeditionRequest::IsPlayerCountValidated()
auto bypass_status = RuleI(Expedition, MinStatusToBypassPlayerCountRequirements); auto bypass_status = RuleI(Expedition, MinStatusToBypassPlayerCountRequirements);
auto gm_bypass = (m_requester && m_requester->GetGM() && m_requester->Admin() >= bypass_status); auto gm_bypass = (m_requester && m_requester->GetGM() && m_requester->Admin() >= bypass_status);
if (m_members.size() > m_max_players) if (!gm_bypass && m_members.size() < m_dz->GetMinPlayers())
{
// 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)
{ {
requirements_met = false; 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_members.size()).str(),
fmt::format_int(m_min_players).str(), fmt::format_int(m_dz->GetMinPlayers()).str(),
fmt::format_int(m_max_players).str() fmt::format_int(m_dz->GetMaxPlayers()).str()
}); });
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -161,7 +161,7 @@ public:
inline int GetMentorPercent() { return mentor_percent; } inline int GetMentorPercent() { return mentor_percent; }
inline Client *GetMentoree() { return mentoree; } 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}; Mob* members[MAX_GROUP_MEMBERS] {nullptr};
char membername[MAX_GROUP_MEMBERS][64] {""}; 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_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); 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_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); 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) { Lua_Expedition Lua_Client::CreateExpeditionFromTemplate(uint32_t dz_template_id) {
@ -1968,16 +1968,15 @@ luabind::object Lua_Client::GetExpeditionLockouts(lua_State* L)
if (d_) if (d_)
{ {
auto self = reinterpret_cast<NativeType*>(d_); auto self = reinterpret_cast<NativeType*>(d_);
auto lockouts = self->GetExpeditionLockouts(); const auto& lockouts = self->GetDzLockouts();
for (const auto& lockout : lockouts) 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) if (luabind::type(lockout_table) != LUA_TTABLE)
{ {
lockout_table = luabind::newtable(L); lockout_table = luabind::newtable(L);
} }
lockout_table[lockout.GetEventName()] = lockout.GetSecondsRemaining(); lockout_table[lockout.Event()] = lockout.GetSecondsRemaining();
} }
} }
return lua_table; return lua_table;
@ -1989,13 +1988,12 @@ luabind::object Lua_Client::GetExpeditionLockouts(lua_State* L, std::string expe
if (d_) if (d_)
{ {
auto self = reinterpret_cast<NativeType*>(d_); auto self = reinterpret_cast<NativeType*>(d_);
auto lockouts = self->GetExpeditionLockouts(); const auto& lockouts = self->GetDzLockouts();
for (const auto& lockout : lockouts) 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) { std::string Lua_Client::GetLockoutExpeditionUUID(std::string expedition_name, std::string event_name) {
Lua_Safe_Call_String(); Lua_Safe_Call_String();
std::string uuid; std::string uuid;
auto lockout = self->GetExpeditionLockout(expedition_name, event_name); auto lockout = self->GetDzLockout(expedition_name, event_name);
if (lockout) if (lockout)
{ {
uuid = lockout->GetExpeditionUUID(); uuid = lockout->UUID();
} }
return uuid; return uuid;
} }
void Lua_Client::AddExpeditionLockout(std::string expedition_name, std::string event_name, uint32 seconds) { void Lua_Client::AddExpeditionLockout(std::string expedition_name, std::string event_name, uint32 seconds) {
Lua_Safe_Call_Void(); 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) { void Lua_Client::AddExpeditionLockout(std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) {
Lua_Safe_Call_Void(); 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) { void Lua_Client::AddExpeditionLockoutDuration(std::string expedition_name, std::string event_name, int seconds) {
Lua_Safe_Call_Void(); 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) { void Lua_Client::AddExpeditionLockoutDuration(std::string expedition_name, std::string event_name, int seconds, std::string uuid) {
Lua_Safe_Call_Void(); 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() { void Lua_Client::RemoveAllExpeditionLockouts() {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->RemoveAllExpeditionLockouts({}, true); self->RemoveDzLockouts({}, true);
} }
void Lua_Client::RemoveAllExpeditionLockouts(std::string expedition_name) { void Lua_Client::RemoveAllExpeditionLockouts(std::string expedition_name) {
Lua_Safe_Call_Void(); 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) { void Lua_Client::RemoveExpeditionLockout(std::string expedition_name, std::string event_name) {
Lua_Safe_Call_Void(); 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) { bool Lua_Client::HasExpeditionLockout(std::string expedition_name, std::string event_name) {
Lua_Safe_Call_Bool(); 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) { void Lua_Client::MovePCDynamicZone(uint32 zone_id) {

View File

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

View File

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

View File

@ -25,8 +25,8 @@
#include "encounter.h" #include "encounter.h"
#include "lua_encounter.h" #include "lua_encounter.h"
#include "data_bucket.h" #include "data_bucket.h"
#include "expedition.h"
#include "dialogue_window.h" #include "dialogue_window.h"
#include "dynamic_zone.h"
#include "../common/events/player_event_logs.h" #include "../common/events/player_event_logs.h"
#include "worldserver.h" #include "worldserver.h"
#include "zone.h" #include "zone.h"
@ -1828,36 +1828,36 @@ void lua_set_content_flag(std::string flag_name, bool enabled){
Lua_Expedition lua_get_expedition() { Lua_Expedition lua_get_expedition() {
if (zone && zone->GetInstanceID() != 0) if (zone && zone->GetInstanceID() != 0)
{ {
return Expedition::FindCachedExpeditionByZoneInstance(zone->GetZoneID(), zone->GetInstanceID()); return DynamicZone::FindExpeditionByZone(zone->GetZoneID(), zone->GetInstanceID());
} }
return nullptr; return nullptr;
} }
Lua_Expedition lua_get_expedition_by_char_id(uint32 char_id) { 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) { 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) { 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::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); 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) { auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const DzLockout& lockout) {
return lockout.IsSameLockout(expedition_name, event_name); return lockout.IsSame(expedition_name, event_name);
}); });
if (it != lockouts.end()) if (it != lockouts.end())
{ {
lua_table["remaining"] = it->GetSecondsRemaining(); lua_table["remaining"] = it->GetSecondsRemaining();
lua_table["uuid"] = it->GetExpeditionUUID(); lua_table["uuid"] = it->UUID();
} }
return lua_table; 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::object lua_get_expedition_lockouts_by_char_id(lua_State* L, uint32 char_id) {
luabind::adl::object lua_table = luabind::newtable(L); 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) 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) if (luabind::type(lockout_table) != LUA_TTABLE)
{ {
lockout_table = luabind::newtable(L); 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) if (luabind::type(event_table) != LUA_TTABLE)
{ {
event_table = luabind::newtable(L); event_table = luabind::newtable(L);
} }
event_table["remaining"] = lockout.GetSecondsRemaining(); event_table["remaining"] = lockout.GetSecondsRemaining();
event_table["uuid"] = lockout.GetExpeditionUUID(); event_table["uuid"] = lockout.UUID();
} }
return lua_table; 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::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); 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) 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) if (luabind::type(event_table) != LUA_TTABLE)
{ {
event_table = luabind::newtable(L); event_table = luabind::newtable(L);
} }
event_table["remaining"] = lockout.GetSecondsRemaining(); event_table["remaining"] = lockout.GetSecondsRemaining();
event_table["uuid"] = lockout.GetExpeditionUUID(); event_table["uuid"] = lockout.UUID();
} }
} }
return lua_table; return lua_table;
} }
void lua_add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds) { 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); auto lockout = DzLockout::Create(expedition_name, event_name, seconds);
Expedition::AddLockoutClients(lockout); DynamicZone::AddClientsLockout(lockout);
} }
void lua_add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) { 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); auto lockout = DzLockout::Create(expedition_name, event_name, seconds, uuid);
Expedition::AddLockoutClients(lockout); DynamicZone::AddClientsLockout(lockout);
} }
void lua_add_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name, uint32 seconds) { 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) { 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) { 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) { 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) { 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) { 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) bool Lua_Group::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name)
{ {
Lua_Safe_Call_Bool(); 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) bool Lua_Group::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name, int max_check_count)
{ {
Lua_Safe_Call_Bool(); 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() { 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) bool Lua_Raid::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name)
{ {
Lua_Safe_Call_Bool(); 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) bool Lua_Raid::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name, int max_check_count)
{ {
Lua_Safe_Call_Bool(); 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() { luabind::scope lua_register_raid() {

View File

@ -5,7 +5,7 @@
#include "../common/global_define.h" #include "../common/global_define.h"
#include "embperl.h" #include "embperl.h"
#include "client.h" #include "client.h"
#include "expedition.h" #include "dynamic_zone.h"
#include "titles.h" #include "titles.h"
#include "dialogue_window.h" #include "dialogue_window.h"
@ -1775,7 +1775,7 @@ DynamicZoneLocation GetDynamicZoneLocationFromHash(perl::hash table)
return { zone_id, x, y, z, h }; 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 table = table_ref;
perl::hash expedition = table["expedition"]; perl::hash expedition = table["expedition"];
@ -1822,17 +1822,17 @@ Expedition* Perl_Client_CreateExpedition(Client* self, perl::reference table_ref
return self->CreateExpedition(dz); 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); 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); self->CreateTaskDynamicZone(task_id, dz);
} }
Expedition* Perl_Client_GetExpedition(Client* self) DynamicZone* Perl_Client_GetExpedition(Client* self)
{ {
return self->GetExpedition(); return self->GetExpedition();
} }
@ -1884,15 +1884,15 @@ perl::reference Perl_Client_GetExpeditionLockouts(Client* self)
{ {
perl::hash lockout_hash; perl::hash lockout_hash;
auto lockouts = self->GetExpeditionLockouts(); const auto& lockouts = self->GetDzLockouts();
for (const auto& lockout : lockouts) 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 perl::hash events = lockout_hash[lockout.DzName()]; // nested
events[lockout.GetEventName()] = lockout.GetSecondsRemaining(); events[lockout.Event()] = lockout.GetSecondsRemaining();
} }
return perl::reference(lockout_hash); return perl::reference(lockout_hash);
@ -1902,10 +1902,10 @@ perl::reference Perl_Client_GetExpeditionLockouts(Client* self, std::string expe
{ {
perl::hash event_hash; perl::hash event_hash;
auto lockouts = self->GetExpeditionLockouts(expedition_name); auto lockouts = self->GetDzLockouts(expedition_name);
for (const auto& lockout : lockouts) for (const auto& lockout : lockouts)
{ {
event_hash[lockout.GetEventName()] = lockout.GetSecondsRemaining(); event_hash[lockout.Event()] = lockout.GetSecondsRemaining();
} }
return perl::reference(event_hash); 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) std::string Perl_Client_GetLockoutExpeditionUUID(Client* self, std::string expedition_name, std::string event_name)
{ {
auto lockout = self->GetExpeditionLockout(expedition_name, event_name); auto lockout = self->GetDzLockout(expedition_name, event_name);
return lockout ? lockout->GetExpeditionUUID() : std::string{}; return lockout ? lockout->UUID() : std::string{};
} }
void Perl_Client_AddExpeditionLockout(Client* self, std::string expedition_name, std::string event_name, uint32 seconds) 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) 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) 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) 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) void Perl_Client_RemoveAllExpeditionLockouts(Client* self)
{ {
self->RemoveAllExpeditionLockouts({}, true); self->RemoveDzLockouts({}, true);
} }
void Perl_Client_RemoveAllExpeditionLockouts(Client* self, std::string expedition_name) 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) 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) 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) 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("CountAugmentEquippedByID", &Perl_Client_CountAugmentEquippedByID);
package.add("CountItem", &Perl_Client_CountItem); package.add("CountItem", &Perl_Client_CountItem);
package.add("CountItemEquippedByID", &Perl_Client_CountItemEquippedByID); package.add("CountItemEquippedByID", &Perl_Client_CountItemEquippedByID);
package.add("CreateExpedition", (Expedition*(*)(Client*, perl::reference))&Perl_Client_CreateExpedition); package.add("CreateExpedition", (DynamicZone*(*)(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", (DynamicZone*(*)(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*, std::string, uint32, uint32, std::string, uint32, uint32, bool))&Perl_Client_CreateExpedition);
package.add("CreateExpeditionFromTemplate", &Perl_Client_CreateExpeditionFromTemplate); package.add("CreateExpeditionFromTemplate", &Perl_Client_CreateExpeditionFromTemplate);
package.add("CreateTaskDynamicZone", &Perl_Client_CreateTaskDynamicZone); package.add("CreateTaskDynamicZone", &Perl_Client_CreateTaskDynamicZone);
package.add("DecreaseByID", &Perl_Client_DecreaseByID); package.add("DecreaseByID", &Perl_Client_DecreaseByID);

View File

@ -3,214 +3,209 @@
#ifdef EMBPERL_XS_CLASSES #ifdef EMBPERL_XS_CLASSES
#include "embperl.h" #include "embperl.h"
#include "expedition.h" #include "dynamic_zone.h"
#include "../common/zone_store.h" #include "../common/zone_store.h"
#include "../common/global_define.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); 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); 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); 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) uint32_t Perl_Expedition_GetID(DynamicZone* self)
{
return self->GetDynamicZone()->GetID();
}
uint32_t Perl_Expedition_GetID(Expedition* self)
{ {
return self->GetID(); 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(); return self->GetLeaderName();
} }
perl::reference Perl_Expedition_GetLockouts(Expedition* self) perl::reference Perl_Expedition_GetLockouts(DynamicZone* self)
{ {
perl::hash table; perl::hash table;
auto lockouts = self->GetLockouts(); const auto& lockouts = self->GetLockouts();
for (const auto& lockout : lockouts) for (const auto& lockout : lockouts)
{ {
table[lockout.first] = lockout.second.GetSecondsRemaining(); table[lockout.Event()] = lockout.GetSecondsRemaining();
} }
return perl::reference(table); 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; perl::hash table;
for (const auto& member : self->GetDynamicZone()->GetMembers()) for (const auto& member : self->GetMembers())
{ {
table[member.name] = member.id; table[member.name] = member.id;
} }
return perl::reference(table); return perl::reference(table);
} }
std::string Perl_Expedition_GetName(Expedition* self) std::string Perl_Expedition_GetName(DynamicZone* self)
{ {
return self->GetName(); 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); return self->HasLockout(event_name);
} }
bool Perl_Expedition_HasReplayLockout(Expedition* self) bool Perl_Expedition_HasReplayLockout(DynamicZone* self)
{ {
return self->HasReplayLockout(); return self->HasReplayLockout();
} }
bool Perl_Expedition_IsLocked(Expedition* self) bool Perl_Expedition_IsLocked(DynamicZone* self)
{ {
return self->IsLocked(); 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); 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>(); 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>(); 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); 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); self->UpdateLockoutDuration(event_name, seconds, members_only);
} }
@ -219,14 +214,14 @@ void perl_register_expedition()
{ {
perl::interpreter perl(PERL_GET_THX); 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("AddLockout", &Perl_Expedition_AddLockout);
package.add("AddLockoutDuration", (void(*)(Expedition*, std::string, int))&Perl_Expedition_AddLockoutDuration); package.add("AddLockoutDuration", (void(*)(DynamicZone*, 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, bool))&Perl_Expedition_AddLockoutDuration);
package.add("AddReplayLockout", &Perl_Expedition_AddReplayLockout); package.add("AddReplayLockout", &Perl_Expedition_AddReplayLockout);
package.add("AddReplayLockoutDuration", (void(*)(Expedition*, int))&Perl_Expedition_AddReplayLockoutDuration); package.add("AddReplayLockoutDuration", (void(*)(DynamicZone*, int))&Perl_Expedition_AddReplayLockoutDuration);
package.add("AddReplayLockoutDuration", (void(*)(Expedition*, int, bool))&Perl_Expedition_AddReplayLockoutDuration); package.add("AddReplayLockoutDuration", (void(*)(DynamicZone*, int, bool))&Perl_Expedition_AddReplayLockoutDuration);
package.add("GetDynamicZoneID", &Perl_Expedition_GetDynamicZoneID); package.add("GetDynamicZoneID", &Perl_Expedition_GetID);
package.add("GetID", &Perl_Expedition_GetID); package.add("GetID", &Perl_Expedition_GetID);
package.add("GetInstanceID", &Perl_Expedition_GetInstanceID); package.add("GetInstanceID", &Perl_Expedition_GetInstanceID);
package.add("GetLeaderName", &Perl_Expedition_GetLeaderName); package.add("GetLeaderName", &Perl_Expedition_GetLeaderName);
@ -247,9 +242,9 @@ void perl_register_expedition()
package.add("RemoveCompass", &Perl_Expedition_RemoveCompass); package.add("RemoveCompass", &Perl_Expedition_RemoveCompass);
package.add("RemoveLockout", &Perl_Expedition_RemoveLockout); package.add("RemoveLockout", &Perl_Expedition_RemoveLockout);
package.add("SetCompass", &Perl_Expedition_SetCompass); package.add("SetCompass", &Perl_Expedition_SetCompass);
package.add("SetLocked", (void(*)(Expedition*, bool))&Perl_Expedition_SetLocked); package.add("SetLocked", (void(*)(DynamicZone*, bool))&Perl_Expedition_SetLocked);
package.add("SetLocked", (void(*)(Expedition*, bool, int))&Perl_Expedition_SetLocked); package.add("SetLocked", (void(*)(DynamicZone*, bool, int))&Perl_Expedition_SetLocked);
package.add("SetLocked", (void(*)(Expedition*, bool, int, uint32_t))&Perl_Expedition_SetLocked); package.add("SetLocked", (void(*)(DynamicZone*, bool, int, uint32_t))&Perl_Expedition_SetLocked);
package.add("SetLootEventByNPCTypeID", &Perl_Expedition_SetLootEventByNPCTypeID); package.add("SetLootEventByNPCTypeID", &Perl_Expedition_SetLootEventByNPCTypeID);
package.add("SetLootEventBySpawnID", &Perl_Expedition_SetLootEventBySpawnID); package.add("SetLootEventBySpawnID", &Perl_Expedition_SetLootEventBySpawnID);
package.add("SetReplayLockoutOnMemberJoin", &Perl_Expedition_SetReplayLockoutOnMemberJoin); package.add("SetReplayLockoutOnMemberJoin", &Perl_Expedition_SetReplayLockoutOnMemberJoin);
@ -257,8 +252,8 @@ void perl_register_expedition()
package.add("SetSecondsRemaining", &Perl_Expedition_SetSecondsRemaining); package.add("SetSecondsRemaining", &Perl_Expedition_SetSecondsRemaining);
package.add("SetSwitchID", &Perl_Expedition_SetSwitchID); package.add("SetSwitchID", &Perl_Expedition_SetSwitchID);
package.add("SetZoneInLocation", &Perl_Expedition_SetZoneInLocation); package.add("SetZoneInLocation", &Perl_Expedition_SetZoneInLocation);
package.add("UpdateLockoutDuration", (void(*)(Expedition*, std::string, uint32_t))&Perl_Expedition_UpdateLockoutDuration); package.add("UpdateLockoutDuration", (void(*)(DynamicZone*, 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, bool))&Perl_Expedition_UpdateLockoutDuration);
} }
void perl_register_expedition_lock_messages() void perl_register_expedition_lock_messages()
@ -266,9 +261,9 @@ void perl_register_expedition_lock_messages()
perl::interpreter perl(PERL_GET_THX); perl::interpreter perl(PERL_GET_THX);
auto package = perl.new_package("ExpeditionLockMessage"); auto package = perl.new_package("ExpeditionLockMessage");
package.add_const("None", static_cast<int>(ExpeditionLockMessage::None)); package.add_const("None", static_cast<int>(DzLockMsg::None));
package.add_const("Close", static_cast<int>(ExpeditionLockMessage::Close)); package.add_const("Close", static_cast<int>(DzLockMsg::Close));
package.add_const("Begin", static_cast<int>(ExpeditionLockMessage::Begin)); package.add_const("Begin", static_cast<int>(DzLockMsg::Begin));
} }
#endif //EMBPERL_XS_CLASSES #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) 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) 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 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) 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) 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) { int Perl_Raid_GetGroupNumber(Raid* self, int member_index) {

View File

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

View File

@ -328,42 +328,42 @@
#define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1! #define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1!
#define TASK_UPDATED 3471 //Your task '%1' has been updated. #define TASK_UPDATED 3471 //Your task '%1' has been updated.
#define YOU_ASSIGNED_TASK 3472 //You have been assigned the task '%1'. #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 DZ_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 DZ_REPLAY_YOU 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 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 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 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 EXPEDITION_AVAILABLE 3507 //%1 is now available to you. #define DZ_AVAILABLE 3507 //%1 is now available to you.
#define DZADD_INVITE 3508 //Sending an invitation to: %1. #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 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 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 DZ_NO_LEADER_INFO 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 DZ_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 DZ_NOT_MEMBER 3514 //%1 is not a member of this expedition.
#define EXPEDITION_REMOVED 3516 //%1 has been removed from %2. #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 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 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 DZLIST_REPLAY_TIMER 3519 //You have %1d:%2h:%3m remaining until you may enter %4. #define DZ_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 DZ_LEADER_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 DZ_LEADER_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 DZ_INVITE_ACCEPTED 3522 //%1 has accepted your offer to join your expedition.
#define EXPEDITION_MEMBER_ADDED 3523 //%1 has been added to %2. #define DZ_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 DZ_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 DZ_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 DZ_INVITED 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 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 EXPEDITION_NO_TIMERS 3529 //You have no outstanding timers. #define DZ_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 DZ_MINUTES_REMAIN 3551 //You only have %1 minutes remaining before this expedition comes to an end.
#define EXPEDITION_LEADER 3552 //Expedition Leader: %1 #define DZ_LEADER 3552 //Expedition Leader: %1
#define EXPEDITION_MEMBERS 3553 //Expedition Members: %1 #define DZ_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_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 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 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_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_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_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_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_LEAVE_ZONE 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_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_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_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. #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.SetMinPlayers(task->min_players);
dz_request.SetMaxPlayers(task->max_players); dz_request.SetMaxPlayers(task->max_players);
// a task might create a dz from an objective so override dz duration to time remaining // a task might create a dz from an element so override dz duration to time remaining
// live probably creates the dz with the shared task and just adds members for objectives
std::chrono::seconds seconds(TaskTimeLeft(task_id)); std::chrono::seconds seconds(TaskTimeLeft(task_id));
if (task->duration == 0 || seconds.count() < 0) if (task->duration == 0 || seconds.count() < 0)
{ {
// todo: maybe add a rule for duration
// cap unlimited duration tasks so instance isn't held indefinitely // cap unlimited duration tasks so instance isn't held indefinitely
// expected behavior is to re-acquire any unlimited tasks that have an expired dz // 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)); 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())); dz_request.SetDuration(static_cast<uint32_t>(seconds.count()));
if (task->type == TaskType::Task || task->type == TaskType::Quest) if (task->type == TaskType::Shared)
{
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)
{ {
dz_request.SetType(DynamicZoneType::Mission); dz_request.SetType(DynamicZoneType::Mission);
// shared task missions are created in world // 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 pack = std::make_unique<ServerPacket>(ServerOP_SharedTaskCreateDynamicZone, static_cast<uint32_t>(pack_size));
auto buf = reinterpret_cast<ServerSharedTaskCreateDynamicZone_Struct*>(pack->pBuffer); auto buf = reinterpret_cast<ServerSharedTaskCreateDynamicZone_Struct*>(pack->pBuffer);
buf->source_character_id = client->CharacterID(); buf->source_character_id = client->CharacterID();
buf->task_id = task_id; buf->task_id = task_id;
buf->cereal_size = static_cast<uint32_t>(dyn_pack.Length()); buf->cereal_size = static_cast<uint32_t>(sv.size());
memcpy(buf->cereal_data, dyn_pack.Data(), dyn_pack.Length()); memcpy(buf->cereal_data, sv.data(), sv.size());
worldserver.SendPacket(pack.get()); 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 "client.h"
#include "command.h" #include "command.h"
#include "corpse.h" #include "corpse.h"
#include "dynamic_zone.h"
#include "entity.h" #include "entity.h"
#include "expedition.h"
#include "quest_parser_collection.h" #include "quest_parser_collection.h"
#include "guild_mgr.h" #include "guild_mgr.h"
#include "mob.h" #include "mob.h"
@ -3601,20 +3601,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
break; 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_DzCreated:
case ServerOP_DzDeleted: case ServerOP_DzDeleted:
case ServerOP_DzAddPlayer:
case ServerOP_DzMakeLeader:
case ServerOP_DzAddRemoveMember: case ServerOP_DzAddRemoveMember:
case ServerOP_DzSwapMembers: case ServerOP_DzSwapMembers:
case ServerOP_DzRemoveAllMembers: case ServerOP_DzRemoveAllMembers:
@ -3628,6 +3618,11 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
case ServerOP_DzLeaderChanged: case ServerOP_DzLeaderChanged:
case ServerOP_DzExpireWarning: case ServerOP_DzExpireWarning:
case ServerOP_DzMovePC: case ServerOP_DzMovePC:
case ServerOP_DzLock:
case ServerOP_DzReplayOnJoin:
case ServerOP_DzLockout:
case ServerOP_DzLockoutDuration:
case ServerOP_DzCharacterLockout:
{ {
DynamicZone::HandleWorldMessage(pack); DynamicZone::HandleWorldMessage(pack);
break; break;

View File

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

View File

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

View File

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