mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
It helps if you actually push more than the changelog message...
This commit is contained in:
parent
7557cfd845
commit
4b133c808c
@ -149,6 +149,8 @@ public:
|
||||
static const uint32 BANDOLIER_SIZE = Titanium::consts::BANDOLIER_SIZE; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = Titanium::consts::POTION_BELT_SIZE;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 56;
|
||||
|
||||
// legacy-related functions
|
||||
//static int ServerToPerlSlot(int slot); // encode
|
||||
//static int PerlToServerSlot(int slot); // decode
|
||||
|
||||
@ -5269,6 +5269,23 @@ struct ClientMarqueeMessage_Struct {
|
||||
|
||||
typedef std::list<ServerLootItem_Struct*> ItemList;
|
||||
|
||||
struct TextLinkBody_Struct {
|
||||
uint8 unknown_1; /* '%1X' - Server field 1 */
|
||||
uint32 item_id; /* '%05X' - Server field 2 */
|
||||
uint32 augment_1; /* '%05X' - Server field 3 */
|
||||
uint32 augment_2; /* '%05X' - Server field 4 */
|
||||
uint32 augment_3; /* '%05X' - Server field 5 */
|
||||
uint32 augment_4; /* '%05X' - Server field 6 */
|
||||
uint32 augment_5; /* '%05X' - Server field 7 */
|
||||
uint32 augment_6; /* '%05X' - Server field 8 */
|
||||
uint8 unknown_2; /* '%1X' - Server field 9 */
|
||||
uint8 unknown_3; /* '%1X' - Server field 10 */
|
||||
uint32 unknown_4; /* '%04X' - Server field 11 */
|
||||
uint8 unknown_5; /* '%1X' - Server field 12 */
|
||||
uint32 ornament_icon; /* '%05X' - Server field 13 */
|
||||
int hash; /* '%08X' - Server field 14 */
|
||||
};
|
||||
|
||||
// Restore structure packing to default
|
||||
#pragma pack()
|
||||
|
||||
|
||||
@ -33,6 +33,18 @@ namespace RoF
|
||||
static inline uint32 RoFToServerMainInvSlot(structs::MainInvItemSlotStruct RoFSlot);
|
||||
static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse);
|
||||
|
||||
// server to client text link converters
|
||||
static inline void ServerToRoFTextLinks(std::string& rofTextLink, const std::string& serverTextLink);
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody);
|
||||
static inline void ServerToRoFTextLinkBodyStruct(structs::TextLinkBody_Struct& rofLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
static inline bool GenerateRoFTextLinkBody(std::string& rofLinkBody, const structs::TextLinkBody_Struct& rofLinkBodyStruct);
|
||||
|
||||
// client to server text link converters
|
||||
static inline void RoFToServerTextLinks(std::string& serverTextLink, const std::string& rofTextLink);
|
||||
static inline bool DegenerateRoFTextLinkBody(structs::TextLinkBody_Struct& rofLinkBodyStruct, const std::string& rofLinkBody);
|
||||
static inline void RoFToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& rofLinkBodyStruct);
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
|
||||
void Register(EQStreamIdentifier &into)
|
||||
{
|
||||
//create our opcode manager if we havent already
|
||||
@ -488,7 +500,13 @@ namespace RoF
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToRoFTextLinks(new_message, old_message);
|
||||
|
||||
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
|
||||
in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
@ -501,7 +519,7 @@ namespace RoF
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->skill_in_language);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->message);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown
|
||||
@ -3096,6 +3114,44 @@ namespace RoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_SpecialMesg)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
ServerToRoFTextLinks(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Stun_Struct);
|
||||
@ -4041,7 +4097,13 @@ namespace RoF
|
||||
|
||||
uint32 Skill = VARSTRUCT_DECODE_TYPE(uint32, InBuffer);
|
||||
|
||||
__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
|
||||
std::string old_message = InBuffer;
|
||||
std::string new_message;
|
||||
RoFToServerTextLinks(new_message, old_message);
|
||||
|
||||
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer;
|
||||
|
||||
@ -4050,7 +4112,7 @@ namespace RoF
|
||||
emu->language = Language;
|
||||
emu->chan_num = Channel;
|
||||
emu->skill_in_language = Skill;
|
||||
strcpy(emu->message, InBuffer);
|
||||
strcpy(emu->message, new_message.c_str());
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
@ -5627,5 +5689,365 @@ namespace RoF
|
||||
{
|
||||
return (RoFCorpse - 1);
|
||||
}
|
||||
|
||||
static inline void ServerToRoFTextLinks(std::string& rofTextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): old message '%s'", serverTextLink.c_str());
|
||||
|
||||
if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): link size equal, no conversion necessary");
|
||||
rofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (serverTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): delimiter not found, no conversion necessary");
|
||||
rofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToRoFTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateRoFTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): conversion error");
|
||||
rofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
rofTextLink.push_back(delimiter);
|
||||
rofTextLink.append(segments[iter].c_str());
|
||||
rofTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
rofTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): new message '%s'", rofTextLink.c_str());
|
||||
#else
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
rofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToRoFTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateRoFTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF): conversion error");
|
||||
rofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
rofTextLink.push_back(delimiter);
|
||||
rofTextLink.append(segments[iter].c_str());
|
||||
rofTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
rofTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody)
|
||||
{
|
||||
memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct));
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void ServerToRoFTextLinkBodyStruct(structs::TextLinkBody_Struct& rofLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
rofLinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1;
|
||||
rofLinkBodyStruct.item_id = serverLinkBodyStruct.item_id;
|
||||
rofLinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1;
|
||||
rofLinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2;
|
||||
rofLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3;
|
||||
rofLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4;
|
||||
rofLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5;
|
||||
rofLinkBodyStruct.augment_6 = serverLinkBodyStruct.augment_6;
|
||||
rofLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3;
|
||||
rofLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4;
|
||||
rofLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5;
|
||||
rofLinkBodyStruct.ornament_icon = serverLinkBodyStruct.ornament_icon;
|
||||
rofLinkBodyStruct.hash = serverLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateRoFTextLinkBody(std::string& rofLinkBody, const structs::TextLinkBody_Struct& rofLinkBodyStruct)
|
||||
{
|
||||
rofLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X",
|
||||
rofLinkBodyStruct.unknown_1,
|
||||
rofLinkBodyStruct.item_id,
|
||||
rofLinkBodyStruct.augment_1,
|
||||
rofLinkBodyStruct.augment_2,
|
||||
rofLinkBodyStruct.augment_3,
|
||||
rofLinkBodyStruct.augment_4,
|
||||
rofLinkBodyStruct.augment_5,
|
||||
rofLinkBodyStruct.augment_6,
|
||||
rofLinkBodyStruct.unknown_2,
|
||||
rofLinkBodyStruct.unknown_3,
|
||||
rofLinkBodyStruct.unknown_4,
|
||||
rofLinkBodyStruct.ornament_icon,
|
||||
rofLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (rofLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void RoFToServerTextLinks(std::string& serverTextLink, const std::string& rofTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): old message '%s'", rofTextLink.c_str());
|
||||
|
||||
if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): link size equal, no conversion necessary");
|
||||
serverTextLink = rofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (rofTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): delimiter not found, no conversion necessary");
|
||||
serverTextLink = rofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(rofTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateRoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
RoFToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): conversion error");
|
||||
serverTextLink = rofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): new message '%s'", serverTextLink.c_str());
|
||||
#else
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find(delimiter) == std::string::npos)) {
|
||||
serverTextLink = rofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(rofTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateRoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
RoFToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF->Server): conversion error");
|
||||
serverTextLink = rofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateRoFTextLinkBody(structs::TextLinkBody_Struct& rofLinkBodyStruct, const std::string& rofLinkBody)
|
||||
{
|
||||
// RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
memset(&rofLinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct));
|
||||
if (rofLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
rofLinkBodyStruct.unknown_1 = (uint8)strtol(rofLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.item_id = (uint32)strtol(rofLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.augment_1 = (uint32)strtol(rofLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.augment_2 = (uint32)strtol(rofLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.augment_3 = (uint32)strtol(rofLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.augment_4 = (uint32)strtol(rofLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.augment_5 = (uint32)strtol(rofLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.augment_6 = (uint32)strtol(rofLinkBody.substr(31, 5).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.unknown_2 = (uint8)strtol(rofLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.unknown_3 = (uint32)strtol(rofLinkBody.substr(37, 4).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.unknown_4 = (uint8)strtol(rofLinkBody.substr(41, 1).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.ornament_icon = (uint32)strtol(rofLinkBody.substr(42, 5).c_str(), nullptr, 16);
|
||||
rofLinkBodyStruct.hash = (int)strtol(rofLinkBody.substr(47, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void RoFToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& rofLinkBodyStruct)
|
||||
{
|
||||
serverLinkBodyStruct.unknown_1 = rofLinkBodyStruct.unknown_1;
|
||||
serverLinkBodyStruct.item_id = rofLinkBodyStruct.item_id;
|
||||
serverLinkBodyStruct.augment_1 = rofLinkBodyStruct.augment_1;
|
||||
serverLinkBodyStruct.augment_2 = rofLinkBodyStruct.augment_2;
|
||||
serverLinkBodyStruct.augment_3 = rofLinkBodyStruct.augment_3;
|
||||
serverLinkBodyStruct.augment_4 = rofLinkBodyStruct.augment_4;
|
||||
serverLinkBodyStruct.augment_5 = rofLinkBodyStruct.augment_5;
|
||||
serverLinkBodyStruct.augment_6 = rofLinkBodyStruct.augment_6;
|
||||
serverLinkBodyStruct.unknown_2 = NOT_USED;
|
||||
serverLinkBodyStruct.unknown_3 = rofLinkBodyStruct.unknown_2;
|
||||
serverLinkBodyStruct.unknown_4 = rofLinkBodyStruct.unknown_3;
|
||||
serverLinkBodyStruct.unknown_5 = rofLinkBodyStruct.unknown_4;
|
||||
serverLinkBodyStruct.ornament_icon = rofLinkBodyStruct.ornament_icon;
|
||||
serverLinkBodyStruct.hash = rofLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
serverLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X",
|
||||
serverLinkBodyStruct.unknown_1,
|
||||
serverLinkBodyStruct.item_id,
|
||||
serverLinkBodyStruct.augment_1,
|
||||
serverLinkBodyStruct.augment_2,
|
||||
serverLinkBodyStruct.augment_3,
|
||||
serverLinkBodyStruct.augment_4,
|
||||
serverLinkBodyStruct.augment_5,
|
||||
serverLinkBodyStruct.augment_6,
|
||||
serverLinkBodyStruct.unknown_2,
|
||||
serverLinkBodyStruct.unknown_3,
|
||||
serverLinkBodyStruct.unknown_4,
|
||||
serverLinkBodyStruct.unknown_5,
|
||||
serverLinkBodyStruct.ornament_icon,
|
||||
serverLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// end namespace RoF
|
||||
|
||||
@ -33,6 +33,18 @@ namespace RoF2
|
||||
static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct RoF2Slot);
|
||||
static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse);
|
||||
|
||||
// server to client text link converters
|
||||
static inline void ServerToRoF2TextLinks(std::string& rof2TextLink, const std::string& serverTextLink);
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody);
|
||||
static inline void ServerToRoF2TextLinkBodyStruct(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
static inline bool GenerateRoF2TextLinkBody(std::string& rof2LinkBody, const structs::TextLinkBody_Struct& rof2LinkBodyStruct);
|
||||
|
||||
// client to server text link converters
|
||||
static inline void RoF2ToServerTextLinks(std::string& serverTextLink, const std::string& rof2TextLink);
|
||||
static inline bool DegenerateRoF2TextLinkBody(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const std::string& rof2LinkBody);
|
||||
static inline void RoF2ToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& rof2LinkBodyStruct);
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
|
||||
void Register(EQStreamIdentifier &into)
|
||||
{
|
||||
//create our opcode manager if we havent already
|
||||
@ -554,7 +566,13 @@ namespace RoF2
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToRoF2TextLinks(new_message, old_message);
|
||||
|
||||
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
|
||||
in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
@ -567,7 +585,7 @@ namespace RoF2
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->skill_in_language);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->message);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown
|
||||
@ -3162,6 +3180,44 @@ namespace RoF2
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_SpecialMesg)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
ServerToRoF2TextLinks(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Stun_Struct);
|
||||
@ -4113,7 +4169,13 @@ namespace RoF2
|
||||
|
||||
uint32 Skill = VARSTRUCT_DECODE_TYPE(uint32, InBuffer);
|
||||
|
||||
__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
|
||||
std::string old_message = InBuffer;
|
||||
std::string new_message;
|
||||
RoF2ToServerTextLinks(new_message, old_message);
|
||||
|
||||
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer;
|
||||
|
||||
@ -4122,7 +4184,7 @@ namespace RoF2
|
||||
emu->language = Language;
|
||||
emu->chan_num = Channel;
|
||||
emu->skill_in_language = Skill;
|
||||
strcpy(emu->message, InBuffer);
|
||||
strcpy(emu->message, new_message.c_str());
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
@ -5722,5 +5784,368 @@ namespace RoF2
|
||||
{
|
||||
return (RoF2Corpse + EmuConstants::CORPSE_BEGIN - 1);
|
||||
}
|
||||
|
||||
static inline void ServerToRoF2TextLinks(std::string& rof2TextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): old message '%s'", serverTextLink.c_str());
|
||||
|
||||
if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): link size equal, no conversion necessary");
|
||||
rof2TextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (serverTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): delimiter not found, no conversion necessary");
|
||||
rof2TextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToRoF2TextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateRoF2TextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): conversion error");
|
||||
rof2TextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
rof2TextLink.push_back(delimiter);
|
||||
rof2TextLink.append(segments[iter].c_str());
|
||||
rof2TextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
rof2TextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): new message '%s'", rof2TextLink.c_str());
|
||||
#else
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
rof2TextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToRoF2TextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateRoF2TextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->RoF2): conversion error");
|
||||
rof2TextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
rof2TextLink.push_back(delimiter);
|
||||
rof2TextLink.append(segments[iter].c_str());
|
||||
rof2TextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
rof2TextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody)
|
||||
{
|
||||
memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct));
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void ServerToRoF2TextLinkBodyStruct(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
rof2LinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1;
|
||||
rof2LinkBodyStruct.item_id = serverLinkBodyStruct.item_id;
|
||||
rof2LinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1;
|
||||
rof2LinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2;
|
||||
rof2LinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3;
|
||||
rof2LinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4;
|
||||
rof2LinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5;
|
||||
rof2LinkBodyStruct.augment_6 = serverLinkBodyStruct.augment_6;
|
||||
rof2LinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_2;
|
||||
rof2LinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_3;
|
||||
rof2LinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_4;
|
||||
rof2LinkBodyStruct.unknown_5 = serverLinkBodyStruct.unknown_5;
|
||||
rof2LinkBodyStruct.ornament_icon = serverLinkBodyStruct.ornament_icon;
|
||||
rof2LinkBodyStruct.hash = serverLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateRoF2TextLinkBody(std::string& rof2LinkBody, const structs::TextLinkBody_Struct& rof2LinkBodyStruct)
|
||||
{
|
||||
rof2LinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X",
|
||||
rof2LinkBodyStruct.unknown_1,
|
||||
rof2LinkBodyStruct.item_id,
|
||||
rof2LinkBodyStruct.augment_1,
|
||||
rof2LinkBodyStruct.augment_2,
|
||||
rof2LinkBodyStruct.augment_3,
|
||||
rof2LinkBodyStruct.augment_4,
|
||||
rof2LinkBodyStruct.augment_5,
|
||||
rof2LinkBodyStruct.augment_6,
|
||||
rof2LinkBodyStruct.unknown_2,
|
||||
rof2LinkBodyStruct.unknown_3,
|
||||
rof2LinkBodyStruct.unknown_4,
|
||||
rof2LinkBodyStruct.unknown_5,
|
||||
rof2LinkBodyStruct.ornament_icon,
|
||||
rof2LinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (rof2LinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void RoF2ToServerTextLinks(std::string& serverTextLink, const std::string& rof2TextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): old message '%s'", rof2TextLink.c_str());
|
||||
|
||||
if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): link size equal, no conversion necessary");
|
||||
serverTextLink = rof2TextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (rof2TextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): delimiter not found, no conversion necessary");
|
||||
serverTextLink = rof2TextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(rof2TextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateRoF2TextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
RoF2ToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): conversion error");
|
||||
serverTextLink = rof2TextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): new message '%s'", serverTextLink.c_str());
|
||||
#else
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find(delimiter) == std::string::npos)) {
|
||||
serverTextLink = rof2TextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(rof2TextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateRoF2TextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
RoF2ToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(RoF2->Server): conversion error");
|
||||
serverTextLink = rof2TextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateRoF2TextLinkBody(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const std::string& rof2LinkBody)
|
||||
{
|
||||
// RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
memset(&rof2LinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct));
|
||||
if (rof2LinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
rof2LinkBodyStruct.unknown_1 = (uint8)strtol(rof2LinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.item_id = (uint32)strtol(rof2LinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.augment_1 = (uint32)strtol(rof2LinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.augment_2 = (uint32)strtol(rof2LinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.augment_3 = (uint32)strtol(rof2LinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.augment_4 = (uint32)strtol(rof2LinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.augment_5 = (uint32)strtol(rof2LinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.augment_6 = (uint32)strtol(rof2LinkBody.substr(31, 5).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.unknown_2 = (uint8)strtol(rof2LinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.unknown_3 = (uint32)strtol(rof2LinkBody.substr(37, 4).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.unknown_4 = (uint8)strtol(rof2LinkBody.substr(41, 1).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.unknown_5 = (uint8)strtol(rof2LinkBody.substr(42, 1).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.ornament_icon = (uint32)strtol(rof2LinkBody.substr(43, 5).c_str(), nullptr, 16);
|
||||
rof2LinkBodyStruct.hash = (int)strtol(rof2LinkBody.substr(48, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void RoF2ToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& rof2LinkBodyStruct)
|
||||
{
|
||||
serverLinkBodyStruct.unknown_1 = rof2LinkBodyStruct.unknown_1;
|
||||
serverLinkBodyStruct.item_id = rof2LinkBodyStruct.item_id;
|
||||
serverLinkBodyStruct.augment_1 = rof2LinkBodyStruct.augment_1;
|
||||
serverLinkBodyStruct.augment_2 = rof2LinkBodyStruct.augment_2;
|
||||
serverLinkBodyStruct.augment_3 = rof2LinkBodyStruct.augment_3;
|
||||
serverLinkBodyStruct.augment_4 = rof2LinkBodyStruct.augment_4;
|
||||
serverLinkBodyStruct.augment_5 = rof2LinkBodyStruct.augment_5;
|
||||
serverLinkBodyStruct.augment_6 = rof2LinkBodyStruct.augment_6;
|
||||
serverLinkBodyStruct.unknown_2 = rof2LinkBodyStruct.unknown_2;
|
||||
serverLinkBodyStruct.unknown_3 = rof2LinkBodyStruct.unknown_3;
|
||||
serverLinkBodyStruct.unknown_4 = rof2LinkBodyStruct.unknown_4;
|
||||
serverLinkBodyStruct.unknown_5 = rof2LinkBodyStruct.unknown_5;
|
||||
serverLinkBodyStruct.ornament_icon = rof2LinkBodyStruct.ornament_icon;
|
||||
serverLinkBodyStruct.hash = rof2LinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
serverLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X",
|
||||
serverLinkBodyStruct.unknown_1,
|
||||
serverLinkBodyStruct.item_id,
|
||||
serverLinkBodyStruct.augment_1,
|
||||
serverLinkBodyStruct.augment_2,
|
||||
serverLinkBodyStruct.augment_3,
|
||||
serverLinkBodyStruct.augment_4,
|
||||
serverLinkBodyStruct.augment_5,
|
||||
serverLinkBodyStruct.augment_6,
|
||||
serverLinkBodyStruct.unknown_2,
|
||||
serverLinkBodyStruct.unknown_3,
|
||||
serverLinkBodyStruct.unknown_4,
|
||||
serverLinkBodyStruct.unknown_5,
|
||||
serverLinkBodyStruct.ornament_icon,
|
||||
serverLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// end namespace RoF2
|
||||
|
||||
@ -181,6 +181,8 @@ namespace RoF2 {
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 56;
|
||||
}
|
||||
|
||||
namespace limits {
|
||||
|
||||
@ -95,6 +95,7 @@ E(OP_SkillUpdate)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_SpawnAppearance)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_Stun)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_TaskDescription)
|
||||
|
||||
@ -4872,6 +4872,25 @@ struct MercenaryMerchantResponse_Struct {
|
||||
/*0004*/
|
||||
};
|
||||
|
||||
// RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
struct TextLinkBody_Struct
|
||||
{
|
||||
uint8 unknown_1; /* '%1X' - RoF2 field 1 / Server field 1 */
|
||||
uint32 item_id; /* '%05X' - RoF2 field 2 / Server field 2 */
|
||||
uint32 augment_1; /* '%05X' - RoF2 field 3 / Server field 3 */
|
||||
uint32 augment_2; /* '%05X' - RoF2 field 4 / Server field 4 */
|
||||
uint32 augment_3; /* '%05X' - RoF2 field 5 / Server field 5 */
|
||||
uint32 augment_4; /* '%05X' - RoF2 field 6 / Server field 6 */
|
||||
uint32 augment_5; /* '%05X' - RoF2 field 7 / Server field 7 */
|
||||
uint32 augment_6; /* '%05X' - RoF2 field 8 / Server field 8 */
|
||||
uint8 unknown_2; /* '%1X' - RoF2 field 9 / Server field 9 */
|
||||
uint8 unknown_3; /* '%1X' - RoF2 field 10 / Server field 10 */
|
||||
uint32 unknown_4; /* '%04X' - RoF2 field 11 / Server field 11 */
|
||||
uint8 unknown_5; /* '%1X' - RoF2 field 12 / Server field 12 */
|
||||
uint32 ornament_icon; /* '%05X' - RoF2 field 13 / Server field 13 */
|
||||
int hash; /* '%08X' - RoF2 field 14 / Server field 14 */
|
||||
};
|
||||
|
||||
}; //end namespace structs
|
||||
}; //end namespace RoF2
|
||||
|
||||
|
||||
@ -180,6 +180,8 @@ namespace RoF {
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 55;
|
||||
}
|
||||
|
||||
namespace limits {
|
||||
|
||||
@ -84,6 +84,7 @@ E(OP_SkillUpdate)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_SpawnAppearance)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_Stun)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_TaskDescription)
|
||||
|
||||
@ -4894,6 +4894,24 @@ struct MercenaryMerchantResponse_Struct {
|
||||
/*0004*/
|
||||
};
|
||||
|
||||
// RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
struct TextLinkBody_Struct
|
||||
{
|
||||
uint8 unknown_1; /* '%1X' - RoF field 1 / Server field 1 */
|
||||
uint32 item_id; /* '%05X' - RoF field 2 / Server field 2 */
|
||||
uint32 augment_1; /* '%05X' - RoF field 3 / Server field 3 */
|
||||
uint32 augment_2; /* '%05X' - RoF field 4 / Server field 4 */
|
||||
uint32 augment_3; /* '%05X' - RoF field 5 / Server field 5 */
|
||||
uint32 augment_4; /* '%05X' - RoF field 6 / Server field 6 */
|
||||
uint32 augment_5; /* '%05X' - RoF field 7 / Server field 7 */
|
||||
uint32 augment_6; /* '%05X' - RoF field 8 / Server field 8 */
|
||||
uint8 unknown_2; /* '%1X' - RoF field 9 / Server field 10 */
|
||||
uint32 unknown_3; /* '%04X' - RoF field 10 / Server field 11 */
|
||||
uint8 unknown_4; /* '%1X' - RoF field 11 / Server field 12 */
|
||||
uint32 ornament_icon; /* '%05X' - RoF field 12 / Server field 13 */
|
||||
int hash; /* '%08X' - RoF field 13 / Server field 14 */
|
||||
};
|
||||
|
||||
}; //end namespace structs
|
||||
}; //end namespace RoF
|
||||
|
||||
|
||||
@ -31,6 +31,18 @@ namespace SoD
|
||||
static inline uint32 SoDToServerSlot(uint32 SoDSlot);
|
||||
static inline uint32 SoDToServerCorpseSlot(uint32 SoDCorpse);
|
||||
|
||||
// server to client text link converters
|
||||
static inline void ServerToSoDTextLinks(std::string& sodTextLink, const std::string& serverTextLink);
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody);
|
||||
static inline void ServerToSoDTextLinkBodyStruct(structs::TextLinkBody_Struct& sodLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
static inline bool GenerateSoDTextLinkBody(std::string& sodLinkBody, const structs::TextLinkBody_Struct& sodLinkBodyStruct);
|
||||
|
||||
// client to server text link converters
|
||||
static inline void SoDToServerTextLinks(std::string& serverTextLink, const std::string& sodTextLink);
|
||||
static inline bool DegenerateSoDTextLinkBody(structs::TextLinkBody_Struct& sodLinkBodyStruct, const std::string& sodLinkBody);
|
||||
static inline void SoDToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& sodLinkBodyStruct);
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
|
||||
void Register(EQStreamIdentifier &into)
|
||||
{
|
||||
//create our opcode manager if we havent already
|
||||
@ -296,6 +308,35 @@ namespace SoD
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ChannelMessage)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
ChannelMessage_Struct *emu = (ChannelMessage_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToSoDTextLinks(new_message, old_message);
|
||||
|
||||
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
memcpy(OutBuffer, __emu_buffer, sizeof(ChannelMessage_Struct));
|
||||
|
||||
OutBuffer += sizeof(ChannelMessage_Struct);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_CharInventory)
|
||||
{
|
||||
//consume the packet
|
||||
@ -1963,6 +2004,44 @@ namespace SoD
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_SpecialMesg)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
ServerToSoDTextLinks(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Stun_Struct);
|
||||
@ -2729,6 +2808,25 @@ namespace SoD
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_ChannelMessage)
|
||||
{
|
||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
|
||||
std::string new_message;
|
||||
SoDToServerTextLinks(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
|
||||
ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer;
|
||||
|
||||
memcpy(emu, __eq_buffer, sizeof(ChannelMessage_Struct));
|
||||
strcpy(emu->message, new_message.c_str());
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
|
||||
DECODE(OP_CharacterCreate)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::CharCreate_Struct);
|
||||
@ -3683,5 +3781,362 @@ namespace SoD
|
||||
//uint32 ServerCorpse;
|
||||
return (SoDCorpse - 1);
|
||||
}
|
||||
|
||||
static inline void ServerToSoDTextLinks(std::string& sodTextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): old message '%s'", serverTextLink.c_str());
|
||||
|
||||
if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): link size equal, no conversion necessary");
|
||||
sodTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (serverTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): delimiter not found, no conversion necessary");
|
||||
sodTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToSoDTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateSoDTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): conversion error");
|
||||
sodTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
sodTextLink.push_back(delimiter);
|
||||
sodTextLink.append(segments[iter].c_str());
|
||||
sodTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
sodTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): new message '%s'", sodTextLink.c_str());
|
||||
#else
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
sodTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToSoDTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateSoDTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoD): conversion error");
|
||||
sodTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
sodTextLink.push_back(delimiter);
|
||||
sodTextLink.append(segments[iter].c_str());
|
||||
sodTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
sodTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody)
|
||||
{
|
||||
memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct));
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void ServerToSoDTextLinkBodyStruct(structs::TextLinkBody_Struct& sodLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
sodLinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1;
|
||||
sodLinkBodyStruct.item_id = serverLinkBodyStruct.item_id;
|
||||
sodLinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1;
|
||||
sodLinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2;
|
||||
sodLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3;
|
||||
sodLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4;
|
||||
sodLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5;
|
||||
sodLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3;
|
||||
sodLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4;
|
||||
sodLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5;
|
||||
sodLinkBodyStruct.ornament_icon = serverLinkBodyStruct.ornament_icon;
|
||||
sodLinkBodyStruct.hash = serverLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateSoDTextLinkBody(std::string& sodLinkBody, const structs::TextLinkBody_Struct& sodLinkBodyStruct)
|
||||
{
|
||||
sodLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X",
|
||||
sodLinkBodyStruct.unknown_1,
|
||||
sodLinkBodyStruct.item_id,
|
||||
sodLinkBodyStruct.augment_1,
|
||||
sodLinkBodyStruct.augment_2,
|
||||
sodLinkBodyStruct.augment_3,
|
||||
sodLinkBodyStruct.augment_4,
|
||||
sodLinkBodyStruct.augment_5,
|
||||
sodLinkBodyStruct.unknown_2,
|
||||
sodLinkBodyStruct.unknown_3,
|
||||
sodLinkBodyStruct.unknown_4,
|
||||
sodLinkBodyStruct.ornament_icon,
|
||||
sodLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (sodLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void SoDToServerTextLinks(std::string& serverTextLink, const std::string& sodTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): old message '%s'", sodTextLink.c_str());
|
||||
|
||||
if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): link size equal, no conversion necessary");
|
||||
serverTextLink = sodTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sodTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): delimiter not found, no conversion necessary");
|
||||
serverTextLink = sodTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(sodTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateSoDTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
SoDToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): conversion error");
|
||||
serverTextLink = sodTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): new message '%s'", serverTextLink.c_str());
|
||||
#else
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find(delimiter) == std::string::npos)) {
|
||||
serverTextLink = sodTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(sodTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateSoDTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
SoDToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoD->Server): conversion error");
|
||||
serverTextLink = sodTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateSoDTextLinkBody(structs::TextLinkBody_Struct& sodLinkBodyStruct, const std::string& sodLinkBody)
|
||||
{
|
||||
// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
memset(&sodLinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct));
|
||||
if (sodLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
sodLinkBodyStruct.unknown_1 = (uint8)strtol(sodLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.item_id = (uint32)strtol(sodLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.augment_1 = (uint32)strtol(sodLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.augment_2 = (uint32)strtol(sodLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.augment_3 = (uint32)strtol(sodLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.augment_4 = (uint32)strtol(sodLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.augment_5 = (uint32)strtol(sodLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.unknown_2 = (uint8)strtol(sodLinkBody.substr(31, 1).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.unknown_3 = (uint32)strtol(sodLinkBody.substr(32, 4).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.unknown_4 = (uint8)strtol(sodLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.ornament_icon = (uint32)strtol(sodLinkBody.substr(37, 5).c_str(), nullptr, 16);
|
||||
sodLinkBodyStruct.hash = (int)strtol(sodLinkBody.substr(42, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void SoDToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& sodLinkBodyStruct)
|
||||
{
|
||||
serverLinkBodyStruct.unknown_1 = sodLinkBodyStruct.unknown_1;
|
||||
serverLinkBodyStruct.item_id = sodLinkBodyStruct.item_id;
|
||||
serverLinkBodyStruct.augment_1 = sodLinkBodyStruct.augment_1;
|
||||
serverLinkBodyStruct.augment_2 = sodLinkBodyStruct.augment_2;
|
||||
serverLinkBodyStruct.augment_3 = sodLinkBodyStruct.augment_3;
|
||||
serverLinkBodyStruct.augment_4 = sodLinkBodyStruct.augment_4;
|
||||
serverLinkBodyStruct.augment_5 = sodLinkBodyStruct.augment_5;
|
||||
serverLinkBodyStruct.augment_6 = NOT_USED;
|
||||
serverLinkBodyStruct.unknown_2 = NOT_USED;
|
||||
serverLinkBodyStruct.unknown_3 = sodLinkBodyStruct.unknown_2;
|
||||
serverLinkBodyStruct.unknown_4 = sodLinkBodyStruct.unknown_3;
|
||||
serverLinkBodyStruct.unknown_5 = sodLinkBodyStruct.unknown_4;
|
||||
serverLinkBodyStruct.ornament_icon = sodLinkBodyStruct.ornament_icon;
|
||||
serverLinkBodyStruct.hash = sodLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
serverLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X",
|
||||
serverLinkBodyStruct.unknown_1,
|
||||
serverLinkBodyStruct.item_id,
|
||||
serverLinkBodyStruct.augment_1,
|
||||
serverLinkBodyStruct.augment_2,
|
||||
serverLinkBodyStruct.augment_3,
|
||||
serverLinkBodyStruct.augment_4,
|
||||
serverLinkBodyStruct.augment_5,
|
||||
serverLinkBodyStruct.augment_6,
|
||||
serverLinkBodyStruct.unknown_2,
|
||||
serverLinkBodyStruct.unknown_3,
|
||||
serverLinkBodyStruct.unknown_4,
|
||||
serverLinkBodyStruct.unknown_5,
|
||||
serverLinkBodyStruct.ornament_icon,
|
||||
serverLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// end namespace SoD
|
||||
|
||||
@ -177,6 +177,8 @@ namespace SoD {
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 50;
|
||||
}
|
||||
|
||||
namespace limits {
|
||||
|
||||
@ -8,6 +8,7 @@ E(OP_Barter)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_Buff)
|
||||
E(OP_CancelTrade)
|
||||
E(OP_ChannelMessage)
|
||||
E(OP_CharInventory)
|
||||
E(OP_ClientUpdate)
|
||||
E(OP_Consider)
|
||||
@ -57,6 +58,7 @@ E(OP_ShopPlayerBuy)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_Stun)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_Track)
|
||||
@ -81,6 +83,7 @@ D(OP_BazaarSearch)
|
||||
D(OP_Buff)
|
||||
D(OP_Bug)
|
||||
D(OP_CastSpell)
|
||||
D(OP_ChannelMessage)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ClientUpdate)
|
||||
D(OP_Consider)
|
||||
|
||||
@ -4409,6 +4409,22 @@ struct MercenaryAssign_Struct {
|
||||
/*0012*/
|
||||
};
|
||||
|
||||
// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
struct TextLinkBody_Struct
|
||||
{
|
||||
uint8 unknown_1; /* '%1X' - SoD field 1 / Server field 1 */
|
||||
uint32 item_id; /* '%05X' - SoD field 2 / Server field 2 */
|
||||
uint32 augment_1; /* '%05X' - SoD field 3 / Server field 3 */
|
||||
uint32 augment_2; /* '%05X' - SoD field 4 / Server field 4 */
|
||||
uint32 augment_3; /* '%05X' - SoD field 5 / Server field 5 */
|
||||
uint32 augment_4; /* '%05X' - SoD field 6 / Server field 6 */
|
||||
uint32 augment_5; /* '%05X' - SoD field 7 / Server field 7 */
|
||||
uint8 unknown_2; /* '%1X' - SoD field 8 / Server field 10 */
|
||||
uint32 unknown_3; /* '%04X' - SoD field 9 / Server field 11 */
|
||||
uint8 unknown_4; /* '%1X' - SoD field 10 / Server field 12 */
|
||||
uint32 ornament_icon; /* '%05X' - SoD field 11 / Server field 13 */
|
||||
int hash; /* '%08X' - SoD field 12 / Server field 14 */
|
||||
};
|
||||
|
||||
}; //end namespace structs
|
||||
}; //end namespace SoD
|
||||
|
||||
@ -31,6 +31,18 @@ namespace SoF
|
||||
static inline uint32 SoFToServerSlot(uint32 SoFSlot);
|
||||
static inline uint32 SoFToServerCorpseSlot(uint32 SoFCorpse);
|
||||
|
||||
// server to client text link converters
|
||||
static inline void ServerToSoFTextLinks(std::string& sofTextLink, const std::string& serverTextLink);
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody);
|
||||
static inline void ServerToSoFTextLinkBodyStruct(structs::TextLinkBody_Struct& sofLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
static inline bool GenerateSoFTextLinkBody(std::string& sofLinkBody, const structs::TextLinkBody_Struct& sofLinkBodyStruct);
|
||||
|
||||
// client to server text link converters
|
||||
static inline void SoFToServerTextLinks(std::string& serverTextLink, const std::string& sofTextLink);
|
||||
static inline bool DegenerateSoFTextLinkBody(structs::TextLinkBody_Struct& sofLinkBodyStruct, const std::string& sofLinkBody);
|
||||
static inline void SoFToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& sofLinkBodyStruct);
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
|
||||
void Register(EQStreamIdentifier &into)
|
||||
{
|
||||
//create our opcode manager if we havent already
|
||||
@ -278,6 +290,35 @@ namespace SoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ChannelMessage)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
ChannelMessage_Struct *emu = (ChannelMessage_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToSoFTextLinks(new_message, old_message);
|
||||
|
||||
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
memcpy(OutBuffer, __emu_buffer, sizeof(ChannelMessage_Struct));
|
||||
|
||||
OutBuffer += sizeof(ChannelMessage_Struct);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_CharInventory)
|
||||
{
|
||||
//consume the packet
|
||||
@ -1609,6 +1650,44 @@ namespace SoF
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_SpecialMesg)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
ServerToSoFTextLinks(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Stun_Struct);
|
||||
@ -2129,6 +2208,25 @@ namespace SoF
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_ChannelMessage)
|
||||
{
|
||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
|
||||
std::string new_message;
|
||||
SoFToServerTextLinks(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
|
||||
ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer;
|
||||
|
||||
memcpy(emu, __eq_buffer, sizeof(ChannelMessage_Struct));
|
||||
strcpy(emu->message, new_message.c_str());
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
|
||||
DECODE(OP_CharacterCreate)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::CharCreate_Struct);
|
||||
@ -3005,5 +3103,362 @@ namespace SoF
|
||||
//uint32 ServerCorpse;
|
||||
return (SoFCorpse - 1);
|
||||
}
|
||||
|
||||
static inline void ServerToSoFTextLinks(std::string& sofTextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): old message '%s'", serverTextLink.c_str());
|
||||
|
||||
if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): link size equal, no conversion necessary");
|
||||
sofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (serverTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): delimiter not found, no conversion necessary");
|
||||
sofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToSoFTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateSoFTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): conversion error");
|
||||
sofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
sofTextLink.push_back(delimiter);
|
||||
sofTextLink.append(segments[iter].c_str());
|
||||
sofTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
sofTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): new message '%s'", sofTextLink.c_str());
|
||||
#else
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
sofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToSoFTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateSoFTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->SoF): conversion error");
|
||||
sofTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
sofTextLink.push_back(delimiter);
|
||||
sofTextLink.append(segments[iter].c_str());
|
||||
sofTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
sofTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody)
|
||||
{
|
||||
memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct));
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void ServerToSoFTextLinkBodyStruct(structs::TextLinkBody_Struct& sofLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
sofLinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1;
|
||||
sofLinkBodyStruct.item_id = serverLinkBodyStruct.item_id;
|
||||
sofLinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1;
|
||||
sofLinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2;
|
||||
sofLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3;
|
||||
sofLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4;
|
||||
sofLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5;
|
||||
sofLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3;
|
||||
sofLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4;
|
||||
sofLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5;
|
||||
sofLinkBodyStruct.ornament_icon = serverLinkBodyStruct.ornament_icon;
|
||||
sofLinkBodyStruct.hash = serverLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateSoFTextLinkBody(std::string& sofLinkBody, const structs::TextLinkBody_Struct& sofLinkBodyStruct)
|
||||
{
|
||||
sofLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X",
|
||||
sofLinkBodyStruct.unknown_1,
|
||||
sofLinkBodyStruct.item_id,
|
||||
sofLinkBodyStruct.augment_1,
|
||||
sofLinkBodyStruct.augment_2,
|
||||
sofLinkBodyStruct.augment_3,
|
||||
sofLinkBodyStruct.augment_4,
|
||||
sofLinkBodyStruct.augment_5,
|
||||
sofLinkBodyStruct.unknown_2,
|
||||
sofLinkBodyStruct.unknown_3,
|
||||
sofLinkBodyStruct.unknown_4,
|
||||
sofLinkBodyStruct.ornament_icon,
|
||||
sofLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (sofLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void SoFToServerTextLinks(std::string& serverTextLink, const std::string& sofTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): old message '%s'", sofTextLink.c_str());
|
||||
|
||||
if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): link size equal, no conversion necessary");
|
||||
serverTextLink = sofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sofTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): delimiter not found, no conversion necessary");
|
||||
serverTextLink = sofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(sofTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateSoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
SoFToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): conversion error");
|
||||
serverTextLink = sofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): new message '%s'", serverTextLink.c_str());
|
||||
#else
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find(delimiter) == std::string::npos)) {
|
||||
serverTextLink = sofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(sofTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateSoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
SoFToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(SoF->Server): conversion error");
|
||||
serverTextLink = sofTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateSoFTextLinkBody(structs::TextLinkBody_Struct& sofLinkBodyStruct, const std::string& sofLinkBody)
|
||||
{
|
||||
// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
memset(&sofLinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct));
|
||||
if (sofLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
sofLinkBodyStruct.unknown_1 = (uint8)strtol(sofLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.item_id = (uint32)strtol(sofLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.augment_1 = (uint32)strtol(sofLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.augment_2 = (uint32)strtol(sofLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.augment_3 = (uint32)strtol(sofLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.augment_4 = (uint32)strtol(sofLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.augment_5 = (uint32)strtol(sofLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.unknown_2 = (uint8)strtol(sofLinkBody.substr(31, 1).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.unknown_3 = (uint32)strtol(sofLinkBody.substr(32, 4).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.unknown_4 = (uint8)strtol(sofLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.ornament_icon = (uint32)strtol(sofLinkBody.substr(37, 5).c_str(), nullptr, 16);
|
||||
sofLinkBodyStruct.hash = (int)strtol(sofLinkBody.substr(42, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void SoFToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& sofLinkBodyStruct)
|
||||
{
|
||||
serverLinkBodyStruct.unknown_1 = sofLinkBodyStruct.unknown_1;
|
||||
serverLinkBodyStruct.item_id = sofLinkBodyStruct.item_id;
|
||||
serverLinkBodyStruct.augment_1 = sofLinkBodyStruct.augment_1;
|
||||
serverLinkBodyStruct.augment_2 = sofLinkBodyStruct.augment_2;
|
||||
serverLinkBodyStruct.augment_3 = sofLinkBodyStruct.augment_3;
|
||||
serverLinkBodyStruct.augment_4 = sofLinkBodyStruct.augment_4;
|
||||
serverLinkBodyStruct.augment_5 = sofLinkBodyStruct.augment_5;
|
||||
serverLinkBodyStruct.augment_6 = NOT_USED;
|
||||
serverLinkBodyStruct.unknown_2 = NOT_USED;
|
||||
serverLinkBodyStruct.unknown_3 = sofLinkBodyStruct.unknown_2;
|
||||
serverLinkBodyStruct.unknown_4 = sofLinkBodyStruct.unknown_3;
|
||||
serverLinkBodyStruct.unknown_5 = sofLinkBodyStruct.unknown_4;
|
||||
serverLinkBodyStruct.ornament_icon = sofLinkBodyStruct.ornament_icon;
|
||||
serverLinkBodyStruct.hash = sofLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
serverLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X",
|
||||
serverLinkBodyStruct.unknown_1,
|
||||
serverLinkBodyStruct.item_id,
|
||||
serverLinkBodyStruct.augment_1,
|
||||
serverLinkBodyStruct.augment_2,
|
||||
serverLinkBodyStruct.augment_3,
|
||||
serverLinkBodyStruct.augment_4,
|
||||
serverLinkBodyStruct.augment_5,
|
||||
serverLinkBodyStruct.augment_6,
|
||||
serverLinkBodyStruct.unknown_2,
|
||||
serverLinkBodyStruct.unknown_3,
|
||||
serverLinkBodyStruct.unknown_4,
|
||||
serverLinkBodyStruct.unknown_5,
|
||||
serverLinkBodyStruct.ornament_icon,
|
||||
serverLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// end namespace SoF
|
||||
|
||||
@ -177,6 +177,8 @@ namespace SoF {
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 50;
|
||||
}
|
||||
|
||||
namespace limits {
|
||||
|
||||
@ -8,6 +8,7 @@ E(OP_BazaarSearch)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_Buff)
|
||||
E(OP_CancelTrade)
|
||||
E(OP_ChannelMessage)
|
||||
E(OP_CharInventory)
|
||||
E(OP_ClientUpdate)
|
||||
E(OP_Consider)
|
||||
@ -50,6 +51,7 @@ E(OP_SendZonepoints)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_Stun)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
@ -70,6 +72,7 @@ D(OP_AugmentInfo)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_Buff)
|
||||
D(OP_CastSpell)
|
||||
D(OP_ChannelMessage)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_ClientUpdate)
|
||||
D(OP_Consider)
|
||||
|
||||
@ -4115,18 +4115,24 @@ struct AltCurrencySellItem_Struct {
|
||||
/*010*/ uint32 cost;
|
||||
};
|
||||
|
||||
// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
struct TextLinkBody_Struct
|
||||
{
|
||||
uint8 unknown_1; /* '%1X' - SoF field 1 / Server field 1 */
|
||||
uint32 item_id; /* '%05X' - SoF field 2 / Server field 2 */
|
||||
uint32 augment_1; /* '%05X' - SoF field 3 / Server field 3 */
|
||||
uint32 augment_2; /* '%05X' - SoF field 4 / Server field 4 */
|
||||
uint32 augment_3; /* '%05X' - SoF field 5 / Server field 5 */
|
||||
uint32 augment_4; /* '%05X' - SoF field 6 / Server field 6 */
|
||||
uint32 augment_5; /* '%05X' - SoF field 7 / Server field 7 */
|
||||
uint8 unknown_2; /* '%1X' - SoF field 8 / Server field 10 */
|
||||
uint32 unknown_3; /* '%04X' - SoF field 9 / Server field 11 */
|
||||
uint8 unknown_4; /* '%1X' - SoF field 10 / Server field 12 */
|
||||
uint32 ornament_icon; /* '%05X' - SoF field 11 / Server field 13 */
|
||||
int hash; /* '%08X' - SoF field 12 / Server field 14 */
|
||||
};
|
||||
|
||||
}; //end namespace structs
|
||||
}; //end namespace SoF
|
||||
|
||||
#endif /*SoF_STRUCTS_H_*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "../races.h"
|
||||
|
||||
#include "../eq_packet_structs.h"
|
||||
#include "../misc_functions.h"
|
||||
#include "../string_util.h"
|
||||
#include "../item.h"
|
||||
#include "titanium_structs.h"
|
||||
@ -28,6 +29,18 @@ namespace Titanium
|
||||
static inline uint32 TitaniumToServerSlot(int16 TitaniumSlot);
|
||||
static inline uint32 TitaniumToServerCorpseSlot(int16 TitaniumCorpse);
|
||||
|
||||
// server to client text link converters
|
||||
static inline void ServerToTitaniumTextLinks(std::string& titaniumTextLink, const std::string& serverTextLink);
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody);
|
||||
static inline void ServerToTitaniumTextLinkBodyStruct(structs::TextLinkBody_Struct& titaniumLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
static inline bool GenerateTitaniumTextLinkBody(std::string& titaniumLinkBody, const structs::TextLinkBody_Struct& titaniumLinkBodyStruct);
|
||||
|
||||
// client to server text link converters
|
||||
static inline void TitaniumToServerTextLinks(std::string& serverTextLink, const std::string& titaniumTextLink);
|
||||
static inline bool DegenerateTitaniumTextLinkBody(structs::TextLinkBody_Struct& titaniumLinkBodyStruct, const std::string& titaniumLinkBody);
|
||||
static inline void TitaniumToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& titaniumLinkBodyStruct);
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
|
||||
void Register(EQStreamIdentifier &into)
|
||||
{
|
||||
//create our opcode manager if we havent already
|
||||
@ -220,6 +233,35 @@ namespace Titanium
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_ChannelMessage)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
ChannelMessage_Struct *emu = (ChannelMessage_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToTitaniumTextLinks(new_message, old_message);
|
||||
|
||||
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
memcpy(OutBuffer, __emu_buffer, sizeof(ChannelMessage_Struct));
|
||||
|
||||
OutBuffer += sizeof(ChannelMessage_Struct);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_CharInventory)
|
||||
{
|
||||
//consume the packet
|
||||
@ -1070,6 +1112,44 @@ namespace Titanium
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_SpecialMesg)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
ServerToTitaniumTextLinks(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Track)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
@ -1371,6 +1451,25 @@ namespace Titanium
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_ChannelMessage)
|
||||
{
|
||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||
|
||||
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
|
||||
std::string new_message;
|
||||
TitaniumToServerTextLinks(new_message, old_message);
|
||||
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
|
||||
ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer;
|
||||
|
||||
memcpy(emu, __eq_buffer, sizeof(ChannelMessage_Struct));
|
||||
strcpy(emu->message, new_message.c_str());
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
|
||||
DECODE(OP_CharacterCreate)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::CharCreate_Struct);
|
||||
@ -1763,5 +1862,359 @@ namespace Titanium
|
||||
//uint32 ServerCorpse;
|
||||
return TitaniumCorpse;
|
||||
}
|
||||
|
||||
static inline void ServerToTitaniumTextLinks(std::string& titaniumTextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): old message '%s'", serverTextLink.c_str());
|
||||
|
||||
if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): link size equal, no conversion necessary");
|
||||
titaniumTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (serverTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): delimiter not found, no conversion necessary");
|
||||
titaniumTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToTitaniumTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateTitaniumTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): conversion error");
|
||||
titaniumTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
titaniumTextLink.push_back(delimiter);
|
||||
titaniumTextLink.append(segments[iter].c_str());
|
||||
titaniumTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
titaniumTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): new message '%s'", titaniumTextLink.c_str());
|
||||
#else
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
titaniumTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToTitaniumTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateTitaniumTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): conversion error");
|
||||
titaniumTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
titaniumTextLink.push_back(delimiter);
|
||||
titaniumTextLink.append(segments[iter].c_str());
|
||||
titaniumTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
titaniumTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody)
|
||||
{
|
||||
memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct));
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void ServerToTitaniumTextLinkBodyStruct(structs::TextLinkBody_Struct& titaniumLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
titaniumLinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1;
|
||||
titaniumLinkBodyStruct.item_id = serverLinkBodyStruct.item_id;
|
||||
titaniumLinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1;
|
||||
titaniumLinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2;
|
||||
titaniumLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3;
|
||||
titaniumLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4;
|
||||
titaniumLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5;
|
||||
titaniumLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3;
|
||||
titaniumLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4;
|
||||
titaniumLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5;
|
||||
titaniumLinkBodyStruct.hash = serverLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateTitaniumTextLinkBody(std::string& titaniumLinkBody, const structs::TextLinkBody_Struct& titaniumLinkBodyStruct)
|
||||
{
|
||||
titaniumLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X",
|
||||
titaniumLinkBodyStruct.unknown_1,
|
||||
titaniumLinkBodyStruct.item_id,
|
||||
titaniumLinkBodyStruct.augment_1,
|
||||
titaniumLinkBodyStruct.augment_2,
|
||||
titaniumLinkBodyStruct.augment_3,
|
||||
titaniumLinkBodyStruct.augment_4,
|
||||
titaniumLinkBodyStruct.augment_5,
|
||||
titaniumLinkBodyStruct.unknown_2,
|
||||
titaniumLinkBodyStruct.unknown_3,
|
||||
titaniumLinkBodyStruct.unknown_4,
|
||||
titaniumLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (titaniumLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void TitaniumToServerTextLinks(std::string& serverTextLink, const std::string& titaniumTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): old message '%s'", titaniumTextLink.c_str());
|
||||
|
||||
if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): link size equal, no conversion necessary");
|
||||
serverTextLink = titaniumTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (titaniumTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): delimiter not found, no conversion necessary");
|
||||
serverTextLink = titaniumTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(titaniumTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateTitaniumTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
TitaniumToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): conversion error");
|
||||
serverTextLink = titaniumTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): new message '%s'", serverTextLink.c_str());
|
||||
#else
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find(delimiter) == std::string::npos)) {
|
||||
serverTextLink = titaniumTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(titaniumTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateTitaniumTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
TitaniumToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Titanium->Server): conversion error");
|
||||
serverTextLink = titaniumTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateTitaniumTextLinkBody(structs::TextLinkBody_Struct& titaniumLinkBodyStruct, const std::string& titaniumLinkBody)
|
||||
{
|
||||
// 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X"
|
||||
memset(&titaniumLinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct));
|
||||
if (titaniumLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
titaniumLinkBodyStruct.unknown_1 = (uint8)strtol(titaniumLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
titaniumLinkBodyStruct.item_id = (uint32)strtol(titaniumLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
titaniumLinkBodyStruct.augment_1 = (uint32)strtol(titaniumLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
titaniumLinkBodyStruct.augment_2 = (uint32)strtol(titaniumLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
titaniumLinkBodyStruct.augment_3 = (uint32)strtol(titaniumLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
titaniumLinkBodyStruct.augment_4 = (uint32)strtol(titaniumLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
titaniumLinkBodyStruct.augment_5 = (uint32)strtol(titaniumLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
titaniumLinkBodyStruct.unknown_2 = (uint8)strtol(titaniumLinkBody.substr(31, 1).c_str(), nullptr, 16);
|
||||
titaniumLinkBodyStruct.unknown_3 = (uint32)strtol(titaniumLinkBody.substr(32, 4).c_str(), nullptr, 16);
|
||||
titaniumLinkBodyStruct.unknown_4 = (uint8)strtol(titaniumLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
titaniumLinkBodyStruct.hash = (int)strtol(titaniumLinkBody.substr(37, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void TitaniumToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& titaniumLinkBodyStruct)
|
||||
{
|
||||
serverLinkBodyStruct.unknown_1 = titaniumLinkBodyStruct.unknown_1;
|
||||
serverLinkBodyStruct.item_id = titaniumLinkBodyStruct.item_id;
|
||||
serverLinkBodyStruct.augment_1 = titaniumLinkBodyStruct.augment_1;
|
||||
serverLinkBodyStruct.augment_2 = titaniumLinkBodyStruct.augment_2;
|
||||
serverLinkBodyStruct.augment_3 = titaniumLinkBodyStruct.augment_3;
|
||||
serverLinkBodyStruct.augment_4 = titaniumLinkBodyStruct.augment_4;
|
||||
serverLinkBodyStruct.augment_5 = titaniumLinkBodyStruct.augment_5;
|
||||
serverLinkBodyStruct.augment_6 = NOT_USED;
|
||||
serverLinkBodyStruct.unknown_2 = NOT_USED;
|
||||
serverLinkBodyStruct.unknown_3 = titaniumLinkBodyStruct.unknown_2;
|
||||
serverLinkBodyStruct.unknown_4 = titaniumLinkBodyStruct.unknown_3;
|
||||
serverLinkBodyStruct.unknown_5 = titaniumLinkBodyStruct.unknown_4;
|
||||
serverLinkBodyStruct.ornament_icon = NOT_USED;
|
||||
serverLinkBodyStruct.hash = titaniumLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
serverLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X",
|
||||
serverLinkBodyStruct.unknown_1,
|
||||
serverLinkBodyStruct.item_id,
|
||||
serverLinkBodyStruct.augment_1,
|
||||
serverLinkBodyStruct.augment_2,
|
||||
serverLinkBodyStruct.augment_3,
|
||||
serverLinkBodyStruct.augment_4,
|
||||
serverLinkBodyStruct.augment_5,
|
||||
serverLinkBodyStruct.augment_6,
|
||||
serverLinkBodyStruct.unknown_2,
|
||||
serverLinkBodyStruct.unknown_3,
|
||||
serverLinkBodyStruct.unknown_4,
|
||||
serverLinkBodyStruct.unknown_5,
|
||||
serverLinkBodyStruct.ornament_icon,
|
||||
serverLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// end namespace Titanium
|
||||
|
||||
@ -176,6 +176,8 @@ namespace Titanium {
|
||||
static const uint32 BANDOLIERS_COUNT = 4; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 4;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 45;
|
||||
}
|
||||
|
||||
namespace limits {
|
||||
|
||||
@ -4,6 +4,7 @@ E(OP_AdventureMerchantSell)
|
||||
E(OP_ApplyPoison)
|
||||
E(OP_BazaarSearch)
|
||||
E(OP_BecomeTrader)
|
||||
E(OP_ChannelMessage)
|
||||
E(OP_CharInventory)
|
||||
E(OP_DeleteCharge)
|
||||
E(OP_DeleteItem)
|
||||
@ -35,6 +36,7 @@ E(OP_RespondAA)
|
||||
E(OP_SendCharInfo)
|
||||
E(OP_SendAATable)
|
||||
E(OP_ShopPlayerSell)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_Track)
|
||||
E(OP_Trader)
|
||||
E(OP_TraderBuy)
|
||||
@ -49,6 +51,7 @@ D(OP_AdventureMerchantSell)
|
||||
D(OP_ApplyPoison)
|
||||
D(OP_AugmentItem)
|
||||
D(OP_CastSpell)
|
||||
D(OP_ChannelMessage)
|
||||
D(OP_CharacterCreate)
|
||||
D(OP_Consume)
|
||||
D(OP_DeleteItem)
|
||||
|
||||
@ -3329,19 +3329,23 @@ struct LFGuild_GuildToggle_Struct
|
||||
/*616*/
|
||||
};
|
||||
|
||||
// 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X"
|
||||
struct TextLinkBody_Struct
|
||||
{
|
||||
uint8 unknown_1; /* '%1X' - Titanium field 1 / Server field 1 */
|
||||
uint32 item_id; /* '%05X' - Titanium field 2 / Server field 2 */
|
||||
uint32 augment_1; /* '%05X' - Titanium field 3 / Server field 3 */
|
||||
uint32 augment_2; /* '%05X' - Titanium field 4 / Server field 4 */
|
||||
uint32 augment_3; /* '%05X' - Titanium field 5 / Server field 5 */
|
||||
uint32 augment_4; /* '%05X' - Titanium field 6 / Server field 6 */
|
||||
uint32 augment_5; /* '%05X' - Titanium field 7 / Server field 7 */
|
||||
uint8 unknown_2; /* '%1X' - Titanium field 8 / Server field 10 */
|
||||
uint32 unknown_3; /* '%04X' - Titanium field 9 / Server field 11 */
|
||||
uint8 unknown_4; /* '%1X' - Titanium field 10 / Server field 12 */
|
||||
int hash; /* '%08X' - Titanium field 11 / Server field 14 */
|
||||
};
|
||||
|
||||
}; //end namespace structs
|
||||
}; //end namespace Titanium
|
||||
|
||||
|
||||
|
||||
#endif /*Titanium_STRUCTS_H_*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -31,6 +31,18 @@ namespace Underfoot
|
||||
static inline uint32 UnderfootToServerSlot(uint32 UnderfootSlot);
|
||||
static inline uint32 UnderfootToServerCorpseSlot(uint32 UnderfootCorpse);
|
||||
|
||||
// server to client text link converters
|
||||
static inline void ServerToUnderfootTextLinks(std::string& underfootTextLink, const std::string& serverTextLink);
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody);
|
||||
static inline void ServerToUnderfootTextLinkBodyStruct(structs::TextLinkBody_Struct& underfootLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
static inline bool GenerateUnderfootTextLinkBody(std::string& underfootLinkBody, const structs::TextLinkBody_Struct& underfootLinkBodyStruct);
|
||||
|
||||
// client to server text link converters
|
||||
static inline void UnderfootToServerTextLinks(std::string& serverTextLink, const std::string& underfootTextLink);
|
||||
static inline bool DegenerateUnderfootTextLinkBody(structs::TextLinkBody_Struct& underfootLinkBodyStruct, const std::string& underfootLinkBody);
|
||||
static inline void UnderfootToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& underfootLinkBodyStruct);
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct);
|
||||
|
||||
void Register(EQStreamIdentifier &into)
|
||||
{
|
||||
//create our opcode manager if we havent already
|
||||
@ -432,7 +444,12 @@ namespace Underfoot
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
|
||||
std::string old_message = emu->message;
|
||||
std::string new_message;
|
||||
ServerToUnderfootTextLinks(new_message, old_message);
|
||||
|
||||
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
|
||||
in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
|
||||
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
@ -446,7 +463,7 @@ namespace Underfoot
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->skill_in_language);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->message);
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown
|
||||
@ -2298,6 +2315,44 @@ namespace Underfoot
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_SpecialMesg)
|
||||
{
|
||||
EQApplicationPacket *in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
std::string old_message = &emu->message[strlen(emu->sayer)];
|
||||
std::string new_message;
|
||||
ServerToUnderfootTextLinks(new_message, old_message);
|
||||
|
||||
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
|
||||
in->size = 25 + strlen(emu->sayer) + new_message.length();
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
|
||||
char *OutBuffer = (char *)in->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
ENCODE(OP_Stun)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(Stun_Struct);
|
||||
@ -3036,7 +3091,13 @@ namespace Underfoot
|
||||
|
||||
uint32 Skill = VARSTRUCT_DECODE_TYPE(uint32, InBuffer);
|
||||
|
||||
__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
|
||||
std::string old_message = InBuffer;
|
||||
std::string new_message;
|
||||
UnderfootToServerTextLinks(new_message, old_message);
|
||||
|
||||
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
|
||||
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
|
||||
|
||||
__packet->pBuffer = new unsigned char[__packet->size];
|
||||
ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer;
|
||||
|
||||
@ -3045,7 +3106,7 @@ namespace Underfoot
|
||||
emu->language = Language;
|
||||
emu->chan_num = Channel;
|
||||
emu->skill_in_language = Skill;
|
||||
strcpy(emu->message, InBuffer);
|
||||
strcpy(emu->message, new_message.c_str());
|
||||
|
||||
delete[] __eq_buffer;
|
||||
}
|
||||
@ -4155,5 +4216,362 @@ namespace Underfoot
|
||||
//uint32 ServerCorpse;
|
||||
return (UnderfootCorpse - 1);
|
||||
}
|
||||
|
||||
static inline void ServerToUnderfootTextLinks(std::string& underfootTextLink, const std::string& serverTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): old message '%s'", serverTextLink.c_str());
|
||||
|
||||
if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): link size equal, no conversion necessary");
|
||||
underfootTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (serverTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): delimiter not found, no conversion necessary");
|
||||
underfootTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToUnderfootTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateUnderfootTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): conversion error");
|
||||
underfootTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
underfootTextLink.push_back(delimiter);
|
||||
underfootTextLink.append(segments[iter].c_str());
|
||||
underfootTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
underfootTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): new message '%s'", underfootTextLink.c_str());
|
||||
#else
|
||||
if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
|
||||
underfootTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(serverTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
structs::TextLinkBody_Struct new_body_data;
|
||||
ServerToUnderfootTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateUnderfootTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): conversion error");
|
||||
underfootTextLink = serverTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
underfootTextLink.push_back(delimiter);
|
||||
underfootTextLink.append(segments[iter].c_str());
|
||||
underfootTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
underfootTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody)
|
||||
{
|
||||
memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct));
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16);
|
||||
serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void ServerToUnderfootTextLinkBodyStruct(structs::TextLinkBody_Struct& underfootLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
underfootLinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1;
|
||||
underfootLinkBodyStruct.item_id = serverLinkBodyStruct.item_id;
|
||||
underfootLinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1;
|
||||
underfootLinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2;
|
||||
underfootLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3;
|
||||
underfootLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4;
|
||||
underfootLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5;
|
||||
underfootLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3;
|
||||
underfootLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4;
|
||||
underfootLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5;
|
||||
underfootLinkBodyStruct.ornament_icon = serverLinkBodyStruct.ornament_icon;
|
||||
underfootLinkBodyStruct.hash = serverLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateUnderfootTextLinkBody(std::string& underfootLinkBody, const structs::TextLinkBody_Struct& underfootLinkBodyStruct)
|
||||
{
|
||||
underfootLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X",
|
||||
underfootLinkBodyStruct.unknown_1,
|
||||
underfootLinkBodyStruct.item_id,
|
||||
underfootLinkBodyStruct.augment_1,
|
||||
underfootLinkBodyStruct.augment_2,
|
||||
underfootLinkBodyStruct.augment_3,
|
||||
underfootLinkBodyStruct.augment_4,
|
||||
underfootLinkBodyStruct.augment_5,
|
||||
underfootLinkBodyStruct.unknown_2,
|
||||
underfootLinkBodyStruct.unknown_3,
|
||||
underfootLinkBodyStruct.unknown_4,
|
||||
underfootLinkBodyStruct.ornament_icon,
|
||||
underfootLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (underfootLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void UnderfootToServerTextLinks(std::string& serverTextLink, const std::string& underfootTextLink)
|
||||
{
|
||||
const char delimiter = 0x12;
|
||||
|
||||
#if EQDEBUG >= 6
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): old message '%s'", underfootTextLink.c_str());
|
||||
|
||||
if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): link size equal, no conversion necessary");
|
||||
serverTextLink = underfootTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
if (underfootTextLink.find(delimiter) == std::string::npos) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): delimiter not found, no conversion necessary");
|
||||
serverTextLink = underfootTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(underfootTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateUnderfootTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
UnderfootToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body generation error '%s'", segment.c_str());
|
||||
conversion_error = true;
|
||||
}
|
||||
else {
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body generation success '%s'", segment.c_str());
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): conversion error");
|
||||
serverTextLink = underfootTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): segment[%u] '%s'", iter, segments[iter].c_str());
|
||||
}
|
||||
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): new message '%s'", serverTextLink.c_str());
|
||||
#else
|
||||
if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (underfootTextLink.find(delimiter) == std::string::npos)) {
|
||||
serverTextLink = underfootTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
bool conversion_error = false;
|
||||
auto segments = SplitString(underfootTextLink, delimiter);
|
||||
|
||||
for (size_t iter = 1; iter < segments.size(); iter += 2) {
|
||||
structs::TextLinkBody_Struct old_body_data;
|
||||
if (!DegenerateUnderfootTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
TextLinkBody_Struct new_body_data;
|
||||
UnderfootToServerTextLinkBodyStruct(new_body_data, old_body_data);
|
||||
|
||||
std::string segment;
|
||||
if (!GenerateServerTextLinkBody(segment, new_body_data)) {
|
||||
conversion_error = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str());
|
||||
segments[iter] = segment.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (conversion_error) {
|
||||
_log(CHANNELS__ERROR, "TextLink(Underfoot->Server): conversion error");
|
||||
serverTextLink = underfootTextLink;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t iter = 0; iter < segments.size(); ++iter) {
|
||||
if (iter & 1) {
|
||||
serverTextLink.push_back(delimiter);
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
serverTextLink.push_back(delimiter);
|
||||
}
|
||||
else {
|
||||
serverTextLink.append(segments[iter].c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool DegenerateUnderfootTextLinkBody(structs::TextLinkBody_Struct& underfootLinkBodyStruct, const std::string& underfootLinkBody)
|
||||
{
|
||||
// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
memset(&underfootLinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct));
|
||||
if (underfootLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
underfootLinkBodyStruct.unknown_1 = (uint8)strtol(underfootLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.item_id = (uint32)strtol(underfootLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.augment_1 = (uint32)strtol(underfootLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.augment_2 = (uint32)strtol(underfootLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.augment_3 = (uint32)strtol(underfootLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.augment_4 = (uint32)strtol(underfootLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.augment_5 = (uint32)strtol(underfootLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.unknown_2 = (uint8)strtol(underfootLinkBody.substr(31, 1).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.unknown_3 = (uint32)strtol(underfootLinkBody.substr(32, 4).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.unknown_4 = (uint8)strtol(underfootLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.ornament_icon = (uint32)strtol(underfootLinkBody.substr(37, 5).c_str(), nullptr, 16);
|
||||
underfootLinkBodyStruct.hash = (int)strtol(underfootLinkBody.substr(42, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void UnderfootToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& underfootLinkBodyStruct)
|
||||
{
|
||||
serverLinkBodyStruct.unknown_1 = underfootLinkBodyStruct.unknown_1;
|
||||
serverLinkBodyStruct.item_id = underfootLinkBodyStruct.item_id;
|
||||
serverLinkBodyStruct.augment_1 = underfootLinkBodyStruct.augment_1;
|
||||
serverLinkBodyStruct.augment_2 = underfootLinkBodyStruct.augment_2;
|
||||
serverLinkBodyStruct.augment_3 = underfootLinkBodyStruct.augment_3;
|
||||
serverLinkBodyStruct.augment_4 = underfootLinkBodyStruct.augment_4;
|
||||
serverLinkBodyStruct.augment_5 = underfootLinkBodyStruct.augment_5;
|
||||
serverLinkBodyStruct.augment_6 = NOT_USED;
|
||||
serverLinkBodyStruct.unknown_2 = NOT_USED;
|
||||
serverLinkBodyStruct.unknown_3 = underfootLinkBodyStruct.unknown_2;
|
||||
serverLinkBodyStruct.unknown_4 = underfootLinkBodyStruct.unknown_3;
|
||||
serverLinkBodyStruct.unknown_5 = underfootLinkBodyStruct.unknown_4;
|
||||
serverLinkBodyStruct.ornament_icon = underfootLinkBodyStruct.ornament_icon;
|
||||
serverLinkBodyStruct.hash = underfootLinkBodyStruct.hash;
|
||||
}
|
||||
|
||||
static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct)
|
||||
{
|
||||
serverLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X",
|
||||
serverLinkBodyStruct.unknown_1,
|
||||
serverLinkBodyStruct.item_id,
|
||||
serverLinkBodyStruct.augment_1,
|
||||
serverLinkBodyStruct.augment_2,
|
||||
serverLinkBodyStruct.augment_3,
|
||||
serverLinkBodyStruct.augment_4,
|
||||
serverLinkBodyStruct.augment_5,
|
||||
serverLinkBodyStruct.augment_6,
|
||||
serverLinkBodyStruct.unknown_2,
|
||||
serverLinkBodyStruct.unknown_3,
|
||||
serverLinkBodyStruct.unknown_4,
|
||||
serverLinkBodyStruct.unknown_5,
|
||||
serverLinkBodyStruct.ornament_icon,
|
||||
serverLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// end namespace Underfoot
|
||||
|
||||
@ -177,6 +177,8 @@ namespace Underfoot {
|
||||
static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances
|
||||
static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance
|
||||
static const uint32 POTION_BELT_SIZE = 5;
|
||||
|
||||
static const size_t TEXT_LINK_BODY_LENGTH = 50;
|
||||
}
|
||||
|
||||
namespace limits {
|
||||
|
||||
@ -65,6 +65,7 @@ E(OP_ShopPlayerSell)
|
||||
E(OP_SomeItemPacketMaybe)
|
||||
E(OP_SpawnAppearance)
|
||||
E(OP_SpawnDoor)
|
||||
E(OP_SpecialMesg)
|
||||
E(OP_Stun)
|
||||
E(OP_TargetBuffs)
|
||||
E(OP_Track)
|
||||
|
||||
@ -4530,6 +4530,23 @@ struct MercenaryAssign_Struct {
|
||||
/*0012*/
|
||||
};
|
||||
|
||||
// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
struct TextLinkBody_Struct
|
||||
{
|
||||
uint8 unknown_1; /* '%1X' - Underfoot field 1 / Server field 1 */
|
||||
uint32 item_id; /* '%05X' - Underfoot field 2 / Server field 2 */
|
||||
uint32 augment_1; /* '%05X' - Underfoot field 3 / Server field 3 */
|
||||
uint32 augment_2; /* '%05X' - Underfoot field 4 / Server field 4 */
|
||||
uint32 augment_3; /* '%05X' - Underfoot field 5 / Server field 5 */
|
||||
uint32 augment_4; /* '%05X' - Underfoot field 6 / Server field 6 */
|
||||
uint32 augment_5; /* '%05X' - Underfoot field 7 / Server field 7 */
|
||||
uint8 unknown_2; /* '%1X' - Underfoot field 8 / Server field 10 */
|
||||
uint32 unknown_3; /* '%04X' - Underfoot field 9 / Server field 11 */
|
||||
uint8 unknown_4; /* '%1X' - Underfoot field 10 / Server field 12 */
|
||||
uint32 ornament_icon; /* '%05X' - Underfoot field 11 / Server field 13 */
|
||||
int hash; /* '%08X' - Underfoot field 12 / Server field 14 */
|
||||
};
|
||||
|
||||
}; //end namespace structs
|
||||
}; //end namespace Underfoot
|
||||
|
||||
|
||||
@ -11707,7 +11707,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
|
||||
std::string item_link;
|
||||
Client::TextLink linker;
|
||||
linker.SetLinkType(linker.linkItemInst);
|
||||
linker.SetClientVersion(c->GetClientVersion());
|
||||
|
||||
for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) {
|
||||
if((i == MainSecondary) && is2Hweapon) {
|
||||
|
||||
286
zone/client.cpp
286
zone/client.cpp
@ -8271,71 +8271,27 @@ std::string Client::TextLink::GenerateLink()
|
||||
generate_body();
|
||||
generate_text();
|
||||
|
||||
if (m_LinkBody.length() && m_LinkText.length()) {
|
||||
m_Link.append(StringFormat("%c", 0x12));
|
||||
if ((m_LinkBody.length() == EmuConstants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) {
|
||||
m_Link.push_back(0x12);
|
||||
m_Link.append(m_LinkBody);
|
||||
m_Link.append(m_LinkText);
|
||||
m_Link.append(StringFormat("%c", 0x12));
|
||||
m_Link.push_back(0x12);
|
||||
}
|
||||
|
||||
if ((m_Link.length() == 0) || (m_Link.length() > 250)) {
|
||||
m_Error = true;
|
||||
m_Link = "<LINKER ERROR>";
|
||||
_log(CHANNELS__ERROR, "TextLink::GenerateLink() failed to generate a useable text link (LinkType: %i, Lengths: {l: %u, b: %u, t: %u})",
|
||||
_log(CHANNELS__ERROR, "TextLink::GenerateLink() failed to generate a useable text link (LinkType: %i, Lengths: {link: %u, body: %u, text: %u})",
|
||||
m_LinkType, m_Link.length(), m_LinkBody.length(), m_LinkText.length());
|
||||
#if EQDEBUG >= 5
|
||||
_log(CHANNELS__ERROR, ">> LinkBody: %s", m_LinkBody.c_str());
|
||||
_log(CHANNELS__ERROR, ">> LinkText: %s", m_LinkText.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
return m_Link;
|
||||
}
|
||||
|
||||
const char* Client::TextLink::GetLink()
|
||||
{
|
||||
if (m_Link.length() == 0)
|
||||
return nullptr;
|
||||
|
||||
return m_Link.c_str();
|
||||
}
|
||||
|
||||
const char* Client::TextLink::GetLinkBody()
|
||||
{
|
||||
if (m_LinkBody.length() == 0)
|
||||
return nullptr;
|
||||
|
||||
return m_LinkBody.c_str();
|
||||
}
|
||||
|
||||
const char* Client::TextLink::GetLinkText()
|
||||
{
|
||||
if (m_LinkText.length() == 0)
|
||||
return nullptr;
|
||||
|
||||
return m_LinkText.c_str();
|
||||
}
|
||||
|
||||
std::string Client::TextLink::GetLinkString()
|
||||
{
|
||||
if (m_Link.length() == 0)
|
||||
return "";
|
||||
|
||||
return m_Link;
|
||||
}
|
||||
|
||||
std::string Client::TextLink::GetLinkBodyString()
|
||||
{
|
||||
if (m_LinkBody.length() == 0)
|
||||
return "";
|
||||
|
||||
return m_LinkBody;
|
||||
}
|
||||
|
||||
std::string Client::TextLink::GetLinkTextString()
|
||||
{
|
||||
if (m_LinkText.length() == 0)
|
||||
return "";
|
||||
|
||||
return m_LinkText;
|
||||
}
|
||||
|
||||
void Client::TextLink::Reset()
|
||||
{
|
||||
m_LinkType = linkBlank;
|
||||
@ -8348,81 +8304,72 @@ void Client::TextLink::Reset()
|
||||
m_Link.clear();
|
||||
m_LinkBody.clear();
|
||||
m_LinkText.clear();
|
||||
m_ClientVersion = EQClientUnknown;
|
||||
m_Error = false;
|
||||
}
|
||||
|
||||
void Client::TextLink::generate_body()
|
||||
{
|
||||
enum { field_0 = 0, field_1, field_2, field_3, field_4, field_5, field_6, field_7, field_8, field_9, field_10, field_11, field_12, field_13 };
|
||||
static const int field_count = 14;
|
||||
static const bool field_use[_EQClientCount][field_count] = {
|
||||
// 6.2: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X"
|
||||
// SoF: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
// RoF: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
// RoF2: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X"
|
||||
/*
|
||||
Current server mask: EQClientRoF2
|
||||
|
||||
RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X" (56)
|
||||
RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (55)
|
||||
SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (50)
|
||||
6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" (45)
|
||||
*/
|
||||
|
||||
//(RoF2) %01x %05x %05x %05x %05x %05x %05x %05x %01x %01x %04x %01x %05x %08x
|
||||
{ true, true, true, true, true, true, true, true, true, true, true, true, true, true }, // EQClientUnknown
|
||||
{ true, true, true, true, true, true, true, false, false, true, true, true, false, true }, // EQClient6.2
|
||||
{ true, true, true, true, true, true, true, false, false, true, true, true, false, true }, // EQClientTitanium
|
||||
{ true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientSoF
|
||||
{ true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientSoD
|
||||
{ true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientUnderfoot
|
||||
{ true, true, true, true, true, true, true, true, false, true, true, true, true, true }, // EQClientRoF
|
||||
{ true, true, true, true, true, true, true, true, true, true, true, true, true, true } // EQClientRoF2
|
||||
};
|
||||
|
||||
/*%01X*/ uint8 unknown_0 = NOT_USED;
|
||||
/*%05X*/ uint32 item_id = NOT_USED;
|
||||
/*%05X*/ uint32 augment_0 = NOT_USED;
|
||||
/*%05X*/ uint32 augment_1 = NOT_USED;
|
||||
/*%05X*/ uint32 augment_2 = NOT_USED;
|
||||
/*%05X*/ uint32 augment_3 = NOT_USED;
|
||||
/*%05X*/ uint32 augment_4 = NOT_USED;
|
||||
/*%05X*/ uint32 augment_5 = NOT_USED;
|
||||
/*%01X*/ uint8 unknown_8 = NOT_USED;
|
||||
/*%01X*/ uint8 unknown_9 = NOT_USED;
|
||||
/*%04X*/ uint32 unknown_10 = NOT_USED;
|
||||
/*%01X*/ uint8 unknown_11 = NOT_USED;
|
||||
/*%05X*/ uint32 unknown_12 = NOT_USED;
|
||||
/*%08X*/ int hash = NOT_USED;
|
||||
// could use a ##_cast<TextLinkBody_Struct*>(&this) with a memset to '0' since these properties are inherited
|
||||
|
||||
unknown_1 = NOT_USED; /* field 1 */
|
||||
item_id = NOT_USED; /* field 2 */
|
||||
augment_1 = NOT_USED; /* field 3 */
|
||||
augment_2 = NOT_USED; /* field 4 */
|
||||
augment_3 = NOT_USED; /* field 5 */
|
||||
augment_4 = NOT_USED; /* field 6 */
|
||||
augment_5 = NOT_USED; /* field 7 */
|
||||
augment_6 = NOT_USED; /* field 8 */
|
||||
unknown_2 = NOT_USED; /* field 9 */
|
||||
unknown_3 = NOT_USED; /* field 10 */
|
||||
unknown_4 = NOT_USED; /* field 11 */
|
||||
unknown_5 = NOT_USED; /* field 12 */
|
||||
ornament_icon = NOT_USED; /* field 13 */
|
||||
hash = NOT_USED; /* field 14 */
|
||||
|
||||
const Item_Struct* item_data = nullptr;
|
||||
|
||||
switch (m_LinkType) {
|
||||
case linkBlank:
|
||||
break;
|
||||
case linkItemData:
|
||||
if (m_ItemData != nullptr) {
|
||||
item_id = m_ItemData->ID;
|
||||
// TODO: add hash call
|
||||
}
|
||||
if (m_ItemData == nullptr) { break; }
|
||||
item_id = m_ItemData->ID;
|
||||
// TODO: add hash call
|
||||
break;
|
||||
case linkLootItem:
|
||||
if (m_LootData != nullptr) {
|
||||
const Item_Struct* item_data = database.GetItem(m_LootData->item_id);
|
||||
if (item_data == nullptr) { break; }
|
||||
item_id = item_data->ID;
|
||||
augment_0 = m_LootData->aug_1;
|
||||
augment_1 = m_LootData->aug_2;
|
||||
augment_2 = m_LootData->aug_3;
|
||||
augment_3 = m_LootData->aug_4;
|
||||
augment_4 = m_LootData->aug_5;
|
||||
augment_5 = m_LootData->aug_6;
|
||||
// TODO: add hash call
|
||||
}
|
||||
if (m_LootData == nullptr) { break; }
|
||||
item_data = database.GetItem(m_LootData->item_id);
|
||||
if (item_data == nullptr) { break; }
|
||||
item_id = item_data->ID;
|
||||
augment_1 = m_LootData->aug_1;
|
||||
augment_2 = m_LootData->aug_2;
|
||||
augment_3 = m_LootData->aug_3;
|
||||
augment_4 = m_LootData->aug_4;
|
||||
augment_5 = m_LootData->aug_5;
|
||||
augment_6 = m_LootData->aug_6;
|
||||
// TODO: add hash call
|
||||
break;
|
||||
case linkItemInst:
|
||||
if (m_ItemInst != nullptr) {
|
||||
if (m_ItemInst->GetItem() == nullptr) { break; }
|
||||
item_id = m_ItemInst->GetItem()->ID;
|
||||
augment_0 = m_ItemInst->GetAugmentItemID(0);
|
||||
augment_1 = m_ItemInst->GetAugmentItemID(1);
|
||||
augment_2 = m_ItemInst->GetAugmentItemID(2);
|
||||
augment_3 = m_ItemInst->GetAugmentItemID(3);
|
||||
augment_4 = m_ItemInst->GetAugmentItemID(4);
|
||||
augment_5 = m_ItemInst->GetAugmentItemID(5);
|
||||
// TODO: add hash call
|
||||
}
|
||||
if (m_ItemInst == nullptr) { break; }
|
||||
if (m_ItemInst->GetItem() == nullptr) { break; }
|
||||
item_id = m_ItemInst->GetItem()->ID;
|
||||
augment_1 = m_ItemInst->GetAugmentItemID(0);
|
||||
augment_2 = m_ItemInst->GetAugmentItemID(1);
|
||||
augment_3 = m_ItemInst->GetAugmentItemID(2);
|
||||
augment_4 = m_ItemInst->GetAugmentItemID(3);
|
||||
augment_5 = m_ItemInst->GetAugmentItemID(4);
|
||||
augment_6 = m_ItemInst->GetAugmentItemID(5);
|
||||
ornament_icon = m_ItemInst->GetOrnamentationIcon();
|
||||
// TODO: add hash call
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -8433,23 +8380,27 @@ void Client::TextLink::generate_body()
|
||||
}
|
||||
|
||||
if (m_TaskUse) {
|
||||
hash = 0x0000000014505DC2;
|
||||
//hash = 0x0000000014505DC2;
|
||||
hash = 0x14505DC2;
|
||||
}
|
||||
|
||||
if (field_use[m_ClientVersion][field_0]) { m_LinkBody.append(StringFormat("%01x", unknown_0)); }
|
||||
if (field_use[m_ClientVersion][field_1]) { m_LinkBody.append(StringFormat("%05x", item_id)); }
|
||||
if (field_use[m_ClientVersion][field_2]) { m_LinkBody.append(StringFormat("%05x", augment_0)); }
|
||||
if (field_use[m_ClientVersion][field_3]) { m_LinkBody.append(StringFormat("%05x", augment_1)); }
|
||||
if (field_use[m_ClientVersion][field_4]) { m_LinkBody.append(StringFormat("%05x", augment_2)); }
|
||||
if (field_use[m_ClientVersion][field_5]) { m_LinkBody.append(StringFormat("%05x", augment_3)); }
|
||||
if (field_use[m_ClientVersion][field_6]) { m_LinkBody.append(StringFormat("%05x", augment_4)); }
|
||||
if (field_use[m_ClientVersion][field_7]) { m_LinkBody.append(StringFormat("%05x", augment_5)); }
|
||||
if (field_use[m_ClientVersion][field_8]) { m_LinkBody.append(StringFormat("%01x", unknown_8)); }
|
||||
if (field_use[m_ClientVersion][field_9]) { m_LinkBody.append(StringFormat("%01x", unknown_9)); }
|
||||
if (field_use[m_ClientVersion][field_10]) { m_LinkBody.append(StringFormat("%04x", unknown_10)); }
|
||||
if (field_use[m_ClientVersion][field_11]) { m_LinkBody.append(StringFormat("%01x", unknown_11)); }
|
||||
if (field_use[m_ClientVersion][field_12]) { m_LinkBody.append(StringFormat("%05x", unknown_12)); }
|
||||
if (field_use[m_ClientVersion][field_13]) { m_LinkBody.append(StringFormat("%08x", hash)); }
|
||||
m_LinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X",
|
||||
unknown_1,
|
||||
item_id,
|
||||
augment_1,
|
||||
augment_2,
|
||||
augment_3,
|
||||
augment_4,
|
||||
augment_5,
|
||||
augment_6,
|
||||
unknown_2,
|
||||
unknown_3,
|
||||
unknown_4,
|
||||
unknown_5,
|
||||
ornament_icon,
|
||||
hash
|
||||
);
|
||||
}
|
||||
|
||||
void Client::TextLink::generate_text()
|
||||
@ -8459,35 +8410,76 @@ void Client::TextLink::generate_text()
|
||||
return;
|
||||
}
|
||||
|
||||
const Item_Struct* item_data = nullptr;
|
||||
|
||||
switch (m_LinkType) {
|
||||
case linkBlank:
|
||||
break;
|
||||
case linkItemData:
|
||||
if (m_ItemData != nullptr) {
|
||||
m_LinkText = m_ItemData->Name;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
if (m_ItemData == nullptr) { break; }
|
||||
m_LinkText = m_ItemData->Name;
|
||||
return;
|
||||
case linkLootItem:
|
||||
if (m_LootData != nullptr) {
|
||||
const Item_Struct* item_data = database.GetItem(m_LootData->item_id);
|
||||
if (item_data != nullptr) {
|
||||
m_LinkText = item_data->Name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (m_LootData == nullptr) { break; }
|
||||
item_data = database.GetItem(m_LootData->item_id);
|
||||
if (item_data == nullptr) { break; }
|
||||
m_LinkText = item_data->Name;
|
||||
return;
|
||||
case linkItemInst:
|
||||
if (m_ItemInst != nullptr) {
|
||||
if (m_ItemInst->GetItem() != nullptr) {
|
||||
m_LinkText = m_ItemInst->GetItem()->Name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (m_ItemInst == nullptr) { break; }
|
||||
if (m_ItemInst->GetItem() == nullptr) { break; }
|
||||
m_LinkText = m_ItemInst->GetItem()->Name;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_LinkText = "null";
|
||||
}
|
||||
|
||||
bool Client::TextLink::DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruct, const std::string& textLinkBody)
|
||||
{
|
||||
memset(&textLinkBodyStruct, 0, sizeof(TextLinkBody_Struct));
|
||||
if (textLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
|
||||
textLinkBodyStruct.unknown_1 = (uint8)strtol(textLinkBody.substr(0, 1).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.item_id = (uint32)strtol(textLinkBody.substr(1, 5).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.augment_1 = (uint32)strtol(textLinkBody.substr(6, 5).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.augment_2 = (uint32)strtol(textLinkBody.substr(11, 5).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.augment_3 = (uint32)strtol(textLinkBody.substr(16, 5).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.augment_4 = (uint32)strtol(textLinkBody.substr(21, 5).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.augment_5 = (uint32)strtol(textLinkBody.substr(26, 5).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.augment_6 = (uint32)strtol(textLinkBody.substr(31, 5).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.unknown_2 = (uint8)strtol(textLinkBody.substr(36, 1).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.unknown_3 = (uint8)strtol(textLinkBody.substr(37, 1).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.unknown_4 = (uint32)strtol(textLinkBody.substr(38, 4).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.unknown_5 = (uint8)strtol(textLinkBody.substr(42, 1).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.ornament_icon = (uint32)strtol(textLinkBody.substr(43, 5).c_str(), nullptr, 16);
|
||||
textLinkBodyStruct.hash = (int)strtol(textLinkBody.substr(48, 8).c_str(), nullptr, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLinkBody_Struct& textLinkBodyStruct)
|
||||
{
|
||||
textLinkBody = StringFormat(
|
||||
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X",
|
||||
textLinkBodyStruct.unknown_1,
|
||||
textLinkBodyStruct.item_id,
|
||||
textLinkBodyStruct.augment_1,
|
||||
textLinkBodyStruct.augment_2,
|
||||
textLinkBodyStruct.augment_3,
|
||||
textLinkBodyStruct.augment_4,
|
||||
textLinkBodyStruct.augment_5,
|
||||
textLinkBodyStruct.augment_6,
|
||||
textLinkBodyStruct.unknown_2,
|
||||
textLinkBodyStruct.unknown_3,
|
||||
textLinkBodyStruct.unknown_4,
|
||||
textLinkBodyStruct.unknown_5,
|
||||
textLinkBodyStruct.ornament_icon,
|
||||
textLinkBodyStruct.hash
|
||||
);
|
||||
|
||||
if (textLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -819,7 +819,7 @@ public:
|
||||
//
|
||||
// class Client::TextLink
|
||||
//
|
||||
class TextLink {
|
||||
class TextLink : TextLinkBody_Struct {
|
||||
public:
|
||||
enum LinkType { linkBlank = 0, linkItemData, linkLootItem, linkItemInst };
|
||||
|
||||
@ -832,20 +832,19 @@ public:
|
||||
void SetProxyItemID(uint32 proxyItemID) { m_ProxyItemID = proxyItemID; } // mainly for saylinks..but, not limited to
|
||||
void SetProxyText(const char* proxyText) { m_ProxyText = proxyText; } // overrides standard text use
|
||||
void SetTaskUse() { m_TaskUse = true; }
|
||||
void SetClientVersion(EQClientVersion clientVersion) { m_ClientVersion = EQLimits::ValidateClientVersion(clientVersion); }
|
||||
|
||||
std::string GenerateLink();
|
||||
bool LinkError() { return m_Error; }
|
||||
|
||||
const char* GetLink(); // contains full format: '/12x' '<LinkBody>' '<LinkText>' '/12x'
|
||||
const char* GetLinkBody(); // contains format: '<LinkBody>'
|
||||
const char* GetLinkText(); // contains format: '<LinkText>'
|
||||
std::string GetLinkString();
|
||||
std::string GetLinkBodyString();
|
||||
std::string GetLinkTextString();
|
||||
std::string GetLink() { return m_Link; } // contains full string format: '/12x' '<LinkBody>' '<LinkText>' '/12x'
|
||||
std::string GetLinkBody() { return m_LinkBody; } // contains string format: '<LinkBody>'
|
||||
std::string GetLinkText() { return m_LinkText; } // contains string format: '<LinkText>'
|
||||
|
||||
void Reset();
|
||||
|
||||
static bool DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruct, const std::string& textLinkBody);
|
||||
static bool GenerateLinkBody(std::string& textLinkBody, const TextLinkBody_Struct& textLinkBodyStruct);
|
||||
|
||||
private:
|
||||
void generate_body();
|
||||
void generate_text();
|
||||
@ -860,7 +859,6 @@ public:
|
||||
std::string m_Link;
|
||||
std::string m_LinkBody;
|
||||
std::string m_LinkText;
|
||||
EQClientVersion m_ClientVersion;
|
||||
bool m_Error;
|
||||
};
|
||||
|
||||
|
||||
@ -2621,7 +2621,6 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
std::string item_link;
|
||||
Client::TextLink linker;
|
||||
linker.SetLinkType(linker.linkItemInst);
|
||||
linker.SetClientVersion(c->GetClientVersion());
|
||||
|
||||
c->Message(0, "Displaying inventory for %s...", targetClient->GetName());
|
||||
|
||||
@ -5574,7 +5573,6 @@ void command_itemsearch(Client *c, const Seperator *sep)
|
||||
std::string item_link;
|
||||
Client::TextLink linker;
|
||||
linker.SetLinkType(linker.linkItemData);
|
||||
linker.SetClientVersion(c->GetClientVersion());
|
||||
|
||||
if (Seperator::IsNumber(search_criteria)) {
|
||||
item = database.GetItem(atoi(search_criteria));
|
||||
|
||||
@ -1258,23 +1258,16 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
|
||||
SetPlayerKillItemID(0);
|
||||
}
|
||||
|
||||
/* Send message with item link to groups and such */
|
||||
Client::TextLink linker;
|
||||
linker.SetLinkType(linker.linkItemInst);
|
||||
linker.SetItemInst(inst);
|
||||
linker.SetClientVersion(client->GetClientVersion());
|
||||
/* Send message with item link to groups and such */
|
||||
Client::TextLink linker;
|
||||
linker.SetLinkType(linker.linkItemInst);
|
||||
linker.SetItemInst(inst);
|
||||
|
||||
auto item_link = linker.GenerateLink();
|
||||
|
||||
client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, item_link.c_str());
|
||||
|
||||
if(!IsPlayerCorpse()) {
|
||||
// When sending to multiple/unknown client types, we set for the highest client..
|
||||
// ..which is processed when 'EQClientUnknown,' or default value, is selected.
|
||||
// This should help with any current issues..or it may create more! O.o
|
||||
linker.SetClientVersion(EQClientUnknown);
|
||||
item_link = linker.GenerateLink();
|
||||
|
||||
if (!IsPlayerCorpse()) {
|
||||
Group *g = client->GetGroup();
|
||||
if(g != nullptr) {
|
||||
g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str());
|
||||
|
||||
@ -515,7 +515,6 @@ void NPC::QueryLoot(Client* to)
|
||||
Client::TextLink linker;
|
||||
linker.SetLinkType(linker.linkItemData);
|
||||
linker.SetItemData(item);
|
||||
linker.SetClientVersion(to->GetClientVersion());
|
||||
|
||||
auto item_link = linker.GenerateLink();
|
||||
|
||||
|
||||
@ -1234,7 +1234,6 @@ void QuestManager::itemlink(int item_id) {
|
||||
Client::TextLink linker;
|
||||
linker.SetLinkType(linker.linkItemData);
|
||||
linker.SetItemData(item);
|
||||
linker.SetClientVersion(initiator->GetClientVersion());
|
||||
|
||||
auto item_link = linker.GenerateLink();
|
||||
|
||||
@ -2474,8 +2473,6 @@ const char* QuestManager::varlink(char* perltext, int item_id) {
|
||||
Client::TextLink linker;
|
||||
linker.SetLinkType(linker.linkItemData);
|
||||
linker.SetItemData(item);
|
||||
if (initiator)
|
||||
linker.SetClientVersion(initiator->GetClientVersion());
|
||||
|
||||
auto item_link = linker.GenerateLink();
|
||||
strcpy(perltext, item_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink()
|
||||
@ -2668,8 +2665,6 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam
|
||||
Client::TextLink linker;
|
||||
linker.SetProxyItemID(sayid);
|
||||
linker.SetProxyText(LinkName);
|
||||
if (initiator)
|
||||
linker.SetClientVersion(initiator->GetClientVersion());
|
||||
|
||||
auto say_link = linker.GenerateLink();
|
||||
strcpy(Phrase, say_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink()
|
||||
|
||||
@ -2779,7 +2779,6 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN
|
||||
Client::TextLink linker;
|
||||
linker.SetLinkType(linker.linkItemData);
|
||||
linker.SetItemData(reward_item);
|
||||
linker.SetClientVersion(c->GetClientVersion());
|
||||
linker.SetTaskUse();
|
||||
if (strlen(Tasks[TaskID]->Reward) != 0)
|
||||
linker.SetProxyText(Tasks[TaskID]->Reward);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user