Rework of the text link translator code (Known bug with broadcast message link size not in OP_ChannelMessage or OP_SpecialMesg)

This commit is contained in:
Uleat 2015-01-06 23:19:41 -05:00
parent 2c43e6f68d
commit b27737bfcd
15 changed files with 304 additions and 2133 deletions

View File

@ -5270,19 +5270,20 @@ struct ClientMarqueeMessage_Struct {
typedef std::list<ServerLootItem_Struct*> ItemList; typedef std::list<ServerLootItem_Struct*> ItemList;
struct TextLinkBody_Struct { struct TextLinkBody_Struct {
uint8 unknown_1; // Current server mask: EQClientRoF2
uint32 item_id; uint8 unknown_1; /* %1X */
uint32 augment_1; uint32 item_id; /* %05X */
uint32 augment_2; uint32 augment_1; /* %05X */
uint32 augment_3; uint32 augment_2; /* %05X */
uint32 augment_4; uint32 augment_3; /* %05X */
uint32 augment_5; uint32 augment_4; /* %05X */
uint32 augment_6; uint32 augment_5; /* %05X */
uint8 is_evolving; uint32 augment_6; /* %05X */
uint32 lore_group; uint8 is_evolving; /* %1X */
uint8 evolve_max; uint32 evolve_group; /* %05X */
uint32 ornament_icon; uint8 evolve_level; /* %02X */
int hash; uint32 ornament_icon; /* %05X */
int hash; /* %08X */
}; };
// Restore structure packing to default // Restore structure packing to default

View File

@ -33,17 +33,11 @@ namespace RoF
static inline uint32 RoFToServerMainInvSlot(structs::MainInvItemSlotStruct RoFSlot); static inline uint32 RoFToServerMainInvSlot(structs::MainInvItemSlotStruct RoFSlot);
static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse); static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse);
// server to client text link converters // server to client text link converter
static inline void ServerToRoFTextLinks(std::string& rofTextLink, const std::string& serverTextLink); static inline void ServerToRoFTextLink(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 // client to server text link converter
static inline void RoFToServerTextLinks(std::string& serverTextLink, const std::string& rofTextLink); static inline void RoFToServerTextLink(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) void Register(EQStreamIdentifier &into)
{ {
@ -502,7 +496,7 @@ namespace RoF
std::string old_message = emu->message; std::string old_message = emu->message;
std::string new_message; std::string new_message;
ServerToRoFTextLinks(new_message, old_message); ServerToRoFTextLink(new_message, old_message);
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; //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->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
@ -3125,7 +3119,7 @@ namespace RoF
std::string old_message = &emu->message[strlen(emu->sayer)]; std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message; std::string new_message;
ServerToRoFTextLinks(new_message, old_message); ServerToRoFTextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = 25 + strlen(emu->sayer) + new_message.length(); in->size = 25 + strlen(emu->sayer) + new_message.length();
@ -4099,7 +4093,7 @@ namespace RoF
std::string old_message = InBuffer; std::string old_message = InBuffer;
std::string new_message; std::string new_message;
RoFToServerTextLinks(new_message, old_message); RoFToServerTextLink(new_message, old_message);
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; //__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@ -5651,361 +5645,77 @@ namespace RoF
return (RoFCorpse - 1); return (RoFCorpse - 1);
} }
static inline void ServerToRoFTextLinks(std::string& rofTextLink, const std::string& serverTextLink) static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink)
{ {
const char delimiter = 0x12; 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)) { if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
rofTextLink = serverTextLink; rofTextLink = serverTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(serverTextLink, delimiter); auto segments = SplitString(serverTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
structs::TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
ServerToRoFTextLinkBodyStruct(new_body_data, old_body_data); // RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// RoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (55)
// Diff: ^
std::string segment; new_segment.append(segments[segment_iter].substr(0, 41).c_str());
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) { if (segments[segment_iter].substr(41, 1) == "0")
_log(CHANNELS__ERROR, "TextLink(Server->RoF): conversion error"); new_segment.append(segments[segment_iter].substr(42, 1).c_str());
rofTextLink = serverTextLink; else
return; new_segment.append("F");
}
new_segment.append(segments[segment_iter].substr(43).c_str());
for (size_t iter = 0; iter < segments.size(); ++iter) {
if (iter & 1) {
rofTextLink.push_back(delimiter); rofTextLink.push_back(delimiter);
rofTextLink.append(segments[iter].c_str()); rofTextLink.append(new_segment.c_str());
rofTextLink.push_back(delimiter); rofTextLink.push_back(delimiter);
} }
else { else {
rofTextLink.append(segments[iter].c_str()); rofTextLink.append(segments[segment_iter].c_str());
} }
} }
#endif
} }
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink)
{
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.is_evolving = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
serverLinkBodyStruct.lore_group = (uint32)strtol(serverLinkBody.substr(37, 5).c_str(), nullptr, 16);
serverLinkBodyStruct.evolve_max = (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.is_evolving = serverLinkBodyStruct.is_evolving;
rofLinkBodyStruct.lore_group = serverLinkBodyStruct.lore_group;
rofLinkBodyStruct.evolve_max = serverLinkBodyStruct.evolve_max;
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.is_evolving,
rofLinkBodyStruct.lore_group,
rofLinkBodyStruct.evolve_max,
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; 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)) { if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find(delimiter) == std::string::npos)) {
serverTextLink = rofTextLink; serverTextLink = rofTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(rofTextLink, delimiter); auto segments = SplitString(rofTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
structs::TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateRoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 36 37 41 42 47 (Source)
RoFToServerTextLinkBodyStruct(new_body_data, old_body_data); // RoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (55)
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff: ^
std::string segment; new_segment.append(segments[segment_iter].substr(0, 41).c_str());
if (!GenerateServerTextLinkBody(segment, new_body_data)) { new_segment.append("0");
conversion_error = true; new_segment.append(segments[segment_iter].substr(41).c_str());
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.push_back(delimiter);
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(new_segment.c_str());
serverTextLink.push_back(delimiter); serverTextLink.push_back(delimiter);
} }
else { else {
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(segments[segment_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.is_evolving = (uint8)strtol(rofLinkBody.substr(36, 1).c_str(), nullptr, 16);
rofLinkBodyStruct.lore_group = (uint32)strtol(rofLinkBody.substr(37, 4).c_str(), nullptr, 16);
rofLinkBodyStruct.evolve_max = (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.is_evolving = rofLinkBodyStruct.is_evolving;
serverLinkBodyStruct.lore_group = rofLinkBodyStruct.lore_group;
serverLinkBodyStruct.evolve_max = rofLinkBodyStruct.evolve_max;
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" "%05X" "%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.is_evolving,
serverLinkBodyStruct.lore_group,
serverLinkBodyStruct.evolve_max,
serverLinkBodyStruct.ornament_icon,
serverLinkBodyStruct.hash
);
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
return true;
} }
} }
// end namespace RoF // end namespace RoF

View File

@ -33,17 +33,11 @@ namespace RoF2
static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct RoF2Slot); static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct RoF2Slot);
static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse); static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse);
// server to client text link converters // server to client text link converter
static inline void ServerToRoF2TextLinks(std::string& rof2TextLink, const std::string& serverTextLink); static inline void ServerToRoF2TextLink(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 // client to server text link converter
static inline void RoF2ToServerTextLinks(std::string& serverTextLink, const std::string& rof2TextLink); static inline void RoF2ToServerTextLink(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) void Register(EQStreamIdentifier &into)
{ {
@ -568,7 +562,7 @@ namespace RoF2
std::string old_message = emu->message; std::string old_message = emu->message;
std::string new_message; std::string new_message;
ServerToRoF2TextLinks(new_message, old_message); ServerToRoF2TextLink(new_message, old_message);
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; //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->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
@ -3191,7 +3185,7 @@ namespace RoF2
std::string old_message = &emu->message[strlen(emu->sayer)]; std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message; std::string new_message;
ServerToRoF2TextLinks(new_message, old_message); ServerToRoF2TextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = 25 + strlen(emu->sayer) + new_message.length(); in->size = 25 + strlen(emu->sayer) + new_message.length();
@ -4171,7 +4165,7 @@ namespace RoF2
std::string old_message = InBuffer; std::string old_message = InBuffer;
std::string new_message; std::string new_message;
RoF2ToServerTextLinks(new_message, old_message); RoF2ToServerTextLink(new_message, old_message);
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; //__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@ -5746,361 +5740,68 @@ namespace RoF2
return (RoF2Corpse + EmuConstants::CORPSE_BEGIN - 1); return (RoF2Corpse + EmuConstants::CORPSE_BEGIN - 1);
} }
static inline void ServerToRoF2TextLinks(std::string& rof2TextLink, const std::string& serverTextLink) static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink)
{ {
const char delimiter = 0x12; 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)) { if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
rof2TextLink = serverTextLink; rof2TextLink = serverTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(serverTextLink, delimiter); auto segments = SplitString(serverTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
structs::TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
ServerToRoF2TextLinkBodyStruct(new_body_data, old_body_data); // RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff:
std::string segment; new_segment.append(segments[segment_iter]);
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.push_back(delimiter);
rof2TextLink.append(segments[iter].c_str()); rof2TextLink.append(new_segment.c_str());
rof2TextLink.push_back(delimiter); rof2TextLink.push_back(delimiter);
} }
else { else {
rof2TextLink.append(segments[iter].c_str()); rof2TextLink.append(segments[segment_iter].c_str());
} }
} }
#endif
} }
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink)
{
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.is_evolving = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
serverLinkBodyStruct.lore_group = (uint32)strtol(serverLinkBody.substr(37, 5).c_str(), nullptr, 16);
serverLinkBodyStruct.evolve_max = (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.is_evolving = serverLinkBodyStruct.is_evolving;
rof2LinkBodyStruct.lore_group = serverLinkBodyStruct.lore_group;
rof2LinkBodyStruct.evolve_max = serverLinkBodyStruct.evolve_max;
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" "%05X" "%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.is_evolving,
rof2LinkBodyStruct.lore_group,
rof2LinkBodyStruct.evolve_max,
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; 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)) { if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find(delimiter) == std::string::npos)) {
serverTextLink = rof2TextLink; serverTextLink = rof2TextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(rof2TextLink, delimiter); auto segments = SplitString(rof2TextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
structs::TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateRoF2TextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
RoF2ToServerTextLinkBodyStruct(new_body_data, old_body_data); // RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff:
std::string segment; new_segment.append(segments[segment_iter]);
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.push_back(delimiter);
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(new_segment.c_str());
serverTextLink.push_back(delimiter); serverTextLink.push_back(delimiter);
} }
else { else {
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(segments[segment_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" "%05X" "%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.is_evolving = (uint8)strtol(rof2LinkBody.substr(36, 1).c_str(), nullptr, 16);
rof2LinkBodyStruct.lore_group = (uint32)strtol(rof2LinkBody.substr(37, 5).c_str(), nullptr, 16);
rof2LinkBodyStruct.evolve_max = (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.is_evolving = rof2LinkBodyStruct.is_evolving;
serverLinkBodyStruct.lore_group = rof2LinkBodyStruct.lore_group;
serverLinkBodyStruct.evolve_max = rof2LinkBodyStruct.evolve_max;
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" "%05X" "%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.is_evolving,
serverLinkBodyStruct.lore_group,
serverLinkBodyStruct.evolve_max,
serverLinkBodyStruct.ornament_icon,
serverLinkBodyStruct.hash
);
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
return true;
} }
} }
// end namespace RoF2 // end namespace RoF2

