diff options
author | Shauren <shauren.trinity@gmail.com> | 2017-07-12 00:05:41 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2017-07-12 00:05:41 +0200 |
commit | 0d06fcee17274148ef6b5516b8cd03e3b8372f9a (patch) | |
tree | ec07f780936711aa85dc84e4b152166283b1ea7c | |
parent | 42622aa3d4082c29887a47427745d25d79d4c7f9 (diff) |
Core/PacketIO: Updated and enabled LFG packets
22 files changed, 1234 insertions, 706 deletions
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 79296f43d1c..356a519c238 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -993,7 +993,7 @@ void Battleground::RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool Sen if (SendPacket) { WorldPackets::Battleground::BattlefieldStatusNone battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), player->GetBattlegroundQueueJoinTime(bgQueueTypeId), m_ArenaType); + sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), player->GetBattlegroundQueueJoinTime(bgQueueTypeId)); player->SendDirectMessage(battlefieldStatus.Write()); } diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 4be999c7d4a..c779adce640 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -169,7 +169,7 @@ void BattlegroundMgr::BuildBattlegroundStatusHeader(WorldPackets::Battleground:: { header->Ticket.RequesterGuid = player->GetGUID(); header->Ticket.Id = ticketId; - header->Ticket.Type = bg->isArena() ? arenaType : 1; + header->Ticket.Type = WorldPackets::LFG::RideType::Battlegrounds; header->Ticket.Time = joinTime; header->QueueID = bg->GetQueueId(); header->RangeMin = bg->GetMinLevel(); @@ -180,11 +180,11 @@ void BattlegroundMgr::BuildBattlegroundStatusHeader(WorldPackets::Battleground:: header->TournamentRules = false; } -void BattlegroundMgr::BuildBattlegroundStatusNone(WorldPackets::Battleground::BattlefieldStatusNone* battlefieldStatus, Player* player, uint32 ticketId, uint32 joinTime, uint32 arenaType) +void BattlegroundMgr::BuildBattlegroundStatusNone(WorldPackets::Battleground::BattlefieldStatusNone* battlefieldStatus, Player* player, uint32 ticketId, uint32 joinTime) { battlefieldStatus->Ticket.RequesterGuid = player->GetGUID(); battlefieldStatus->Ticket.Id = ticketId; - battlefieldStatus->Ticket.Type = arenaType; + battlefieldStatus->Ticket.Type = WorldPackets::LFG::RideType::Battlegrounds; battlefieldStatus->Ticket.Time = joinTime; } @@ -220,7 +220,7 @@ void BattlegroundMgr::BuildBattlegroundStatusFailed(WorldPackets::Battleground:: { battlefieldStatus->Ticket.RequesterGuid = pPlayer->GetGUID(); battlefieldStatus->Ticket.Id = ticketId; - battlefieldStatus->Ticket.Type = arenaType; + battlefieldStatus->Ticket.Type = WorldPackets::LFG::RideType::Battlegrounds; battlefieldStatus->Ticket.Time = pPlayer->GetBattlegroundQueueJoinTime(BGQueueTypeId(bg->GetTypeID(), arenaType)); battlefieldStatus->QueueID = bg->GetQueueId(); battlefieldStatus->Reason = result; diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h index a240d53d916..e69c934ea91 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.h +++ b/src/server/game/Battlegrounds/BattlegroundMgr.h @@ -88,7 +88,7 @@ class TC_GAME_API BattlegroundMgr /* Packet Building */ void SendBattlegroundList(Player* player, ObjectGuid const& guid, BattlegroundTypeId bgTypeId); void BuildBattlegroundStatusHeader(WorldPackets::Battleground::BattlefieldStatusHeader* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 arenaType); - void BuildBattlegroundStatusNone(WorldPackets::Battleground::BattlefieldStatusNone* battlefieldStatus, Player* player, uint32 ticketId, uint32 joinTime, uint32 arenaType); + void BuildBattlegroundStatusNone(WorldPackets::Battleground::BattlefieldStatusNone* battlefieldStatus, Player* player, uint32 ticketId, uint32 joinTime); void BuildBattlegroundStatusNeedConfirmation(WorldPackets::Battleground::BattlefieldStatusNeedConfirmation* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 timeout, uint32 arenaType); void BuildBattlegroundStatusActive(WorldPackets::Battleground::BattlefieldStatusActive* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 arenaType); void BuildBattlegroundStatusQueued(WorldPackets::Battleground::BattlefieldStatusQueued* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 avgWaitTime, uint32 arenaType, bool asGroup); diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp index bd0c588c627..54e66f968c3 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp +++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp @@ -398,7 +398,7 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount) // queue->removeplayer, it causes bugs WorldPackets::Battleground::BattlefieldStatusNone battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, plr2, queueSlot, plr2->GetBattlegroundQueueJoinTime(bgQueueTypeId), group->ArenaType); + sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, plr2, queueSlot, plr2->GetBattlegroundQueueJoinTime(bgQueueTypeId)); plr2->SendDirectMessage(battlefieldStatus.Write()); } // then actually delete, this may delete the group as well! @@ -1080,7 +1080,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) sBattlegroundMgr->ScheduleQueueUpdate(0, 0, m_BgQueueTypeId, m_BgTypeId, bg->GetBracketId()); WorldPackets::Battleground::BattlefieldStatusNone battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, player, queueSlot, player->GetBattlegroundQueueJoinTime(m_BgQueueTypeId), m_ArenaType); + sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, player, queueSlot, player->GetBattlegroundQueueJoinTime(m_BgQueueTypeId)); player->SendDirectMessage(battlefieldStatus.Write()); } } diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h index 3b6e29862a1..4b20b28eb47 100644 --- a/src/server/game/DungeonFinding/LFG.h +++ b/src/server/game/DungeonFinding/LFG.h @@ -55,17 +55,21 @@ enum LfgUpdateType LFG_UPDATETYPE_PROPOSAL_DECLINED = 10, LFG_UPDATETYPE_GROUP_FOUND = 11, LFG_UPDATETYPE_ADDED_TO_QUEUE = 13, - LFG_UPDATETYPE_PROPOSAL_BEGIN = 14, - LFG_UPDATETYPE_UPDATE_STATUS = 15, - LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE = 16, - LFG_UPDATETYPE_GROUP_DISBAND_UNK16 = 17, // FIXME: Sometimes at group disband - LFG_UPDATETYPE_JOIN_QUEUE_INITIAL = 24, - LFG_UPDATETYPE_DUNGEON_FINISHED = 25, - LFG_UPDATETYPE_PARTY_ROLE_NOT_AVAILABLE = 43, - LFG_UPDATETYPE_JOIN_LFG_OBJECT_FAILED = 45, + LFG_UPDATETYPE_SUSPENDED_QUEUE = 14, + LFG_UPDATETYPE_PROPOSAL_BEGIN = 15, + LFG_UPDATETYPE_UPDATE_STATUS = 16, + LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE = 17, + LFG_UPDATETYPE_GROUP_DISBAND_UNK16 = 18, // FIXME: Sometimes at group disband + LFG_UPDATETYPE_JOIN_QUEUE_INITIAL = 25, + LFG_UPDATETYPE_DUNGEON_FINISHED = 26, + LFG_UPDATETYPE_PARTY_ROLE_NOT_AVAILABLE = 46, + LFG_UPDATETYPE_JOIN_LFG_OBJECT_FAILED = 48, + LFG_UPDATETYPE_REMOVED_LEVELUP = 49, + LFG_UPDATETYPE_REMOVED_XP_TOGGLE = 50, + LFG_UPDATETYPE_REMOVED_FACTION_CHANGE = 51 }; -enum LfgState +enum LfgState : uint8 { LFG_STATE_NONE, // Not using LFG / LFR LFG_STATE_ROLECHECK, // Rolecheck active @@ -77,6 +81,15 @@ enum LfgState LFG_STATE_RAIDBROWSER // Using Raid finder }; +enum LfgQueueType +{ + LFG_QUEUE_DUNGEON = 1, + LFG_QUEUE_LFR = 2, + LFG_QUEUE_SCENARIO = 3, + LFG_QUEUE_FLEX = 4, + LFG_QUEUE_WORLD_PVP = 5 +}; + /// Instance lock types enum LfgLockStatusType { diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 5b63f36dfbf..819a2c842fd 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -422,21 +422,21 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons) // Check player or group member restrictions if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER)) - joinData.result = LFG_JOIN_NOT_MEET_REQS; + joinData.result = LFG_JOIN_NO_SLOTS_PLAYER; else if (player->InBattleground() || player->InArena() || player->InBattlegroundQueue()) - joinData.result = LFG_JOIN_USING_BG_SYSTEM; + joinData.result = LFG_JOIN_CANT_USE_DUNGEONS; else if (player->HasAura(LFG_SPELL_DUNGEON_DESERTER)) - joinData.result = LFG_JOIN_DESERTER; + joinData.result = LFG_JOIN_DESERTER_PLAYER; else if (player->HasAura(LFG_SPELL_DUNGEON_COOLDOWN)) - joinData.result = LFG_JOIN_RANDOM_COOLDOWN; + joinData.result = LFG_JOIN_RANDOM_COOLDOWN_PLAYER; else if (dungeons.empty()) - joinData.result = LFG_JOIN_NOT_MEET_REQS; + joinData.result = LFG_JOIN_NO_SLOTS_PLAYER; else if (player->HasAura(9454)) // check Freeze debuff - joinData.result = LFG_JOIN_NOT_MEET_REQS; + joinData.result = LFG_JOIN_NO_SLOTS_PLAYER; else if (grp) { if (grp->GetMembersCount() > MAX_GROUP_SIZE) - joinData.result = LFG_JOIN_TOO_MUCH_MEMBERS; + joinData.result = LFG_JOIN_TOO_MANY_MEMBERS; else { uint8 memberCount = 0; @@ -445,13 +445,13 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons) if (Player* plrg = itr->GetSource()) { if (!plrg->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER)) - joinData.result = LFG_JOIN_INTERNAL_ERROR; + joinData.result = LFG_JOIN_NO_LFG_OBJECT; if (plrg->HasAura(LFG_SPELL_DUNGEON_DESERTER)) - joinData.result = LFG_JOIN_PARTY_DESERTER; + joinData.result = LFG_JOIN_DESERTER_PARTY; else if (plrg->HasAura(LFG_SPELL_DUNGEON_COOLDOWN)) - joinData.result = LFG_JOIN_PARTY_RANDOM_COOLDOWN; + joinData.result = LFG_JOIN_RANDOM_COOLDOWN_PARTY; else if (plrg->InBattleground() || plrg->InArena() || plrg->InBattlegroundQueue()) - joinData.result = LFG_JOIN_USING_BG_SYSTEM; + joinData.result = LFG_JOIN_CANT_USE_DUNGEONS; else if (plrg->HasAura(9454)) // check Freeze debuff joinData.result = LFG_JOIN_PARTY_NOT_MEET_REQS; ++memberCount; @@ -460,7 +460,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons) } if (joinData.result == LFG_JOIN_OK && memberCount != grp->GetMembersCount()) - joinData.result = LFG_JOIN_DISCONNECTED; + joinData.result = LFG_JOIN_MEMBERS_NOT_PRESENT; } } else @@ -478,23 +478,23 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons) { case LFG_TYPE_RANDOM: if (dungeons.size() > 1) // Only allow 1 random dungeon - joinData.result = LFG_JOIN_DUNGEON_INVALID; + joinData.result = LFG_JOIN_INVALID_SLOT; else rDungeonId = (*dungeons.begin()); // No break on purpose (Random can only be dungeon or heroic dungeon) case LFG_TYPE_HEROIC: case LFG_TYPE_DUNGEON: if (isRaid) - joinData.result = LFG_JOIN_MIXED_RAID_DUNGEON; + joinData.result = LFG_JOIN_MISMATCHED_SLOTS; isDungeon = true; break; case LFG_TYPE_RAID: if (isDungeon) - joinData.result = LFG_JOIN_MIXED_RAID_DUNGEON; + joinData.result = LFG_JOIN_MISMATCHED_SLOTS; isRaid = true; break; default: - joinData.result = LFG_JOIN_DUNGEON_INVALID; + joinData.result = LFG_JOIN_INVALID_SLOT; break; } } @@ -509,7 +509,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons) // if we have lockmap then there are no compatible dungeons GetCompatibleDungeons(dungeons, players, joinData.lockmap, isContinue); if (dungeons.empty()) - joinData.result = grp ? LFG_JOIN_INTERNAL_ERROR : LFG_JOIN_NOT_MEET_REQS; + joinData.result = grp ? LFG_JOIN_NO_LFG_OBJECT : LFG_JOIN_NO_SLOTS_PLAYER; } } @@ -531,6 +531,11 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons) return; } + WorldPackets::LFG::RideTicket ticket; + ticket.RequesterGuid = guid; + ticket.Id = GetQueueId(gguid); + ticket.Type = WorldPackets::LFG::RideType::Lfg; + ticket.Time = int32(time(nullptr)); std::string debugNames = ""; if (grp) // Begin rolecheck { @@ -558,6 +563,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons) ObjectGuid pguid = plrg->GetGUID(); plrg->GetSession()->SendLfgUpdateStatus(updateData, true); SetState(pguid, LFG_STATE_ROLECHECK); + SetTicket(pguid, ticket); if (!isContinue) SetSelectedDungeons(pguid, dungeons); roleCheck.roles[pguid] = 0; @@ -586,10 +592,12 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons) SetSelectedDungeons(guid, dungeons); } // Send update to player - player->GetSession()->SendLfgJoinResult(joinData); - player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE, dungeons), false); - SetState(gguid, LFG_STATE_QUEUED); + SetTicket(guid, ticket); SetRoles(guid, roles); + player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE_INITIAL, dungeons), false); + SetState(guid, LFG_STATE_QUEUED); + player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, dungeons), false); + player->GetSession()->SendLfgJoinResult(joinData); debugNames.append(player->GetName()); } @@ -670,6 +678,15 @@ void LFGMgr::LeaveLfg(ObjectGuid guid, bool disconnected) } } +WorldPackets::LFG::RideTicket const* LFGMgr::GetTicket(ObjectGuid guid) const +{ + auto itr = PlayersStore.find(guid); + if (itr != PlayersStore.end()) + return &itr->second.GetTicket(); + + return nullptr; +} + /** Update the Role check info with the player selected role. @@ -717,11 +734,7 @@ void LFGMgr::UpdateRoleCheck(ObjectGuid gguid, ObjectGuid guid /* = ObjectGuid:: else dungeons = roleCheck.dungeons; - LfgJoinResult joinResult = LFG_JOIN_FAILED; - if (roleCheck.state == LFG_ROLECHECK_MISSING_ROLE || roleCheck.state == LFG_ROLECHECK_WRONG_ROLES) - joinResult = LFG_JOIN_ROLE_CHECK_FAILED; - - LfgJoinResultData joinData = LfgJoinResultData(joinResult, roleCheck.state); + LfgJoinResultData joinData = LfgJoinResultData(LFG_JOIN_ROLE_CHECK_FAILED, roleCheck.state); for (LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it) { ObjectGuid pguid = it->first; @@ -1282,7 +1295,7 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* { TC_LOG_DEBUG("lfg.teleport", "Player %s not in group/lfggroup or dungeon not found!", player->GetName().c_str()); - player->GetSession()->SendLfgTeleportError(uint8(LFG_TELEPORTERROR_INVALID_LOCATION)); + player->GetSession()->SendLfgTeleportError(LFG_TELEPORT_RESULT_NO_RETURN_LOCATION); return; } @@ -1296,20 +1309,20 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* return; } - LfgTeleportError error = LFG_TELEPORTERROR_OK; + LfgTeleportResult error = LFG_TELEPORT_RESULT_NONE; if (!player->IsAlive()) - error = LFG_TELEPORTERROR_PLAYER_DEAD; + error = LFG_TELEPORT_RESULT_DEAD; else if (player->IsFalling() || player->HasUnitState(UNIT_STATE_JUMPING)) - error = LFG_TELEPORTERROR_FALLING; + error = LFG_TELEPORT_RESULT_FALLING; else if (player->IsMirrorTimerActive(FATIGUE_TIMER)) - error = LFG_TELEPORTERROR_FATIGUE; + error = LFG_TELEPORT_RESULT_EXHAUSTION; else if (player->GetVehicle()) - error = LFG_TELEPORTERROR_IN_VEHICLE; + error = LFG_TELEPORT_RESULT_ON_TRANSPORT; else if (!player->GetCharmGUID().IsEmpty()) - error = LFG_TELEPORTERROR_CHARMING; + error = LFG_TELEPORT_RESULT_IMMUNE_TO_SUMMONS; else if (player->HasAura(9454)) // check Freeze debuff - error = LFG_TELEPORTERROR_INVALID_LOCATION; + error = LFG_TELEPORT_RESULT_NO_RETURN_LOCATION; else if (player->GetMapId() != uint32(dungeon->map)) // Do not teleport players in dungeon to the entrance { uint32 mapid = dungeon->map; @@ -1346,13 +1359,13 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* } if (!player->TeleportTo(mapid, x, y, z, orientation)) - error = LFG_TELEPORTERROR_INVALID_LOCATION; + error = LFG_TELEPORT_RESULT_NO_RETURN_LOCATION; } else - error = LFG_TELEPORTERROR_INVALID_LOCATION; + error = LFG_TELEPORT_RESULT_NO_RETURN_LOCATION; - if (error != LFG_TELEPORTERROR_OK) - player->GetSession()->SendLfgTeleportError(uint8(error)); + if (error != LFG_TELEPORT_RESULT_NONE) + player->GetSession()->SendLfgTeleportError(error); TC_LOG_DEBUG("lfg.teleport", "Player %s is being teleported in to map %u " "(x: %f, y: %f, z: %f) Result: %u", player->GetName().c_str(), dungeon->map, @@ -1744,6 +1757,11 @@ void LFGMgr::DecreaseKicksLeft(ObjectGuid guid) TC_LOG_TRACE("lfg.data.group.kicksleft.decrease", "Group: %s, Kicks: %u", guid.ToString().c_str(), GroupsStore[guid].GetKicksLeft()); } +void LFGMgr::SetTicket(ObjectGuid guid, WorldPackets::LFG::RideTicket const& ticket) +{ + PlayersStore[guid].SetTicket(ticket); +} + void LFGMgr::RemovePlayerData(ObjectGuid guid) { TC_LOG_TRACE("lfg.data.player.remove", "Player: %s", guid.ToString().c_str()); diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index a8834046760..10eaca4a8b3 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -32,6 +32,14 @@ class Quest; struct LfgDungeonsEntry; enum Difficulty : uint8; +namespace WorldPackets +{ + namespace LFG + { + struct RideTicket; + } +} + namespace lfg { @@ -80,40 +88,51 @@ enum LfgProposalState }; /// Teleport errors -enum LfgTeleportError +enum LfgTeleportResult : uint8 { // 7 = "You can't do that right now" | 5 = No client reaction - LFG_TELEPORTERROR_OK = 0, // Internal use - LFG_TELEPORTERROR_PLAYER_DEAD = 1, - LFG_TELEPORTERROR_FALLING = 2, - LFG_TELEPORTERROR_IN_VEHICLE = 3, - LFG_TELEPORTERROR_FATIGUE = 4, - LFG_TELEPORTERROR_INVALID_LOCATION = 6, - LFG_TELEPORTERROR_CHARMING = 8 // FIXME - It can be 7 or 8 (Need proper data) + LFG_TELEPORT_RESULT_NONE = 0, // Internal use + LFG_TELEPORT_RESULT_DEAD = 1, + LFG_TELEPORT_RESULT_FALLING = 2, + LFG_TELEPORT_RESULT_ON_TRANSPORT = 3, + LFG_TELEPORT_RESULT_EXHAUSTION = 4, + LFG_TELEPORT_RESULT_NO_RETURN_LOCATION = 6, + LFG_TELEPORT_RESULT_IMMUNE_TO_SUMMONS = 8 // FIXME - It can be 7 or 8 (Need proper data) + + // unknown values + //LFG_TELEPORT_RESULT_NOT_IN_DUNGEON, + //LFG_TELEPORT_RESULT_NOT_ALLOWED, + //LFG_TELEPORT_RESULT_ALREADY_IN_DUNGEON }; /// Queue join results enum LfgJoinResult { // 3 = No client reaction | 18 = "Rolecheck failed" - LFG_JOIN_OK = 0x00, // Joined (no client msg) - LFG_JOIN_FAILED = 0x1B, // RoleCheck Failed - LFG_JOIN_GROUPFULL = 0x1C, // Your group is full - LFG_JOIN_INTERNAL_ERROR = 0x1E, // Internal LFG Error - LFG_JOIN_NOT_MEET_REQS = 0x1F, // You do not meet the requirements for the chosen dungeons - LFG_JOIN_PARTY_NOT_MEET_REQS = 6, // One or more party members do not meet the requirements for the chosen dungeons (FIXME) - LFG_JOIN_MIXED_RAID_DUNGEON = 0x20, // You cannot mix dungeons, raids, and random when picking dungeons - LFG_JOIN_MULTI_REALM = 0x21, // The dungeon you chose does not support players from multiple realms - LFG_JOIN_DISCONNECTED = 0x22, // One or more party members are pending invites or disconnected - LFG_JOIN_PARTY_INFO_FAILED = 0x23, // Could not retrieve information about some party members - LFG_JOIN_DUNGEON_INVALID = 0x24, // One or more dungeons was not valid - LFG_JOIN_DESERTER = 0x25, // You can not queue for dungeons until your deserter debuff wears off - LFG_JOIN_PARTY_DESERTER = 0x26, // One or more party members has a deserter debuff - LFG_JOIN_RANDOM_COOLDOWN = 0x27, // You can not queue for random dungeons while on random dungeon cooldown - LFG_JOIN_PARTY_RANDOM_COOLDOWN = 0x28, // One or more party members are on random dungeon cooldown - LFG_JOIN_TOO_MUCH_MEMBERS = 0x29, // You can not enter dungeons with more that 5 party members - LFG_JOIN_USING_BG_SYSTEM = 0x2A, // You can not use the dungeon system while in BG or arenas - LFG_JOIN_ROLE_CHECK_FAILED = 0x2B // Role check failed, client shows special error + LFG_JOIN_OK = 0x00, // Joined (no client msg) + LFG_JOIN_GROUP_FULL = 0x1F, // Your group is already full. + LFG_JOIN_NO_LFG_OBJECT = 0x21, // Internal LFG Error. + LFG_JOIN_NO_SLOTS_PLAYER = 0x22, // You do not meet the requirements for the chosen dungeons. + LFG_JOIN_MISMATCHED_SLOTS = 0x23, // You cannot mix dungeons, raids, and random when picking dungeons. + LFG_JOIN_PARTY_PLAYERS_FROM_DIFFERENT_REALMS = 0x24, // The dungeon you chose does not support players from multiple realms. + LFG_JOIN_MEMBERS_NOT_PRESENT = 0x25, // One or more group members are pending invites or disconnected. + LFG_JOIN_GET_INFO_TIMEOUT = 0x26, // Could not retrieve information about some party members. + LFG_JOIN_INVALID_SLOT = 0x27, // One or more dungeons was not valid. + LFG_JOIN_DESERTER_PLAYER = 0x28, // You can not queue for dungeons until your deserter debuff wears off. + LFG_JOIN_DESERTER_PARTY = 0x29, // One or more party members has a deserter debuff. + LFG_JOIN_RANDOM_COOLDOWN_PLAYER = 0x2A, // You can not queue for random dungeons while on random dungeon cooldown. + LFG_JOIN_RANDOM_COOLDOWN_PARTY = 0x2B, // One or more party members are on random dungeon cooldown. + LFG_JOIN_TOO_MANY_MEMBERS = 0x2C, // You have too many group members to queue for that. + LFG_JOIN_CANT_USE_DUNGEONS = 0x2D, // You cannot queue for a dungeon or raid while using battlegrounds or arenas. + LFG_JOIN_ROLE_CHECK_FAILED = 0x2E, // The Role Check has failed. + LFG_JOIN_TOO_FEW_MEMBERS = 0x34, // You do not have enough group members to queue for that. + LFG_JOIN_REASON_TOO_MANY_LFG = 0x35, // You are queued for too many instances. + LFG_JOIN_MISMATCHED_SLOTS_LOCAL_XREALM = 0x37, // You cannot mix realm-only and x-realm entries when listing your name in other raids. + LFG_JOIN_ALREADY_USING_LFG_LIST = 0x3F, // You can't do that while using Premade Groups. + LFG_JOIN_NOT_LEADER = 0x45, // You are not the party leader. + LFG_JOIN_DEAD = 0x49, + + LFG_JOIN_PARTY_NOT_MEET_REQS = 6, // One or more party members do not meet the requirements for the chosen dungeons (FIXME) }; /// Role check states @@ -178,14 +197,13 @@ struct LfgUpdateData // Data needed by SMSG_LFG_QUEUE_STATUS struct LfgQueueStatusData { - LfgQueueStatusData(uint8 _queueId = 0, uint32 _dungeonId = 0, time_t _joinTime = 0, int32 _waitTime = -1, int32 _waitTimeAvg = -1, int32 _waitTimeTank = -1, int32 _waitTimeHealer = -1, + LfgQueueStatusData(uint8 _queueId = 0, uint32 _dungeonId = 0, int32 _waitTime = -1, int32 _waitTimeAvg = -1, int32 _waitTimeTank = -1, int32 _waitTimeHealer = -1, int32 _waitTimeDps = -1, uint32 _queuedTime = 0, uint8 _tanks = 0, uint8 _healers = 0, uint8 _dps = 0) : - queueId(_queueId), dungeonId(_dungeonId), joinTime(_joinTime), waitTime(_waitTime), waitTimeAvg(_waitTimeAvg), waitTimeTank(_waitTimeTank), + queueId(_queueId), dungeonId(_dungeonId), waitTime(_waitTime), waitTimeAvg(_waitTimeAvg), waitTimeTank(_waitTimeTank), waitTimeHealer(_waitTimeHealer), waitTimeDps(_waitTimeDps), queuedTime(_queuedTime), tanks(_tanks), healers(_healers), dps(_dps) { } uint8 queueId; uint32 dungeonId; - time_t joinTime; int32 waitTime; int32 waitTimeAvg; int32 waitTimeTank; @@ -393,6 +411,8 @@ class TC_GAME_API LFGMgr void JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons); /// Leaves lfg void LeaveLfg(ObjectGuid guid, bool disconnected = false); + /// Gets unique join queue data + WorldPackets::LFG::RideTicket const* GetTicket(ObjectGuid guid) const; // LfgQueue /// Get last lfg state (NONE, DUNGEON or FINISHED_DUNGEON) @@ -423,6 +443,7 @@ class TC_GAME_API LFGMgr void SetDungeon(ObjectGuid guid, uint32 dungeon); void SetSelectedDungeons(ObjectGuid guid, LfgDungeonSet const& dungeons); void DecreaseKicksLeft(ObjectGuid guid); + void SetTicket(ObjectGuid guid, WorldPackets::LFG::RideTicket const& ticket); void SetState(ObjectGuid guid, LfgState state); void SetVoteKick(ObjectGuid gguid, bool active); void RemovePlayerData(ObjectGuid guid); diff --git a/src/server/game/DungeonFinding/LFGPlayerData.cpp b/src/server/game/DungeonFinding/LFGPlayerData.cpp index db0168dfd7e..351a3a3f426 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.cpp +++ b/src/server/game/DungeonFinding/LFGPlayerData.cpp @@ -26,6 +26,11 @@ LfgPlayerData::LfgPlayerData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NO LfgPlayerData::~LfgPlayerData() { } +void LfgPlayerData::SetTicket(WorldPackets::LFG::RideTicket const& ticket) +{ + m_Ticket = ticket; +} + void LfgPlayerData::SetState(LfgState state) { switch (state) @@ -73,6 +78,11 @@ void LfgPlayerData::SetSelectedDungeons(LfgDungeonSet const& dungeons) m_SelectedDungeons = dungeons; } +WorldPackets::LFG::RideTicket const& LfgPlayerData::GetTicket() const +{ + return m_Ticket; +} + LfgState LfgPlayerData::GetState() const { return m_State; diff --git a/src/server/game/DungeonFinding/LFGPlayerData.h b/src/server/game/DungeonFinding/LFGPlayerData.h index ba6a78619a3..cf670eb64d9 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.h +++ b/src/server/game/DungeonFinding/LFGPlayerData.h @@ -19,6 +19,7 @@ #define _LFGPLAYERDATA_H #include "LFG.h" +#include "LFGPacketsCommon.h" namespace lfg { @@ -33,6 +34,7 @@ class TC_GAME_API LfgPlayerData ~LfgPlayerData(); // General + void SetTicket(WorldPackets::LFG::RideTicket const& ticket); void SetState(LfgState state); void RestoreState(); void SetTeam(uint8 team); @@ -43,6 +45,7 @@ class TC_GAME_API LfgPlayerData void SetSelectedDungeons(const LfgDungeonSet& dungeons); // General + WorldPackets::LFG::RideTicket const& GetTicket() const; LfgState GetState() const; LfgState GetOldState() const; uint8 GetTeam() const; @@ -54,6 +57,7 @@ class TC_GAME_API LfgPlayerData private: // General + WorldPackets::LFG::RideTicket m_Ticket; ///< Join ticket LfgState m_State; ///< State if group in LFG LfgState m_OldState; ///< Old State - Used to restore state after failed Rolecheck/Proposal // Player diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp index 03eabe6a408..571bd09c406 100644 --- a/src/server/game/DungeonFinding/LFGQueue.cpp +++ b/src/server/game/DungeonFinding/LFGQueue.cpp @@ -621,7 +621,7 @@ void LFGQueue::UpdateQueueTimers(uint8 queueId, time_t currTime) if (queueinfo.bestCompatible.empty()) FindBestCompatibleInQueue(itQueue); - LfgQueueStatusData queueData(queueId, dungeonId, queueinfo.joinTime, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps); + LfgQueueStatusData queueData(queueId, dungeonId, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps); for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer) { ObjectGuid pguid = itPlayer->first; diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 3bd64194885..d3d62697adb 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -42,10 +42,7 @@ void LFGPlayerScript::OnLogout(Player* player) return; if (!player->GetGroup()) - { - player->GetSession()->SendLfgLfrList(false); sLFGMgr->LeaveLfg(player->GetGUID()); - } else if (player->GetSession()->PlayerDisconnected()) sLFGMgr->LeaveLfg(player->GetGUID(), true); } diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp index a3a1b235c3b..97ce3c50b9e 100644 --- a/src/server/game/Entities/Object/ObjectGuid.cpp +++ b/src/server/game/Entities/Object/ObjectGuid.cpp @@ -150,18 +150,6 @@ void ObjectGuid::SetRawValue(std::vector<uint8> const& guid) memcpy(this, guid.data(), sizeof(*this)); } -uint8& ObjectGuid::operator[](uint32 index) -{ - ASSERT(index < sizeof(uint64) * 2); - return ((uint8*)&_low)[index]; -} - -uint8 const& ObjectGuid::operator[](uint32 index) const -{ - ASSERT(index < sizeof(uint64) * 2); - return ((uint8 const*)&_low)[index]; -} - ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid) { uint8 lowMask = 0; diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h index 131f911f77d..866af7b6155 100644 --- a/src/server/game/Entities/Object/ObjectGuid.h +++ b/src/server/game/Entities/Object/ObjectGuid.h @@ -247,9 +247,6 @@ class TC_GAME_API ObjectGuid LowType GetMaxCounter() const { return GetMaxCounter(GetHigh()); } - uint8& operator[](uint32 index); - uint8 const& operator[](uint32 index) const; - bool IsEmpty() const { return _low == 0 && _high == 0; } bool IsCreature() const { return GetHigh() == HighGuid::Creature; } bool IsPet() const { return GetHigh() == HighGuid::Pet; } diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 971d6586c2f..e3041fdbba3 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1496,7 +1496,7 @@ void Group::SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot* slot) { partyUpdate.LfgInfos = boost::in_place(); - partyUpdate.LfgInfos->Slot = sLFGMgr->GetDungeon(m_guid); + partyUpdate.LfgInfos->Slot = sLFGMgr->GetLFGDungeonEntry(sLFGMgr->GetDungeon(m_guid)); partyUpdate.LfgInfos->BootCount = 0; partyUpdate.LfgInfos->Aborted = false; diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index 4ec65edb41a..fd305e902df 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -255,7 +255,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPackets::Battleground::Battl if (!_player->InBattlegroundQueue()) { TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, AcceptedInvite: %u. Player not in queue!", - GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite)); + GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite)); return; } @@ -263,7 +263,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPackets::Battleground::Battl if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE) { TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, AcceptedInvite: %u. Invalid queueSlot!", - GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite)); + GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite)); return; } @@ -274,14 +274,14 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPackets::Battleground::Battl if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) { TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, AcceptedInvite: %u. Player not in queue (No player Group Info)!", - GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite)); + GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite)); return; } // if action == 1, then player must have been invited to join if (!ginfo.IsInvitedToBGInstanceGUID && battlefieldPort.AcceptedInvite) { TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, AcceptedInvite: %u. Player is not invited to any bg!", - GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite)); + GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite)); return; } @@ -294,7 +294,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPackets::Battleground::Battl if (battlefieldPort.AcceptedInvite) { TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, AcceptedInvite: %u. Cant find BG with id %u!", - GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite), ginfo.IsInvitedToBGInstanceGUID); + GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite), ginfo.IsInvitedToBGInstanceGUID); return; } @@ -307,7 +307,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPackets::Battleground::Battl } TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s Slot: %u, Unk: %u, Time: %u, AcceptedInvite: %u.", - GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, battlefieldPort.Ticket.Type, battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite)); + GetPlayerInfo().c_str(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time, uint32(battlefieldPort.AcceptedInvite)); // get real bg type bgTypeId = bg->GetTypeID(); diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index a368a9a1b7e..24b0aa0bb19 100644 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -18,213 +18,62 @@ #include "WorldSession.h" #include "Group.h" #include "LFGMgr.h" +#include "LFGPackets.h" #include "Log.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Opcodes.h" #include "Player.h" +#include "World.h" #include "WorldPacket.h" -void BuildPlayerLockDungeonBlock(WorldPacket& data, lfg::LfgLockMap const& lock) -{ - data << uint32(lock.size()); // Size of lock dungeons - for (lfg::LfgLockMap::const_iterator it = lock.begin(); it != lock.end(); ++it) - { - TC_LOG_TRACE("lfg", "BuildPlayerLockDungeonBlock:: DungeonID: %u Lock status: %u Required itemLevel: %u Current itemLevel: %f", - (it->first & 0x00FFFFFF), it->second.lockStatus, it->second.requiredItemLevel, it->second.currentItemLevel); - - data << uint32(it->first); // Dungeon entry (id + type) - data << uint32(it->second.lockStatus); // Lock status - data << uint32(it->second.requiredItemLevel); // Required itemLevel - data << uint32(it->second.currentItemLevel); // Current itemLevel - } -} - -void BuildPartyLockDungeonBlock(WorldPacket& data, lfg::LfgLockPartyMap const& lockMap) -{ - data << uint8(lockMap.size()); - for (lfg::LfgLockPartyMap::const_iterator it = lockMap.begin(); it != lockMap.end(); ++it) - { - data << it->first; // Player guid - BuildPlayerLockDungeonBlock(data, it->second); - } -} - -void BuildQuestReward(WorldPacket& data, Quest const* quest, Player* player) -{ - uint8 rewCount = quest->GetRewItemsCount() + quest->GetRewCurrencyCount(); - - data << uint32(player->GetQuestMoneyReward(quest)); - data << uint32(player->GetQuestXPReward(quest)); - data << uint8(rewCount); - if (rewCount) - { - for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) - { - if (uint32 currencyId = quest->RewardCurrencyId[i]) - { - data << uint32(currencyId); - data << uint32(0); - data << uint32(quest->RewardCurrencyCount[i]); - data << uint8(1); // Is currency - } - } - - for (uint8 i = 0; i < QUEST_REWARD_ITEM_COUNT; ++i) - { - if (uint32 itemId = quest->RewardItemId[i]) - { - //ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId); - data << uint32(itemId); - data << uint32(/*item ? item->DisplayInfoID :*/ 0); - data << uint32(quest->RewardItemCount[i]); - data << uint8(0); // Is currency - } - } - } -} - -void WorldSession::HandleLfgJoinOpcode(WorldPacket& recvData) +void WorldSession::HandleLfgJoinOpcode(WorldPackets::LFG::DFJoin& dfJoin) { if (!sLFGMgr->isOptionEnabled(lfg::LFG_OPTION_ENABLE_DUNGEON_FINDER | lfg::LFG_OPTION_ENABLE_RAID_BROWSER) || (GetPlayer()->GetGroup() && GetPlayer()->GetGroup()->GetLeaderGUID() != GetPlayer()->GetGUID() && (GetPlayer()->GetGroup()->GetMembersCount() == MAX_GROUP_SIZE || !GetPlayer()->GetGroup()->isLFGGroup()))) - { - recvData.rfinish(); return; - } - - uint32 roles; - - recvData >> roles; - for (int32 i = 0; i < 3; ++i) - recvData.read_skip<uint32>(); - uint32 commentLen = recvData.ReadBits(9); - uint32 numDungeons = recvData.ReadBits(24); - - if (!numDungeons) + if (dfJoin.Slots.empty()) { TC_LOG_DEBUG("lfg", "CMSG_DF_JOIN %s no dungeons selected", GetPlayerInfo().c_str()); - recvData.rfinish(); return; } - std::string comment = recvData.ReadString(commentLen); - lfg::LfgDungeonSet newDungeons; - for (uint32 i = 0; i < numDungeons; ++i) + for (uint32 slot : dfJoin.Slots) { - uint32 dungeon; - recvData >> dungeon; - dungeon &= 0x00FFFFFF; // remove the type from the dungeon entry - if (dungeon) + uint32 dungeon = slot & 0x00FFFFFF; + if (sLfgDungeonsStore.LookupEntry(dungeon)) newDungeons.insert(dungeon); } - TC_LOG_DEBUG("lfg", "CMSG_DF_JOIN %s roles: %u, Dungeons: %u, Comment: %s", - GetPlayerInfo().c_str(), roles, uint8(newDungeons.size()), comment.c_str()); + TC_LOG_DEBUG("lfg", "CMSG_DF_JOIN %s roles: %u, Dungeons: %u", GetPlayerInfo().c_str(), dfJoin.Roles, uint8(newDungeons.size())); - sLFGMgr->JoinLfg(GetPlayer(), uint8(roles), newDungeons); + sLFGMgr->JoinLfg(GetPlayer(), uint8(dfJoin.Roles), newDungeons); } -void WorldSession::HandleLfgLeaveOpcode(WorldPacket& recvData) +void WorldSession::HandleLfgLeaveOpcode(WorldPackets::LFG::DFLeave& dfLeave) { - ObjectGuid leaveGuid; Group* group = GetPlayer()->GetGroup(); - ObjectGuid guid = GetPlayer()->GetGUID(); - ObjectGuid gguid = group ? group->GetGUID() : guid; - - recvData.read_skip<uint32>(); // Always 8 - recvData.read_skip<uint32>(); // Join date - recvData.read_skip<uint32>(); // Always 3 - recvData.read_skip<uint32>(); // Queue Id - - leaveGuid[4] = recvData.ReadBit(); - leaveGuid[5] = recvData.ReadBit(); - leaveGuid[0] = recvData.ReadBit(); - leaveGuid[6] = recvData.ReadBit(); - leaveGuid[2] = recvData.ReadBit(); - leaveGuid[7] = recvData.ReadBit(); - leaveGuid[1] = recvData.ReadBit(); - leaveGuid[3] = recvData.ReadBit(); - - recvData.ReadByteSeq(leaveGuid[7]); - recvData.ReadByteSeq(leaveGuid[4]); - recvData.ReadByteSeq(leaveGuid[3]); - recvData.ReadByteSeq(leaveGuid[2]); - recvData.ReadByteSeq(leaveGuid[6]); - recvData.ReadByteSeq(leaveGuid[0]); - recvData.ReadByteSeq(leaveGuid[1]); - recvData.ReadByteSeq(leaveGuid[5]); TC_LOG_DEBUG("lfg", "CMSG_DF_LEAVE %s in group: %u sent guid %s.", - GetPlayerInfo().c_str(), group ? 1 : 0, leaveGuid.ToString().c_str()); + GetPlayerInfo().c_str(), group ? 1 : 0, dfLeave.Ticket.RequesterGuid.ToString().c_str()); // Check cheating - only leader can leave the queue - if (!group || group->GetLeaderGUID() == guid) - sLFGMgr->LeaveLfg(gguid); + if (!group || group->GetLeaderGUID() == dfLeave.Ticket.RequesterGuid) + sLFGMgr->LeaveLfg(dfLeave.Ticket.RequesterGuid); } -void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recvData) +void WorldSession::HandleLfgProposalResultOpcode(WorldPackets::LFG::DFProposalResponse& dfProposalResponse) { - uint32 proposalID; // Proposal ID - bool accept; - - ObjectGuid guid1; - ObjectGuid guid2; - - recvData >> proposalID; - recvData.read_skip<uint32>(); - recvData.read_skip<uint32>(); - recvData.read_skip<uint32>(); - - guid2[4] = recvData.ReadBit(); - guid2[5] = recvData.ReadBit(); - guid2[0] = recvData.ReadBit(); - guid2[6] = recvData.ReadBit(); - guid2[2] = recvData.ReadBit(); - guid2[7] = recvData.ReadBit(); - guid2[1] = recvData.ReadBit(); - guid2[3] = recvData.ReadBit(); - - recvData.ReadByteSeq(guid2[7]); - recvData.ReadByteSeq(guid2[4]); - recvData.ReadByteSeq(guid2[3]); - recvData.ReadByteSeq(guid2[2]); - recvData.ReadByteSeq(guid2[6]); - recvData.ReadByteSeq(guid2[0]); - recvData.ReadByteSeq(guid2[1]); - recvData.ReadByteSeq(guid2[5]); - - guid1[7] = recvData.ReadBit(); - accept = recvData.ReadBit(); - guid1[1] = recvData.ReadBit(); - guid1[3] = recvData.ReadBit(); - guid1[0] = recvData.ReadBit(); - guid1[5] = recvData.ReadBit(); - guid1[4] = recvData.ReadBit(); - guid1[6] = recvData.ReadBit(); - guid1[2] = recvData.ReadBit(); - - recvData.ReadByteSeq(guid1[7]); - recvData.ReadByteSeq(guid1[1]); - recvData.ReadByteSeq(guid1[5]); - recvData.ReadByteSeq(guid1[6]); - recvData.ReadByteSeq(guid1[3]); - recvData.ReadByteSeq(guid1[4]); - recvData.ReadByteSeq(guid1[0]); - recvData.ReadByteSeq(guid1[2]); - TC_LOG_DEBUG("lfg", "CMSG_LFG_PROPOSAL_RESULT %s proposal: %u accept: %u", - GetPlayerInfo().c_str(), proposalID, accept ? 1 : 0); - sLFGMgr->UpdateProposal(proposalID, GetPlayer()->GetGUID(), accept); + GetPlayerInfo().c_str(), dfProposalResponse.ProposalID, dfProposalResponse.Accepted ? 1 : 0); + sLFGMgr->UpdateProposal(dfProposalResponse.ProposalID, GetPlayer()->GetGUID(), dfProposalResponse.Accepted); } -void WorldSession::HandleLfgSetRolesOpcode(WorldPacket& recvData) +void WorldSession::HandleLfgSetRolesOpcode(WorldPackets::LFG::DFSetRoles& dfSetRoles) { - uint8 roles; - recvData >> roles; // Player Group Roles ObjectGuid guid = GetPlayer()->GetGUID(); Group* group = GetPlayer()->GetGroup(); if (!group) @@ -235,112 +84,120 @@ void WorldSession::HandleLfgSetRolesOpcode(WorldPacket& recvData) } ObjectGuid gguid = group->GetGUID(); TC_LOG_DEBUG("lfg", "CMSG_DF_SET_ROLES: Group %s, Player %s, Roles: %u", - gguid.ToString().c_str(), GetPlayerInfo().c_str(), roles); - sLFGMgr->UpdateRoleCheck(gguid, guid, roles); + gguid.ToString().c_str(), GetPlayerInfo().c_str(), dfSetRoles.RolesDesired); + sLFGMgr->UpdateRoleCheck(gguid, guid, dfSetRoles.RolesDesired); } -void WorldSession::HandleLfgSetBootVoteOpcode(WorldPacket& recvData) +void WorldSession::HandleLfgSetBootVoteOpcode(WorldPackets::LFG::DFBootPlayerVote& dfBootPlayerVote) { - bool agree; // Agree to kick player - recvData >> agree; - ObjectGuid guid = GetPlayer()->GetGUID(); TC_LOG_DEBUG("lfg", "CMSG_LFG_SET_BOOT_VOTE %s agree: %u", - GetPlayerInfo().c_str(), agree ? 1 : 0); - sLFGMgr->UpdateBoot(guid, agree); + GetPlayerInfo().c_str(), dfBootPlayerVote.Vote ? 1 : 0); + sLFGMgr->UpdateBoot(guid, dfBootPlayerVote.Vote); } -void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recvData) +void WorldSession::HandleLfgTeleportOpcode(WorldPackets::LFG::DFTeleport& dfTeleport) { - bool out; - recvData >> out; - TC_LOG_DEBUG("lfg", "CMSG_DF_TELEPORT %s out: %u", - GetPlayerInfo().c_str(), out ? 1 : 0); - sLFGMgr->TeleportPlayer(GetPlayer(), out, true); + GetPlayerInfo().c_str(), dfTeleport.TeleportOut ? 1 : 0); + sLFGMgr->TeleportPlayer(GetPlayer(), dfTeleport.TeleportOut, true); } -void WorldSession::HandleDFGetSystemInfo(WorldPacket& recvData) +void WorldSession::HandleDFGetSystemInfo(WorldPackets::LFG::DFGetSystemInfo& dfGetSystemInfo) { - bool forPlayer = recvData.ReadBit(); - TC_LOG_DEBUG("lfg", "CMSG_DF_GET_SYSTEM_INFO %s for %s", GetPlayerInfo().c_str(), (forPlayer ? "player" : "party")); + TC_LOG_DEBUG("lfg", "CMSG_DF_GET_SYSTEM_INFO %s for %s", GetPlayerInfo().c_str(), (dfGetSystemInfo.Player ? "player" : "party")); - if (forPlayer) + if (dfGetSystemInfo.Player) SendLfgPlayerLockInfo(); else SendLfgPartyLockInfo(); } -void WorldSession::SendLfgPlayerLockInfo() +void WorldSession::HandleDFGetJoinStatus(WorldPackets::LFG::DFGetJoinStatus& /*dfGetJoinStatus*/) { + TC_LOG_DEBUG("lfg", "CMSG_DF_GET_JOIN_STATUS %s", GetPlayerInfo().c_str()); + + if (!GetPlayer()->isUsingLfg()) + return; + ObjectGuid guid = GetPlayer()->GetGUID(); + lfg::LfgUpdateData updateData = sLFGMgr->GetLfgStatus(guid); + + if (GetPlayer()->GetGroup()) + { + SendLfgUpdateStatus(updateData, true); + updateData.dungeons.clear(); + SendLfgUpdateStatus(updateData, false); + } + else + { + SendLfgUpdateStatus(updateData, false); + updateData.dungeons.clear(); + SendLfgUpdateStatus(updateData, true); + } +} + +void WorldSession::SendLfgPlayerLockInfo() +{ + TC_LOG_DEBUG("lfg", "SMSG_LFG_PLAYER_INFO %s", GetPlayerInfo().c_str()); // Get Random dungeons that can be done at a certain level and expansion uint8 level = GetPlayer()->getLevel(); - lfg::LfgDungeonSet const& randomDungeons = - sLFGMgr->GetRandomAndSeasonalDungeons(level, GetExpansion()); + lfg::LfgDungeonSet const& randomDungeons = sLFGMgr->GetRandomAndSeasonalDungeons(level, GetExpansion()); - // Get player locked Dungeons - lfg::LfgLockMap const& lock = sLFGMgr->GetLockedDungeons(guid); - uint32 rsize = uint32(randomDungeons.size()); - uint32 lsize = uint32(lock.size()); + WorldPackets::LFG::LfgPlayerInfo lfgPlayerInfo; - TC_LOG_DEBUG("lfg", "SMSG_LFG_PLAYER_INFO %s", GetPlayerInfo().c_str()); - WorldPacket data(SMSG_LFG_PLAYER_INFO, 1 + rsize * (4 + 1 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4) + 4 + lsize * (1 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4)); + // Get player locked Dungeons + for (auto const& lock : sLFGMgr->GetLockedDungeons(_player->GetGUID())) + lfgPlayerInfo.BlackList.Slot.emplace_back(lock.first, lock.second.lockStatus, lock.second.requiredItemLevel, lock.second.currentItemLevel); - data << uint8(randomDungeons.size()); // Random Dungeon count - for (lfg::LfgDungeonSet::const_iterator it = randomDungeons.begin(); it != randomDungeons.end(); ++it) + for (uint32 slot : randomDungeons) { - data << uint32(*it); // Dungeon Entry (id + type) - lfg::LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(*it, level); - Quest const* quest = NULL; + lfgPlayerInfo.Dungeon.emplace_back(); + WorldPackets::LFG::LfgPlayerDungeonInfo& playerDungeonInfo = lfgPlayerInfo.Dungeon.back(); + playerDungeonInfo.Slot = slot; + playerDungeonInfo.CompletionQuantity = 1; + playerDungeonInfo.CompletionLimit = 1; + playerDungeonInfo.CompletionCurrencyID = 0; + playerDungeonInfo.SpecificQuantity = 0; + playerDungeonInfo.SpecificLimit = 1; + playerDungeonInfo.OverallQuantity = 0; + playerDungeonInfo.OverallLimit = 1; + playerDungeonInfo.PurseWeeklyQuantity = 0; + playerDungeonInfo.PurseWeeklyLimit = 0; + playerDungeonInfo.PurseQuantity = 0; + playerDungeonInfo.PurseLimit = 0; + playerDungeonInfo.Quantity = 1; + playerDungeonInfo.CompletedMask = 0; + playerDungeonInfo.EncounterMask = 0; + + Quest const* quest = nullptr; bool done = false; - if (reward) + if (lfg::LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(slot, level)) { - quest = sObjectMgr->GetQuestTemplate(reward->firstQuest); - if (quest) + if (Quest const* quest = sObjectMgr->GetQuestTemplate(reward->firstQuest)) { - done = !GetPlayer()->CanRewardQuest(quest, false); - if (done) + playerDungeonInfo.FirstReward = !GetPlayer()->CanRewardQuest(quest, false); + if (!playerDungeonInfo.FirstReward) quest = sObjectMgr->GetQuestTemplate(reward->otherQuest); - } - } - - data << uint8(done); - data << uint32(0); // currencyQuantity - data << uint32(0); // some sort of overall cap/weekly cap - data << uint32(0); // currencyID - data << uint32(0); // tier1Quantity - data << uint32(0); // tier1Limit - data << uint32(0); // overallQuantity - data << uint32(0); // overallLimit - data << uint32(0); // periodPurseQuantity - data << uint32(0); // periodPurseLimit - data << uint32(0); // purseQuantity - data << uint32(0); // purseLimit - data << uint32(0); // some sort of reward for completion - data << uint32(0); // completedEncounters - data << uint8(0); // Call to Arms eligible - - for (uint32 i = 0; i < 3; ++i) - { - data << uint32(0); // Call to Arms Role - //if (role) - // BuildQuestReward(data, ctaRoleQuest, GetPlayer()); - } - if (quest) - BuildQuestReward(data, quest, GetPlayer()); - else - { - data << uint32(0); // Money - data << uint32(0); // XP - data << uint8(0); // Reward count + if (quest) + { + playerDungeonInfo.Rewards.RewardMoney = _player->GetQuestMoneyReward(quest); + playerDungeonInfo.Rewards.RewardXP = _player->GetQuestXPReward(quest); + for (uint8 i = 0; i < QUEST_REWARD_ITEM_COUNT; ++i) + if (uint32 itemId = quest->RewardItemId[i]) + playerDungeonInfo.Rewards.Item.emplace_back(itemId, quest->RewardItemCount[i]); + + for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + if (uint32 curencyId = quest->RewardCurrencyId[i]) + playerDungeonInfo.Rewards.Currency.emplace_back(curencyId, quest->RewardCurrencyCount[i]); + } + } } } - BuildPlayerLockDungeonBlock(data, lock); - SendPacket(&data); + SendPacket(lfgPlayerInfo.Write());; } void WorldSession::SendLfgPartyLockInfo() @@ -350,9 +207,10 @@ void WorldSession::SendLfgPartyLockInfo() if (!group) return; + WorldPackets::LFG::LfgPartyInfo lfgPartyInfo; + // Get the locked dungeons of the other party members - lfg::LfgLockPartyMap lockMap; - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* plrg = itr->GetSource(); if (!plrg) @@ -362,51 +220,22 @@ void WorldSession::SendLfgPartyLockInfo() if (pguid == guid) continue; - lockMap[pguid] = sLFGMgr->GetLockedDungeons(pguid); + lfgPartyInfo.Player.emplace_back(); + WorldPackets::LFG::LFGBlackList& lfgBlackList = lfgPartyInfo.Player.back(); + lfgBlackList.PlayerGuid = pguid; + for (auto const& lock : sLFGMgr->GetLockedDungeons(pguid)) + lfgBlackList.Slot.emplace_back(lock.first, lock.second.lockStatus, lock.second.requiredItemLevel, lock.second.currentItemLevel); } - uint32 size = 0; - for (lfg::LfgLockPartyMap::const_iterator it = lockMap.begin(); it != lockMap.end(); ++it) - size += 8 + 4 + uint32(it->second.size()) * (4 + 4 + 4 + 4); - TC_LOG_DEBUG("lfg", "SMSG_LFG_PARTY_INFO %s", GetPlayerInfo().c_str()); - WorldPacket data(SMSG_LFG_PARTY_INFO, 1 + size); - BuildPartyLockDungeonBlock(data, lockMap); - SendPacket(&data); -} - -void WorldSession::HandleDFGetJoinStatus(WorldPacket& /*recvData*/) -{ - TC_LOG_DEBUG("lfg", "CMSG_DF_GET_JOIN_STATUS %s", GetPlayerInfo().c_str()); - - if (!GetPlayer()->isUsingLfg()) - return; - - ObjectGuid guid = GetPlayer()->GetGUID(); - lfg::LfgUpdateData updateData = sLFGMgr->GetLfgStatus(guid); - - if (GetPlayer()->GetGroup()) - { - SendLfgUpdateStatus(updateData, true); - updateData.dungeons.clear(); - SendLfgUpdateStatus(updateData, false); - } - else - { - SendLfgUpdateStatus(updateData, false); - updateData.dungeons.clear(); - SendLfgUpdateStatus(updateData, true); - } + SendPacket(lfgPartyInfo.Write());; } void WorldSession::SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, bool party) { bool join = false; bool queued = false; - uint8 size = uint8(updateData.dungeons.size()); ObjectGuid guid = _player->GetGUID(); - time_t joinTime = sLFGMgr->GetQueueJoinTime(_player->GetGUID()); - uint32 queueId = sLFGMgr->GetQueueId(_player->GetGUID()); switch (updateData.updateType) { @@ -432,40 +261,25 @@ void WorldSession::SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, boo TC_LOG_DEBUG("lfg", "SMSG_LFG_UPDATE_STATUS %s updatetype: %u, party %s", GetPlayerInfo().c_str(), updateData.updateType, party ? "true" : "false"); - WorldPacket data(SMSG_LFG_UPDATE_STATUS, 1 + 8 + 3 + 2 + 1 + 4 + 4 + 1 + 1 + 1 + 4 + size); - data.WriteBit(guid[1] != 0); - data.WriteBit(party); - data.WriteBits(size, 24); - data.WriteBit(guid[6] != 0); - data.WriteBit(size > 0); // Extra info - data.WriteBit(guid[4] != 0); - data.WriteBit(guid[7] != 0); - data.WriteBit(guid[2] != 0); - data.WriteBit(join); // LFG Join - data.WriteBit(guid[0] != 0); - data.WriteBit(guid[3] != 0); - data.WriteBit(guid[5] != 0); - data.WriteBit(queued); // Join the queue - - data << uint8(updateData.updateType); // Lfg Update type - data << uint32(queueId); // Queue Id - data << uint32(joinTime); // Join date - data.WriteByteSeq(guid[6]); - for (uint8 i = 0; i < 3; ++i) - data << uint8(0); // unk - Always 0 - - data.WriteByteSeq(guid[1]); - data.WriteByteSeq(guid[2]); - data.WriteByteSeq(guid[4]); - data.WriteByteSeq(guid[3]); - data.WriteByteSeq(guid[5]); - data.WriteByteSeq(guid[0]); - data << uint32(3); - data.WriteByteSeq(guid[7]); - for (lfg::LfgDungeonSet::const_iterator it = updateData.dungeons.begin(); it != updateData.dungeons.end(); ++it) - data << uint32(*it); - - SendPacket(&data); + WorldPackets::LFG::LFGUpdateStatus lfgUpdateStatus; + if (WorldPackets::LFG::RideTicket const* ticket = sLFGMgr->GetTicket(_player->GetGUID())) + lfgUpdateStatus.Ticket = *ticket; + + lfgUpdateStatus.SubType = lfg::LFG_QUEUE_DUNGEON; // other types not implemented + lfgUpdateStatus.Reason = updateData.updateType; + std::transform(updateData.dungeons.begin(), updateData.dungeons.end(), std::back_inserter(lfgUpdateStatus.Slots), [](uint32 dungeonId) + { + return sLFGMgr->GetLFGDungeonEntry(dungeonId); + }); + lfgUpdateStatus.RequestedRoles = sLFGMgr->GetRoles(_player->GetGUID()); + //lfgUpdateStatus.SuspendedPlayers; + lfgUpdateStatus.IsParty = party; + lfgUpdateStatus.NotifyUI = true; + lfgUpdateStatus.Joined = join; + lfgUpdateStatus.LfgJoined = updateData.updateType != lfg::LFG_UPDATETYPE_REMOVED_FROM_QUEUE; + lfgUpdateStatus.Queued = queued; + + SendPacket(lfgUpdateStatus.Write()); } void WorldSession::SendLfgRoleChosen(ObjectGuid guid, uint8 roles) @@ -473,11 +287,11 @@ void WorldSession::SendLfgRoleChosen(ObjectGuid guid, uint8 roles) TC_LOG_DEBUG("lfg", "SMSG_LFG_ROLE_CHOSEN %s guid: %s roles: %u", GetPlayerInfo().c_str(), guid.ToString().c_str(), roles); - WorldPacket data(SMSG_ROLE_CHOSEN, 8 + 1 + 4); - data << guid; // Guid - data << uint8(roles > 0); // Ready - data << uint32(roles); // Roles - SendPacket(&data); + WorldPackets::LFG::RoleChosen roleChosen; + roleChosen.Player = guid; + roleChosen.RoleMask = roles; + roleChosen.Accepted = roles > 0; + SendPacket(roleChosen.Write()); } void WorldSession::SendLfgRoleCheckUpdate(lfg::LfgRoleCheck const& roleCheck) @@ -489,118 +303,63 @@ void WorldSession::SendLfgRoleCheckUpdate(lfg::LfgRoleCheck const& roleCheck) dungeons = roleCheck.dungeons; TC_LOG_DEBUG("lfg", "SMSG_LFG_ROLE_CHECK_UPDATE %s", GetPlayerInfo().c_str()); - WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + dungeons.size() * 4 + 1 + roleCheck.roles.size() * (8 + 1 + 4 + 1)); - - data << uint32(roleCheck.state); // Check result - data << uint8(roleCheck.state == lfg::LFG_ROLECHECK_INITIALITING); - data << uint8(dungeons.size()); // Number of dungeons - if (!dungeons.empty()) - for (lfg::LfgDungeonSet::iterator it = dungeons.begin(); it != dungeons.end(); ++it) - data << uint32(sLFGMgr->GetLFGDungeonEntry(*it)); // Dungeon - - data << uint8(roleCheck.roles.size()); // Players in group + WorldPackets::LFG::LFGRoleCheckUpdate lfgRoleCheckUpdate; + lfgRoleCheckUpdate.PartyIndex = 127; + lfgRoleCheckUpdate.RoleCheckStatus = roleCheck.state; + std::transform(dungeons.begin(), dungeons.end(), std::back_inserter(lfgRoleCheckUpdate.JoinSlots), [](uint32 dungeonId) + { + return sLFGMgr->GetLFGDungeonEntry(dungeonId); + }); + lfgRoleCheckUpdate.BgQueueID = 0; + lfgRoleCheckUpdate.GroupFinderActivityID = 0; if (!roleCheck.roles.empty()) { // Leader info MUST be sent 1st :S - ObjectGuid guid = roleCheck.leader; - uint8 roles = roleCheck.roles.find(guid)->second; - Player* player = ObjectAccessor::FindConnectedPlayer(guid); - data << guid; // Guid - data << uint8(roles > 0); // Ready - data << uint32(roles); // Roles - data << uint8(player ? player->getLevel() : 0); // Level + uint8 roles = roleCheck.roles.find(roleCheck.leader)->second; + lfgRoleCheckUpdate.Members.emplace_back(roleCheck.leader, roles, ASSERT_NOTNULL(sWorld->GetCharacterInfo(roleCheck.leader))->Level, roles > 0); for (lfg::LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it) { if (it->first == roleCheck.leader) continue; - guid = it->first; roles = it->second; - player = ObjectAccessor::FindConnectedPlayer(guid); - data << guid; // Guid - data << uint8(roles > 0); // Ready - data << uint32(roles); // Roles - data << uint8(player ? player->getLevel() : 0);// Level + lfgRoleCheckUpdate.Members.emplace_back(it->first, roles, ASSERT_NOTNULL(sWorld->GetCharacterInfo(it->first))->Level, roles > 0); } } - SendPacket(&data); + + SendPacket(lfgRoleCheckUpdate.Write()); } void WorldSession::SendLfgJoinResult(lfg::LfgJoinResultData const& joinData) { - uint32 size = 0; - ObjectGuid guid = GetPlayer()->GetGUID(); - uint32 queueId = sLFGMgr->GetQueueId(_player->GetGUID()); - for (lfg::LfgLockPartyMap::const_iterator it = joinData.lockmap.begin(); it != joinData.lockmap.end(); ++it) - size += 8 + 4 + uint32(it->second.size()) * (4 + 4 + 4 + 4); - TC_LOG_DEBUG("lfg", "SMSG_LFG_JOIN_RESULT %s checkResult: %u checkValue: %u", GetPlayerInfo().c_str(), joinData.result, joinData.state); - WorldPacket data(SMSG_LFG_JOIN_RESULT, 4 + 4 + size); - data << uint32(3); - data << uint8(joinData.result); // Check Result - data << uint32(queueId); // Queue Id - data << uint8(joinData.state); // Check Value - data << uint32(time(NULL)); // Join date - data.WriteBit(guid[2] != 0); - data.WriteBit(guid[7] != 0); - data.WriteBit(guid[3] != 0); - data.WriteBit(guid[0] != 0); - data.WriteBits(joinData.lockmap.size(), 24); - for (lfg::LfgLockPartyMap::const_iterator it = joinData.lockmap.begin(); it != joinData.lockmap.end(); ++it) - { - ObjectGuid playerGuid = it->first; - data.WriteBit(playerGuid[7] != 0); - data.WriteBit(playerGuid[5] != 0); - data.WriteBit(playerGuid[3] != 0); - data.WriteBit(playerGuid[6] != 0); - data.WriteBit(playerGuid[0] != 0); - data.WriteBit(playerGuid[2] != 0); - data.WriteBit(playerGuid[4] != 0); - data.WriteBit(playerGuid[1] != 0); - data.WriteBits(it->second.size(), 22); - } + WorldPackets::LFG::LFGJoinResult lfgJoinResult; + if (WorldPackets::LFG::RideTicket const* ticket = sLFGMgr->GetTicket(GetPlayer()->GetGUID())) + lfgJoinResult.Ticket = *ticket; + lfgJoinResult.Result = joinData.result; + if (joinData.result == lfg::LFG_JOIN_ROLE_CHECK_FAILED) + lfgJoinResult.ResultDetail = joinData.state; - data.WriteBit(guid[4] != 0); - data.WriteBit(guid[5] != 0); - data.WriteBit(guid[1] != 0); - data.WriteBit(guid[6] != 0); for (lfg::LfgLockPartyMap::const_iterator it = joinData.lockmap.begin(); it != joinData.lockmap.end(); ++it) { + lfgJoinResult.BlackList.emplace_back(); + WorldPackets::LFG::LFGJoinBlackList& blackList = lfgJoinResult.BlackList.back(); + blackList.Guid = it->first; + ObjectGuid playerGuid = it->first; for (lfg::LfgLockMap::const_iterator itr = it->second.begin(); itr != it->second.end(); ++itr) { TC_LOG_TRACE("lfg", "SendLfgJoinResult:: %s DungeonID: %u Lock status: %u Required itemLevel: %u Current itemLevel: %f", - playerGuid.ToString().c_str(), (itr->first & 0x00FFFFFF), itr->second.lockStatus, itr->second.requiredItemLevel, itr->second.currentItemLevel); + it->first.ToString().c_str(), (itr->first & 0x00FFFFFF), itr->second.lockStatus, itr->second.requiredItemLevel, itr->second.currentItemLevel); - data << uint32(itr->second.lockStatus); // Lock status - data << uint32(itr->second.currentItemLevel); // Current itemLevel - data << uint32(itr->second.requiredItemLevel); // Required itemLevel - data << uint32(itr->first); // Dungeon entry (id + type) + blackList.Slots.emplace_back(itr->first, itr->second.lockStatus, itr->second.requiredItemLevel, itr->second.currentItemLevel); } - - data.WriteByteSeq(playerGuid[2]); - data.WriteByteSeq(playerGuid[5]); - data.WriteByteSeq(playerGuid[1]); - data.WriteByteSeq(playerGuid[0]); - data.WriteByteSeq(playerGuid[4]); - data.WriteByteSeq(playerGuid[3]); - data.WriteByteSeq(playerGuid[6]); - data.WriteByteSeq(playerGuid[7]); } - data.WriteByteSeq(guid[1]); - data.WriteByteSeq(guid[4]); - data.WriteByteSeq(guid[3]); - data.WriteByteSeq(guid[5]); - data.WriteByteSeq(guid[0]); - data.WriteByteSeq(guid[7]); - data.WriteByteSeq(guid[2]); - data.WriteByteSeq(guid[6]); - - SendPacket(&data); + SendPacket(lfgJoinResult.Write()); } void WorldSession::SendLfgQueueStatus(lfg::LfgQueueStatusData const& queueData) @@ -612,40 +371,20 @@ void WorldSession::SendLfgQueueStatus(lfg::LfgQueueStatusData const& queueData) queueData.waitTimeTank, queueData.waitTimeHealer, queueData.waitTimeDps, queueData.queuedTime, queueData.tanks, queueData.healers, queueData.dps); - ObjectGuid guid = _player->GetGUID(); - WorldPacket data(SMSG_LFG_QUEUE_STATUS, 4 + 4 + 4 + 4 + 4 + 4 + 1 + 1 + 1 + 4 + 4 + 4 + 4 + 8); - data.WriteBit(guid[3] != 0); - data.WriteBit(guid[0] != 0); - data.WriteBit(guid[2] != 0); - data.WriteBit(guid[6] != 0); - data.WriteBit(guid[5] != 0); - data.WriteBit(guid[7] != 0); - data.WriteBit(guid[1] != 0); - data.WriteBit(guid[4] != 0); - - data.WriteByteSeq(guid[0]); - data << uint8(queueData.tanks); // Tanks needed - data << int32(queueData.waitTimeTank); // Wait Tanks - data << uint8(queueData.healers); // Healers needed - data << int32(queueData.waitTimeHealer); // Wait Healers - data << uint8(queueData.dps); // Dps needed - data << int32(queueData.waitTimeDps); // Wait Dps - data.WriteByteSeq(guid[4]); - data.WriteByteSeq(guid[6]); - data << int32(queueData.waitTime); // Wait Time - data << uint32(queueData.joinTime); // Join time - data << uint32(queueData.dungeonId); // Dungeon - data << uint32(queueData.queuedTime); // Player wait time in queue - data.WriteByteSeq(guid[5]); - data.WriteByteSeq(guid[7]); - data.WriteByteSeq(guid[3]); - data << uint32(queueData.queueId); // Queue Id - data.WriteByteSeq(guid[1]); - data.WriteByteSeq(guid[2]); - data << int32(queueData.waitTimeAvg); // Average Wait time - data << uint32(3); - - SendPacket(&data); + WorldPackets::LFG::LFGQueueStatus lfgQueueStatus; + if (WorldPackets::LFG::RideTicket const* ticket = sLFGMgr->GetTicket(GetPlayer()->GetGUID())) + lfgQueueStatus.Ticket = *ticket; + lfgQueueStatus.Slot = sLFGMgr->GetLFGDungeonEntry(queueData.dungeonId); + lfgQueueStatus.AvgWaitTimeMe = queueData.waitTime; + lfgQueueStatus.AvgWaitTime = queueData.waitTimeAvg; + lfgQueueStatus.AvgWaitTimeByRole[0] = queueData.waitTimeTank; + lfgQueueStatus.AvgWaitTimeByRole[1] = queueData.waitTimeHealer; + lfgQueueStatus.AvgWaitTimeByRole[2] = queueData.waitTimeDps; + lfgQueueStatus.LastNeeded[0] = queueData.tanks; + lfgQueueStatus.LastNeeded[1] = queueData.healers; + lfgQueueStatus.LastNeeded[2] = queueData.dps; + lfgQueueStatus.QueuedTime = queueData.queuedTime; + SendPacket(lfgQueueStatus.Write()); } void WorldSession::SendLfgPlayerReward(lfg::LfgPlayerRewardData const& rewardData) @@ -656,28 +395,35 @@ void WorldSession::SendLfgPlayerReward(lfg::LfgPlayerRewardData const& rewardDat TC_LOG_DEBUG("lfg", "SMSG_LFG_PLAYER_REWARD %s rdungeonEntry: %u, sdungeonEntry: %u, done: %u", GetPlayerInfo().c_str(), rewardData.rdungeonEntry, rewardData.sdungeonEntry, rewardData.done); - uint8 itemNum = rewardData.quest->GetRewItemsCount() + rewardData.quest->GetRewCurrencyCount(); + WorldPackets::LFG::LFGPlayerReward lfgPlayerReward; + lfgPlayerReward.QueuedSlot = rewardData.rdungeonEntry; + lfgPlayerReward.ActualSlot = rewardData.sdungeonEntry; + lfgPlayerReward.RewardMoney = GetPlayer()->GetQuestMoneyReward(rewardData.quest); + lfgPlayerReward.AddedXP = GetPlayer()->GetQuestXPReward(rewardData.quest); + + for (uint8 i = 0; i < QUEST_REWARD_ITEM_COUNT; ++i) + if (uint32 itemId = rewardData.quest->RewardItemId[i]) + lfgPlayerReward.Rewards.emplace_back(itemId, rewardData.quest->RewardItemCount[i], 0, false); - WorldPacket data(SMSG_LFG_PLAYER_REWARD, 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 + 1 + itemNum * (4 + 4 + 4)); - data << uint32(rewardData.rdungeonEntry); // Random Dungeon Finished - data << uint32(rewardData.sdungeonEntry); // Dungeon Finished - BuildQuestReward(data, rewardData.quest, GetPlayer()); - SendPacket(&data); + for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + if (uint32 curencyId = rewardData.quest->RewardCurrencyId[i]) + lfgPlayerReward.Rewards.emplace_back(curencyId, rewardData.quest->RewardCurrencyCount[i], 0, true); + + SendPacket(lfgPlayerReward.Write()); } void WorldSession::SendLfgBootProposalUpdate(lfg::LfgPlayerBoot const& boot) { - ObjectGuid guid = GetPlayer()->GetGUID(); - lfg::LfgAnswer playerVote = boot.votes.find(guid)->second; + lfg::LfgAnswer playerVote = boot.votes.find(GetPlayer()->GetGUID())->second; uint8 votesNum = 0; uint8 agreeNum = 0; - uint32 secsleft = uint8((boot.cancelTime - time(NULL)) / 1000); - for (lfg::LfgAnswerContainer::const_iterator it = boot.votes.begin(); it != boot.votes.end(); ++it) + int32 secsleft = int32((boot.cancelTime - time(nullptr)) / 1000); + for (const auto& vote : boot.votes) { - if (it->second != lfg::LFG_ANSWER_PENDING) + if (vote.second != lfg::LFG_ANSWER_PENDING) { ++votesNum; - if (it->second == lfg::LFG_ANSWER_AGREE) + if (vote.second == lfg::LFG_ANSWER_AGREE) ++agreeNum; } } @@ -687,18 +433,19 @@ void WorldSession::SendLfgBootProposalUpdate(lfg::LfgPlayerBoot const& boot) GetPlayerInfo().c_str(), uint8(boot.inProgress), uint8(playerVote != lfg::LFG_ANSWER_PENDING), uint8(playerVote == lfg::LFG_ANSWER_AGREE), boot.victim.ToString().c_str(), votesNum, agreeNum, secsleft, lfg::LFG_GROUP_KICK_VOTES_NEEDED, boot.reason.c_str()); - WorldPacket data(SMSG_LFG_BOOT_PLAYER, 1 + 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + boot.reason.length()); - data << uint8(boot.inProgress); // Vote in progress - data << uint8(agreeNum >= lfg::LFG_GROUP_KICK_VOTES_NEEDED); // Did succeed - data << uint8(playerVote != lfg::LFG_ANSWER_PENDING); // Did Vote - data << uint8(playerVote == lfg::LFG_ANSWER_AGREE); // Agree - data << boot.victim; // Victim GUID - data << uint32(votesNum); // Total Votes - data << uint32(agreeNum); // Agree Count - data << uint32(secsleft); // Time Left - data << uint32(lfg::LFG_GROUP_KICK_VOTES_NEEDED); // Needed Votes - data << boot.reason.c_str(); // Kick reason - SendPacket(&data); + + WorldPackets::LFG::LfgBootPlayer lfgBootPlayer; + lfgBootPlayer.Info.VoteInProgress = boot.inProgress; + lfgBootPlayer.Info.VotePassed = agreeNum >= lfg::LFG_GROUP_KICK_VOTES_NEEDED; + lfgBootPlayer.Info.MyVoteCompleted = playerVote != lfg::LFG_ANSWER_PENDING; + lfgBootPlayer.Info.MyVote = playerVote == lfg::LFG_ANSWER_AGREE; + lfgBootPlayer.Info.Target = boot.victim; + lfgBootPlayer.Info.TotalVotes = votesNum; + lfgBootPlayer.Info.BootVotes = agreeNum; + lfgBootPlayer.Info.TimeLeft = secsleft; + lfgBootPlayer.Info.VotesNeeded = lfg::LFG_GROUP_KICK_VOTES_NEEDED; + lfgBootPlayer.Info.Reason = boot.reason; + SendPacket(lfgBootPlayer.Write()); } void WorldSession::SendLfgUpdateProposal(lfg::LfgProposal const& proposal) @@ -707,8 +454,6 @@ void WorldSession::SendLfgUpdateProposal(lfg::LfgProposal const& proposal) ObjectGuid gguid = proposal.players.find(guid)->second.group; bool silent = !proposal.isNew && gguid == proposal.group; uint32 dungeonEntry = proposal.dungeonId; - uint32 queueId = sLFGMgr->GetQueueId(_player->GetGUID()); - time_t joinTime = sLFGMgr->GetQueueJoinTime(_player->GetGUID()); TC_LOG_DEBUG("lfg", "SMSG_LFG_PROPOSAL_UPDATE %s state: %u", GetPlayerInfo().c_str(), proposal.state); @@ -721,124 +466,49 @@ void WorldSession::SendLfgUpdateProposal(lfg::LfgProposal const& proposal) dungeonEntry = (*playerDungeons.begin()); } - dungeonEntry = sLFGMgr->GetLFGDungeonEntry(dungeonEntry); - - WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + proposal.players.size() * (4 + 1 + 1 + 1 + 1 +1)); - data << uint32(joinTime); - data << uint32(proposal.encounters); // Encounters done - data << uint32(queueId); // Queue Id - data << uint32(3); // Always 3 - data << uint32(dungeonEntry); // Dungeon - data << uint32(proposal.id); // Proposal Id - data << uint8(proposal.state); // State - - data.WriteBit(gguid[4] != 0); - data.WriteBit(guid[3] != 0); - data.WriteBit(guid[7] != 0); - data.WriteBit(guid[0] != 0); - data.WriteBit(gguid[1] != 0); - data.WriteBit(silent); - data.WriteBit(guid[4] != 0); - data.WriteBit(guid[5] != 0); - data.WriteBit(gguid[3] != 0); - data.WriteBits(proposal.players.size(), 23); - data.WriteBit(gguid[7] != 0); - - for (lfg::LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) + WorldPackets::LFG::LFGProposalUpdate lfgProposalUpdate; + if (WorldPackets::LFG::RideTicket const* ticket = sLFGMgr->GetTicket(GetPlayer()->GetGUID())) + lfgProposalUpdate.Ticket = *ticket; + lfgProposalUpdate.InstanceID = 0; + lfgProposalUpdate.ProposalID = proposal.id; + lfgProposalUpdate.Slot = sLFGMgr->GetLFGDungeonEntry(dungeonEntry); + lfgProposalUpdate.State = proposal.state; + lfgProposalUpdate.CompletedMask = proposal.encounters; + lfgProposalUpdate.ValidCompletedMask = true; + lfgProposalUpdate.ProposalSilent = silent; + lfgProposalUpdate.IsRequeue = !proposal.isNew; + + for (auto const& player : proposal.players) { - lfg::LfgProposalPlayer const& player = it->second; - - if (!player.group) - { - data.WriteBit(false); - data.WriteBit(false); - } - else - { - data.WriteBit(player.group == proposal.group); // Is group in dungeon - data.WriteBit(player.group == gguid); // Same group as the player - } - - data.WriteBit(player.accept == lfg::LFG_ANSWER_AGREE); - data.WriteBit(player.accept != lfg::LFG_ANSWER_PENDING); - data.WriteBit(it->first == guid); - } - - data.WriteBit(gguid[5] != 0); - data.WriteBit(guid[6] != 0); - data.WriteBit(gguid[2] != 0); - data.WriteBit(gguid[6] != 0); - data.WriteBit(guid[2] != 0); - data.WriteBit(guid[1] != 0); - data.WriteBit(gguid[0] != 0); - - data.WriteByteSeq(guid[5]); - data.WriteByteSeq(gguid[3]); - data.WriteByteSeq(gguid[6]); - data.WriteByteSeq(guid[6]); - data.WriteByteSeq(guid[0]); - data.WriteByteSeq(gguid[5]); - data.WriteByteSeq(guid[1]); - - for (lfg::LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) - { - lfg::LfgProposalPlayer const& player = it->second; - data << uint32(player.role); + lfgProposalUpdate.Players.emplace_back(); + auto& proposalPlayer = lfgProposalUpdate.Players.back(); + proposalPlayer.Roles = player.second.role; + proposalPlayer.Me = player.first == guid; + proposalPlayer.MyParty = !player.second.group.IsEmpty() && player.second.group == proposal.group; + proposalPlayer.SameParty = !player.second.group.IsEmpty() && player.second.group == gguid; + proposalPlayer.Responded = player.second.accept != lfg::LFG_ANSWER_PENDING; + proposalPlayer.Accepted = player.second.accept == lfg::LFG_ANSWER_AGREE; } - data.WriteByteSeq(gguid[7]); - data.WriteByteSeq(guid[4]); - data.WriteByteSeq(gguid[0]); - data.WriteByteSeq(gguid[1]); - data.WriteByteSeq(guid[2]); - data.WriteByteSeq(guid[7]); - data.WriteByteSeq(gguid[2]); - data.WriteByteSeq(guid[3]); - data.WriteByteSeq(gguid[4]); - - SendPacket(&data); -} - -void WorldSession::SendLfgLfrList(bool /*update*/) -{ - //TC_LOG_DEBUG("lfg", "SMSG_LFG_LFR_LIST %s update: %u", - // GetPlayerInfo().c_str(), update ? 1 : 0); - //WorldPacket data(SMSG_LFG_UPDATE_SEARCH, 1); - //data << uint8(update); // In Lfg Queue? - //SendPacket(&data); + SendPacket(lfgProposalUpdate.Write()); } void WorldSession::SendLfgDisabled() { TC_LOG_DEBUG("lfg", "SMSG_LFG_DISABLED %s", GetPlayerInfo().c_str()); - WorldPacket data(SMSG_LFG_DISABLED, 0); - SendPacket(&data); + SendPacket(WorldPackets::LFG::LFGDisabled().Write()); } void WorldSession::SendLfgOfferContinue(uint32 dungeonEntry) { TC_LOG_DEBUG("lfg", "SMSG_LFG_OFFER_CONTINUE %s dungeon entry: %u", GetPlayerInfo().c_str(), dungeonEntry); - WorldPacket data(SMSG_LFG_OFFER_CONTINUE, 4); - data << uint32(dungeonEntry); - SendPacket(&data); + SendPacket(WorldPackets::LFG::LFGOfferContinue(sLFGMgr->GetLFGDungeonEntry(dungeonEntry)).Write()); } -void WorldSession::SendLfgTeleportError(uint8 err) +void WorldSession::SendLfgTeleportError(lfg::LfgTeleportResult err) { TC_LOG_DEBUG("lfg", "SMSG_LFG_TELEPORT_DENIED %s reason: %u", GetPlayerInfo().c_str(), err); - WorldPacket data(SMSG_LFG_TELEPORT_DENIED, 4); - data << uint32(err); // Error - SendPacket(&data); -} - -/* -void WorldSession::SendLfrUpdateListOpcode(uint32 dungeonEntry) -{ - TC_LOG_DEBUG("network", "SMSG_LFG_UPDATE_LIST %s dungeon entry: %u", - GetPlayerInfo().c_str(), dungeonEntry); - WorldPacket data(SMSG_LFG_UPDATE_LIST); - SendPacket(&data); + SendPacket(WorldPackets::LFG::LFGTeleportDenied(err).Write()); } -*/ diff --git a/src/server/game/Server/Packets/LFGPackets.cpp b/src/server/game/Server/Packets/LFGPackets.cpp index 4ec8178035c..ddc18719815 100644 --- a/src/server/game/Server/Packets/LFGPackets.cpp +++ b/src/server/game/Server/Packets/LFGPackets.cpp @@ -16,3 +16,392 @@ */ #include "LFGPackets.h" + +void WorldPackets::LFG::DFJoin::Read() +{ + QueueAsGroup = _worldPacket.ReadBit(); + Unknown = _worldPacket.ReadBit(); + _worldPacket >> PartyIndex; + _worldPacket >> Roles; + Slots.resize(_worldPacket.read<uint32>()); + for (uint32& slot : Slots) + _worldPacket >> slot; +} + +void WorldPackets::LFG::DFLeave::Read() +{ + _worldPacket >> Ticket; +} + +void WorldPackets::LFG::DFProposalResponse::Read() +{ + _worldPacket >> Ticket; + _worldPacket >> InstanceID; + _worldPacket >> InstanceID; + Accepted = _worldPacket.ReadBit(); +} + +void WorldPackets::LFG::DFSetRoles::Read() +{ + _worldPacket >> RolesDesired; + _worldPacket >> PartyIndex; +} + +void WorldPackets::LFG::DFBootPlayerVote::Read() +{ + Vote = _worldPacket.ReadBit(); +} + +void WorldPackets::LFG::DFTeleport::Read() +{ + TeleportOut = _worldPacket.ReadBit(); +} + +void WorldPackets::LFG::DFGetSystemInfo::Read() +{ + Player = _worldPacket.ReadBit(); + _worldPacket >> PartyIndex; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LFGBlackListSlot const& lfgBlackListSlot) +{ + data << uint32(lfgBlackListSlot.Slot); + data << uint32(lfgBlackListSlot.Reason); + data << int32(lfgBlackListSlot.SubReason1); + data << int32(lfgBlackListSlot.SubReason2); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LFGBlackList const& blackList) +{ + data.WriteBit(blackList.PlayerGuid.is_initialized()); + data << uint32(blackList.Slot.size()); + if (blackList.PlayerGuid) + data << *blackList.PlayerGuid; + + for (WorldPackets::LFG::LFGBlackListSlot const& slot : blackList.Slot) + data << slot; + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LfgPlayerQuestRewardItem const& playerQuestRewardItem) +{ + data << int32(playerQuestRewardItem.ItemID); + data << int32(playerQuestRewardItem.Quantity); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LfgPlayerQuestRewardCurrency const& playerQuestRewardCurrency) +{ + data << int32(playerQuestRewardCurrency.CurrencyID); + data << int32(playerQuestRewardCurrency.Quantity); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LfgPlayerQuestReward const& playerQuestReward) +{ + data << uint32(playerQuestReward.Mask); + data << int32(playerQuestReward.RewardMoney); + data << int32(playerQuestReward.RewardXP); + data << uint32(playerQuestReward.Item.size()); + data << uint32(playerQuestReward.Currency.size()); + data << uint32(playerQuestReward.BonusCurrency.size()); + + for (WorldPackets::LFG::LfgPlayerQuestRewardItem const& item : playerQuestReward.Item) + data << item; + + for (WorldPackets::LFG::LfgPlayerQuestRewardCurrency const& currency : playerQuestReward.Currency) + data << currency; + + for (WorldPackets::LFG::LfgPlayerQuestRewardCurrency const& bonusCurrency : playerQuestReward.BonusCurrency) + data << bonusCurrency; + + data.WriteBit(playerQuestReward.RewardSpellID.is_initialized()); + data.WriteBit(playerQuestReward.Unused1.is_initialized()); + data.WriteBit(playerQuestReward.Unused2.is_initialized()); + data.WriteBit(playerQuestReward.Honor.is_initialized()); + data.FlushBits(); + + if (playerQuestReward.RewardSpellID) + data << int32(*playerQuestReward.RewardSpellID); + + if (playerQuestReward.Unused1) + data << int32(*playerQuestReward.Unused1); + + if (playerQuestReward.Unused2) + data << uint64(*playerQuestReward.Unused2); + + if (playerQuestReward.Honor) + data << int32(*playerQuestReward.Honor); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LfgPlayerDungeonInfo const& playerDungeonInfo) +{ + data << uint32(playerDungeonInfo.Slot); + data << int32(playerDungeonInfo.CompletionQuantity); + data << int32(playerDungeonInfo.CompletionLimit); + data << int32(playerDungeonInfo.CompletionCurrencyID); + data << int32(playerDungeonInfo.SpecificQuantity); + data << int32(playerDungeonInfo.SpecificLimit); + data << int32(playerDungeonInfo.OverallQuantity); + data << int32(playerDungeonInfo.OverallLimit); + data << int32(playerDungeonInfo.PurseWeeklyQuantity); + data << int32(playerDungeonInfo.PurseWeeklyLimit); + data << int32(playerDungeonInfo.PurseQuantity); + data << int32(playerDungeonInfo.PurseLimit); + data << int32(playerDungeonInfo.Quantity); + data << uint32(playerDungeonInfo.CompletedMask); + data << uint32(playerDungeonInfo.EncounterMask); + data << uint32(playerDungeonInfo.ShortageReward.size()); + data.WriteBit(playerDungeonInfo.FirstReward); + data.WriteBit(playerDungeonInfo.ShortageEligible); + data.FlushBits(); + + data << playerDungeonInfo.Rewards; + for (WorldPackets::LFG::LfgPlayerQuestReward const& shortageReward : playerDungeonInfo.ShortageReward) + data << shortageReward; + + return data; +} + +WorldPacket const* WorldPackets::LFG::LfgPlayerInfo::Write() +{ + _worldPacket << uint32(Dungeon.size()); + _worldPacket << BlackList; + for (LfgPlayerDungeonInfo const& playerDungeonInfo : Dungeon) + _worldPacket << playerDungeonInfo; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::LFG::LfgPartyInfo::Write() +{ + _worldPacket << uint32(Player.size()); + for (WorldPackets::LFG::LFGBlackList const& player : Player) + _worldPacket << player; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::LFG::LFGUpdateStatus::Write() +{ + _worldPacket << Ticket; + _worldPacket << uint8(SubType); + _worldPacket << uint8(Reason); + _worldPacket << uint32(Slots.size()); + _worldPacket << uint32(RequestedRoles); + _worldPacket << uint32(SuspendedPlayers.size()); + + for (uint32 slot : Slots) + _worldPacket << uint32(slot); + + for (ObjectGuid const& suspendedPlayer : SuspendedPlayers) + _worldPacket << suspendedPlayer; + + _worldPacket.WriteBit(IsParty); + _worldPacket.WriteBit(NotifyUI); + _worldPacket.WriteBit(Joined); + _worldPacket.WriteBit(LfgJoined); + _worldPacket.WriteBit(Queued); + _worldPacket.WriteBit(Unused); + _worldPacket.FlushBits(); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::LFG::RoleChosen::Write() +{ + _worldPacket << Player; + _worldPacket << uint32(RoleMask); + _worldPacket.WriteBit(Accepted); + _worldPacket.FlushBits(); + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LFGRoleCheckUpdateMember const& lfgRoleCheckUpdateMember) +{ + data << lfgRoleCheckUpdateMember.Guid; + data << uint32(lfgRoleCheckUpdateMember.RolesDesired); + data << uint8(lfgRoleCheckUpdateMember.Level); + data.WriteBit(lfgRoleCheckUpdateMember.RoleCheckComplete); + data.FlushBits(); + + return data; +} + +WorldPacket const* WorldPackets::LFG::LFGRoleCheckUpdate::Write() +{ + _worldPacket << uint8(PartyIndex); + _worldPacket << uint8(RoleCheckStatus); + _worldPacket << uint32(JoinSlots.size()); + _worldPacket << uint64(BgQueueID); + _worldPacket << int32(GroupFinderActivityID); + _worldPacket << uint32(Members.size()); + + for (uint32 slot : JoinSlots) + _worldPacket << uint32(slot); + + _worldPacket.WriteBit(IsBeginning); + _worldPacket.WriteBit(IsRequeue); + _worldPacket.FlushBits(); + + for (LFGRoleCheckUpdateMember const& member : Members) + _worldPacket << member; + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LFGJoinBlackListSlot const& lfgBlackListSlot) +{ + data << int32(lfgBlackListSlot.Slot); + data << int32(lfgBlackListSlot.Reason); + data << int32(lfgBlackListSlot.SubReason1); + data << int32(lfgBlackListSlot.SubReason2); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LFGJoinBlackList const& blackList) +{ + data << blackList.Guid; + data << uint32(blackList.Slots.size()); + + for (WorldPackets::LFG::LFGJoinBlackListSlot const& slot : blackList.Slots) + data << slot; + + return data; +} + +WorldPacket const* WorldPackets::LFG::LFGJoinResult::Write() +{ + _worldPacket << Ticket; + _worldPacket << uint8(Result); + _worldPacket << uint8(ResultDetail); + _worldPacket << uint32(BlackList.size()); + + for (LFGJoinBlackList const& blackList : BlackList) + _worldPacket << blackList; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::LFG::LFGQueueStatus::Write() +{ + _worldPacket << Ticket; + _worldPacket << uint32(Slot); + _worldPacket << uint32(AvgWaitTimeMe); + _worldPacket << uint32(AvgWaitTime); + + for (uint32 i = 0; i < 3; ++i) + { + _worldPacket << uint32(AvgWaitTimeByRole[i]); + _worldPacket << uint8(LastNeeded[i]); + } + _worldPacket << uint32(QueuedTime); + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LFGPlayerRewards const& lfgPlayerRewards) +{ + data << int32(lfgPlayerRewards.RewardItem); + data << uint32(lfgPlayerRewards.RewardItemQuantity); + data << int32(lfgPlayerRewards.BonusCurrency); + data.WriteBit(lfgPlayerRewards.IsCurrency); + + return data; +} + +WorldPacket const* WorldPackets::LFG::LFGPlayerReward::Write() +{ + _worldPacket << uint32(QueuedSlot); + _worldPacket << uint32(ActualSlot); + _worldPacket << int32(RewardMoney); + _worldPacket << int32(AddedXP); + _worldPacket << uint32(Rewards.size()); + + for (LFGPlayerRewards const& reward : Rewards) + _worldPacket << reward; + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LfgBootInfo const& lfgBootInfo) +{ + data.WriteBit(lfgBootInfo.VoteInProgress); + data.WriteBit(lfgBootInfo.VotePassed); + data.WriteBit(lfgBootInfo.MyVoteCompleted); + data.WriteBit(lfgBootInfo.MyVote); + data.WriteBits(lfgBootInfo.Reason.length(), 8); + data << lfgBootInfo.Target; + data << uint32(lfgBootInfo.TotalVotes); + data << uint32(lfgBootInfo.BootVotes); + data << int32(lfgBootInfo.TimeLeft); + data << uint32(lfgBootInfo.VotesNeeded); + data.WriteString(lfgBootInfo.Reason); + + return data; +} + +WorldPacket const* WorldPackets::LFG::LfgBootPlayer::Write() +{ + _worldPacket << Info; + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LFGProposalUpdatePlayer const& lfgProposalUpdatePlayer) +{ + data << uint32(lfgProposalUpdatePlayer.Roles); + data.WriteBit(lfgProposalUpdatePlayer.Me); + data.WriteBit(lfgProposalUpdatePlayer.SameParty); + data.WriteBit(lfgProposalUpdatePlayer.MyParty); + data.WriteBit(lfgProposalUpdatePlayer.Responded); + data.WriteBit(lfgProposalUpdatePlayer.Accepted); + data.FlushBits(); + + return data; +} + +WorldPacket const* WorldPackets::LFG::LFGProposalUpdate::Write() +{ + _worldPacket << Ticket; + _worldPacket << uint64(InstanceID); + _worldPacket << uint32(ProposalID); + _worldPacket << uint32(Slot); + _worldPacket << int8(State); + _worldPacket << uint32(CompletedMask); + _worldPacket << uint32(Players.size()); + _worldPacket << uint8(Unused); + _worldPacket.WriteBit(ValidCompletedMask); + _worldPacket.WriteBit(ProposalSilent); + _worldPacket.WriteBit(IsRequeue); + _worldPacket.FlushBits(); + + for (LFGProposalUpdatePlayer const& player : Players) + _worldPacket << player; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::LFG::LFGOfferContinue::Write() +{ + _worldPacket << uint32(Slot); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::LFG::LFGTeleportDenied::Write() +{ + _worldPacket.WriteBits(Reason, 4); + _worldPacket.FlushBits(); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/LFGPackets.h b/src/server/game/Server/Packets/LFGPackets.h index 18b8ef8620a..e0958a9daea 100644 --- a/src/server/game/Server/Packets/LFGPackets.h +++ b/src/server/game/Server/Packets/LFGPackets.h @@ -20,11 +20,414 @@ #include "Packet.h" #include "LFGPacketsCommon.h" +#include "Optional.h" + +namespace lfg +{ + enum LfgTeleportResult : uint8; +} namespace WorldPackets { namespace LFG { + class DFJoin final : public ClientPacket + { + public: + DFJoin(WorldPacket&& packet) : ClientPacket(CMSG_DF_JOIN, std::move(packet)) { } + + void Read() override; + + bool QueueAsGroup = false; + bool Unknown = false; // Always false in 7.2.5 + uint8 PartyIndex = 0; + uint32 Roles = 0; + Array<uint32, 50> Slots; + }; + + class DFLeave final : public ClientPacket + { + public: + DFLeave(WorldPacket&& packet) : ClientPacket(CMSG_DF_LEAVE, std::move(packet)) { } + + void Read() override; + + RideTicket Ticket; + }; + + class DFProposalResponse final : public ClientPacket + { + public: + DFProposalResponse(WorldPacket&& packet) : ClientPacket(CMSG_DF_PROPOSAL_RESPONSE, std::move(packet)) { } + + void Read() override; + + RideTicket Ticket; + uint64 InstanceID = 0; + uint32 ProposalID = 0; + bool Accepted = false; + }; + + class DFSetRoles final : public ClientPacket + { + public: + DFSetRoles(WorldPacket&& packet) : ClientPacket(CMSG_DF_SET_ROLES, std::move(packet)) { } + + void Read() override; + + uint32 RolesDesired = 0; + uint8 PartyIndex = 0; + }; + + class DFBootPlayerVote final : public ClientPacket + { + public: + DFBootPlayerVote(WorldPacket&& packet) : ClientPacket(CMSG_DF_BOOT_PLAYER_VOTE, std::move(packet)) { } + + void Read() override; + + bool Vote = false; + }; + + class DFTeleport final : public ClientPacket + { + public: + DFTeleport(WorldPacket&& packet) : ClientPacket(CMSG_DF_TELEPORT, std::move(packet)) { } + + void Read() override; + + bool TeleportOut = false; + }; + + class DFGetSystemInfo final : public ClientPacket + { + public: + DFGetSystemInfo(WorldPacket&& packet) : ClientPacket(CMSG_DF_GET_SYSTEM_INFO, std::move(packet)) { } + + void Read() override; + + uint8 PartyIndex = 0; + bool Player = false; + }; + + class DFGetJoinStatus final : public ClientPacket + { + public: + DFGetJoinStatus(WorldPacket&& packet) : ClientPacket(CMSG_DF_GET_JOIN_STATUS, std::move(packet)) { } + + void Read() override { } + }; + + struct LFGBlackListSlot + { + LFGBlackListSlot() { } + LFGBlackListSlot(uint32 slot, uint32 reason, int32 subReason1, int32 subReason2) + : Slot(slot), Reason(reason), SubReason1(subReason1), SubReason2(subReason2) { } + + uint32 Slot = 0; + uint32 Reason = 0; + int32 SubReason1 = 0; + int32 SubReason2 = 0; + }; + + struct LFGBlackList + { + Optional<ObjectGuid> PlayerGuid; + std::vector<LFGBlackListSlot> Slot; + }; + + struct LfgPlayerQuestRewardItem + { + LfgPlayerQuestRewardItem() { } + LfgPlayerQuestRewardItem(int32 itemId, int32 quantity) : ItemID(itemId), Quantity(quantity) { } + + int32 ItemID = 0; + int32 Quantity = 0; + }; + + struct LfgPlayerQuestRewardCurrency + { + LfgPlayerQuestRewardCurrency() { } + LfgPlayerQuestRewardCurrency(int32 currencyID, int32 quantity) : CurrencyID(currencyID), Quantity(quantity) { } + + int32 CurrencyID = 0; + int32 Quantity = 0; + }; + + struct LfgPlayerQuestReward + { + uint32 Mask = 0; // Roles required for this reward, only used by ShortageReward in SMSG_LFG_PLAYER_INFO + int32 RewardMoney = 0; // Only used by SMSG_LFG_PLAYER_INFO + int32 RewardXP = 0; + std::vector<LfgPlayerQuestRewardItem> Item; + std::vector<LfgPlayerQuestRewardCurrency> Currency; // Only used by SMSG_LFG_PLAYER_INFO + std::vector<LfgPlayerQuestRewardCurrency> BonusCurrency; // Only used by SMSG_LFG_PLAYER_INFO + Optional<int32> RewardSpellID; // Only used by SMSG_LFG_PLAYER_INFO + Optional<int32> Unused1; + Optional<uint64> Unused2; + Optional<int32> Honor; // Only used by SMSG_REQUEST_PVP_REWARDS_RESPONSE + }; + + struct LfgPlayerDungeonInfo + { + uint32 Slot = 0; + int32 CompletionQuantity = 0; + int32 CompletionLimit = 0; + int32 CompletionCurrencyID = 0; + int32 SpecificQuantity = 0; + int32 SpecificLimit = 0; + int32 OverallQuantity = 0; + int32 OverallLimit = 0; + int32 PurseWeeklyQuantity = 0; + int32 PurseWeeklyLimit = 0; + int32 PurseQuantity = 0; + int32 PurseLimit = 0; + int32 Quantity = 0; + uint32 CompletedMask = 0; + uint32 EncounterMask = 0; + bool FirstReward = false; + bool ShortageEligible = false; + LfgPlayerQuestReward Rewards; + std::vector<LfgPlayerQuestReward> ShortageReward; + }; + + class LfgPlayerInfo final : public ServerPacket + { + public: + LfgPlayerInfo() : ServerPacket(SMSG_LFG_PLAYER_INFO) { } + + WorldPacket const* Write() override; + + LFGBlackList BlackList; + std::vector<LfgPlayerDungeonInfo> Dungeon; + }; + + class LfgPartyInfo final : public ServerPacket + { + public: + LfgPartyInfo() : ServerPacket(SMSG_LFG_PARTY_INFO) { } + + WorldPacket const* Write() override; + + std::vector<LFGBlackList> Player; + }; + + class LFGUpdateStatus final : public ServerPacket + { + public: + LFGUpdateStatus() : ServerPacket(SMSG_LFG_UPDATE_STATUS) { } + + WorldPacket const* Write() override; + + RideTicket Ticket; + uint8 SubType = 0; + uint8 Reason = 0; + std::vector<uint32> Slots; + uint32 RequestedRoles = 0; + std::vector<ObjectGuid> SuspendedPlayers; + bool NotifyUI = false; + bool IsParty = false; + bool Joined = false; + bool LfgJoined = false; + bool Queued = false; + bool Unused = false; + }; + + class RoleChosen final : public ServerPacket + { + public: + RoleChosen() : ServerPacket(SMSG_ROLE_CHOSEN, 16 + 4 + 1) { } + + WorldPacket const* Write() override; + + ObjectGuid Player; + uint32 RoleMask = 0; + bool Accepted = false; + }; + + struct LFGRoleCheckUpdateMember + { + LFGRoleCheckUpdateMember() { } + LFGRoleCheckUpdateMember(ObjectGuid guid, uint32 rolesDesired, uint8 level, bool roleCheckComplete) + : Guid(guid), RolesDesired(rolesDesired), Level(level), RoleCheckComplete(roleCheckComplete) { } + + ObjectGuid Guid; + uint32 RolesDesired = 0; + uint8 Level = 0; + bool RoleCheckComplete = false; + }; + + class LFGRoleCheckUpdate final : public ServerPacket + { + public: + LFGRoleCheckUpdate() : ServerPacket(SMSG_LFG_ROLE_CHECK_UPDATE) { } + + WorldPacket const* Write() override; + + uint8 PartyIndex = 0; + uint8 RoleCheckStatus = 0; + std::vector<uint32> JoinSlots; + uint64 BgQueueID = 0; + int32 GroupFinderActivityID = 0; + std::vector<LFGRoleCheckUpdateMember> Members; + bool IsBeginning = false; + bool IsRequeue = false; + }; + + struct LFGJoinBlackListSlot + { + LFGJoinBlackListSlot() { } + LFGJoinBlackListSlot(int32 slot, int32 reason, int32 subReason1, int32 subReason2) + : Slot(slot), Reason(reason), SubReason1(subReason1), SubReason2(subReason2) { } + + int32 Slot = 0; + int32 Reason = 0; + int32 SubReason1 = 0; + int32 SubReason2 = 0; + }; + + struct LFGJoinBlackList + { + ObjectGuid Guid; + std::vector<LFGJoinBlackListSlot> Slots; + }; + + class LFGJoinResult final : public ServerPacket + { + public: + LFGJoinResult() : ServerPacket(SMSG_LFG_JOIN_RESULT) { } + + WorldPacket const* Write() override; + + RideTicket Ticket; + uint8 Result = 0; + uint8 ResultDetail = 0; + std::vector<LFGJoinBlackList> BlackList; + }; + + class LFGQueueStatus final : public ServerPacket + { + public: + LFGQueueStatus() : ServerPacket(SMSG_LFG_QUEUE_STATUS, 16 + 4 + 4 + 4 + 4 + 4 + 4 + 4 * 3 + 3 + 4) { } + + WorldPacket const* Write() override; + + RideTicket Ticket; + uint32 Slot = 0; + uint32 AvgWaitTimeMe = 0; + uint32 AvgWaitTime = 0; + uint32 AvgWaitTimeByRole[3] = {}; + uint8 LastNeeded[3] = {}; + uint32 QueuedTime = 0; + }; + + struct LFGPlayerRewards + { + LFGPlayerRewards() { } + LFGPlayerRewards(int32 rewardItem, uint32 rewardItemQuantity, int32 bonusCurrency, bool isCurrency) + : RewardItem(rewardItem), RewardItemQuantity(rewardItemQuantity), BonusCurrency(bonusCurrency), IsCurrency(isCurrency) { } + + int32 RewardItem = 0; + uint32 RewardItemQuantity = 0; + int32 BonusCurrency = 0; + bool IsCurrency = false; + }; + + class LFGPlayerReward final : public ServerPacket + { + public: + LFGPlayerReward() : ServerPacket(SMSG_LFG_PLAYER_REWARD) { } + + WorldPacket const* Write() override; + + uint32 QueuedSlot = 0; + uint32 ActualSlot = 0; + int32 RewardMoney = 0; + int32 AddedXP = 0; + std::vector<LFGPlayerRewards> Rewards; + }; + + struct LfgBootInfo + { + bool VoteInProgress = false; + bool VotePassed = false; + bool MyVoteCompleted = false; + bool MyVote = false; + ObjectGuid Target; + uint32 TotalVotes = 0; + uint32 BootVotes = 0; + int32 TimeLeft = 0; + uint32 VotesNeeded = 0; + std::string Reason; + }; + + class LfgBootPlayer final : public ServerPacket + { + public: + LfgBootPlayer() : ServerPacket(SMSG_LFG_BOOT_PLAYER) { } + + WorldPacket const* Write() override; + + LfgBootInfo Info; + }; + + struct LFGProposalUpdatePlayer + { + uint32 Roles = 0; + bool Me = false; + bool SameParty = false; + bool MyParty = false; + bool Responded = false; + bool Accepted = false; + }; + + class LFGProposalUpdate final : public ServerPacket + { + public: + LFGProposalUpdate() : ServerPacket(SMSG_LFG_PROPOSAL_UPDATE) { } + + WorldPacket const* Write() override; + + RideTicket Ticket; + uint64 InstanceID = 0; + uint32 ProposalID = 0; + uint32 Slot = 0; + int8 State = 0; + uint32 CompletedMask = 0; + uint8 Unused; + bool ValidCompletedMask = false; + bool ProposalSilent = false; + bool IsRequeue; + std::vector<LFGProposalUpdatePlayer> Players; + }; + + class LFGDisabled final : public ServerPacket + { + public: + LFGDisabled() : ServerPacket(SMSG_LFG_DISABLED, 0) { } + + WorldPacket const* Write() override { return &_worldPacket; } + }; + + class LFGOfferContinue final : public ServerPacket + { + public: + LFGOfferContinue(uint32 slot) : ServerPacket(SMSG_LFG_OFFER_CONTINUE, 4), Slot(slot) { } + + WorldPacket const* Write() override; + + uint32 Slot = 0; + }; + + class LFGTeleportDenied final : public ServerPacket + { + public: + LFGTeleportDenied(lfg::LfgTeleportResult reason) : ServerPacket(SMSG_LFG_TELEPORT_DENIED, 1), Reason(reason) { } + + WorldPacket const* Write() override; + + lfg::LfgTeleportResult Reason; + }; } } diff --git a/src/server/game/Server/Packets/LFGPacketsCommon.cpp b/src/server/game/Server/Packets/LFGPacketsCommon.cpp index 71af239d5aa..74b08383a72 100644 --- a/src/server/game/Server/Packets/LFGPacketsCommon.cpp +++ b/src/server/game/Server/Packets/LFGPacketsCommon.cpp @@ -21,7 +21,7 @@ ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::LFG::RideTicket& ticket) { data >> ticket.RequesterGuid; data >> ticket.Id; - data >> ticket.Type; + ticket.Type = data.read<WorldPackets::LFG::RideType>(); data >> ticket.Time; return data; @@ -30,9 +30,9 @@ ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::LFG::RideTicket& ticket) ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::RideTicket const& ticket) { data << ticket.RequesterGuid; - data << int32(ticket.Id); - data << int32(ticket.Type); - data << uint32(ticket.Time); + data << uint32(ticket.Id); + data << uint32(ticket.Type); + data << int32(ticket.Time); return data; } diff --git a/src/server/game/Server/Packets/LFGPacketsCommon.h b/src/server/game/Server/Packets/LFGPacketsCommon.h index 957ed07f161..b36f0082b6f 100644 --- a/src/server/game/Server/Packets/LFGPacketsCommon.h +++ b/src/server/game/Server/Packets/LFGPacketsCommon.h @@ -25,12 +25,19 @@ namespace WorldPackets { namespace LFG { + enum class RideType : uint32 + { + None = 0, + Battlegrounds = 1, + Lfg = 2 + }; + struct RideTicket { ObjectGuid RequesterGuid; - int32 Id = 0; - int32 Type = 0; - uint32 Time = 0; + uint32 Id = 0; + RideType Type = RideType::None; + int32 Time = 0; }; } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 2d22d52c736..1001dd1aeec 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -352,15 +352,15 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_DEL_IGNORE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelIgnoreOpcode); DEFINE_HANDLER(CMSG_DEPOSIT_REAGENT_BANK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_DESTROY_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDestroyItemOpcode); - DEFINE_HANDLER(CMSG_DF_BOOT_PLAYER_VOTE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetBootVoteOpcode); + DEFINE_HANDLER(CMSG_DF_BOOT_PLAYER_VOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetBootVoteOpcode); DEFINE_HANDLER(CMSG_DF_GET_JOIN_STATUS, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleDFGetJoinStatus); - DEFINE_HANDLER(CMSG_DF_GET_SYSTEM_INFO, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleDFGetSystemInfo); - DEFINE_HANDLER(CMSG_DF_JOIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode); - DEFINE_HANDLER(CMSG_DF_LEAVE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgLeaveOpcode); - DEFINE_HANDLER(CMSG_DF_PROPOSAL_RESPONSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgProposalResultOpcode); - DEFINE_HANDLER(CMSG_DF_READY_CHECK_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_DF_SET_ROLES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetRolesOpcode); - DEFINE_HANDLER(CMSG_DF_TELEPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgTeleportOpcode); + DEFINE_HANDLER(CMSG_DF_GET_SYSTEM_INFO, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleDFGetSystemInfo); + DEFINE_HANDLER(CMSG_DF_JOIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode); + DEFINE_HANDLER(CMSG_DF_LEAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgLeaveOpcode); + DEFINE_HANDLER(CMSG_DF_PROPOSAL_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgProposalResultOpcode); + DEFINE_HANDLER(CMSG_DF_READY_CHECK_RESPONSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_DF_SET_ROLES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetRolesOpcode); + DEFINE_HANDLER(CMSG_DF_TELEPORT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgTeleportOpcode); DEFINE_HANDLER(CMSG_DISCARDED_TIME_SYNC_ACKS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_DISMISS_CRITTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissCritter); DEFINE_HANDLER(CMSG_DO_MASTER_LOOT_ROLL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL); @@ -1313,28 +1313,27 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARN_TALENTS_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEVEL_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEVEL_UP_INFO, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_BOOT_PLAYER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_DISABLED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_BOOT_PLAYER, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_DISABLED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_INSTANCE_SHUTDOWN_COUNTDOWN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_JOIN_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_JOIN_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_JOIN_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_SEARCH_RESULTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_SEARCH_STATUS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_UPDATE_BLACKLIST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_LIST_UPDATE_STATUS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_OFFER_CONTINUE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_PARTY_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_PLAYER_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_PLAYER_REWARD, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_PROPOSAL_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_QUEUE_STATUS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_OFFER_CONTINUE, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_PARTY_INFO, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_PLAYER_INFO, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_PLAYER_REWARD, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_PROPOSAL_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_QUEUE_STATUS, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_READY_CHECK_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_READY_CHECK_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_ROLE_CHECK_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - //DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_SEARCH_RESULTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_ROLE_CHECK_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_SLOT_INVALID, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_TELEPORT_DENIED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_UPDATE_STATUS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_TELEPORT_DENIED, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_UPDATE_STATUS, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICANT_LIST_CHANGED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICATIONS, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LF_GUILD_APPLICATIONS_LIST_CHANGED, STATUS_NEVER, CONNECTION_TYPE_REALM); @@ -1634,7 +1633,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHANGED_INFORM, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHOSEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHOSEN, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_POLL_INFORM, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RUNE_REGEN_DEBUG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_BOOT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 122585e0a74..ae51478180e 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -64,6 +64,7 @@ struct LfgQueueStatusData; struct LfgPlayerRewardData; struct LfgRoleCheck; struct LfgUpdateData; +enum LfgTeleportResult : uint8; } namespace rbac @@ -399,6 +400,18 @@ namespace WorldPackets struct ItemInstance; } + namespace LFG + { + class DFJoin; + class DFLeave; + class DFProposalResponse; + class DFSetRoles; + class DFBootPlayerVote; + class DFTeleport; + class DFGetSystemInfo; + class DFGetJoinStatus; + } + namespace Loot { class LootUnit; @@ -1527,21 +1540,20 @@ class TC_GAME_API WorldSession void HandleInstanceLockResponse(WorldPackets::Instance::InstanceLockResponse& packet); // Looking for Dungeon/Raid - void HandleDFGetSystemInfo(WorldPacket& recvData); void SendLfgPlayerLockInfo(); void SendLfgPartyLockInfo(); - void HandleLfgJoinOpcode(WorldPacket& recvData); - void HandleLfgLeaveOpcode(WorldPacket& recvData); - void HandleLfgSetRolesOpcode(WorldPacket& recvData); - void HandleLfgProposalResultOpcode(WorldPacket& recvData); - void HandleLfgSetBootVoteOpcode(WorldPacket& recvData); - void HandleLfgTeleportOpcode(WorldPacket& recvData); - void HandleDFGetJoinStatus(WorldPacket& recvData); + void HandleLfgJoinOpcode(WorldPackets::LFG::DFJoin& dfJoin); + void HandleLfgLeaveOpcode(WorldPackets::LFG::DFLeave& dfLeave); + void HandleLfgProposalResultOpcode(WorldPackets::LFG::DFProposalResponse& dfProposalResponse); + void HandleLfgSetRolesOpcode(WorldPackets::LFG::DFSetRoles& dfSetRoles); + void HandleLfgSetBootVoteOpcode(WorldPackets::LFG::DFBootPlayerVote& dfBootPlayerVote); + void HandleLfgTeleportOpcode(WorldPackets::LFG::DFTeleport& dfTeleport); + void HandleDFGetSystemInfo(WorldPackets::LFG::DFGetSystemInfo& dfGetSystemInfo); + void HandleDFGetJoinStatus(WorldPackets::LFG::DFGetJoinStatus& dfGetJoinStatus); void SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, bool party); void SendLfgRoleChosen(ObjectGuid guid, uint8 roles); void SendLfgRoleCheckUpdate(lfg::LfgRoleCheck const& pRoleCheck); - void SendLfgLfrList(bool update); void SendLfgJoinResult(lfg::LfgJoinResultData const& joinData); void SendLfgQueueStatus(lfg::LfgQueueStatusData const& queueData); void SendLfgPlayerReward(lfg::LfgPlayerRewardData const& lfgPlayerRewardData); @@ -1549,7 +1561,7 @@ class TC_GAME_API WorldSession void SendLfgUpdateProposal(lfg::LfgProposal const& proposal); void SendLfgDisabled(); void SendLfgOfferContinue(uint32 dungeonEntry); - void SendLfgTeleportError(uint8 err); + void SendLfgTeleportError(lfg::LfgTeleportResult err); void HandleSelfResOpcode(WorldPackets::Spells::SelfRes& packet); void HandleRequestPetInfo(WorldPackets::Pet::RequestPetInfo& packet); |