diff --git a/common/patches/client_version.cpp b/common/patches/client_version.cpp index 94ac4b483..667c525b5 100644 --- a/common/patches/client_version.cpp +++ b/common/patches/client_version.cpp @@ -51,9 +51,11 @@ struct ClientComponents case Version::SoF: messageComponent = std::make_unique(); break; - default: + case Version::Titanium: messageComponent = std::make_unique(); break; + default: + break; } } @@ -61,19 +63,22 @@ struct ClientComponents std::unique_ptr messageComponent; }; -static const std::unordered_map s_patches = [] { - std::unordered_map p; - p.emplace(Version::Titanium, Version::Titanium); - p.emplace(Version::SoF, Version::SoF); - p.emplace(Version::SoD, Version::SoD); - p.emplace(Version::UF, Version::UF); - p.emplace(Version::RoF, Version::RoF); - p.emplace(Version::RoF2, Version::RoF2); - p.emplace(Version::TOB, Version::TOB); - return p; -}(); +// this array must be in the same order as the Version enum because it converts Version to index directly +static const std::array s_patches = { + { + ClientComponents(Version::Unknown), // empty + ClientComponents(Version::Client62), // empty + ClientComponents(Version::Titanium), + ClientComponents(Version::SoF), + ClientComponents(Version::SoD), + ClientComponents(Version::UF), + ClientComponents(Version::RoF), + ClientComponents(Version::RoF2), + ClientComponents(Version::TOB), + } +}; const std::unique_ptr& GetMessageComponent(Version version) { - return s_patches.at(version).messageComponent; + return s_patches.at(static_cast(version)).messageComponent; } diff --git a/common/patches/client_version.h b/common/patches/client_version.h index 054cd2a7d..a0ebf9c3a 100644 --- a/common/patches/client_version.h +++ b/common/patches/client_version.h @@ -9,5 +9,5 @@ namespace Message { class IMessage; } -// store all static functions for the different patches here +// store all static functions for the different patches here, this can return nullptr for unsupported patches const std::unique_ptr& GetMessageComponent(EQ::versions::ClientVersion version); diff --git a/zone/client_version.h b/zone/client_version.h index 640720fb2..6c710658c 100644 --- a/zone/client_version.h +++ b/zone/client_version.h @@ -22,15 +22,17 @@ template requires std::is_member_function_pointer_v static void QueuePacket(Client* c, Fun fun, Obj* obj, Args&&... args) { - std::unique_ptr app = std::invoke(fun, obj, std::forward(args)...); - if (app) - c->QueuePacket(app.get()); + if (obj != nullptr) { + std::unique_ptr app = std::invoke(fun, obj, std::forward(args)...); + if (app) + c->QueuePacket(app.get()); + } } // packet generator queue functions static auto QueueClients(Mob* sender, bool ignore_sender = false, bool ackreq = true) { - return [=](Fun fun, ComponentGetter component, Args&&... args) + return [=](Fun fun, const ComponentGetter& component, Args&&... args) requires std::is_member_function_pointer_v { std::vector>> build_packets; @@ -44,8 +46,9 @@ static auto QueueClients(Mob* sender, bool ignore_sender = false, bool ackreq = }); if (packet_it == build_packets.end()) - packet_it = build_packets.emplace(build_packets.end(), ent->ClientVersion(), - std::invoke(fun, component(ent), std::forward(args)...)); + if (Obj* comp = component(ent); comp != nullptr) + packet_it = build_packets.emplace(build_packets.end(), ent->ClientVersion(), + std::invoke(fun, comp, std::forward(args)...)); if (packet_it->second != nullptr) ent->QueuePacket(packet_it->second.get(), ackreq, Client::CLIENT_CONNECTED); @@ -61,7 +64,7 @@ static auto QueueCloseClients( { if (distance <= 0) distance = static_cast(zone->GetClientUpdateRange()); - return [=](Fun fun, ComponentGetter component, Args&&... args) + return [=](Fun fun, const ComponentGetter& component, Args&&... args) requires std::is_member_function_pointer_v { if (sender == nullptr) { @@ -85,8 +88,9 @@ static auto QueueCloseClients( }); if (packet_it == build_packets.end()) - packet_it = build_packets.emplace(build_packets.end(), client->ClientVersion(), - std::invoke(fun, component(client), std::forward(args)...)); + if (auto comp = component(client); comp != nullptr) + packet_it = build_packets.emplace(build_packets.end(), client->ClientVersion(), + std::invoke(fun, comp, std::forward(args)...)); if (packet_it->second != nullptr) client->QueuePacket(packet_it->second.get(), is_ack_required, Client::CLIENT_CONNECTED); @@ -101,6 +105,8 @@ static auto QueueCloseClients( // Helpers for the Message interface to send message packets namespace Message { + +// this can return nullptr when the component doesn't exist for the version static std::function GetComponent = [](const Client* c) -> IMessage* { return GetMessageComponent(c->GetClientVersion()).get(); };