From 179f47dbe30eaad3ec746c780e2bc2d21b034397 Mon Sep 17 00:00:00 2001 From: Trevius Date: Sun, 4 Jan 2015 20:42:45 -0600 Subject: [PATCH 01/10] RoF+ - Added the "Your race, class, or deity cannot use this item." message since it no longer exists in the eqstr_us.txt file. --- zone/spells.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index ce5d9df8d..2b5536bb3 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -274,7 +274,15 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, database.SetHackerFlag(CastToClient()->AccountName(), CastToClient()->GetCleanName(), "Clicking race/class restricted item with an invalid class"); } else { - Message_StringID(13, CANNOT_USE_ITEM); + if (CastToClient()->GetClientVersion() >= EQClientRoF) + { + // Line 181 in eqstr_us.txt was changed in RoF+ + Message(15, "Your race, class, or deity cannot use this item."); + } + else + { + Message_StringID(13, CANNOT_USE_ITEM); + } } return(false); } From 7557cfd845b8436a7e7f14313af59355655953c0 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 5 Jan 2015 13:44:16 -0500 Subject: [PATCH 02/10] Added text link translators for all supported clients - currently, only OP_ChannelMessage and OP_SpecialMesg are translated. --- changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.txt b/changelog.txt index 5aa90cfc9..c9a9a2c3a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/05/2015 == +Uleat: Fixed (added translators for) item/text links. Only 'OP_ChannelMessage' and 'OP_SpecialMesg' are currently handled..more text channels will be added as the need arises. + == 01/03/2015 == Trevius: (RoF2) /shield (shielding) and /key (key ring) are both now functional after opcode updates. From 4b133c808c3dfdf619a83420b98eb55e8fa41552 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 5 Jan 2015 13:50:03 -0500 Subject: [PATCH 03/10] It helps if you actually push more than the changelog message... --- common/eq_dictionary.h | 2 + common/eq_packet_structs.h | 17 + common/patches/rof.cpp | 430 ++++++++++++++++++++++++- common/patches/rof2.cpp | 433 ++++++++++++++++++++++++- common/patches/rof2_constants.h | 2 + common/patches/rof2_ops.h | 1 + common/patches/rof2_structs.h | 19 ++ common/patches/rof_constants.h | 2 + common/patches/rof_ops.h | 1 + common/patches/rof_structs.h | 18 ++ common/patches/sod.cpp | 455 +++++++++++++++++++++++++++ common/patches/sod_constants.h | 2 + common/patches/sod_ops.h | 3 + common/patches/sod_structs.h | 16 + common/patches/sof.cpp | 455 +++++++++++++++++++++++++++ common/patches/sof_constants.h | 2 + common/patches/sof_ops.h | 3 + common/patches/sof_structs.h | 26 +- common/patches/titanium.cpp | 453 ++++++++++++++++++++++++++ common/patches/titanium_constants.h | 2 + common/patches/titanium_ops.h | 3 + common/patches/titanium_structs.h | 28 +- common/patches/underfoot.cpp | 426 ++++++++++++++++++++++++- common/patches/underfoot_constants.h | 2 + common/patches/underfoot_ops.h | 1 + common/patches/underfoot_structs.h | 17 + zone/bot.cpp | 1 - zone/client.cpp | 286 ++++++++--------- zone/client.h | 16 +- zone/command.cpp | 2 - zone/corpse.cpp | 17 +- zone/npc.cpp | 1 - zone/questmgr.cpp | 5 - zone/tasks.cpp | 1 - 34 files changed, 2936 insertions(+), 212 deletions(-) diff --git a/common/eq_dictionary.h b/common/eq_dictionary.h index 43511072f..3438f133b 100644 --- a/common/eq_dictionary.h +++ b/common/eq_dictionary.h @@ -149,6 +149,8 @@ public: static const uint32 BANDOLIER_SIZE = Titanium::consts::BANDOLIER_SIZE; // size = number of equipment slots in bandolier instance static const uint32 POTION_BELT_SIZE = Titanium::consts::POTION_BELT_SIZE; + static const size_t TEXT_LINK_BODY_LENGTH = 56; + // legacy-related functions //static int ServerToPerlSlot(int slot); // encode //static int PerlToServerSlot(int slot); // decode diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 07daa97fd..32f7360fb 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -5269,6 +5269,23 @@ struct ClientMarqueeMessage_Struct { typedef std::list ItemList; +struct TextLinkBody_Struct { + uint8 unknown_1; /* '%1X' - Server field 1 */ + uint32 item_id; /* '%05X' - Server field 2 */ + uint32 augment_1; /* '%05X' - Server field 3 */ + uint32 augment_2; /* '%05X' - Server field 4 */ + uint32 augment_3; /* '%05X' - Server field 5 */ + uint32 augment_4; /* '%05X' - Server field 6 */ + uint32 augment_5; /* '%05X' - Server field 7 */ + uint32 augment_6; /* '%05X' - Server field 8 */ + uint8 unknown_2; /* '%1X' - Server field 9 */ + uint8 unknown_3; /* '%1X' - Server field 10 */ + uint32 unknown_4; /* '%04X' - Server field 11 */ + uint8 unknown_5; /* '%1X' - Server field 12 */ + uint32 ornament_icon; /* '%05X' - Server field 13 */ + int hash; /* '%08X' - Server field 14 */ +}; + // Restore structure packing to default #pragma pack() diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 36d487545..d236d2b34 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -33,6 +33,18 @@ namespace RoF static inline uint32 RoFToServerMainInvSlot(structs::MainInvItemSlotStruct RoFSlot); static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse); + // server to client text link converters + static inline void ServerToRoFTextLinks(std::string& rofTextLink, const std::string& serverTextLink); + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); + static inline void ServerToRoFTextLinkBodyStruct(structs::TextLinkBody_Struct& rofLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); + static inline bool GenerateRoFTextLinkBody(std::string& rofLinkBody, const structs::TextLinkBody_Struct& rofLinkBodyStruct); + + // client to server text link converters + static inline void RoFToServerTextLinks(std::string& serverTextLink, const std::string& rofTextLink); + static inline bool DegenerateRoFTextLinkBody(structs::TextLinkBody_Struct& rofLinkBodyStruct, const std::string& rofLinkBody); + static inline void RoFToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& rofLinkBodyStruct); + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -488,7 +500,13 @@ namespace RoF unsigned char *__emu_buffer = in->pBuffer; - in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; + std::string old_message = emu->message; + std::string new_message; + ServerToRoFTextLinks(new_message, old_message); + + //in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; + in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39; + in->pBuffer = new unsigned char[in->size]; char *OutBuffer = (char *)in->pBuffer; @@ -501,7 +519,7 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->skill_in_language); - VARSTRUCT_ENCODE_STRING(OutBuffer, emu->message); + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown @@ -3096,6 +3114,44 @@ namespace RoF FINISH_ENCODE(); } + ENCODE(OP_SpecialMesg) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string new_message; + ServerToRoFTextLinks(new_message, old_message); + + //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; + in->size = 25 + strlen(emu->sayer) + new_message.length(); + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id); + + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_Stun) { ENCODE_LENGTH_EXACT(Stun_Struct); @@ -4041,7 +4097,13 @@ namespace RoF uint32 Skill = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - __packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; + std::string old_message = InBuffer; + std::string new_message; + RoFToServerTextLinks(new_message, old_message); + + //__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; + __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; + __packet->pBuffer = new unsigned char[__packet->size]; ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer; @@ -4050,7 +4112,7 @@ namespace RoF emu->language = Language; emu->chan_num = Channel; emu->skill_in_language = Skill; - strcpy(emu->message, InBuffer); + strcpy(emu->message, new_message.c_str()); delete[] __eq_buffer; } @@ -5627,5 +5689,365 @@ namespace RoF { return (RoFCorpse - 1); } + + static inline void ServerToRoFTextLinks(std::string& rofTextLink, const std::string& serverTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(Server->RoF): old message '%s'", serverTextLink.c_str()); + + if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF): link size equal, no conversion necessary"); + rofTextLink = serverTextLink; + return; + } + + if (serverTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF): delimiter not found, no conversion necessary"); + rofTextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->RoF): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + } + + structs::TextLinkBody_Struct new_body_data; + ServerToRoFTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateRoFTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->RoF): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF): conversion error"); + rofTextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + rofTextLink.push_back(delimiter); + rofTextLink.append(segments[iter].c_str()); + rofTextLink.push_back(delimiter); + } + else { + rofTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->RoF): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->RoF): new message '%s'", rofTextLink.c_str()); +#else + if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { + rofTextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + structs::TextLinkBody_Struct new_body_data; + ServerToRoFTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateRoFTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF): conversion error"); + rofTextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + rofTextLink.push_back(delimiter); + rofTextLink.append(segments[iter].c_str()); + rofTextLink.push_back(delimiter); + } + else { + rofTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) + { + memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + + serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void ServerToRoFTextLinkBodyStruct(structs::TextLinkBody_Struct& rofLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct) + { + rofLinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1; + rofLinkBodyStruct.item_id = serverLinkBodyStruct.item_id; + rofLinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1; + rofLinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2; + rofLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3; + rofLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; + rofLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; + rofLinkBodyStruct.augment_6 = serverLinkBodyStruct.augment_6; + rofLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3; + rofLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4; + rofLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5; + rofLinkBodyStruct.ornament_icon = serverLinkBodyStruct.ornament_icon; + rofLinkBodyStruct.hash = serverLinkBodyStruct.hash; + } + + static inline bool GenerateRoFTextLinkBody(std::string& rofLinkBody, const structs::TextLinkBody_Struct& rofLinkBodyStruct) + { + rofLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X", + rofLinkBodyStruct.unknown_1, + rofLinkBodyStruct.item_id, + rofLinkBodyStruct.augment_1, + rofLinkBodyStruct.augment_2, + rofLinkBodyStruct.augment_3, + rofLinkBodyStruct.augment_4, + rofLinkBodyStruct.augment_5, + rofLinkBodyStruct.augment_6, + rofLinkBodyStruct.unknown_2, + rofLinkBodyStruct.unknown_3, + rofLinkBodyStruct.unknown_4, + rofLinkBodyStruct.ornament_icon, + rofLinkBodyStruct.hash + ); + + if (rofLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } + + static inline void RoFToServerTextLinks(std::string& serverTextLink, const std::string& rofTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(RoF->Server): old message '%s'", rofTextLink.c_str()); + + if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(RoF->Server): link size equal, no conversion necessary"); + serverTextLink = rofTextLink; + return; + } + + if (rofTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(RoF->Server): delimiter not found, no conversion necessary"); + serverTextLink = rofTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(rofTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateRoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(RoF->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(RoF->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + } + + TextLinkBody_Struct new_body_data; + RoFToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(RoF->Server): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(RoF->Server): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(RoF->Server): conversion error"); + serverTextLink = rofTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(RoF->Server): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(RoF->Server): new message '%s'", serverTextLink.c_str()); +#else + if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find(delimiter) == std::string::npos)) { + serverTextLink = rofTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(rofTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateRoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + TextLinkBody_Struct new_body_data; + RoFToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(RoF->Server): conversion error"); + serverTextLink = rofTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateRoFTextLinkBody(structs::TextLinkBody_Struct& rofLinkBodyStruct, const std::string& rofLinkBody) + { + // RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" + memset(&rofLinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct)); + if (rofLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + + rofLinkBodyStruct.unknown_1 = (uint8)strtol(rofLinkBody.substr(0, 1).c_str(), nullptr, 16); + rofLinkBodyStruct.item_id = (uint32)strtol(rofLinkBody.substr(1, 5).c_str(), nullptr, 16); + rofLinkBodyStruct.augment_1 = (uint32)strtol(rofLinkBody.substr(6, 5).c_str(), nullptr, 16); + rofLinkBodyStruct.augment_2 = (uint32)strtol(rofLinkBody.substr(11, 5).c_str(), nullptr, 16); + rofLinkBodyStruct.augment_3 = (uint32)strtol(rofLinkBody.substr(16, 5).c_str(), nullptr, 16); + rofLinkBodyStruct.augment_4 = (uint32)strtol(rofLinkBody.substr(21, 5).c_str(), nullptr, 16); + rofLinkBodyStruct.augment_5 = (uint32)strtol(rofLinkBody.substr(26, 5).c_str(), nullptr, 16); + rofLinkBodyStruct.augment_6 = (uint32)strtol(rofLinkBody.substr(31, 5).c_str(), nullptr, 16); + rofLinkBodyStruct.unknown_2 = (uint8)strtol(rofLinkBody.substr(36, 1).c_str(), nullptr, 16); + rofLinkBodyStruct.unknown_3 = (uint32)strtol(rofLinkBody.substr(37, 4).c_str(), nullptr, 16); + rofLinkBodyStruct.unknown_4 = (uint8)strtol(rofLinkBody.substr(41, 1).c_str(), nullptr, 16); + rofLinkBodyStruct.ornament_icon = (uint32)strtol(rofLinkBody.substr(42, 5).c_str(), nullptr, 16); + rofLinkBodyStruct.hash = (int)strtol(rofLinkBody.substr(47, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void RoFToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& rofLinkBodyStruct) + { + serverLinkBodyStruct.unknown_1 = rofLinkBodyStruct.unknown_1; + serverLinkBodyStruct.item_id = rofLinkBodyStruct.item_id; + serverLinkBodyStruct.augment_1 = rofLinkBodyStruct.augment_1; + serverLinkBodyStruct.augment_2 = rofLinkBodyStruct.augment_2; + serverLinkBodyStruct.augment_3 = rofLinkBodyStruct.augment_3; + serverLinkBodyStruct.augment_4 = rofLinkBodyStruct.augment_4; + serverLinkBodyStruct.augment_5 = rofLinkBodyStruct.augment_5; + serverLinkBodyStruct.augment_6 = rofLinkBodyStruct.augment_6; + serverLinkBodyStruct.unknown_2 = NOT_USED; + serverLinkBodyStruct.unknown_3 = rofLinkBodyStruct.unknown_2; + serverLinkBodyStruct.unknown_4 = rofLinkBodyStruct.unknown_3; + serverLinkBodyStruct.unknown_5 = rofLinkBodyStruct.unknown_4; + serverLinkBodyStruct.ornament_icon = rofLinkBodyStruct.ornament_icon; + serverLinkBodyStruct.hash = rofLinkBodyStruct.hash; + } + + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) + { + serverLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + serverLinkBodyStruct.unknown_1, + serverLinkBodyStruct.item_id, + serverLinkBodyStruct.augment_1, + serverLinkBodyStruct.augment_2, + serverLinkBodyStruct.augment_3, + serverLinkBodyStruct.augment_4, + serverLinkBodyStruct.augment_5, + serverLinkBodyStruct.augment_6, + serverLinkBodyStruct.unknown_2, + serverLinkBodyStruct.unknown_3, + serverLinkBodyStruct.unknown_4, + serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.ornament_icon, + serverLinkBodyStruct.hash + ); + + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } } // end namespace RoF diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 02ac289a9..6356a6f7d 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -33,6 +33,18 @@ namespace RoF2 static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct RoF2Slot); static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse); + // server to client text link converters + static inline void ServerToRoF2TextLinks(std::string& rof2TextLink, const std::string& serverTextLink); + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); + static inline void ServerToRoF2TextLinkBodyStruct(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); + static inline bool GenerateRoF2TextLinkBody(std::string& rof2LinkBody, const structs::TextLinkBody_Struct& rof2LinkBodyStruct); + + // client to server text link converters + static inline void RoF2ToServerTextLinks(std::string& serverTextLink, const std::string& rof2TextLink); + static inline bool DegenerateRoF2TextLinkBody(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const std::string& rof2LinkBody); + static inline void RoF2ToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& rof2LinkBodyStruct); + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -554,7 +566,13 @@ namespace RoF2 unsigned char *__emu_buffer = in->pBuffer; - in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; + std::string old_message = emu->message; + std::string new_message; + ServerToRoF2TextLinks(new_message, old_message); + + //in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; + in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39; + in->pBuffer = new unsigned char[in->size]; char *OutBuffer = (char *)in->pBuffer; @@ -567,7 +585,7 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->skill_in_language); - VARSTRUCT_ENCODE_STRING(OutBuffer, emu->message); + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown @@ -3162,6 +3180,44 @@ namespace RoF2 FINISH_ENCODE(); } + ENCODE(OP_SpecialMesg) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string new_message; + ServerToRoF2TextLinks(new_message, old_message); + + //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; + in->size = 25 + strlen(emu->sayer) + new_message.length(); + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id); + + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_Stun) { ENCODE_LENGTH_EXACT(Stun_Struct); @@ -4113,7 +4169,13 @@ namespace RoF2 uint32 Skill = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - __packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; + std::string old_message = InBuffer; + std::string new_message; + RoF2ToServerTextLinks(new_message, old_message); + + //__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; + __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; + __packet->pBuffer = new unsigned char[__packet->size]; ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer; @@ -4122,7 +4184,7 @@ namespace RoF2 emu->language = Language; emu->chan_num = Channel; emu->skill_in_language = Skill; - strcpy(emu->message, InBuffer); + strcpy(emu->message, new_message.c_str()); delete[] __eq_buffer; } @@ -5722,5 +5784,368 @@ namespace RoF2 { return (RoF2Corpse + EmuConstants::CORPSE_BEGIN - 1); } + + static inline void ServerToRoF2TextLinks(std::string& rof2TextLink, const std::string& serverTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): old message '%s'", serverTextLink.c_str()); + + if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): link size equal, no conversion necessary"); + rof2TextLink = serverTextLink; + return; + } + + if (serverTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): delimiter not found, no conversion necessary"); + rof2TextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + } + + structs::TextLinkBody_Struct new_body_data; + ServerToRoF2TextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateRoF2TextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): conversion error"); + rof2TextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + rof2TextLink.push_back(delimiter); + rof2TextLink.append(segments[iter].c_str()); + rof2TextLink.push_back(delimiter); + } + else { + rof2TextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): new message '%s'", rof2TextLink.c_str()); +#else + if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { + rof2TextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + structs::TextLinkBody_Struct new_body_data; + ServerToRoF2TextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateRoF2TextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->RoF2): conversion error"); + rof2TextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + rof2TextLink.push_back(delimiter); + rof2TextLink.append(segments[iter].c_str()); + rof2TextLink.push_back(delimiter); + } + else { + rof2TextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) + { + memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + + serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void ServerToRoF2TextLinkBodyStruct(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct) + { + rof2LinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1; + rof2LinkBodyStruct.item_id = serverLinkBodyStruct.item_id; + rof2LinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1; + rof2LinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2; + rof2LinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3; + rof2LinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; + rof2LinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; + rof2LinkBodyStruct.augment_6 = serverLinkBodyStruct.augment_6; + rof2LinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_2; + rof2LinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_3; + rof2LinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_4; + rof2LinkBodyStruct.unknown_5 = serverLinkBodyStruct.unknown_5; + rof2LinkBodyStruct.ornament_icon = serverLinkBodyStruct.ornament_icon; + rof2LinkBodyStruct.hash = serverLinkBodyStruct.hash; + } + + static inline bool GenerateRoF2TextLinkBody(std::string& rof2LinkBody, const structs::TextLinkBody_Struct& rof2LinkBodyStruct) + { + rof2LinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X", + rof2LinkBodyStruct.unknown_1, + rof2LinkBodyStruct.item_id, + rof2LinkBodyStruct.augment_1, + rof2LinkBodyStruct.augment_2, + rof2LinkBodyStruct.augment_3, + rof2LinkBodyStruct.augment_4, + rof2LinkBodyStruct.augment_5, + rof2LinkBodyStruct.augment_6, + rof2LinkBodyStruct.unknown_2, + rof2LinkBodyStruct.unknown_3, + rof2LinkBodyStruct.unknown_4, + rof2LinkBodyStruct.unknown_5, + rof2LinkBodyStruct.ornament_icon, + rof2LinkBodyStruct.hash + ); + + if (rof2LinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } + + static inline void RoF2ToServerTextLinks(std::string& serverTextLink, const std::string& rof2TextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): old message '%s'", rof2TextLink.c_str()); + + if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): link size equal, no conversion necessary"); + serverTextLink = rof2TextLink; + return; + } + + if (rof2TextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): delimiter not found, no conversion necessary"); + serverTextLink = rof2TextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(rof2TextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateRoF2TextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + } + + TextLinkBody_Struct new_body_data; + RoF2ToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): conversion error"); + serverTextLink = rof2TextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): new message '%s'", serverTextLink.c_str()); +#else + if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find(delimiter) == std::string::npos)) { + serverTextLink = rof2TextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(rof2TextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateRoF2TextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + TextLinkBody_Struct new_body_data; + RoF2ToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(RoF2->Server): conversion error"); + serverTextLink = rof2TextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateRoF2TextLinkBody(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const std::string& rof2LinkBody) + { + // RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X" + memset(&rof2LinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct)); + if (rof2LinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + + rof2LinkBodyStruct.unknown_1 = (uint8)strtol(rof2LinkBody.substr(0, 1).c_str(), nullptr, 16); + rof2LinkBodyStruct.item_id = (uint32)strtol(rof2LinkBody.substr(1, 5).c_str(), nullptr, 16); + rof2LinkBodyStruct.augment_1 = (uint32)strtol(rof2LinkBody.substr(6, 5).c_str(), nullptr, 16); + rof2LinkBodyStruct.augment_2 = (uint32)strtol(rof2LinkBody.substr(11, 5).c_str(), nullptr, 16); + rof2LinkBodyStruct.augment_3 = (uint32)strtol(rof2LinkBody.substr(16, 5).c_str(), nullptr, 16); + rof2LinkBodyStruct.augment_4 = (uint32)strtol(rof2LinkBody.substr(21, 5).c_str(), nullptr, 16); + rof2LinkBodyStruct.augment_5 = (uint32)strtol(rof2LinkBody.substr(26, 5).c_str(), nullptr, 16); + rof2LinkBodyStruct.augment_6 = (uint32)strtol(rof2LinkBody.substr(31, 5).c_str(), nullptr, 16); + rof2LinkBodyStruct.unknown_2 = (uint8)strtol(rof2LinkBody.substr(36, 1).c_str(), nullptr, 16); + rof2LinkBodyStruct.unknown_3 = (uint32)strtol(rof2LinkBody.substr(37, 4).c_str(), nullptr, 16); + rof2LinkBodyStruct.unknown_4 = (uint8)strtol(rof2LinkBody.substr(41, 1).c_str(), nullptr, 16); + rof2LinkBodyStruct.unknown_5 = (uint8)strtol(rof2LinkBody.substr(42, 1).c_str(), nullptr, 16); + rof2LinkBodyStruct.ornament_icon = (uint32)strtol(rof2LinkBody.substr(43, 5).c_str(), nullptr, 16); + rof2LinkBodyStruct.hash = (int)strtol(rof2LinkBody.substr(48, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void RoF2ToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& rof2LinkBodyStruct) + { + serverLinkBodyStruct.unknown_1 = rof2LinkBodyStruct.unknown_1; + serverLinkBodyStruct.item_id = rof2LinkBodyStruct.item_id; + serverLinkBodyStruct.augment_1 = rof2LinkBodyStruct.augment_1; + serverLinkBodyStruct.augment_2 = rof2LinkBodyStruct.augment_2; + serverLinkBodyStruct.augment_3 = rof2LinkBodyStruct.augment_3; + serverLinkBodyStruct.augment_4 = rof2LinkBodyStruct.augment_4; + serverLinkBodyStruct.augment_5 = rof2LinkBodyStruct.augment_5; + serverLinkBodyStruct.augment_6 = rof2LinkBodyStruct.augment_6; + serverLinkBodyStruct.unknown_2 = rof2LinkBodyStruct.unknown_2; + serverLinkBodyStruct.unknown_3 = rof2LinkBodyStruct.unknown_3; + serverLinkBodyStruct.unknown_4 = rof2LinkBodyStruct.unknown_4; + serverLinkBodyStruct.unknown_5 = rof2LinkBodyStruct.unknown_5; + serverLinkBodyStruct.ornament_icon = rof2LinkBodyStruct.ornament_icon; + serverLinkBodyStruct.hash = rof2LinkBodyStruct.hash; + } + + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) + { + serverLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + serverLinkBodyStruct.unknown_1, + serverLinkBodyStruct.item_id, + serverLinkBodyStruct.augment_1, + serverLinkBodyStruct.augment_2, + serverLinkBodyStruct.augment_3, + serverLinkBodyStruct.augment_4, + serverLinkBodyStruct.augment_5, + serverLinkBodyStruct.augment_6, + serverLinkBodyStruct.unknown_2, + serverLinkBodyStruct.unknown_3, + serverLinkBodyStruct.unknown_4, + serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.ornament_icon, + serverLinkBodyStruct.hash + ); + + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } } // end namespace RoF2 diff --git a/common/patches/rof2_constants.h b/common/patches/rof2_constants.h index 596ffa7e7..b4cbb15e0 100644 --- a/common/patches/rof2_constants.h +++ b/common/patches/rof2_constants.h @@ -181,6 +181,8 @@ namespace RoF2 { static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance static const uint32 POTION_BELT_SIZE = 5; + + static const size_t TEXT_LINK_BODY_LENGTH = 56; } namespace limits { diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 79614504d..66b86d756 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -95,6 +95,7 @@ E(OP_SkillUpdate) E(OP_SomeItemPacketMaybe) E(OP_SpawnAppearance) E(OP_SpawnDoor) +E(OP_SpecialMesg) E(OP_Stun) E(OP_TargetBuffs) E(OP_TaskDescription) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 9ba71574c..60cf07808 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4872,6 +4872,25 @@ struct MercenaryMerchantResponse_Struct { /*0004*/ }; +// RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X" +struct TextLinkBody_Struct +{ + uint8 unknown_1; /* '%1X' - RoF2 field 1 / Server field 1 */ + uint32 item_id; /* '%05X' - RoF2 field 2 / Server field 2 */ + uint32 augment_1; /* '%05X' - RoF2 field 3 / Server field 3 */ + uint32 augment_2; /* '%05X' - RoF2 field 4 / Server field 4 */ + uint32 augment_3; /* '%05X' - RoF2 field 5 / Server field 5 */ + uint32 augment_4; /* '%05X' - RoF2 field 6 / Server field 6 */ + uint32 augment_5; /* '%05X' - RoF2 field 7 / Server field 7 */ + uint32 augment_6; /* '%05X' - RoF2 field 8 / Server field 8 */ + uint8 unknown_2; /* '%1X' - RoF2 field 9 / Server field 9 */ + uint8 unknown_3; /* '%1X' - RoF2 field 10 / Server field 10 */ + uint32 unknown_4; /* '%04X' - RoF2 field 11 / Server field 11 */ + uint8 unknown_5; /* '%1X' - RoF2 field 12 / Server field 12 */ + uint32 ornament_icon; /* '%05X' - RoF2 field 13 / Server field 13 */ + int hash; /* '%08X' - RoF2 field 14 / Server field 14 */ +}; + }; //end namespace structs }; //end namespace RoF2 diff --git a/common/patches/rof_constants.h b/common/patches/rof_constants.h index 97cb25aa5..233a1b36c 100644 --- a/common/patches/rof_constants.h +++ b/common/patches/rof_constants.h @@ -180,6 +180,8 @@ namespace RoF { static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance static const uint32 POTION_BELT_SIZE = 5; + + static const size_t TEXT_LINK_BODY_LENGTH = 55; } namespace limits { diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 878870a81..ef97dda99 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -84,6 +84,7 @@ E(OP_SkillUpdate) E(OP_SomeItemPacketMaybe) E(OP_SpawnAppearance) E(OP_SpawnDoor) +E(OP_SpecialMesg) E(OP_Stun) E(OP_TargetBuffs) E(OP_TaskDescription) diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index fb2f09615..4aa2c04a2 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4894,6 +4894,24 @@ struct MercenaryMerchantResponse_Struct { /*0004*/ }; +// RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" +struct TextLinkBody_Struct +{ + uint8 unknown_1; /* '%1X' - RoF field 1 / Server field 1 */ + uint32 item_id; /* '%05X' - RoF field 2 / Server field 2 */ + uint32 augment_1; /* '%05X' - RoF field 3 / Server field 3 */ + uint32 augment_2; /* '%05X' - RoF field 4 / Server field 4 */ + uint32 augment_3; /* '%05X' - RoF field 5 / Server field 5 */ + uint32 augment_4; /* '%05X' - RoF field 6 / Server field 6 */ + uint32 augment_5; /* '%05X' - RoF field 7 / Server field 7 */ + uint32 augment_6; /* '%05X' - RoF field 8 / Server field 8 */ + uint8 unknown_2; /* '%1X' - RoF field 9 / Server field 10 */ + uint32 unknown_3; /* '%04X' - RoF field 10 / Server field 11 */ + uint8 unknown_4; /* '%1X' - RoF field 11 / Server field 12 */ + uint32 ornament_icon; /* '%05X' - RoF field 12 / Server field 13 */ + int hash; /* '%08X' - RoF field 13 / Server field 14 */ +}; + }; //end namespace structs }; //end namespace RoF diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 7355526c4..b30bad97d 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -31,6 +31,18 @@ namespace SoD static inline uint32 SoDToServerSlot(uint32 SoDSlot); static inline uint32 SoDToServerCorpseSlot(uint32 SoDCorpse); + // server to client text link converters + static inline void ServerToSoDTextLinks(std::string& sodTextLink, const std::string& serverTextLink); + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); + static inline void ServerToSoDTextLinkBodyStruct(structs::TextLinkBody_Struct& sodLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); + static inline bool GenerateSoDTextLinkBody(std::string& sodLinkBody, const structs::TextLinkBody_Struct& sodLinkBodyStruct); + + // client to server text link converters + static inline void SoDToServerTextLinks(std::string& serverTextLink, const std::string& sodTextLink); + static inline bool DegenerateSoDTextLinkBody(structs::TextLinkBody_Struct& sodLinkBodyStruct, const std::string& sodLinkBody); + static inline void SoDToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& sodLinkBodyStruct); + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -296,6 +308,35 @@ namespace SoD FINISH_ENCODE(); } + ENCODE(OP_ChannelMessage) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + std::string old_message = emu->message; + std::string new_message; + ServerToSoDTextLinks(new_message, old_message); + + in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; + + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + memcpy(OutBuffer, __emu_buffer, sizeof(ChannelMessage_Struct)); + + OutBuffer += sizeof(ChannelMessage_Struct); + + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_CharInventory) { //consume the packet @@ -1963,6 +2004,44 @@ namespace SoD FINISH_ENCODE(); } + ENCODE(OP_SpecialMesg) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string new_message; + ServerToSoDTextLinks(new_message, old_message); + + //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; + in->size = 25 + strlen(emu->sayer) + new_message.length(); + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id); + + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_Stun) { ENCODE_LENGTH_EXACT(Stun_Struct); @@ -2729,6 +2808,25 @@ namespace SoD FINISH_DIRECT_DECODE(); } + DECODE(OP_ChannelMessage) + { + unsigned char *__eq_buffer = __packet->pBuffer; + + std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)]; + std::string new_message; + SoDToServerTextLinks(new_message, old_message); + + __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; + __packet->pBuffer = new unsigned char[__packet->size]; + + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer; + + memcpy(emu, __eq_buffer, sizeof(ChannelMessage_Struct)); + strcpy(emu->message, new_message.c_str()); + + delete[] __eq_buffer; + } + DECODE(OP_CharacterCreate) { DECODE_LENGTH_EXACT(structs::CharCreate_Struct); @@ -3683,5 +3781,362 @@ namespace SoD //uint32 ServerCorpse; return (SoDCorpse - 1); } + + static inline void ServerToSoDTextLinks(std::string& sodTextLink, const std::string& serverTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(Server->SoD): old message '%s'", serverTextLink.c_str()); + + if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(Server->SoD): link size equal, no conversion necessary"); + sodTextLink = serverTextLink; + return; + } + + if (serverTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(Server->SoD): delimiter not found, no conversion necessary"); + sodTextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(Server->SoD): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->SoD): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + } + + structs::TextLinkBody_Struct new_body_data; + ServerToSoDTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateSoDTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(Server->SoD): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->SoD): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->SoD): conversion error"); + sodTextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + sodTextLink.push_back(delimiter); + sodTextLink.append(segments[iter].c_str()); + sodTextLink.push_back(delimiter); + } + else { + sodTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->SoD): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->SoD): new message '%s'", sodTextLink.c_str()); +#else + if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { + sodTextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + structs::TextLinkBody_Struct new_body_data; + ServerToSoDTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateSoDTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->SoD): conversion error"); + sodTextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + sodTextLink.push_back(delimiter); + sodTextLink.append(segments[iter].c_str()); + sodTextLink.push_back(delimiter); + } + else { + sodTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) + { + memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + + serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void ServerToSoDTextLinkBodyStruct(structs::TextLinkBody_Struct& sodLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct) + { + sodLinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1; + sodLinkBodyStruct.item_id = serverLinkBodyStruct.item_id; + sodLinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1; + sodLinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2; + sodLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3; + sodLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; + sodLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; + sodLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3; + sodLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4; + sodLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5; + sodLinkBodyStruct.ornament_icon = serverLinkBodyStruct.ornament_icon; + sodLinkBodyStruct.hash = serverLinkBodyStruct.hash; + } + + static inline bool GenerateSoDTextLinkBody(std::string& sodLinkBody, const structs::TextLinkBody_Struct& sodLinkBodyStruct) + { + sodLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X", + sodLinkBodyStruct.unknown_1, + sodLinkBodyStruct.item_id, + sodLinkBodyStruct.augment_1, + sodLinkBodyStruct.augment_2, + sodLinkBodyStruct.augment_3, + sodLinkBodyStruct.augment_4, + sodLinkBodyStruct.augment_5, + sodLinkBodyStruct.unknown_2, + sodLinkBodyStruct.unknown_3, + sodLinkBodyStruct.unknown_4, + sodLinkBodyStruct.ornament_icon, + sodLinkBodyStruct.hash + ); + + if (sodLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } + + static inline void SoDToServerTextLinks(std::string& serverTextLink, const std::string& sodTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(SoD->Server): old message '%s'", sodTextLink.c_str()); + + if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(SoD->Server): link size equal, no conversion necessary"); + serverTextLink = sodTextLink; + return; + } + + if (sodTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(SoD->Server): delimiter not found, no conversion necessary"); + serverTextLink = sodTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(sodTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateSoDTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(SoD->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(SoD->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + } + + TextLinkBody_Struct new_body_data; + SoDToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(SoD->Server): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(SoD->Server): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(SoD->Server): conversion error"); + serverTextLink = sodTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(SoD->Server): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(SoD->Server): new message '%s'", serverTextLink.c_str()); +#else + if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find(delimiter) == std::string::npos)) { + serverTextLink = sodTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(sodTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateSoDTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + TextLinkBody_Struct new_body_data; + SoDToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(SoD->Server): conversion error"); + serverTextLink = sodTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateSoDTextLinkBody(structs::TextLinkBody_Struct& sodLinkBodyStruct, const std::string& sodLinkBody) + { + // SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" + memset(&sodLinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct)); + if (sodLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + + sodLinkBodyStruct.unknown_1 = (uint8)strtol(sodLinkBody.substr(0, 1).c_str(), nullptr, 16); + sodLinkBodyStruct.item_id = (uint32)strtol(sodLinkBody.substr(1, 5).c_str(), nullptr, 16); + sodLinkBodyStruct.augment_1 = (uint32)strtol(sodLinkBody.substr(6, 5).c_str(), nullptr, 16); + sodLinkBodyStruct.augment_2 = (uint32)strtol(sodLinkBody.substr(11, 5).c_str(), nullptr, 16); + sodLinkBodyStruct.augment_3 = (uint32)strtol(sodLinkBody.substr(16, 5).c_str(), nullptr, 16); + sodLinkBodyStruct.augment_4 = (uint32)strtol(sodLinkBody.substr(21, 5).c_str(), nullptr, 16); + sodLinkBodyStruct.augment_5 = (uint32)strtol(sodLinkBody.substr(26, 5).c_str(), nullptr, 16); + sodLinkBodyStruct.unknown_2 = (uint8)strtol(sodLinkBody.substr(31, 1).c_str(), nullptr, 16); + sodLinkBodyStruct.unknown_3 = (uint32)strtol(sodLinkBody.substr(32, 4).c_str(), nullptr, 16); + sodLinkBodyStruct.unknown_4 = (uint8)strtol(sodLinkBody.substr(36, 1).c_str(), nullptr, 16); + sodLinkBodyStruct.ornament_icon = (uint32)strtol(sodLinkBody.substr(37, 5).c_str(), nullptr, 16); + sodLinkBodyStruct.hash = (int)strtol(sodLinkBody.substr(42, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void SoDToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& sodLinkBodyStruct) + { + serverLinkBodyStruct.unknown_1 = sodLinkBodyStruct.unknown_1; + serverLinkBodyStruct.item_id = sodLinkBodyStruct.item_id; + serverLinkBodyStruct.augment_1 = sodLinkBodyStruct.augment_1; + serverLinkBodyStruct.augment_2 = sodLinkBodyStruct.augment_2; + serverLinkBodyStruct.augment_3 = sodLinkBodyStruct.augment_3; + serverLinkBodyStruct.augment_4 = sodLinkBodyStruct.augment_4; + serverLinkBodyStruct.augment_5 = sodLinkBodyStruct.augment_5; + serverLinkBodyStruct.augment_6 = NOT_USED; + serverLinkBodyStruct.unknown_2 = NOT_USED; + serverLinkBodyStruct.unknown_3 = sodLinkBodyStruct.unknown_2; + serverLinkBodyStruct.unknown_4 = sodLinkBodyStruct.unknown_3; + serverLinkBodyStruct.unknown_5 = sodLinkBodyStruct.unknown_4; + serverLinkBodyStruct.ornament_icon = sodLinkBodyStruct.ornament_icon; + serverLinkBodyStruct.hash = sodLinkBodyStruct.hash; + } + + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) + { + serverLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + serverLinkBodyStruct.unknown_1, + serverLinkBodyStruct.item_id, + serverLinkBodyStruct.augment_1, + serverLinkBodyStruct.augment_2, + serverLinkBodyStruct.augment_3, + serverLinkBodyStruct.augment_4, + serverLinkBodyStruct.augment_5, + serverLinkBodyStruct.augment_6, + serverLinkBodyStruct.unknown_2, + serverLinkBodyStruct.unknown_3, + serverLinkBodyStruct.unknown_4, + serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.ornament_icon, + serverLinkBodyStruct.hash + ); + + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } } // end namespace SoD diff --git a/common/patches/sod_constants.h b/common/patches/sod_constants.h index 8bdf45532..89749fd56 100644 --- a/common/patches/sod_constants.h +++ b/common/patches/sod_constants.h @@ -177,6 +177,8 @@ namespace SoD { static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance static const uint32 POTION_BELT_SIZE = 5; + + static const size_t TEXT_LINK_BODY_LENGTH = 50; } namespace limits { diff --git a/common/patches/sod_ops.h b/common/patches/sod_ops.h index 038b42e08..e3b6c1f41 100644 --- a/common/patches/sod_ops.h +++ b/common/patches/sod_ops.h @@ -8,6 +8,7 @@ E(OP_Barter) E(OP_BazaarSearch) E(OP_Buff) E(OP_CancelTrade) +E(OP_ChannelMessage) E(OP_CharInventory) E(OP_ClientUpdate) E(OP_Consider) @@ -57,6 +58,7 @@ E(OP_ShopPlayerBuy) E(OP_ShopPlayerSell) E(OP_SomeItemPacketMaybe) E(OP_SpawnDoor) +E(OP_SpecialMesg) E(OP_Stun) E(OP_TargetBuffs) E(OP_Track) @@ -81,6 +83,7 @@ D(OP_BazaarSearch) D(OP_Buff) D(OP_Bug) D(OP_CastSpell) +D(OP_ChannelMessage) D(OP_CharacterCreate) D(OP_ClientUpdate) D(OP_Consider) diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 7ec101fd3..3c1acc37d 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -4409,6 +4409,22 @@ struct MercenaryAssign_Struct { /*0012*/ }; +// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" +struct TextLinkBody_Struct +{ + uint8 unknown_1; /* '%1X' - SoD field 1 / Server field 1 */ + uint32 item_id; /* '%05X' - SoD field 2 / Server field 2 */ + uint32 augment_1; /* '%05X' - SoD field 3 / Server field 3 */ + uint32 augment_2; /* '%05X' - SoD field 4 / Server field 4 */ + uint32 augment_3; /* '%05X' - SoD field 5 / Server field 5 */ + uint32 augment_4; /* '%05X' - SoD field 6 / Server field 6 */ + uint32 augment_5; /* '%05X' - SoD field 7 / Server field 7 */ + uint8 unknown_2; /* '%1X' - SoD field 8 / Server field 10 */ + uint32 unknown_3; /* '%04X' - SoD field 9 / Server field 11 */ + uint8 unknown_4; /* '%1X' - SoD field 10 / Server field 12 */ + uint32 ornament_icon; /* '%05X' - SoD field 11 / Server field 13 */ + int hash; /* '%08X' - SoD field 12 / Server field 14 */ +}; }; //end namespace structs }; //end namespace SoD diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index fc46c53cb..cd5a1ef71 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -31,6 +31,18 @@ namespace SoF static inline uint32 SoFToServerSlot(uint32 SoFSlot); static inline uint32 SoFToServerCorpseSlot(uint32 SoFCorpse); + // server to client text link converters + static inline void ServerToSoFTextLinks(std::string& sofTextLink, const std::string& serverTextLink); + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); + static inline void ServerToSoFTextLinkBodyStruct(structs::TextLinkBody_Struct& sofLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); + static inline bool GenerateSoFTextLinkBody(std::string& sofLinkBody, const structs::TextLinkBody_Struct& sofLinkBodyStruct); + + // client to server text link converters + static inline void SoFToServerTextLinks(std::string& serverTextLink, const std::string& sofTextLink); + static inline bool DegenerateSoFTextLinkBody(structs::TextLinkBody_Struct& sofLinkBodyStruct, const std::string& sofLinkBody); + static inline void SoFToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& sofLinkBodyStruct); + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -278,6 +290,35 @@ namespace SoF FINISH_ENCODE(); } + ENCODE(OP_ChannelMessage) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + std::string old_message = emu->message; + std::string new_message; + ServerToSoFTextLinks(new_message, old_message); + + in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; + + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + memcpy(OutBuffer, __emu_buffer, sizeof(ChannelMessage_Struct)); + + OutBuffer += sizeof(ChannelMessage_Struct); + + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_CharInventory) { //consume the packet @@ -1609,6 +1650,44 @@ namespace SoF FINISH_ENCODE(); } + ENCODE(OP_SpecialMesg) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string new_message; + ServerToSoFTextLinks(new_message, old_message); + + //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; + in->size = 25 + strlen(emu->sayer) + new_message.length(); + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id); + + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_Stun) { ENCODE_LENGTH_EXACT(Stun_Struct); @@ -2129,6 +2208,25 @@ namespace SoF FINISH_DIRECT_DECODE(); } + DECODE(OP_ChannelMessage) + { + unsigned char *__eq_buffer = __packet->pBuffer; + + std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)]; + std::string new_message; + SoFToServerTextLinks(new_message, old_message); + + __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; + __packet->pBuffer = new unsigned char[__packet->size]; + + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer; + + memcpy(emu, __eq_buffer, sizeof(ChannelMessage_Struct)); + strcpy(emu->message, new_message.c_str()); + + delete[] __eq_buffer; + } + DECODE(OP_CharacterCreate) { DECODE_LENGTH_EXACT(structs::CharCreate_Struct); @@ -3005,5 +3103,362 @@ namespace SoF //uint32 ServerCorpse; return (SoFCorpse - 1); } + + static inline void ServerToSoFTextLinks(std::string& sofTextLink, const std::string& serverTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(Server->SoF): old message '%s'", serverTextLink.c_str()); + + if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(Server->SoF): link size equal, no conversion necessary"); + sofTextLink = serverTextLink; + return; + } + + if (serverTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(Server->SoF): delimiter not found, no conversion necessary"); + sofTextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(Server->SoF): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->SoF): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + } + + structs::TextLinkBody_Struct new_body_data; + ServerToSoFTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateSoFTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(Server->SoF): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->SoF): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->SoF): conversion error"); + sofTextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + sofTextLink.push_back(delimiter); + sofTextLink.append(segments[iter].c_str()); + sofTextLink.push_back(delimiter); + } + else { + sofTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->SoF): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->SoF): new message '%s'", sofTextLink.c_str()); +#else + if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { + sofTextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + structs::TextLinkBody_Struct new_body_data; + ServerToSoFTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateSoFTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->SoF): conversion error"); + sofTextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + sofTextLink.push_back(delimiter); + sofTextLink.append(segments[iter].c_str()); + sofTextLink.push_back(delimiter); + } + else { + sofTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) + { + memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + + serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void ServerToSoFTextLinkBodyStruct(structs::TextLinkBody_Struct& sofLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct) + { + sofLinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1; + sofLinkBodyStruct.item_id = serverLinkBodyStruct.item_id; + sofLinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1; + sofLinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2; + sofLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3; + sofLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; + sofLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; + sofLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3; + sofLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4; + sofLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5; + sofLinkBodyStruct.ornament_icon = serverLinkBodyStruct.ornament_icon; + sofLinkBodyStruct.hash = serverLinkBodyStruct.hash; + } + + static inline bool GenerateSoFTextLinkBody(std::string& sofLinkBody, const structs::TextLinkBody_Struct& sofLinkBodyStruct) + { + sofLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X", + sofLinkBodyStruct.unknown_1, + sofLinkBodyStruct.item_id, + sofLinkBodyStruct.augment_1, + sofLinkBodyStruct.augment_2, + sofLinkBodyStruct.augment_3, + sofLinkBodyStruct.augment_4, + sofLinkBodyStruct.augment_5, + sofLinkBodyStruct.unknown_2, + sofLinkBodyStruct.unknown_3, + sofLinkBodyStruct.unknown_4, + sofLinkBodyStruct.ornament_icon, + sofLinkBodyStruct.hash + ); + + if (sofLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } + + static inline void SoFToServerTextLinks(std::string& serverTextLink, const std::string& sofTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(SoF->Server): old message '%s'", sofTextLink.c_str()); + + if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(SoF->Server): link size equal, no conversion necessary"); + serverTextLink = sofTextLink; + return; + } + + if (sofTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(SoF->Server): delimiter not found, no conversion necessary"); + serverTextLink = sofTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(sofTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateSoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(SoF->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(SoF->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + } + + TextLinkBody_Struct new_body_data; + SoFToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(SoF->Server): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(SoF->Server): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(SoF->Server): conversion error"); + serverTextLink = sofTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(SoF->Server): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(SoF->Server): new message '%s'", serverTextLink.c_str()); +#else + if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find(delimiter) == std::string::npos)) { + serverTextLink = sofTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(sofTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateSoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + TextLinkBody_Struct new_body_data; + SoFToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(SoF->Server): conversion error"); + serverTextLink = sofTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateSoFTextLinkBody(structs::TextLinkBody_Struct& sofLinkBodyStruct, const std::string& sofLinkBody) + { + // SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" + memset(&sofLinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct)); + if (sofLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + + sofLinkBodyStruct.unknown_1 = (uint8)strtol(sofLinkBody.substr(0, 1).c_str(), nullptr, 16); + sofLinkBodyStruct.item_id = (uint32)strtol(sofLinkBody.substr(1, 5).c_str(), nullptr, 16); + sofLinkBodyStruct.augment_1 = (uint32)strtol(sofLinkBody.substr(6, 5).c_str(), nullptr, 16); + sofLinkBodyStruct.augment_2 = (uint32)strtol(sofLinkBody.substr(11, 5).c_str(), nullptr, 16); + sofLinkBodyStruct.augment_3 = (uint32)strtol(sofLinkBody.substr(16, 5).c_str(), nullptr, 16); + sofLinkBodyStruct.augment_4 = (uint32)strtol(sofLinkBody.substr(21, 5).c_str(), nullptr, 16); + sofLinkBodyStruct.augment_5 = (uint32)strtol(sofLinkBody.substr(26, 5).c_str(), nullptr, 16); + sofLinkBodyStruct.unknown_2 = (uint8)strtol(sofLinkBody.substr(31, 1).c_str(), nullptr, 16); + sofLinkBodyStruct.unknown_3 = (uint32)strtol(sofLinkBody.substr(32, 4).c_str(), nullptr, 16); + sofLinkBodyStruct.unknown_4 = (uint8)strtol(sofLinkBody.substr(36, 1).c_str(), nullptr, 16); + sofLinkBodyStruct.ornament_icon = (uint32)strtol(sofLinkBody.substr(37, 5).c_str(), nullptr, 16); + sofLinkBodyStruct.hash = (int)strtol(sofLinkBody.substr(42, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void SoFToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& sofLinkBodyStruct) + { + serverLinkBodyStruct.unknown_1 = sofLinkBodyStruct.unknown_1; + serverLinkBodyStruct.item_id = sofLinkBodyStruct.item_id; + serverLinkBodyStruct.augment_1 = sofLinkBodyStruct.augment_1; + serverLinkBodyStruct.augment_2 = sofLinkBodyStruct.augment_2; + serverLinkBodyStruct.augment_3 = sofLinkBodyStruct.augment_3; + serverLinkBodyStruct.augment_4 = sofLinkBodyStruct.augment_4; + serverLinkBodyStruct.augment_5 = sofLinkBodyStruct.augment_5; + serverLinkBodyStruct.augment_6 = NOT_USED; + serverLinkBodyStruct.unknown_2 = NOT_USED; + serverLinkBodyStruct.unknown_3 = sofLinkBodyStruct.unknown_2; + serverLinkBodyStruct.unknown_4 = sofLinkBodyStruct.unknown_3; + serverLinkBodyStruct.unknown_5 = sofLinkBodyStruct.unknown_4; + serverLinkBodyStruct.ornament_icon = sofLinkBodyStruct.ornament_icon; + serverLinkBodyStruct.hash = sofLinkBodyStruct.hash; + } + + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) + { + serverLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + serverLinkBodyStruct.unknown_1, + serverLinkBodyStruct.item_id, + serverLinkBodyStruct.augment_1, + serverLinkBodyStruct.augment_2, + serverLinkBodyStruct.augment_3, + serverLinkBodyStruct.augment_4, + serverLinkBodyStruct.augment_5, + serverLinkBodyStruct.augment_6, + serverLinkBodyStruct.unknown_2, + serverLinkBodyStruct.unknown_3, + serverLinkBodyStruct.unknown_4, + serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.ornament_icon, + serverLinkBodyStruct.hash + ); + + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } } // end namespace SoF diff --git a/common/patches/sof_constants.h b/common/patches/sof_constants.h index 0b959ef3a..5e0f4b18a 100644 --- a/common/patches/sof_constants.h +++ b/common/patches/sof_constants.h @@ -177,6 +177,8 @@ namespace SoF { static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance static const uint32 POTION_BELT_SIZE = 5; + + static const size_t TEXT_LINK_BODY_LENGTH = 50; } namespace limits { diff --git a/common/patches/sof_ops.h b/common/patches/sof_ops.h index 132e3dc77..88d468c82 100644 --- a/common/patches/sof_ops.h +++ b/common/patches/sof_ops.h @@ -8,6 +8,7 @@ E(OP_BazaarSearch) E(OP_BecomeTrader) E(OP_Buff) E(OP_CancelTrade) +E(OP_ChannelMessage) E(OP_CharInventory) E(OP_ClientUpdate) E(OP_Consider) @@ -50,6 +51,7 @@ E(OP_SendZonepoints) E(OP_ShopPlayerSell) E(OP_SomeItemPacketMaybe) E(OP_SpawnDoor) +E(OP_SpecialMesg) E(OP_Stun) E(OP_Track) E(OP_Trader) @@ -70,6 +72,7 @@ D(OP_AugmentInfo) D(OP_AugmentItem) D(OP_Buff) D(OP_CastSpell) +D(OP_ChannelMessage) D(OP_CharacterCreate) D(OP_ClientUpdate) D(OP_Consider) diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 51f41a590..5986e0029 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -4115,18 +4115,24 @@ struct AltCurrencySellItem_Struct { /*010*/ uint32 cost; }; +// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" +struct TextLinkBody_Struct +{ + uint8 unknown_1; /* '%1X' - SoF field 1 / Server field 1 */ + uint32 item_id; /* '%05X' - SoF field 2 / Server field 2 */ + uint32 augment_1; /* '%05X' - SoF field 3 / Server field 3 */ + uint32 augment_2; /* '%05X' - SoF field 4 / Server field 4 */ + uint32 augment_3; /* '%05X' - SoF field 5 / Server field 5 */ + uint32 augment_4; /* '%05X' - SoF field 6 / Server field 6 */ + uint32 augment_5; /* '%05X' - SoF field 7 / Server field 7 */ + uint8 unknown_2; /* '%1X' - SoF field 8 / Server field 10 */ + uint32 unknown_3; /* '%04X' - SoF field 9 / Server field 11 */ + uint8 unknown_4; /* '%1X' - SoF field 10 / Server field 12 */ + uint32 ornament_icon; /* '%05X' - SoF field 11 / Server field 13 */ + int hash; /* '%08X' - SoF field 12 / Server field 14 */ +}; }; //end namespace structs }; //end namespace SoF #endif /*SoF_STRUCTS_H_*/ - - - - - - - - - - diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index f9ad6a4ff..fb7faa4f9 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -7,6 +7,7 @@ #include "../races.h" #include "../eq_packet_structs.h" +#include "../misc_functions.h" #include "../string_util.h" #include "../item.h" #include "titanium_structs.h" @@ -28,6 +29,18 @@ namespace Titanium static inline uint32 TitaniumToServerSlot(int16 TitaniumSlot); static inline uint32 TitaniumToServerCorpseSlot(int16 TitaniumCorpse); + // server to client text link converters + static inline void ServerToTitaniumTextLinks(std::string& titaniumTextLink, const std::string& serverTextLink); + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); + static inline void ServerToTitaniumTextLinkBodyStruct(structs::TextLinkBody_Struct& titaniumLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); + static inline bool GenerateTitaniumTextLinkBody(std::string& titaniumLinkBody, const structs::TextLinkBody_Struct& titaniumLinkBodyStruct); + + // client to server text link converters + static inline void TitaniumToServerTextLinks(std::string& serverTextLink, const std::string& titaniumTextLink); + static inline bool DegenerateTitaniumTextLinkBody(structs::TextLinkBody_Struct& titaniumLinkBodyStruct, const std::string& titaniumLinkBody); + static inline void TitaniumToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& titaniumLinkBodyStruct); + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -220,6 +233,35 @@ namespace Titanium FINISH_ENCODE(); } + ENCODE(OP_ChannelMessage) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + std::string old_message = emu->message; + std::string new_message; + ServerToTitaniumTextLinks(new_message, old_message); + + in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; + + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + memcpy(OutBuffer, __emu_buffer, sizeof(ChannelMessage_Struct)); + + OutBuffer += sizeof(ChannelMessage_Struct); + + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_CharInventory) { //consume the packet @@ -1070,6 +1112,44 @@ namespace Titanium FINISH_ENCODE(); } + ENCODE(OP_SpecialMesg) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string new_message; + ServerToTitaniumTextLinks(new_message, old_message); + + //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; + in->size = 25 + strlen(emu->sayer) + new_message.length(); + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id); + + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_Track) { EQApplicationPacket *in = *p; @@ -1371,6 +1451,25 @@ namespace Titanium FINISH_DIRECT_DECODE(); } + DECODE(OP_ChannelMessage) + { + unsigned char *__eq_buffer = __packet->pBuffer; + + std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)]; + std::string new_message; + TitaniumToServerTextLinks(new_message, old_message); + + __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; + __packet->pBuffer = new unsigned char[__packet->size]; + + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer; + + memcpy(emu, __eq_buffer, sizeof(ChannelMessage_Struct)); + strcpy(emu->message, new_message.c_str()); + + delete[] __eq_buffer; + } + DECODE(OP_CharacterCreate) { DECODE_LENGTH_EXACT(structs::CharCreate_Struct); @@ -1763,5 +1862,359 @@ namespace Titanium //uint32 ServerCorpse; return TitaniumCorpse; } + + static inline void ServerToTitaniumTextLinks(std::string& titaniumTextLink, const std::string& serverTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): old message '%s'", serverTextLink.c_str()); + + if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): link size equal, no conversion necessary"); + titaniumTextLink = serverTextLink; + return; + } + + if (serverTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): delimiter not found, no conversion necessary"); + titaniumTextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + } + + structs::TextLinkBody_Struct new_body_data; + ServerToTitaniumTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateTitaniumTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): conversion error"); + titaniumTextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + titaniumTextLink.push_back(delimiter); + titaniumTextLink.append(segments[iter].c_str()); + titaniumTextLink.push_back(delimiter); + } + else { + titaniumTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): new message '%s'", titaniumTextLink.c_str()); +#else + if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { + titaniumTextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + structs::TextLinkBody_Struct new_body_data; + ServerToTitaniumTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateTitaniumTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->Titanium): conversion error"); + titaniumTextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + titaniumTextLink.push_back(delimiter); + titaniumTextLink.append(segments[iter].c_str()); + titaniumTextLink.push_back(delimiter); + } + else { + titaniumTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) + { + memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + + serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void ServerToTitaniumTextLinkBodyStruct(structs::TextLinkBody_Struct& titaniumLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct) + { + titaniumLinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1; + titaniumLinkBodyStruct.item_id = serverLinkBodyStruct.item_id; + titaniumLinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1; + titaniumLinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2; + titaniumLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3; + titaniumLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; + titaniumLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; + titaniumLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3; + titaniumLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4; + titaniumLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5; + titaniumLinkBodyStruct.hash = serverLinkBodyStruct.hash; + } + + static inline bool GenerateTitaniumTextLinkBody(std::string& titaniumLinkBody, const structs::TextLinkBody_Struct& titaniumLinkBodyStruct) + { + titaniumLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X", + titaniumLinkBodyStruct.unknown_1, + titaniumLinkBodyStruct.item_id, + titaniumLinkBodyStruct.augment_1, + titaniumLinkBodyStruct.augment_2, + titaniumLinkBodyStruct.augment_3, + titaniumLinkBodyStruct.augment_4, + titaniumLinkBodyStruct.augment_5, + titaniumLinkBodyStruct.unknown_2, + titaniumLinkBodyStruct.unknown_3, + titaniumLinkBodyStruct.unknown_4, + titaniumLinkBodyStruct.hash + ); + + if (titaniumLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } + + static inline void TitaniumToServerTextLinks(std::string& serverTextLink, const std::string& titaniumTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): old message '%s'", titaniumTextLink.c_str()); + + if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): link size equal, no conversion necessary"); + serverTextLink = titaniumTextLink; + return; + } + + if (titaniumTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): delimiter not found, no conversion necessary"); + serverTextLink = titaniumTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(titaniumTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateTitaniumTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + } + + TextLinkBody_Struct new_body_data; + TitaniumToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): conversion error"); + serverTextLink = titaniumTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): new message '%s'", serverTextLink.c_str()); +#else + if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find(delimiter) == std::string::npos)) { + serverTextLink = titaniumTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(titaniumTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateTitaniumTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + TextLinkBody_Struct new_body_data; + TitaniumToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Titanium->Server): conversion error"); + serverTextLink = titaniumTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateTitaniumTextLinkBody(structs::TextLinkBody_Struct& titaniumLinkBodyStruct, const std::string& titaniumLinkBody) + { + // 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" + memset(&titaniumLinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct)); + if (titaniumLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + + titaniumLinkBodyStruct.unknown_1 = (uint8)strtol(titaniumLinkBody.substr(0, 1).c_str(), nullptr, 16); + titaniumLinkBodyStruct.item_id = (uint32)strtol(titaniumLinkBody.substr(1, 5).c_str(), nullptr, 16); + titaniumLinkBodyStruct.augment_1 = (uint32)strtol(titaniumLinkBody.substr(6, 5).c_str(), nullptr, 16); + titaniumLinkBodyStruct.augment_2 = (uint32)strtol(titaniumLinkBody.substr(11, 5).c_str(), nullptr, 16); + titaniumLinkBodyStruct.augment_3 = (uint32)strtol(titaniumLinkBody.substr(16, 5).c_str(), nullptr, 16); + titaniumLinkBodyStruct.augment_4 = (uint32)strtol(titaniumLinkBody.substr(21, 5).c_str(), nullptr, 16); + titaniumLinkBodyStruct.augment_5 = (uint32)strtol(titaniumLinkBody.substr(26, 5).c_str(), nullptr, 16); + titaniumLinkBodyStruct.unknown_2 = (uint8)strtol(titaniumLinkBody.substr(31, 1).c_str(), nullptr, 16); + titaniumLinkBodyStruct.unknown_3 = (uint32)strtol(titaniumLinkBody.substr(32, 4).c_str(), nullptr, 16); + titaniumLinkBodyStruct.unknown_4 = (uint8)strtol(titaniumLinkBody.substr(36, 1).c_str(), nullptr, 16); + titaniumLinkBodyStruct.hash = (int)strtol(titaniumLinkBody.substr(37, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void TitaniumToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& titaniumLinkBodyStruct) + { + serverLinkBodyStruct.unknown_1 = titaniumLinkBodyStruct.unknown_1; + serverLinkBodyStruct.item_id = titaniumLinkBodyStruct.item_id; + serverLinkBodyStruct.augment_1 = titaniumLinkBodyStruct.augment_1; + serverLinkBodyStruct.augment_2 = titaniumLinkBodyStruct.augment_2; + serverLinkBodyStruct.augment_3 = titaniumLinkBodyStruct.augment_3; + serverLinkBodyStruct.augment_4 = titaniumLinkBodyStruct.augment_4; + serverLinkBodyStruct.augment_5 = titaniumLinkBodyStruct.augment_5; + serverLinkBodyStruct.augment_6 = NOT_USED; + serverLinkBodyStruct.unknown_2 = NOT_USED; + serverLinkBodyStruct.unknown_3 = titaniumLinkBodyStruct.unknown_2; + serverLinkBodyStruct.unknown_4 = titaniumLinkBodyStruct.unknown_3; + serverLinkBodyStruct.unknown_5 = titaniumLinkBodyStruct.unknown_4; + serverLinkBodyStruct.ornament_icon = NOT_USED; + serverLinkBodyStruct.hash = titaniumLinkBodyStruct.hash; + } + + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) + { + serverLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + serverLinkBodyStruct.unknown_1, + serverLinkBodyStruct.item_id, + serverLinkBodyStruct.augment_1, + serverLinkBodyStruct.augment_2, + serverLinkBodyStruct.augment_3, + serverLinkBodyStruct.augment_4, + serverLinkBodyStruct.augment_5, + serverLinkBodyStruct.augment_6, + serverLinkBodyStruct.unknown_2, + serverLinkBodyStruct.unknown_3, + serverLinkBodyStruct.unknown_4, + serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.ornament_icon, + serverLinkBodyStruct.hash + ); + + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } } // end namespace Titanium diff --git a/common/patches/titanium_constants.h b/common/patches/titanium_constants.h index 85e525fe8..ff44513c2 100644 --- a/common/patches/titanium_constants.h +++ b/common/patches/titanium_constants.h @@ -176,6 +176,8 @@ namespace Titanium { static const uint32 BANDOLIERS_COUNT = 4; // count = number of bandolier instances static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance static const uint32 POTION_BELT_SIZE = 4; + + static const size_t TEXT_LINK_BODY_LENGTH = 45; } namespace limits { diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index 338558602..a3d2e71af 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -4,6 +4,7 @@ E(OP_AdventureMerchantSell) E(OP_ApplyPoison) E(OP_BazaarSearch) E(OP_BecomeTrader) +E(OP_ChannelMessage) E(OP_CharInventory) E(OP_DeleteCharge) E(OP_DeleteItem) @@ -35,6 +36,7 @@ E(OP_RespondAA) E(OP_SendCharInfo) E(OP_SendAATable) E(OP_ShopPlayerSell) +E(OP_SpecialMesg) E(OP_Track) E(OP_Trader) E(OP_TraderBuy) @@ -49,6 +51,7 @@ D(OP_AdventureMerchantSell) D(OP_ApplyPoison) D(OP_AugmentItem) D(OP_CastSpell) +D(OP_ChannelMessage) D(OP_CharacterCreate) D(OP_Consume) D(OP_DeleteItem) diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 0b5b1ec25..7fb2df5cd 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -3329,19 +3329,23 @@ struct LFGuild_GuildToggle_Struct /*616*/ }; +// 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" +struct TextLinkBody_Struct +{ + uint8 unknown_1; /* '%1X' - Titanium field 1 / Server field 1 */ + uint32 item_id; /* '%05X' - Titanium field 2 / Server field 2 */ + uint32 augment_1; /* '%05X' - Titanium field 3 / Server field 3 */ + uint32 augment_2; /* '%05X' - Titanium field 4 / Server field 4 */ + uint32 augment_3; /* '%05X' - Titanium field 5 / Server field 5 */ + uint32 augment_4; /* '%05X' - Titanium field 6 / Server field 6 */ + uint32 augment_5; /* '%05X' - Titanium field 7 / Server field 7 */ + uint8 unknown_2; /* '%1X' - Titanium field 8 / Server field 10 */ + uint32 unknown_3; /* '%04X' - Titanium field 9 / Server field 11 */ + uint8 unknown_4; /* '%1X' - Titanium field 10 / Server field 12 */ + int hash; /* '%08X' - Titanium field 11 / Server field 14 */ +}; + }; //end namespace structs }; //end namespace Titanium - - #endif /*Titanium_STRUCTS_H_*/ - - - - - - - - - - diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 5ee38f586..e45dae148 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -31,6 +31,18 @@ namespace Underfoot static inline uint32 UnderfootToServerSlot(uint32 UnderfootSlot); static inline uint32 UnderfootToServerCorpseSlot(uint32 UnderfootCorpse); + // server to client text link converters + static inline void ServerToUnderfootTextLinks(std::string& underfootTextLink, const std::string& serverTextLink); + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); + static inline void ServerToUnderfootTextLinkBodyStruct(structs::TextLinkBody_Struct& underfootLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); + static inline bool GenerateUnderfootTextLinkBody(std::string& underfootLinkBody, const structs::TextLinkBody_Struct& underfootLinkBodyStruct); + + // client to server text link converters + static inline void UnderfootToServerTextLinks(std::string& serverTextLink, const std::string& underfootTextLink); + static inline bool DegenerateUnderfootTextLinkBody(structs::TextLinkBody_Struct& underfootLinkBodyStruct, const std::string& underfootLinkBody); + static inline void UnderfootToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& underfootLinkBodyStruct); + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -432,7 +444,12 @@ namespace Underfoot unsigned char *__emu_buffer = in->pBuffer; - in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; + std::string old_message = emu->message; + std::string new_message; + ServerToUnderfootTextLinks(new_message, old_message); + + //in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; + in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39; in->pBuffer = new unsigned char[in->size]; @@ -446,7 +463,7 @@ namespace Underfoot VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->skill_in_language); - VARSTRUCT_ENCODE_STRING(OutBuffer, emu->message); + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown @@ -2298,6 +2315,44 @@ namespace Underfoot FINISH_ENCODE(); } + ENCODE(OP_SpecialMesg) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + std::string old_message = &emu->message[strlen(emu->sayer)]; + std::string new_message; + ServerToUnderfootTextLinks(new_message, old_message); + + //in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; + in->size = 25 + strlen(emu->sayer) + new_message.length(); + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id); + + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + + VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_Stun) { ENCODE_LENGTH_EXACT(Stun_Struct); @@ -3036,7 +3091,13 @@ namespace Underfoot uint32 Skill = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - __packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; + std::string old_message = InBuffer; + std::string new_message; + UnderfootToServerTextLinks(new_message, old_message); + + //__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; + __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; + __packet->pBuffer = new unsigned char[__packet->size]; ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer; @@ -3045,7 +3106,7 @@ namespace Underfoot emu->language = Language; emu->chan_num = Channel; emu->skill_in_language = Skill; - strcpy(emu->message, InBuffer); + strcpy(emu->message, new_message.c_str()); delete[] __eq_buffer; } @@ -4155,5 +4216,362 @@ namespace Underfoot //uint32 ServerCorpse; return (UnderfootCorpse - 1); } + + static inline void ServerToUnderfootTextLinks(std::string& underfootTextLink, const std::string& serverTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): old message '%s'", serverTextLink.c_str()); + + if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): link size equal, no conversion necessary"); + underfootTextLink = serverTextLink; + return; + } + + if (serverTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): delimiter not found, no conversion necessary"); + underfootTextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + } + + structs::TextLinkBody_Struct new_body_data; + ServerToUnderfootTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateUnderfootTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): conversion error"); + underfootTextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + underfootTextLink.push_back(delimiter); + underfootTextLink.append(segments[iter].c_str()); + underfootTextLink.push_back(delimiter); + } + else { + underfootTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): new message '%s'", underfootTextLink.c_str()); +#else + if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { + underfootTextLink = serverTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(serverTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + TextLinkBody_Struct old_body_data; + if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + structs::TextLinkBody_Struct new_body_data; + ServerToUnderfootTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateUnderfootTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): conversion error"); + underfootTextLink = serverTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + underfootTextLink.push_back(delimiter); + underfootTextLink.append(segments[iter].c_str()); + underfootTextLink.push_back(delimiter); + } + else { + underfootTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody) + { + memset(&serverLinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + + serverLinkBodyStruct.unknown_1 = (uint8)strtol(serverLinkBody.substr(0, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.item_id = (uint32)strtol(serverLinkBody.substr(1, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_1 = (uint32)strtol(serverLinkBody.substr(6, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_2 = (uint32)strtol(serverLinkBody.substr(11, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_3 = (uint32)strtol(serverLinkBody.substr(16, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); + serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.ornament_icon = (uint32)strtol(serverLinkBody.substr(43, 5).c_str(), nullptr, 16); + serverLinkBodyStruct.hash = (int)strtol(serverLinkBody.substr(48, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void ServerToUnderfootTextLinkBodyStruct(structs::TextLinkBody_Struct& underfootLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct) + { + underfootLinkBodyStruct.unknown_1 = serverLinkBodyStruct.unknown_1; + underfootLinkBodyStruct.item_id = serverLinkBodyStruct.item_id; + underfootLinkBodyStruct.augment_1 = serverLinkBodyStruct.augment_1; + underfootLinkBodyStruct.augment_2 = serverLinkBodyStruct.augment_2; + underfootLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3; + underfootLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; + underfootLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; + underfootLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3; + underfootLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4; + underfootLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5; + underfootLinkBodyStruct.ornament_icon = serverLinkBodyStruct.ornament_icon; + underfootLinkBodyStruct.hash = serverLinkBodyStruct.hash; + } + + static inline bool GenerateUnderfootTextLinkBody(std::string& underfootLinkBody, const structs::TextLinkBody_Struct& underfootLinkBodyStruct) + { + underfootLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X", + underfootLinkBodyStruct.unknown_1, + underfootLinkBodyStruct.item_id, + underfootLinkBodyStruct.augment_1, + underfootLinkBodyStruct.augment_2, + underfootLinkBodyStruct.augment_3, + underfootLinkBodyStruct.augment_4, + underfootLinkBodyStruct.augment_5, + underfootLinkBodyStruct.unknown_2, + underfootLinkBodyStruct.unknown_3, + underfootLinkBodyStruct.unknown_4, + underfootLinkBodyStruct.ornament_icon, + underfootLinkBodyStruct.hash + ); + + if (underfootLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } + + static inline void UnderfootToServerTextLinks(std::string& serverTextLink, const std::string& underfootTextLink) + { + const char delimiter = 0x12; + +#if EQDEBUG >= 6 + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): old message '%s'", underfootTextLink.c_str()); + + if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): link size equal, no conversion necessary"); + serverTextLink = underfootTextLink; + return; + } + + if (underfootTextLink.find(delimiter) == std::string::npos) { + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): delimiter not found, no conversion necessary"); + serverTextLink = underfootTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(underfootTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateUnderfootTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); + } + + TextLinkBody_Struct new_body_data; + UnderfootToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body generation error '%s'", segment.c_str()); + conversion_error = true; + } + else { + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body generation success '%s'", segment.c_str()); + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): conversion error"); + serverTextLink = underfootTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): segment[%u] '%s'", iter, segments[iter].c_str()); + } + + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): new message '%s'", serverTextLink.c_str()); +#else + if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (underfootTextLink.find(delimiter) == std::string::npos)) { + serverTextLink = underfootTextLink; + return; + } + + bool conversion_error = false; + auto segments = SplitString(underfootTextLink, delimiter); + + for (size_t iter = 1; iter < segments.size(); iter += 2) { + structs::TextLinkBody_Struct old_body_data; + if (!DegenerateUnderfootTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { + conversion_error = true; + break; + } + + TextLinkBody_Struct new_body_data; + UnderfootToServerTextLinkBodyStruct(new_body_data, old_body_data); + + std::string segment; + if (!GenerateServerTextLinkBody(segment, new_body_data)) { + conversion_error = true; + break; + } + else { + segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); + segments[iter] = segment.c_str(); + } + } + + if (conversion_error) { + _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): conversion error"); + serverTextLink = underfootTextLink; + return; + } + + for (size_t iter = 0; iter < segments.size(); ++iter) { + if (iter & 1) { + serverTextLink.push_back(delimiter); + serverTextLink.append(segments[iter].c_str()); + serverTextLink.push_back(delimiter); + } + else { + serverTextLink.append(segments[iter].c_str()); + } + } +#endif + } + + static inline bool DegenerateUnderfootTextLinkBody(structs::TextLinkBody_Struct& underfootLinkBodyStruct, const std::string& underfootLinkBody) + { + // SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" + memset(&underfootLinkBodyStruct, 0, sizeof(structs::TextLinkBody_Struct)); + if (underfootLinkBody.length() != consts::TEXT_LINK_BODY_LENGTH) { return false; } + + underfootLinkBodyStruct.unknown_1 = (uint8)strtol(underfootLinkBody.substr(0, 1).c_str(), nullptr, 16); + underfootLinkBodyStruct.item_id = (uint32)strtol(underfootLinkBody.substr(1, 5).c_str(), nullptr, 16); + underfootLinkBodyStruct.augment_1 = (uint32)strtol(underfootLinkBody.substr(6, 5).c_str(), nullptr, 16); + underfootLinkBodyStruct.augment_2 = (uint32)strtol(underfootLinkBody.substr(11, 5).c_str(), nullptr, 16); + underfootLinkBodyStruct.augment_3 = (uint32)strtol(underfootLinkBody.substr(16, 5).c_str(), nullptr, 16); + underfootLinkBodyStruct.augment_4 = (uint32)strtol(underfootLinkBody.substr(21, 5).c_str(), nullptr, 16); + underfootLinkBodyStruct.augment_5 = (uint32)strtol(underfootLinkBody.substr(26, 5).c_str(), nullptr, 16); + underfootLinkBodyStruct.unknown_2 = (uint8)strtol(underfootLinkBody.substr(31, 1).c_str(), nullptr, 16); + underfootLinkBodyStruct.unknown_3 = (uint32)strtol(underfootLinkBody.substr(32, 4).c_str(), nullptr, 16); + underfootLinkBodyStruct.unknown_4 = (uint8)strtol(underfootLinkBody.substr(36, 1).c_str(), nullptr, 16); + underfootLinkBodyStruct.ornament_icon = (uint32)strtol(underfootLinkBody.substr(37, 5).c_str(), nullptr, 16); + underfootLinkBodyStruct.hash = (int)strtol(underfootLinkBody.substr(42, 8).c_str(), nullptr, 16); + + return true; + } + + static inline void UnderfootToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& underfootLinkBodyStruct) + { + serverLinkBodyStruct.unknown_1 = underfootLinkBodyStruct.unknown_1; + serverLinkBodyStruct.item_id = underfootLinkBodyStruct.item_id; + serverLinkBodyStruct.augment_1 = underfootLinkBodyStruct.augment_1; + serverLinkBodyStruct.augment_2 = underfootLinkBodyStruct.augment_2; + serverLinkBodyStruct.augment_3 = underfootLinkBodyStruct.augment_3; + serverLinkBodyStruct.augment_4 = underfootLinkBodyStruct.augment_4; + serverLinkBodyStruct.augment_5 = underfootLinkBodyStruct.augment_5; + serverLinkBodyStruct.augment_6 = NOT_USED; + serverLinkBodyStruct.unknown_2 = NOT_USED; + serverLinkBodyStruct.unknown_3 = underfootLinkBodyStruct.unknown_2; + serverLinkBodyStruct.unknown_4 = underfootLinkBodyStruct.unknown_3; + serverLinkBodyStruct.unknown_5 = underfootLinkBodyStruct.unknown_4; + serverLinkBodyStruct.ornament_icon = underfootLinkBodyStruct.ornament_icon; + serverLinkBodyStruct.hash = underfootLinkBodyStruct.hash; + } + + static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) + { + serverLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + serverLinkBodyStruct.unknown_1, + serverLinkBodyStruct.item_id, + serverLinkBodyStruct.augment_1, + serverLinkBodyStruct.augment_2, + serverLinkBodyStruct.augment_3, + serverLinkBodyStruct.augment_4, + serverLinkBodyStruct.augment_5, + serverLinkBodyStruct.augment_6, + serverLinkBodyStruct.unknown_2, + serverLinkBodyStruct.unknown_3, + serverLinkBodyStruct.unknown_4, + serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.ornament_icon, + serverLinkBodyStruct.hash + ); + + if (serverLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + return true; + } } // end namespace Underfoot diff --git a/common/patches/underfoot_constants.h b/common/patches/underfoot_constants.h index b89a4f255..a656c56eb 100644 --- a/common/patches/underfoot_constants.h +++ b/common/patches/underfoot_constants.h @@ -177,6 +177,8 @@ namespace Underfoot { static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance static const uint32 POTION_BELT_SIZE = 5; + + static const size_t TEXT_LINK_BODY_LENGTH = 50; } namespace limits { diff --git a/common/patches/underfoot_ops.h b/common/patches/underfoot_ops.h index cfb4d4fe9..61f4f1c0f 100644 --- a/common/patches/underfoot_ops.h +++ b/common/patches/underfoot_ops.h @@ -65,6 +65,7 @@ E(OP_ShopPlayerSell) E(OP_SomeItemPacketMaybe) E(OP_SpawnAppearance) E(OP_SpawnDoor) +E(OP_SpecialMesg) E(OP_Stun) E(OP_TargetBuffs) E(OP_Track) diff --git a/common/patches/underfoot_structs.h b/common/patches/underfoot_structs.h index 3a63a8c0f..9180a762b 100644 --- a/common/patches/underfoot_structs.h +++ b/common/patches/underfoot_structs.h @@ -4530,6 +4530,23 @@ struct MercenaryAssign_Struct { /*0012*/ }; +// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" +struct TextLinkBody_Struct +{ + uint8 unknown_1; /* '%1X' - Underfoot field 1 / Server field 1 */ + uint32 item_id; /* '%05X' - Underfoot field 2 / Server field 2 */ + uint32 augment_1; /* '%05X' - Underfoot field 3 / Server field 3 */ + uint32 augment_2; /* '%05X' - Underfoot field 4 / Server field 4 */ + uint32 augment_3; /* '%05X' - Underfoot field 5 / Server field 5 */ + uint32 augment_4; /* '%05X' - Underfoot field 6 / Server field 6 */ + uint32 augment_5; /* '%05X' - Underfoot field 7 / Server field 7 */ + uint8 unknown_2; /* '%1X' - Underfoot field 8 / Server field 10 */ + uint32 unknown_3; /* '%04X' - Underfoot field 9 / Server field 11 */ + uint8 unknown_4; /* '%1X' - Underfoot field 10 / Server field 12 */ + uint32 ornament_icon; /* '%05X' - Underfoot field 11 / Server field 13 */ + int hash; /* '%08X' - Underfoot field 12 / Server field 14 */ +}; + }; //end namespace structs }; //end namespace Underfoot diff --git a/zone/bot.cpp b/zone/bot.cpp index d41b6db11..bd7c9f946 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -11707,7 +11707,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { std::string item_link; Client::TextLink linker; linker.SetLinkType(linker.linkItemInst); - linker.SetClientVersion(c->GetClientVersion()); for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { if((i == MainSecondary) && is2Hweapon) { diff --git a/zone/client.cpp b/zone/client.cpp index 0ad34d752..54324932d 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8271,71 +8271,27 @@ std::string Client::TextLink::GenerateLink() generate_body(); generate_text(); - if (m_LinkBody.length() && m_LinkText.length()) { - m_Link.append(StringFormat("%c", 0x12)); + if ((m_LinkBody.length() == EmuConstants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) { + m_Link.push_back(0x12); m_Link.append(m_LinkBody); m_Link.append(m_LinkText); - m_Link.append(StringFormat("%c", 0x12)); + m_Link.push_back(0x12); } if ((m_Link.length() == 0) || (m_Link.length() > 250)) { m_Error = true; m_Link = ""; - _log(CHANNELS__ERROR, "TextLink::GenerateLink() failed to generate a useable text link (LinkType: %i, Lengths: {l: %u, b: %u, t: %u})", + _log(CHANNELS__ERROR, "TextLink::GenerateLink() failed to generate a useable text link (LinkType: %i, Lengths: {link: %u, body: %u, text: %u})", m_LinkType, m_Link.length(), m_LinkBody.length(), m_LinkText.length()); +#if EQDEBUG >= 5 + _log(CHANNELS__ERROR, ">> LinkBody: %s", m_LinkBody.c_str()); + _log(CHANNELS__ERROR, ">> LinkText: %s", m_LinkText.c_str()); +#endif } return m_Link; } -const char* Client::TextLink::GetLink() -{ - if (m_Link.length() == 0) - return nullptr; - - return m_Link.c_str(); -} - -const char* Client::TextLink::GetLinkBody() -{ - if (m_LinkBody.length() == 0) - return nullptr; - - return m_LinkBody.c_str(); -} - -const char* Client::TextLink::GetLinkText() -{ - if (m_LinkText.length() == 0) - return nullptr; - - return m_LinkText.c_str(); -} - -std::string Client::TextLink::GetLinkString() -{ - if (m_Link.length() == 0) - return ""; - - return m_Link; -} - -std::string Client::TextLink::GetLinkBodyString() -{ - if (m_LinkBody.length() == 0) - return ""; - - return m_LinkBody; -} - -std::string Client::TextLink::GetLinkTextString() -{ - if (m_LinkText.length() == 0) - return ""; - - return m_LinkText; -} - void Client::TextLink::Reset() { m_LinkType = linkBlank; @@ -8348,81 +8304,72 @@ void Client::TextLink::Reset() m_Link.clear(); m_LinkBody.clear(); m_LinkText.clear(); - m_ClientVersion = EQClientUnknown; m_Error = false; } void Client::TextLink::generate_body() { - enum { field_0 = 0, field_1, field_2, field_3, field_4, field_5, field_6, field_7, field_8, field_9, field_10, field_11, field_12, field_13 }; - static const int field_count = 14; - static const bool field_use[_EQClientCount][field_count] = { - // 6.2: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" - // SoF: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" - // RoF: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" - // RoF2: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X" + /* + Current server mask: EQClientRoF2 + + RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X" (56) + RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (55) + SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (50) + 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" (45) + */ -//(RoF2) %01x %05x %05x %05x %05x %05x %05x %05x %01x %01x %04x %01x %05x %08x - { true, true, true, true, true, true, true, true, true, true, true, true, true, true }, // EQClientUnknown - { true, true, true, true, true, true, true, false, false, true, true, true, false, true }, // EQClient6.2 - { true, true, true, true, true, true, true, false, false, true, true, true, false, true }, // EQClientTitanium - { true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientSoF - { true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientSoD - { true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientUnderfoot - { true, true, true, true, true, true, true, true, false, true, true, true, true, true }, // EQClientRoF - { true, true, true, true, true, true, true, true, true, true, true, true, true, true } // EQClientRoF2 - }; - -/*%01X*/ uint8 unknown_0 = NOT_USED; -/*%05X*/ uint32 item_id = NOT_USED; -/*%05X*/ uint32 augment_0 = NOT_USED; -/*%05X*/ uint32 augment_1 = NOT_USED; -/*%05X*/ uint32 augment_2 = NOT_USED; -/*%05X*/ uint32 augment_3 = NOT_USED; -/*%05X*/ uint32 augment_4 = NOT_USED; -/*%05X*/ uint32 augment_5 = NOT_USED; -/*%01X*/ uint8 unknown_8 = NOT_USED; -/*%01X*/ uint8 unknown_9 = NOT_USED; -/*%04X*/ uint32 unknown_10 = NOT_USED; -/*%01X*/ uint8 unknown_11 = NOT_USED; -/*%05X*/ uint32 unknown_12 = NOT_USED; -/*%08X*/ int hash = NOT_USED; + // could use a ##_cast(&this) with a memset to '0' since these properties are inherited + + unknown_1 = NOT_USED; /* field 1 */ + item_id = NOT_USED; /* field 2 */ + augment_1 = NOT_USED; /* field 3 */ + augment_2 = NOT_USED; /* field 4 */ + augment_3 = NOT_USED; /* field 5 */ + augment_4 = NOT_USED; /* field 6 */ + augment_5 = NOT_USED; /* field 7 */ + augment_6 = NOT_USED; /* field 8 */ + unknown_2 = NOT_USED; /* field 9 */ + unknown_3 = NOT_USED; /* field 10 */ + unknown_4 = NOT_USED; /* field 11 */ + unknown_5 = NOT_USED; /* field 12 */ + ornament_icon = NOT_USED; /* field 13 */ + hash = NOT_USED; /* field 14 */ + const Item_Struct* item_data = nullptr; + switch (m_LinkType) { case linkBlank: break; case linkItemData: - if (m_ItemData != nullptr) { - item_id = m_ItemData->ID; - // TODO: add hash call - } + if (m_ItemData == nullptr) { break; } + item_id = m_ItemData->ID; + // TODO: add hash call break; case linkLootItem: - if (m_LootData != nullptr) { - const Item_Struct* item_data = database.GetItem(m_LootData->item_id); - if (item_data == nullptr) { break; } - item_id = item_data->ID; - augment_0 = m_LootData->aug_1; - augment_1 = m_LootData->aug_2; - augment_2 = m_LootData->aug_3; - augment_3 = m_LootData->aug_4; - augment_4 = m_LootData->aug_5; - augment_5 = m_LootData->aug_6; - // TODO: add hash call - } + if (m_LootData == nullptr) { break; } + item_data = database.GetItem(m_LootData->item_id); + if (item_data == nullptr) { break; } + item_id = item_data->ID; + augment_1 = m_LootData->aug_1; + augment_2 = m_LootData->aug_2; + augment_3 = m_LootData->aug_3; + augment_4 = m_LootData->aug_4; + augment_5 = m_LootData->aug_5; + augment_6 = m_LootData->aug_6; + // TODO: add hash call break; case linkItemInst: - if (m_ItemInst != nullptr) { - if (m_ItemInst->GetItem() == nullptr) { break; } - item_id = m_ItemInst->GetItem()->ID; - augment_0 = m_ItemInst->GetAugmentItemID(0); - augment_1 = m_ItemInst->GetAugmentItemID(1); - augment_2 = m_ItemInst->GetAugmentItemID(2); - augment_3 = m_ItemInst->GetAugmentItemID(3); - augment_4 = m_ItemInst->GetAugmentItemID(4); - augment_5 = m_ItemInst->GetAugmentItemID(5); - // TODO: add hash call - } + if (m_ItemInst == nullptr) { break; } + if (m_ItemInst->GetItem() == nullptr) { break; } + item_id = m_ItemInst->GetItem()->ID; + augment_1 = m_ItemInst->GetAugmentItemID(0); + augment_2 = m_ItemInst->GetAugmentItemID(1); + augment_3 = m_ItemInst->GetAugmentItemID(2); + augment_4 = m_ItemInst->GetAugmentItemID(3); + augment_5 = m_ItemInst->GetAugmentItemID(4); + augment_6 = m_ItemInst->GetAugmentItemID(5); + ornament_icon = m_ItemInst->GetOrnamentationIcon(); + // TODO: add hash call break; default: break; @@ -8433,23 +8380,27 @@ void Client::TextLink::generate_body() } if (m_TaskUse) { - hash = 0x0000000014505DC2; + //hash = 0x0000000014505DC2; + hash = 0x14505DC2; } - if (field_use[m_ClientVersion][field_0]) { m_LinkBody.append(StringFormat("%01x", unknown_0)); } - if (field_use[m_ClientVersion][field_1]) { m_LinkBody.append(StringFormat("%05x", item_id)); } - if (field_use[m_ClientVersion][field_2]) { m_LinkBody.append(StringFormat("%05x", augment_0)); } - if (field_use[m_ClientVersion][field_3]) { m_LinkBody.append(StringFormat("%05x", augment_1)); } - if (field_use[m_ClientVersion][field_4]) { m_LinkBody.append(StringFormat("%05x", augment_2)); } - if (field_use[m_ClientVersion][field_5]) { m_LinkBody.append(StringFormat("%05x", augment_3)); } - if (field_use[m_ClientVersion][field_6]) { m_LinkBody.append(StringFormat("%05x", augment_4)); } - if (field_use[m_ClientVersion][field_7]) { m_LinkBody.append(StringFormat("%05x", augment_5)); } - if (field_use[m_ClientVersion][field_8]) { m_LinkBody.append(StringFormat("%01x", unknown_8)); } - if (field_use[m_ClientVersion][field_9]) { m_LinkBody.append(StringFormat("%01x", unknown_9)); } - if (field_use[m_ClientVersion][field_10]) { m_LinkBody.append(StringFormat("%04x", unknown_10)); } - if (field_use[m_ClientVersion][field_11]) { m_LinkBody.append(StringFormat("%01x", unknown_11)); } - if (field_use[m_ClientVersion][field_12]) { m_LinkBody.append(StringFormat("%05x", unknown_12)); } - if (field_use[m_ClientVersion][field_13]) { m_LinkBody.append(StringFormat("%08x", hash)); } + m_LinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X", + unknown_1, + item_id, + augment_1, + augment_2, + augment_3, + augment_4, + augment_5, + augment_6, + unknown_2, + unknown_3, + unknown_4, + unknown_5, + ornament_icon, + hash + ); } void Client::TextLink::generate_text() @@ -8459,35 +8410,76 @@ void Client::TextLink::generate_text() return; } + const Item_Struct* item_data = nullptr; + switch (m_LinkType) { case linkBlank: break; case linkItemData: - if (m_ItemData != nullptr) { - m_LinkText = m_ItemData->Name; - return; - } - break; + if (m_ItemData == nullptr) { break; } + m_LinkText = m_ItemData->Name; + return; case linkLootItem: - if (m_LootData != nullptr) { - const Item_Struct* item_data = database.GetItem(m_LootData->item_id); - if (item_data != nullptr) { - m_LinkText = item_data->Name; - return; - } - } - break; + if (m_LootData == nullptr) { break; } + item_data = database.GetItem(m_LootData->item_id); + if (item_data == nullptr) { break; } + m_LinkText = item_data->Name; + return; case linkItemInst: - if (m_ItemInst != nullptr) { - if (m_ItemInst->GetItem() != nullptr) { - m_LinkText = m_ItemInst->GetItem()->Name; - return; - } - } - break; + if (m_ItemInst == nullptr) { break; } + if (m_ItemInst->GetItem() == nullptr) { break; } + m_LinkText = m_ItemInst->GetItem()->Name; + return; default: break; } m_LinkText = "null"; } + +bool Client::TextLink::DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruct, const std::string& textLinkBody) +{ + memset(&textLinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); + if (textLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + + textLinkBodyStruct.unknown_1 = (uint8)strtol(textLinkBody.substr(0, 1).c_str(), nullptr, 16); + textLinkBodyStruct.item_id = (uint32)strtol(textLinkBody.substr(1, 5).c_str(), nullptr, 16); + textLinkBodyStruct.augment_1 = (uint32)strtol(textLinkBody.substr(6, 5).c_str(), nullptr, 16); + textLinkBodyStruct.augment_2 = (uint32)strtol(textLinkBody.substr(11, 5).c_str(), nullptr, 16); + textLinkBodyStruct.augment_3 = (uint32)strtol(textLinkBody.substr(16, 5).c_str(), nullptr, 16); + textLinkBodyStruct.augment_4 = (uint32)strtol(textLinkBody.substr(21, 5).c_str(), nullptr, 16); + textLinkBodyStruct.augment_5 = (uint32)strtol(textLinkBody.substr(26, 5).c_str(), nullptr, 16); + textLinkBodyStruct.augment_6 = (uint32)strtol(textLinkBody.substr(31, 5).c_str(), nullptr, 16); + textLinkBodyStruct.unknown_2 = (uint8)strtol(textLinkBody.substr(36, 1).c_str(), nullptr, 16); + textLinkBodyStruct.unknown_3 = (uint8)strtol(textLinkBody.substr(37, 1).c_str(), nullptr, 16); + textLinkBodyStruct.unknown_4 = (uint32)strtol(textLinkBody.substr(38, 4).c_str(), nullptr, 16); + textLinkBodyStruct.unknown_5 = (uint8)strtol(textLinkBody.substr(42, 1).c_str(), nullptr, 16); + textLinkBodyStruct.ornament_icon = (uint32)strtol(textLinkBody.substr(43, 5).c_str(), nullptr, 16); + textLinkBodyStruct.hash = (int)strtol(textLinkBody.substr(48, 8).c_str(), nullptr, 16); + + return true; +} + +bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLinkBody_Struct& textLinkBodyStruct) +{ + textLinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X", + textLinkBodyStruct.unknown_1, + textLinkBodyStruct.item_id, + textLinkBodyStruct.augment_1, + textLinkBodyStruct.augment_2, + textLinkBodyStruct.augment_3, + textLinkBodyStruct.augment_4, + textLinkBodyStruct.augment_5, + textLinkBodyStruct.augment_6, + textLinkBodyStruct.unknown_2, + textLinkBodyStruct.unknown_3, + textLinkBodyStruct.unknown_4, + textLinkBodyStruct.unknown_5, + textLinkBodyStruct.ornament_icon, + textLinkBodyStruct.hash + ); + + if (textLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + return true; +} diff --git a/zone/client.h b/zone/client.h index b7bb8f6a5..d6ef83523 100644 --- a/zone/client.h +++ b/zone/client.h @@ -819,7 +819,7 @@ public: // // class Client::TextLink // - class TextLink { + class TextLink : TextLinkBody_Struct { public: enum LinkType { linkBlank = 0, linkItemData, linkLootItem, linkItemInst }; @@ -832,20 +832,19 @@ public: void SetProxyItemID(uint32 proxyItemID) { m_ProxyItemID = proxyItemID; } // mainly for saylinks..but, not limited to void SetProxyText(const char* proxyText) { m_ProxyText = proxyText; } // overrides standard text use void SetTaskUse() { m_TaskUse = true; } - void SetClientVersion(EQClientVersion clientVersion) { m_ClientVersion = EQLimits::ValidateClientVersion(clientVersion); } std::string GenerateLink(); bool LinkError() { return m_Error; } - const char* GetLink(); // contains full format: '/12x' '' '' '/12x' - const char* GetLinkBody(); // contains format: '' - const char* GetLinkText(); // contains format: '' - std::string GetLinkString(); - std::string GetLinkBodyString(); - std::string GetLinkTextString(); + std::string GetLink() { return m_Link; } // contains full string format: '/12x' '' '' '/12x' + std::string GetLinkBody() { return m_LinkBody; } // contains string format: '' + std::string GetLinkText() { return m_LinkText; } // contains string format: '' void Reset(); + static bool DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruct, const std::string& textLinkBody); + static bool GenerateLinkBody(std::string& textLinkBody, const TextLinkBody_Struct& textLinkBodyStruct); + private: void generate_body(); void generate_text(); @@ -860,7 +859,6 @@ public: std::string m_Link; std::string m_LinkBody; std::string m_LinkText; - EQClientVersion m_ClientVersion; bool m_Error; }; diff --git a/zone/command.cpp b/zone/command.cpp index d31ea97b7..b33a3ee6d 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2621,7 +2621,6 @@ void command_peekinv(Client *c, const Seperator *sep) std::string item_link; Client::TextLink linker; linker.SetLinkType(linker.linkItemInst); - linker.SetClientVersion(c->GetClientVersion()); c->Message(0, "Displaying inventory for %s...", targetClient->GetName()); @@ -5574,7 +5573,6 @@ void command_itemsearch(Client *c, const Seperator *sep) std::string item_link; Client::TextLink linker; linker.SetLinkType(linker.linkItemData); - linker.SetClientVersion(c->GetClientVersion()); if (Seperator::IsNumber(search_criteria)) { item = database.GetItem(atoi(search_criteria)); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 380697eac..d5db03856 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1258,23 +1258,16 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { SetPlayerKillItemID(0); } - /* Send message with item link to groups and such */ - Client::TextLink linker; - linker.SetLinkType(linker.linkItemInst); - linker.SetItemInst(inst); - linker.SetClientVersion(client->GetClientVersion()); + /* Send message with item link to groups and such */ + Client::TextLink linker; + linker.SetLinkType(linker.linkItemInst); + linker.SetItemInst(inst); auto item_link = linker.GenerateLink(); client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, item_link.c_str()); - if(!IsPlayerCorpse()) { - // When sending to multiple/unknown client types, we set for the highest client.. - // ..which is processed when 'EQClientUnknown,' or default value, is selected. - // This should help with any current issues..or it may create more! O.o - linker.SetClientVersion(EQClientUnknown); - item_link = linker.GenerateLink(); - + if (!IsPlayerCorpse()) { Group *g = client->GetGroup(); if(g != nullptr) { g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); diff --git a/zone/npc.cpp b/zone/npc.cpp index a478e3b51..d6cf9ed9f 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -515,7 +515,6 @@ void NPC::QueryLoot(Client* to) Client::TextLink linker; linker.SetLinkType(linker.linkItemData); linker.SetItemData(item); - linker.SetClientVersion(to->GetClientVersion()); auto item_link = linker.GenerateLink(); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 3fb714d7e..53eed6787 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1234,7 +1234,6 @@ void QuestManager::itemlink(int item_id) { Client::TextLink linker; linker.SetLinkType(linker.linkItemData); linker.SetItemData(item); - linker.SetClientVersion(initiator->GetClientVersion()); auto item_link = linker.GenerateLink(); @@ -2474,8 +2473,6 @@ const char* QuestManager::varlink(char* perltext, int item_id) { Client::TextLink linker; linker.SetLinkType(linker.linkItemData); linker.SetItemData(item); - if (initiator) - linker.SetClientVersion(initiator->GetClientVersion()); auto item_link = linker.GenerateLink(); strcpy(perltext, item_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink() @@ -2668,8 +2665,6 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam Client::TextLink linker; linker.SetProxyItemID(sayid); linker.SetProxyText(LinkName); - if (initiator) - linker.SetClientVersion(initiator->GetClientVersion()); auto say_link = linker.GenerateLink(); strcpy(Phrase, say_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink() diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 79efb1115..1f6e381fd 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -2779,7 +2779,6 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN Client::TextLink linker; linker.SetLinkType(linker.linkItemData); linker.SetItemData(reward_item); - linker.SetClientVersion(c->GetClientVersion()); linker.SetTaskUse(); if (strlen(Tasks[TaskID]->Reward) != 0) linker.SetProxyText(Tasks[TaskID]->Reward); From 668823eaf20fa5533d9226f57368b2254e98e22e Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 5 Jan 2015 23:11:38 -0500 Subject: [PATCH 04/10] Fix for text link issues with items whose loregroup is '-1' --- common/eq_packet_structs.h | 27 ++++++++--------- common/patches/rof.cpp | 41 ++++++++++++------------- common/patches/rof2.cpp | 48 +++++++++++++----------------- common/patches/rof2_structs.h | 29 +++++++++--------- common/patches/rof_structs.h | 26 ++++++++-------- common/patches/sod.cpp | 41 ++++++++++++------------- common/patches/sod_structs.h | 24 +++++++-------- common/patches/sof.cpp | 41 ++++++++++++------------- common/patches/sof_structs.h | 24 +++++++-------- common/patches/titanium.cpp | 41 ++++++++++++------------- common/patches/titanium_structs.h | 22 +++++++------- common/patches/underfoot.cpp | 41 ++++++++++++------------- common/patches/underfoot_structs.h | 24 +++++++-------- zone/client.cpp | 44 +++++++++++++-------------- 14 files changed, 223 insertions(+), 250 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 32f7360fb..2c38b5bb0 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -5270,20 +5270,19 @@ struct ClientMarqueeMessage_Struct { typedef std::list ItemList; struct TextLinkBody_Struct { - uint8 unknown_1; /* '%1X' - Server field 1 */ - uint32 item_id; /* '%05X' - Server field 2 */ - uint32 augment_1; /* '%05X' - Server field 3 */ - uint32 augment_2; /* '%05X' - Server field 4 */ - uint32 augment_3; /* '%05X' - Server field 5 */ - uint32 augment_4; /* '%05X' - Server field 6 */ - uint32 augment_5; /* '%05X' - Server field 7 */ - uint32 augment_6; /* '%05X' - Server field 8 */ - uint8 unknown_2; /* '%1X' - Server field 9 */ - uint8 unknown_3; /* '%1X' - Server field 10 */ - uint32 unknown_4; /* '%04X' - Server field 11 */ - uint8 unknown_5; /* '%1X' - Server field 12 */ - uint32 ornament_icon; /* '%05X' - Server field 13 */ - int hash; /* '%08X' - Server field 14 */ + 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; }; // Restore structure packing to default diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index d236d2b34..00b76da6c 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -5819,10 +5819,9 @@ namespace RoF serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.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); @@ -5839,9 +5838,9 @@ namespace RoF rofLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; rofLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; rofLinkBodyStruct.augment_6 = serverLinkBodyStruct.augment_6; - rofLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3; - rofLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4; - rofLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5; + rofLinkBodyStruct.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; } @@ -5858,9 +5857,9 @@ namespace RoF rofLinkBodyStruct.augment_4, rofLinkBodyStruct.augment_5, rofLinkBodyStruct.augment_6, - rofLinkBodyStruct.unknown_2, - rofLinkBodyStruct.unknown_3, - rofLinkBodyStruct.unknown_4, + rofLinkBodyStruct.is_evolving, + rofLinkBodyStruct.lore_group, + rofLinkBodyStruct.evolve_max, rofLinkBodyStruct.ornament_icon, rofLinkBodyStruct.hash ); @@ -5999,9 +5998,9 @@ namespace RoF rofLinkBodyStruct.augment_4 = (uint32)strtol(rofLinkBody.substr(21, 5).c_str(), nullptr, 16); rofLinkBodyStruct.augment_5 = (uint32)strtol(rofLinkBody.substr(26, 5).c_str(), nullptr, 16); rofLinkBodyStruct.augment_6 = (uint32)strtol(rofLinkBody.substr(31, 5).c_str(), nullptr, 16); - rofLinkBodyStruct.unknown_2 = (uint8)strtol(rofLinkBody.substr(36, 1).c_str(), nullptr, 16); - rofLinkBodyStruct.unknown_3 = (uint32)strtol(rofLinkBody.substr(37, 4).c_str(), nullptr, 16); - rofLinkBodyStruct.unknown_4 = (uint8)strtol(rofLinkBody.substr(41, 1).c_str(), nullptr, 16); + rofLinkBodyStruct.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); @@ -6018,10 +6017,9 @@ namespace RoF serverLinkBodyStruct.augment_4 = rofLinkBodyStruct.augment_4; serverLinkBodyStruct.augment_5 = rofLinkBodyStruct.augment_5; serverLinkBodyStruct.augment_6 = rofLinkBodyStruct.augment_6; - serverLinkBodyStruct.unknown_2 = NOT_USED; - serverLinkBodyStruct.unknown_3 = rofLinkBodyStruct.unknown_2; - serverLinkBodyStruct.unknown_4 = rofLinkBodyStruct.unknown_3; - serverLinkBodyStruct.unknown_5 = rofLinkBodyStruct.unknown_4; + serverLinkBodyStruct.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; } @@ -6029,7 +6027,7 @@ namespace RoF static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) { serverLinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%05X" "%01X" "%05X" "%08X", serverLinkBodyStruct.unknown_1, serverLinkBodyStruct.item_id, serverLinkBodyStruct.augment_1, @@ -6038,10 +6036,9 @@ namespace RoF serverLinkBodyStruct.augment_4, serverLinkBodyStruct.augment_5, serverLinkBodyStruct.augment_6, - serverLinkBodyStruct.unknown_2, - serverLinkBodyStruct.unknown_3, - serverLinkBodyStruct.unknown_4, - serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.is_evolving, + serverLinkBodyStruct.lore_group, + serverLinkBodyStruct.evolve_max, serverLinkBodyStruct.ornament_icon, serverLinkBodyStruct.hash ); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 6356a6f7d..3d23c54bc 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -5914,10 +5914,9 @@ namespace RoF2 serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.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); @@ -5934,10 +5933,9 @@ namespace RoF2 rof2LinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; rof2LinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; rof2LinkBodyStruct.augment_6 = serverLinkBodyStruct.augment_6; - rof2LinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_2; - rof2LinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_3; - rof2LinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_4; - rof2LinkBodyStruct.unknown_5 = serverLinkBodyStruct.unknown_5; + rof2LinkBodyStruct.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; } @@ -5945,7 +5943,7 @@ namespace RoF2 static inline bool GenerateRoF2TextLinkBody(std::string& rof2LinkBody, const structs::TextLinkBody_Struct& rof2LinkBodyStruct) { rof2LinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X", + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X", rof2LinkBodyStruct.unknown_1, rof2LinkBodyStruct.item_id, rof2LinkBodyStruct.augment_1, @@ -5954,10 +5952,9 @@ namespace RoF2 rof2LinkBodyStruct.augment_4, rof2LinkBodyStruct.augment_5, rof2LinkBodyStruct.augment_6, - rof2LinkBodyStruct.unknown_2, - rof2LinkBodyStruct.unknown_3, - rof2LinkBodyStruct.unknown_4, - rof2LinkBodyStruct.unknown_5, + rof2LinkBodyStruct.is_evolving, + rof2LinkBodyStruct.lore_group, + rof2LinkBodyStruct.evolve_max, rof2LinkBodyStruct.ornament_icon, rof2LinkBodyStruct.hash ); @@ -6084,7 +6081,7 @@ namespace RoF2 static inline bool DegenerateRoF2TextLinkBody(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const std::string& rof2LinkBody) { - // RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X" + // 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; } @@ -6096,10 +6093,9 @@ namespace RoF2 rof2LinkBodyStruct.augment_4 = (uint32)strtol(rof2LinkBody.substr(21, 5).c_str(), nullptr, 16); rof2LinkBodyStruct.augment_5 = (uint32)strtol(rof2LinkBody.substr(26, 5).c_str(), nullptr, 16); rof2LinkBodyStruct.augment_6 = (uint32)strtol(rof2LinkBody.substr(31, 5).c_str(), nullptr, 16); - rof2LinkBodyStruct.unknown_2 = (uint8)strtol(rof2LinkBody.substr(36, 1).c_str(), nullptr, 16); - rof2LinkBodyStruct.unknown_3 = (uint32)strtol(rof2LinkBody.substr(37, 4).c_str(), nullptr, 16); - rof2LinkBodyStruct.unknown_4 = (uint8)strtol(rof2LinkBody.substr(41, 1).c_str(), nullptr, 16); - rof2LinkBodyStruct.unknown_5 = (uint8)strtol(rof2LinkBody.substr(42, 1).c_str(), nullptr, 16); + rof2LinkBodyStruct.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); @@ -6116,10 +6112,9 @@ namespace RoF2 serverLinkBodyStruct.augment_4 = rof2LinkBodyStruct.augment_4; serverLinkBodyStruct.augment_5 = rof2LinkBodyStruct.augment_5; serverLinkBodyStruct.augment_6 = rof2LinkBodyStruct.augment_6; - serverLinkBodyStruct.unknown_2 = rof2LinkBodyStruct.unknown_2; - serverLinkBodyStruct.unknown_3 = rof2LinkBodyStruct.unknown_3; - serverLinkBodyStruct.unknown_4 = rof2LinkBodyStruct.unknown_4; - serverLinkBodyStruct.unknown_5 = rof2LinkBodyStruct.unknown_5; + serverLinkBodyStruct.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; } @@ -6127,7 +6122,7 @@ namespace RoF2 static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) { serverLinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%05X" "%01X" "%05X" "%08X", serverLinkBodyStruct.unknown_1, serverLinkBodyStruct.item_id, serverLinkBodyStruct.augment_1, @@ -6136,10 +6131,9 @@ namespace RoF2 serverLinkBodyStruct.augment_4, serverLinkBodyStruct.augment_5, serverLinkBodyStruct.augment_6, - serverLinkBodyStruct.unknown_2, - serverLinkBodyStruct.unknown_3, - serverLinkBodyStruct.unknown_4, - serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.is_evolving, + serverLinkBodyStruct.lore_group, + serverLinkBodyStruct.evolve_max, serverLinkBodyStruct.ornament_icon, serverLinkBodyStruct.hash ); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 60cf07808..0b2de35ab 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4872,23 +4872,22 @@ struct MercenaryMerchantResponse_Struct { /*0004*/ }; -// RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X" +// RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X" struct TextLinkBody_Struct { - uint8 unknown_1; /* '%1X' - RoF2 field 1 / Server field 1 */ - uint32 item_id; /* '%05X' - RoF2 field 2 / Server field 2 */ - uint32 augment_1; /* '%05X' - RoF2 field 3 / Server field 3 */ - uint32 augment_2; /* '%05X' - RoF2 field 4 / Server field 4 */ - uint32 augment_3; /* '%05X' - RoF2 field 5 / Server field 5 */ - uint32 augment_4; /* '%05X' - RoF2 field 6 / Server field 6 */ - uint32 augment_5; /* '%05X' - RoF2 field 7 / Server field 7 */ - uint32 augment_6; /* '%05X' - RoF2 field 8 / Server field 8 */ - uint8 unknown_2; /* '%1X' - RoF2 field 9 / Server field 9 */ - uint8 unknown_3; /* '%1X' - RoF2 field 10 / Server field 10 */ - uint32 unknown_4; /* '%04X' - RoF2 field 11 / Server field 11 */ - uint8 unknown_5; /* '%1X' - RoF2 field 12 / Server field 12 */ - uint32 ornament_icon; /* '%05X' - RoF2 field 13 / Server field 13 */ - int hash; /* '%08X' - RoF2 field 14 / Server field 14 */ + 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 diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 4aa2c04a2..c5f02dc9b 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4897,19 +4897,19 @@ struct MercenaryMerchantResponse_Struct { // RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" struct TextLinkBody_Struct { - uint8 unknown_1; /* '%1X' - RoF field 1 / Server field 1 */ - uint32 item_id; /* '%05X' - RoF field 2 / Server field 2 */ - uint32 augment_1; /* '%05X' - RoF field 3 / Server field 3 */ - uint32 augment_2; /* '%05X' - RoF field 4 / Server field 4 */ - uint32 augment_3; /* '%05X' - RoF field 5 / Server field 5 */ - uint32 augment_4; /* '%05X' - RoF field 6 / Server field 6 */ - uint32 augment_5; /* '%05X' - RoF field 7 / Server field 7 */ - uint32 augment_6; /* '%05X' - RoF field 8 / Server field 8 */ - uint8 unknown_2; /* '%1X' - RoF field 9 / Server field 10 */ - uint32 unknown_3; /* '%04X' - RoF field 10 / Server field 11 */ - uint8 unknown_4; /* '%1X' - RoF field 11 / Server field 12 */ - uint32 ornament_icon; /* '%05X' - RoF field 12 / Server field 13 */ - int hash; /* '%08X' - RoF field 13 / Server field 14 */ + 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 diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index b30bad97d..94d1cb120 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3911,10 +3911,9 @@ namespace SoD serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.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); @@ -3930,9 +3929,9 @@ namespace SoD sodLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3; sodLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; sodLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; - sodLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3; - sodLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4; - sodLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5; + sodLinkBodyStruct.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; } @@ -3948,9 +3947,9 @@ namespace SoD sodLinkBodyStruct.augment_3, sodLinkBodyStruct.augment_4, sodLinkBodyStruct.augment_5, - sodLinkBodyStruct.unknown_2, - sodLinkBodyStruct.unknown_3, - sodLinkBodyStruct.unknown_4, + sodLinkBodyStruct.is_evolving, + sodLinkBodyStruct.lore_group, + sodLinkBodyStruct.evolve_max, sodLinkBodyStruct.ornament_icon, sodLinkBodyStruct.hash ); @@ -4088,9 +4087,9 @@ namespace SoD sodLinkBodyStruct.augment_3 = (uint32)strtol(sodLinkBody.substr(16, 5).c_str(), nullptr, 16); sodLinkBodyStruct.augment_4 = (uint32)strtol(sodLinkBody.substr(21, 5).c_str(), nullptr, 16); sodLinkBodyStruct.augment_5 = (uint32)strtol(sodLinkBody.substr(26, 5).c_str(), nullptr, 16); - sodLinkBodyStruct.unknown_2 = (uint8)strtol(sodLinkBody.substr(31, 1).c_str(), nullptr, 16); - sodLinkBodyStruct.unknown_3 = (uint32)strtol(sodLinkBody.substr(32, 4).c_str(), nullptr, 16); - sodLinkBodyStruct.unknown_4 = (uint8)strtol(sodLinkBody.substr(36, 1).c_str(), nullptr, 16); + sodLinkBodyStruct.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); @@ -4107,10 +4106,9 @@ namespace SoD serverLinkBodyStruct.augment_4 = sodLinkBodyStruct.augment_4; serverLinkBodyStruct.augment_5 = sodLinkBodyStruct.augment_5; serverLinkBodyStruct.augment_6 = NOT_USED; - serverLinkBodyStruct.unknown_2 = NOT_USED; - serverLinkBodyStruct.unknown_3 = sodLinkBodyStruct.unknown_2; - serverLinkBodyStruct.unknown_4 = sodLinkBodyStruct.unknown_3; - serverLinkBodyStruct.unknown_5 = sodLinkBodyStruct.unknown_4; + serverLinkBodyStruct.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; } @@ -4118,7 +4116,7 @@ namespace SoD static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) { serverLinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%05X" "%01X" "%05X" "%08X", serverLinkBodyStruct.unknown_1, serverLinkBodyStruct.item_id, serverLinkBodyStruct.augment_1, @@ -4127,10 +4125,9 @@ namespace SoD serverLinkBodyStruct.augment_4, serverLinkBodyStruct.augment_5, serverLinkBodyStruct.augment_6, - serverLinkBodyStruct.unknown_2, - serverLinkBodyStruct.unknown_3, - serverLinkBodyStruct.unknown_4, - serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.is_evolving, + serverLinkBodyStruct.lore_group, + serverLinkBodyStruct.evolve_max, serverLinkBodyStruct.ornament_icon, serverLinkBodyStruct.hash ); diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 3c1acc37d..39f81b7c1 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -4412,18 +4412,18 @@ struct MercenaryAssign_Struct { // SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" struct TextLinkBody_Struct { - uint8 unknown_1; /* '%1X' - SoD field 1 / Server field 1 */ - uint32 item_id; /* '%05X' - SoD field 2 / Server field 2 */ - uint32 augment_1; /* '%05X' - SoD field 3 / Server field 3 */ - uint32 augment_2; /* '%05X' - SoD field 4 / Server field 4 */ - uint32 augment_3; /* '%05X' - SoD field 5 / Server field 5 */ - uint32 augment_4; /* '%05X' - SoD field 6 / Server field 6 */ - uint32 augment_5; /* '%05X' - SoD field 7 / Server field 7 */ - uint8 unknown_2; /* '%1X' - SoD field 8 / Server field 10 */ - uint32 unknown_3; /* '%04X' - SoD field 9 / Server field 11 */ - uint8 unknown_4; /* '%1X' - SoD field 10 / Server field 12 */ - uint32 ornament_icon; /* '%05X' - SoD field 11 / Server field 13 */ - int hash; /* '%08X' - SoD field 12 / Server field 14 */ + 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 diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index cd5a1ef71..a75b07307 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -3233,10 +3233,9 @@ namespace SoF serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.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); @@ -3252,9 +3251,9 @@ namespace SoF sofLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3; sofLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; sofLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; - sofLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3; - sofLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4; - sofLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5; + sofLinkBodyStruct.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; } @@ -3270,9 +3269,9 @@ namespace SoF sofLinkBodyStruct.augment_3, sofLinkBodyStruct.augment_4, sofLinkBodyStruct.augment_5, - sofLinkBodyStruct.unknown_2, - sofLinkBodyStruct.unknown_3, - sofLinkBodyStruct.unknown_4, + sofLinkBodyStruct.is_evolving, + sofLinkBodyStruct.lore_group, + sofLinkBodyStruct.evolve_max, sofLinkBodyStruct.ornament_icon, sofLinkBodyStruct.hash ); @@ -3410,9 +3409,9 @@ namespace SoF sofLinkBodyStruct.augment_3 = (uint32)strtol(sofLinkBody.substr(16, 5).c_str(), nullptr, 16); sofLinkBodyStruct.augment_4 = (uint32)strtol(sofLinkBody.substr(21, 5).c_str(), nullptr, 16); sofLinkBodyStruct.augment_5 = (uint32)strtol(sofLinkBody.substr(26, 5).c_str(), nullptr, 16); - sofLinkBodyStruct.unknown_2 = (uint8)strtol(sofLinkBody.substr(31, 1).c_str(), nullptr, 16); - sofLinkBodyStruct.unknown_3 = (uint32)strtol(sofLinkBody.substr(32, 4).c_str(), nullptr, 16); - sofLinkBodyStruct.unknown_4 = (uint8)strtol(sofLinkBody.substr(36, 1).c_str(), nullptr, 16); + sofLinkBodyStruct.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); @@ -3429,10 +3428,9 @@ namespace SoF serverLinkBodyStruct.augment_4 = sofLinkBodyStruct.augment_4; serverLinkBodyStruct.augment_5 = sofLinkBodyStruct.augment_5; serverLinkBodyStruct.augment_6 = NOT_USED; - serverLinkBodyStruct.unknown_2 = NOT_USED; - serverLinkBodyStruct.unknown_3 = sofLinkBodyStruct.unknown_2; - serverLinkBodyStruct.unknown_4 = sofLinkBodyStruct.unknown_3; - serverLinkBodyStruct.unknown_5 = sofLinkBodyStruct.unknown_4; + serverLinkBodyStruct.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; } @@ -3440,7 +3438,7 @@ namespace SoF static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) { serverLinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%05X" "%01X" "%05X" "%08X", serverLinkBodyStruct.unknown_1, serverLinkBodyStruct.item_id, serverLinkBodyStruct.augment_1, @@ -3449,10 +3447,9 @@ namespace SoF serverLinkBodyStruct.augment_4, serverLinkBodyStruct.augment_5, serverLinkBodyStruct.augment_6, - serverLinkBodyStruct.unknown_2, - serverLinkBodyStruct.unknown_3, - serverLinkBodyStruct.unknown_4, - serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.is_evolving, + serverLinkBodyStruct.lore_group, + serverLinkBodyStruct.evolve_max, serverLinkBodyStruct.ornament_icon, serverLinkBodyStruct.hash ); diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 5986e0029..08d7f6fa6 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -4118,18 +4118,18 @@ struct AltCurrencySellItem_Struct { // SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" struct TextLinkBody_Struct { - uint8 unknown_1; /* '%1X' - SoF field 1 / Server field 1 */ - uint32 item_id; /* '%05X' - SoF field 2 / Server field 2 */ - uint32 augment_1; /* '%05X' - SoF field 3 / Server field 3 */ - uint32 augment_2; /* '%05X' - SoF field 4 / Server field 4 */ - uint32 augment_3; /* '%05X' - SoF field 5 / Server field 5 */ - uint32 augment_4; /* '%05X' - SoF field 6 / Server field 6 */ - uint32 augment_5; /* '%05X' - SoF field 7 / Server field 7 */ - uint8 unknown_2; /* '%1X' - SoF field 8 / Server field 10 */ - uint32 unknown_3; /* '%04X' - SoF field 9 / Server field 11 */ - uint8 unknown_4; /* '%1X' - SoF field 10 / Server field 12 */ - uint32 ornament_icon; /* '%05X' - SoF field 11 / Server field 13 */ - int hash; /* '%08X' - SoF field 12 / Server field 14 */ + 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 diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index fb7faa4f9..e083f9561 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1992,10 +1992,9 @@ namespace Titanium serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.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); @@ -2011,9 +2010,9 @@ namespace Titanium titaniumLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3; titaniumLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; titaniumLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; - titaniumLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3; - titaniumLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4; - titaniumLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5; + titaniumLinkBodyStruct.is_evolving = serverLinkBodyStruct.is_evolving; + titaniumLinkBodyStruct.lore_group = serverLinkBodyStruct.lore_group; + titaniumLinkBodyStruct.evolve_max = serverLinkBodyStruct.evolve_max; titaniumLinkBodyStruct.hash = serverLinkBodyStruct.hash; } @@ -2028,9 +2027,9 @@ namespace Titanium titaniumLinkBodyStruct.augment_3, titaniumLinkBodyStruct.augment_4, titaniumLinkBodyStruct.augment_5, - titaniumLinkBodyStruct.unknown_2, - titaniumLinkBodyStruct.unknown_3, - titaniumLinkBodyStruct.unknown_4, + titaniumLinkBodyStruct.is_evolving, + titaniumLinkBodyStruct.lore_group, + titaniumLinkBodyStruct.evolve_max, titaniumLinkBodyStruct.hash ); @@ -2167,9 +2166,9 @@ namespace Titanium titaniumLinkBodyStruct.augment_3 = (uint32)strtol(titaniumLinkBody.substr(16, 5).c_str(), nullptr, 16); titaniumLinkBodyStruct.augment_4 = (uint32)strtol(titaniumLinkBody.substr(21, 5).c_str(), nullptr, 16); titaniumLinkBodyStruct.augment_5 = (uint32)strtol(titaniumLinkBody.substr(26, 5).c_str(), nullptr, 16); - titaniumLinkBodyStruct.unknown_2 = (uint8)strtol(titaniumLinkBody.substr(31, 1).c_str(), nullptr, 16); - titaniumLinkBodyStruct.unknown_3 = (uint32)strtol(titaniumLinkBody.substr(32, 4).c_str(), nullptr, 16); - titaniumLinkBodyStruct.unknown_4 = (uint8)strtol(titaniumLinkBody.substr(36, 1).c_str(), nullptr, 16); + titaniumLinkBodyStruct.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; @@ -2185,10 +2184,9 @@ namespace Titanium serverLinkBodyStruct.augment_4 = titaniumLinkBodyStruct.augment_4; serverLinkBodyStruct.augment_5 = titaniumLinkBodyStruct.augment_5; serverLinkBodyStruct.augment_6 = NOT_USED; - serverLinkBodyStruct.unknown_2 = NOT_USED; - serverLinkBodyStruct.unknown_3 = titaniumLinkBodyStruct.unknown_2; - serverLinkBodyStruct.unknown_4 = titaniumLinkBodyStruct.unknown_3; - serverLinkBodyStruct.unknown_5 = titaniumLinkBodyStruct.unknown_4; + serverLinkBodyStruct.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; } @@ -2196,7 +2194,7 @@ namespace Titanium static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) { serverLinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%05X" "%01X" "%05X" "%08X", serverLinkBodyStruct.unknown_1, serverLinkBodyStruct.item_id, serverLinkBodyStruct.augment_1, @@ -2205,10 +2203,9 @@ namespace Titanium serverLinkBodyStruct.augment_4, serverLinkBodyStruct.augment_5, serverLinkBodyStruct.augment_6, - serverLinkBodyStruct.unknown_2, - serverLinkBodyStruct.unknown_3, - serverLinkBodyStruct.unknown_4, - serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.is_evolving, + serverLinkBodyStruct.lore_group, + serverLinkBodyStruct.evolve_max, serverLinkBodyStruct.ornament_icon, serverLinkBodyStruct.hash ); diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 7fb2df5cd..06536c7c2 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -3332,17 +3332,17 @@ struct LFGuild_GuildToggle_Struct // 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" struct TextLinkBody_Struct { - uint8 unknown_1; /* '%1X' - Titanium field 1 / Server field 1 */ - uint32 item_id; /* '%05X' - Titanium field 2 / Server field 2 */ - uint32 augment_1; /* '%05X' - Titanium field 3 / Server field 3 */ - uint32 augment_2; /* '%05X' - Titanium field 4 / Server field 4 */ - uint32 augment_3; /* '%05X' - Titanium field 5 / Server field 5 */ - uint32 augment_4; /* '%05X' - Titanium field 6 / Server field 6 */ - uint32 augment_5; /* '%05X' - Titanium field 7 / Server field 7 */ - uint8 unknown_2; /* '%1X' - Titanium field 8 / Server field 10 */ - uint32 unknown_3; /* '%04X' - Titanium field 9 / Server field 11 */ - uint8 unknown_4; /* '%1X' - Titanium field 10 / Server field 12 */ - int hash; /* '%08X' - Titanium field 11 / Server field 14 */ + 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 diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index e45dae148..022c1d62c 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -4346,10 +4346,9 @@ namespace Underfoot serverLinkBodyStruct.augment_4 = (uint32)strtol(serverLinkBody.substr(21, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_5 = (uint32)strtol(serverLinkBody.substr(26, 5).c_str(), nullptr, 16); serverLinkBodyStruct.augment_6 = (uint32)strtol(serverLinkBody.substr(31, 5).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_2 = (uint8)strtol(serverLinkBody.substr(36, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_3 = (uint8)strtol(serverLinkBody.substr(37, 1).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_4 = (uint32)strtol(serverLinkBody.substr(38, 4).c_str(), nullptr, 16); - serverLinkBodyStruct.unknown_5 = (uint8)strtol(serverLinkBody.substr(42, 1).c_str(), nullptr, 16); + serverLinkBodyStruct.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); @@ -4365,9 +4364,9 @@ namespace Underfoot underfootLinkBodyStruct.augment_3 = serverLinkBodyStruct.augment_3; underfootLinkBodyStruct.augment_4 = serverLinkBodyStruct.augment_4; underfootLinkBodyStruct.augment_5 = serverLinkBodyStruct.augment_5; - underfootLinkBodyStruct.unknown_2 = serverLinkBodyStruct.unknown_3; - underfootLinkBodyStruct.unknown_3 = serverLinkBodyStruct.unknown_4; - underfootLinkBodyStruct.unknown_4 = serverLinkBodyStruct.unknown_5; + underfootLinkBodyStruct.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; } @@ -4383,9 +4382,9 @@ namespace Underfoot underfootLinkBodyStruct.augment_3, underfootLinkBodyStruct.augment_4, underfootLinkBodyStruct.augment_5, - underfootLinkBodyStruct.unknown_2, - underfootLinkBodyStruct.unknown_3, - underfootLinkBodyStruct.unknown_4, + underfootLinkBodyStruct.is_evolving, + underfootLinkBodyStruct.lore_group, + underfootLinkBodyStruct.evolve_max, underfootLinkBodyStruct.ornament_icon, underfootLinkBodyStruct.hash ); @@ -4523,9 +4522,9 @@ namespace Underfoot underfootLinkBodyStruct.augment_3 = (uint32)strtol(underfootLinkBody.substr(16, 5).c_str(), nullptr, 16); underfootLinkBodyStruct.augment_4 = (uint32)strtol(underfootLinkBody.substr(21, 5).c_str(), nullptr, 16); underfootLinkBodyStruct.augment_5 = (uint32)strtol(underfootLinkBody.substr(26, 5).c_str(), nullptr, 16); - underfootLinkBodyStruct.unknown_2 = (uint8)strtol(underfootLinkBody.substr(31, 1).c_str(), nullptr, 16); - underfootLinkBodyStruct.unknown_3 = (uint32)strtol(underfootLinkBody.substr(32, 4).c_str(), nullptr, 16); - underfootLinkBodyStruct.unknown_4 = (uint8)strtol(underfootLinkBody.substr(36, 1).c_str(), nullptr, 16); + underfootLinkBodyStruct.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); @@ -4542,10 +4541,9 @@ namespace Underfoot serverLinkBodyStruct.augment_4 = underfootLinkBodyStruct.augment_4; serverLinkBodyStruct.augment_5 = underfootLinkBodyStruct.augment_5; serverLinkBodyStruct.augment_6 = NOT_USED; - serverLinkBodyStruct.unknown_2 = NOT_USED; - serverLinkBodyStruct.unknown_3 = underfootLinkBodyStruct.unknown_2; - serverLinkBodyStruct.unknown_4 = underfootLinkBodyStruct.unknown_3; - serverLinkBodyStruct.unknown_5 = underfootLinkBodyStruct.unknown_4; + serverLinkBodyStruct.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; } @@ -4553,7 +4551,7 @@ namespace Underfoot static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct) { serverLinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%01X" "%04X" "%01X" "%05X" "%08X", + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%01X" "%05X" "%01X" "%05X" "%08X", serverLinkBodyStruct.unknown_1, serverLinkBodyStruct.item_id, serverLinkBodyStruct.augment_1, @@ -4562,10 +4560,9 @@ namespace Underfoot serverLinkBodyStruct.augment_4, serverLinkBodyStruct.augment_5, serverLinkBodyStruct.augment_6, - serverLinkBodyStruct.unknown_2, - serverLinkBodyStruct.unknown_3, - serverLinkBodyStruct.unknown_4, - serverLinkBodyStruct.unknown_5, + serverLinkBodyStruct.is_evolving, + serverLinkBodyStruct.lore_group, + serverLinkBodyStruct.evolve_max, serverLinkBodyStruct.ornament_icon, serverLinkBodyStruct.hash ); diff --git a/common/patches/underfoot_structs.h b/common/patches/underfoot_structs.h index 9180a762b..b196e5867 100644 --- a/common/patches/underfoot_structs.h +++ b/common/patches/underfoot_structs.h @@ -4533,18 +4533,18 @@ struct MercenaryAssign_Struct { // SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" struct TextLinkBody_Struct { - uint8 unknown_1; /* '%1X' - Underfoot field 1 / Server field 1 */ - uint32 item_id; /* '%05X' - Underfoot field 2 / Server field 2 */ - uint32 augment_1; /* '%05X' - Underfoot field 3 / Server field 3 */ - uint32 augment_2; /* '%05X' - Underfoot field 4 / Server field 4 */ - uint32 augment_3; /* '%05X' - Underfoot field 5 / Server field 5 */ - uint32 augment_4; /* '%05X' - Underfoot field 6 / Server field 6 */ - uint32 augment_5; /* '%05X' - Underfoot field 7 / Server field 7 */ - uint8 unknown_2; /* '%1X' - Underfoot field 8 / Server field 10 */ - uint32 unknown_3; /* '%04X' - Underfoot field 9 / Server field 11 */ - uint8 unknown_4; /* '%1X' - Underfoot field 10 / Server field 12 */ - uint32 ornament_icon; /* '%05X' - Underfoot field 11 / Server field 13 */ - int hash; /* '%08X' - Underfoot field 12 / Server field 14 */ + 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 diff --git a/zone/client.cpp b/zone/client.cpp index 54324932d..c8bbd25cf 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8312,10 +8312,10 @@ void Client::TextLink::generate_body() /* Current server mask: EQClientRoF2 - RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X" (56) - RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (55) - SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (50) - 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" (45) + RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X" (56) + RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (55) + SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (50) + 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" (45) */ // could use a ##_cast(&this) with a memset to '0' since these properties are inherited @@ -8328,12 +8328,11 @@ void Client::TextLink::generate_body() augment_4 = NOT_USED; /* field 6 */ augment_5 = NOT_USED; /* field 7 */ augment_6 = NOT_USED; /* field 8 */ - unknown_2 = NOT_USED; /* field 9 */ - unknown_3 = NOT_USED; /* field 10 */ - unknown_4 = NOT_USED; /* field 11 */ - unknown_5 = NOT_USED; /* field 12 */ - ornament_icon = NOT_USED; /* field 13 */ - hash = NOT_USED; /* field 14 */ + 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; @@ -8385,7 +8384,7 @@ void Client::TextLink::generate_body() } m_LinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X", + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X", unknown_1, item_id, augment_1, @@ -8394,10 +8393,9 @@ void Client::TextLink::generate_body() augment_4, augment_5, augment_6, - unknown_2, - unknown_3, - unknown_4, - unknown_5, + is_evolving, + lore_group, + evolve_max, ornament_icon, hash ); @@ -8450,10 +8448,9 @@ bool Client::TextLink::DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruc textLinkBodyStruct.augment_4 = (uint32)strtol(textLinkBody.substr(21, 5).c_str(), nullptr, 16); textLinkBodyStruct.augment_5 = (uint32)strtol(textLinkBody.substr(26, 5).c_str(), nullptr, 16); textLinkBodyStruct.augment_6 = (uint32)strtol(textLinkBody.substr(31, 5).c_str(), nullptr, 16); - textLinkBodyStruct.unknown_2 = (uint8)strtol(textLinkBody.substr(36, 1).c_str(), nullptr, 16); - textLinkBodyStruct.unknown_3 = (uint8)strtol(textLinkBody.substr(37, 1).c_str(), nullptr, 16); - textLinkBodyStruct.unknown_4 = (uint32)strtol(textLinkBody.substr(38, 4).c_str(), nullptr, 16); - textLinkBodyStruct.unknown_5 = (uint8)strtol(textLinkBody.substr(42, 1).c_str(), nullptr, 16); + textLinkBodyStruct.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_max = (uint8)strtol(textLinkBody.substr(42, 1).c_str(), nullptr, 16); textLinkBodyStruct.ornament_icon = (uint32)strtol(textLinkBody.substr(43, 5).c_str(), nullptr, 16); textLinkBodyStruct.hash = (int)strtol(textLinkBody.substr(48, 8).c_str(), nullptr, 16); @@ -8463,7 +8460,7 @@ bool Client::TextLink::DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruc bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLinkBody_Struct& textLinkBodyStruct) { textLinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X", + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X", textLinkBodyStruct.unknown_1, textLinkBodyStruct.item_id, textLinkBodyStruct.augment_1, @@ -8472,10 +8469,9 @@ bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLin textLinkBodyStruct.augment_4, textLinkBodyStruct.augment_5, textLinkBodyStruct.augment_6, - textLinkBodyStruct.unknown_2, - textLinkBodyStruct.unknown_3, - textLinkBodyStruct.unknown_4, - textLinkBodyStruct.unknown_5, + textLinkBodyStruct.is_evolving, + textLinkBodyStruct.lore_group, + textLinkBodyStruct.evolve_max, textLinkBodyStruct.ornament_icon, textLinkBodyStruct.hash ); From f1a73d4da2e0bcfefe19a0bd99cafde42a23ecda Mon Sep 17 00:00:00 2001 From: Trevius Date: Tue, 6 Jan 2015 01:19:33 -0600 Subject: [PATCH 05/10] Changed the pet command #defines to be based on RoF2 list of pet commands and added decodes to Titanium, SoF and SoD. (RoF+) The /pet focus on/off and /pet hold on/off commands are now functional. Added more toggle and on/off support for pet commands. --- changelog.txt | 4 ++ common/patches/rof.cpp | 43 +------------------ common/patches/rof2.cpp | 43 +------------------ common/patches/sod.cpp | 81 +++++++++++++++++++++++++++++++++++ common/patches/sod_ops.h | 1 + common/patches/sof.cpp | 81 +++++++++++++++++++++++++++++++++++ common/patches/sof_ops.h | 1 + common/patches/titanium.cpp | 81 +++++++++++++++++++++++++++++++++++ common/patches/titanium_ops.h | 1 + common/patches/underfoot.cpp | 53 +---------------------- zone/client_packet.cpp | 69 ++++++++++++++++++++++++----- zone/npc.h | 1 + zone/pets.h | 48 ++++++++++++--------- 13 files changed, 343 insertions(+), 164 deletions(-) diff --git a/changelog.txt b/changelog.txt index c9a9a2c3a..36e19a297 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/06/2015 == +Trevius: Changed the pet command #defines to be based on RoF2 list of pet commands and added decodes to Titanium, SoF and SoD. +Trevius: (RoF+) The /pet focus on/off and /pet hold on/off commands are now functional. + == 01/05/2015 == Uleat: Fixed (added translators for) item/text links. Only 'OP_ChannelMessage' and 'OP_SpecialMesg' are currently handled..more text channels will be added as the need arises. diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 00b76da6c..57312d6f0 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -4518,47 +4518,8 @@ namespace RoF DECODE_LENGTH_EXACT(structs::PetCommand_Struct); SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); - switch (eq->command) - { - case 0x00: - emu->command = 0x04; // Health - break; - case 0x01: - emu->command = 0x10; // Leader - break; - case 0x02: - emu->command = 0x07; // Attack - break; - case 0x04: - emu->command = 0x08; // Follow - break; - case 0x05: - emu->command = 0x05; // Guard - break; - case 0x06: - emu->command = 0x09; // Sit. Needs work. This appears to be a toggle between Sit/Stand now. - break; - case 0x0c: - emu->command = 0x0b; // Taunt - break; - case 0x0f: - emu->command = 0x0c; // Hold - break; - case 0x10: - emu->command = 0x1b; // Hold on - break; - case 0x11: - emu->command = 0x1c; // Hold off - break; - case 0x1c: - emu->command = 0x01; // Back - break; - case 0x1d: - emu->command = 0x02; // Leave/Go Away - break; - default: - emu->command = eq->command; - } + IN(command); + emu->unknown = eq->unknown04; FINISH_DIRECT_DECODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 3d23c54bc..9f93c0700 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4589,47 +4589,8 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::PetCommand_Struct); SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); - switch (eq->command) - { - case 0x00: - emu->command = 0x04; // Health - break; - case 0x01: - emu->command = 0x10; // Leader - break; - case 0x02: - emu->command = 0x07; // Attack - break; - case 0x04: - emu->command = 0x08; // Follow - break; - case 0x05: - emu->command = 0x05; // Guard - break; - case 0x06: - emu->command = 0x09; // Sit. Needs work. This appears to be a toggle between Sit/Stand now. - break; - case 0x0c: - emu->command = 0x0b; // Taunt - break; - case 0x0f: - emu->command = 0x0c; // Hold - break; - case 0x10: - emu->command = 0x1b; // Hold on - break; - case 0x11: - emu->command = 0x1c; // Hold off - break; - case 0x1c: - emu->command = 0x01; // Back - break; - case 0x1d: - emu->command = 0x02; // Leave/Go Away - break; - default: - emu->command = eq->command; - } + IN(command); + emu->unknown = eq->unknown04; FINISH_DIRECT_DECODE(); } diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 94d1cb120..a6025b287 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3105,6 +3105,87 @@ namespace SoD FINISH_DIRECT_DECODE(); } + DECODE(OP_PetCommands) + { + DECODE_LENGTH_EXACT(structs::PetCommand_Struct); + SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); + + switch (eq->command) + { + case 0x04: + emu->command = 0x00; // /pet health + break; + case 0x10: + emu->command = 0x01; // /pet leader + break; + case 0x07: + emu->command = 0x02; // /pet attack or Pet Window + break; + case 0x08: + emu->command = 0x04; // /pet follow or Pet Window + break; + case 0x05: + emu->command = 0x05; // /pet guard or Pet Window + break; + case 0x09: + emu->command = 0x07; // /pet sit or Pet Window + break; + case 0x0a: + emu->command = 0x08; // /pet stand or Pet Window + break; + case 0x06: + emu->command = 0x03; // /pet guard me + break; + case 0x03: // Case Made Up + emu->command = 0x09; // Stop? + break; + case 0x0b: + emu->command = 0x0d; // /pet taunt or Pet Window + break; + case 0x0e: + emu->command = 0x0e; // /pet notaunt or Pet Window + break; + case 0x0c: + emu->command = 0x0f; // /pet hold + break; + case 0x1b: + emu->command = 0x10; // /pet hold on + break; + case 0x1c: + emu->command = 0x11; // /pet hold off + break; + case 0x11: + emu->command = 0x12; // Slumber? + break; + case 0x12: + emu->command = 0x15; // /pet no cast + break; + case 0x0d: // Case Made Up + emu->command = 0x16; // Pet Window No Cast + break; + case 0x13: + emu->command = 0x18; // /pet focus + break; + case 0x19: + emu->command = 0x19; // /pet focus on + break; + case 0x1a: + emu->command = 0x1a; // /pet focus off + break; + case 0x01: + emu->command = 0x1c; // /pet back off + break; + case 0x02: + emu->command = 0x1d; // /pet get lost + break; + default: + emu->command = eq->command; + } + OUT(unknown); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_RaidInvite) { DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct); diff --git a/common/patches/sod_ops.h b/common/patches/sod_ops.h index e3b6c1f41..0a0a8a4d5 100644 --- a/common/patches/sod_ops.h +++ b/common/patches/sod_ops.h @@ -104,6 +104,7 @@ D(OP_ItemVerifyRequest) D(OP_LoadSpellSet) D(OP_LootItem) D(OP_MoveItem) +D(OP_PetCommands) D(OP_RaidInvite) D(OP_ReadBook) D(OP_Save) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index a75b07307..5e3dff8b1 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2443,6 +2443,87 @@ namespace SoF FINISH_DIRECT_DECODE(); } + DECODE(OP_PetCommands) + { + DECODE_LENGTH_EXACT(structs::PetCommand_Struct); + SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); + + switch (eq->command) + { + case 0x04: + emu->command = 0x00; // /pet health + break; + case 0x10: + emu->command = 0x01; // /pet leader + break; + case 0x07: + emu->command = 0x02; // /pet attack or Pet Window + break; + case 0x08: + emu->command = 0x04; // /pet follow or Pet Window + break; + case 0x05: + emu->command = 0x05; // /pet guard or Pet Window + break; + case 0x09: + emu->command = 0x07; // /pet sit or Pet Window + break; + case 0x0a: + emu->command = 0x08; // /pet stand or Pet Window + break; + case 0x06: + emu->command = 0x03; // /pet guard me + break; + case 0x03: // Case Made Up + emu->command = 0x09; // Stop? + break; + case 0x0b: + emu->command = 0x0d; // /pet taunt or Pet Window + break; + case 0x0e: + emu->command = 0x0e; // /pet notaunt or Pet Window + break; + case 0x0c: + emu->command = 0x0f; // /pet hold + break; + case 0x1b: + emu->command = 0x10; // /pet hold on + break; + case 0x1c: + emu->command = 0x11; // /pet hold off + break; + case 0x11: + emu->command = 0x12; // Slumber? + break; + case 0x12: + emu->command = 0x15; // /pet no cast + break; + case 0x0d: // Case Made Up + emu->command = 0x16; // Pet Window No Cast + break; + case 0x13: + emu->command = 0x18; // /pet focus + break; + case 0x19: + emu->command = 0x19; // /pet focus on + break; + case 0x1a: + emu->command = 0x1a; // /pet focus off + break; + case 0x01: + emu->command = 0x1c; // /pet back off + break; + case 0x02: + emu->command = 0x1d; // /pet get lost + break; + default: + emu->command = eq->command; + } + OUT(unknown); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_RaidInvite) { DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct); diff --git a/common/patches/sof_ops.h b/common/patches/sof_ops.h index 88d468c82..9cfd400e3 100644 --- a/common/patches/sof_ops.h +++ b/common/patches/sof_ops.h @@ -88,6 +88,7 @@ D(OP_ItemLinkClick) D(OP_ItemVerifyRequest) D(OP_LootItem) D(OP_MoveItem) +D(OP_PetCommands) D(OP_RaidInvite) D(OP_ReadBook) D(OP_Save) diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index e083f9561..895f2ee88 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1637,6 +1637,87 @@ namespace Titanium FINISH_DIRECT_DECODE(); } + DECODE(OP_PetCommands) + { + DECODE_LENGTH_EXACT(structs::PetCommand_Struct); + SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); + + switch (eq->command) + { + case 0x04: + emu->command = 0x00; // /pet health + break; + case 0x10: + emu->command = 0x01; // /pet leader + break; + case 0x07: + emu->command = 0x02; // /pet attack or Pet Window + break; + case 0x08: + emu->command = 0x04; // /pet follow or Pet Window + break; + case 0x05: + emu->command = 0x05; // /pet guard or Pet Window + break; + case 0x09: + emu->command = 0x07; // /pet sit or Pet Window + break; + case 0x0a: + emu->command = 0x08; // /pet stand or Pet Window + break; + case 0x06: + emu->command = 0x03; // /pet guard me + break; + case 0x03: // Case Made Up + emu->command = 0x09; // Stop? + break; + case 0x0b: + emu->command = 0x0d; // /pet taunt or Pet Window + break; + case 0x0e: + emu->command = 0x0e; // /pet notaunt or Pet Window + break; + case 0x0c: + emu->command = 0x0f; // /pet hold + break; + case 0x1b: + emu->command = 0x10; // /pet hold on + break; + case 0x1c: + emu->command = 0x11; // /pet hold off + break; + case 0x11: + emu->command = 0x12; // Slumber? + break; + case 0x12: + emu->command = 0x15; // /pet no cast + break; + case 0x0d: // Case Made Up + emu->command = 0x16; // Pet Window No Cast + break; + case 0x13: + emu->command = 0x18; // /pet focus + break; + case 0x19: + emu->command = 0x19; // /pet focus on + break; + case 0x1a: + emu->command = 0x1a; // /pet focus off + break; + case 0x01: + emu->command = 0x1c; // /pet back off + break; + case 0x02: + emu->command = 0x1d; // /pet get lost + break; + default: + emu->command = eq->command; + } + OUT(unknown); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_ReadBook) { // no apparent slot translation needed -U diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index a3d2e71af..4ddcae630 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -62,6 +62,7 @@ D(OP_ItemLinkClick) D(OP_LFGuild) D(OP_LootItem) D(OP_MoveItem) +D(OP_PetCommands) D(OP_ReadBook) D(OP_SetServerFilter) D(OP_ShopPlayerSell) diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 022c1d62c..b525a3c46 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -3425,57 +3425,8 @@ namespace Underfoot DECODE_LENGTH_EXACT(structs::PetCommand_Struct); SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); - switch (eq->command) - { - case 0x00: - emu->command = 0x04; // Health - break; - case 0x01: - emu->command = 0x10; // Leader - break; - case 0x02: - emu->command = 0x07; // Attack - break; - case 0x04: - emu->command = 0x08; // Follow - break; - case 0x05: - emu->command = 0x05; // Guard - break; - case 0x06: - emu->command = 0x09; // Sit. Needs work. This appears to be a toggle between Sit/Stand now. - break; - case 0x0c: - emu->command = 0x0b; // Taunt - break; - case 0x0f: - emu->command = 0x0c; // Hold - break; - case 0x10: - emu->command = 0x1b; // Hold on - break; - case 0x11: - emu->command = 0x1c; // Hold off - break; - case 0x1c: - emu->command = 0x01; // Back - break; - case 0x1d: - emu->command = 0x02; // Leave/Go Away - break; - case 0x15: - emu->command = 0x12; // No Cast - /command - break; - case 0x16: - emu->command = 0x12; // No Cast - Pet Window - break; - case 0x18: - emu->command = 0x13; // Focus - Pet Window - break; - default: - emu->command = eq->command; - } - OUT(unknown); + IN(command); + IN(unknown); FINISH_DIRECT_DECODE(); } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index cf1dc71b8..785abb0c8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9925,12 +9925,14 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) uint32 PetCommand = pet->command; // Handle Sit/Stand toggle in UF and later. + /* if (GetClientVersion() >= EQClientUnderfoot) { if (PetCommand == PET_SITDOWN) if (mypet->GetPetOrder() == SPO_Sit) PetCommand = PET_STANDUP; } + */ switch (PetCommand) { @@ -10036,13 +10038,28 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_TAUNT: { + if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if (mypet->CastToNPC()->IsTaunting()) + { + Message_StringID(MT_PetResponse, PET_NO_TAUNT); + mypet->CastToNPC()->SetTaunting(false); + } + else + { + Message_StringID(MT_PetResponse, PET_DO_TAUNT); + mypet->CastToNPC()->SetTaunting(true); + } + } + break; + } + case PET_TAUNT_ON: { if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { Message_StringID(MT_PetResponse, PET_DO_TAUNT); mypet->CastToNPC()->SetTaunting(true); } break; } - case PET_NOTAUNT: { + case PET_TAUNT_OFF: { if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { Message_StringID(MT_PetResponse, PET_NO_TAUNT); mypet->CastToNPC()->SetTaunting(false); @@ -10060,16 +10077,25 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } break; } - case PET_SITDOWN: { + case PET_SIT: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { - mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); - mypet->SetPetOrder(SPO_Sit); - mypet->SetRunAnimSpeed(0); - if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet - mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting - mypet->SendAppearancePacket(AT_Anim, ANIM_SIT); + if (mypet->GetPetOrder() == SPO_Sit) + { + mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); + mypet->SetPetOrder(SPO_Follow); + mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); + } + else + { + mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); + mypet->SetPetOrder(SPO_Sit); + mypet->SetRunAnimSpeed(0); + if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet + mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting + mypet->SendAppearancePacket(AT_Anim, ANIM_SIT); + } } break; } @@ -10083,6 +10109,19 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } break; } + case PET_SITDOWN: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + + if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); + mypet->SetPetOrder(SPO_Sit); + mypet->SetRunAnimSpeed(0); + if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet + mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting + mypet->SendAppearancePacket(AT_Anim, ANIM_SIT); + } + break; + } case PET_SLUMBER: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF @@ -10101,9 +10140,16 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); - mypet->WipeHateList(); - mypet->SetHeld(true); + if (mypet->IsHeld()) + { + mypet->SetHeld(false); + } + else + { + mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + mypet->WipeHateList(); + mypet->SetHeld(true); + } } break; } @@ -10123,6 +10169,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetHeld(false); break; } + case PET_NOCAST_ON: case PET_NOCAST: { if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { if (mypet->IsFeared()) diff --git a/zone/npc.h b/zone/npc.h index 72cc7f38c..e7a72ff11 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -266,6 +266,7 @@ public: void SetPetSpellID(uint16 amt) {pet_spell_id = amt;} uint32 GetMaxDamage(uint8 tlevel); void SetTaunting(bool tog) {taunting = tog;} + bool IsTaunting() const { return taunting; } void PickPocket(Client* thief); void StartSwarmTimer(uint32 duration) { swarm_timer.Start(duration); } void AddLootDrop(const Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); diff --git a/zone/pets.h b/zone/pets.h index db78accea..243807502 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -1,26 +1,34 @@ #ifndef PETS_H #define PETS_H -#define PET_BACKOFF 1 -#define PET_GETLOST 2 -#define PET_HEALTHREPORT 4 -#define PET_GUARDHERE 5 -#define PET_GUARDME 6 -#define PET_ATTACK 7 -#define PET_FOLLOWME 8 -#define PET_SITDOWN 9 -#define PET_STANDUP 10 -#define PET_TAUNT 11 -#define PET_HOLD 12 -#define PET_NOTAUNT 14 -#define PET_LEADER 16 -#define PET_SLUMBER 17 -#define PET_NOCAST 18 -#define PET_FOCUS 19 -#define PET_FOCUS_ON 25 -#define PET_FOCUS_OFF 26 -#define PET_HOLD_ON 27 -#define PET_HOLD_OFF 28 +// Defines based on the RoF2 Client +#define PET_HEALTHREPORT 0 // 0x00 - /pet health +#define PET_LEADER 1 // 0x01 - /pet leader +#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window +#define PET_GUARDME 3 // 0x03 - No longer exists? - define not from client +#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window +#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window +#define PET_SIT 6 // 0x06 - /pet sit or Pet Window +#define PET_SITDOWN 7 // 0x07 - /pet sit on +#define PET_STANDUP 8 // 0x08 - /pet sit off +#define PET_STOP 9 // 0x09 - Not implemented? + // Guessing 10 and 11 are PET_STOP_ON and PET_STOP_OFF +#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window +#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on +#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off +#define PET_HOLD 15 // 0x0f - /pet hold +#define PET_HOLD_ON 16 // 0x10 - /pet hold on +#define PET_HOLD_OFF 17 // 0x11 - /pet hold off +#define PET_SLUMBER 18 // 0x12 - What is this? - define not from client + // Guessing 19 and 20 are PET_SLUMBER_ON and PET_SLUMBER_OFF +#define PET_NOCAST 21 // 0x15 - /pet no cast +#define PET_NOCAST_ON 22 // 0x16 - Pet Window No Cast +#define PET_NOCAST_OFF 23 // 0x17 - Guessed +#define PET_FOCUS 24 // 0x18 - /pet focus +#define PET_FOCUS_ON 25 // 0x19 - /pet focus on +#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off +#define PET_BACKOFF 28 // 0x1c - /pet back off +#define PET_GETLOST 29 // 0x1d - /pet get lost class Mob; struct NPCType; From cde406a49656a791f12bb6dbfad9caeaaef794a0 Mon Sep 17 00:00:00 2001 From: JJ Date: Tue, 6 Jan 2015 13:51:36 -0500 Subject: [PATCH 06/10] Add PhR to #showstats and a few places that can/should be implemented in the future. --- zone/client.cpp | 13 +++++++++---- zone/client.h | 3 +++ zone/lua_mob.cpp | 5 +++++ zone/lua_mob.h | 1 + zone/mob.cpp | 2 +- zone/mob.h | 2 +- zone/perl_mob.cpp | 26 ++++++++++++++++++++++++++ 7 files changed, 46 insertions(+), 6 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index c8bbd25cf..143b9271a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -6255,6 +6255,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->DR = GetDR(); made_npc->PR = GetPR(); made_npc->Corrup = GetCorrup(); + made_npc->PhR = GetPhR(); // looks made_npc->texture = GetEquipmentMaterial(MaterialChest); made_npc->helmtexture = GetEquipmentMaterial(MaterialHead); @@ -6352,7 +6353,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) // Set Class std::string class_Name = itoa(GetClass()); - std::string class_List[] = { "WAR", "CLR", "PAL", "RNG", "SK", "DRU", "MNK", "BRD", "ROG", "SHM", "NEC", "WIZ", "MAG", "ENC", "BST", "BER" }; + std::string class_List[] = { "WAR", "CLR", "PAL", "RNG", "SHD", "DRU", "MNK", "BRD", "ROG", "SHM", "NEC", "WIZ", "MAG", "ENC", "BST", "BER" }; if(GetClass() < 17 && GetClass() > 0) { class_Name = class_List[GetClass()-1]; } @@ -6440,7 +6441,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) /*===========================*/ std::string regen_row_header = ""; std::string regen_row_color = ""; - std::string base_regen_field = ""; + std::string base_regen_field = ""; std::string base_regen_spacing = ""; std::string item_regen_field = ""; std::string item_regen_spacing = ""; @@ -6601,8 +6602,11 @@ void Client::SendStatsWindow(Client* client, bool use_window) } case 6: { a_stat_name = " CHA: "; + a_resist_name = "PhR: "; // Not implemented for clients yet a_stat = itoa(GetCHA()); h_stat = itoa(GetHeroicCHA()); + a_resist = itoa(GetPhR()); + h_resist_field = itoa(GetHeroicPhR()); break; } default: { break; } @@ -6617,8 +6621,9 @@ void Client::SendStatsWindow(Client* client, bool use_window) for(int h = a_resist.size(); h < max_stat_value_len; h++) { a_resist_spacing += " . "; } stat_field += indP + a_stat_name + a_stat_spacing + a_stat + heroic_color + h_stat + ""; + stat_field += h_stat_spacing + a_resist_name + a_resist_spacing + a_resist + heroic_color + h_resist_field + ""; if(stat_row_counter < 6) { - stat_field += h_stat_spacing + a_resist_name + a_resist_spacing + a_resist + heroic_color + h_resist_field + "
"; + stat_field += "
"; } } /*########################################################## @@ -6827,7 +6832,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) client->Message(0, " Haste: %i / %i (Item: %i + Spell: %i + Over: %i)", GetHaste(), RuleI(Character, HasteCap), itembonuses.haste, spellbonuses.haste + spellbonuses.hastetype2, spellbonuses.hastetype3 + ExtraHaste); client->Message(0, " STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); client->Message(0, " hSTR: %i hSTA: %i hDEX: %i hAGI: %i hINT: %i hWIS: %i hCHA: %i", GetHeroicSTR(), GetHeroicSTA(), GetHeroicDEX(), GetHeroicAGI(), GetHeroicINT(), GetHeroicWIS(), GetHeroicCHA()); - client->Message(0, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup()); + client->Message(0, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i PhR: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup(), GetPhR()); client->Message(0, " hMR: %i hPR: %i hFR: %i hCR: %i hDR: %i hCorruption: %i", GetHeroicMR(), GetHeroicPR(), GetHeroicFR(), GetHeroicCR(), GetHeroicDR(), GetHeroicCorrup()); client->Message(0, " Shielding: %i Spell Shield: %i DoT Shielding: %i Stun Resist: %i Strikethrough: %i Avoidance: %i Accuracy: %i Combat Effects: %i", GetShielding(), GetSpellShield(), GetDoTShield(), GetStunResist(), GetStrikeThrough(), GetAvoidance(), GetAccuracy(), GetCombatEffects()); client->Message(0, " Heal Amt.: %i Spell Dmg.: %i Clairvoyance: %i DS Mitigation: %i", GetHealAmt(), GetSpellDmg(), GetClair(), GetDSMit()); diff --git a/zone/client.h b/zone/client.h index d6ef83523..fd88848fa 100644 --- a/zone/client.h +++ b/zone/client.h @@ -428,6 +428,7 @@ public: inline virtual int32 GetPR() const { return PR; } inline virtual int32 GetCR() const { return CR; } inline virtual int32 GetCorrup() const { return Corrup; } + inline virtual int32 GetPhR() const { return PhR; } int32 GetMaxStat() const; int32 GetMaxResist() const; @@ -452,6 +453,7 @@ public: inline uint8 GetBaseAGI() const { return m_pp.AGI; } inline uint8 GetBaseWIS() const { return m_pp.WIS; } inline uint8 GetBaseCorrup() const { return 15; } // Same for all + inline uint8 GetBasePhR() const { return 0; } // Guessing at 0 as base inline virtual int32 GetHeroicSTR() const { return itembonuses.HeroicSTR; } inline virtual int32 GetHeroicSTA() const { return itembonuses.HeroicSTA; } @@ -466,6 +468,7 @@ public: inline virtual int32 GetHeroicPR() const { return itembonuses.HeroicPR; } inline virtual int32 GetHeroicCR() const { return itembonuses.HeroicCR; } inline virtual int32 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; } + inline virtual int32 GetHeroicPhR() const { return 0; } // Heroic PhR not implemented yet // Mod2 inline virtual int32 GetShielding() const { return itembonuses.MeleeMitigation; } inline virtual int32 GetSpellShield() const { return itembonuses.SpellShield; } diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 92afdd8b3..b65cda254 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -576,6 +576,11 @@ int Lua_Mob::GetCorruption() { return self->GetCorrup(); } +int Lua_Mob::GetPhR() { + Lua_Safe_Call_Int(); + return self->GetPhR(); +} + int Lua_Mob::GetMaxSTR() { Lua_Safe_Call_Int(); return self->GetMaxSTR(); diff --git a/zone/lua_mob.h b/zone/lua_mob.h index a5c00c5f0..f272cd440 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -128,6 +128,7 @@ public: int GetPR(); int GetCR(); int GetCorruption(); + int GetPhR(); int GetMaxSTR(); int GetMaxSTA(); int GetMaxDEX(); diff --git a/zone/mob.cpp b/zone/mob.cpp index 79391de5c..3ea572eb6 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1296,7 +1296,7 @@ void Mob::ShowStats(Client* client) client->Message(0, " Mana: %i Max Mana: %i", GetMana(), GetMaxMana()); client->Message(0, " Total ATK: %i Worn/Spell ATK (Cap %i): %i", GetATK(), RuleI(Character, ItemATKCap), GetATKBonus()); client->Message(0, " STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); - client->Message(0, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup()); + client->Message(0, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i PhR: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup(), GetPhR()); client->Message(0, " Race: %i BaseRace: %i Texture: %i HelmTexture: %i Gender: %i BaseGender: %i", GetRace(), GetBaseRace(), GetTexture(), GetHelmTexture(), GetGender(), GetBaseGender()); if (client->Admin() >= 100) client->Message(0, " EntityID: %i PetID: %i OwnerID: %i AIControlled: %i Targetted: %i", GetID(), GetPetID(), GetOwnerID(), IsAIControlled(), targeted); diff --git a/zone/mob.h b/zone/mob.h index 47d2cca2f..5997ffeae 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -371,7 +371,7 @@ public: inline virtual int32 GetPR() const { return PR + itembonuses.PR + spellbonuses.PR; } inline virtual int32 GetCR() const { return CR + itembonuses.CR + spellbonuses.CR; } inline virtual int32 GetCorrup() const { return Corrup + itembonuses.Corrup + spellbonuses.Corrup; } - inline virtual int32 GetPhR() const { return PhR; } + inline virtual int32 GetPhR() const { return PhR; } // PhR bonuses not implemented yet inline StatBonuses GetItemBonuses() const { return itembonuses; } inline StatBonuses GetSpellBonuses() const { return spellbonuses; } inline StatBonuses GetAABonuses() const { return aabonuses; } diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 7977c3dd1..633139704 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -2933,6 +2933,32 @@ XS(XS_Mob_GetCorruption) XSRETURN(1); } +XS(XS_Mob_GetPhR); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_GetPhR) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::GetPhR(THIS)"); + { + Mob * THIS; + int32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "Mob")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Mob *, tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Mob"); + if (THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetPhR(); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + XS(XS_Mob_GetMaxSTR); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_GetMaxSTR) { From 364f2f6bf81ec24e54fca24d9cff6845a3979378 Mon Sep 17 00:00:00 2001 From: JJ Date: Tue, 6 Jan 2015 15:09:18 -0500 Subject: [PATCH 07/10] Forgot prototype declaration from previous commit. Also fix corruption declaration. --- zone/perl_mob.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 633139704..af07cfcdf 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -8488,7 +8488,8 @@ XS(boot_Mob) newXSproto(strcpy(buf, "GetDR"), XS_Mob_GetDR, file, "$"); newXSproto(strcpy(buf, "GetPR"), XS_Mob_GetPR, file, "$"); newXSproto(strcpy(buf, "GetCR"), XS_Mob_GetCR, file, "$"); - newXSproto(strcpy(buf, "GetCorruption"), XS_Mob_GetCR, file, "$"); + newXSproto(strcpy(buf, "GetCorruption"), XS_Mob_GetCorruption, file, "$"); + newXSproto(strcpy(buf, "GetPhR"), XS_Mob_GetPhR, file, "$"); newXSproto(strcpy(buf, "GetMaxSTR"), XS_Mob_GetMaxSTR, file, "$"); newXSproto(strcpy(buf, "GetMaxSTA"), XS_Mob_GetMaxSTA, file, "$"); newXSproto(strcpy(buf, "GetMaxDEX"), XS_Mob_GetMaxDEX, file, "$"); From 671701460176ea19962e5411ca13ddc296947b5c Mon Sep 17 00:00:00 2001 From: JJ Date: Tue, 6 Jan 2015 16:10:29 -0500 Subject: [PATCH 08/10] Lua declaration as well... --- zone/lua_mob.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index b65cda254..26bb08f0a 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1967,6 +1967,7 @@ luabind::scope lua_register_mob() { .def("GetPR", &Lua_Mob::GetPR) .def("GetCR", &Lua_Mob::GetCR) .def("GetCorruption", &Lua_Mob::GetCorruption) + .def("GetPhR", &Lua_Mob::GetPhR) .def("GetMaxSTR", &Lua_Mob::GetMaxSTR) .def("GetMaxSTA", &Lua_Mob::GetMaxSTA) .def("GetMaxDEX", &Lua_Mob::GetMaxDEX) From 2c43e6f68dab213b8b11c10bbf9ec63e9670eac2 Mon Sep 17 00:00:00 2001 From: Trevius Date: Tue, 6 Jan 2015 19:14:06 -0600 Subject: [PATCH 09/10] Added defines for all remaining pet commands and some support for them as well. --- changelog.txt | 1 + common/patches/sod.cpp | 8 ++-- common/patches/sof.cpp | 6 ++- common/patches/titanium.cpp | 6 ++- zone/client_packet.cpp | 75 ++++++++++++++++++++++++++++++++++++- zone/pets.h | 27 +++++++------ 6 files changed, 102 insertions(+), 21 deletions(-) diff --git a/changelog.txt b/changelog.txt index 36e19a297..1b5483e73 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 01/06/2015 == Trevius: Changed the pet command #defines to be based on RoF2 list of pet commands and added decodes to Titanium, SoF and SoD. Trevius: (RoF+) The /pet focus on/off and /pet hold on/off commands are now functional. +Trevius: Added defines for all remaining pet commands and some support for them as well. == 01/05/2015 == Uleat: Fixed (added translators for) item/text links. Only 'OP_ChannelMessage' and 'OP_SpecialMesg' are currently handled..more text channels will be added as the need arises. diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index a6025b287..910a094d4 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3121,6 +3121,8 @@ namespace SoD case 0x07: emu->command = 0x02; // /pet attack or Pet Window break; + case 0x03: // Case Guessed + emu->command = 0x03; // /pet qattack case 0x08: emu->command = 0x04; // /pet follow or Pet Window break; @@ -3134,10 +3136,10 @@ namespace SoD emu->command = 0x08; // /pet stand or Pet Window break; case 0x06: - emu->command = 0x03; // /pet guard me + emu->command = 0x1e; // /pet guard me break; - case 0x03: // Case Made Up - emu->command = 0x09; // Stop? + case 0x0f: // Case Made Up + emu->command = 0x09; // /pet stop break; case 0x0b: emu->command = 0x0d; // /pet taunt or Pet Window diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 5e3dff8b1..70fb34597 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2459,6 +2459,8 @@ namespace SoF case 0x07: emu->command = 0x02; // /pet attack or Pet Window break; + case 0x03: // Case Guessed + emu->command = 0x03; // /pet qattack case 0x08: emu->command = 0x04; // /pet follow or Pet Window break; @@ -2472,9 +2474,9 @@ namespace SoF emu->command = 0x08; // /pet stand or Pet Window break; case 0x06: - emu->command = 0x03; // /pet guard me + emu->command = 0x1e; // /pet guard me break; - case 0x03: // Case Made Up + case 0x0f: // Case Made Up emu->command = 0x09; // Stop? break; case 0x0b: diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 895f2ee88..eef600795 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1653,6 +1653,8 @@ namespace Titanium case 0x07: emu->command = 0x02; // /pet attack or Pet Window break; + case 0x03: // Case Guessed + emu->command = 0x03; // /pet qattack case 0x08: emu->command = 0x04; // /pet follow or Pet Window break; @@ -1666,9 +1668,9 @@ namespace Titanium emu->command = 0x08; // /pet stand or Pet Window break; case 0x06: - emu->command = 0x03; // /pet guard me + emu->command = 0x1e; // /pet guard me break; - case 0x03: // Case Made Up + case 0x0f: // Case Made Up emu->command = 0x09; // Stop? break; case 0x0b: diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 785abb0c8..c9ec08b30 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9970,6 +9970,31 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } break; } + case PET_QATTACK: { + if (mypet->IsFeared()) + break; //prevent pet from attacking stuff while feared + + if (!GetTarget()) + break; + if (GetTarget()->IsMezzed()) { + Message_StringID(10, CANNOT_WAKE, mypet->GetCleanName(), GetTarget()->GetCleanName()); + break; + } + + if (!mypet->IsAttackAllowed(GetTarget())) { + mypet->Say_StringID(NOT_LEGAL_TARGET); + break; + } + + if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) { + if (GetTarget() != this && mypet->DistNoRootNoZ(*GetTarget()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { + zone->AddAggroMob(); + mypet->AddToHateList(GetTarget(), 1); + Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), GetTarget()->GetCleanName()); + } + } + break; + } case PET_BACKOFF: { if (mypet->IsFeared()) break; //keeps pet running while feared @@ -10126,6 +10151,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF if (mypet->GetPetType() != petAnimation) { + // Needs to have an IsSleeping() check added and this case should toggle on/off mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); mypet->SetPetOrder(SPO_Sit); mypet->SetRunAnimSpeed(0); @@ -10135,6 +10161,30 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } break; } + case PET_SLUMBER_ON: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + + if (mypet->GetPetType() != petAnimation) { + mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); + mypet->SetPetOrder(SPO_Sit); + mypet->SetRunAnimSpeed(0); + if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet + mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting + mypet->SendAppearancePacket(AT_Anim, ANIM_DEATH); + } + break; + } + case PET_SLUMBER_OFF: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + + if (mypet->GetPetType() != petAnimation) { + mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); + mypet->SetPetOrder(SPO_Follow); + mypet->SetRunAnimSpeed(mypet->GetBaseRunspeed()); + mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); + } + break; + } case PET_HOLD: { if (GetAA(aaPetDiscipline) && mypet->IsNPC()){ if (mypet->IsFeared()) @@ -10169,8 +10219,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetHeld(false); break; } - case PET_NOCAST_ON: - case PET_NOCAST: { + case PET_SPELLHOLD: { if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { if (mypet->IsFeared()) break; @@ -10185,6 +10234,28 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } break; } + case PET_SPELLHOLD_ON: { + if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { + if (mypet->IsFeared()) + break; + if (!mypet->IsNoCast()) { + Message_StringID(MT_PetResponse, PET_NOT_CASTING); + mypet->CastToNPC()->SetNoCast(true); + } + } + break; + } + case PET_SPELLHOLD_OFF: { + if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { + if (mypet->IsFeared()) + break; + if (mypet->IsNoCast()) { + Message_StringID(MT_PetResponse, PET_CASTING); + mypet->CastToNPC()->SetNoCast(false); + } + } + break; + } case PET_FOCUS: { if (GetAA(aaAdvancedPetDiscipline) >= 1 && mypet->IsNPC()) { if (mypet->IsFeared()) diff --git a/zone/pets.h b/zone/pets.h index 243807502..f0c71fbe7 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -2,33 +2,36 @@ #define PETS_H // Defines based on the RoF2 Client -#define PET_HEALTHREPORT 0 // 0x00 - /pet health -#define PET_LEADER 1 // 0x01 - /pet leader +#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window +#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window #define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window -#define PET_GUARDME 3 // 0x03 - No longer exists? - define not from client +#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window #define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window #define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window #define PET_SIT 6 // 0x06 - /pet sit or Pet Window #define PET_SITDOWN 7 // 0x07 - /pet sit on #define PET_STANDUP 8 // 0x08 - /pet sit off -#define PET_STOP 9 // 0x09 - Not implemented? - // Guessing 10 and 11 are PET_STOP_ON and PET_STOP_OFF +#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented +#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented +#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented #define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window #define PET_TAUNT_ON 13 // 0x0d - /pet taunt on #define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off -#define PET_HOLD 15 // 0x0f - /pet hold +#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window #define PET_HOLD_ON 16 // 0x10 - /pet hold on #define PET_HOLD_OFF 17 // 0x11 - /pet hold off -#define PET_SLUMBER 18 // 0x12 - What is this? - define not from client - // Guessing 19 and 20 are PET_SLUMBER_ON and PET_SLUMBER_OFF -#define PET_NOCAST 21 // 0x15 - /pet no cast -#define PET_NOCAST_ON 22 // 0x16 - Pet Window No Cast -#define PET_NOCAST_OFF 23 // 0x17 - Guessed -#define PET_FOCUS 24 // 0x18 - /pet focus +#define PET_SLUMBER 18 // 0x12 - What activates this? - define guessed +#define PET_SLUMBER_ON 19 // 0x13 - What activates this? - define guessed +#define PET_SLUMBER_OFF 20 // 0x14 - What activates this? - define guessed +#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window +#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on +#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off +#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window #define PET_FOCUS_ON 25 // 0x19 - /pet focus on #define PET_FOCUS_OFF 26 // 0x1a - /pet focus off #define PET_BACKOFF 28 // 0x1c - /pet back off #define PET_GETLOST 29 // 0x1d - /pet get lost +#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client class Mob; struct NPCType; From b27737bfcdf69dcb7323a71b34c229d4948f43d0 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 6 Jan 2015 23:19:41 -0500 Subject: [PATCH 10/10] Rework of the text link translator code (Known bug with broadcast message link size not in OP_ChannelMessage or OP_SpecialMesg) --- common/eq_packet_structs.h | 27 +-- common/patches/rof.cpp | 364 +++-------------------------- common/patches/rof2.cpp | 357 +++------------------------- common/patches/rof2_structs.h | 18 -- common/patches/rof_structs.h | 18 -- common/patches/sod.cpp | 364 ++++------------------------- common/patches/sod_structs.h | 17 -- common/patches/sof.cpp | 364 ++++------------------------- common/patches/sof_structs.h | 17 -- common/patches/titanium.cpp | 363 ++++------------------------ common/patches/titanium_structs.h | 16 -- common/patches/underfoot.cpp | 364 ++++------------------------- common/patches/underfoot_structs.h | 17 -- zone/client.cpp | 128 +++++----- zone/client.h | 3 +- 15 files changed, 304 insertions(+), 2133 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 2c38b5bb0..0c91d96f8 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -5270,19 +5270,20 @@ struct ClientMarqueeMessage_Struct { typedef std::list ItemList; 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; + // Current server mask: EQClientRoF2 + uint8 unknown_1; /* %1X */ + uint32 item_id; /* %05X */ + uint32 augment_1; /* %05X */ + uint32 augment_2; /* %05X */ + uint32 augment_3; /* %05X */ + uint32 augment_4; /* %05X */ + uint32 augment_5; /* %05X */ + uint32 augment_6; /* %05X */ + uint8 is_evolving; /* %1X */ + uint32 evolve_group; /* %05X */ + uint8 evolve_level; /* %02X */ + uint32 ornament_icon; /* %05X */ + int hash; /* %08X */ }; // Restore structure packing to default diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 57312d6f0..f65302c36 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -33,17 +33,11 @@ namespace RoF static inline uint32 RoFToServerMainInvSlot(structs::MainInvItemSlotStruct RoFSlot); static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse); - // server to client text link converters - static inline void ServerToRoFTextLinks(std::string& rofTextLink, const std::string& serverTextLink); - static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); - static inline void ServerToRoFTextLinkBodyStruct(structs::TextLinkBody_Struct& rofLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); - static inline bool GenerateRoFTextLinkBody(std::string& rofLinkBody, const structs::TextLinkBody_Struct& rofLinkBodyStruct); + // server to client text link converter + static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink); - // client to server text link converters - static inline void RoFToServerTextLinks(std::string& serverTextLink, const std::string& rofTextLink); - static inline bool DegenerateRoFTextLinkBody(structs::TextLinkBody_Struct& rofLinkBodyStruct, const std::string& rofLinkBody); - static inline void RoFToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& rofLinkBodyStruct); - static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + // client to server text link converter + static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink); void Register(EQStreamIdentifier &into) { @@ -502,7 +496,7 @@ namespace RoF std::string old_message = emu->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) + strlen(emu->targetname) + new_message.length() + 39; @@ -3125,7 +3119,7 @@ namespace RoF std::string old_message = &emu->message[strlen(emu->sayer)]; 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 = 25 + strlen(emu->sayer) + new_message.length(); @@ -4099,7 +4093,7 @@ namespace RoF std::string old_message = InBuffer; 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) + new_message.length() + 1; @@ -5651,361 +5645,77 @@ namespace RoF 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; - -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(Server->RoF): old message '%s'", serverTextLink.c_str()); - - if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF): link size equal, no conversion necessary"); - rofTextLink = serverTextLink; - return; - } - - if (serverTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF): delimiter not found, no conversion necessary"); - rofTextLink = serverTextLink; - return; - } - bool conversion_error = false; - auto segments = SplitString(serverTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->RoF): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - } - - structs::TextLinkBody_Struct new_body_data; - ServerToRoFTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateRoFTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->RoF): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF): conversion error"); - rofTextLink = serverTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - rofTextLink.push_back(delimiter); - rofTextLink.append(segments[iter].c_str()); - rofTextLink.push_back(delimiter); - } - else { - rofTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->RoF): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->RoF): new message '%s'", rofTextLink.c_str()); -#else if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { rofTextLink = serverTextLink; return; } - bool conversion_error = false; auto segments = SplitString(serverTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - structs::TextLinkBody_Struct new_body_data; - ServerToRoFTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source) + // 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; - 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(); - } - } + new_segment.append(segments[segment_iter].substr(0, 41).c_str()); - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF): conversion error"); - rofTextLink = serverTextLink; - return; - } + if (segments[segment_iter].substr(41, 1) == "0") + new_segment.append(segments[segment_iter].substr(42, 1).c_str()); + else + 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.append(segments[iter].c_str()); + rofTextLink.append(new_segment.c_str()); rofTextLink.push_back(delimiter); } 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) - { - 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) + static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink) { const char delimiter = 0x12; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(RoF->Server): old message '%s'", rofTextLink.c_str()); - - if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(RoF->Server): link size equal, no conversion necessary"); - serverTextLink = rofTextLink; - return; - } - - if (rofTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(RoF->Server): delimiter not found, no conversion necessary"); - serverTextLink = rofTextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(rofTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateRoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(RoF->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(RoF->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - } - - TextLinkBody_Struct new_body_data; - RoFToServerTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateServerTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(RoF->Server): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(RoF->Server): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(RoF->Server): conversion error"); - serverTextLink = rofTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - serverTextLink.push_back(delimiter); - serverTextLink.append(segments[iter].c_str()); - serverTextLink.push_back(delimiter); - } - else { - serverTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(RoF->Server): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(RoF->Server): new message '%s'", serverTextLink.c_str()); -#else if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find(delimiter) == std::string::npos)) { serverTextLink = rofTextLink; return; } - bool conversion_error = false; auto segments = SplitString(rofTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateRoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - TextLinkBody_Struct new_body_data; - RoFToServerTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 36 37 41 42 47 (Source) + // 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; - 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(); - } - } + new_segment.append(segments[segment_iter].substr(0, 41).c_str()); + new_segment.append("0"); + new_segment.append(segments[segment_iter].substr(41).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.append(new_segment.c_str()); serverTextLink.push_back(delimiter); } 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 diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 9f93c0700..03d919dd8 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -33,17 +33,11 @@ namespace RoF2 static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct RoF2Slot); static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse); - // server to client text link converters - static inline void ServerToRoF2TextLinks(std::string& rof2TextLink, const std::string& serverTextLink); - static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); - static inline void ServerToRoF2TextLinkBodyStruct(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); - static inline bool GenerateRoF2TextLinkBody(std::string& rof2LinkBody, const structs::TextLinkBody_Struct& rof2LinkBodyStruct); + // server to client text link converter + static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink); - // client to server text link converters - static inline void RoF2ToServerTextLinks(std::string& serverTextLink, const std::string& rof2TextLink); - static inline bool DegenerateRoF2TextLinkBody(structs::TextLinkBody_Struct& rof2LinkBodyStruct, const std::string& rof2LinkBody); - static inline void RoF2ToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& rof2LinkBodyStruct); - static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + // client to server text link converter + static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink); void Register(EQStreamIdentifier &into) { @@ -568,7 +562,7 @@ namespace RoF2 std::string old_message = emu->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) + strlen(emu->targetname) + new_message.length() + 39; @@ -3191,7 +3185,7 @@ namespace RoF2 std::string old_message = &emu->message[strlen(emu->sayer)]; 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 = 25 + strlen(emu->sayer) + new_message.length(); @@ -4171,7 +4165,7 @@ namespace RoF2 std::string old_message = InBuffer; 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) + new_message.length() + 1; @@ -5746,361 +5740,68 @@ namespace RoF2 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; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(Server->RoF2): old message '%s'", serverTextLink.c_str()); - - if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF2): link size equal, no conversion necessary"); - rof2TextLink = serverTextLink; - return; - } - - if (serverTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF2): delimiter not found, no conversion necessary"); - rof2TextLink = serverTextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(serverTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF2): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->RoF2): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - } - - structs::TextLinkBody_Struct new_body_data; - ServerToRoF2TextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateRoF2TextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF2): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->RoF2): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->RoF2): conversion error"); - rof2TextLink = serverTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - rof2TextLink.push_back(delimiter); - rof2TextLink.append(segments[iter].c_str()); - rof2TextLink.push_back(delimiter); - } - else { - rof2TextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->RoF2): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->RoF2): new message '%s'", rof2TextLink.c_str()); -#else if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { rof2TextLink = serverTextLink; return; } - bool conversion_error = false; auto segments = SplitString(serverTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - structs::TextLinkBody_Struct new_body_data; - ServerToRoF2TextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source) + // 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; - 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(); - } - } + new_segment.append(segments[segment_iter]); - 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.append(new_segment.c_str()); rof2TextLink.push_back(delimiter); } 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) - { - 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) + static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink) { const char delimiter = 0x12; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(RoF2->Server): old message '%s'", rof2TextLink.c_str()); - - if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(RoF2->Server): link size equal, no conversion necessary"); - serverTextLink = rof2TextLink; - return; - } - - if (rof2TextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(RoF2->Server): delimiter not found, no conversion necessary"); - serverTextLink = rof2TextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(rof2TextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateRoF2TextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(RoF2->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(RoF2->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - } - - TextLinkBody_Struct new_body_data; - RoF2ToServerTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateServerTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(RoF2->Server): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(RoF2->Server): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(RoF2->Server): conversion error"); - serverTextLink = rof2TextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - serverTextLink.push_back(delimiter); - serverTextLink.append(segments[iter].c_str()); - serverTextLink.push_back(delimiter); - } - else { - serverTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(RoF2->Server): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(RoF2->Server): new message '%s'", serverTextLink.c_str()); -#else if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find(delimiter) == std::string::npos)) { serverTextLink = rof2TextLink; return; } - bool conversion_error = false; auto segments = SplitString(rof2TextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateRoF2TextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - TextLinkBody_Struct new_body_data; - RoF2ToServerTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source) + // 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; - 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(); - } - } + new_segment.append(segments[segment_iter]); - 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.append(new_segment.c_str()); serverTextLink.push_back(delimiter); } 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 diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 0b2de35ab..9ba71574c 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4872,24 +4872,6 @@ struct MercenaryMerchantResponse_Struct { /*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 RoF2 diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index c5f02dc9b..fb2f09615 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4894,24 +4894,6 @@ struct MercenaryMerchantResponse_Struct { /*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 RoF diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 910a094d4..6982290c8 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -31,17 +31,11 @@ namespace SoD static inline uint32 SoDToServerSlot(uint32 SoDSlot); static inline uint32 SoDToServerCorpseSlot(uint32 SoDCorpse); - // server to client text link converters - static inline void ServerToSoDTextLinks(std::string& sodTextLink, const std::string& serverTextLink); - static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); - static inline void ServerToSoDTextLinkBodyStruct(structs::TextLinkBody_Struct& sodLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); - static inline bool GenerateSoDTextLinkBody(std::string& sodLinkBody, const structs::TextLinkBody_Struct& sodLinkBodyStruct); + // server to client text link converter + static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink); - // client to server text link converters - static inline void SoDToServerTextLinks(std::string& serverTextLink, const std::string& sodTextLink); - static inline bool DegenerateSoDTextLinkBody(structs::TextLinkBody_Struct& sodLinkBodyStruct, const std::string& sodLinkBody); - static inline void SoDToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& sodLinkBodyStruct); - static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + // client to server text link converter + static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink); void Register(EQStreamIdentifier &into) { @@ -319,7 +313,7 @@ namespace SoD std::string old_message = emu->message; std::string new_message; - ServerToSoDTextLinks(new_message, old_message); + ServerToSoDTextLink(new_message, old_message); 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 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 = 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 new_message; - SoDToServerTextLinks(new_message, old_message); + SoDToServerTextLink(new_message, old_message); __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; __packet->pBuffer = new unsigned char[__packet->size]; @@ -3865,358 +3859,80 @@ namespace SoD 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; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(Server->SoD): old message '%s'", serverTextLink.c_str()); - - if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(Server->SoD): link size equal, no conversion necessary"); - sodTextLink = serverTextLink; - return; - } - - if (serverTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(Server->SoD): delimiter not found, no conversion necessary"); - sodTextLink = serverTextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(serverTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(Server->SoD): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->SoD): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - } - - structs::TextLinkBody_Struct new_body_data; - ServerToSoDTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateSoDTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(Server->SoD): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->SoD): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->SoD): conversion error"); - sodTextLink = serverTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - sodTextLink.push_back(delimiter); - sodTextLink.append(segments[iter].c_str()); - sodTextLink.push_back(delimiter); - } - else { - sodTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->SoD): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->SoD): new message '%s'", sodTextLink.c_str()); -#else if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { sodTextLink = serverTextLink; return; } - bool conversion_error = false; auto segments = SplitString(serverTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - structs::TextLinkBody_Struct new_body_data; - ServerToSoDTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source) + // 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; - if (!GenerateSoDTextLinkBody(segment, new_body_data)) { - conversion_error = true; - break; - } - else { - segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } + new_segment.append(segments[segment_iter].substr(0, 31).c_str()); + new_segment.append(segments[segment_iter].substr(36, 5).c_str()); - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->SoD): conversion error"); - sodTextLink = serverTextLink; - return; - } + if (segments[segment_iter].substr(41, 1) == "0") + new_segment.append(segments[segment_iter].substr(42, 1).c_str()); + else + 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.append(segments[iter].c_str()); + sodTextLink.append(new_segment.c_str()); sodTextLink.push_back(delimiter); } 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) - { - 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) + static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink) { const char delimiter = 0x12; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(SoD->Server): old message '%s'", sodTextLink.c_str()); - - if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(SoD->Server): link size equal, no conversion necessary"); - serverTextLink = sodTextLink; - return; - } - - if (sodTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(SoD->Server): delimiter not found, no conversion necessary"); - serverTextLink = sodTextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(sodTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateSoDTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(SoD->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(SoD->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - } - - TextLinkBody_Struct new_body_data; - SoDToServerTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateServerTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(SoD->Server): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(SoD->Server): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(SoD->Server): conversion error"); - serverTextLink = sodTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - serverTextLink.push_back(delimiter); - serverTextLink.append(segments[iter].c_str()); - serverTextLink.push_back(delimiter); - } - else { - serverTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(SoD->Server): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(SoD->Server): new message '%s'", serverTextLink.c_str()); -#else if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find(delimiter) == std::string::npos)) { serverTextLink = sodTextLink; return; } - bool conversion_error = false; auto segments = SplitString(sodTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateSoDTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - TextLinkBody_Struct new_body_data; - SoDToServerTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 32 36 37 42 (Source) + // 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; - 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(); - } - } + new_segment.append(segments[segment_iter].substr(0, 31).c_str()); + new_segment.append("00000"); + new_segment.append(segments[segment_iter].substr(31, 5).c_str()); + new_segment.append("0"); + new_segment.append(segments[segment_iter].substr(36).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.append(new_segment.c_str()); serverTextLink.push_back(delimiter); } 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 diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 39f81b7c1..24ed9c7cc 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -4409,23 +4409,6 @@ struct MercenaryAssign_Struct { /*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 SoD diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 70fb34597..8405f9def 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -31,17 +31,11 @@ namespace SoF static inline uint32 SoFToServerSlot(uint32 SoFSlot); static inline uint32 SoFToServerCorpseSlot(uint32 SoFCorpse); - // server to client text link converters - static inline void ServerToSoFTextLinks(std::string& sofTextLink, const std::string& serverTextLink); - static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); - static inline void ServerToSoFTextLinkBodyStruct(structs::TextLinkBody_Struct& sofLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); - static inline bool GenerateSoFTextLinkBody(std::string& sofLinkBody, const structs::TextLinkBody_Struct& sofLinkBodyStruct); + // server to client text link converter + static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink); - // client to server text link converters - static inline void SoFToServerTextLinks(std::string& serverTextLink, const std::string& sofTextLink); - static inline bool DegenerateSoFTextLinkBody(structs::TextLinkBody_Struct& sofLinkBodyStruct, const std::string& sofLinkBody); - static inline void SoFToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& sofLinkBodyStruct); - static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + // client to server text link converter + static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink); void Register(EQStreamIdentifier &into) { @@ -301,7 +295,7 @@ namespace SoF std::string old_message = emu->message; std::string new_message; - ServerToSoFTextLinks(new_message, old_message); + ServerToSoFTextLink(new_message, old_message); 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 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 = 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 new_message; - SoFToServerTextLinks(new_message, old_message); + SoFToServerTextLink(new_message, old_message); __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; __packet->pBuffer = new unsigned char[__packet->size]; @@ -3187,358 +3181,80 @@ namespace SoF 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; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(Server->SoF): old message '%s'", serverTextLink.c_str()); - - if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(Server->SoF): link size equal, no conversion necessary"); - sofTextLink = serverTextLink; - return; - } - - if (serverTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(Server->SoF): delimiter not found, no conversion necessary"); - sofTextLink = serverTextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(serverTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(Server->SoF): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->SoF): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - } - - structs::TextLinkBody_Struct new_body_data; - ServerToSoFTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateSoFTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(Server->SoF): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->SoF): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->SoF): conversion error"); - sofTextLink = serverTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - sofTextLink.push_back(delimiter); - sofTextLink.append(segments[iter].c_str()); - sofTextLink.push_back(delimiter); - } - else { - sofTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->SoF): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->SoF): new message '%s'", sofTextLink.c_str()); -#else if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { sofTextLink = serverTextLink; return; } - bool conversion_error = false; auto segments = SplitString(serverTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - structs::TextLinkBody_Struct new_body_data; - ServerToSoFTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source) + // 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; - if (!GenerateSoFTextLinkBody(segment, new_body_data)) { - conversion_error = true; - break; - } - else { - segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } + new_segment.append(segments[segment_iter].substr(0, 31).c_str()); + new_segment.append(segments[segment_iter].substr(36, 5).c_str()); - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->SoF): conversion error"); - sofTextLink = serverTextLink; - return; - } + if (segments[segment_iter].substr(41, 1) == "0") + new_segment.append(segments[segment_iter].substr(42, 1).c_str()); + else + 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.append(segments[iter].c_str()); + sofTextLink.append(new_segment.c_str()); sofTextLink.push_back(delimiter); } 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) - { - 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) + static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink) { const char delimiter = 0x12; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(SoF->Server): old message '%s'", sofTextLink.c_str()); - - if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(SoF->Server): link size equal, no conversion necessary"); - serverTextLink = sofTextLink; - return; - } - - if (sofTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(SoF->Server): delimiter not found, no conversion necessary"); - serverTextLink = sofTextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(sofTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateSoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(SoF->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(SoF->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - } - - TextLinkBody_Struct new_body_data; - SoFToServerTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateServerTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(SoF->Server): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(SoF->Server): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(SoF->Server): conversion error"); - serverTextLink = sofTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - serverTextLink.push_back(delimiter); - serverTextLink.append(segments[iter].c_str()); - serverTextLink.push_back(delimiter); - } - else { - serverTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(SoF->Server): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(SoF->Server): new message '%s'", serverTextLink.c_str()); -#else if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find(delimiter) == std::string::npos)) { serverTextLink = sofTextLink; return; } - bool conversion_error = false; auto segments = SplitString(sofTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateSoFTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - TextLinkBody_Struct new_body_data; - SoFToServerTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 32 36 37 42 (Source) + // 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; - 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(); - } - } + new_segment.append(segments[segment_iter].substr(0, 31).c_str()); + new_segment.append("00000"); + new_segment.append(segments[segment_iter].substr(31, 5).c_str()); + new_segment.append("0"); + new_segment.append(segments[segment_iter].substr(36).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.append(new_segment.c_str()); serverTextLink.push_back(delimiter); } 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 diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 08d7f6fa6..4e84998b7 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -4115,23 +4115,6 @@ struct AltCurrencySellItem_Struct { /*010*/ uint32 cost; }; -// SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" -struct TextLinkBody_Struct -{ - uint8 unknown_1; - 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 SoF diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index eef600795..f40c0266c 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -29,17 +29,11 @@ namespace Titanium static inline uint32 TitaniumToServerSlot(int16 TitaniumSlot); static inline uint32 TitaniumToServerCorpseSlot(int16 TitaniumCorpse); - // server to client text link converters - static inline void ServerToTitaniumTextLinks(std::string& titaniumTextLink, const std::string& serverTextLink); - static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); - static inline void ServerToTitaniumTextLinkBodyStruct(structs::TextLinkBody_Struct& titaniumLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); - static inline bool GenerateTitaniumTextLinkBody(std::string& titaniumLinkBody, const structs::TextLinkBody_Struct& titaniumLinkBodyStruct); + // server to client text link converter + static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink); - // client to server text link converters - static inline void TitaniumToServerTextLinks(std::string& serverTextLink, const std::string& titaniumTextLink); - static inline bool DegenerateTitaniumTextLinkBody(structs::TextLinkBody_Struct& titaniumLinkBodyStruct, const std::string& titaniumLinkBody); - static inline void TitaniumToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& titaniumLinkBodyStruct); - static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + // client to server text link converter + static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink); void Register(EQStreamIdentifier &into) { @@ -244,7 +238,7 @@ namespace Titanium std::string old_message = emu->message; std::string new_message; - ServerToTitaniumTextLinks(new_message, old_message); + ServerToTitaniumTextLink(new_message, old_message); 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 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 = 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 new_message; - TitaniumToServerTextLinks(new_message, old_message); + TitaniumToServerTextLink(new_message, old_message); __packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1; __packet->pBuffer = new unsigned char[__packet->size]; @@ -1946,355 +1940,82 @@ namespace Titanium 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; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): old message '%s'", serverTextLink.c_str()); - - if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): link size equal, no conversion necessary"); - titaniumTextLink = serverTextLink; - return; - } - - if (serverTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): delimiter not found, no conversion necessary"); - titaniumTextLink = serverTextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(serverTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - } - - structs::TextLinkBody_Struct new_body_data; - ServerToTitaniumTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateTitaniumTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): conversion error"); - titaniumTextLink = serverTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - titaniumTextLink.push_back(delimiter); - titaniumTextLink.append(segments[iter].c_str()); - titaniumTextLink.push_back(delimiter); - } - else { - titaniumTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): new message '%s'", titaniumTextLink.c_str()); -#else if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { titaniumTextLink = serverTextLink; return; } - bool conversion_error = false; auto segments = SplitString(serverTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - structs::TextLinkBody_Struct new_body_data; - ServerToTitaniumTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source) + // 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; - if (!GenerateTitaniumTextLinkBody(segment, new_body_data)) { - conversion_error = true; - break; - } - else { - segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } + new_segment.append(segments[segment_iter].substr(0, 31).c_str()); + new_segment.append(segments[segment_iter].substr(36, 5).c_str()); - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->Titanium): conversion error"); - titaniumTextLink = serverTextLink; - return; - } + if (segments[segment_iter].substr(41, 1) == "0") + new_segment.append(segments[segment_iter].substr(42, 1).c_str()); + else + 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.append(segments[iter].c_str()); + titaniumTextLink.append(new_segment.c_str()); titaniumTextLink.push_back(delimiter); } 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) - { - 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) + static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink) { const char delimiter = 0x12; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(Titanium->Server): old message '%s'", titaniumTextLink.c_str()); - - if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(Titanium->Server): link size equal, no conversion necessary"); - serverTextLink = titaniumTextLink; - return; - } - - if (titaniumTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(Titanium->Server): delimiter not found, no conversion necessary"); - serverTextLink = titaniumTextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(titaniumTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateTitaniumTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(Titanium->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Titanium->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - } - - TextLinkBody_Struct new_body_data; - TitaniumToServerTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateServerTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(Titanium->Server): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Titanium->Server): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Titanium->Server): conversion error"); - serverTextLink = titaniumTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - serverTextLink.push_back(delimiter); - serverTextLink.append(segments[iter].c_str()); - serverTextLink.push_back(delimiter); - } - else { - serverTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Titanium->Server): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Titanium->Server): new message '%s'", serverTextLink.c_str()); -#else if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find(delimiter) == std::string::npos)) { serverTextLink = titaniumTextLink; return; } - bool conversion_error = false; auto segments = SplitString(titaniumTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateTitaniumTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - TextLinkBody_Struct new_body_data; - TitaniumToServerTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 32 36 37 (Source) + // 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; - 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(); - } - } + new_segment.append(segments[segment_iter].substr(0, 31).c_str()); + new_segment.append("00000"); + new_segment.append(segments[segment_iter].substr(31, 5).c_str()); + new_segment.append("0"); + new_segment.append(segments[segment_iter].substr(36, 1).c_str()); + new_segment.append("00000"); + new_segment.append(segments[segment_iter].substr(37).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.append(new_segment.c_str()); serverTextLink.push_back(delimiter); } 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 diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 06536c7c2..7d21ba998 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -3329,22 +3329,6 @@ struct LFGuild_GuildToggle_Struct /*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 Titanium diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index b525a3c46..1ebd8dc8d 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -31,17 +31,11 @@ namespace Underfoot static inline uint32 UnderfootToServerSlot(uint32 UnderfootSlot); static inline uint32 UnderfootToServerCorpseSlot(uint32 UnderfootCorpse); - // server to client text link converters - static inline void ServerToUnderfootTextLinks(std::string& underfootTextLink, const std::string& serverTextLink); - static inline bool DegenerateServerTextLinkBody(TextLinkBody_Struct& serverLinkBodyStruct, const std::string& serverLinkBody); - static inline void ServerToUnderfootTextLinkBodyStruct(structs::TextLinkBody_Struct& underfootLinkBodyStruct, const TextLinkBody_Struct& serverLinkBodyStruct); - static inline bool GenerateUnderfootTextLinkBody(std::string& underfootLinkBody, const structs::TextLinkBody_Struct& underfootLinkBodyStruct); + // server to client text link converter + static inline void ServerToUnderfootTextLink(std::string& underfootTextLink, const std::string& serverTextLink); - // client to server text link converters - static inline void UnderfootToServerTextLinks(std::string& serverTextLink, const std::string& underfootTextLink); - static inline bool DegenerateUnderfootTextLinkBody(structs::TextLinkBody_Struct& underfootLinkBodyStruct, const std::string& underfootLinkBody); - static inline void UnderfootToServerTextLinkBodyStruct(TextLinkBody_Struct& serverLinkBodyStruct, const structs::TextLinkBody_Struct& underfootLinkBodyStruct); - static inline bool GenerateServerTextLinkBody(std::string& serverLinkBody, const TextLinkBody_Struct& serverLinkBodyStruct); + // client to server text link converter + static inline void UnderfootToServerTextLink(std::string& serverTextLink, const std::string& underfootTextLink); void Register(EQStreamIdentifier &into) { @@ -446,7 +440,7 @@ namespace Underfoot std::string old_message = emu->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) + strlen(emu->targetname) + new_message.length() + 39; @@ -2326,7 +2320,7 @@ namespace Underfoot std::string old_message = &emu->message[strlen(emu->sayer)]; 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 = 25 + strlen(emu->sayer) + new_message.length(); @@ -3093,7 +3087,7 @@ namespace Underfoot std::string old_message = InBuffer; 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) + new_message.length() + 1; @@ -4168,358 +4162,80 @@ namespace Underfoot 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; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): old message '%s'", serverTextLink.c_str()); - - if (consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): link size equal, no conversion necessary"); - underfootTextLink = serverTextLink; - return; - } - - if (serverTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): delimiter not found, no conversion necessary"); - underfootTextLink = serverTextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(serverTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body degeneration error '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body degeneration success '%s'", segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - } - - structs::TextLinkBody_Struct new_body_data; - ServerToUnderfootTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateUnderfootTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): conversion error"); - underfootTextLink = serverTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - underfootTextLink.push_back(delimiter); - underfootTextLink.append(segments[iter].c_str()); - underfootTextLink.push_back(delimiter); - } - else { - underfootTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): new message '%s'", underfootTextLink.c_str()); -#else if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find(delimiter) == std::string::npos)) { underfootTextLink = serverTextLink; return; } - bool conversion_error = false; auto segments = SplitString(serverTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - TextLinkBody_Struct old_body_data; - if (!DegenerateServerTextLinkBody(old_body_data, segments[iter].substr(0, EmuConstants::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - structs::TextLinkBody_Struct new_body_data; - ServerToUnderfootTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 36 37 41 43 48 (Source) + // 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; - if (!GenerateUnderfootTextLinkBody(segment, new_body_data)) { - conversion_error = true; - break; - } - else { - segment.append(segments[iter].substr(EmuConstants::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } + new_segment.append(segments[segment_iter].substr(0, 31).c_str()); + new_segment.append(segments[segment_iter].substr(36, 5).c_str()); - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Server->Underfoot): conversion error"); - underfootTextLink = serverTextLink; - return; - } + if (segments[segment_iter].substr(41, 1) == "0") + new_segment.append(segments[segment_iter].substr(42, 1).c_str()); + else + 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.append(segments[iter].c_str()); + underfootTextLink.append(new_segment.c_str()); underfootTextLink.push_back(delimiter); } 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) - { - 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) + static inline void UnderfootToServerTextLink(std::string& serverTextLink, const std::string& underfootTextLink) { const char delimiter = 0x12; -#if EQDEBUG >= 6 - _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): old message '%s'", underfootTextLink.c_str()); - - if (EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) { - _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): link size equal, no conversion necessary"); - serverTextLink = underfootTextLink; - return; - } - - if (underfootTextLink.find(delimiter) == std::string::npos) { - _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): delimiter not found, no conversion necessary"); - serverTextLink = underfootTextLink; - return; - } - - bool conversion_error = false; - auto segments = SplitString(underfootTextLink, delimiter); - - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateUnderfootTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body degeneration error '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body degeneration success '%s'", segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str()); - } - - TextLinkBody_Struct new_body_data; - UnderfootToServerTextLinkBodyStruct(new_body_data, old_body_data); - - std::string segment; - if (!GenerateServerTextLinkBody(segment, new_body_data)) { - _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body generation error '%s'", segment.c_str()); - conversion_error = true; - } - else { - _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): body generation success '%s'", segment.c_str()); - segment.append(segments[iter].substr(consts::TEXT_LINK_BODY_LENGTH).c_str()); - segments[iter] = segment.c_str(); - } - } - - if (conversion_error) { - _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): conversion error"); - serverTextLink = underfootTextLink; - return; - } - - for (size_t iter = 0; iter < segments.size(); ++iter) { - if (iter & 1) { - serverTextLink.push_back(delimiter); - serverTextLink.append(segments[iter].c_str()); - serverTextLink.push_back(delimiter); - } - else { - serverTextLink.append(segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): segment[%u] '%s'", iter, segments[iter].c_str()); - } - - _log(CHANNELS__ERROR, "TextLink(Underfoot->Server): new message '%s'", serverTextLink.c_str()); -#else if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (underfootTextLink.find(delimiter) == std::string::npos)) { serverTextLink = underfootTextLink; return; } - bool conversion_error = false; auto segments = SplitString(underfootTextLink, delimiter); - for (size_t iter = 1; iter < segments.size(); iter += 2) { - structs::TextLinkBody_Struct old_body_data; - if (!DegenerateUnderfootTextLinkBody(old_body_data, segments[iter].substr(0, consts::TEXT_LINK_BODY_LENGTH).c_str())) { - conversion_error = true; - break; - } + for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { + if (segment_iter & 1) { + std::string new_segment; - TextLinkBody_Struct new_body_data; - UnderfootToServerTextLinkBodyStruct(new_body_data, old_body_data); + // Idx: 0 1 6 11 16 21 26 31 32 36 37 42 (Source) + // 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; - 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(); - } - } + new_segment.append(segments[segment_iter].substr(0, 31).c_str()); + new_segment.append("00000"); + new_segment.append(segments[segment_iter].substr(31, 5).c_str()); + new_segment.append("0"); + new_segment.append(segments[segment_iter].substr(36).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.append(new_segment.c_str()); serverTextLink.push_back(delimiter); } 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 diff --git a/common/patches/underfoot_structs.h b/common/patches/underfoot_structs.h index b196e5867..3a63a8c0f 100644 --- a/common/patches/underfoot_structs.h +++ b/common/patches/underfoot_structs.h @@ -4530,23 +4530,6 @@ struct MercenaryAssign_Struct { /*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 Underfoot diff --git a/zone/client.cpp b/zone/client.cpp index 143b9271a..8b82f77cf 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8317,27 +8317,13 @@ void Client::TextLink::generate_body() /* Current server mask: EQClientRoF2 - RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X" (56) - RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (55) - SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (50) - 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" (45) + RoF2: "%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) + 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) */ - // could use a ##_cast(&this) with a memset to '0' since these properties are inherited - - unknown_1 = NOT_USED; /* field 1 */ - item_id = NOT_USED; /* field 2 */ - augment_1 = NOT_USED; /* field 3 */ - augment_2 = NOT_USED; /* field 4 */ - augment_3 = NOT_USED; /* field 5 */ - augment_4 = NOT_USED; /* field 6 */ - augment_5 = NOT_USED; /* field 7 */ - augment_6 = NOT_USED; /* field 8 */ - 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 */ + memset(&m_LinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); const Item_Struct* item_data = nullptr; @@ -8346,33 +8332,40 @@ void Client::TextLink::generate_body() break; case linkItemData: 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 break; case linkLootItem: if (m_LootData == nullptr) { break; } item_data = database.GetItem(m_LootData->item_id); if (item_data == nullptr) { break; } - item_id = item_data->ID; - augment_1 = m_LootData->aug_1; - augment_2 = m_LootData->aug_2; - augment_3 = m_LootData->aug_3; - augment_4 = m_LootData->aug_4; - augment_5 = m_LootData->aug_5; - augment_6 = m_LootData->aug_6; + m_LinkBodyStruct.item_id = item_data->ID; + m_LinkBodyStruct.augment_1 = m_LootData->aug_1; + m_LinkBodyStruct.augment_2 = m_LootData->aug_2; + m_LinkBodyStruct.augment_3 = m_LootData->aug_3; + m_LinkBodyStruct.augment_4 = m_LootData->aug_4; + m_LinkBodyStruct.augment_5 = m_LootData->aug_5; + 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 break; case linkItemInst: if (m_ItemInst == nullptr) { break; } if (m_ItemInst->GetItem() == nullptr) { break; } - item_id = m_ItemInst->GetItem()->ID; - augment_1 = m_ItemInst->GetAugmentItemID(0); - augment_2 = m_ItemInst->GetAugmentItemID(1); - augment_3 = m_ItemInst->GetAugmentItemID(2); - augment_4 = m_ItemInst->GetAugmentItemID(3); - augment_5 = m_ItemInst->GetAugmentItemID(4); - augment_6 = m_ItemInst->GetAugmentItemID(5); - ornament_icon = m_ItemInst->GetOrnamentationIcon(); + m_LinkBodyStruct.item_id = m_ItemInst->GetItem()->ID; + m_LinkBodyStruct.augment_1 = m_ItemInst->GetAugmentItemID(0); + m_LinkBodyStruct.augment_2 = m_ItemInst->GetAugmentItemID(1); + m_LinkBodyStruct.augment_3 = m_ItemInst->GetAugmentItemID(2); + m_LinkBodyStruct.augment_4 = m_ItemInst->GetAugmentItemID(3); + m_LinkBodyStruct.augment_5 = m_ItemInst->GetAugmentItemID(4); + m_LinkBodyStruct.augment_6 = m_ItemInst->GetAugmentItemID(5); + 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 break; default: @@ -8380,29 +8373,28 @@ void Client::TextLink::generate_body() } if (m_ProxyItemID != NOT_USED) { - item_id = m_ProxyItemID; + m_LinkBodyStruct.item_id = m_ProxyItemID; } if (m_TaskUse) { - //hash = 0x0000000014505DC2; - hash = 0x14505DC2; + m_LinkBodyStruct.hash = 0x14505DC2; } m_LinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X", - unknown_1, - item_id, - augment_1, - augment_2, - augment_3, - augment_4, - augment_5, - augment_6, - is_evolving, - lore_group, - evolve_max, - ornament_icon, - hash + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", + (0x0F & m_LinkBodyStruct.unknown_1), + (0x000FFFFF & m_LinkBodyStruct.item_id), + (0x000FFFFF & m_LinkBodyStruct.augment_1), + (0x000FFFFF & m_LinkBodyStruct.augment_2), + (0x000FFFFF & m_LinkBodyStruct.augment_3), + (0x000FFFFF & m_LinkBodyStruct.augment_4), + (0x000FFFFF & m_LinkBodyStruct.augment_5), + (0x000FFFFF & m_LinkBodyStruct.augment_6), + (0x0F & m_LinkBodyStruct.is_evolving), + (0x0000FFFF & m_LinkBodyStruct.evolve_group), + (0xFF & m_LinkBodyStruct.evolve_level), + (0x000FFFFF & m_LinkBodyStruct.ornament_icon), + (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_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.lore_group = (uint32)strtol(textLinkBody.substr(37, 5).c_str(), nullptr, 16); - textLinkBodyStruct.evolve_max = (uint8)strtol(textLinkBody.substr(42, 1).c_str(), nullptr, 16); + textLinkBodyStruct.evolve_group = (uint32)strtol(textLinkBody.substr(37, 4).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.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) { textLinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%05X" "%1X" "%05X" "%08X", - textLinkBodyStruct.unknown_1, - textLinkBodyStruct.item_id, - textLinkBodyStruct.augment_1, - textLinkBodyStruct.augment_2, - textLinkBodyStruct.augment_3, - textLinkBodyStruct.augment_4, - textLinkBodyStruct.augment_5, - textLinkBodyStruct.augment_6, - textLinkBodyStruct.is_evolving, - textLinkBodyStruct.lore_group, - textLinkBodyStruct.evolve_max, - textLinkBodyStruct.ornament_icon, - textLinkBodyStruct.hash + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", + (0x0F & textLinkBodyStruct.unknown_1), + (0x000FFFFF & textLinkBodyStruct.item_id), + (0x000FFFFF & textLinkBodyStruct.augment_1), + (0x000FFFFF & textLinkBodyStruct.augment_2), + (0x000FFFFF & textLinkBodyStruct.augment_3), + (0x000FFFFF & textLinkBodyStruct.augment_4), + (0x000FFFFF & textLinkBodyStruct.augment_5), + (0x000FFFFF & textLinkBodyStruct.augment_6), + (0x0F & textLinkBodyStruct.is_evolving), + (0x0000FFFF & textLinkBodyStruct.evolve_group), + (0xFF & textLinkBodyStruct.evolve_level), + (0x000FFFFF & textLinkBodyStruct.ornament_icon), + (0xFFFFFFFF & textLinkBodyStruct.hash) ); if (textLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } diff --git a/zone/client.h b/zone/client.h index fd88848fa..22b413b50 100644 --- a/zone/client.h +++ b/zone/client.h @@ -822,7 +822,7 @@ public: // // class Client::TextLink // - class TextLink : TextLinkBody_Struct { + class TextLink { public: enum LinkType { linkBlank = 0, linkItemData, linkLootItem, linkItemInst }; @@ -859,6 +859,7 @@ public: uint32 m_ProxyItemID; const char* m_ProxyText; bool m_TaskUse; + TextLinkBody_Struct m_LinkBodyStruct; std::string m_Link; std::string m_LinkBody; std::string m_LinkText;