mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-27 08:17:16 +00:00
Moved formatted message into the new tob patch and cleaned up a bit
This commit is contained in:
@@ -135,6 +135,7 @@ set(common_sources
|
|||||||
util/directory.cpp
|
util/directory.cpp
|
||||||
util/uuid.cpp
|
util/uuid.cpp
|
||||||
zone_store.cpp
|
zone_store.cpp
|
||||||
|
links.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(repositories
|
set(repositories
|
||||||
@@ -735,7 +736,6 @@ set(common_headers
|
|||||||
version.h
|
version.h
|
||||||
zone_store.h
|
zone_store.h
|
||||||
links.h
|
links.h
|
||||||
links.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${common_sources})
|
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${common_sources})
|
||||||
|
|||||||
@@ -651,43 +651,6 @@ namespace TOB
|
|||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_FormattedMessage)
|
|
||||||
{
|
|
||||||
EQApplicationPacket* in = *p;
|
|
||||||
*p = nullptr;
|
|
||||||
|
|
||||||
FormattedMessage_Struct* emu = (FormattedMessage_Struct*)in->pBuffer;
|
|
||||||
|
|
||||||
char* old_message_ptr = (char*)in->pBuffer;
|
|
||||||
old_message_ptr += sizeof(FormattedMessage_Struct);
|
|
||||||
|
|
||||||
std::string old_message_array[9];
|
|
||||||
|
|
||||||
for (int i = 0; i < 9; ++i) {
|
|
||||||
if (*old_message_ptr == 0) { break; }
|
|
||||||
old_message_array[i] = old_message_ptr;
|
|
||||||
old_message_ptr += old_message_array[i].length() + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SerializeBuffer buffer;
|
|
||||||
buffer.WriteUInt32(0); // This is a string written like the message arrays
|
|
||||||
buffer.WriteUInt8(emu->unknown0);
|
|
||||||
buffer.WriteUInt32(emu->string_id);
|
|
||||||
buffer.WriteUInt32(emu->type);
|
|
||||||
|
|
||||||
for (int i = 0; i < 9; ++i) {
|
|
||||||
std::string new_message;
|
|
||||||
ServerToTOBConvertLinks(new_message, old_message_array[i]);
|
|
||||||
buffer.WriteLengthString(new_message);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_FormattedMessage, buffer.size());
|
|
||||||
outapp->WriteData(buffer.buffer(), buffer.size());
|
|
||||||
dest->FastQueuePacket(&outapp, ack_req);
|
|
||||||
|
|
||||||
delete in;
|
|
||||||
}
|
|
||||||
|
|
||||||
ENCODE(OP_GMTraining) {
|
ENCODE(OP_GMTraining) {
|
||||||
ENCODE_LENGTH_EXACT(GMTrainee_Struct);
|
ENCODE_LENGTH_EXACT(GMTrainee_Struct);
|
||||||
SETUP_DIRECT_ENCODE(GMTrainee_Struct, structs::GMTrainee_Struct);
|
SETUP_DIRECT_ENCODE(GMTrainee_Struct, structs::GMTrainee_Struct);
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ E(OP_DeleteSpawn)
|
|||||||
E(OP_DisciplineUpdate)
|
E(OP_DisciplineUpdate)
|
||||||
E(OP_ExpansionInfo)
|
E(OP_ExpansionInfo)
|
||||||
E(OP_ExpUpdate)
|
E(OP_ExpUpdate)
|
||||||
E(OP_FormattedMessage)
|
|
||||||
E(OP_GMTraining)
|
E(OP_GMTraining)
|
||||||
E(OP_GMTrainSkillConfirm)
|
E(OP_GMTrainSkillConfirm)
|
||||||
E(OP_GroundSpawn)
|
E(OP_GroundSpawn)
|
||||||
|
|||||||
@@ -32,8 +32,10 @@
|
|||||||
using Version = EQ::versions::ClientVersion;
|
using Version = EQ::versions::ClientVersion;
|
||||||
using namespace ZoneClient;
|
using namespace ZoneClient;
|
||||||
|
|
||||||
struct ClientComponents {
|
struct ClientComponents
|
||||||
explicit ClientComponents(Version version) : version(version) {
|
{
|
||||||
|
explicit ClientComponents(Version version) : version(version)
|
||||||
|
{
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case Version::TOB:
|
case Version::TOB:
|
||||||
messageComponent = std::make_shared<Message::TOB>();
|
messageComponent = std::make_shared<Message::TOB>();
|
||||||
@@ -63,7 +65,8 @@ struct ClientComponents {
|
|||||||
std::shared_ptr<Message::IMessage> messageComponent;
|
std::shared_ptr<Message::IMessage> messageComponent;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const ClientComponents& GetComponents(Version version) {
|
static const ClientComponents& GetComponents(Version version)
|
||||||
|
{
|
||||||
static const std::unordered_map<Version, ClientComponents> patches = [] {
|
static const std::unordered_map<Version, ClientComponents> patches = [] {
|
||||||
std::unordered_map<Version, ClientComponents> p;
|
std::unordered_map<Version, ClientComponents> p;
|
||||||
p.emplace(Version::Titanium, Version::Titanium);
|
p.emplace(Version::Titanium, Version::Titanium);
|
||||||
@@ -79,7 +82,8 @@ static const ClientComponents& GetComponents(Version version) {
|
|||||||
return patches.at(version);
|
return patches.at(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<Message::IMessage>& ClientPatch::GetMessageComponent(Version version) {
|
const std::shared_ptr<Message::IMessage>& ClientPatch::GetMessageComponent(Version version)
|
||||||
|
{
|
||||||
return GetComponents(version).messageComponent;
|
return GetComponents(version).messageComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-10
@@ -21,7 +21,8 @@ public:
|
|||||||
static const std::shared_ptr<Message::IMessage>& GetMessageComponent(EQ::versions::ClientVersion version);
|
static const std::shared_ptr<Message::IMessage>& GetMessageComponent(EQ::versions::ClientVersion version);
|
||||||
|
|
||||||
template<typename Fun, typename... Args>
|
template<typename Fun, typename... Args>
|
||||||
static void QueuePacket(Client* c, Fun fun, Args&&... args) {
|
static void QueuePacket(Client* c, Fun fun, Args&&... args)
|
||||||
|
{
|
||||||
static_assert(std::is_member_function_pointer_v<Fun>);
|
static_assert(std::is_member_function_pointer_v<Fun>);
|
||||||
EQApplicationPacket* app = std::invoke(fun, c->GetMessageComponent().get(), std::forward<Args>(args)...);
|
EQApplicationPacket* app = std::invoke(fun, c->GetMessageComponent().get(), std::forward<Args>(args)...);
|
||||||
if (app != nullptr) {
|
if (app != nullptr) {
|
||||||
@@ -31,10 +32,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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... Args>(Fun fun, Args&&... args) {
|
return [=]<typename Fun, typename... Args>(Fun fun, Args&&... args) {
|
||||||
static_assert(std::is_member_function_pointer_v<Fun>);
|
static_assert(std::is_member_function_pointer_v<Fun>);
|
||||||
std::map<EQ::versions::ClientVersion, EQApplicationPacket*> build_packets;
|
std::unordered_map<EQ::versions::ClientVersion, EQApplicationPacket*> build_packets;
|
||||||
auto client_list = entity_list.GetClientList();
|
auto client_list = entity_list.GetClientList();
|
||||||
|
|
||||||
for (auto [_, ent] : client_list) {
|
for (auto [_, ent] : client_list) {
|
||||||
@@ -54,9 +56,11 @@ public:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto QueueCloseClients(Mob* sender, bool ignore_sender = false, float distance = 200,
|
static auto QueueCloseClients(
|
||||||
|
Mob* sender, bool ignore_sender = false, float distance = 200,
|
||||||
Mob* skipped_mob = nullptr, bool is_ack_required = true,
|
Mob* skipped_mob = nullptr, bool is_ack_required = true,
|
||||||
eqFilterType filter = FilterNone) {
|
eqFilterType filter = FilterNone)
|
||||||
|
{
|
||||||
if (distance <= 0) distance = zone->GetClientUpdateRange();
|
if (distance <= 0) distance = zone->GetClientUpdateRange();
|
||||||
|
|
||||||
return [=]<typename Fun, typename... Args>(Fun fun, Args&&... args) {
|
return [=]<typename Fun, typename... Args>(Fun fun, Args&&... args) {
|
||||||
@@ -64,15 +68,16 @@ public:
|
|||||||
QueueClients(sender, ignore_sender, is_ack_required)(fun, std::forward<Args>(args)...);
|
QueueClients(sender, ignore_sender, is_ack_required)(fun, std::forward<Args>(args)...);
|
||||||
} else {
|
} else {
|
||||||
float distance_squared = distance * distance;
|
float distance_squared = distance * distance;
|
||||||
std::map<EQ::versions::ClientVersion, EQApplicationPacket*> build_packets;
|
std::unordered_map<EQ::versions::ClientVersion, EQApplicationPacket*> build_packets;
|
||||||
|
|
||||||
for (auto& [_, mob] : sender->GetCloseMobList(distance)) {
|
for (auto& [_, mob] : sender->GetCloseMobList(distance)) {
|
||||||
if (mob && mob->IsClient()) {
|
if (mob && mob->IsClient()) {
|
||||||
Client* client = mob->CastToClient();
|
Client* client = mob->CastToClient();
|
||||||
if ((!ignore_sender || client != sender) &&
|
if ((!ignore_sender || client != sender)
|
||||||
client != skipped_mob &&
|
&& client != skipped_mob
|
||||||
DistanceSquared(client->GetPosition(), sender->GetPosition()) < distance_squared &&
|
&& DistanceSquared(client->GetPosition(), sender->GetPosition()) < distance_squared
|
||||||
client->Connected() && client->ShouldGetPacket(sender, filter)) {
|
&& client->Connected()
|
||||||
|
&& client->ShouldGetPacket(sender, filter)) {
|
||||||
auto [packet, _] = build_packets.try_emplace(
|
auto [packet, _] = build_packets.try_emplace(
|
||||||
client->ClientVersion(),
|
client->ClientVersion(),
|
||||||
std::invoke(fun, GetMessageComponent(client->ClientVersion()).get(), std::forward<Args>(args)...));
|
std::invoke(fun, GetMessageComponent(client->ClientVersion()).get(), std::forward<Args>(args)...));
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ class Mob;
|
|||||||
class EQApplicationPacket;
|
class EQApplicationPacket;
|
||||||
|
|
||||||
namespace ZoneClient::Message {
|
namespace ZoneClient::Message {
|
||||||
|
class IMessage
|
||||||
class IMessage {
|
{
|
||||||
public:
|
public:
|
||||||
constexpr IMessage() {}
|
constexpr IMessage() {}
|
||||||
constexpr virtual ~IMessage() {}
|
constexpr virtual ~IMessage() {}
|
||||||
@@ -42,12 +42,12 @@ public:
|
|||||||
// 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, uint32_t spell_id,
|
virtual EQApplicationPacket* InterruptSpell(uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
||||||
const char* spell_name_override = "") const = 0;
|
const char* spell_name_override = "") const = 0;
|
||||||
virtual EQApplicationPacket* InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
virtual EQApplicationPacket* InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id,
|
||||||
const char* spell_name_override = "") const = 0;
|
uint32_t spell_id, const char* spell_name_override = "") const = 0;
|
||||||
|
|
||||||
// Everything else is specializations of logic needed to build strings that differ between patches
|
// Everything else is specializations of logic needed to build strings that differ between patches
|
||||||
virtual EQApplicationPacket* Fizzle(uint32_t type, uint32_t message, uint32_t spell_id) const = 0;
|
virtual EQApplicationPacket* Fizzle(uint32_t type, uint32_t message, uint32_t spell_id) const = 0;
|
||||||
virtual EQApplicationPacket* FizzleOther(uint32_t type, uint32_t message, uint32_t spell_id, const char* caster) const = 0;
|
virtual EQApplicationPacket* FizzleOther(uint32_t type, uint32_t message, uint32_t spell_id,
|
||||||
|
const char* caster) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Zone::Message
|
} // namespace Zone::Message
|
||||||
|
|||||||
@@ -20,11 +20,10 @@
|
|||||||
#include "zone/patch/components/message/uf.h"
|
#include "zone/patch/components/message/uf.h"
|
||||||
|
|
||||||
namespace ZoneClient::Message {
|
namespace ZoneClient::Message {
|
||||||
|
class RoF : public UF
|
||||||
class RoF : public UF {
|
{
|
||||||
public:
|
public:
|
||||||
constexpr RoF() {}
|
constexpr RoF() {}
|
||||||
constexpr ~RoF() override {}
|
constexpr ~RoF() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Zone::Message
|
} // namespace Zone::Message
|
||||||
|
|||||||
@@ -20,11 +20,10 @@
|
|||||||
#include "zone/patch/components/message/rof.h"
|
#include "zone/patch/components/message/rof.h"
|
||||||
|
|
||||||
namespace ZoneClient::Message {
|
namespace ZoneClient::Message {
|
||||||
|
class RoF2 : public RoF
|
||||||
class RoF2 : public RoF {
|
{
|
||||||
public:
|
public:
|
||||||
constexpr RoF2() {}
|
constexpr RoF2() {}
|
||||||
constexpr ~RoF2() override {}
|
constexpr ~RoF2() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Zone::Message
|
} // namespace Zone::Message
|
||||||
|
|||||||
@@ -20,11 +20,10 @@
|
|||||||
#include "zone/patch/components/message/sof.h"
|
#include "zone/patch/components/message/sof.h"
|
||||||
|
|
||||||
namespace ZoneClient::Message {
|
namespace ZoneClient::Message {
|
||||||
|
class SoD : public SoF
|
||||||
class SoD : public SoF {
|
{
|
||||||
public:
|
public:
|
||||||
constexpr SoD() {}
|
constexpr SoD() {}
|
||||||
constexpr ~SoD() override {}
|
constexpr ~SoD() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Zone::Message
|
} // namespace Zone::Message
|
||||||
|
|||||||
@@ -20,11 +20,10 @@
|
|||||||
#include "zone/patch/components/message/titanium.h"
|
#include "zone/patch/components/message/titanium.h"
|
||||||
|
|
||||||
namespace ZoneClient::Message {
|
namespace ZoneClient::Message {
|
||||||
|
class SoF : public Titanium
|
||||||
class SoF : public Titanium {
|
{
|
||||||
public:
|
public:
|
||||||
constexpr SoF() {}
|
constexpr SoF() {}
|
||||||
constexpr ~SoF() override {}
|
constexpr ~SoF() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Zone::Message
|
} // namespace Zone::Message
|
||||||
|
|||||||
@@ -24,7 +24,8 @@
|
|||||||
#include "common/serialize_buffer.h"
|
#include "common/serialize_buffer.h"
|
||||||
|
|
||||||
namespace ZoneClient::Message {
|
namespace ZoneClient::Message {
|
||||||
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 = new EQApplicationPacket(OP_SimpleMessage, sizeof(SimpleMessage_Struct));
|
||||||
@@ -39,26 +40,25 @@ EQApplicationPacket* Titanium::Simple(uint32_t color, uint32_t id) const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* Titanium::Formatted(uint32_t color, uint32_t id,
|
EQApplicationPacket* Titanium::Formatted(
|
||||||
|
uint32_t color, uint32_t id,
|
||||||
const char* a1, const char* a2, const char* a3,
|
const char* a1, const char* a2, const char* a3,
|
||||||
const char* a4, const char* a5, const char* a6,
|
const char* a4, const char* a5, const char* a6,
|
||||||
const char* a7, const char* a8, const char* a9) const {
|
const char* a7, const char* a8, const char* a9) const
|
||||||
|
{
|
||||||
uint32_t string_id = ResolveID(id);
|
uint32_t string_id = ResolveID(id);
|
||||||
if (string_id > 0) {
|
if (string_id > 0) {
|
||||||
if (!a1)
|
if (!a1)
|
||||||
return Simple(color, id);
|
return Simple(color, id);
|
||||||
|
|
||||||
const char* args[] = {a1, a2, a3, a4, a5, a6, a7, a8, a9};
|
|
||||||
|
|
||||||
SerializeBuffer buf(20);
|
SerializeBuffer buf(20);
|
||||||
buf.WriteInt32(0);
|
buf.WriteInt32(0);
|
||||||
buf.WriteInt32(string_id);
|
buf.WriteInt32(string_id);
|
||||||
buf.WriteInt32(color);
|
buf.WriteInt32(color);
|
||||||
|
|
||||||
for (const auto* arg : args) {
|
for (const auto* a : {a1, a2, a3, a4, a5, a6, a7, a8, a9}) {
|
||||||
if (!arg)
|
if (a != nullptr)
|
||||||
break;
|
buf.WriteString(a);
|
||||||
buf.WriteString(arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.WriteInt8(0);
|
buf.WriteInt8(0);
|
||||||
@@ -69,8 +69,10 @@ EQApplicationPacket* Titanium::Formatted(uint32_t color, uint32_t id,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* Titanium::InterruptSpell(uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
EQApplicationPacket* Titanium::InterruptSpell(
|
||||||
const char* spell_name_override) const {
|
uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
||||||
|
const char* spell_name_override) const
|
||||||
|
{
|
||||||
auto outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct));
|
auto outapp = new 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);
|
||||||
@@ -80,8 +82,10 @@ 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, uint32_t spell_id,
|
EQApplicationPacket* Titanium::InterruptSpellOther(
|
||||||
const char* spell_name_override) const {
|
Mob* sender, uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
||||||
|
const char* spell_name_override) const
|
||||||
|
{
|
||||||
auto name = sender->GetCleanName();
|
auto name = sender->GetCleanName();
|
||||||
auto outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(name) + 1);
|
auto outapp = new 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);
|
||||||
@@ -91,19 +95,21 @@ EQApplicationPacket* Titanium::InterruptSpellOther(Mob* sender, uint32_t message
|
|||||||
return outapp;
|
return outapp;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* Titanium::Fizzle(uint32_t type, uint32_t message, uint32_t spell_id) const {
|
EQApplicationPacket* Titanium::Fizzle(uint32_t type, uint32_t message, uint32_t spell_id) const
|
||||||
|
{
|
||||||
return Simple(type, message);
|
return Simple(type, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* Titanium::FizzleOther(uint32_t type, uint32_t message, uint32_t spell_id, const char* caster) const {
|
EQApplicationPacket* Titanium::FizzleOther(uint32_t type, uint32_t message, uint32_t spell_id, const char* caster) const
|
||||||
|
{
|
||||||
return Formatted(type, message, caster);
|
return Formatted(type, message, caster);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A value of 0 means that the string isn't mapped in this client, valid string ids start at 1
|
// A value of 0 means that the string isn't mapped in this client, valid string ids start at 1
|
||||||
uint32_t Titanium::ResolveID(uint32_t id) const {
|
uint32_t Titanium::ResolveID(uint32_t id) const
|
||||||
|
{
|
||||||
// passthrough — string IDs are defined at the base client level;
|
// passthrough — string IDs are defined at the base client level;
|
||||||
// override in patches where IDs need remapping
|
// override in patches where IDs need remapping
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ZoneClient::Message
|
} // namespace ZoneClient::Message
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#include "zone/patch/components/message/IMessage.h"
|
#include "zone/patch/components/message/IMessage.h"
|
||||||
|
|
||||||
namespace ZoneClient::Message {
|
namespace ZoneClient::Message {
|
||||||
|
class Titanium : public IMessage
|
||||||
class Titanium : public IMessage {
|
{
|
||||||
public:
|
public:
|
||||||
constexpr Titanium() {}
|
constexpr Titanium() {}
|
||||||
constexpr ~Titanium() override {}
|
constexpr ~Titanium() override {}
|
||||||
@@ -39,10 +39,10 @@ public:
|
|||||||
const char* spell_name_override = "") const override;
|
const char* spell_name_override = "") const override;
|
||||||
|
|
||||||
EQApplicationPacket* Fizzle(uint32_t type, uint32_t message, uint32_t spell_id) const override;
|
EQApplicationPacket* Fizzle(uint32_t type, uint32_t message, uint32_t spell_id) const override;
|
||||||
EQApplicationPacket* FizzleOther(uint32_t type, uint32_t message, uint32_t spell_id, const char* caster) const override;
|
EQApplicationPacket* FizzleOther(uint32_t type, uint32_t message,
|
||||||
|
uint32_t spell_id, const char* caster) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual uint32_t ResolveID(uint32_t id) const;
|
virtual uint32_t ResolveID(uint32_t id) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Zone::Message
|
} // namespace Zone::Message
|
||||||
|
|||||||
@@ -20,12 +20,13 @@
|
|||||||
#include "common/links.h"
|
#include "common/links.h"
|
||||||
|
|
||||||
namespace ZoneClient::Message {
|
namespace ZoneClient::Message {
|
||||||
|
struct TOBStringIDs
|
||||||
struct TOBStringIDs {
|
{
|
||||||
static constexpr uint32_t DisarmedTrap = 1458; // You successfully disarmed the trap
|
static constexpr uint32_t DisarmedTrap = 1458; // You successfully disarmed the trap
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t TOB::ResolveID(uint32_t id) const {
|
uint32_t TOB::ResolveID(uint32_t id) const
|
||||||
|
{
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case YOU_FLURRY:
|
case YOU_FLURRY:
|
||||||
case BOW_DOUBLE_DAMAGE:
|
case BOW_DOUBLE_DAMAGE:
|
||||||
@@ -72,7 +73,131 @@ uint32_t TOB::ResolveID(uint32_t id) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* TOB::InterruptSpell(uint32_t message, uint32_t spawn_id, uint32_t spell_id, const char* spell_name_override) const {
|
// TOB is the first patch to fully support links in the client. This helper function is therefore internal to TOB
|
||||||
|
// because any future patches would default to the TOB message strings
|
||||||
|
static void ServerToTOBConvertLinks(std::string& message_out, const std::string& message_in)
|
||||||
|
{
|
||||||
|
if (message_in.find('\x12') == std::string::npos) {
|
||||||
|
message_out = message_in;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto segments = Strings::Split(message_in, '\x12');
|
||||||
|
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
|
||||||
|
if (segment_iter & 1) {
|
||||||
|
auto etag = std::stoi(segments[segment_iter].substr(0, 1));
|
||||||
|
|
||||||
|
switch (etag) {
|
||||||
|
case 0: {
|
||||||
|
size_t index = 1;
|
||||||
|
auto item_id = segments[segment_iter].substr(index, 5);
|
||||||
|
index += 5;
|
||||||
|
|
||||||
|
auto aug1 = segments[segment_iter].substr(index, 5);
|
||||||
|
index += 5;
|
||||||
|
|
||||||
|
auto aug2 = segments[segment_iter].substr(index, 5);
|
||||||
|
index += 5;
|
||||||
|
|
||||||
|
auto aug3 = segments[segment_iter].substr(index, 5);
|
||||||
|
index += 5;
|
||||||
|
|
||||||
|
auto aug4 = segments[segment_iter].substr(index, 5);
|
||||||
|
index += 5;
|
||||||
|
|
||||||
|
auto aug5 = segments[segment_iter].substr(index, 5);
|
||||||
|
index += 5;
|
||||||
|
|
||||||
|
auto aug6 = segments[segment_iter].substr(index, 5);
|
||||||
|
index += 5;
|
||||||
|
|
||||||
|
auto is_evolving = segments[segment_iter].substr(index, 1);
|
||||||
|
index += 1;
|
||||||
|
|
||||||
|
auto evolutionGroup = segments[segment_iter].substr(index, 4);
|
||||||
|
index += 4;
|
||||||
|
|
||||||
|
auto evolutionLevel = segments[segment_iter].substr(index, 2);
|
||||||
|
index += 2;
|
||||||
|
|
||||||
|
auto ornamentationIconID = segments[segment_iter].substr(index, 5);
|
||||||
|
index += 5;
|
||||||
|
|
||||||
|
auto itemHash = segments[segment_iter].substr(index, 8);
|
||||||
|
index += 8;
|
||||||
|
|
||||||
|
auto text = segments[segment_iter].substr(index);
|
||||||
|
|
||||||
|
message_out.push_back('\x12');
|
||||||
|
message_out.push_back('0'); //etag item
|
||||||
|
message_out.append(item_id);
|
||||||
|
message_out.append(aug1);
|
||||||
|
message_out.append("00000");
|
||||||
|
message_out.append(aug2);
|
||||||
|
message_out.append("00000");
|
||||||
|
message_out.append(aug3);
|
||||||
|
message_out.append("00000");
|
||||||
|
message_out.append(aug4);
|
||||||
|
message_out.append("00000");
|
||||||
|
message_out.append(aug5);
|
||||||
|
message_out.append("00000");
|
||||||
|
message_out.append(aug6);
|
||||||
|
message_out.append("00000");
|
||||||
|
message_out.append(is_evolving);
|
||||||
|
message_out.append(evolutionGroup);
|
||||||
|
message_out.append(evolutionLevel);
|
||||||
|
message_out.append(ornamentationIconID);
|
||||||
|
message_out.append("00000");
|
||||||
|
message_out.append(itemHash);
|
||||||
|
message_out.append(text);
|
||||||
|
message_out.push_back('\x12');
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
//unsupported etag right now; just pass it as is
|
||||||
|
message_out.push_back('\x12');
|
||||||
|
message_out.append(segments[segment_iter]);
|
||||||
|
message_out.push_back('\x12');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message_out.append(segments[segment_iter]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EQApplicationPacket* TOB::Formatted(uint32_t color, uint32_t id, const char* a1, const char* a2, const char* a3,
|
||||||
|
const char* a4, const char* a5, const char* a6, const char* a7, const char* a8, const char* a9) const
|
||||||
|
{
|
||||||
|
uint32_t string_id = ResolveID(id);
|
||||||
|
if (string_id > 0) {
|
||||||
|
SerializeBuffer buffer(49);
|
||||||
|
// 49 is the minimum size needed for this packet since each arg writes at least 4 bytes
|
||||||
|
buffer.WriteUInt32(0);
|
||||||
|
// This is a string written like the message arrays, but it seems to be discarded by the client
|
||||||
|
buffer.WriteUInt8(0); // 0 is a zone packet, 1 is a world packet -- these are always sent from zone from here
|
||||||
|
buffer.WriteUInt32(string_id);
|
||||||
|
buffer.WriteUInt32(color);
|
||||||
|
|
||||||
|
for (auto a : {a1, a2, a3, a4, a5, a6, a7, a8, a9}) {
|
||||||
|
if (a != nullptr) {
|
||||||
|
std::string new_message;
|
||||||
|
ServerToTOBConvertLinks(new_message, a);
|
||||||
|
buffer.WriteLengthString(new_message);
|
||||||
|
} else
|
||||||
|
buffer.WriteUInt32(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EQApplicationPacket(OP_FormattedMessage, std::move(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
EQApplicationPacket* TOB::InterruptSpell(uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
||||||
|
const char* spell_name_override) const
|
||||||
|
{
|
||||||
std::string spell_name = spell_name_override == nullptr || *spell_name_override == '\0'
|
std::string spell_name = spell_name_override == nullptr || *spell_name_override == '\0'
|
||||||
? GetSpellName(spell_id)
|
? GetSpellName(spell_id)
|
||||||
: spell_name_override;
|
: spell_name_override;
|
||||||
@@ -90,7 +215,8 @@ EQApplicationPacket* TOB::InterruptSpell(uint32_t message, uint32_t spawn_id, ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* TOB::InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
EQApplicationPacket* TOB::InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
||||||
const char* spell_name_override) const {
|
const char* spell_name_override) const
|
||||||
|
{
|
||||||
std::string spell_name = spell_name_override == nullptr || *spell_name_override == '\0'
|
std::string spell_name = spell_name_override == nullptr || *spell_name_override == '\0'
|
||||||
? GetSpellName(spell_id)
|
? GetSpellName(spell_id)
|
||||||
: spell_name_override;
|
: spell_name_override;
|
||||||
@@ -98,7 +224,8 @@ EQApplicationPacket* TOB::InterruptSpellOther(Mob* sender, uint32_t message, uin
|
|||||||
std::string spell_link = Links::FormatSpellLink(spell_id, spell_name);
|
std::string spell_link = Links::FormatSpellLink(spell_id, spell_name);
|
||||||
|
|
||||||
auto name = sender->GetCleanName();
|
auto name = sender->GetCleanName();
|
||||||
auto outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(name) + spell_link.size() + 2);
|
auto outapp = new EQApplicationPacket(OP_InterruptCast,
|
||||||
|
sizeof(InterruptCast_Struct) + strlen(name) + spell_link.size() + 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);
|
||||||
ic->spawnid = spawn_id;
|
ic->spawnid = spawn_id;
|
||||||
@@ -107,14 +234,16 @@ EQApplicationPacket* TOB::InterruptSpellOther(Mob* sender, uint32_t message, uin
|
|||||||
return outapp;
|
return outapp;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* TOB::Fizzle(uint32_t type, uint32_t message, uint32_t spell_id) const {
|
EQApplicationPacket* TOB::Fizzle(uint32_t type, uint32_t message, uint32_t spell_id) const
|
||||||
|
{
|
||||||
std::string spell_name(GetSpellName(spell_id));
|
std::string spell_name(GetSpellName(spell_id));
|
||||||
std::string spell_link = Links::FormatSpellLink(spell_id, spell_name);
|
std::string spell_link = Links::FormatSpellLink(spell_id, spell_name);
|
||||||
|
|
||||||
return Formatted(type, message, spell_link.c_str());
|
return Formatted(type, message, spell_link.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket* TOB::FizzleOther(uint32_t type, uint32_t message, uint32_t spell_id, const char* caster) const {
|
EQApplicationPacket* TOB::FizzleOther(uint32_t type, uint32_t message, uint32_t spell_id, const char* caster) const
|
||||||
|
{
|
||||||
std::string spell_name(GetSpellName(spell_id));
|
std::string spell_name(GetSpellName(spell_id));
|
||||||
std::string spell_link = Links::FormatSpellLink(spell_id, spell_name);
|
std::string spell_link = Links::FormatSpellLink(spell_id, spell_name);
|
||||||
|
|
||||||
|
|||||||
@@ -20,21 +20,27 @@
|
|||||||
#include "zone/patch/components/message/rof2.h"
|
#include "zone/patch/components/message/rof2.h"
|
||||||
|
|
||||||
namespace ZoneClient::Message {
|
namespace ZoneClient::Message {
|
||||||
class TOB : public RoF2 {
|
class TOB : public RoF2
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
constexpr TOB() {}
|
constexpr TOB() {}
|
||||||
constexpr ~TOB() override {}
|
constexpr ~TOB() override {}
|
||||||
|
|
||||||
|
EQApplicationPacket* Formatted(uint32_t color, uint32_t id,
|
||||||
|
const char* a1 = nullptr, const char* a2 = nullptr, const char* a3 = nullptr,
|
||||||
|
const char* a4 = nullptr, const char* a5 = nullptr, const char* a6 = nullptr,
|
||||||
|
const char* a7 = nullptr, const char* a8 = nullptr, const char* a9 = nullptr) const override;
|
||||||
|
|
||||||
EQApplicationPacket* InterruptSpell(uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
EQApplicationPacket* InterruptSpell(uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
||||||
const char* spell_name_override) const override;
|
const char* spell_name_override) const override;
|
||||||
EQApplicationPacket* InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
EQApplicationPacket* InterruptSpellOther(Mob* sender, uint32_t message, uint32_t spawn_id, uint32_t spell_id,
|
||||||
const char* spell_name_override) const override;
|
const char* spell_name_override) const override;
|
||||||
|
|
||||||
EQApplicationPacket* Fizzle(uint32_t type, uint32_t message, uint32_t spell_id) const override;
|
EQApplicationPacket* Fizzle(uint32_t type, uint32_t message, uint32_t spell_id) const override;
|
||||||
EQApplicationPacket* FizzleOther(uint32_t type, uint32_t message, uint32_t spell_id, const char* caster) const override;
|
EQApplicationPacket*
|
||||||
|
FizzleOther(uint32_t type, uint32_t message, uint32_t spell_id, const char* caster) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t ResolveID(uint32_t id) const override;
|
uint32_t ResolveID(uint32_t id) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Zone::Message
|
} // namespace Zone::Message
|
||||||
|
|||||||
@@ -20,11 +20,10 @@
|
|||||||
#include "patch/components/message/sod.h"
|
#include "patch/components/message/sod.h"
|
||||||
|
|
||||||
namespace ZoneClient::Message {
|
namespace ZoneClient::Message {
|
||||||
|
class UF : public SoD
|
||||||
class UF : public SoD {
|
{
|
||||||
public:
|
public:
|
||||||
constexpr UF() {}
|
constexpr UF() {}
|
||||||
constexpr ~UF() override {}
|
constexpr ~UF() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Zone::Message
|
} // namespace Zone::Message
|
||||||
|
|||||||
+5
-6
@@ -80,6 +80,7 @@
|
|||||||
#include "common/rulesys.h"
|
#include "common/rulesys.h"
|
||||||
#include "common/spdat.h"
|
#include "common/spdat.h"
|
||||||
#include "common/strings.h"
|
#include "common/strings.h"
|
||||||
|
#include "patch/client_version.h"
|
||||||
#include "zone/bot.h"
|
#include "zone/bot.h"
|
||||||
#include "zone/client.h"
|
#include "zone/client.h"
|
||||||
#include "zone/fastmath.h"
|
#include "zone/fastmath.h"
|
||||||
@@ -94,10 +95,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "common/links.h"
|
|
||||||
#include "common/packet_dump.h"
|
|
||||||
#include "patch/client_version.h"
|
|
||||||
|
|
||||||
extern Zone *zone;
|
extern Zone *zone;
|
||||||
extern volatile bool is_zone_loaded;
|
extern volatile bool is_zone_loaded;
|
||||||
extern WorldServer worldserver;
|
extern WorldServer worldserver;
|
||||||
@@ -337,13 +334,15 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
|||||||
StopCasting();
|
StopCasting();
|
||||||
|
|
||||||
if (IsClient())
|
if (IsClient())
|
||||||
ZoneClient::ClientPatch::QueuePacket(CastToClient(), &ZoneClient::Message::IMessage::Fizzle,
|
ZoneClient::ClientPatch::QueuePacket(
|
||||||
|
CastToClient(), &ZoneClient::Message::IMessage::Fizzle,
|
||||||
Chat::SpellFailure, fizzle_msg, spell_id);
|
Chat::SpellFailure, fizzle_msg, spell_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Song Failure message
|
* Song Failure message
|
||||||
*/
|
*/
|
||||||
ZoneClient::ClientPatch::QueueCloseClients(this, true, RuleI(Range, SpellMessages),
|
ZoneClient::ClientPatch::QueueCloseClients(
|
||||||
|
this, true, RuleI(Range, SpellMessages),
|
||||||
nullptr, true,
|
nullptr, true,
|
||||||
IsClient() ? FilterPCSpells : FilterNPCSpells)(
|
IsClient() ? FilterPCSpells : FilterNPCSpells)(
|
||||||
&ZoneClient::Message::IMessage::FizzleOther, Chat::SpellFailure,
|
&ZoneClient::Message::IMessage::FizzleOther, Chat::SpellFailure,
|
||||||
|
|||||||
Reference in New Issue
Block a user