View File

@ -4872,24 +4872,6 @@ struct MercenaryMerchantResponse_Struct {
/*0004*/ /*0004*/
}; };
// RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X"
struct TextLinkBody_Struct
{
uint8 unknown_1;
uint32 item_id;
uint32 augment_1;
uint32 augment_2;
uint32 augment_3;
uint32 augment_4;
uint32 augment_5;
uint32 augment_6;
uint8 is_evolving;
uint32 lore_group;
uint8 evolve_max;
uint32 ornament_icon;
int hash;
};
}; //end namespace structs }; //end namespace structs
}; //end namespace RoF2 }; //end namespace RoF2

View File

@ -4894,24 +4894,6 @@ struct MercenaryMerchantResponse_Struct {
/*0004*/ /*0004*/
}; };
// RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
struct TextLinkBody_Struct
{
uint8 unknown_1;
uint32 item_id;
uint32 augment_1;
uint32 augment_2;
uint32 augment_3;
uint32 augment_4;
uint32 augment_5;
uint32 augment_6;
uint8 is_evolving;
uint32 lore_group;
uint8 evolve_max;
uint32 ornament_icon;
int hash;
};
}; //end namespace structs }; //end namespace structs
}; //end namespace RoF }; //end namespace RoF

View File

@ -31,17 +31,11 @@ namespace SoD
static inline uint32 SoDToServerSlot(uint32 SoDSlot); static inline uint32 SoDToServerSlot(uint32 SoDSlot);
static inline uint32 SoDToServerCorpseSlot(uint32 SoDCorpse); static inline uint32 SoDToServerCorpseSlot(uint32 SoDCorpse);
// server to client text link converters // server to client text link converter
static inline void ServerToSoDTextLinks(std::string& sodTextLink, const std::string& serverTextLink); static inline void ServerToSoDTextLink(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 // client to server text link converter
static inline void SoDToServerTextLinks(std::string& serverTextLink, const std::string& sodTextLink); static inline void SoDToServerTextLink(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) void Register(EQStreamIdentifier &into)
{ {
@ -319,7 +313,7 @@ namespace SoD
std::string old_message = emu->message; std::string old_message = emu->message;
std::string new_message; std::string new_message;
ServerToSoDTextLinks(new_message, old_message); ServerToSoDTextLink(new_message, old_message);
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@ -2015,7 +2009,7 @@ namespace SoD
std::string old_message = &emu->message[strlen(emu->sayer)]; std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message; std::string new_message;
ServerToSoDTextLinks(new_message, old_message); ServerToSoDTextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = 25 + strlen(emu->sayer) + new_message.length(); in->size = 25 + strlen(emu->sayer) + new_message.length();
@ -2814,7 +2808,7 @@ namespace SoD
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)]; std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
std::string new_message; std::string new_message;
SoDToServerTextLinks(new_message, old_message); SoDToServerTextLink(new_message, old_message);
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
__packet->pBuffer = new unsigned char[__packet->size]; __packet->pBuffer = new unsigned char[__packet->size];
@ -3865,358 +3859,80 @@ namespace SoD
return (SoDCorpse - 1); return (SoDCorpse - 1);
} }
static inline void ServerToSoDTextLinks(std::string& sodTextLink, const std::string& serverTextLink) static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink)
{ {
const char delimiter = 0x12; 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)) { if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
sodTextLink = serverTextLink; sodTextLink = serverTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(serverTextLink, delimiter); auto segments = SplitString(serverTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
structs::TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
ServerToSoDTextLinkBodyStruct(new_body_data, old_body_data); // RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
// Diff: ^^^^^ ^
std::string segment; new_segment.append(segments[segment_iter].substr(0, 31).c_str());
if (!GenerateSoDTextLinkBody(segment, new_body_data)) { new_segment.append(segments[segment_iter].substr(36, 5).c_str());
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) { if (segments[segment_iter].substr(41, 1) == "0")
_log(CHANNELS__ERROR, "TextLink(Server->SoD): conversion error"); new_segment.append(segments[segment_iter].substr(42, 1).c_str());
sodTextLink = serverTextLink; else
return; new_segment.append("F");
}
new_segment.append(segments[segment_iter].substr(43).c_str());
for (size_t iter = 0; iter < segments.size(); ++iter) {
if (iter & 1) {
sodTextLink.push_back(delimiter); sodTextLink.push_back(delimiter);
sodTextLink.append(segments[iter].c_str()); sodTextLink.append(new_segment.c_str());
sodTextLink.push_back(delimiter); sodTextLink.push_back(delimiter);
} }
else { else {
sodTextLink.append(segments[iter].c_str()); sodTextLink.append(segments[segment_iter].c_str());
} }
} }
#endif
} }
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink)
{
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.is_evolving = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
serverLinkBodyStruct.lore_group = (uint32)strtol(serverLinkBody.substr(37, 5).c_str(), nullptr, 16);
serverLinkBodyStruct.evolve_max = (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.is_evolving = serverLinkBodyStruct.is_evolving;
sodLinkBodyStruct.lore_group = serverLinkBodyStruct.lore_group;
sodLinkBodyStruct.evolve_max = serverLinkBodyStruct.evolve_max;
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.is_evolving,
sodLinkBodyStruct.lore_group,
sodLinkBodyStruct.evolve_max,
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; 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)) { if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find(delimiter) == std::string::npos)) {
serverTextLink = sodTextLink; serverTextLink = sodTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(sodTextLink, delimiter); auto segments = SplitString(sodTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
structs::TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateSoDTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 32 36 37 42 (Source)
SoDToServerTextLinkBodyStruct(new_body_data, old_body_data); // SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff: ^^^^^ ^
std::string segment; new_segment.append(segments[segment_iter].substr(0, 31).c_str());
if (!GenerateServerTextLinkBody(segment, new_body_data)) { new_segment.append("00000");
conversion_error = true; new_segment.append(segments[segment_iter].substr(31, 5).c_str());
break; new_segment.append("0");
} new_segment.append(segments[segment_iter].substr(36).c_str());
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.push_back(delimiter);
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(new_segment.c_str());
serverTextLink.push_back(delimiter); serverTextLink.push_back(delimiter);
} }
else { else {
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(segments[segment_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.is_evolving = (uint8)strtol(sodLinkBody.substr(31, 1).c_str(), nullptr, 16);
sodLinkBodyStruct.lore_group = (uint32)strtol(sodLinkBody.substr(32, 4).c_str(), nullptr, 16);
sodLinkBodyStruct.evolve_max = (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.is_evolving = sodLinkBodyStruct.is_evolving;
serverLinkBodyStruct.lore_group = sodLinkBodyStruct.lore_group;
serverLinkBodyStruct.evolve_max = sodLinkBodyStruct.evolve_max;
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" "%05X" "%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.is_evolving,
serverLinkBodyStruct.lore_group,
serverLinkBodyStruct.evolve_max,
serverLinkBodyStruct.ornament_icon,
serverLinkBodyStruct.hash
);
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
return true;
} }
} }
// end namespace SoD // end namespace SoD

