diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 5078cca68..46fd564e6 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -136,20 +136,22 @@ N(OP_Dye), N(OP_DynamicWall), N(OP_DzAddPlayer), N(OP_DzChooseZone), +N(OP_DzChooseZoneReply), N(OP_DzCompass), N(OP_DzExpeditionEndsWarning), N(OP_DzExpeditionInfo), -N(OP_DzExpeditionList), -N(OP_DzJoinExpeditionConfirm), -N(OP_DzJoinExpeditionReply), -N(OP_DzLeaderStatus), +N(OP_DzExpeditionInvite), +N(OP_DzExpeditionInviteResponse), +N(OP_DzExpeditionLockoutTimers), N(OP_DzListTimers), N(OP_DzMakeLeader), N(OP_DzMemberList), -N(OP_DzMemberStatus), +N(OP_DzMemberListName), +N(OP_DzMemberListStatus), N(OP_DzPlayerList), N(OP_DzQuit), N(OP_DzRemovePlayer), +N(OP_DzSetLeaderName), N(OP_DzSwapPlayer), N(OP_Emote), N(OP_EndLootRequest), @@ -271,6 +273,7 @@ N(OP_ItemVerifyRequest), N(OP_ItemViewUnknown), N(OP_Jump), N(OP_KeyRing), +N(OP_KickPlayers), N(OP_KnowledgeBase), N(OP_LDoNButton), N(OP_LDoNDisarmTraps), diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index c22069196..da589abbf 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4835,17 +4835,98 @@ struct BuffIcon_Struct BuffIconEntry_Struct entries[0]; }; -struct ExpeditionInfo_Struct +struct ExpeditionInvite_Struct { -/*000*/ uint32 max_players; -/*004*/ char expedition_name[128]; -/*132*/ char leader_name[64]; +/*000*/ uint32 client_id; // unique character id +/*004*/ uint32 unknown004; // added after titanium +/*008*/ char inviter_name[64]; +/*072*/ char expedition_name[128]; +/*200*/ uint8 swapping; // 0: adding 1: swapping +/*201*/ char swap_name[64]; // if swapping, swap name being removed +/*265*/ uint8 padding[3]; +/*268*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply +/*270*/ uint16 dz_instance_id; }; -struct ExpeditionJoinPrompt_Struct +struct ExpeditionInviteResponse_Struct { -/*000*/ char player_name[64]; -/*064*/ char expedition_name[64]; +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; // added after titanium +/*008*/ uint16 dz_zone_id; // dz_id pair sent in invite +/*010*/ uint16 dz_instance_id; +/*012*/ uint8 accepted; // 0: declined 1: accepted +/*013*/ uint8 swapping; // 0: adding 1: swapping (sent in invite) +/*014*/ char swap_name[64]; // swap name sent in invite +/*078*/ uint8 unknown078; // padding garbage? +/*079*/ uint8 unknown079; // padding garbage? +}; + +struct ExpeditionInfo_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; // added after titanium +/*008*/ uint32 assigned; // padded bool, 0: not in expedition (clear data), 1: in expedition +/*012*/ uint32 max_players; +/*016*/ char expedition_name[128]; +/*144*/ char leader_name[64]; +}; + +struct ExpeditionMemberEntry_Struct +{ +/*000*/ char name[64]; // variable length, null terminated, max 0x40 (64) +/*064*/ uint8 status; // 0: unknown, 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead +}; + +struct ExpeditionMemberList_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length +}; + +struct ExpeditionMemberListName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status +/*012*/ char name[64]; +}; + +struct ExpeditionLockoutTimerEntry_Struct +{ +/*000*/ char expedition_name[128]; // variable length, null terminated, max 0x80 (128) +/*000*/ uint32 seconds_remaining; +/*000*/ uint32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers +/*000*/ char event_name[256]; // variable length, null terminated, max 0x100 (256) +}; + +struct ExpeditionLockoutTimers_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0]; +}; + +struct ExpeditionSetLeaderName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ char leader_name[64]; +}; + +struct ExpeditionCommand_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ char name[64]; +}; + +struct ExpeditionCommandSwap_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ char add_player_name[64]; // swap to (player must confirm) +/*072*/ char rem_player_name[64]; // swap from }; struct ExpeditionExpireWarning @@ -4853,48 +4934,67 @@ struct ExpeditionExpireWarning /*008*/ uint32 minutes_remaining; }; -struct ExpeditionCompassEntry_Struct +struct DynamicZoneCompassEntry_Struct { -/*000*/ uint32 enabled; //guess -/*004*/ float y; -/*008*/ float x; -/*012*/ float z; +/*000*/ uint16 dz_zone_id; // target dz id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) +/*008*/ uint32 unknown008; +/*012*/ float y; +/*016*/ float x; +/*020*/ float z; }; -struct ExpeditionCompass_Struct +struct DynamicZoneCompass_Struct { +/*000*/ uint32 client_id; /*000*/ uint32 count; -/*004*/ ExpeditionCompassEntry_Struct entries[0]; +/*004*/ DynamicZoneCompassEntry_Struct entries[0]; }; -struct ExpeditionMemberEntry_Struct +struct DynamicZoneChooseZoneEntry_Struct { - char name[64]; - char status; +/*000*/ uint16 dz_zone_id; // dz_id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 unknown_id1; // seen 28 00 00 00 (40), sent back in reply +/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply +/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different +/*016*/ char description[128]; // variable length, null terminated +/*144*/ char leader_name[64]; // variable length, null terminated }; -struct ExpeditionMemberList_Struct +struct DynamicZoneChooseZone_Struct { -/*000*/ uint32 count; -/*004*/ ExpeditionMemberEntry_Struct entries[0]; +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0]; }; -struct ExpeditionLockoutEntry_Struct +struct DynamicZoneChooseZoneReply_Struct { -/*000*/ uint32 time_left; -/*004*/ char expedition[128]; -/*132*/ char expedition_event[128]; +/*000*/ uint32 unknown000; // ff ff ff ff +/*004*/ uint32 unknown004; // seen 69 00 00 00 +/*008*/ uint32 unknown008; // ff ff ff ff +/*012*/ uint32 unknown_id1; // from choose zone entry message +/*016*/ uint16 dz_zone_id; // dz_id pair +/*018*/ uint16 dz_instance_id; +/*020*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest +/*024*/ uint32 unknown_id2; // from choose zone entry message +/*028*/ uint32 unknown028; // 00 00 00 00 +/*032*/ uint32 unknown032; // always same as unknown044 +/*036*/ uint32 unknown036; +/*040*/ uint32 unknown040; +/*044*/ uint32 unknown044; // always same as unknown032 +/*048*/ uint32 unknown048; // seen 01 00 00 00 and 02 00 00 00 }; -struct ExpeditionLockoutList_Struct +struct KickPlayers_Struct { -/*000*/ uint32 count; -/*004*/ ExpeditionLockoutEntry_Struct entries[0]; -}; - -struct ExpeditionLeaderSet_Struct -{ -/*000*/ char leader_name[64]; +/*000*/ char char_name[64]; +/*064*/ uint32 unknown064; // always 0 +/*068*/ uint8 kick_expedition; // true if /kickplayers exp +/*069*/ uint8 kick_task; // true if /kickplayers task +/*070*/ uint8 padding[2]; }; struct CorpseDrag_Struct diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 8811c8746..6d7d0021b 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -710,15 +710,48 @@ namespace RoF FINISH_ENCODE(); } + ENCODE(OP_DzChooseZone) + { + SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); + + for (uint32 i = 0; i < emu->count; ++i) + { + buf.WriteUInt16(emu->choices[i].dz_zone_id); + buf.WriteUInt16(emu->choices[i].dz_instance_id); + buf.WriteUInt32(emu->choices[i].unknown_id1); + buf.WriteUInt32(emu->choices[i].dz_type); + buf.WriteUInt32(emu->choices[i].unknown_id2); + buf.WriteString(emu->choices[i].description); + buf.WriteString(emu->choices[i].leader_name); + } + + __packet->size = buf.size(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); + + FINISH_ENCODE(); + } + ENCODE(OP_DzCompass) { - SETUP_VAR_ENCODE(ExpeditionCompass_Struct); - ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); + SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); + ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, + sizeof(structs::DynamicZoneCompass_Struct) + + sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count + ); + OUT(client_id); OUT(count); for (uint32 i = 0; i < emu->count; ++i) { + OUT(entries[i].dz_zone_id); + OUT(entries[i].dz_instance_id); + OUT(entries[i].dz_type); OUT(entries[i].x); OUT(entries[i].y); OUT(entries[i].z); @@ -742,81 +775,60 @@ namespace RoF ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct); SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct); + OUT(client_id); + OUT(assigned); OUT(max_players); - eq->unknown004 = 785316192; - eq->unknown008 = 435601; - strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); - strncpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } - ENCODE(OP_DzExpeditionList) + ENCODE(OP_DzExpeditionInvite) { - SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct); + ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct); + SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + OUT(client_id); + strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name)); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + OUT(swapping); + strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name)); + OUT(dz_zone_id); + OUT(dz_instance_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionLockoutTimers) + { + SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event)); - ss.write((const char*)&null_term, sizeof(char)); + buf.WriteString(emu->timers[i].expedition_name); + buf.WriteUInt32(emu->timers[i].seconds_remaining); + buf.WriteUInt32(emu->timers[i].event_type); + buf.WriteString(emu->timers[i].event_name); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } - ENCODE(OP_DzJoinExpeditionConfirm) + ENCODE(OP_DzSetLeaderName) { - ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); - SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); + ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct); - strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); - strncpy(eq->player_name, emu->player_name, sizeof(eq->player_name)); - - FINISH_ENCODE(); - } - - ENCODE(OP_DzLeaderStatus) - { - SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct); - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->leader_name, strlen(emu->leader_name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//1 - ss.write((const char*)&client_id, sizeof(uint32)); - - __packet->size = ss.str().length(); - __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + OUT(client_id); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } @@ -825,26 +837,43 @@ namespace RoF { SETUP_VAR_ENCODE(ExpeditionMemberList_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].name, strlen(emu->entries[i].name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].status, sizeof(char)); + buf.WriteString(emu->members[i].name); + buf.WriteUInt8(emu->members[i].status); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } + ENCODE(OP_DzMemberListName) + { + ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct); + + OUT(client_id); + OUT(add_name); + strn0cpy(eq->name, emu->name, sizeof(eq->name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzMemberListStatus) + { + auto emu = reinterpret_cast((*p)->pBuffer); + if (emu->count == 1) + { + ENCODE_FORWARD(OP_DzMemberList); + } + } + ENCODE(OP_Emote) { EQApplicationPacket *in = *p; @@ -4388,6 +4417,84 @@ namespace RoF FINISH_DIRECT_DECODE(); } + DECODE(OP_DzAddPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzChooseZoneReply) + { + DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct); + SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct); + + IN(unknown000); + IN(unknown004); + IN(unknown008); + IN(unknown_id1); + IN(dz_zone_id); + IN(dz_instance_id); + IN(dz_type); + IN(unknown_id2); + IN(unknown028); + IN(unknown032); + IN(unknown036); + IN(unknown040); + IN(unknown044); + IN(unknown048); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzExpeditionInviteResponse) + { + DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct); + SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct); + + IN(dz_zone_id); + IN(dz_instance_id); + IN(accepted); + IN(swapping); + strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzMakeLeader) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzRemovePlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzSwapPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct); + + strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name)); + strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name)); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_Emote) { unsigned char *__eq_buffer = __packet->pBuffer; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 09a2d502d..671d539ed 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -759,15 +759,48 @@ namespace RoF2 FINISH_ENCODE(); } + ENCODE(OP_DzChooseZone) + { + SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); + + for (uint32 i = 0; i < emu->count; ++i) + { + buf.WriteUInt16(emu->choices[i].dz_zone_id); + buf.WriteUInt16(emu->choices[i].dz_instance_id); + buf.WriteUInt32(emu->choices[i].unknown_id1); + buf.WriteUInt32(emu->choices[i].dz_type); + buf.WriteUInt32(emu->choices[i].unknown_id2); + buf.WriteString(emu->choices[i].description); + buf.WriteString(emu->choices[i].leader_name); + } + + __packet->size = buf.size(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); + + FINISH_ENCODE(); + } + ENCODE(OP_DzCompass) { - SETUP_VAR_ENCODE(ExpeditionCompass_Struct); - ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); + SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); + ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, + sizeof(structs::DynamicZoneCompass_Struct) + + sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count + ); + OUT(client_id); OUT(count); for (uint32 i = 0; i < emu->count; ++i) { + OUT(entries[i].dz_zone_id); + OUT(entries[i].dz_instance_id); + OUT(entries[i].dz_type); OUT(entries[i].x); OUT(entries[i].y); OUT(entries[i].z); @@ -791,81 +824,60 @@ namespace RoF2 ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct); SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct); + OUT(client_id); + OUT(assigned); OUT(max_players); - eq->unknown004 = 785316192; - eq->unknown008 = 435601; - strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); - strncpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } - ENCODE(OP_DzExpeditionList) + ENCODE(OP_DzExpeditionInvite) { - SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct); + ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct); + SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + OUT(client_id); + strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name)); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + OUT(swapping); + strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name)); + OUT(dz_zone_id); + OUT(dz_instance_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionLockoutTimers) + { + SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event)); - ss.write((const char*)&null_term, sizeof(char)); + buf.WriteString(emu->timers[i].expedition_name); + buf.WriteUInt32(emu->timers[i].seconds_remaining); + buf.WriteUInt32(emu->timers[i].event_type); + buf.WriteString(emu->timers[i].event_name); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } - ENCODE(OP_DzJoinExpeditionConfirm) + ENCODE(OP_DzSetLeaderName) { - ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); - SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); + ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct); - strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); - strncpy(eq->player_name, emu->player_name, sizeof(eq->player_name)); - - FINISH_ENCODE(); - } - - ENCODE(OP_DzLeaderStatus) - { - SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct); - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->leader_name, strlen(emu->leader_name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//1 - ss.write((const char*)&client_id, sizeof(uint32)); - - __packet->size = ss.str().length(); - __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + OUT(client_id); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } @@ -874,26 +886,43 @@ namespace RoF2 { SETUP_VAR_ENCODE(ExpeditionMemberList_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].name, strlen(emu->entries[i].name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].status, sizeof(char)); + buf.WriteString(emu->members[i].name); + buf.WriteUInt8(emu->members[i].status); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } + ENCODE(OP_DzMemberListName) + { + ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct); + + OUT(client_id); + OUT(add_name); + strn0cpy(eq->name, emu->name, sizeof(eq->name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzMemberListStatus) + { + auto emu = reinterpret_cast((*p)->pBuffer); + if (emu->count == 1) + { + ENCODE_FORWARD(OP_DzMemberList); + } + } + ENCODE(OP_Emote) { EQApplicationPacket *in = *p; @@ -4585,6 +4614,84 @@ namespace RoF2 FINISH_DIRECT_DECODE(); } + DECODE(OP_DzAddPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzChooseZoneReply) + { + DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct); + SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct); + + IN(unknown000); + IN(unknown004); + IN(unknown008); + IN(unknown_id1); + IN(dz_zone_id); + IN(dz_instance_id); + IN(dz_type); + IN(unknown_id2); + IN(unknown028); + IN(unknown032); + IN(unknown036); + IN(unknown040); + IN(unknown044); + IN(unknown048); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzExpeditionInviteResponse) + { + DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct); + SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct); + + IN(dz_zone_id); + IN(dz_instance_id); + IN(accepted); + IN(swapping); + strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzMakeLeader) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzRemovePlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzSwapPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct); + + strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name)); + strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name)); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_Emote) { unsigned char *__eq_buffer = __packet->pBuffer; diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 32798fef5..22b6e6662 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -58,13 +58,16 @@ E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DeleteSpawn) E(OP_DisciplineUpdate) +E(OP_DzChooseZone) E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzExpeditionList) -E(OP_DzJoinExpeditionConfirm) -E(OP_DzLeaderStatus) +E(OP_DzExpeditionInvite) +E(OP_DzExpeditionLockoutTimers) E(OP_DzMemberList) +E(OP_DzMemberListName) +E(OP_DzMemberListStatus) +E(OP_DzSetLeaderName) E(OP_Emote) E(OP_ExpansionInfo) E(OP_FormattedMessage) @@ -159,6 +162,12 @@ D(OP_ConsiderCorpse) D(OP_Consume) D(OP_Damage) D(OP_DeleteItem) +D(OP_DzAddPlayer) +D(OP_DzChooseZoneReply) +D(OP_DzExpeditionInviteResponse) +D(OP_DzMakeLeader) +D(OP_DzRemovePlayer) +D(OP_DzSwapPlayer) D(OP_Emote) D(OP_EnvDamage) D(OP_FaceChange) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 96e74187d..5e2b99ba2 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4882,52 +4882,169 @@ struct VeteranClaim /*076*/ uint32 action; }; -struct ExpeditionEntryHeader_Struct +struct ExpeditionInvite_Struct +{ +/*000*/ uint32 client_id; // unique character id +/*004*/ uint32 unknown004; +/*008*/ char inviter_name[64]; +/*072*/ char expedition_name[128]; +/*200*/ uint8 swapping; // 0: adding 1: swapping +/*201*/ char swap_name[64]; // if swapping, swap name being removed +/*265*/ uint8 padding[3]; +/*268*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply +/*270*/ uint16 dz_instance_id; +}; + +struct ExpeditionInviteResponse_Struct { /*000*/ uint32 unknown000; -/*000*/ uint32 number_of_entries; -}; - -struct ExpeditionJoinPrompt_Struct -{ -/*000*/ uint32 clientid; /*004*/ uint32 unknown004; -/*008*/ char player_name[64]; -/*072*/ char expedition_name[64]; -}; - -struct ExpeditionExpireWarning -{ -/*000*/ uint32 clientid; -/*004*/ uint32 unknown004; -/*008*/ uint32 minutes_remaining; +/*008*/ uint16 dz_zone_id; // dz_id pair sent in invite +/*010*/ uint16 dz_instance_id; +/*012*/ uint8 accepted; // 0: declined 1: accepted +/*013*/ uint8 swapping; // 0: adding 1: swapping (sent in invite) +/*014*/ char swap_name[64]; // swap name sent in invite +/*078*/ uint8 unknown078; // padding garbage? +/*079*/ uint8 unknown079; // padding garbage? }; struct ExpeditionInfo_Struct { -/*000*/ uint32 clientid; +/*000*/ uint32 client_id; /*004*/ uint32 unknown004; -/*008*/ uint32 unknown008; +/*008*/ uint32 assigned; // padded bool, 0: not in expedition (clear data), 1: in expedition /*012*/ uint32 max_players; -/*016*/ char expedition_name[128]; -/*142*/ char leader_name[64]; +/*016*/ char expedition_name[128]; +/*144*/ char leader_name[64]; +//*208*/ uint32 unknown208; // live sends 01 00 00 00 here but client doesn't read it }; -struct ExpeditionCompassEntry_Struct +struct ExpeditionMemberEntry_Struct { -/*000*/ float unknown000; //seen *((uint32*)) = 1584791871 -/*004*/ uint32 enabled; //guess -/*008*/ uint32 unknown008; //seen 1019 +/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64) +/*000*/ uint8 status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead +}; + +struct ExpeditionMemberList_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; // number of players in window +/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length +}; + +struct ExpeditionMemberListName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status +/*012*/ char name[64]; +}; + +struct ExpeditionLockoutTimerEntry_Struct +{ +/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ uint32 seconds_remaining; +/*000*/ uint32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers +/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256) +}; + +struct ExpeditionLockoutTimers_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0]; +}; + +struct ExpeditionSetLeaderName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ char leader_name[64]; +}; + +struct ExpeditionCommand_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ char name[64]; +}; + +struct ExpeditionCommandSwap_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ char add_player_name[64]; // swap to (player must confirm) +/*072*/ char rem_player_name[64]; // swap from +}; + +struct ExpeditionExpireWarning +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 minutes_remaining; +}; + +struct DynamicZoneCompassEntry_Struct +{ +/*000*/ uint16 dz_zone_id; // target dz id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) +/*008*/ uint32 unknown008; /*012*/ float y; /*016*/ float x; /*020*/ float z; }; -struct ExpeditionCompass_Struct +struct DynamicZoneCompass_Struct { -/*000*/ uint32 clientid; +/*000*/ uint32 client_id; /*004*/ uint32 count; -/*008*/ ExpeditionCompassEntry_Struct entries[0]; +/*008*/ DynamicZoneCompassEntry_Struct entries[0]; +}; + +struct DynamicZoneChooseZoneEntry_Struct +{ +/*000*/ uint16 dz_zone_id; // dz_id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 unknown_id1; // seen 28 00 00 00 (40), sent back in reply +/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply +/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different +/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64) +}; + +struct DynamicZoneChooseZone_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0]; +}; + +struct DynamicZoneChooseZoneReply_Struct +{ +/*000*/ uint32 unknown000; // ff ff ff ff +/*004*/ uint32 unknown004; // seen 69 00 00 00 +/*008*/ uint32 unknown008; // ff ff ff ff +/*012*/ uint32 unknown_id1; // from choose zone entry message +/*016*/ uint16 dz_zone_id; // dz_id pair +/*018*/ uint16 dz_instance_id; +/*020*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest +/*024*/ uint32 unknown_id2; // from choose zone entry message +/*028*/ uint32 unknown028; // 00 00 00 00 +/*032*/ uint32 unknown032; // always same as unknown044 +/*036*/ uint32 unknown036; +/*040*/ uint32 unknown040; +/*044*/ uint32 unknown044; // always same as unknown032 +/*048*/ uint32 unknown048; // seen 01 00 00 00 and 02 00 00 00 +}; + +struct KickPlayers_Struct +{ +/*000*/ char char_name[64]; +/*064*/ uint32 unknown064; // always 0 +/*068*/ uint8 kick_expedition; // true if /kickplayers exp +/*069*/ uint8 kick_task; // true if /kickplayers task +/*070*/ uint8 padding[2]; }; struct MaxCharacters_Struct diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 11fd83f51..f06834d21 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -44,13 +44,16 @@ E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DeleteSpawn) E(OP_DisciplineUpdate) +E(OP_DzChooseZone) E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzExpeditionList) -E(OP_DzJoinExpeditionConfirm) -E(OP_DzLeaderStatus) +E(OP_DzExpeditionInvite) +E(OP_DzExpeditionLockoutTimers) E(OP_DzMemberList) +E(OP_DzMemberListName) +E(OP_DzMemberListStatus) +E(OP_DzSetLeaderName) E(OP_Emote) E(OP_ExpansionInfo) E(OP_FormattedMessage) @@ -145,6 +148,12 @@ D(OP_ConsiderCorpse) D(OP_Consume) D(OP_Damage) D(OP_DeleteItem) +D(OP_DzAddPlayer) +D(OP_DzChooseZoneReply) +D(OP_DzExpeditionInviteResponse) +D(OP_DzMakeLeader) +D(OP_DzRemovePlayer) +D(OP_DzSwapPlayer) D(OP_Emote) D(OP_EnvDamage) D(OP_FaceChange) diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index c22278aac..e99a6b96a 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4815,52 +4815,159 @@ struct VeteranClaim /*076*/ uint32 action; }; -struct ExpeditionEntryHeader_Struct +struct ExpeditionInvite_Struct +{ +/*000*/ uint32 client_id; // unique character id +/*004*/ uint32 unknown004; +/*008*/ char inviter_name[64]; +/*072*/ char expedition_name[128]; +/*200*/ uint8 swapping; // 0: adding 1: swapping +/*201*/ char swap_name[64]; // if swapping, swap name being removed +/*265*/ uint8 padding[3]; +/*268*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply +/*270*/ uint16 dz_instance_id; +}; + +struct ExpeditionInviteResponse_Struct { /*000*/ uint32 unknown000; -/*000*/ uint32 number_of_entries; -}; - -struct ExpeditionJoinPrompt_Struct -{ -/*000*/ uint32 clientid; /*004*/ uint32 unknown004; -/*008*/ char player_name[64]; -/*072*/ char expedition_name[64]; -}; - -struct ExpeditionExpireWarning -{ -/*000*/ uint32 clientid; -/*004*/ uint32 unknown004; -/*008*/ uint32 minutes_remaining; +/*008*/ uint16 dz_zone_id; // dz_id pair sent in invite +/*010*/ uint16 dz_instance_id; +/*012*/ uint8 accepted; // 0: declined 1: accepted +/*013*/ uint8 swapping; // 0: adding 1: swapping (sent in invite) +/*014*/ char swap_name[64]; // swap name sent in invite +/*078*/ uint8 unknown078; // padding garbage? +/*079*/ uint8 unknown079; // padding garbage? }; struct ExpeditionInfo_Struct { -/*000*/ uint32 clientid; +/*000*/ uint32 client_id; /*004*/ uint32 unknown004; -/*008*/ uint32 unknown008; +/*008*/ uint32 assigned; // padded bool /*012*/ uint32 max_players; -/*016*/ char expedition_name[128]; -/*142*/ char leader_name[64]; +/*016*/ char expedition_name[128]; +/*144*/ char leader_name[64]; }; -struct ExpeditionCompassEntry_Struct +struct ExpeditionMemberEntry_Struct { -/*000*/ float unknown000; //seen *((uint32*)) = 1584791871 -/*004*/ uint32 enabled; //guess -/*008*/ uint32 unknown008; //seen 1019 +/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64) +/*000*/ uint8 status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead +}; + +struct ExpeditionMemberList_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; // number of players in window +/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length +}; + +struct ExpeditionMemberListName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status +/*012*/ char name[64]; +}; + +struct ExpeditionLockoutTimerEntry_Struct +{ +/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ uint32 seconds_remaining; +/*000*/ uint32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers +/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256) +}; + +struct ExpeditionLockoutTimers_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0]; +}; + +struct ExpeditionSetLeaderName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ char leader_name[64]; +}; + +struct ExpeditionCommand_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ char name[64]; +}; + +struct ExpeditionCommandSwap_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ char add_player_name[64]; // swap to (player must confirm) +/*072*/ char rem_player_name[64]; // swap from +}; + +struct ExpeditionExpireWarning +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 minutes_remaining; +}; + +struct DynamicZoneCompassEntry_Struct +{ +/*000*/ uint16 dz_zone_id; // target dz id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) +/*008*/ uint32 unknown008; /*012*/ float y; /*016*/ float x; /*020*/ float z; }; -struct ExpeditionCompass_Struct +struct DynamicZoneCompass_Struct { -/*000*/ uint32 clientid; +/*000*/ uint32 client_id; /*004*/ uint32 count; -/*008*/ ExpeditionCompassEntry_Struct entries[0]; +/*008*/ DynamicZoneCompassEntry_Struct entries[0]; +}; + +struct DynamicZoneChooseZoneEntry_Struct +{ +/*000*/ uint16 dz_zone_id; // dz_id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 unknown_id1; // sent back in reply +/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply +/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different +/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64) +}; + +struct DynamicZoneChooseZone_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0]; +}; + +struct DynamicZoneChooseZoneReply_Struct +{ +/*000*/ uint32 unknown000; // ff ff ff ff +/*004*/ uint32 unknown004; // seen 69 00 00 00 +/*008*/ uint32 unknown008; // ff ff ff ff +/*012*/ uint32 unknown_id1; // from choose zone entry message +/*016*/ uint16 dz_zone_id; // dz_id pair +/*018*/ uint16 dz_instance_id; +/*020*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest +/*024*/ uint32 unknown_id2; // from choose zone entry message +/*028*/ uint32 unknown028; // 00 00 00 00 +/*032*/ uint32 unknown032; // always same as unknown044 +/*036*/ uint32 unknown036; +/*040*/ uint32 unknown040; +/*044*/ uint32 unknown044; // always same as unknown032 +/*048*/ uint32 unknown048; // seen 01 00 00 00 and 02 00 00 00 }; struct MaxCharacters_Struct diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 45f2fe20e..e84641919 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -483,15 +483,48 @@ namespace SoD FINISH_ENCODE(); } + ENCODE(OP_DzChooseZone) + { + SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); + + for (uint32 i = 0; i < emu->count; ++i) + { + buf.WriteUInt16(emu->choices[i].dz_zone_id); + buf.WriteUInt16(emu->choices[i].dz_instance_id); + buf.WriteUInt32(emu->choices[i].unknown_id1); + buf.WriteUInt32(emu->choices[i].dz_type); + buf.WriteUInt32(emu->choices[i].unknown_id2); + buf.WriteString(emu->choices[i].description); + buf.WriteString(emu->choices[i].leader_name); + } + + __packet->size = buf.size(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); + + FINISH_ENCODE(); + } + ENCODE(OP_DzCompass) { - SETUP_VAR_ENCODE(ExpeditionCompass_Struct); - ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); + SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); + ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, + sizeof(structs::DynamicZoneCompass_Struct) + + sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count + ); + OUT(client_id); OUT(count); for (uint32 i = 0; i < emu->count; ++i) { + OUT(entries[i].dz_zone_id); + OUT(entries[i].dz_instance_id); + OUT(entries[i].dz_type); OUT(entries[i].x); OUT(entries[i].y); OUT(entries[i].z); @@ -515,81 +548,60 @@ namespace SoD ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct); SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct); + OUT(client_id); + OUT(assigned); OUT(max_players); - eq->unknown004 = 785316192; - eq->unknown008 = 435601; - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->leader_name, emu->leader_name); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } - ENCODE(OP_DzExpeditionList) + ENCODE(OP_DzExpeditionInvite) { - SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct); + ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct); + SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + OUT(client_id); + strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name)); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + OUT(swapping); + strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name)); + OUT(dz_zone_id); + OUT(dz_instance_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionLockoutTimers) + { + SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event)); - ss.write((const char*)&null_term, sizeof(char)); + buf.WriteString(emu->timers[i].expedition_name); + buf.WriteUInt32(emu->timers[i].seconds_remaining); + buf.WriteUInt32(emu->timers[i].event_type); + buf.WriteString(emu->timers[i].event_name); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } - ENCODE(OP_DzJoinExpeditionConfirm) + ENCODE(OP_DzSetLeaderName) { - ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); - SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); + ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct); - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->player_name, emu->player_name); - - FINISH_ENCODE(); - } - - ENCODE(OP_DzLeaderStatus) - { - SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct); - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->leader_name, strlen(emu->leader_name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//1 - ss.write((const char*)&client_id, sizeof(uint32)); - - __packet->size = ss.str().length(); - __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + OUT(client_id); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } @@ -598,26 +610,44 @@ namespace SoD { SETUP_VAR_ENCODE(ExpeditionMemberList_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].name, strlen(emu->entries[i].name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].status, sizeof(char)); + buf.WriteString(emu->members[i].name); + buf.WriteUInt8(emu->members[i].status); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } + ENCODE(OP_DzMemberListName) + { + ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct); + + OUT(client_id); + OUT(add_name); + strn0cpy(eq->name, emu->name, sizeof(eq->name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzMemberListStatus) + { + auto emu = reinterpret_cast((*p)->pBuffer); + if (emu->count == 1) + { + ENCODE_FORWARD(OP_DzMemberList); + } + } + + ENCODE(OP_Emote) { EQApplicationPacket *in = *p; @@ -2974,6 +3004,84 @@ namespace SoD FINISH_DIRECT_DECODE(); } + DECODE(OP_DzAddPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzChooseZoneReply) + { + DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct); + SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct); + + IN(unknown000); + IN(unknown004); + IN(unknown008); + IN(unknown_id1); + IN(dz_zone_id); + IN(dz_instance_id); + IN(dz_type); + IN(unknown_id2); + IN(unknown028); + IN(unknown032); + IN(unknown036); + IN(unknown040); + IN(unknown044); + IN(unknown048); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzExpeditionInviteResponse) + { + DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct); + SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct); + + IN(dz_zone_id); + IN(dz_instance_id); + IN(accepted); + IN(swapping); + strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzMakeLeader) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzRemovePlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzSwapPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct); + + strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name)); + strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name)); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_Emote) { unsigned char *__eq_buffer = __packet->pBuffer; diff --git a/common/patches/sod_ops.h b/common/patches/sod_ops.h index 6909e1f28..5216a77ce 100644 --- a/common/patches/sod_ops.h +++ b/common/patches/sod_ops.h @@ -35,13 +35,16 @@ E(OP_Consider) E(OP_Damage) E(OP_DeleteCharge) E(OP_DeleteItem) +E(OP_DzChooseZone) E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzExpeditionList) -E(OP_DzJoinExpeditionConfirm) -E(OP_DzLeaderStatus) +E(OP_DzExpeditionInvite) +E(OP_DzExpeditionLockoutTimers) E(OP_DzMemberList) +E(OP_DzMemberListName) +E(OP_DzMemberListStatus) +E(OP_DzSetLeaderName) E(OP_Emote) E(OP_ExpansionInfo) E(OP_FormattedMessage) @@ -111,6 +114,12 @@ D(OP_Consider) D(OP_ConsiderCorpse) D(OP_Consume) D(OP_DeleteItem) +D(OP_DzAddPlayer) +D(OP_DzChooseZoneReply) +D(OP_DzExpeditionInviteResponse) +D(OP_DzMakeLeader) +D(OP_DzRemovePlayer) +D(OP_DzSwapPlayer) D(OP_Emote) D(OP_FaceChange) D(OP_FindPersonRequest) diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 7a2ae5710..f31ee6792 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -4169,52 +4169,160 @@ struct VeteranReward /*012*/ VeteranRewardItem items[8]; }; -struct ExpeditionEntryHeader_Struct + +struct ExpeditionInvite_Struct +{ +/*000*/ uint32 client_id; // unique character id +/*004*/ uint32 unknown004; +/*008*/ char inviter_name[64]; +/*072*/ char expedition_name[128]; +/*200*/ uint8 swapping; // 0: adding 1: swapping +/*201*/ char swap_name[64]; // if swapping, swap name being removed +/*265*/ uint8 padding[3]; +/*268*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply +/*270*/ uint16 dz_instance_id; +}; + +struct ExpeditionInviteResponse_Struct { /*000*/ uint32 unknown000; -/*000*/ uint32 number_of_entries; -}; - -struct ExpeditionJoinPrompt_Struct -{ -/*000*/ uint32 clientid; /*004*/ uint32 unknown004; -/*008*/ char player_name[64]; -/*072*/ char expedition_name[64]; -}; - -struct ExpeditionExpireWarning -{ -/*000*/ uint32 clientid; -/*004*/ uint32 unknown004; -/*008*/ uint32 minutes_remaining; +/*008*/ uint16 dz_zone_id; // dz_id pair sent in invite +/*010*/ uint16 dz_instance_id; +/*012*/ uint8 accepted; // 0: declined 1: accepted +/*013*/ uint8 swapping; // 0: adding 1: swapping (sent in invite) +/*014*/ char swap_name[64]; // swap name sent in invite +/*078*/ uint8 unknown078; // padding garbage? +/*079*/ uint8 unknown079; // padding garbage? }; struct ExpeditionInfo_Struct { -/*000*/ uint32 clientid; +/*000*/ uint32 client_id; /*004*/ uint32 unknown004; -/*008*/ uint32 unknown008; +/*008*/ uint32 assigned; // padded bool /*012*/ uint32 max_players; -/*016*/ char expedition_name[128]; -/*142*/ char leader_name[64]; +/*016*/ char expedition_name[128]; +/*144*/ char leader_name[64]; }; -struct ExpeditionCompassEntry_Struct +struct ExpeditionMemberEntry_Struct { -/*000*/ float unknown000; //seen *((uint32*)) = 1584791871 -/*004*/ uint32 enabled; //guess -/*008*/ uint32 unknown008; //seen 1019 +/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64) +/*000*/ uint8 status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead +}; + +struct ExpeditionMemberList_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; // number of players in window +/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length +}; + +struct ExpeditionMemberListName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status +/*012*/ char name[64]; +}; + +struct ExpeditionLockoutTimerEntry_Struct +{ +/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ uint32 seconds_remaining; +/*000*/ uint32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers +/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256) +}; + +struct ExpeditionLockoutTimers_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0]; +}; + +struct ExpeditionSetLeaderName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ char leader_name[64]; +}; + +struct ExpeditionCommand_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ char name[64]; +}; + +struct ExpeditionCommandSwap_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ char add_player_name[64]; // swap to (player must confirm) +/*072*/ char rem_player_name[64]; // swap from +}; + +struct ExpeditionExpireWarning +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 minutes_remaining; +}; + +struct DynamicZoneCompassEntry_Struct +{ +/*000*/ uint16 dz_zone_id; // target dz id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) +/*008*/ uint32 unknown008; /*012*/ float y; /*016*/ float x; /*020*/ float z; }; -struct ExpeditionCompass_Struct +struct DynamicZoneCompass_Struct { -/*000*/ uint32 clientid; +/*000*/ uint32 client_id; /*004*/ uint32 count; -/*008*/ ExpeditionCompassEntry_Struct entries[0]; +/*008*/ DynamicZoneCompassEntry_Struct entries[0]; +}; + +struct DynamicZoneChooseZoneEntry_Struct +{ +/*000*/ uint16 dz_zone_id; // dz_id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 unknown_id1; // sent back in reply +/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply +/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different +/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64) +}; + +struct DynamicZoneChooseZone_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0]; +}; + +struct DynamicZoneChooseZoneReply_Struct +{ +/*000*/ uint32 unknown000; // ff ff ff ff +/*004*/ uint32 unknown004; // seen 69 00 00 00 +/*008*/ uint32 unknown008; // ff ff ff ff +/*012*/ uint32 unknown_id1; // from choose zone entry message +/*016*/ uint16 dz_zone_id; // dz_id pair +/*018*/ uint16 dz_instance_id; +/*020*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest +/*024*/ uint32 unknown_id2; // from choose zone entry message +/*028*/ uint32 unknown028; // 00 00 00 00 +/*032*/ uint32 unknown032; // always same as unknown044 +/*036*/ uint32 unknown036; +/*040*/ uint32 unknown040; +/*044*/ uint32 unknown044; // always same as unknown032 +/*048*/ uint32 unknown048; // seen 01 00 00 00 and 02 00 00 00 }; struct AltCurrencySelectItem_Struct { diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index f8ccf0274..ccb1fd19e 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -471,14 +471,48 @@ namespace SoF FINISH_ENCODE(); } + ENCODE(OP_DzChooseZone) + { + SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); + + for (uint32 i = 0; i < emu->count; ++i) + { + buf.WriteUInt16(emu->choices[i].dz_zone_id); + buf.WriteUInt16(emu->choices[i].dz_instance_id); + buf.WriteUInt32(emu->choices[i].unknown_id1); + buf.WriteUInt32(emu->choices[i].dz_type); + buf.WriteUInt32(emu->choices[i].unknown_id2); + buf.WriteString(emu->choices[i].description); + buf.WriteString(emu->choices[i].leader_name); + } + + __packet->size = buf.size(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); + + FINISH_ENCODE(); + } + ENCODE(OP_DzCompass) { - SETUP_VAR_ENCODE(ExpeditionCompass_Struct); - ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); + SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); + ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, + sizeof(structs::DynamicZoneCompass_Struct) + + sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count + ); + + OUT(client_id); OUT(count); for (uint32 i = 0; i < emu->count; ++i) { + OUT(entries[i].dz_zone_id); + OUT(entries[i].dz_instance_id); + OUT(entries[i].dz_type); OUT(entries[i].x); OUT(entries[i].y); OUT(entries[i].z); @@ -502,80 +536,60 @@ namespace SoF ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct); SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct); + OUT(client_id); + OUT(assigned); OUT(max_players); - eq->enabled_max = 1; - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->leader_name, emu->leader_name); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } - ENCODE(OP_DzExpeditionList) + ENCODE(OP_DzExpeditionInvite) { - SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct); + ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct); + SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); - for (int i = 0; i < emu->count; ++i) + OUT(client_id); + strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name)); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + OUT(swapping); + strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name)); + OUT(dz_zone_id); + OUT(dz_instance_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionLockoutTimers) + { + SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); + for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event)); - ss.write((const char*)&null_term, sizeof(char)); + buf.WriteString(emu->timers[i].expedition_name); + buf.WriteUInt32(emu->timers[i].seconds_remaining); + buf.WriteUInt32(emu->timers[i].event_type); + buf.WriteString(emu->timers[i].event_name); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } - ENCODE(OP_DzJoinExpeditionConfirm) + ENCODE(OP_DzSetLeaderName) { - ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); - SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); + ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct); - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->player_name, emu->player_name); - - FINISH_ENCODE(); - } - - ENCODE(OP_DzLeaderStatus) - { - SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct); - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - - ss.write((const char*)&client_id, sizeof(uint32)); - //ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->leader_name, strlen(emu->leader_name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//1 - ss.write((const char*)&client_id, sizeof(uint32)); - - __packet->size = ss.str().length(); - __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + OUT(client_id); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } @@ -584,26 +598,43 @@ namespace SoF { SETUP_VAR_ENCODE(ExpeditionMemberList_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].name, strlen(emu->entries[i].name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].status, sizeof(char)); + buf.WriteString(emu->members[i].name); + buf.WriteUInt8(emu->members[i].status); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } + ENCODE(OP_DzMemberListName) + { + ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct); + + OUT(client_id); + OUT(add_name); + strn0cpy(eq->name, emu->name, sizeof(eq->name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzMemberListStatus) + { + auto emu = reinterpret_cast((*p)->pBuffer); + if (emu->count == 1) + { + ENCODE_FORWARD(OP_DzMemberList); + } + } + ENCODE(OP_Emote) { EQApplicationPacket *in = *p; @@ -2435,6 +2466,83 @@ namespace SoF FINISH_DIRECT_DECODE(); } + DECODE(OP_DzAddPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzChooseZoneReply) + { + DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct); + SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct); + + emu->unknown000 = eq->unknown000; + emu->unknown008 = eq->unknown004; + IN(unknown_id1); + IN(dz_zone_id); + IN(dz_instance_id); + IN(dz_type); + IN(unknown_id2); + emu->unknown028 = eq->unknown024; + emu->unknown032 = eq->unknown028; + emu->unknown036 = eq->unknown032; + emu->unknown040 = eq->unknown036; + emu->unknown044 = eq->unknown040; + emu->unknown048 = eq->unknown044; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzExpeditionInviteResponse) + { + DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct); + SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct); + + IN(dz_zone_id); + IN(dz_instance_id); + IN(accepted); + IN(swapping); + strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzMakeLeader) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzRemovePlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzSwapPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct); + + strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name)); + strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name)); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_Emote) { unsigned char *__eq_buffer = __packet->pBuffer; diff --git a/common/patches/sof_ops.h b/common/patches/sof_ops.h index 0ff2cfd2f..653bb5979 100644 --- a/common/patches/sof_ops.h +++ b/common/patches/sof_ops.h @@ -36,13 +36,16 @@ E(OP_Damage) E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DeleteSpawn) +E(OP_DzChooseZone) E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzExpeditionList) -E(OP_DzJoinExpeditionConfirm) -E(OP_DzLeaderStatus) +E(OP_DzExpeditionInvite) +E(OP_DzExpeditionLockoutTimers) E(OP_DzMemberList) +E(OP_DzMemberListName) +E(OP_DzMemberListStatus) +E(OP_DzSetLeaderName) E(OP_Emote) E(OP_ExpansionInfo) E(OP_FormattedMessage) @@ -103,6 +106,12 @@ D(OP_Consider) D(OP_ConsiderCorpse) D(OP_Consume) D(OP_DeleteItem) +D(OP_DzAddPlayer) +D(OP_DzChooseZoneReply) +D(OP_DzExpeditionInviteResponse) +D(OP_DzMakeLeader) +D(OP_DzRemovePlayer) +D(OP_DzSwapPlayer) D(OP_Emote) D(OP_FaceChange) D(OP_FindPersonRequest) diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index b9716d016..fac58e554 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -4088,43 +4088,150 @@ struct VeteranReward /*012*/ VeteranRewardItem items[8]; }; -struct ExpeditionExpireWarning +struct ExpeditionInvite_Struct +{ +/*000*/ uint32 client_id; +/*004*/ char inviter_name[64]; +/*068*/ char expedition_name[128]; +/*196*/ uint8 swapping; // 0: adding 1: swapping +/*197*/ char swap_name[64]; // if swapping, swap name being removed +/*261*/ uint8 padding[3]; +/*264*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply +/*268*/ uint16 dz_instance_id; +}; + +struct ExpeditionInviteResponse_Struct { /*000*/ uint32 unknown000; -/*004*/ uint32 minutes_remaining; +/*004*/ uint16 dz_zone_id; // dz_id pair sent in invite +/*006*/ uint16 dz_instance_id; +/*008*/ uint8 accepted; // 0: declined 1: accepted +/*009*/ uint8 swapping; // 0: adding 1: swapping (sent in invite) +/*010*/ char swap_name[64]; // swap name sent in invite +/*074*/ uint8 unknown078; // padding/garbage? +/*075*/ uint8 unknown079; // padding/garbage? }; struct ExpeditionInfo_Struct { -/*000*/ uint32 clientid; -/*004*/ uint32 enabled_max; +/*000*/ uint32 client_id; +/*004*/ uint32 assigned; // padded bool /*008*/ uint32 max_players; -/*012*/ char expedition_name[128]; -/*142*/ char leader_name[64]; +/*012*/ char expedition_name[128]; +/*140*/ char leader_name[64]; }; -struct ExpeditionCompassEntry_Struct +struct ExpeditionMemberEntry_Struct { -/*000*/ float unknown000; //seen *((uint32*)) = 1584791871 -/*004*/ uint32 enabled; //guess -/*008*/ uint32 unknown008; //seen 1019 +/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64) +/*000*/ uint8 status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead +}; + +struct ExpeditionMemberList_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length +}; + +struct ExpeditionMemberListName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status +/*008*/ char name[64]; +}; + +struct ExpeditionLockoutTimerEntry_Struct +{ +/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ uint32 seconds_remaining; +/*000*/ uint32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers +/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256) +}; + +struct ExpeditionLockoutTimers_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0]; +}; + +struct ExpeditionSetLeaderName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ char leader_name[64]; +}; + +struct ExpeditionCommand_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ char name[64]; +}; + +struct ExpeditionCommandSwap_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ char add_player_name[64]; // swap to (player must confirm) +/*068*/ char rem_player_name[64]; // swap from +}; + +struct ExpeditionExpireWarning +{ +/*000*/ uint32 client_id; +/*004*/ uint32 minutes_remaining; +}; + +struct DynamicZoneCompassEntry_Struct +{ +/*000*/ uint16 dz_zone_id; // target dz id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) +/*008*/ uint32 unknown008; /*012*/ float y; /*016*/ float x; /*020*/ float z; }; -struct ExpeditionCompass_Struct +struct DynamicZoneCompass_Struct { -/*000*/ uint32 clientid; +/*000*/ uint32 client_id; /*004*/ uint32 count; -/*008*/ ExpeditionCompassEntry_Struct entries[0]; +/*008*/ DynamicZoneCompassEntry_Struct entries[0]; }; -struct ExpeditionJoinPrompt_Struct +struct DynamicZoneChooseZoneEntry_Struct { -/*000*/ uint32 clientid; -/*004*/ char player_name[64]; -/*068*/ char expedition_name[64]; +/*000*/ uint16 dz_zone_id; // dz_id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 unknown_id1; // sent back in reply +/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply +/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different +/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64) +}; + +struct DynamicZoneChooseZone_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0]; +}; + +struct DynamicZoneChooseZoneReply_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ uint32 unknown_id1; +/*012*/ uint16 dz_zone_id; +/*014*/ uint16 dz_instance_id; +/*016*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest +/*020*/ uint32 unknown_id2; +/*024*/ uint32 unknown024; +/*028*/ uint32 unknown028; // always same as unknown040 +/*032*/ uint32 unknown032; +/*036*/ uint32 unknown036; +/*040*/ uint32 unknown040; // always same as unknown028 +/*044*/ uint32 unknown044; }; struct AltCurrencySelectItem_Struct { diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 505bca10c..5b97f7110 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -414,15 +414,48 @@ namespace Titanium FINISH_ENCODE(); } + ENCODE(OP_DzChooseZone) + { + SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); + + for (uint32 i = 0; i < emu->count; ++i) + { + buf.WriteUInt16(emu->choices[i].dz_zone_id); + buf.WriteUInt16(emu->choices[i].dz_instance_id); + buf.WriteUInt32(emu->choices[i].unknown_id1); + buf.WriteUInt32(emu->choices[i].dz_type); + buf.WriteUInt32(emu->choices[i].unknown_id2); + buf.WriteString(emu->choices[i].description); + buf.WriteString(emu->choices[i].leader_name); + } + + __packet->size = buf.size(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); + + FINISH_ENCODE(); + } + ENCODE(OP_DzCompass) { - SETUP_VAR_ENCODE(ExpeditionCompass_Struct); - ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); + SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); + ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, + sizeof(structs::DynamicZoneCompass_Struct) + + sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count + ); + OUT(client_id); OUT(count); for (uint32 i = 0; i < emu->count; ++i) { + OUT(entries[i].dz_zone_id); + OUT(entries[i].dz_instance_id); + OUT(entries[i].dz_type); OUT(entries[i].x); OUT(entries[i].y); OUT(entries[i].z); @@ -446,80 +479,60 @@ namespace Titanium ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct); SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct); + OUT(client_id); + OUT(assigned); OUT(max_players); - eq->enabled_max = 1; - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->leader_name, emu->leader_name); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } - ENCODE(OP_DzExpeditionList) + ENCODE(OP_DzExpeditionInvite) { - SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct); + ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct); + SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + OUT(client_id); + strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name)); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + OUT(swapping); + strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name)); + OUT(dz_zone_id); + OUT(dz_instance_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionLockoutTimers) + { + SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event)); - ss.write((const char*)&null_term, sizeof(char)); + buf.WriteString(emu->timers[i].expedition_name); + buf.WriteUInt32(emu->timers[i].seconds_remaining); + buf.WriteUInt32(emu->timers[i].event_type); + buf.WriteString(emu->timers[i].event_name); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } - ENCODE(OP_DzJoinExpeditionConfirm) + ENCODE(OP_DzSetLeaderName) { - ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); - SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); + ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct); - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->player_name, emu->player_name); - - FINISH_ENCODE(); - } - - ENCODE(OP_DzLeaderStatus) - { - SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct); - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - - ss.write((const char*)&client_id, sizeof(uint32)); - //ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->leader_name, strlen(emu->leader_name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//1 - ss.write((const char*)&client_id, sizeof(uint32)); - - __packet->size = ss.str().length(); - __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + OUT(client_id); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } @@ -528,26 +541,43 @@ namespace Titanium { SETUP_VAR_ENCODE(ExpeditionMemberList_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].name, strlen(emu->entries[i].name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].status, sizeof(char)); + buf.WriteString(emu->members[i].name); + buf.WriteUInt8(emu->members[i].status); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } + ENCODE(OP_DzMemberListName) + { + ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct); + + OUT(client_id); + OUT(add_name); + strn0cpy(eq->name, emu->name, sizeof(eq->name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzMemberListStatus) + { + auto emu = reinterpret_cast((*p)->pBuffer); + if (emu->count == 1) + { + ENCODE_FORWARD(OP_DzMemberList); + } + } + ENCODE(OP_Emote) { EQApplicationPacket *in = *p; @@ -1943,6 +1973,83 @@ namespace Titanium FINISH_DIRECT_DECODE(); } + DECODE(OP_DzAddPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzChooseZoneReply) + { + DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct); + SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct); + + emu->unknown000 = eq->unknown000; + emu->unknown008 = eq->unknown004; + IN(unknown_id1); + IN(dz_zone_id); + IN(dz_instance_id); + IN(dz_type); + IN(unknown_id2); + emu->unknown028 = eq->unknown024; + emu->unknown032 = eq->unknown028; + emu->unknown036 = eq->unknown032; + emu->unknown040 = eq->unknown036; + emu->unknown044 = eq->unknown040; + emu->unknown048 = eq->unknown044; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzExpeditionInviteResponse) + { + DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct); + SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct); + + IN(dz_zone_id); + IN(dz_instance_id); + IN(accepted); + IN(swapping); + strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzMakeLeader) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzRemovePlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzSwapPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct); + + strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name)); + strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name)); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_Emote) { unsigned char *__eq_buffer = __packet->pBuffer; diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index d3c8c1dde..961c850fe 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -32,13 +32,16 @@ E(OP_Damage) E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DeleteSpawn) +E(OP_DzChooseZone) E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzExpeditionList) -E(OP_DzJoinExpeditionConfirm) -E(OP_DzLeaderStatus) +E(OP_DzExpeditionInvite) +E(OP_DzExpeditionLockoutTimers) E(OP_DzMemberList) +E(OP_DzMemberListName) +E(OP_DzMemberListStatus) +E(OP_DzSetLeaderName) E(OP_Emote) E(OP_FormattedMessage) E(OP_GroundSpawn) @@ -86,6 +89,12 @@ D(OP_CharacterCreate) D(OP_ClientUpdate) D(OP_Consume) D(OP_DeleteItem) +D(OP_DzAddPlayer) +D(OP_DzChooseZoneReply) +D(OP_DzExpeditionInviteResponse) +D(OP_DzMakeLeader) +D(OP_DzRemovePlayer) +D(OP_DzSwapPlayer) D(OP_Emote) D(OP_FaceChange) D(OP_InspectAnswer) diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index f620089d6..ba5bb6ab5 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -3299,43 +3299,150 @@ struct VeteranReward /*004*/ VeteranRewardItem item; }; -struct ExpeditionExpireWarning +struct ExpeditionInvite_Struct +{ +/*000*/ uint32 client_id; +/*004*/ char inviter_name[64]; +/*068*/ char expedition_name[128]; +/*196*/ uint8 swapping; // 0: adding 1: swapping +/*197*/ char swap_name[64]; // if swapping, swap name being removed +/*261*/ uint8 padding[3]; +/*264*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply +/*268*/ uint16 dz_instance_id; +}; + +struct ExpeditionInviteResponse_Struct { /*000*/ uint32 unknown000; -/*004*/ uint32 minutes_remaining; +/*004*/ uint16 dz_zone_id; // dz_id pair sent in invite +/*006*/ uint16 dz_instance_id; +/*008*/ uint8 accepted; // 0: declined 1: accepted +/*009*/ uint8 swapping; // 0: adding 1: swapping (sent in invite) +/*010*/ char swap_name[64]; // swap name sent in invite +/*074*/ uint8 unknown078; // padding/garbage? +/*075*/ uint8 unknown079; // padding/garbage? }; struct ExpeditionInfo_Struct { -/*000*/ uint32 clientid; -/*004*/ uint32 enabled_max; +/*000*/ uint32 client_id; +/*004*/ uint32 assigned; // padded bool /*008*/ uint32 max_players; -/*012*/ char expedition_name[128]; -/*142*/ char leader_name[64]; +/*012*/ char expedition_name[128]; +/*140*/ char leader_name[64]; }; -struct ExpeditionCompassEntry_Struct +struct ExpeditionMemberEntry_Struct { -/*000*/ float unknown000; //seen *((uint32*)) = 1584791871 -/*004*/ uint32 enabled; //guess -/*008*/ uint32 unknown008; //seen 1019 +/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64) +/*000*/ uint8 status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead +}; + +struct ExpeditionMemberList_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length +}; + +struct ExpeditionMemberListName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status +/*008*/ char name[64]; +}; + +struct ExpeditionLockoutTimerEntry_Struct +{ +/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ uint32 seconds_remaining; +/*000*/ uint32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers +/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256) +}; + +struct ExpeditionLockoutTimers_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0]; +}; + +struct ExpeditionSetLeaderName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ char leader_name[64]; +}; + +struct ExpeditionCommand_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ char name[64]; +}; + +struct ExpeditionCommandSwap_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ char add_player_name[64]; // swap to (player must confirm) +/*068*/ char rem_player_name[64]; // swap from +}; + +struct ExpeditionExpireWarning +{ +/*000*/ uint32 client_id; +/*004*/ uint32 minutes_remaining; +}; + +struct DynamicZoneCompassEntry_Struct +{ +/*000*/ uint16 dz_zone_id; // target dz id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) +/*008*/ uint32 unknown008; /*012*/ float y; /*016*/ float x; /*020*/ float z; }; -struct ExpeditionCompass_Struct +struct DynamicZoneCompass_Struct { -/*000*/ uint32 clientid; +/*000*/ uint32 client_id; /*004*/ uint32 count; -/*008*/ ExpeditionCompassEntry_Struct entries[0]; +/*008*/ DynamicZoneCompassEntry_Struct entries[0]; }; -struct ExpeditionJoinPrompt_Struct +struct DynamicZoneChooseZoneEntry_Struct { -/*000*/ uint32 clientid; -/*004*/ char player_name[64]; -/*068*/ char expedition_name[64]; +/*000*/ uint16 dz_zone_id; // dz_id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 unknown_id1; // sent back in reply +/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply +/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different +/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64) +}; + +struct DynamicZoneChooseZone_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0]; +}; + +struct DynamicZoneChooseZoneReply_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ uint32 unknown_id1; +/*012*/ uint16 dz_zone_id; +/*014*/ uint16 dz_instance_id; +/*016*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest +/*020*/ uint32 unknown_id2; +/*024*/ uint32 unknown024; +/*028*/ uint32 unknown028; // always same as unknown040 +/*032*/ uint32 unknown032; +/*036*/ uint32 unknown036; +/*040*/ uint32 unknown040; // always same as unknown028 +/*044*/ uint32 unknown044; }; struct LFGuild_SearchPlayer_Struct diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 9dfc653b4..fa3000346 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -613,14 +613,48 @@ namespace UF FINISH_ENCODE(); } + ENCODE(OP_DzChooseZone) + { + SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); + + for (uint32 i = 0; i < emu->count; ++i) + { + buf.WriteUInt16(emu->choices[i].dz_zone_id); + buf.WriteUInt16(emu->choices[i].dz_instance_id); + buf.WriteUInt32(emu->choices[i].unknown_id1); + buf.WriteUInt32(emu->choices[i].dz_type); + buf.WriteUInt32(emu->choices[i].unknown_id2); + buf.WriteString(emu->choices[i].description); + buf.WriteString(emu->choices[i].leader_name); + } + + __packet->size = buf.size(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); + + FINISH_ENCODE(); + } + ENCODE(OP_DzCompass) { - SETUP_VAR_ENCODE(ExpeditionCompass_Struct); - ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); + SETUP_VAR_ENCODE(DynamicZoneCompass_Struct); + ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct, + sizeof(structs::DynamicZoneCompass_Struct) + + sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count + ); + + OUT(client_id); OUT(count); for (uint32 i = 0; i < emu->count; ++i) { + OUT(entries[i].dz_zone_id); + OUT(entries[i].dz_instance_id); + OUT(entries[i].dz_type); OUT(entries[i].x); OUT(entries[i].y); OUT(entries[i].z); @@ -644,81 +678,60 @@ namespace UF ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct); SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct); + OUT(client_id); + OUT(assigned); OUT(max_players); - eq->unknown004 = 785316192; - eq->unknown008 = 435601; - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->leader_name, emu->leader_name); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } - ENCODE(OP_DzExpeditionList) + ENCODE(OP_DzExpeditionInvite) { - SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct); + ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct); + SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + OUT(client_id); + strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name)); + strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + OUT(swapping); + strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name)); + OUT(dz_zone_id); + OUT(dz_instance_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionLockoutTimers) + { + SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct); + + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event)); - ss.write((const char*)&null_term, sizeof(char)); + buf.WriteString(emu->timers[i].expedition_name); + buf.WriteUInt32(emu->timers[i].seconds_remaining); + buf.WriteUInt32(emu->timers[i].event_type); + buf.WriteString(emu->timers[i].event_name); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } - ENCODE(OP_DzJoinExpeditionConfirm) + ENCODE(OP_DzSetLeaderName) { - ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); - SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); + ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct); - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->player_name, emu->player_name); - - FINISH_ENCODE(); - } - - ENCODE(OP_DzLeaderStatus) - { - SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct); - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - uint32 client_id = 0; - uint8 null_term = 0; - - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write(emu->leader_name, strlen(emu->leader_name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&client_id, sizeof(uint32));//1 - ss.write((const char*)&client_id, sizeof(uint32)); - - __packet->size = ss.str().length(); - __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + OUT(client_id); + strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); FINISH_ENCODE(); } @@ -727,26 +740,43 @@ namespace UF { SETUP_VAR_ENCODE(ExpeditionMemberList_Struct); - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - - uint32 client_id = 0; - uint8 null_term = 0; - ss.write((const char*)&client_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint32)); + SerializeBuffer buf; + buf.WriteUInt32(emu->client_id); + buf.WriteUInt32(emu->count); for (uint32 i = 0; i < emu->count; ++i) { - ss.write(emu->entries[i].name, strlen(emu->entries[i].name)); - ss.write((const char*)&null_term, sizeof(char)); - ss.write((const char*)&emu->entries[i].status, sizeof(char)); + buf.WriteString(emu->members[i].name); + buf.WriteUInt8(emu->members[i].status); } - __packet->size = ss.str().length(); + __packet->size = buf.size(); __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + memcpy(__packet->pBuffer, buf.buffer(), __packet->size); FINISH_ENCODE(); } + ENCODE(OP_DzMemberListName) + { + ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct); + SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct); + + OUT(client_id); + OUT(add_name); + strn0cpy(eq->name, emu->name, sizeof(eq->name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzMemberListStatus) + { + auto emu = reinterpret_cast((*p)->pBuffer); + if (emu->count == 1) + { + ENCODE_FORWARD(OP_DzMemberList); + } + } + ENCODE(OP_Emote) { EQApplicationPacket *in = *p; @@ -3315,6 +3345,84 @@ namespace UF FINISH_DIRECT_DECODE(); } + DECODE(OP_DzAddPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzChooseZoneReply) + { + DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct); + SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct); + + IN(unknown000); + IN(unknown004); + IN(unknown008); + IN(unknown_id1); + IN(dz_zone_id); + IN(dz_instance_id); + IN(dz_type); + IN(unknown_id2); + IN(unknown028); + IN(unknown032); + IN(unknown036); + IN(unknown040); + IN(unknown044); + IN(unknown048); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzExpeditionInviteResponse) + { + DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct); + SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct); + + IN(dz_zone_id); + IN(dz_instance_id); + IN(accepted); + IN(swapping); + strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzMakeLeader) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzRemovePlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct); + + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DzSwapPlayer) + { + DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct); + SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct); + + strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name)); + strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name)); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_Emote) { unsigned char *__eq_buffer = __packet->pBuffer; diff --git a/common/patches/uf_ops.h b/common/patches/uf_ops.h index 9d7742cf0..76b7e014b 100644 --- a/common/patches/uf_ops.h +++ b/common/patches/uf_ops.h @@ -38,13 +38,16 @@ E(OP_Damage) E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DisciplineUpdate) +E(OP_DzChooseZone) E(OP_DzCompass) E(OP_DzExpeditionEndsWarning) E(OP_DzExpeditionInfo) -E(OP_DzExpeditionList) -E(OP_DzJoinExpeditionConfirm) -E(OP_DzLeaderStatus) +E(OP_DzExpeditionInvite) +E(OP_DzExpeditionLockoutTimers) E(OP_DzMemberList) +E(OP_DzMemberListName) +E(OP_DzMemberListStatus) +E(OP_DzSetLeaderName) E(OP_Emote) E(OP_ExpansionInfo) E(OP_FormattedMessage) @@ -120,6 +123,12 @@ D(OP_ConsiderCorpse) D(OP_Consume) D(OP_Damage) D(OP_DeleteItem) +D(OP_DzAddPlayer) +D(OP_DzChooseZoneReply) +D(OP_DzExpeditionInviteResponse) +D(OP_DzMakeLeader) +D(OP_DzRemovePlayer) +D(OP_DzSwapPlayer) D(OP_Emote) D(OP_EnvDamage) D(OP_FaceChange) diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 895881a7a..7a8eab757 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -4250,52 +4250,160 @@ struct VeteranReward /*012*/ VeteranRewardItem items[8]; }; -struct ExpeditionEntryHeader_Struct + +struct ExpeditionInvite_Struct +{ +/*000*/ uint32 client_id; // unique character id +/*004*/ uint32 unknown004; +/*008*/ char inviter_name[64]; +/*072*/ char expedition_name[128]; +/*200*/ uint8 swapping; // 0: adding 1: swapping +/*201*/ char swap_name[64]; // if swapping, swap name being removed +/*265*/ uint8 padding[3]; +/*268*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply +/*270*/ uint16 dz_instance_id; +}; + +struct ExpeditionInviteResponse_Struct { /*000*/ uint32 unknown000; -/*000*/ uint32 number_of_entries; -}; - -struct ExpeditionJoinPrompt_Struct -{ -/*000*/ uint32 clientid; /*004*/ uint32 unknown004; -/*008*/ char player_name[64]; -/*072*/ char expedition_name[64]; -}; - -struct ExpeditionExpireWarning -{ -/*000*/ uint32 clientid; -/*004*/ uint32 unknown004; -/*008*/ uint32 minutes_remaining; +/*008*/ uint16 dz_zone_id; // dz_id pair sent in invite +/*010*/ uint16 dz_instance_id; +/*012*/ uint8 accepted; // 0: declined 1: accepted +/*013*/ uint8 swapping; // 0: adding 1: swapping (sent in invite) +/*014*/ char swap_name[64]; // swap name sent in invite +/*078*/ uint8 unknown078; // padding garbage? +/*079*/ uint8 unknown079; // padding garbage? }; struct ExpeditionInfo_Struct { -/*000*/ uint32 clientid; +/*000*/ uint32 client_id; /*004*/ uint32 unknown004; -/*008*/ uint32 unknown008; +/*008*/ uint32 assigned; // padded bool /*012*/ uint32 max_players; -/*016*/ char expedition_name[128]; -/*142*/ char leader_name[64]; +/*016*/ char expedition_name[128]; +/*144*/ char leader_name[64]; }; -struct ExpeditionCompassEntry_Struct +struct ExpeditionMemberEntry_Struct { -/*000*/ float unknown000; //seen *((uint32*)) = 1584791871 -/*004*/ uint32 enabled; //guess -/*008*/ uint32 unknown008; //seen 1019 +/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64) +/*000*/ uint8 status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead +}; + +struct ExpeditionMemberList_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; // number of players in window +/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length +}; + +struct ExpeditionMemberListName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status +/*012*/ char name[64]; +}; + +struct ExpeditionLockoutTimerEntry_Struct +{ +/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ uint32 seconds_remaining; +/*000*/ uint32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers +/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256) +}; + +struct ExpeditionLockoutTimers_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0]; +}; + +struct ExpeditionSetLeaderName_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ char leader_name[64]; +}; + +struct ExpeditionCommand_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ char name[64]; +}; + +struct ExpeditionCommandSwap_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ char add_player_name[64]; // swap to (player must confirm) +/*072*/ char rem_player_name[64]; // swap from +}; + +struct ExpeditionExpireWarning +{ +/*000*/ uint32 client_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 minutes_remaining; +}; + +struct DynamicZoneCompassEntry_Struct +{ +/*000*/ uint16 dz_zone_id; // target dz id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green) +/*008*/ uint32 unknown008; /*012*/ float y; /*016*/ float x; /*020*/ float z; }; -struct ExpeditionCompass_Struct +struct DynamicZoneCompass_Struct { -/*000*/ uint32 clientid; +/*000*/ uint32 client_id; /*004*/ uint32 count; -/*008*/ ExpeditionCompassEntry_Struct entries[0]; +/*008*/ DynamicZoneCompassEntry_Struct entries[0]; +}; + +struct DynamicZoneChooseZoneEntry_Struct +{ +/*000*/ uint16 dz_zone_id; // dz_id pair +/*002*/ uint16 dz_instance_id; +/*004*/ uint32 unknown_id1; // sent back in reply +/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply +/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different +/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128) +/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64) +}; + +struct DynamicZoneChooseZone_Struct +{ +/*000*/ uint32 client_id; +/*004*/ uint32 count; +/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0]; +}; + +struct DynamicZoneChooseZoneReply_Struct +{ +/*000*/ uint32 unknown000; // ff ff ff ff +/*004*/ uint32 unknown004; // seen 69 00 00 00 +/*008*/ uint32 unknown008; // ff ff ff ff +/*012*/ uint32 unknown_id1; // from choose zone entry message +/*016*/ uint16 dz_zone_id; // dz_id pair +/*018*/ uint16 dz_instance_id; +/*020*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest +/*024*/ uint32 unknown_id2; // from choose zone entry message +/*028*/ uint32 unknown028; // 00 00 00 00 +/*032*/ uint32 unknown032; // always same as unknown044 +/*036*/ uint32 unknown036; +/*040*/ uint32 unknown040; +/*044*/ uint32 unknown044; // always same as unknown032 +/*048*/ uint32 unknown048; // seen 01 00 00 00 and 02 00 00 00 }; struct AltCurrencySelectItem_Struct { diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 6e638ba1a..76178bf62 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -375,16 +375,18 @@ OP_DzRemovePlayer=0x0dc1 OP_DzSwapPlayer=0x4995 OP_DzMakeLeader=0x17b2 OP_DzPlayerList=0x1aff -OP_DzJoinExpeditionConfirm=0x30df -OP_DzJoinExpeditionReply=0x15d4 +OP_DzExpeditionInvite=0x30df +OP_DzExpeditionInviteResponse=0x15d4 OP_DzExpeditionInfo=0x3861 -OP_DzExpeditionList=0x0b3b -OP_DzMemberStatus=0x26c2 -OP_DzLeaderStatus=0x4021 -OP_DzExpeditionEndsWarning=0x32eb +OP_DzExpeditionLockoutTimers=0x0b3b OP_DzMemberList=0x348f +OP_DzMemberListName=0x26c2 +OP_DzMemberListStatus=0x0000 +OP_DzSetLeaderName=0x4021 +OP_DzExpeditionEndsWarning=0x32eb OP_DzCompass=0x0e01 # Was 0x4f09 OP_DzChooseZone=0x6e5e # Maybe 0x29d6 +OP_DzChooseZoneReply=0x0000 # New Opcodes OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ? diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index f62b90dd4..96f3258a8 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -368,25 +368,28 @@ OP_AggroMeterLockTarget=0x1643 OP_AggroMeterTargetInfo=0x16bc OP_AggroMeterUpdate=0x1781 OP_UnderWorld=0x2eb3 # clients sends up when they detect an underworld issue, might be useful for cheat detection +OP_KickPlayers=0x6770 # Expeditions +OP_DzQuit=0xb2e3 +OP_DzListTimers=0x7b68 OP_DzAddPlayer=0x4701 OP_DzRemovePlayer=0x1abc OP_DzSwapPlayer=0x405b OP_DzMakeLeader=0x543d OP_DzPlayerList=0x14c6 -OP_DzJoinExpeditionConfirm=0x7f4b -OP_DzJoinExpeditionReply=0x1950 -OP_DzListTimers=0x7b68 +OP_DzExpeditionInvite=0x7f4b +OP_DzExpeditionInviteResponse=0x1950 OP_DzExpeditionInfo=0x9119 -OP_DzExpeditionList=0x205f -OP_DzQuit=0xb2e3 -OP_DzMemberStatus=0x32f0 -OP_DzLeaderStatus=0x3de9 +OP_DzExpeditionLockoutTimers=0x205f OP_DzMemberList=0x5ae4 -OP_DzExpeditionEndsWarning=0x383c +OP_DzMemberListName=0x32f0 +OP_DzMemberListStatus=0x12F5 +OP_DzSetLeaderName=0x3de9 +OP_DzExpeditionEndsWarning=0x5189 OP_DzCompass=0x3e0e OP_DzChooseZone=0x0b7d +OP_DzChooseZoneReply=0x4de1 # New Opcodes OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ? diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index 05e4a335f..1ef8a138a 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -367,17 +367,18 @@ OP_DzRemovePlayer=0xa682 OP_DzSwapPlayer=0x0d8d OP_DzMakeLeader=0x1caa OP_DzPlayerList=0x74ca -OP_DzJoinExpeditionConfirm=0x1772 -OP_DzJoinExpeditionReply=0x3c13 +OP_DzExpeditionInvite=0x1772 +OP_DzExpeditionInviteResponse=0x3c13 OP_DzExpeditionInfo=0x128e -OP_DzMemberStatus=0x4661 -OP_DzLeaderStatus=0x226f -OP_DzExpeditionEndsWarning=0x1879 -OP_DzExpeditionList=0x3657 +OP_DzExpeditionLockoutTimers=0x3657 OP_DzMemberList=0x74e4 +OP_DzMemberListName=0x4661 +OP_DzMemberListStatus=0x1d99 +OP_DzSetLeaderName=0x226f +OP_DzExpeditionEndsWarning=0x1879 OP_DzCompass=0x35d3 OP_DzChooseZone=0x0d8a -#0x1d99 was grouped with these too but I don't really know it's purpose. +OP_DzChooseZoneReply=0x5a67 # New Opcodes OP_SpawnPositionUpdate=0x4656 # diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index c6d754ba3..1c5fd3eda 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -348,16 +348,18 @@ OP_DzRemovePlayer=0x2ce8 OP_DzSwapPlayer=0x2c3e OP_DzMakeLeader=0x1a75 OP_DzPlayerList=0x5116 -OP_DzJoinExpeditionConfirm=0x1793 -OP_DzJoinExpeditionReply=0x7a6f +OP_DzExpeditionInvite=0x1793 +OP_DzExpeditionInviteResponse=0x7a6f OP_DzExpeditionInfo=0x60a6 -OP_DzMemberStatus=0x0516 -OP_DzLeaderStatus=0x79d3 -OP_DzExpeditionEndsWarning=0x5153 -OP_DzExpeditionList=0x02ac +OP_DzExpeditionLockoutTimers=0x02ac OP_DzMemberList=0x5e14 +OP_DzMemberListName=0x0516 +OP_DzMemberListStatus=0x0000 +OP_DzSetLeaderName=0x79d3 +OP_DzExpeditionEndsWarning=0x5153 OP_DzCompass=0x531d OP_DzChooseZone=0x3c5b +OP_DzChooseZoneReply=0x0000 #Looting OP_LootRequest=0x36E3 #Trevius 02/16/09 diff --git a/utils/patches/patch_Titanium.conf b/utils/patches/patch_Titanium.conf index ade2576aa..f984f88db 100644 --- a/utils/patches/patch_Titanium.conf +++ b/utils/patches/patch_Titanium.conf @@ -297,17 +297,18 @@ OP_DzRemovePlayer=0x540b OP_DzSwapPlayer=0x794a OP_DzMakeLeader=0x0ce9 OP_DzPlayerList=0xada0 -OP_DzJoinExpeditionConfirm=0x3817 -OP_DzJoinExpeditionReply=0x5da9 +OP_DzExpeditionInvite=0x3817 +OP_DzExpeditionInviteResponse=0x5da9 OP_DzExpeditionInfo=0x98e -OP_DzMemberStatus=0x1826 -OP_DzLeaderStatus=0x7abc -OP_DzExpeditionEndsWarning=0x1c3f -OP_DzExpeditionList=0x7c12 +OP_DzExpeditionLockoutTimers=0x7c12 OP_DzMemberList=0x9b6 +OP_DzMemberListName=0x1826 +OP_DzMemberListStatus=0x330d +OP_DzSetLeaderName=0x7abc +OP_DzExpeditionEndsWarning=0x1c3f OP_DzCompass=0x28aa OP_DzChooseZone=0x1022 -#0x330d is something but I'm not sure what yet. +OP_DzChooseZoneReply=0x20e7 #bazaar trader stuff stuff: #become and buy from diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index 101fafde1..8efce91f6 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -377,16 +377,18 @@ OP_DzRemovePlayer=0x054e OP_DzSwapPlayer=0x4661 OP_DzMakeLeader=0x226f OP_DzPlayerList=0x74e4 -OP_DzJoinExpeditionConfirm=0x3c5e -OP_DzJoinExpeditionReply=0x1154 +OP_DzExpeditionInvite=0x3c5e +OP_DzExpeditionInviteResponse=0x1154 OP_DzExpeditionInfo=0x1150 -OP_DzMemberStatus=0x2d17 -OP_DzLeaderStatus=0x2caf -OP_DzExpeditionEndsWarning=0x6ac2 -OP_DzExpeditionList=0x70d8 +OP_DzExpeditionLockoutTimers=0x70d8 OP_DzMemberList=0x15c4 +OP_DzMemberListName=0x2d17 +OP_DzMemberListStatus=0x0d98 +OP_DzSetLeaderName=0x2caf +OP_DzExpeditionEndsWarning=0x6ac2 OP_DzCompass=0x01cb OP_DzChooseZone=0x65e1 +OP_DzChooseZoneReply=0xa682 #shroud OP_ShroudSelectionWindow=0x72ad diff --git a/zone/client.cpp b/zone/client.cpp index 6338e410f..821c14570 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -6126,8 +6126,8 @@ void Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 coun { auto outapp = new EQApplicationPacket(OP_DzCompass, sizeof(ExpeditionInfo_Struct) + - sizeof(ExpeditionCompassEntry_Struct) * count); - ExpeditionCompass_Struct *ecs = (ExpeditionCompass_Struct*)outapp->pBuffer; + sizeof(DynamicZoneCompassEntry_Struct) * count); + DynamicZoneCompass_Struct *ecs = (DynamicZoneCompass_Struct*)outapp->pBuffer; //ecs->clientid = GetID(); ecs->count = count; diff --git a/zone/lua_packet.cpp b/zone/lua_packet.cpp index 648d6fa87..4936259e6 100644 --- a/zone/lua_packet.cpp +++ b/zone/lua_packet.cpp @@ -788,16 +788,18 @@ luabind::scope lua_register_packet_opcodes() { luabind::value("DzRemovePlayer", static_cast(OP_DzRemovePlayer)), luabind::value("DzSwapPlayer", static_cast(OP_DzSwapPlayer)), luabind::value("DzMakeLeader", static_cast(OP_DzMakeLeader)), - luabind::value("DzJoinExpeditionConfirm", static_cast(OP_DzJoinExpeditionConfirm)), - luabind::value("DzJoinExpeditionReply", static_cast(OP_DzJoinExpeditionReply)), + luabind::value("DzExpeditionInvite", static_cast(OP_DzExpeditionInvite)), + luabind::value("DzExpeditionInviteResponse", static_cast(OP_DzExpeditionInviteResponse)), luabind::value("DzExpeditionInfo", static_cast(OP_DzExpeditionInfo)), - luabind::value("DzMemberStatus", static_cast(OP_DzMemberStatus)), - luabind::value("DzLeaderStatus", static_cast(OP_DzLeaderStatus)), + luabind::value("DzMemberListName", static_cast(OP_DzMemberListName)), + luabind::value("DzMemberListStatus", static_cast(OP_DzMemberListStatus)), + luabind::value("DzSetLeaderName", static_cast(OP_DzSetLeaderName)), luabind::value("DzExpeditionEndsWarning", static_cast(OP_DzExpeditionEndsWarning)), - luabind::value("DzExpeditionList", static_cast(OP_DzExpeditionList)), + luabind::value("DzExpeditionLockoutTimers", static_cast(OP_DzExpeditionLockoutTimers)), luabind::value("DzMemberList", static_cast(OP_DzMemberList)), luabind::value("DzCompass", static_cast(OP_DzCompass)), luabind::value("DzChooseZone", static_cast(OP_DzChooseZone)), + luabind::value("DzChooseZoneReply", static_cast(OP_DzChooseZoneReply)), luabind::value("BuffCreate", static_cast(OP_BuffCreate)), luabind::value("GuildStatus", static_cast(OP_GuildStatus)), luabind::value("BuffRemoveRequest", static_cast(OP_BuffRemoveRequest)),