mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-28 17:37:18 +00:00
Merge branch 'tob_stringupgrade' into tob_buffupdate
This commit is contained in:
@@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "client_version.h"
|
||||||
#include "common/emu_opcodes.h"
|
#include "common/emu_opcodes.h"
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
@@ -24,11 +24,14 @@ public:
|
|||||||
IBuff() = default;
|
IBuff() = default;
|
||||||
virtual ~IBuff() = default;
|
virtual ~IBuff() = default;
|
||||||
|
|
||||||
virtual EQApplicationPacket* MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target, bool clear_buffs) const = 0;
|
virtual std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
|
||||||
|
bool clear_buffs) const = 0;
|
||||||
|
|
||||||
virtual EQApplicationPacket* BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const = 0;
|
virtual std::unique_ptr<EQApplicationPacket> BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot,
|
||||||
virtual EQApplicationPacket* RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove, bool buff_timers_suspended, const std::vector<uint32_t>& slots) const = 0;
|
bool fade) const = 0;
|
||||||
virtual void SetRefreshType(EQApplicationPacket* packet, Mob* source, Client* target) const = 0;
|
virtual std::unique_ptr<EQApplicationPacket> RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
|
||||||
|
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const = 0;
|
||||||
|
virtual void SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Buff
|
} // namespace Buff
|
||||||
|
|||||||
@@ -37,12 +37,14 @@ public:
|
|||||||
virtual ~IMessage() = default;
|
virtual ~IMessage() = default;
|
||||||
|
|
||||||
// these two are the basic string message packets
|
// these two are the basic string message packets
|
||||||
[[nodiscard]] virtual EQApplicationPacket* Simple(uint32_t color, uint32_t id) const = 0;
|
virtual std::unique_ptr<EQApplicationPacket> Simple(uint32_t color, uint32_t id) const = 0;
|
||||||
[[nodiscard]] virtual EQApplicationPacket* Formatted(uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const = 0;
|
virtual std::unique_ptr<EQApplicationPacket> Formatted(uint32_t color, uint32_t id,
|
||||||
|
const std::array<const char*, 9>& args) const = 0;
|
||||||
|
|
||||||
// These aren't technically messages, but they use the same format and are similar enough to include here
|
// These aren't technically messages, but they use the same format and are similar enough to include here
|
||||||
virtual EQApplicationPacket* InterruptSpell(uint32_t message, uint32_t spawn_id, const char* spell_link) const = 0;
|
virtual std::unique_ptr<EQApplicationPacket> InterruptSpell(uint32_t message, uint32_t spawn_id,
|
||||||
virtual EQApplicationPacket* InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
|
const char* spell_link) const = 0;
|
||||||
|
virtual std::unique_ptr<EQApplicationPacket> InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
|
||||||
const char* name, const char* spell_link) const = 0;
|
const char* name, const char* spell_link) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
#include "common/patches/rof2.h"
|
#include "common/patches/rof2.h"
|
||||||
#include "common/patches/tob.h"
|
#include "common/patches/tob.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
using Version = EQ::versions::ClientVersion;
|
using Version = EQ::versions::ClientVersion;
|
||||||
|
|
||||||
struct ClientComponents
|
struct ClientComponents
|
||||||
@@ -34,64 +36,64 @@ struct ClientComponents
|
|||||||
{
|
{
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case Version::TOB:
|
case Version::TOB:
|
||||||
buffComponent = std::make_shared<Buff::TOB>();
|
buffComponent = std::make_unique<Buff::TOB>();
|
||||||
messageComponent = std::make_shared<Message::TOB>();
|
messageComponent = std::make_unique<Message::TOB>();
|
||||||
break;
|
break;
|
||||||
case Version::RoF2:
|
case Version::RoF2:
|
||||||
buffComponent = std::make_shared<Buff::RoF2>();
|
buffComponent = std::make_unique<Buff::RoF2>();
|
||||||
messageComponent = std::make_shared<Message::RoF2>();
|
messageComponent = std::make_unique<Message::RoF2>();
|
||||||
break;
|
break;
|
||||||
case Version::RoF:
|
case Version::RoF:
|
||||||
buffComponent = std::make_shared<Buff::RoF>();
|
buffComponent = std::make_unique<Buff::RoF>();
|
||||||
messageComponent = std::make_shared<Message::RoF>();
|
messageComponent = std::make_unique<Message::RoF>();
|
||||||
break;
|
break;
|
||||||
case Version::UF:
|
case Version::UF:
|
||||||
buffComponent = std::make_shared<Buff::UF>();
|
buffComponent = std::make_unique<Buff::UF>();
|
||||||
messageComponent = std::make_shared<Message::UF>();
|
messageComponent = std::make_unique<Message::UF>();
|
||||||
break;
|
break;
|
||||||
case Version::SoD:
|
case Version::SoD:
|
||||||
buffComponent = std::make_shared<Buff::SoD>();
|
buffComponent = std::make_unique<Buff::SoD>();
|
||||||
messageComponent = std::make_shared<Message::SoD>();
|
messageComponent = std::make_unique<Message::SoD>();
|
||||||
break;
|
break;
|
||||||
case Version::SoF:
|
case Version::SoF:
|
||||||
buffComponent = std::make_shared<Buff::SoF>();
|
buffComponent = std::make_unique<Buff::SoF>();
|
||||||
messageComponent = std::make_shared<Message::SoF>();
|
messageComponent = std::make_unique<Message::SoF>();
|
||||||
|
break;
|
||||||
|
case Version::Titanium:
|
||||||
|
buffComponent = std::make_unique<Buff::Titanium>();
|
||||||
|
messageComponent = std::make_unique<Message::Titanium>();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
buffComponent = std::make_shared<Buff::Titanium>();
|
|
||||||
messageComponent = std::make_shared<Message::Titanium>();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Version version;
|
const Version version;
|
||||||
std::shared_ptr<Buff::IBuff> buffComponent;
|
std::unique_ptr<Buff::IBuff> buffComponent;
|
||||||
std::shared_ptr<Message::IMessage> messageComponent;
|
std::unique_ptr<Message::IMessage> messageComponent;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const ClientComponents& GetComponents(Version version)
|
// this array must be in the same order as the Version enum because it converts Version to index directly
|
||||||
|
static const std::array<ClientComponents, EQ::versions::ClientVersionCount> s_patches = {
|
||||||
{
|
{
|
||||||
static const std::unordered_map<Version, ClientComponents> patches = [] {
|
ClientComponents(Version::Unknown), // empty
|
||||||
std::unordered_map<Version, ClientComponents> p;
|
ClientComponents(Version::Client62), // empty
|
||||||
p.emplace(Version::Titanium, Version::Titanium);
|
ClientComponents(Version::Titanium),
|
||||||
p.emplace(Version::SoF, Version::SoF);
|
ClientComponents(Version::SoF),
|
||||||
p.emplace(Version::SoD, Version::SoD);
|
ClientComponents(Version::SoD),
|
||||||
p.emplace(Version::UF, Version::UF);
|
ClientComponents(Version::UF),
|
||||||
p.emplace(Version::RoF, Version::RoF);
|
ClientComponents(Version::RoF),
|
||||||
p.emplace(Version::RoF2, Version::RoF2);
|
ClientComponents(Version::RoF2),
|
||||||
p.emplace(Version::TOB, Version::TOB);
|
ClientComponents(Version::TOB),
|
||||||
return p;
|
}
|
||||||
}();
|
};
|
||||||
|
|
||||||
return patches.at(version);
|
const std::unique_ptr<Buff::IBuff>& GetBuffComponent(Version version)
|
||||||
|
{
|
||||||
|
return s_patches.at(static_cast<uint32_t>(version)).buffComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<Buff::IBuff>& GetBuffComponent(Version version)
|
const std::unique_ptr<Message::IMessage>& GetMessageComponent(Version version)
|
||||||
{
|
{
|
||||||
return GetComponents(version).buffComponent;
|
return s_patches.at(static_cast<uint32_t>(version)).messageComponent;
|
||||||
}
|
|
||||||
|
|
||||||
const std::shared_ptr<Message::IMessage>& GetMessageComponent(Version version)
|
|
||||||
{
|
|
||||||
return GetComponents(version).messageComponent;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ namespace Buff { class IBuff; }
|
|||||||
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
|
||||||
const std::shared_ptr<Buff::IBuff>& GetBuffComponent(EQ::versions::ClientVersion version);
|
// store all static functions for the different patches here, this can return nullptr for unsupported patches
|
||||||
const std::shared_ptr<Message::IMessage>& GetMessageComponent(EQ::versions::ClientVersion version);
|
const std::unique_ptr<Buff::IBuff>& GetBuffComponent(EQ::versions::ClientVersion version);
|
||||||
|
const std::unique_ptr<Message::IMessage>& GetMessageComponent(EQ::versions::ClientVersion version);
|
||||||
|
|||||||
+19
-21
@@ -3924,12 +3924,11 @@ namespace Titanium
|
|||||||
} /*Titanium*/
|
} /*Titanium*/
|
||||||
|
|
||||||
namespace Message {
|
namespace Message {
|
||||||
|
std::unique_ptr<EQApplicationPacket> Titanium::Simple(uint32_t color, uint32_t id) const
|
||||||
EQApplicationPacket* Titanium::Simple(uint32_t color, uint32_t id) const
|
|
||||||
{
|
{
|
||||||
uint32_t string_id = ResolveID(id);
|
uint32_t string_id = ResolveID(id);
|
||||||
if (string_id > 0) {
|
if (string_id > 0) {
|
||||||
auto outapp = new EQApplicationPacket(OP_SimpleMessage, sizeof(SimpleMessage_Struct));
|
auto outapp = std::make_unique<EQApplicationPacket>(OP_SimpleMessage, sizeof(SimpleMessage_Struct));
|
||||||
auto* sms = reinterpret_cast<SimpleMessage_Struct*>(outapp->pBuffer);
|
auto* sms = reinterpret_cast<SimpleMessage_Struct*>(outapp->pBuffer);
|
||||||
sms->string_id = string_id;
|
sms->string_id = string_id;
|
||||||
sms->color = color;
|
sms->color = color;
|
||||||
@@ -3941,7 +3940,7 @@ EQApplicationPacket* Titanium::Simple(uint32_t color, uint32_t id) const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* Titanium::Formatted(
|
std::unique_ptr<EQApplicationPacket> Titanium::Formatted(
|
||||||
uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const
|
uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const
|
||||||
{
|
{
|
||||||
uint32_t string_id = ResolveID(id);
|
uint32_t string_id = ResolveID(id);
|
||||||
@@ -3963,15 +3962,16 @@ EQApplicationPacket* Titanium::Formatted(
|
|||||||
|
|
||||||
buf.WriteUInt8(0);
|
buf.WriteUInt8(0);
|
||||||
|
|
||||||
return new EQApplicationPacket(OP_FormattedMessage, std::move(buf));
|
return std::make_unique<EQApplicationPacket>(OP_FormattedMessage, std::move(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* Titanium::InterruptSpell(uint32_t message, uint32_t spawn_id, const char* spell_link) const
|
std::unique_ptr<EQApplicationPacket> Titanium::InterruptSpell(uint32_t message, uint32_t spawn_id,
|
||||||
|
const char* spell_link) const
|
||||||
{
|
{
|
||||||
auto outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct));
|
auto outapp = std::make_unique<EQApplicationPacket>(OP_InterruptCast, sizeof(InterruptCast_Struct));
|
||||||
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
|
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
|
||||||
ic->messageid = ResolveID(message);
|
ic->messageid = ResolveID(message);
|
||||||
ic->spawnid = spawn_id;
|
ic->spawnid = spawn_id;
|
||||||
@@ -3980,10 +3980,11 @@ EQApplicationPacket* Titanium::InterruptSpell(uint32_t message, uint32_t spawn_i
|
|||||||
return outapp;
|
return outapp;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* Titanium::InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, const char* name,
|
std::unique_ptr<EQApplicationPacket> Titanium::InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
|
||||||
|
const char* name,
|
||||||
const char* spell_link) const
|
const char* spell_link) const
|
||||||
{
|
{
|
||||||
auto outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(name) + 1);
|
auto outapp = std::make_unique<EQApplicationPacket>(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(name) + 1);
|
||||||
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
|
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
|
||||||
ic->messageid = ResolveID(message);
|
ic->messageid = ResolveID(message);
|
||||||
ic->spawnid = spawn_id;
|
ic->spawnid = spawn_id;
|
||||||
@@ -4018,7 +4019,8 @@ void Titanium::ResolveArguments(uint32_t id, std::array<const char*, 9>& args) c
|
|||||||
} // namespace Message
|
} // namespace Message
|
||||||
|
|
||||||
namespace Buff {
|
namespace Buff {
|
||||||
EQApplicationPacket* Titanium::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target, bool clear_buffs) const
|
std::unique_ptr<EQApplicationPacket> Titanium::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
|
||||||
|
bool clear_buffs) const
|
||||||
{
|
{
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
uint32 buff_count;
|
uint32 buff_count;
|
||||||
@@ -4040,15 +4042,10 @@ EQApplicationPacket* Titanium::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* outapp = nullptr;
|
|
||||||
|
|
||||||
//Create it for a targeting window, else create it for a create buff packet.
|
//Create it for a targeting window, else create it for a create buff packet.
|
||||||
if(for_target) {
|
auto outapp = std::make_unique<EQApplicationPacket>(for_target ? OP_RefreshTargetBuffs : OP_RefreshBuffs,
|
||||||
outapp = new EQApplicationPacket(OP_RefreshTargetBuffs, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct) * count);
|
sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct) * count);
|
||||||
}
|
|
||||||
else {
|
|
||||||
outapp = new EQApplicationPacket(OP_RefreshBuffs, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct) * count);
|
|
||||||
}
|
|
||||||
BuffIcon_Struct *buff = (BuffIcon_Struct*)outapp->pBuffer;
|
BuffIcon_Struct *buff = (BuffIcon_Struct*)outapp->pBuffer;
|
||||||
buff->entity_id = mob->GetID();
|
buff->entity_id = mob->GetID();
|
||||||
buff->count = count;
|
buff->count = count;
|
||||||
@@ -4078,17 +4075,18 @@ EQApplicationPacket* Titanium::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bo
|
|||||||
return outapp;
|
return outapp;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* Titanium::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const
|
std::unique_ptr<EQApplicationPacket> Titanium::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot,
|
||||||
|
bool fade) const
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* Titanium::RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
|
std::unique_ptr<EQApplicationPacket> Titanium::RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
|
||||||
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const
|
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Titanium::SetRefreshType(EQApplicationPacket* packet, Mob* source, Client* target) const {}
|
void Titanium::SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const {}
|
||||||
|
|
||||||
} // namespace Buff
|
} // namespace Buff
|
||||||
|
|||||||
@@ -60,11 +60,14 @@ public:
|
|||||||
Titanium() = default;
|
Titanium() = default;
|
||||||
~Titanium() override = default;
|
~Titanium() override = default;
|
||||||
|
|
||||||
[[nodiscard]] EQApplicationPacket* Simple(uint32_t color, uint32_t id) const override;
|
std::unique_ptr<EQApplicationPacket> Simple(uint32_t color, uint32_t id) const override;
|
||||||
[[nodiscard]] EQApplicationPacket* Formatted(uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const override;
|
std::unique_ptr<EQApplicationPacket> Formatted(uint32_t color, uint32_t id,
|
||||||
|
const std::array<const char*, 9>& args) const override;
|
||||||
|
|
||||||
EQApplicationPacket* InterruptSpell(uint32_t message, uint32_t spawn_id, const char* spell_link) const override;
|
std::unique_ptr<EQApplicationPacket> InterruptSpell(uint32_t message, uint32_t spawn_id,
|
||||||
EQApplicationPacket* InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, const char* name,
|
const char* spell_link) const override;
|
||||||
|
std::unique_ptr<EQApplicationPacket> InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
|
||||||
|
const char* name,
|
||||||
const char* spell_link) const override;
|
const char* spell_link) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -82,11 +85,14 @@ public:
|
|||||||
Titanium() = default;
|
Titanium() = default;
|
||||||
~Titanium() override = default;
|
~Titanium() override = default;
|
||||||
|
|
||||||
EQApplicationPacket* MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target, bool clear_buffs) const override;
|
std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
|
||||||
|
bool clear_buffs) const override;
|
||||||
|
|
||||||
EQApplicationPacket* BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const override;
|
std::unique_ptr<EQApplicationPacket>
|
||||||
EQApplicationPacket* RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove, bool buff_timers_suspended, const std::vector<uint32_t>& slots) const override;
|
BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const override;
|
||||||
void SetRefreshType(EQApplicationPacket* packet, Mob* source, Client* target) const override;
|
std::unique_ptr<EQApplicationPacket> RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
|
||||||
|
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const override;
|
||||||
|
void SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Buff
|
} // namespace Buff
|
||||||
|
|||||||
+17
-13
@@ -5550,7 +5550,8 @@ void TOB::ResolveArguments(uint32_t id, std::array<const char*, 9>& args) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* TOB::Formatted(uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const
|
std::unique_ptr<EQApplicationPacket> TOB::Formatted(uint32_t color, uint32_t id,
|
||||||
|
const std::array<const char*, 9>& args) const
|
||||||
{
|
{
|
||||||
uint32_t string_id = ResolveID(id);
|
uint32_t string_id = ResolveID(id);
|
||||||
if (string_id > 0) {
|
if (string_id > 0) {
|
||||||
@@ -5576,15 +5577,16 @@ EQApplicationPacket* TOB::Formatted(uint32_t color, uint32_t id, const std::arra
|
|||||||
buffer.WriteUInt32(0);
|
buffer.WriteUInt32(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new EQApplicationPacket(OP_FormattedMessage, std::move(buffer));
|
return std::make_unique<EQApplicationPacket>(OP_FormattedMessage, std::move(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* TOB::InterruptSpell(uint32_t message, uint32_t spawn_id, const char* spell_link) const
|
std::unique_ptr<EQApplicationPacket> TOB::InterruptSpell(uint32_t message, uint32_t spawn_id,
|
||||||
|
const char* spell_link) const
|
||||||
{
|
{
|
||||||
auto outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(spell_link) + 1);
|
auto outapp = std::make_unique<EQApplicationPacket>(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(spell_link) + 1);
|
||||||
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
|
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
|
||||||
ic->messageid = ResolveID(message);
|
ic->messageid = ResolveID(message);
|
||||||
ic->spawnid = spawn_id;
|
ic->spawnid = spawn_id;
|
||||||
@@ -5594,10 +5596,11 @@ EQApplicationPacket* TOB::InterruptSpell(uint32_t message, uint32_t spawn_id, co
|
|||||||
return outapp;
|
return outapp;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* TOB::InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, const char* name,
|
std::unique_ptr<EQApplicationPacket> TOB::InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
|
||||||
|
const char* name,
|
||||||
const char* spell_link) const
|
const char* spell_link) const
|
||||||
{
|
{
|
||||||
auto outapp = new EQApplicationPacket(OP_InterruptCast,
|
auto outapp = std::make_unique<EQApplicationPacket>(OP_InterruptCast,
|
||||||
sizeof(InterruptCast_Struct) + strlen(name) + strlen(spell_link) + 2);
|
sizeof(InterruptCast_Struct) + strlen(name) + strlen(spell_link) + 2);
|
||||||
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
|
auto ic = reinterpret_cast<InterruptCast_Struct*>(outapp->pBuffer);
|
||||||
ic->messageid = ResolveID(message);
|
ic->messageid = ResolveID(message);
|
||||||
@@ -5610,12 +5613,12 @@ EQApplicationPacket* TOB::InterruptSpellOther(Mob* sender, uint32_t message, uin
|
|||||||
} // namespace Message
|
} // namespace Message
|
||||||
|
|
||||||
namespace Buff {
|
namespace Buff {
|
||||||
|
std::unique_ptr<EQApplicationPacket> TOB::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
|
||||||
|
bool clear_buffs) const { return nullptr; }
|
||||||
|
|
||||||
EQApplicationPacket* TOB::MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target, bool clear_buffs) const { return nullptr; }
|
std::unique_ptr<EQApplicationPacket> TOB::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const
|
||||||
|
|
||||||
EQApplicationPacket* TOB::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const
|
|
||||||
{
|
{
|
||||||
auto packet = new EQApplicationPacket(OP_BuffDefinition, sizeof(::TOB::structs::EQAffectPacket_Struct));
|
auto packet = std::make_unique<EQApplicationPacket>(OP_BuffDefinition, sizeof(::TOB::structs::EQAffectPacket_Struct));
|
||||||
auto affect = reinterpret_cast<::TOB::structs::EQAffectPacket_Struct*>(packet->pBuffer);
|
auto affect = reinterpret_cast<::TOB::structs::EQAffectPacket_Struct*>(packet->pBuffer);
|
||||||
|
|
||||||
// base packet
|
// base packet
|
||||||
@@ -5665,7 +5668,8 @@ EQApplicationPacket* TOB::BuffDefinition(Mob* mob, const Buffs_Struct& buff, int
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* TOB::RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove, bool buff_timers_suspended, const std::vector<uint32_t>& slots) const
|
std::unique_ptr<EQApplicationPacket> TOB::RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
|
||||||
|
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const
|
||||||
{
|
{
|
||||||
Buffs_Struct* buffs = mob->GetBuffs();
|
Buffs_Struct* buffs = mob->GetBuffs();
|
||||||
|
|
||||||
@@ -5704,11 +5708,11 @@ EQApplicationPacket* TOB::RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer
|
|||||||
buffer.WriteUInt8(opcode == OP_RefreshPetBuffs ? 2 : 0);
|
buffer.WriteUInt8(opcode == OP_RefreshPetBuffs ? 2 : 0);
|
||||||
buffer.WriteUInt8(buff_timers_suspended ? 1 : 0); // bBuffTimersOnHold
|
buffer.WriteUInt8(buff_timers_suspended ? 1 : 0); // bBuffTimersOnHold
|
||||||
|
|
||||||
return new EQApplicationPacket(opcode, std::move(buffer));
|
return std::make_unique<EQApplicationPacket>(opcode, std::move(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0 = self buff window, 1 = self target window, 2 = pet buff or target window, 4 = group, 5 = PC, 7 = NPC
|
// 0 = self buff window, 1 = self target window, 2 = pet buff or target window, 4 = group, 5 = PC, 7 = NPC
|
||||||
void TOB::SetRefreshType(EQApplicationPacket* packet, Mob* source, Client* target) const
|
void TOB::SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const
|
||||||
{
|
{
|
||||||
unsigned char* type = &packet->pBuffer[packet->size - 2];
|
unsigned char* type = &packet->pBuffer[packet->size - 2];
|
||||||
|
|
||||||
|
|||||||
+13
-7
@@ -42,10 +42,13 @@ public:
|
|||||||
TOB() = default;
|
TOB() = default;
|
||||||
~TOB() override = default;
|
~TOB() override = default;
|
||||||
|
|
||||||
[[nodiscard]] EQApplicationPacket* Formatted(uint32_t color, uint32_t id, const std::array<const char*, 9>& args) const override;
|
std::unique_ptr<EQApplicationPacket> Formatted(uint32_t color, uint32_t id,
|
||||||
|
const std::array<const char*, 9>& args) const override;
|
||||||
|
|
||||||
EQApplicationPacket* InterruptSpell(uint32_t message, uint32_t spawn_id, const char* spell_link) const override;
|
std::unique_ptr<EQApplicationPacket> InterruptSpell(uint32_t message, uint32_t spawn_id,
|
||||||
EQApplicationPacket* InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, const char* name, const char* spell_link) const override;
|
const char* spell_link) const override;
|
||||||
|
std::unique_ptr<EQApplicationPacket> InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
|
||||||
|
const char* name, const char* spell_link) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
[[nodiscard]] uint32_t ResolveID(uint32_t id) const override;
|
[[nodiscard]] uint32_t ResolveID(uint32_t id) const override;
|
||||||
@@ -62,11 +65,14 @@ public:
|
|||||||
TOB() = default;
|
TOB() = default;
|
||||||
~TOB() override = default;
|
~TOB() override = default;
|
||||||
|
|
||||||
EQApplicationPacket* MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target, bool clear_buffs) const override;
|
std::unique_ptr<EQApplicationPacket> MakeLegacyBuffsPacket(Mob* mob, int32_t timer, bool for_target,
|
||||||
|
bool clear_buffs) const override;
|
||||||
|
|
||||||
EQApplicationPacket* BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const override;
|
std::unique_ptr<EQApplicationPacket>
|
||||||
EQApplicationPacket* RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove, bool buff_timers_suspended, const std::vector<uint32_t>& slots) const override;
|
BuffDefinition(Mob* mob, const Buffs_Struct& buff, int slot, bool fade) const override;
|
||||||
void SetRefreshType(EQApplicationPacket* packet, Mob* source, Client* target) const override;
|
std::unique_ptr<EQApplicationPacket> RefreshBuffs(EmuOpcode opcode, Mob* mob, int32_t timer, bool remove,
|
||||||
|
bool buff_timers_suspended, const std::vector<uint32_t>& slots) const override;
|
||||||
|
void SetRefreshType(const std::unique_ptr<EQApplicationPacket>& packet, Mob* source, Client* target) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Buff
|
} // namespace Buff
|
||||||
|
|||||||
+45
-46
@@ -17,42 +17,39 @@
|
|||||||
namespace ClientPatch {
|
namespace ClientPatch {
|
||||||
|
|
||||||
using ClientList = std::unordered_map<uint16, Client*>;
|
using ClientList = std::unordered_map<uint16, Client*>;
|
||||||
|
template<typename Obj> using ComponentGetter = std::function<Obj*(const Client*)>;
|
||||||
|
|
||||||
template <typename Fun, typename Obj, typename... Args>
|
template <typename Fun, typename Obj, typename... Args>
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
static_assert(std::is_member_function_pointer_v<Fun>);
|
if (obj != nullptr) {
|
||||||
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 != nullptr) {
|
if (app)
|
||||||
c->QueuePacket(app);
|
c->QueuePacket(app.get());
|
||||||
delete app;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,
|
return [=]<typename Fun, typename Obj, typename... Args>(Fun fun, const ComponentGetter<Obj>& component, Args&&... args)
|
||||||
std::function<Obj*(const Client*)> component_getter, Args&&... args) {
|
requires std::is_member_function_pointer_v<Fun>
|
||||||
static_assert(std::is_member_function_pointer_v<Fun> && "Function is required to be a member function");
|
{
|
||||||
|
std::array<std::unique_ptr<EQApplicationPacket>, EQ::versions::ClientVersionCount> build_packets;
|
||||||
std::unordered_map<EQ::versions::ClientVersion, EQApplicationPacket*> build_packets;
|
|
||||||
std::unordered_map<uint16, Client*> client_list = entity_list.GetClientList();
|
std::unordered_map<uint16, Client*> client_list = entity_list.GetClientList();
|
||||||
|
|
||||||
for (auto [_, ent] : client_list) {
|
for (auto [_, ent] : client_list) {
|
||||||
if (!ignore_sender || ent != sender) {
|
if (!ignore_sender || ent != sender) {
|
||||||
auto [packet, _] = build_packets.try_emplace(
|
auto& packet = build_packets.at(static_cast<uint32_t>(ent->ClientVersion()));
|
||||||
ent->ClientVersion(),
|
if (!packet)
|
||||||
std::invoke(fun, component_getter(ent), std::forward<Args>(args)...));
|
if (auto comp = component(ent); comp != nullptr)
|
||||||
|
packet = std::invoke(fun, comp, std::forward<Args>(args)...);
|
||||||
|
|
||||||
if (packet->second != nullptr)
|
if (packet)
|
||||||
ent->QueuePacket(packet->second, ackreq, Client::CLIENT_CONNECTED);
|
ent->QueuePacket(packet.get(), ackreq, Client::CLIENT_CONNECTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto [_, packet] : build_packets)
|
|
||||||
if (packet != nullptr)
|
|
||||||
delete packet;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,15 +60,14 @@ 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,
|
return [=]<typename Fun, typename Obj, typename... Args>(Fun fun, const ComponentGetter<Obj>& component, Args&&... args)
|
||||||
std::function<Obj*(const Client*)> component_getter, Args&&... args) {
|
requires std::is_member_function_pointer_v<Fun>
|
||||||
static_assert(std::is_member_function_pointer_v<Fun>, "Function is required to be a member function");
|
{
|
||||||
|
|
||||||
if (sender == nullptr) {
|
if (sender == nullptr) {
|
||||||
QueueClients(sender, ignore_sender, is_ack_required)(fun, component_getter, std::forward<Args>(args)...);
|
QueueClients(sender, ignore_sender, is_ack_required)(fun, component, std::forward<Args>(args)...);
|
||||||
} else {
|
} else {
|
||||||
float distance_squared = distance * distance;
|
float distance_squared = distance * distance;
|
||||||
std::unordered_map<EQ::versions::ClientVersion, EQApplicationPacket*> build_packets;
|
std::array<std::unique_ptr<EQApplicationPacket>, EQ::versions::ClientVersionCount> build_packets;
|
||||||
|
|
||||||
for (auto& [_, mob] : sender->GetCloseMobList(distance)) {
|
for (auto& [_, mob] : sender->GetCloseMobList(distance)) {
|
||||||
if (mob && mob->IsClient()) {
|
if (mob && mob->IsClient()) {
|
||||||
@@ -80,40 +76,42 @@ static auto QueueCloseClients(
|
|||||||
&& client != skipped_mob
|
&& client != skipped_mob
|
||||||
&& DistanceSquared(client->GetPosition(), sender->GetPosition()) < distance_squared
|
&& DistanceSquared(client->GetPosition(), sender->GetPosition()) < distance_squared
|
||||||
&& client->Connected()
|
&& client->Connected()
|
||||||
&& client->ShouldGetPacket(sender, filter)) {
|
&& client->ShouldGetPacket(sender, filter))
|
||||||
auto [packet, _] = build_packets.try_emplace(
|
{
|
||||||
client->ClientVersion(),
|
auto& packet = build_packets.at(static_cast<uint32_t>(client->ClientVersion()));
|
||||||
std::invoke(fun, component_getter(client), std::forward<Args>(args)...));
|
if (!packet)
|
||||||
|
if (auto comp = component(client); comp != nullptr)
|
||||||
|
packet = std::invoke(fun, comp, std::forward<Args>(args)...);
|
||||||
|
|
||||||
if (packet->second != nullptr)
|
if (packet)
|
||||||
client->QueuePacket(packet->second, is_ack_required, Client::CLIENT_CONNECTED);
|
client->QueuePacket(packet.get(), is_ack_required, Client::CLIENT_CONNECTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto [_, packet] : build_packets)
|
|
||||||
if (packet != nullptr)
|
|
||||||
delete packet;;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Fun, typename Obj, typename... Args>
|
template <typename Fun, typename Obj, typename... Args>
|
||||||
static void FastQueuePacket(Client* c, Fun fun, Obj* obj, Args&&... args)
|
static void FastQueuePacket(Client* c, Fun fun, Obj* obj, Args&&... args)
|
||||||
|
requires std::is_member_function_pointer_v<Fun>
|
||||||
{
|
{
|
||||||
static_assert(std::is_member_function_pointer_v<Fun>);
|
if (obj != nullptr) {
|
||||||
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 != nullptr) {
|
if (app) {
|
||||||
c->FastQueuePacket(&app); // FastQueuePacket inherits the lifetime management of the packet, do not delete or it will be double free
|
// FastQueuePacket specifically takes lifetime management of packet, so release here
|
||||||
|
EQApplicationPacket* packet = app.release();
|
||||||
|
c->FastQueuePacket(&packet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto QueueClientsByTarget(Mob* sender, bool iSendToSender, Mob* SkipThisMob, bool ackreq, bool HoTT,
|
static auto QueueClientsByTarget(Mob* sender, bool iSendToSender, Mob* SkipThisMob, bool ackreq, bool HoTT,
|
||||||
uint32 ClientVersionBits, bool inspect_buffs, bool clear_target_window)
|
uint32 ClientVersionBits, bool inspect_buffs, bool clear_target_window)
|
||||||
{
|
{
|
||||||
return [=]<typename Fun, typename Obj, typename... Args>(Fun fun,
|
return [=]<typename Fun, typename Obj, typename... Args>(Fun fun, const ComponentGetter<Obj> component, Args&&... args)
|
||||||
std::function<Obj*(const Client*)> component_getter, Args&&... args) {
|
requires std::is_member_function_pointer_v<Fun>
|
||||||
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<EQ::versions::ClientVersion, EQApplicationPacket*> build_packets;
|
||||||
std::unordered_map<uint16, Client*> client_list = entity_list.GetClientList();
|
std::unordered_map<uint16, Client*> client_list = entity_list.GetClientList();
|
||||||
|
|
||||||
@@ -167,7 +165,7 @@ static auto QueueClientsByTarget(Mob* sender, bool iSendToSender, Mob* SkipThisM
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Send && (c->ClientVersionBit() & ClientVersionBits)) {
|
if (Send && (c->ClientVersionBit() & ClientVersionBits)) {
|
||||||
EQApplicationPacket* app = std::invoke(fun, component_getter(c), std::forward<Args>(args)...);
|
EQApplicationPacket* app = std::invoke(fun, component(c), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,6 +178,7 @@ static auto QueueClientsByTarget(Mob* sender, bool iSendToSender, Mob* SkipThisM
|
|||||||
// 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();
|
||||||
};
|
};
|
||||||
@@ -202,9 +201,9 @@ static auto CloseMessageString(
|
|||||||
Mob* skipped_mob = nullptr, bool is_ack_required = true,
|
Mob* skipped_mob = nullptr, bool is_ack_required = true,
|
||||||
eqFilterType filter = FilterNone)
|
eqFilterType filter = FilterNone)
|
||||||
{
|
{
|
||||||
return [=]<AllConstChar... Args>(uint32_t type, uint32_t id, Args&&... args) {
|
return [=]<AllConstChar... Args>(uint32_t type, uint32_t id, Args&&... args)
|
||||||
static_assert(sizeof...(Args) <= 9, "Too many arguments");
|
requires (sizeof...(Args) <= 9)
|
||||||
|
{
|
||||||
auto queue_close_clients = ClientPatch::QueueCloseClients(sender, ignore_sender, distance, skipped_mob,
|
auto queue_close_clients = ClientPatch::QueueCloseClients(sender, ignore_sender, distance, skipped_mob,
|
||||||
is_ack_required, filter);
|
is_ack_required, filter);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user