View File

@ -4409,23 +4409,6 @@ struct MercenaryAssign_Struct {
/*0012*/ /*0012*/
}; };
// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
struct TextLinkBody_Struct
{
uint8 unknown_1;
uint32 item_id;
uint32 augment_1;
uint32 augment_2;
uint32 augment_3;
uint32 augment_4;
uint32 augment_5;
uint8 is_evolving;
uint32 lore_group;
uint8 evolve_max;
uint32 ornament_icon;
int hash;
};
}; //end namespace structs }; //end namespace structs
}; //end namespace SoD }; //end namespace SoD

View File

@ -31,17 +31,11 @@ namespace SoF
static inline uint32 SoFToServerSlot(uint32 SoFSlot); static inline uint32 SoFToServerSlot(uint32 SoFSlot);
static inline uint32 SoFToServerCorpseSlot(uint32 SoFCorpse); static inline uint32 SoFToServerCorpseSlot(uint32 SoFCorpse);
// server to client text link converters // server to client text link converter
static inline void ServerToSoFTextLinks(std::string& sofTextLink, const std::string& serverTextLink); static inline void ServerToSoFTextLink(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 // client to server text link converter
static inline void SoFToServerTextLinks(std::string& serverTextLink, const std::string& sofTextLink); static inline void SoFToServerTextLink(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) void Register(EQStreamIdentifier &into)
{ {
@ -301,7 +295,7 @@ namespace SoF
std::string old_message = emu->message; std::string old_message = emu->message;
std::string new_message; std::string new_message;
ServerToSoFTextLinks(new_message, old_message); ServerToSoFTextLink(new_message, old_message);
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@ -1661,7 +1655,7 @@ namespace SoF
std::string old_message = &emu->message[strlen(emu->sayer)]; std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message; std::string new_message;
ServerToSoFTextLinks(new_message, old_message); ServerToSoFTextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = 25 + strlen(emu->sayer) + new_message.length(); in->size = 25 + strlen(emu->sayer) + new_message.length();
@ -2214,7 +2208,7 @@ namespace SoF
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)]; std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
std::string new_message; std::string new_message;
SoFToServerTextLinks(new_message, old_message); SoFToServerTextLink(new_message, old_message);
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
__packet->pBuffer = new unsigned char[__packet->size]; __packet->pBuffer = new unsigned char[__packet->size];
@ -3187,358 +3181,80 @@ namespace SoF
return (SoFCorpse - 1); return (SoFCorpse - 1);
} }
static inline void ServerToSoFTextLinks(std::string& sofTextLink, const std::string& serverTextLink) static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink)
{ {
const char delimiter = 0x12; 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)) { if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
sofTextLink = serverTextLink; sofTextLink = serverTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(serverTextLink, delimiter); auto segments = SplitString(serverTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
structs::TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
ServerToSoFTextLinkBodyStruct(new_body_data, old_body_data); // RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
// Diff: ^^^^^ ^
std::string segment; new_segment.append(segments[segment_iter].substr(0, 31).c_str());
if (!GenerateSoFTextLinkBody(segment, new_body_data)) { new_segment.append(segments[segment_iter].substr(36, 5).c_str());
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) { if (segments[segment_iter].substr(41, 1) == "0")
_log(CHANNELS__ERROR, "TextLink(Server->SoF): conversion error"); new_segment.append(segments[segment_iter].substr(42, 1).c_str());
sofTextLink = serverTextLink; else
return; new_segment.append("F");
}
new_segment.append(segments[segment_iter].substr(43).c_str());
for (size_t iter = 0; iter < segments.size(); ++iter) {
if (iter & 1) {
sofTextLink.push_back(delimiter); sofTextLink.push_back(delimiter);
sofTextLink.append(segments[iter].c_str()); sofTextLink.append(new_segment.c_str());
sofTextLink.push_back(delimiter); sofTextLink.push_back(delimiter);
} }
else { else {
sofTextLink.append(segments[iter].c_str()); sofTextLink.append(segments[segment_iter].c_str());
} }
} }
#endif
} }
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink)
{
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.is_evolving = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
serverLinkBodyStruct.lore_group = (uint32)strtol(serverLinkBody.substr(37, 5).c_str(), nullptr, 16);
serverLinkBodyStruct.evolve_max = (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.is_evolving = serverLinkBodyStruct.is_evolving;
sofLinkBodyStruct.lore_group = serverLinkBodyStruct.lore_group;
sofLinkBodyStruct.evolve_max = serverLinkBodyStruct.evolve_max;
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.is_evolving,
sofLinkBodyStruct.lore_group,
sofLinkBodyStruct.evolve_max,
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; 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)) { if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find(delimiter) == std::string::npos)) {
serverTextLink = sofTextLink; serverTextLink = sofTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(sofTextLink, delimiter); auto segments = SplitString(sofTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
structs::TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateSoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 32 36 37 42 (Source)
SoFToServerTextLinkBodyStruct(new_body_data, old_body_data); // SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff: ^^^^^ ^
std::string segment; new_segment.append(segments[segment_iter].substr(0, 31).c_str());
if (!GenerateServerTextLinkBody(segment, new_body_data)) { new_segment.append("00000");
conversion_error = true; new_segment.append(segments[segment_iter].substr(31, 5).c_str());
break; new_segment.append("0");
} new_segment.append(segments[segment_iter].substr(36).c_str());
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.push_back(delimiter);
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(new_segment.c_str());
serverTextLink.push_back(delimiter); serverTextLink.push_back(delimiter);
} }
else { else {
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(segments[segment_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.is_evolving = (uint8)strtol(sofLinkBody.substr(31, 1).c_str(), nullptr, 16);
sofLinkBodyStruct.lore_group = (uint32)strtol(sofLinkBody.substr(32, 4).c_str(), nullptr, 16);
sofLinkBodyStruct.evolve_max = (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.is_evolving = sofLinkBodyStruct.is_evolving;
serverLinkBodyStruct.lore_group = sofLinkBodyStruct.lore_group;
serverLinkBodyStruct.evolve_max = sofLinkBodyStruct.evolve_max;
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" "%05X" "%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.is_evolving,
serverLinkBodyStruct.lore_group,
serverLinkBodyStruct.evolve_max,
serverLinkBodyStruct.ornament_icon,
serverLinkBodyStruct.hash
);
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
return true;
} }
} }
// end namespace SoF // end namespace SoF

