mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-06 00:32:25 +00:00
104 lines
3.4 KiB
C++
104 lines
3.4 KiB
C++
//
|
|
// Created by dannu on 4/21/2026.
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
|
|
#include "common/emu_versions.h"
|
|
|
|
#include "zone/client.h"
|
|
#include "zone/mob.h"
|
|
|
|
namespace ZoneClient {
|
|
|
|
namespace Message { class IMessage; }
|
|
|
|
// store all static functions for the different patches here
|
|
class ClientPatch {
|
|
public:
|
|
using ClientList = std::unordered_map<uint16, Client*>;
|
|
static const std::shared_ptr<Message::IMessage>& GetMessageComponent(EQ::versions::ClientVersion version);
|
|
|
|
template<typename Fun, typename Obj, typename... Args>
|
|
static void QueuePacket(Client* c, Fun fun, Obj* obj, Args&&... args)
|
|
{
|
|
static_assert(std::is_member_function_pointer_v<Fun>);
|
|
EQApplicationPacket* app = std::invoke(fun, obj, std::forward<Args>(args)...);
|
|
if (app != nullptr) {
|
|
c->QueuePacket(app);
|
|
delete app;
|
|
}
|
|
}
|
|
|
|
// packet generator queue functions
|
|
static auto QueueClients(Mob* sender, bool ignore_sender = false, bool ackreq = true)
|
|
{
|
|
return [=]<typename Fun, typename Obj, typename... Args>(Fun fun, std::function<Obj*(const Client*)> component_getter, Args&&... args) {
|
|
static_assert(std::is_member_function_pointer_v<Fun> && "Function is required to be a member function");
|
|
|
|
std::unordered_map<EQ::versions::ClientVersion, EQApplicationPacket*> build_packets;
|
|
std::unordered_map<uint16, Client*> client_list = entity_list.GetClientList();
|
|
|
|
for (auto [_, ent] : client_list) {
|
|
if (!ignore_sender || ent != sender) {
|
|
auto [packet, _] = build_packets.try_emplace(
|
|
ent->ClientVersion(),
|
|
std::invoke(fun, component_getter(ent), std::forward<Args>(args)...));
|
|
|
|
if (packet->second != nullptr)
|
|
ent->QueuePacket(packet->second, ackreq, Client::CLIENT_CONNECTED);
|
|
}
|
|
}
|
|
|
|
for (auto [_, packet] : build_packets)
|
|
if (packet != nullptr)
|
|
delete packet;
|
|
};
|
|
}
|
|
|
|
static auto QueueCloseClients(
|
|
Mob* sender, bool ignore_sender = false, float distance = 200,
|
|
Mob* skipped_mob = nullptr, bool is_ack_required = true,
|
|
eqFilterType filter = FilterNone)
|
|
{
|
|
if (distance <= 0) distance = static_cast<float>(zone->GetClientUpdateRange());
|
|
|
|
return [=]<typename Fun, typename Obj, typename... Args>(Fun fun, std::function<Obj*(const Client*)> component_getter, Args&&... args) {
|
|
static_assert(std::is_member_function_pointer_v<Fun> && "Function is required to be a member function");
|
|
|
|
if (sender == nullptr) {
|
|
QueueClients(sender, ignore_sender, is_ack_required)(fun, component_getter, std::forward<Args>(args)...);
|
|
} else {
|
|
float distance_squared = distance * distance;
|
|
std::unordered_map<EQ::versions::ClientVersion, EQApplicationPacket*> build_packets;
|
|
|
|
for (auto& [_, mob] : sender->GetCloseMobList(distance)) {
|
|
if (mob && mob->IsClient()) {
|
|
Client* client = mob->CastToClient();
|
|
if ((!ignore_sender || client != sender)
|
|
&& client != skipped_mob
|
|
&& DistanceSquared(client->GetPosition(), sender->GetPosition()) < distance_squared
|
|
&& client->Connected()
|
|
&& client->ShouldGetPacket(sender, filter)) {
|
|
auto [packet, _] = build_packets.try_emplace(
|
|
client->ClientVersion(),
|
|
std::invoke(fun, component_getter(client), std::forward<Args>(args)...));
|
|
|
|
if (packet->second != nullptr)
|
|
client->QueuePacket(packet->second, is_ack_required, Client::CLIENT_CONNECTED);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto [_, packet] : build_packets)
|
|
if (packet != nullptr)
|
|
delete packet;;
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
}
|