@@ -630,67 +630,68 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGroundBracketId bracketId, uint32
630630 return m_selectionPools[BG_TEAM_ALLIANCE ].GetPlayerCount () >= minPlayers && m_selectionPools[BG_TEAM_HORDE ].GetPlayerCount () >= minPlayers;
631631}
632632
633- /*
634- this method is called when group is inserted, or player / group is removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue
635- it must be called after fully adding the members of a group to ensure group joining
636- should be called from BattleGround::RemovePlayer function in some cases
637- */
638- void BattleGroundQueue::Update (BattleGroundTypeId bgTypeId, BattleGroundBracketId bracketId)
633+ void BattleGroundQueue::RemoveOfflinePlayer ()
639634{
640- // ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_lock);
641-
642- // First, remove players who shouldn't be in queue anymore
643- QueuedPlayersMap::iterator itrOffline = m_queuedPlayers.begin ();
644- while (itrOffline != m_queuedPlayers.end ())
635+ for (auto itr = m_queuedPlayers.begin (); itr != m_queuedPlayers.end ();)
645636 {
646- // remove offline players
647- if (!itrOffline->second .online && WorldTimer::getMSTimeDiffToNow (itrOffline->second .lastOnlineTime ) > OFFLINE_BG_QUEUE_TIME )
637+ bool remove = false ;
638+
639+ if (!itr->second .online && WorldTimer::getMSTimeDiffToNow (itr->second .lastOnlineTime ) > OFFLINE_BG_QUEUE_TIME )
648640 {
649- RemovePlayer (itrOffline->first , true );
650- itrOffline = m_queuedPlayers.begin ();
651- continue ;
641+ remove = true ;
652642 }
653-
654- // remove players who are in queue for bg that has ended
655- GroupQueueInfo* group = itrOffline->second .groupInfo ;
656- if (group->isInvitedToBgInstanceGuid )
643+ else if (GroupQueueInfo* group = itr->second .groupInfo )
657644 {
658- BattleGround* bg;
659- if ((bg = sBattleGroundMgr .GetBattleGround (group->isInvitedToBgInstanceGuid , group->bgTypeId )) && bg->GetStatus () == STATUS_WAIT_LEAVE )
645+ if (group->isInvitedToBgInstanceGuid )
660646 {
661- if (itrOffline-> second . online )
647+ if (BattleGround* bg = sBattleGroundMgr . GetBattleGround (group-> isInvitedToBgInstanceGuid , group-> bgTypeId ) )
662648 {
663- if (Player* player = ObjectAccessor::FindPlayerNotInWorld (itrOffline-> first ) )
649+ if (bg-> GetStatus () == STATUS_WAIT_LEAVE )
664650 {
665- BattleGroundQueueTypeId queueTypeId = BattleGroundMgr::BgQueueTypeId (group->bgTypeId );
666- uint32 queueSlot = player->GetBattleGroundQueueIndex (queueTypeId);
667- if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES )
651+ if (itr->second .online )
668652 {
669- player->RemoveBattleGroundQueueId (queueTypeId);
670-
671- WorldPacket data;
672- sBattleGroundMgr .BuildBattleGroundStatusPacket (&data, bg, queueSlot, STATUS_NONE , 0 , 0 );
673- player->GetSession ()->SendPacket (&data);
653+ if (Player* player = ObjectAccessor::FindPlayerNotInWorld (itr->first ))
654+ {
655+ BattleGroundQueueTypeId queueTypeId = BattleGroundMgr::BgQueueTypeId (group->bgTypeId );
656+ uint32 queueSlot = player->GetBattleGroundQueueIndex (queueTypeId);
657+ if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES )
658+ {
659+ player->RemoveBattleGroundQueueId (queueTypeId);
660+
661+ WorldPacket data;
662+ sBattleGroundMgr .BuildBattleGroundStatusPacket (&data, bg, queueSlot, STATUS_NONE , 0 , 0 );
663+ player->GetSession ()->SendPacket (&data);
664+ }
665+ }
674666 }
667+
668+ remove = true ;
675669 }
676670 }
677-
678- RemovePlayer (itrOffline->first , true );
679- itrOffline = m_queuedPlayers.begin ();
680- continue ;
681671 }
682672 }
683673
684- ++itrOffline;
674+ if (remove)
675+ {
676+ itr = m_queuedPlayers.erase (itr);
677+ }
678+ else
679+ {
680+ ++itr;
681+ }
685682 }
683+ }
686684
687- // if no players in queue - do nothing
688- if (m_queuedGroups[bracketId][BG_QUEUE_PREMADE_ALLIANCE ].empty () &&
689- m_queuedGroups[bracketId][BG_QUEUE_PREMADE_HORDE ].empty () &&
690- m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE ].empty () &&
691- m_queuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE ].empty ())
692- return ;
685+ bool BattleGroundQueue::HasPlayersInQueue (BattleGroundBracketId bracketId)
686+ {
687+ return !(m_queuedGroups[bracketId][BG_QUEUE_PREMADE_ALLIANCE ].empty () &&
688+ m_queuedGroups[bracketId][BG_QUEUE_PREMADE_HORDE ].empty () &&
689+ m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE ].empty () &&
690+ m_queuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE ].empty ());
691+ }
693692
693+ void BattleGroundQueue::CheckFreeSlots (BattleGroundTypeId bgTypeId, BattleGroundBracketId bracketId)
694+ {
694695 if (sWorld .getConfig (CONFIG_BOOL_BATTLEGROUND_RANDOMIZE ))
695696 {
696697 auto seed = std::chrono::system_clock::now ().time_since_epoch ().count ();
@@ -702,145 +703,193 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BattleGroundBracketI
702703 std::default_random_engine (seed));
703704 }
704705
705- // battleground with free slot for player should be always in the beginning of the queue
706- // maybe it would be better to create bgfreeslotqueue for each bracketId
707- BgFreeSlotQueueType::iterator itr, next;
708- for (itr = sBattleGroundMgr .m_bgFreeSlotQueue [bgTypeId].begin (); itr != sBattleGroundMgr .m_bgFreeSlotQueue [bgTypeId].end (); itr = next)
706+ std::vector<BattleGround*> fullBattlegrounds;
707+
708+ for (const auto pBattleGround : sBattleGroundMgr .m_bgFreeSlotQueue [bgTypeId])
709709 {
710- next = itr;
711- ++next;
712- // battleground is running, so if:
713- if ((*itr)->GetTypeID () == bgTypeId && (*itr)->GetBracketId () == bracketId &&
714- (*itr)->GetStatus () > STATUS_WAIT_QUEUE && (*itr)->GetStatus () < STATUS_WAIT_LEAVE )
710+ if (pBattleGround->GetTypeID () != bgTypeId || pBattleGround->GetBracketId () != bracketId)
711+ continue ;
712+
713+ if (pBattleGround->GetStatus () <= STATUS_WAIT_QUEUE || pBattleGround->GetStatus () >= STATUS_WAIT_LEAVE )
714+ continue ;
715+
716+ if (!pBattleGround->HasFreeSlots ())
715717 {
716- BattleGround* bg = *itr; // we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!)
717- // and iterator is invalid
718+ fullBattlegrounds.push_back (pBattleGround);
719+ continue ;
720+ }
718721
719- // clear selection pools
720- m_selectionPools[BG_TEAM_ALLIANCE ].Init ();
721- m_selectionPools[BG_TEAM_HORDE ].Init ();
722+ m_selectionPools[BG_TEAM_ALLIANCE ].Init ();
723+ m_selectionPools[BG_TEAM_HORDE ].Init ();
722724
723- // call a function that does the job for us
724- FillPlayersToBg (bg, bracketId);
725+ FillPlayersToBg (pBattleGround, bracketId);
725726
726- // now everything is set, invite players
727- for (const auto itr : m_selectionPools[BG_TEAM_ALLIANCE ].selectedGroups )
728- InviteGroupToBG (itr, bg, itr->groupTeam );
729- for (const auto itr : m_selectionPools[BG_TEAM_HORDE ].selectedGroups )
730- InviteGroupToBG (itr, bg, itr->groupTeam );
727+ for (const auto & group : m_selectionPools[BG_TEAM_ALLIANCE ].selectedGroups )
728+ InviteGroupToBG (group, pBattleGround, group->groupTeam );
729+ for (const auto & group : m_selectionPools[BG_TEAM_HORDE ].selectedGroups )
730+ InviteGroupToBG (group, pBattleGround, group->groupTeam );
731731
732- if (!bg->HasFreeSlots ())
733- {
734- // remove BG from m_bgFreeSlotQueue
735- bg->RemoveFromBGFreeSlotQueue ();
736- }
732+ if (!pBattleGround->HasFreeSlots ())
733+ {
734+ fullBattlegrounds.push_back (pBattleGround);
737735 }
738736 }
739737
740- // finished iterating through the bgs with free slots, maybe we need to create a new bg
738+ for (const auto & pBattleGround : fullBattlegrounds)
739+ {
740+ sLog .Out (LOG_BASIC , LOG_LVL_MINIMAL , " [BattleGroundQueue::Update] removing full bg from m_bgFreeSlotQueue" );
741+ pBattleGround->RemoveFromBGFreeSlotQueue ();
742+ }
743+ }
744+
745+ bool BattleGroundQueue::CheckCreateNewBg (BattleGroundTypeId bgTypeId, BattleGroundBracketId bracketId)
746+ {
747+ bool createdPremadeBg = false ;
748+ bool createdNormalBg = false ;
741749
742- BattleGround* bgTemplate = sBattleGroundMgr .GetBattleGroundTemplate (bgTypeId);
750+ BattleGround* bgTemplate = sBattleGroundMgr .GetBattleGroundTemplate (bgTypeId);
743751 if (!bgTemplate)
744752 {
745- sLog .Out (LOG_BASIC , LOG_LVL_ERROR , " Battleground: Update: bg template not found for %u" , bgTypeId);
746- return ;
753+ sLog .Out (LOG_BASIC , LOG_LVL_ERROR , " [BattleGroundQueue::CheckCreateNewBg] template not found for %u" , bgTypeId);
754+ return false ;
747755 }
748- // get the min. players per team, properly for larger arenas as well.
756+
757+ // Get the min/max players per team
749758 uint32 minPlayersPerTeam = bgTemplate->GetMinPlayersPerTeam ();
750759 uint32 maxPlayersPerTeam = bgTemplate->GetMaxPlayersPerTeam ();
751760
752- int normalMatchesCreationAttempts = 1 ;
753- // now check if there are in queues enough players to start new game of (normal battleground)
754- if (bgTypeId == BATTLEGROUND_AV && sWorld .getConfig (CONFIG_UINT32_AV_MIN_PLAYERS_IN_QUEUE ) && !sBattleGroundMgr .isTesting ())
761+ if (sBattleGroundMgr .isTesting ())
762+ {
763+ minPlayersPerTeam = 1 ;
764+ }
765+
766+ // Alterac Valley specific handling
767+ if (bgTypeId == BATTLEGROUND_AV &&
768+ sWorld .getConfig (CONFIG_UINT32_AV_MIN_PLAYERS_IN_QUEUE ) &&
769+ !sBattleGroundMgr .isTesting ())
755770 {
756771 int minPlayersInQueue = sWorld .getConfig (CONFIG_UINT32_AV_MIN_PLAYERS_IN_QUEUE );
757772 int playersInQueuePerTeam[BG_TEAMS_COUNT ] = {0 };
758- for (uint32 i = 0 ; i < BG_TEAMS_COUNT ; i++)
773+
774+ for (uint32 i = 0 ; i < BG_TEAMS_COUNT ; ++i)
759775 {
760- GroupsQueueType::const_iterator itr = m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE + i].begin ();
761- for (; itr != m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE + i].end (); ++itr)
776+ for (GroupsQueueType::const_iterator itr = m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE + i].begin ();
777+ itr != m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE + i].end (); ++itr)
778+ {
762779 if (!(*itr)->isInvitedToBgInstanceGuid )
763780 playersInQueuePerTeam[i]++; // Only one player, because premades are not allowed in AV.
781+ }
764782 }
783+
765784 if (playersInQueuePerTeam[BG_TEAM_ALLIANCE ] < minPlayersInQueue ||
766- playersInQueuePerTeam[BG_TEAM_HORDE ] < minPlayersInQueue)
767- normalMatchesCreationAttempts = 0 ;
768- else
785+ playersInQueuePerTeam[BG_TEAM_HORDE ] < minPlayersInQueue)
769786 {
770- // Now randomize
771- auto seed = std::chrono::system_clock::now ().time_since_epoch ().count ();
772- std::shuffle (m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE ].begin (),
773- m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE ].begin () + minPlayersInQueue,
774- std::default_random_engine (seed));
775- std::shuffle (m_queuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE ].begin (),
776- m_queuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE ].begin () + minPlayersInQueue,
777- std::default_random_engine (seed));
778- sLog .Out (LOG_BG , LOG_LVL_DETAIL , " Alterac queue randomized (%u alliance vs %u horde)" ,
779- m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE ].size (),
780- m_queuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE ].size ());
787+ return false ;
781788 }
789+
790+ // TODO:
791+ // missing check for sWorld.getConfig(CONFIG_BOOL_BATTLEGROUND_RANDOMIZE) like at CheckFreeSlots()?
792+ auto seed = std::chrono::system_clock::now ().time_since_epoch ().count ();
793+ std::shuffle (m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE ].begin (),
794+ m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE ].end (),
795+ std::default_random_engine (seed));
796+ std::shuffle (m_queuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE ].begin (),
797+ m_queuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE ].end (),
798+ std::default_random_engine (seed));
799+ sLog .Out (LOG_BG , LOG_LVL_DETAIL , " Alterac queue randomized (%u alliance vs %u horde)" ,
800+ m_queuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE ].size (),
801+ m_queuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE ].size ());
782802 }
783- if (bgTypeId == BATTLEGROUND_AV && sWorld .getConfig (CONFIG_UINT32_AV_INITIAL_MAX_PLAYERS ) && !sBattleGroundMgr .isTesting () && normalMatchesCreationAttempts)
803+
804+ if (bgTypeId == BATTLEGROUND_AV && sWorld .getConfig (CONFIG_UINT32_AV_INITIAL_MAX_PLAYERS ) && !sBattleGroundMgr .isTesting ())
784805 {
785- maxPlayersPerTeam = sWorld .getConfig (CONFIG_UINT32_AV_INITIAL_MAX_PLAYERS );
786- if (maxPlayersPerTeam <= minPlayersPerTeam)
787- maxPlayersPerTeam = minPlayersPerTeam;
788- normalMatchesCreationAttempts = 2 ;
806+ uint32 configuredMax = sWorld .getConfig (CONFIG_UINT32_AV_INITIAL_MAX_PLAYERS );
807+ if (configuredMax > minPlayersPerTeam && configuredMax < maxPlayersPerTeam)
808+ maxPlayersPerTeam = configuredMax;
789809 }
790- if (sBattleGroundMgr .isTesting ())
791- minPlayersPerTeam = 1 ;
792810
811+ uint32 qMinLevel = Player::GetMinLevelForBattleGroundBracketId (bracketId, bgTypeId);
812+ uint32 qMaxLevel = Player::GetMaxLevelForBattleGroundBracketId (bracketId, bgTypeId) - 1 ;
813+
814+ // Check for premade match
793815 m_selectionPools[BG_TEAM_ALLIANCE ].Init ();
794816 m_selectionPools[BG_TEAM_HORDE ].Init ();
795817
796- uint32 qMinLevel = Player::GetMinLevelForBattleGroundBracketId (bracketId, bgTypeId);
797- uint32 qMaxLevel = Player::GetMaxLevelForBattleGroundBracketId (bracketId, bgTypeId);
818+ if (CheckPremadeMatch (bracketId, minPlayersPerTeam, maxPlayersPerTeam))
798819 {
799- // check if there is premade against premade match
800- if (CheckPremadeMatch (bracketId, minPlayersPerTeam, maxPlayersPerTeam) )
820+ BattleGround* newBg = sBattleGroundMgr . CreateNewBattleGround (bgTypeId, bracketId);
821+ if (!newBg )
801822 {
802- // create new battleground
803- BattleGround* bg2 = sBattleGroundMgr .CreateNewBattleGround (bgTypeId, bracketId);
804- if (!bg2)
823+ sLog .Out (LOG_BASIC , LOG_LVL_ERROR , " [BattleGroundQueue::CheckCreateNewBg] failed to create premade battleground: %u" , bgTypeId);
824+ return false ;
825+ }
826+
827+ for (uint32 i = 0 ; i < BG_TEAMS_COUNT ; ++i)
828+ {
829+ for (const auto group : m_selectionPools[BG_TEAM_ALLIANCE + i].selectedGroups )
805830 {
806- sLog .Out (LOG_BASIC , LOG_LVL_ERROR , " BattleGroundQueue::Update - Cannot create battleground: %u" , bgTypeId);
807- return ;
831+ InviteGroupToBG (group, newBg, group->groupTeam );
808832 }
809- // invite those selection pools
810- for (uint32 i = 0 ; i < BG_TEAMS_COUNT ; i++)
811- for (const auto itr : m_selectionPools[BG_TEAM_ALLIANCE + i].selectedGroups )
812- InviteGroupToBG (itr, bg2, itr->groupTeam );
813- // start bg
814- bg2->SetLevelRange (qMinLevel, qMaxLevel - 1 );
815- bg2->StartBattleGround ();
816833 }
834+
835+ newBg->SetLevelRange (qMinLevel, qMaxLevel);
836+ newBg->StartBattleGround ();
837+ createdPremadeBg = true ;
817838 }
818839
819- for (int attempt = 0 ; attempt < normalMatchesCreationAttempts; ++attempt)
840+ // Only try to create normal match if no premade was created
841+ if (!createdPremadeBg)
820842 {
821843 m_selectionPools[BG_TEAM_ALLIANCE ].Init ();
822844 m_selectionPools[BG_TEAM_HORDE ].Init ();
823- // if there are enough players in pools, start new battleground or non rated arena
845+
824846 if (CheckNormalMatch (bracketId, minPlayersPerTeam, maxPlayersPerTeam))
825847 {
826- // we successfully created a pool
827- BattleGround* bg2 = sBattleGroundMgr .CreateNewBattleGround (bgTypeId, bracketId);
828- if (!bg2)
848+ BattleGround* newBg = sBattleGroundMgr .CreateNewBattleGround (bgTypeId, bracketId);
849+ if (!newBg)
829850 {
830- sLog .Out (LOG_BASIC , LOG_LVL_ERROR , " BattleGroundQueue::Update - Cannot create battleground: %u" , bgTypeId);
831- return ;
851+ sLog .Out (LOG_BASIC , LOG_LVL_ERROR , " [ BattleGroundQueue::CheckCreateNewBg] Cannot create battleground: %u" , bgTypeId);
852+ return false ;
832853 }
833854
834- // invite those selection pools
835- for (uint32 i = 0 ; i < BG_TEAMS_COUNT ; i++)
836- for (const auto itr : m_selectionPools[BG_TEAM_ALLIANCE + i].selectedGroups )
837- InviteGroupToBG (itr, bg2, itr->groupTeam );
855+ for (uint32 i = 0 ; i < BG_TEAMS_COUNT ; ++i)
856+ {
857+ for (const auto group : m_selectionPools[BG_TEAM_ALLIANCE + i].selectedGroups )
858+ {
859+ InviteGroupToBG (group, newBg, group->groupTeam );
860+ }
861+ }
838862
839- // start bg
840- bg2-> SetLevelRange (qMinLevel, qMaxLevel - 1 );
841- bg2-> StartBattleGround () ;
863+ newBg-> SetLevelRange (qMinLevel, qMaxLevel);
864+ newBg-> StartBattleGround ( );
865+ createdNormalBg = true ;
842866 }
843867 }
868+
869+ return createdPremadeBg || createdNormalBg;
870+ }
871+
872+ void BattleGroundQueue::Update (BattleGroundTypeId bgTypeId, BattleGroundBracketId bracketId)
873+ {
874+ // ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_lock);
875+
876+ RemoveOfflinePlayer ();
877+
878+ if (!HasPlayersInQueue (bracketId))
879+ return ;
880+
881+ // Check if player can join to an existing battleground
882+ CheckFreeSlots (bgTypeId, bracketId);
883+
884+ // When all running battlegrounds are full or if there are no running bgs,
885+ // check if we can create a new one
886+ if (CheckCreateNewBg (bgTypeId, bracketId))
887+ {
888+ // Fix edge case:
889+ // If there are still players left in the queue for the same bracket,
890+ // check if they can join to the battleground which was just created
891+ CheckFreeSlots (bgTypeId, bracketId);
892+ }
844893}
845894
846895/* ********************************************************/
0 commit comments