View File

@ -4115,23 +4115,6 @@ struct AltCurrencySellItem_Struct {
/*010*/ uint32 cost; /*010*/ uint32 cost;
}; };
// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
struct TextLinkBody_Struct
{
uint8 unknown_1;
uint32 item_id;
uint32 augment_1;
uint32 augment_2;
uint32 augment_3;
uint32 augment_4;
uint32 augment_5;
uint8 is_evolving;
uint32 lore_group;
uint8 evolve_max;
uint32 ornament_icon;
int hash;
};
}; //end namespace structs }; //end namespace structs
}; //end namespace SoF }; //end namespace SoF

View File

@ -29,17 +29,11 @@ namespace Titanium
static inline uint32 TitaniumToServerSlot(int16 TitaniumSlot); static inline uint32 TitaniumToServerSlot(int16 TitaniumSlot);
static inline uint32 TitaniumToServerCorpseSlot(int16 TitaniumCorpse); static inline uint32 TitaniumToServerCorpseSlot(int16 TitaniumCorpse);
// server to client text link converters // server to client text link converter
static inline void ServerToTitaniumTextLinks(std::string& titaniumTextLink, const std::string& serverTextLink); static inline void ServerToTitaniumTextLink(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 // client to server text link converter
static inline void TitaniumToServerTextLinks(std::string& serverTextLink, const std::string& titaniumTextLink); static inline void TitaniumToServerTextLink(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) void Register(EQStreamIdentifier &into)
{ {
@ -244,7 +238,7 @@ namespace Titanium
std::string old_message = emu->message; std::string old_message = emu->message;
std::string new_message; std::string new_message;
ServerToTitaniumTextLinks(new_message, old_message); ServerToTitaniumTextLink(new_message, old_message);
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@ -1123,7 +1117,7 @@ namespace Titanium
std::string old_message = &emu->message[strlen(emu->sayer)]; std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message; std::string new_message;
ServerToTitaniumTextLinks(new_message, old_message); ServerToTitaniumTextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = 25 + strlen(emu->sayer) + new_message.length(); in->size = 25 + strlen(emu->sayer) + new_message.length();
@ -1457,7 +1451,7 @@ namespace Titanium
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)]; std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
std::string new_message; std::string new_message;
TitaniumToServerTextLinks(new_message, old_message); TitaniumToServerTextLink(new_message, old_message);
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
__packet->pBuffer = new unsigned char[__packet->size]; __packet->pBuffer = new unsigned char[__packet->size];
@ -1946,355 +1940,82 @@ namespace Titanium
return TitaniumCorpse; return TitaniumCorpse;
} }
static inline void ServerToTitaniumTextLinks(std::string& titaniumTextLink, const std::string& serverTextLink) static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink)
{ {
const char delimiter = 0x12; 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)) { if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
titaniumTextLink = serverTextLink; titaniumTextLink = serverTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(serverTextLink, delimiter); auto segments = SplitString(serverTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
structs::TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
ServerToTitaniumTextLinkBodyStruct(new_body_data, old_body_data); // RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// 6.2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXXXXX (45)
// Diff: ^^^^^ ^ ^^^^^
std::string segment; new_segment.append(segments[segment_iter].substr(0, 31).c_str());
if (!GenerateTitaniumTextLinkBody(segment, new_body_data)) { new_segment.append(segments[segment_iter].substr(36, 5).c_str());
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) { if (segments[segment_iter].substr(41, 1) == "0")
_log(CHANNELS__ERROR, "TextLink(Server->Titanium): conversion error"); new_segment.append(segments[segment_iter].substr(42, 1).c_str());
titaniumTextLink = serverTextLink; else
return; new_segment.append("F");
}
new_segment.append(segments[segment_iter].substr(48).c_str());
for (size_t iter = 0; iter < segments.size(); ++iter) {
if (iter & 1) {
titaniumTextLink.push_back(delimiter); titaniumTextLink.push_back(delimiter);
titaniumTextLink.append(segments[iter].c_str()); titaniumTextLink.append(new_segment.c_str());
titaniumTextLink.push_back(delimiter); titaniumTextLink.push_back(delimiter);
} }
else { else {
titaniumTextLink.append(segments[iter].c_str()); titaniumTextLink.append(segments[segment_iter].c_str());
} }
} }
#endif
} }
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink)
{
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.is_evolving = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
serverLinkBodyStruct.lore_group = (uint32)strtol(serverLinkBody.substr(37, 5).c_str(), nullptr, 16);
serverLinkBodyStruct.evolve_max = (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.is_evolving = serverLinkBodyStruct.is_evolving;
titaniumLinkBodyStruct.lore_group = serverLinkBodyStruct.lore_group;
titaniumLinkBodyStruct.evolve_max = serverLinkBodyStruct.evolve_max;
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.is_evolving,
titaniumLinkBodyStruct.lore_group,
titaniumLinkBodyStruct.evolve_max,
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; 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)) { if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find(delimiter) == std::string::npos)) {
serverTextLink = titaniumTextLink; serverTextLink = titaniumTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(titaniumTextLink, delimiter); auto segments = SplitString(titaniumTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
structs::TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateTitaniumTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 32 36 37 (Source)
TitaniumToServerTextLinkBodyStruct(new_body_data, old_body_data); // 6.2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXXXXX (45)
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff: ^^^^^ ^ ^^^^^
std::string segment; new_segment.append(segments[segment_iter].substr(0, 31).c_str());
if (!GenerateServerTextLinkBody(segment, new_body_data)) { new_segment.append("00000");
conversion_error = true; new_segment.append(segments[segment_iter].substr(31, 5).c_str());
break; new_segment.append("0");
} new_segment.append(segments[segment_iter].substr(36, 1).c_str());
else { new_segment.append("00000");
segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); new_segment.append(segments[segment_iter].substr(37).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.push_back(delimiter);
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(new_segment.c_str());
serverTextLink.push_back(delimiter); serverTextLink.push_back(delimiter);
} }
else { else {
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(segments[segment_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.is_evolving = (uint8)strtol(titaniumLinkBody.substr(31, 1).c_str(), nullptr, 16);
titaniumLinkBodyStruct.lore_group = (uint32)strtol(titaniumLinkBody.substr(32, 4).c_str(), nullptr, 16);
titaniumLinkBodyStruct.evolve_max = (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.is_evolving = titaniumLinkBodyStruct.is_evolving;
serverLinkBodyStruct.lore_group = titaniumLinkBodyStruct.lore_group;
serverLinkBodyStruct.evolve_max = titaniumLinkBodyStruct.evolve_max;
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" "%05X" "%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.is_evolving,
serverLinkBodyStruct.lore_group,
serverLinkBodyStruct.evolve_max,
serverLinkBodyStruct.ornament_icon,
serverLinkBodyStruct.hash
);
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
return true;
} }
} }
// end namespace Titanium // end namespace Titanium

View File

@ -3329,22 +3329,6 @@ struct LFGuild_GuildToggle_Struct
/*616*/ /*616*/
}; };
// 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X"
struct TextLinkBody_Struct
{
uint8 unknown_1;
uint32 item_id;
uint32 augment_1;
uint32 augment_2;
uint32 augment_3;
uint32 augment_4;
uint32 augment_5;
uint8 is_evolving;
uint32 lore_group;
uint8 evolve_max;
int hash;
};
}; //end namespace structs }; //end namespace structs
}; //end namespace Titanium }; //end namespace Titanium

