TrinityCore
LFGQueue.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "LFGQueue.h"
19#include "Containers.h"
20#include "GameTime.h"
21#include "Group.h"
22#include "LFGMgr.h"
23#include "Log.h"
24#include <sstream>
25
26namespace lfg
27{
28
35std::string ConcatenateGuids(GuidList const& check)
36{
37 if (check.empty())
38 return "";
39
40 // need the guids in order to avoid duplicates
41 GuidSet guids(check.begin(), check.end());
42
43 std::ostringstream o;
44
45 GuidSet::const_iterator it = guids.begin();
46 o << it->ToHexString();
47 for (++it; it != guids.end(); ++it)
48 o << '|' << it->ToHexString();
49
50 return o.str();
51}
52
53char const* GetCompatibleString(LfgCompatibility compatibles)
54{
55 switch (compatibles)
56 {
58 return "Pending";
60 return "Compatibles (Bad States)";
62 return "Match";
64 return "Compatibles (Not enough players)";
66 return "Has ignores";
68 return "Multiple Lfg Groups";
70 return "Incompatible dungeons";
72 return "Incompatible roles";
74 return "Too many players";
76 return "Wrong group size";
77 default:
78 return "Unknown";
79 }
80}
81
84{ }
85
86std::string LFGQueue::GetDetailedMatchRoles(GuidList const& check) const
87{
88 if (check.empty())
89 return "";
90
91 // need the guids in order to avoid duplicates
92 GuidSet guids(check.begin(), check.end());
93
94 std::ostringstream o;
95
96 GuidSet::const_iterator it = guids.begin();
97 o << it->ToString();
98 LfgQueueDataContainer::const_iterator itQueue = QueueDataStore.find(*it);
99 if (itQueue != QueueDataStore.end())
100 {
101 // skip leader flag, log only dps/tank/healer
102 auto role = itQueue->second.roles.find(*it);
103 if (role != itQueue->second.roles.end())
104 o << ' ' << GetRolesString(itQueue->second.roles.at(*it) & uint8(~PLAYER_ROLE_LEADER));
105 }
106
107 for (++it; it != guids.end(); ++it)
108 {
109 o << '|' << it->ToString();
110 itQueue = QueueDataStore.find(*it);
111 if (itQueue != QueueDataStore.end())
112 {
113 // skip leader flag, log only dps/tank/healer
114 auto role = itQueue->second.roles.find(*it);
115 if (role != itQueue->second.roles.end())
116 o << ' ' << GetRolesString(itQueue->second.roles.at(*it) & uint8(~PLAYER_ROLE_LEADER));
117 }
118 }
119
120 return o.str();
121}
122
123void LFGQueue::AddToQueue(ObjectGuid guid, bool reAdd)
124{
125 LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
126 if (itQueue == QueueDataStore.end())
127 {
128 TC_LOG_ERROR("lfg.queue.add", "Queue data not found for [{}]", guid.ToString());
129 return;
130 }
131
132 if (reAdd)
134 else
135 AddToNewQueue(guid);
136}
137
139{
140 RemoveFromNewQueue(guid);
143
144 std::string sguid = guid.ToHexString();
145
146 LfgQueueDataContainer::iterator itDelete = QueueDataStore.end();
147 for (LfgQueueDataContainer::iterator itr = QueueDataStore.begin(); itr != QueueDataStore.end(); ++itr)
148 if (itr->first != guid)
149 {
150 if (std::string::npos != itr->second.bestCompatible.find(sguid))
151 {
152 itr->second.bestCompatible.clear();
154 }
155 }
156 else
157 itDelete = itr;
158
159 if (itDelete != QueueDataStore.end())
160 QueueDataStore.erase(itDelete);
161}
162
164{
165 newToQueueStore.push_back(guid);
166}
167
169{
170 newToQueueStore.remove(guid);
171}
172
174{
175 currentQueueStore.push_back(guid);
176}
177
179{
180 currentQueueStore.push_front(guid);
181}
182
184{
185 currentQueueStore.remove(guid);
186}
187
188void LFGQueue::AddQueueData(ObjectGuid guid, time_t joinTime, LfgDungeonSet const& dungeons, LfgRolesMap const& rolesMap)
189{
190 QueueDataStore[guid] = LfgQueueData(joinTime, dungeons, rolesMap);
191 AddToQueue(guid);
192}
193
195{
196 LfgQueueDataContainer::iterator it = QueueDataStore.find(guid);
197 if (it != QueueDataStore.end())
198 QueueDataStore.erase(it);
199}
200
201void LFGQueue::UpdateWaitTimeAvg(int32 waitTime, uint32 dungeonId)
202{
203 LfgWaitTime &wt = waitTimesAvgStore[dungeonId];
204 uint32 old_number = wt.number++;
205 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
206}
207
209{
210 LfgWaitTime &wt = waitTimesTankStore[dungeonId];
211 uint32 old_number = wt.number++;
212 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
213}
214
216{
217 LfgWaitTime &wt = waitTimesHealerStore[dungeonId];
218 uint32 old_number = wt.number++;
219 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
220}
221
222void LFGQueue::UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId)
223{
224 LfgWaitTime &wt = waitTimesDpsStore[dungeonId];
225 uint32 old_number = wt.number++;
226 wt.time = int32((wt.time * old_number + waitTime) / wt.number);
227}
228
235{
236 std::string strGuid = guid.ToHexString();
237
238 TC_LOG_DEBUG("lfg.queue.data.compatibles.remove", "Removing {}", guid.ToString());
239 for (LfgCompatibleContainer::iterator itNext = CompatibleMapStore.begin(); itNext != CompatibleMapStore.end();)
240 {
241 LfgCompatibleContainer::iterator it = itNext++;
242 if (std::string::npos != it->first.find(strGuid))
243 CompatibleMapStore.erase(it);
244 }
245}
246
253void LFGQueue::SetCompatibles(std::string const& key, LfgCompatibility compatibles)
254{
256 data.compatibility = compatibles;
257}
258
259void LFGQueue::SetCompatibilityData(std::string const& key, LfgCompatibilityData const& data)
260{
261 CompatibleMapStore[key] = data;
262}
263
271{
272 LfgCompatibleContainer::iterator itr = CompatibleMapStore.find(key);
273 if (itr != CompatibleMapStore.end())
274 return itr->second.compatibility;
275
277}
278
280{
281 LfgCompatibleContainer::iterator itr = CompatibleMapStore.find(key);
282 if (itr != CompatibleMapStore.end())
283 return &(itr->second);
284
285 return nullptr;
286}
287
289{
290 uint8 proposals = 0;
291 GuidList firstNew;
292 while (!newToQueueStore.empty())
293 {
294 ObjectGuid frontguid = newToQueueStore.front();
295 TC_LOG_DEBUG("lfg.queue.match.check.new", "Checking [{}] newToQueue({}), currentQueue({})", frontguid.ToString(),
297
298 firstNew.clear();
299 firstNew.push_back(frontguid);
300 RemoveFromNewQueue(frontguid);
301
302 GuidList temporalList = currentQueueStore;
303 LfgCompatibility compatibles = FindNewGroups(firstNew, temporalList);
304
305 if (compatibles == LFG_COMPATIBLES_MATCH)
306 ++proposals;
307 else
308 AddToCurrentQueue(frontguid); // Lfg group not found, add this group to the queue.
309 }
310 return proposals;
311}
312
321{
322 std::string strGuids = ConcatenateGuids(check);
323 LfgCompatibility compatibles = GetCompatibles(strGuids);
324
325 TC_LOG_DEBUG("lfg.queue.match.check", "Guids: ({}): {} - all({})", GetDetailedMatchRoles(check), GetCompatibleString(compatibles), GetDetailedMatchRoles(all));
326 if (compatibles == LFG_COMPATIBILITY_PENDING) // Not previously cached, calculate
327 compatibles = CheckCompatibility(check);
328
329 if (compatibles == LFG_COMPATIBLES_BAD_STATES && sLFGMgr->AllQueued(check))
330 {
331 TC_LOG_DEBUG("lfg.queue.match.check", "Guids: ({}) compatibles (cached) changed from bad states to match", GetDetailedMatchRoles(check));
334 }
335
336 if (compatibles != LFG_COMPATIBLES_WITH_LESS_PLAYERS)
337 return compatibles;
338
339 // Try to match with queued groups
340 while (!all.empty())
341 {
342 check.push_back(all.front());
343 all.pop_front();
344 LfgCompatibility subcompatibility = FindNewGroups(check, all);
345 if (subcompatibility == LFG_COMPATIBLES_MATCH)
347 check.pop_back();
348 }
349 return compatibles;
350}
351
359{
360 std::string strGuids = ConcatenateGuids(check);
361 LfgProposal proposal;
362 LfgDungeonSet proposalDungeons;
363 LfgGroupsMap proposalGroups;
364 LfgRolesMap proposalRoles;
365
366 // Check for correct size
367 if (check.size() > MAX_GROUP_SIZE || check.empty())
368 {
369 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}): Size wrong - Not compatibles", GetDetailedMatchRoles(check));
371 }
372
373 // Check all-but-new compatiblitity
374 if (check.size() > 2)
375 {
376 ObjectGuid frontGuid = check.front();
377 check.pop_front();
378
379 // Check all-but-new compatibilities (New, A, B, C, D) --> check(A, B, C, D)
380 LfgCompatibility child_compatibles = CheckCompatibility(check);
381 if (child_compatibles < LFG_COMPATIBLES_WITH_LESS_PLAYERS) // Group not compatible
382 {
383 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) child {} not compatibles", strGuids, GetDetailedMatchRoles(check));
384 SetCompatibles(strGuids, child_compatibles);
385 return child_compatibles;
386 }
387 check.push_front(frontGuid);
388 }
389
390 // Check if more than one LFG group and number of players joining
391 uint8 numPlayers = 0;
392 uint8 numLfgGroups = 0;
393 for (GuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAX_GROUP_SIZE; ++it)
394 {
395 ObjectGuid guid = *it;
396 LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
397 if (itQueue == QueueDataStore.end())
398 {
399 TC_LOG_ERROR("lfg.queue.match.compatibility.check", "Guid: [{}] is not queued but listed as queued!", guid.ToString());
400 RemoveFromQueue(guid);
402 }
403
404 // Store group so we don't need to call Mgr to get it later (if it's player group will be 0 otherwise would have joined as group)
405 for (LfgRolesMap::const_iterator it2 = itQueue->second.roles.begin(); it2 != itQueue->second.roles.end(); ++it2)
406 proposalGroups[it2->first] = itQueue->first.IsParty() ? itQueue->first : ObjectGuid::Empty;
407
408 numPlayers += itQueue->second.roles.size();
409
410 if (sLFGMgr->IsLfgGroup(guid))
411 {
412 if (!numLfgGroups)
413 proposal.group = guid;
414 ++numLfgGroups;
415 }
416 }
417
418 // Group with less that MAX_GROUP_SIZE members always compatible
419 if (check.size() == 1 && numPlayers != MAX_GROUP_SIZE)
420 {
421 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) single group. Compatibles", GetDetailedMatchRoles(check));
422 LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(check.front());
423
425 data.roles = itQueue->second.roles;
427
428 UpdateBestCompatibleInQueue(itQueue, strGuids, data.roles);
429 SetCompatibilityData(strGuids, data);
431 }
432
433 if (numLfgGroups > 1)
434 {
435 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) More than one Lfggroup ({})", GetDetailedMatchRoles(check), numLfgGroups);
438 }
439
440 if (numPlayers > MAX_GROUP_SIZE)
441 {
442 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) Too many players ({})", GetDetailedMatchRoles(check), numPlayers);
445 }
446
447 // If it's single group no need to check for duplicate players, ignores, bad roles or bad dungeons as it's been checked before joining
448 if (check.size() > 1)
449 {
450 for (GuidList::const_iterator it = check.begin(); it != check.end(); ++it)
451 {
452 LfgRolesMap const& roles = QueueDataStore[(*it)].roles;
453 for (LfgRolesMap::const_iterator itRoles = roles.begin(); itRoles != roles.end(); ++itRoles)
454 {
455 LfgRolesMap::const_iterator itPlayer;
456 for (itPlayer = proposalRoles.begin(); itPlayer != proposalRoles.end(); ++itPlayer)
457 {
458 if (itRoles->first == itPlayer->first)
459 TC_LOG_ERROR("lfg.queue.match.compatibility.check", "Guids: ERROR! Player multiple times in queue! [{}]", itRoles->first.ToString());
460 else if (sLFGMgr->HasIgnore(itRoles->first, itPlayer->first))
461 break;
462 }
463 if (itPlayer == proposalRoles.end())
464 proposalRoles[itRoles->first] = itRoles->second;
465 }
466 }
467
468 if (uint8 playersize = numPlayers - proposalRoles.size())
469 {
470 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) not compatible, {} players are ignoring each other", GetDetailedMatchRoles(check), playersize);
473 }
474
475 LfgRolesMap debugRoles = proposalRoles;
476 if (!LFGMgr::CheckGroupRoles(proposalRoles))
477 {
478 std::ostringstream o;
479 for (LfgRolesMap::const_iterator it = debugRoles.begin(); it != debugRoles.end(); ++it)
480 o << ", " << it->first.ToHexString() << ": " << GetRolesString(it->second);
481
482 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) Roles not compatible{}", GetDetailedMatchRoles(check), o.str());
485 }
486
487 GuidList::iterator itguid = check.begin();
488 proposalDungeons = QueueDataStore[*itguid].dungeons;
489 std::ostringstream o;
490 o << ", " << itguid->ToHexString() << ": (" << ConcatenateDungeons(proposalDungeons) << ")";
491 for (++itguid; itguid != check.end(); ++itguid)
492 {
493 LfgDungeonSet temporal;
494 LfgDungeonSet& dungeons = QueueDataStore[*itguid].dungeons;
495 o << ", " << itguid->ToHexString() << ": (" << ConcatenateDungeons(dungeons) << ")";
496 std::set_intersection(proposalDungeons.begin(), proposalDungeons.end(), dungeons.begin(), dungeons.end(), std::inserter(temporal, temporal.begin()));
497 proposalDungeons = temporal;
498 }
499
500 if (proposalDungeons.empty())
501 {
502 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) No compatible dungeons{}", GetDetailedMatchRoles(check), o.str());
505 }
506 }
507 else
508 {
509 ObjectGuid gguid = *check.begin();
510 LfgQueueData const& queue = QueueDataStore[gguid];
511 proposalDungeons = queue.dungeons;
512 proposalRoles = queue.roles;
513 LFGMgr::CheckGroupRoles(proposalRoles); // assing new roles
514 }
515
516 // Enough players?
517 if (numPlayers != MAX_GROUP_SIZE)
518 {
519 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) Compatibles but not enough players({})", GetDetailedMatchRoles(check), numPlayers);
521 data.roles = proposalRoles;
522
523 for (GuidList::const_iterator itr = check.begin(); itr != check.end(); ++itr)
524 UpdateBestCompatibleInQueue(QueueDataStore.find(*itr), strGuids, data.roles);
525
526 SetCompatibilityData(strGuids, data);
528 }
529
530 ObjectGuid gguid = *check.begin();
531 proposal.queues = check;
532 proposal.isNew = numLfgGroups != 1 || sLFGMgr->GetOldState(gguid) != LFG_STATE_DUNGEON;
533
534 if (!sLFGMgr->AllQueued(check))
535 {
536 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) Group MATCH but can't create proposal!", GetDetailedMatchRoles(check));
539 }
540
541 // Create a new proposal
544 proposal.leader.Clear();
546
547 bool leader = false;
548 for (LfgRolesMap::const_iterator itRoles = proposalRoles.begin(); itRoles != proposalRoles.end(); ++itRoles)
549 {
550 // Assing new leader
551 if (itRoles->second & PLAYER_ROLE_LEADER)
552 {
553 if (!leader || !proposal.leader || urand(0, 1))
554 proposal.leader = itRoles->first;
555 leader = true;
556 }
557 else if (!leader && (!proposal.leader || urand(0, 1)))
558 proposal.leader = itRoles->first;
559
560 // Assing player data and roles
561 LfgProposalPlayer &data = proposal.players[itRoles->first];
562 data.role = itRoles->second;
563 data.group = proposalGroups.find(itRoles->first)->second;
564 if (!proposal.isNew && !data.group.IsEmpty() && data.group == proposal.group) // Player from existing group, autoaccept
566 }
567
568 // Mark proposal members as not queued (but not remove queue data)
569 for (GuidList::const_iterator itQueue = proposal.queues.begin(); itQueue != proposal.queues.end(); ++itQueue)
570 {
571 ObjectGuid guid = (*itQueue);
572 RemoveFromNewQueue(guid);
574 }
575
576 sLFGMgr->AddProposal(proposal);
577
578 TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: ({}) MATCH! Group formed", GetDetailedMatchRoles(check));
581}
582
583void LFGQueue::UpdateQueueTimers(uint8 queueId, time_t currTime)
584{
585 TC_LOG_TRACE("lfg.queue.timers.update", "Updating queue timers...");
586 for (LfgQueueDataContainer::iterator itQueue = QueueDataStore.begin(); itQueue != QueueDataStore.end(); ++itQueue)
587 {
588 LfgQueueData& queueinfo = itQueue->second;
589 uint32 dungeonId = (*queueinfo.dungeons.begin());
590 uint32 queuedTime = uint32(currTime - queueinfo.joinTime);
591 uint8 role = PLAYER_ROLE_NONE;
592 int32 waitTime = -1;
593 int32 wtTank = waitTimesTankStore[dungeonId].time;
594 int32 wtHealer = waitTimesHealerStore[dungeonId].time;
595 int32 wtDps = waitTimesDpsStore[dungeonId].time;
596 int32 wtAvg = waitTimesAvgStore[dungeonId].time;
597
598 for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer)
599 role |= itPlayer->second;
600 role &= ~PLAYER_ROLE_LEADER;
601
602 switch (role)
603 {
604 case PLAYER_ROLE_NONE: // Should not happen - just in case
605 waitTime = -1;
606 break;
607 case PLAYER_ROLE_TANK:
608 waitTime = wtTank;
609 break;
611 waitTime = wtHealer;
612 break;
614 waitTime = wtDps;
615 break;
616 default:
617 waitTime = wtAvg;
618 break;
619 }
620
621 if (queueinfo.bestCompatible.empty())
623
624 LfgQueueStatusData queueData(queueId, dungeonId, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps);
625 for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer)
626 {
627 ObjectGuid pguid = itPlayer->first;
628 LFGMgr::SendLfgQueueStatus(pguid, queueData);
629 }
630 }
631}
632
634{
635 LfgQueueDataContainer::const_iterator itr = QueueDataStore.find(guid);
636 if (itr != QueueDataStore.end())
637 return itr->second.joinTime;
638
639 return 0;
640}
641
642std::string LFGQueue::DumpQueueInfo() const
643{
644 uint32 players = 0;
645 uint32 groups = 0;
646 uint32 playersInGroup = 0;
647
648 for (uint8 i = 0; i < 2; ++i)
649 {
650 GuidList const& queue = i ? newToQueueStore : currentQueueStore;
651 for (GuidList::const_iterator it = queue.begin(); it != queue.end(); ++it)
652 {
653 ObjectGuid guid = *it;
654 if (guid.IsParty())
655 {
656 groups++;
657 playersInGroup += sLFGMgr->GetPlayerCount(guid);
658 }
659 else
660 players++;
661 }
662 }
663 std::ostringstream o;
664 o << "Queued Players: " << players << " (in group: " << playersInGroup << ") Groups: " << groups << "\n";
665 return o.str();
666}
667
668std::string LFGQueue::DumpCompatibleInfo(bool full /* = false */) const
669{
670 std::ostringstream o;
671 o << "Compatible Map size: " << CompatibleMapStore.size() << "\n";
672 if (full)
673 for (LfgCompatibleContainer::const_iterator itr = CompatibleMapStore.begin(); itr != CompatibleMapStore.end(); ++itr)
674 {
675 o << "(" << itr->first << "): " << GetCompatibleString(itr->second.compatibility);
676 if (!itr->second.roles.empty())
677 {
678 o << " (";
679 bool first = true;
680 for (auto const& role : itr->second.roles)
681 {
682 if (!first)
683 o << "|";
684 o << role.first.ToString() << " " << GetRolesString(role.second & uint8(~PLAYER_ROLE_LEADER));
685 first = false;
686 }
687 o << ")";
688 }
689 o << "\n";
690 }
691
692 return o.str();
693}
694
695void LFGQueue::FindBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue)
696{
697 TC_LOG_DEBUG("lfg.queue.compatibles.find", "{}", itrQueue->first.ToString());
698 std::string sguid = itrQueue->first.ToHexString();
699
700 for (LfgCompatibleContainer::const_iterator itr = CompatibleMapStore.begin(); itr != CompatibleMapStore.end(); ++itr)
701 if (itr->second.compatibility == LFG_COMPATIBLES_WITH_LESS_PLAYERS &&
702 std::string::npos != itr->first.find(sguid))
703 {
704 UpdateBestCompatibleInQueue(itrQueue, itr->first, itr->second.roles);
705 }
706}
707
708void LFGQueue::UpdateBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue, std::string const& key, LfgRolesMap const& roles)
709{
710 LfgQueueData& queueData = itrQueue->second;
711
712 uint8 storedSize = queueData.bestCompatible.empty() ? 0 :
713 std::count(queueData.bestCompatible.begin(), queueData.bestCompatible.end(), '|') + 1;
714
715 uint8 size = std::count(key.begin(), key.end(), '|') + 1;
716
717 if (size <= storedSize)
718 return;
719
720 TC_LOG_DEBUG("lfg.queue.compatibles.update", "Changed ({}) to ({}) as best compatible group for {}",
721 queueData.bestCompatible, key, itrQueue->first.ToString());
722
723 queueData.bestCompatible = key;
724 queueData.tanks = LFG_TANKS_NEEDED;
725 queueData.healers = LFG_HEALERS_NEEDED;
726 queueData.dps = LFG_DPS_NEEDED;
727 for (LfgRolesMap::const_iterator it = roles.begin(); it != roles.end(); ++it)
728 {
729 uint8 role = it->second;
730 if (role & PLAYER_ROLE_TANK)
731 --queueData.tanks;
732 else if (role & PLAYER_ROLE_HEALER)
733 --queueData.healers;
734 else
735 --queueData.dps;
736 }
737}
738
739} // namespace lfg
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
#define MAX_GROUP_SIZE
Definition: Group.h:50
#define sLFGMgr
Definition: LFGMgr.h:507
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_TRACE(filterType__,...)
Definition: Log.h:153
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
std::list< ObjectGuid > GuidList
Definition: ObjectGuid.h:394
std::set< ObjectGuid > GuidSet
Definition: ObjectGuid.h:393
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:319
std::string ToHexString() const
Definition: ObjectGuid.cpp:559
std::string ToString() const
Definition: ObjectGuid.cpp:554
bool IsParty() const
Definition: ObjectGuid.h:335
void Clear()
Definition: ObjectGuid.h:286
static bool CheckGroupRoles(LfgRolesMap &groles)
Checks if given roles match, modifies given roles map with new roles.
Definition: LFGMgr.cpp:880
static void SendLfgQueueStatus(ObjectGuid guid, LfgQueueStatusData const &data)
Sends queue status to player.
Definition: LFGMgr.cpp:2037
void AddQueueData(ObjectGuid guid, time_t joinTime, LfgDungeonSet const &dungeons, LfgRolesMap const &rolesMap)
Definition: LFGQueue.cpp:188
LfgCompatibility GetCompatibles(std::string const &key)
Definition: LFGQueue.cpp:270
LfgQueueDataContainer QueueDataStore
Queued groups.
Definition: LFGQueue.h:135
time_t GetJoinTime(ObjectGuid guid) const
Definition: LFGQueue.cpp:633
LfgCompatibilityData * GetCompatibilityData(std::string const &key)
Definition: LFGQueue.cpp:279
void UpdateBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue, std::string const &key, LfgRolesMap const &roles)
Definition: LFGQueue.cpp:708
LfgCompatibility FindNewGroups(GuidList &check, GuidList &all)
Definition: LFGQueue.cpp:320
void RemoveQueueData(ObjectGuid guid)
Definition: LFGQueue.cpp:194
void UpdateQueueTimers(uint8 queueId, time_t currTime)
Definition: LFGQueue.cpp:583
LfgCompatibleContainer CompatibleMapStore
Compatible dungeons.
Definition: LFGQueue.h:136
void AddToQueue(ObjectGuid guid, bool reAdd=false)
Definition: LFGQueue.cpp:123
LfgWaitTimesContainer waitTimesTankStore
Average wait time to find a group queuing as tank.
Definition: LFGQueue.h:139
void UpdateWaitTimeAvg(int32 waitTime, uint32 dungeonId)
Definition: LFGQueue.cpp:201
LfgWaitTimesContainer waitTimesAvgStore
Average wait time to find a group queuing as multiple roles.
Definition: LFGQueue.h:138
void RemoveFromQueue(ObjectGuid guid)
Definition: LFGQueue.cpp:138
GuidList currentQueueStore
Ordered list. Used to find groups.
Definition: LFGQueue.h:142
void RemoveFromNewQueue(ObjectGuid guid)
Definition: LFGQueue.cpp:168
void FindBestCompatibleInQueue(LfgQueueDataContainer::iterator itrQueue)
Definition: LFGQueue.cpp:695
std::string DumpCompatibleInfo(bool full=false) const
Definition: LFGQueue.cpp:668
LfgCompatibility CheckCompatibility(GuidList check)
Definition: LFGQueue.cpp:358
void SetCompatibles(std::string const &key, LfgCompatibility compatibles)
Definition: LFGQueue.cpp:253
void AddToCurrentQueue(ObjectGuid guid)
Definition: LFGQueue.cpp:173
void RemoveFromCompatibles(ObjectGuid guid)
Definition: LFGQueue.cpp:234
uint8 FindGroups()
Definition: LFGQueue.cpp:288
std::string DumpQueueInfo() const
Definition: LFGQueue.cpp:642
void RemoveFromCurrentQueue(ObjectGuid guid)
Definition: LFGQueue.cpp:183
void AddToNewQueue(ObjectGuid guid)
Definition: LFGQueue.cpp:163
void UpdateWaitTimeHealer(int32 waitTime, uint32 dungeonId)
Definition: LFGQueue.cpp:215
GuidList newToQueueStore
New groups to add to queue.
Definition: LFGQueue.h:143
void SetCompatibilityData(std::string const &key, LfgCompatibilityData const &compatibles)
Definition: LFGQueue.cpp:259
LfgWaitTimesContainer waitTimesDpsStore
Average wait time to find a group queuing as dps.
Definition: LFGQueue.h:141
void UpdateWaitTimeTank(int32 waitTime, uint32 dungeonId)
Definition: LFGQueue.cpp:208
LfgWaitTimesContainer waitTimesHealerStore
Average wait time to find a group queuing as healer.
Definition: LFGQueue.h:140
std::string GetDetailedMatchRoles(GuidList const &check) const
Definition: LFGQueue.cpp:86
void UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId)
Definition: LFGQueue.cpp:222
void AddToFrontCurrentQueue(ObjectGuid guid)
Definition: LFGQueue.cpp:178
time_t GetGameTime()
Definition: GameTime.cpp:44
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition: Containers.h:109
constexpr std::size_t size()
Definition: UpdateField.h:796
Definition: LFG.cpp:24
@ LFG_HEALERS_NEEDED
Definition: LFG.h:33
@ LFG_TANKS_NEEDED
Definition: LFG.h:32
@ LFG_DPS_NEEDED
Definition: LFG.h:34
char const * GetCompatibleString(LfgCompatibility compatibles)
Definition: LFGQueue.cpp:53
std::map< ObjectGuid, uint8 > LfgRolesMap
Definition: LFG.h:135
@ LFG_TIME_PROPOSAL
Definition: LFGMgr.h:57
@ LFG_ANSWER_AGREE
Definition: LFG.h:119
LfgCompatibility
Definition: LFGQueue.h:28
@ LFG_COMPATIBLES_WITH_LESS_PLAYERS
Definition: LFGQueue.h:36
@ LFG_INCOMPATIBLES_HAS_IGNORES
Definition: LFGQueue.h:33
@ LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS
Definition: LFGQueue.h:32
@ LFG_INCOMPATIBLES_NO_DUNGEONS
Definition: LFGQueue.h:35
@ LFG_COMPATIBILITY_PENDING
Definition: LFGQueue.h:29
@ LFG_COMPATIBLES_MATCH
Definition: LFGQueue.h:38
@ LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS
Definition: LFGQueue.h:31
@ LFG_INCOMPATIBLES_WRONG_GROUP_SIZE
Definition: LFGQueue.h:30
@ LFG_INCOMPATIBLES_NO_ROLES
Definition: LFGQueue.h:34
@ LFG_COMPATIBLES_BAD_STATES
Definition: LFGQueue.h:37
std::string ConcatenateGuids(GuidList const &check)
Definition: LFGQueue.cpp:35
std::string GetRolesString(uint8 roles)
Definition: LFG.cpp:41
std::set< uint32 > LfgDungeonSet
Definition: LFG.h:132
std::map< ObjectGuid, ObjectGuid > LfgGroupsMap
Definition: LFG.h:136
std::string ConcatenateDungeons(LfgDungeonSet const &dungeons)
Definition: LFG.cpp:26
@ PLAYER_ROLE_DAMAGE
Definition: LFG.h:43
@ PLAYER_ROLE_TANK
Definition: LFG.h:41
@ PLAYER_ROLE_NONE
Definition: LFG.h:39
@ PLAYER_ROLE_LEADER
Definition: LFG.h:40
@ PLAYER_ROLE_HEALER
Definition: LFG.h:42
@ LFG_STATE_DUNGEON
Definition: LFG.h:80
@ LFG_PROPOSAL_INITIATING
Definition: LFGMgr.h:88
LfgCompatibility compatibility
Definition: LFGQueue.h:48
Stores player data related to proposal to join.
Definition: LFGMgr.h:245
ObjectGuid group
Accept status (-1 not answer | 0 Not agree | 1 agree)
Definition: LFGMgr.h:249
LfgAnswer accept
Proposed role.
Definition: LFGMgr.h:248
Stores group data related to proposal to join.
Definition: LFGMgr.h:254
ObjectGuid leader
Proposal group (0 if new)
Definition: LFGMgr.h:263
uint32 dungeonId
Proposal Id.
Definition: LFGMgr.h:260
GuidList queues
Determines if it's new group or not.
Definition: LFGMgr.h:267
LfgProposalPlayerContainer players
Show order in update window.
Definition: LFGMgr.h:269
bool isNew
Dungeon Encounters.
Definition: LFGMgr.h:266
LfgProposalState state
Dungeon to join.
Definition: LFGMgr.h:261
ObjectGuid group
State of the proposal.
Definition: LFGMgr.h:262
time_t cancelTime
Leader guid.
Definition: LFGMgr.h:264
Stores player or group queue info.
Definition: LFGQueue.h:54
LfgRolesMap roles
Selected Player Role/s.
Definition: LFGQueue.h:67
time_t joinTime
Player queue join time (to calculate wait times)
Definition: LFGQueue.h:62
std::string bestCompatible
Best compatible combination of people queued.
Definition: LFGQueue.h:68
uint8 tanks
Tanks needed.
Definition: LFGQueue.h:63
LfgDungeonSet dungeons
Selected Player/Group Dungeon/s.
Definition: LFGQueue.h:66
uint8 healers
Healers needed.
Definition: LFGQueue.h:64
uint8 dps
Dps needed.
Definition: LFGQueue.h:65
int32 time
Wait time.
Definition: LFGQueue.h:74
uint32 number
Number of people used to get that wait time.
Definition: LFGQueue.h:75