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