View File

@ -31,17 +31,11 @@ namespace Underfoot
static inline uint32 UnderfootToServerSlot(uint32 UnderfootSlot); static inline uint32 UnderfootToServerSlot(uint32 UnderfootSlot);
static inline uint32 UnderfootToServerCorpseSlot(uint32 UnderfootCorpse); static inline uint32 UnderfootToServerCorpseSlot(uint32 UnderfootCorpse);
// server to client text link converters // server to client text link converter
static inline void ServerToUnderfootTextLinks(std::string& underfootTextLink, const std::string& serverTextLink); static inline void ServerToUnderfootTextLink(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 // client to server text link converter
static inline void UnderfootToServerTextLinks(std::string& serverTextLink, const std::string& underfootTextLink); static inline void UnderfootToServerTextLink(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) void Register(EQStreamIdentifier &into)
{ {
@ -446,7 +440,7 @@ namespace Underfoot
std::string old_message = emu->message; std::string old_message = emu->message;
std::string new_message; std::string new_message;
ServerToUnderfootTextLinks(new_message, old_message); ServerToUnderfootTextLink(new_message, old_message);
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; //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->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
@ -2326,7 +2320,7 @@ namespace Underfoot
std::string old_message = &emu->message[strlen(emu->sayer)]; std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message; std::string new_message;
ServerToUnderfootTextLinks(new_message, old_message); ServerToUnderfootTextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = 25 + strlen(emu->sayer) + new_message.length(); in->size = 25 + strlen(emu->sayer) + new_message.length();
@ -3093,7 +3087,7 @@ namespace Underfoot
std::string old_message = InBuffer; std::string old_message = InBuffer;
std::string new_message; std::string new_message;
UnderfootToServerTextLinks(new_message, old_message); UnderfootToServerTextLink(new_message, old_message);
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; //__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@ -4168,358 +4162,80 @@ namespace Underfoot
return (UnderfootCorpse - 1); return (UnderfootCorpse - 1);
} }
static inline void ServerToUnderfootTextLinks(std::string& underfootTextLink, const std::string& serverTextLink) static inline void ServerToUnderfootTextLink(std::string& underfootTextLink, const std::string& serverTextLink)
{ {
const char delimiter = 0x12; 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)) { if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) {
underfootTextLink = serverTextLink; underfootTextLink = serverTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(serverTextLink, delimiter); auto segments = SplitString(serverTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
structs::TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source)
ServerToUnderfootTextLinkBodyStruct(new_body_data, old_body_data); // RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
// Diff: ^^^^^ ^
std::string segment; new_segment.append(segments[segment_iter].substr(0, 31).c_str());
if (!GenerateUnderfootTextLinkBody(segment, new_body_data)) { new_segment.append(segments[segment_iter].substr(36, 5).c_str());
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) { if (segments[segment_iter].substr(41, 1) == "0")
_log(CHANNELS__ERROR, "TextLink(Server->Underfoot): conversion error"); new_segment.append(segments[segment_iter].substr(42, 1).c_str());
underfootTextLink = serverTextLink; else
return; new_segment.append("F");
}
new_segment.append(segments[segment_iter].substr(43).c_str());
for (size_t iter = 0; iter < segments.size(); ++iter) {
if (iter & 1) {
underfootTextLink.push_back(delimiter); underfootTextLink.push_back(delimiter);
underfootTextLink.append(segments[iter].c_str()); underfootTextLink.append(new_segment.c_str());
underfootTextLink.push_back(delimiter); underfootTextLink.push_back(delimiter);
} }
else { else {
underfootTextLink.append(segments[iter].c_str()); underfootTextLink.append(segments[segment_iter].c_str());
} }
} }
#endif
} }
static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) static inline void UnderfootToServerTextLink(std::string& serverTextLink, const std::string& underfootTextLink)
{
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.is_evolving = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16);
serverLinkBodyStruct.lore_group = (uint32)strtol(serverLinkBody.substr(37, 5).c_str(), nullptr, 16);
serverLinkBodyStruct.evolve_max = (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.is_evolving = serverLinkBodyStruct.is_evolving;
underfootLinkBodyStruct.lore_group = serverLinkBodyStruct.lore_group;
underfootLinkBodyStruct.evolve_max = serverLinkBodyStruct.evolve_max;
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.is_evolving,
underfootLinkBodyStruct.lore_group,
underfootLinkBodyStruct.evolve_max,
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; 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)) { if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (underfootTextLink.find(delimiter) == std::string::npos)) {
serverTextLink = underfootTextLink; serverTextLink = underfootTextLink;
return; return;
} }
bool conversion_error = false;
auto segments = SplitString(underfootTextLink, delimiter); auto segments = SplitString(underfootTextLink, delimiter);
for (size_t iter = 1; iter < segments.size(); iter += 2) { for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
structs::TextLinkBody_Struct old_body_data; if (segment_iter & 1) {
if (!DegenerateUnderfootTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { std::string new_segment;
conversion_error = true;
break;
}
TextLinkBody_Struct new_body_data; // Idx: 0 1 6 11 16 21 26 31 32 36 37 42 (Source)
UnderfootToServerTextLinkBodyStruct(new_body_data, old_body_data); // SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff: ^^^^^ ^
std::string segment; new_segment.append(segments[segment_iter].substr(0, 31).c_str());
if (!GenerateServerTextLinkBody(segment, new_body_data)) { new_segment.append("00000");
conversion_error = true; new_segment.append(segments[segment_iter].substr(31, 5).c_str());
break; new_segment.append("0");
} new_segment.append(segments[segment_iter].substr(36).c_str());
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.push_back(delimiter);
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(new_segment.c_str());
serverTextLink.push_back(delimiter); serverTextLink.push_back(delimiter);
} }
else { else {
serverTextLink.append(segments[iter].c_str()); serverTextLink.append(segments[segment_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.is_evolving = (uint8)strtol(underfootLinkBody.substr(31, 1).c_str(), nullptr, 16);
underfootLinkBodyStruct.lore_group = (uint32)strtol(underfootLinkBody.substr(32, 4).c_str(), nullptr, 16);
underfootLinkBodyStruct.evolve_max = (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.is_evolving = underfootLinkBodyStruct.is_evolving;
serverLinkBodyStruct.lore_group = underfootLinkBodyStruct.lore_group;
serverLinkBodyStruct.evolve_max = underfootLinkBodyStruct.evolve_max;
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" "%05X" "%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.is_evolving,
serverLinkBodyStruct.lore_group,
serverLinkBodyStruct.evolve_max,
serverLinkBodyStruct.ornament_icon,
serverLinkBodyStruct.hash
);
if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }
return true;
} }
} }
// end namespace Underfoot // end namespace Underfoot

