Updated patch map to an array and added null safety checks for the conversion

This commit is contained in:
dannuic
2026-04-25 16:54:30 -06:00
parent 0a6dd09f2c
commit 40870924e9
3 changed files with 34 additions and 23 deletions
+18 -13
View File
@@ -51,9 +51,11 @@ struct ClientComponents
case Version::SoF: case Version::SoF:
messageComponent = std::make_unique<Message::SoF>(); messageComponent = std::make_unique<Message::SoF>();
break; break;
default: case Version::Titanium:
messageComponent = std::make_unique<Message::Titanium>(); messageComponent = std::make_unique<Message::Titanium>();
break; break;
default:
break;
} }
} }
@@ -61,19 +63,22 @@ struct ClientComponents
std::unique_ptr<Message::IMessage> messageComponent; std::unique_ptr<Message::IMessage> messageComponent;
}; };
static const std::unordered_map<Version, ClientComponents> s_patches = [] { // this array must be in the same order as the Version enum because it converts Version to index directly
std::unordered_map<Version, ClientComponents> p; static const std::array<ClientComponents, EQ::versions::ClientVersionCount> s_patches = {
p.emplace(Version::Titanium, Version::Titanium); {
p.emplace(Version::SoF, Version::SoF); ClientComponents(Version::Unknown), // empty
p.emplace(Version::SoD, Version::SoD); ClientComponents(Version::Client62), // empty
p.emplace(Version::UF, Version::UF); ClientComponents(Version::Titanium),
p.emplace(Version::RoF, Version::RoF); ClientComponents(Version::SoF),
p.emplace(Version::RoF2, Version::RoF2); ClientComponents(Version::SoD),
p.emplace(Version::TOB, Version::TOB); ClientComponents(Version::UF),
return p; ClientComponents(Version::RoF),
}(); ClientComponents(Version::RoF2),
ClientComponents(Version::TOB),
}
};
const std::unique_ptr<Message::IMessage>& GetMessageComponent(Version version) const std::unique_ptr<Message::IMessage>& GetMessageComponent(Version version)
{ {
return s_patches.at(version).messageComponent; return s_patches.at(static_cast<uint32_t>(version)).messageComponent;
} }
+1 -1
View File
@@ -9,5 +9,5 @@
namespace Message { class IMessage; } 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<Message::IMessage>& GetMessageComponent(EQ::versions::ClientVersion version); const std::unique_ptr<Message::IMessage>& GetMessageComponent(EQ::versions::ClientVersion version);
+10 -4
View File
@@ -22,15 +22,17 @@ template <typename Fun, typename Obj, typename... Args>
requires std::is_member_function_pointer_v<Fun> requires std::is_member_function_pointer_v<Fun>
static void QueuePacket(Client* c, Fun fun, Obj* obj, Args&&... args) static void QueuePacket(Client* c, Fun fun, Obj* obj, Args&&... args)
{ {
if (obj != nullptr) {
std::unique_ptr<EQApplicationPacket> app = std::invoke(fun, obj, std::forward<Args>(args)...); std::unique_ptr<EQApplicationPacket> app = std::invoke(fun, obj, std::forward<Args>(args)...);
if (app) if (app)
c->QueuePacket(app.get()); c->QueuePacket(app.get());
} }
}
// packet generator queue functions // packet generator queue functions
static auto QueueClients(Mob* sender, bool ignore_sender = false, bool ackreq = true) static auto QueueClients(Mob* sender, bool ignore_sender = false, bool ackreq = true)
{ {
return [=]<typename Fun, typename Obj, typename... Args>(Fun fun, ComponentGetter<Obj> component, Args&&... args) return [=]<typename Fun, typename Obj, typename... Args>(Fun fun, const ComponentGetter<Obj>& component, Args&&... args)
requires std::is_member_function_pointer_v<Fun> requires std::is_member_function_pointer_v<Fun>
{ {
std::vector<std::pair<EQ::versions::ClientVersion, std::unique_ptr<EQApplicationPacket>>> build_packets; std::vector<std::pair<EQ::versions::ClientVersion, std::unique_ptr<EQApplicationPacket>>> build_packets;
@@ -44,8 +46,9 @@ static auto QueueClients(Mob* sender, bool ignore_sender = false, bool ackreq =
}); });
if (packet_it == build_packets.end()) if (packet_it == build_packets.end())
if (Obj* comp = component(ent); comp != nullptr)
packet_it = build_packets.emplace(build_packets.end(), ent->ClientVersion(), packet_it = build_packets.emplace(build_packets.end(), ent->ClientVersion(),
std::invoke(fun, component(ent), std::forward<Args>(args)...)); std::invoke(fun, comp, std::forward<Args>(args)...));
if (packet_it->second != nullptr) if (packet_it->second != nullptr)
ent->QueuePacket(packet_it->second.get(), ackreq, Client::CLIENT_CONNECTED); ent->QueuePacket(packet_it->second.get(), ackreq, Client::CLIENT_CONNECTED);
@@ -61,7 +64,7 @@ static auto QueueCloseClients(
{ {
if (distance <= 0) distance = static_cast<float>(zone->GetClientUpdateRange()); if (distance <= 0) distance = static_cast<float>(zone->GetClientUpdateRange());
return [=]<typename Fun, typename Obj, typename... Args>(Fun fun, ComponentGetter<Obj> component, Args&&... args) return [=]<typename Fun, typename Obj, typename... Args>(Fun fun, const ComponentGetter<Obj>& component, Args&&... args)
requires std::is_member_function_pointer_v<Fun> requires std::is_member_function_pointer_v<Fun>
{ {
if (sender == nullptr) { if (sender == nullptr) {
@@ -85,8 +88,9 @@ static auto QueueCloseClients(
}); });
if (packet_it == build_packets.end()) if (packet_it == build_packets.end())
if (auto comp = component(client); comp != nullptr)
packet_it = build_packets.emplace(build_packets.end(), client->ClientVersion(), packet_it = build_packets.emplace(build_packets.end(), client->ClientVersion(),
std::invoke(fun, component(client), std::forward<Args>(args)...)); std::invoke(fun, comp, std::forward<Args>(args)...));
if (packet_it->second != nullptr) if (packet_it->second != nullptr)
client->QueuePacket(packet_it->second.get(), is_ack_required, Client::CLIENT_CONNECTED); 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 // Helpers for the Message interface to send message packets
namespace Message { namespace Message {
// this can return nullptr when the component doesn't exist for the version
static std::function GetComponent = [](const Client* c) -> IMessage* { static std::function GetComponent = [](const Client* c) -> IMessage* {
return GetMessageComponent(c->GetClientVersion()).get(); return GetMessageComponent(c->GetClientVersion()).get();
}; };