View File

@ -4530,23 +4530,6 @@ struct MercenaryAssign_Struct {
/*0012*/ /*0012*/
}; };
// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X"
struct TextLinkBody_Struct
{
uint8 unknown_1;
uint32 item_id;
uint32 augment_1;
uint32 augment_2;
uint32 augment_3;
uint32 augment_4;
uint32 augment_5;
uint8 is_evolving;
uint32 lore_group;
uint8 evolve_max;
uint32 ornament_icon;
int hash;
};
}; //end namespace structs }; //end namespace structs
}; //end namespace Underfoot }; //end namespace Underfoot

View File

@ -8317,27 +8317,13 @@ void Client::TextLink::generate_body()
/* /*
Current server mask: EQClientRoF2 Current server mask: EQClientRoF2
RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X" (56) RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X" (56)
RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (55) 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) 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) 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" (45)
*/ */
// could use a ##_cast<TextLinkBody_Struct*>(&this) with a memset to '0' since these properties are inherited memset(&m_LinkBodyStruct, 0, sizeof(TextLinkBody_Struct));
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 */
is_evolving = NOT_USED; /* field 9 */
lore_group = NOT_USED; /* field 10 */
evolve_max = NOT_USED; /* field 11 */
ornament_icon = NOT_USED; /* field 12 */
hash = NOT_USED; /* field 13 */
const Item_Struct* item_data = nullptr; const Item_Struct* item_data = nullptr;
@ -8346,33 +8332,40 @@ void Client::TextLink::generate_body()
break; break;
case linkItemData: case linkItemData:
if (m_ItemData == nullptr) { break; } if (m_ItemData == nullptr) { break; }
item_id = m_ItemData->ID; m_LinkBodyStruct.item_id = m_ItemData->ID;
m_LinkBodyStruct.evolve_group = m_ItemData->LoreGroup; // this probably won't work for all items
//m_LinkBodyStruct.evolve_level = m_ItemData->EvolvingLevel;
// TODO: add hash call // TODO: add hash call
break; break;
case linkLootItem: case linkLootItem:
if (m_LootData == nullptr) { break; } if (m_LootData == nullptr) { break; }
item_data = database.GetItem(m_LootData->item_id); item_data = database.GetItem(m_LootData->item_id);
if (item_data == nullptr) { break; } if (item_data == nullptr) { break; }
item_id = item_data->ID; m_LinkBodyStruct.item_id = item_data->ID;
augment_1 = m_LootData->aug_1; m_LinkBodyStruct.augment_1 = m_LootData->aug_1;
augment_2 = m_LootData->aug_2; m_LinkBodyStruct.augment_2 = m_LootData->aug_2;
augment_3 = m_LootData->aug_3; m_LinkBodyStruct.augment_3 = m_LootData->aug_3;
augment_4 = m_LootData->aug_4; m_LinkBodyStruct.augment_4 = m_LootData->aug_4;
augment_5 = m_LootData->aug_5; m_LinkBodyStruct.augment_5 = m_LootData->aug_5;
augment_6 = m_LootData->aug_6; m_LinkBodyStruct.augment_6 = m_LootData->aug_6;
m_LinkBodyStruct.evolve_group = item_data->LoreGroup; // see note above
//m_LinkBodyStruct.evolve_level = item_data->EvolvingLevel;
// TODO: add hash call // TODO: add hash call
break; break;
case linkItemInst: case linkItemInst:
if (m_ItemInst == nullptr) { break; } if (m_ItemInst == nullptr) { break; }
if (m_ItemInst->GetItem() == nullptr) { break; } if (m_ItemInst->GetItem() == nullptr) { break; }
item_id = m_ItemInst->GetItem()->ID; m_LinkBodyStruct.item_id = m_ItemInst->GetItem()->ID;
augment_1 = m_ItemInst->GetAugmentItemID(0); m_LinkBodyStruct.augment_1 = m_ItemInst->GetAugmentItemID(0);
augment_2 = m_ItemInst->GetAugmentItemID(1); m_LinkBodyStruct.augment_2 = m_ItemInst->GetAugmentItemID(1);
augment_3 = m_ItemInst->GetAugmentItemID(2); m_LinkBodyStruct.augment_3 = m_ItemInst->GetAugmentItemID(2);
augment_4 = m_ItemInst->GetAugmentItemID(3); m_LinkBodyStruct.augment_4 = m_ItemInst->GetAugmentItemID(3);
augment_5 = m_ItemInst->GetAugmentItemID(4); m_LinkBodyStruct.augment_5 = m_ItemInst->GetAugmentItemID(4);
augment_6 = m_ItemInst->GetAugmentItemID(5); m_LinkBodyStruct.augment_6 = m_ItemInst->GetAugmentItemID(5);
ornament_icon = m_ItemInst->GetOrnamentationIcon(); m_LinkBodyStruct.is_evolving = (m_ItemInst->IsEvolving() ? 1 : 0);
m_LinkBodyStruct.evolve_group = m_ItemInst->GetItem()->LoreGroup; // see note above
m_LinkBodyStruct.evolve_level = m_ItemInst->GetEvolveLvl();
m_LinkBodyStruct.ornament_icon = m_ItemInst->GetOrnamentationIcon();
// TODO: add hash call // TODO: add hash call
break; break;
default: default:
@ -8380,29 +8373,28 @@ void Client::TextLink::generate_body()
} }
if (m_ProxyItemID != NOT_USED) { if (m_ProxyItemID != NOT_USED) {
item_id = m_ProxyItemID; m_LinkBodyStruct.item_id = m_ProxyItemID;
} }
if (m_TaskUse) { if (m_TaskUse) {
//hash = 0x0000000014505DC2; m_LinkBodyStruct.hash = 0x14505DC2;
hash = 0x14505DC2;
} }
m_LinkBody = StringFormat( m_LinkBody = StringFormat(
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X", "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
unknown_1, (0x0F & m_LinkBodyStruct.unknown_1),
item_id, (0x000FFFFF & m_LinkBodyStruct.item_id),
augment_1, (0x000FFFFF & m_LinkBodyStruct.augment_1),
augment_2, (0x000FFFFF & m_LinkBodyStruct.augment_2),
augment_3, (0x000FFFFF & m_LinkBodyStruct.augment_3),
augment_4, (0x000FFFFF & m_LinkBodyStruct.augment_4),
augment_5, (0x000FFFFF & m_LinkBodyStruct.augment_5),
augment_6, (0x000FFFFF & m_LinkBodyStruct.augment_6),
is_evolving, (0x0F & m_LinkBodyStruct.is_evolving),
lore_group, (0x0000FFFF & m_LinkBodyStruct.evolve_group),
evolve_max, (0xFF & m_LinkBodyStruct.evolve_level),
ornament_icon, (0x000FFFFF & m_LinkBodyStruct.ornament_icon),
hash (0xFFFFFFFF & m_LinkBodyStruct.hash)
); );
} }
@ -8454,8 +8446,8 @@ bool Client::TextLink::DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruc
textLinkBodyStruct.augment_5 = (uint32)strtol(textLinkBody.substr(26, 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.augment_6 = (uint32)strtol(textLinkBody.substr(31, 5).c_str(), nullptr, 16);
textLinkBodyStruct.is_evolving = (uint8)strtol(textLinkBody.substr(36, 1).c_str(), nullptr, 16); textLinkBodyStruct.is_evolving = (uint8)strtol(textLinkBody.substr(36, 1).c_str(), nullptr, 16);
textLinkBodyStruct.lore_group = (uint32)strtol(textLinkBody.substr(37, 5).c_str(), nullptr, 16); textLinkBodyStruct.evolve_group = (uint32)strtol(textLinkBody.substr(37, 4).c_str(), nullptr, 16);
textLinkBodyStruct.evolve_max = (uint8)strtol(textLinkBody.substr(42, 1).c_str(), nullptr, 16); textLinkBodyStruct.evolve_level = (uint8)strtol(textLinkBody.substr(41, 2).c_str(), nullptr, 16);
textLinkBodyStruct.ornament_icon = (uint32)strtol(textLinkBody.substr(43, 5).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); textLinkBodyStruct.hash = (int)strtol(textLinkBody.substr(48, 8).c_str(), nullptr, 16);
@ -8465,20 +8457,20 @@ bool Client::TextLink::DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruc
bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLinkBody_Struct& textLinkBodyStruct) bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLinkBody_Struct& textLinkBodyStruct)
{ {
textLinkBody = StringFormat( textLinkBody = StringFormat(
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X", "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
textLinkBodyStruct.unknown_1, (0x0F & textLinkBodyStruct.unknown_1),
textLinkBodyStruct.item_id, (0x000FFFFF & textLinkBodyStruct.item_id),
textLinkBodyStruct.augment_1, (0x000FFFFF & textLinkBodyStruct.augment_1),
textLinkBodyStruct.augment_2, (0x000FFFFF & textLinkBodyStruct.augment_2),
textLinkBodyStruct.augment_3, (0x000FFFFF & textLinkBodyStruct.augment_3),
textLinkBodyStruct.augment_4, (0x000FFFFF & textLinkBodyStruct.augment_4),
textLinkBodyStruct.augment_5, (0x000FFFFF & textLinkBodyStruct.augment_5),
textLinkBodyStruct.augment_6, (0x000FFFFF & textLinkBodyStruct.augment_6),
textLinkBodyStruct.is_evolving, (0x0F & textLinkBodyStruct.is_evolving),
textLinkBodyStruct.lore_group, (0x0000FFFF & textLinkBodyStruct.evolve_group),
textLinkBodyStruct.evolve_max, (0xFF & textLinkBodyStruct.evolve_level),
textLinkBodyStruct.ornament_icon, (0x000FFFFF & textLinkBodyStruct.ornament_icon),
textLinkBodyStruct.hash (0xFFFFFFFF & textLinkBodyStruct.hash)
); );
if (textLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } if (textLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; }

View File

@ -822,7 +822,7 @@ public:
// //
// class Client::TextLink // class Client::TextLink
// //
class TextLink : TextLinkBody_Struct { class TextLink {
public: public:
enum LinkType { linkBlank = 0, linkItemData, linkLootItem, linkItemInst }; enum LinkType { linkBlank = 0, linkItemData, linkLootItem, linkItemInst };
@ -859,6 +859,7 @@ public:
uint32 m_ProxyItemID; uint32 m_ProxyItemID;
const char* m_ProxyText; const char* m_ProxyText;
bool m_TaskUse; bool m_TaskUse;
TextLinkBody_Struct m_LinkBodyStruct;
std::string m_Link; std::string m_Link;
std::string m_LinkBody; std::string m_LinkBody;
std::string m_LinkText; std::string m_LinkText;