Skip to content

Commit d77d726

Browse files
committed
BG: Rework BG queue to be asynchronous and resolve race conditions
Thx to insunaa for making it compile on linux
1 parent e8da17c commit d77d726

18 files changed

+2500
-1981
lines changed

src/game/BattleGround/BattleGround.cpp

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,9 @@ BattleGround::~BattleGround()
295295
BattleGroundBracketId bracketId = GetBracketId();
296296
if (bracketId != BG_BRACKET_ID_TEMPLATE)
297297
{
298-
sBattleGroundMgr.GetMessager().AddMessage([typeId = GetTypeId(), bracketId, clientInstanceId = GetClientInstanceId()](BattleGroundMgr* mgr)
298+
sWorld.GetBGQueue().GetMessager().AddMessage([bgTypeId = GetTypeId(), bracketId, clientInstanceId = GetClientInstanceId()](BattleGroundQueue* queue)
299299
{
300-
mgr->DeleteClientVisibleInstanceId(typeId, bracketId, clientInstanceId);
300+
queue->DeleteClientVisibleInstanceId(bgTypeId, bracketId, clientInstanceId);
301301
});
302302
}
303303

@@ -307,7 +307,7 @@ BattleGround::~BattleGround()
307307
m_bgMap->SetUnload();
308308

309309
// remove from bg free slot queue
310-
this->RemoveFromBgFreeSlotQueue();
310+
this->RemovedFromBgFreeSlotQueue(true);
311311

312312
for (BattleGroundScoreMap::const_iterator itr = m_playerScores.begin(); itr != m_playerScores.end(); ++itr)
313313
delete itr->second;
@@ -773,7 +773,7 @@ void BattleGround::UpdateWorldStateForPlayer(uint32 field, uint32 value, Player*
773773
*/
774774
void BattleGround::EndBattleGround(Team winner)
775775
{
776-
this->RemoveFromBgFreeSlotQueue();
776+
this->RemovedFromBgFreeSlotQueue(true);
777777

778778
ArenaTeam* winner_arena_team = nullptr;
779779
ArenaTeam* loser_arena_team = nullptr;
@@ -1006,7 +1006,7 @@ void BattleGround::EndBattleGround(Team winner)
10061006
plr->GetSession()->SendPacket(data);
10071007

10081008
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BgQueueTypeId(GetTypeId(), GetArenaType());
1009-
sBattleGroundMgr.BuildBattleGroundStatusPacket(data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType(), plr->GetBGTeam());
1009+
sBattleGroundMgr.BuildBattleGroundStatusPacket(data, true, GetTypeId(), GetClientInstanceId(), IsRated(), GetMapId(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType(), plr->GetBGTeam(), GetMinLevel(), GetMaxLevel());
10101010
plr->GetSession()->SendPacket(data);
10111011
plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
10121012
}
@@ -1041,6 +1041,16 @@ uint32 BattleGround::GetBonusHonorFromKill(uint32 kills) const
10411041
return (uint32)MaNGOS::Honor::hk_honor_at_level(GetMaxLevel(), kills);
10421042
}
10431043

1044+
void BattleGround::SetStatus(BattleGroundStatus status)
1045+
{
1046+
m_status = status;
1047+
sWorld.GetBGQueue().GetMessager().AddMessage([status, bgTypeId = GetTypeId(), instanceId = GetInstanceId()](BattleGroundQueue* queue)
1048+
{
1049+
if (BattleGroundInQueueInfo* bgInstance = queue->GetFreeSlotInstance(bgTypeId, instanceId))
1050+
bgInstance->status = status;
1051+
});
1052+
}
1053+
10441054
/**
10451055
Function that returns the battleground master entry
10461056
*/
@@ -1338,7 +1348,7 @@ void BattleGround::RemovePlayerAtLeave(ObjectGuid playerGuid, bool isOnTransport
13381348
if (doSendPacket)
13391349
{
13401350
WorldPacket data;
1341-
sBattleGroundMgr.BuildBattleGroundStatusPacket(data, this, player->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0, ARENA_TYPE_NONE, TEAM_NONE);
1351+
sBattleGroundMgr.BuildBattleGroundStatusPacket(data, true, GetTypeId(), GetClientInstanceId(), IsRated(), GetMapId(), player->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0, ARENA_TYPE_NONE, TEAM_NONE, GetMinLevel(), GetMaxLevel());
13421352
player->GetSession()->SendPacket(data);
13431353
}
13441354

@@ -1367,15 +1377,23 @@ void BattleGround::RemovePlayerAtLeave(ObjectGuid playerGuid, bool isOnTransport
13671377
delete group;
13681378
}
13691379
}
1370-
DecreaseInvitedCount(team);
1380+
1381+
SetInvitedCount(team, GetInvitedCount(team) - 1); // change ahead of free slot queue - will be synched again after
13711382
// we should update battleground queue, but only if bg isn't ending
13721383
if (IsBattleGround() && GetStatus() < STATUS_WAIT_LEAVE)
13731384
{
13741385
// a player has left the battleground, so there are free slots -> add to queue
1375-
AddToBgFreeSlotQueue();
1376-
sBattleGroundMgr.GetMessager().AddMessage([bgQueueTypeId, bgTypeId, bracketId = GetBracketId()](BattleGroundMgr* mgr)
1386+
if (!AddToBgFreeSlotQueue()) // avoid setting two messages - if was already in queue, just update count
13771387
{
1378-
mgr->ScheduleQueueUpdate(0, ARENA_TYPE_NONE, bgQueueTypeId, bgTypeId, bracketId);
1388+
sWorld.GetBGQueue().GetMessager().AddMessage([bgTypeId, instanceId = GetInstanceId(), team](BattleGroundQueue* queue)
1389+
{
1390+
if (BattleGroundInQueueInfo* bgInstance = queue->GetFreeSlotInstance(bgTypeId, instanceId))
1391+
bgInstance->DecreaseInvitedCount(team);
1392+
});
1393+
}
1394+
sWorld.GetBGQueue().GetMessager().AddMessage([bgQueueTypeId, bgTypeId, bracketId = GetBracketId()](BattleGroundQueue* queue)
1395+
{
1396+
queue->ScheduleQueueUpdate(0, ARENA_TYPE_NONE, bgQueueTypeId, bgTypeId, bracketId);
13791397
});
13801398
}
13811399

@@ -1472,8 +1490,7 @@ void BattleGround::StartBattleGround()
14721490
{
14731491
SetStartTime(0);
14741492

1475-
// add BG to free slot queue
1476-
AddToBgFreeSlotQueue();
1493+
// expects to be already added in free queue
14771494

14781495
// add bg to update list
14791496
// This must be done here, because we need to have already invited some players when first BG::Update() method is executed
@@ -1698,33 +1715,45 @@ void BattleGround::RemovePlayer(Player* /*player*/, ObjectGuid /*guid*/)
16981715
/**
16991716
Function that returns the number of players that can join a battleground based on the provided team
17001717
*/
1701-
void BattleGround::AddToBgFreeSlotQueue()
1718+
bool BattleGround::AddToBgFreeSlotQueue()
17021719
{
17031720
// make sure to add only once
17041721
if (!m_hasBgFreeSlotQueue && IsBattleGround())
17051722
{
1706-
sBattleGroundMgr.BgFreeSlotQueue[m_typeId].push_front(this);
17071723
m_hasBgFreeSlotQueue = true;
1724+
BattleGroundInQueueInfo bgInfo;
1725+
bgInfo.Fill(this);
1726+
sWorld.GetBGQueue().GetMessager().AddMessage([bgInfo](BattleGroundQueue* queue)
1727+
{
1728+
queue->AddBgToFreeSlots(bgInfo);
1729+
});
1730+
return true;
17081731
}
1732+
return false;
17091733
}
17101734

17111735
/**
17121736
Method that removes this battleground from free queue - it must be called when deleting battleground
17131737
*/
1714-
void BattleGround::RemoveFromBgFreeSlotQueue()
1738+
void BattleGround::RemovedFromBgFreeSlotQueue(bool removeFromQueue)
17151739
{
17161740
// set to be able to re-add if needed
1717-
m_hasBgFreeSlotQueue = false;
1718-
BgFreeSlotQueueType& bgFreeSlot = sBattleGroundMgr.BgFreeSlotQueue[m_typeId];
1719-
1720-
for (BgFreeSlotQueueType::iterator itr = bgFreeSlot.begin(); itr != bgFreeSlot.end(); ++itr)
1741+
if (m_hasBgFreeSlotQueue && removeFromQueue)
17211742
{
1722-
if ((*itr)->GetInstanceId() == GetInstanceId())
1743+
sWorld.GetBGQueue().GetMessager().AddMessage([bgTypeId = GetTypeId(), instanceId = GetInstanceId()](BattleGroundQueue* queue)
17231744
{
1724-
bgFreeSlot.erase(itr);
1725-
return;
1726-
}
1745+
queue->RemoveBgFromFreeSlots(bgTypeId, instanceId);
1746+
});
17271747
}
1748+
m_hasBgFreeSlotQueue = false;
1749+
}
1750+
1751+
void BattleGround::SetInvitedCount(Team team, uint32 count)
1752+
{
1753+
if (team == ALLIANCE)
1754+
m_invitedAlliance = count;
1755+
else
1756+
m_invitedHorde = count;
17281757
}
17291758

17301759
/**
@@ -2167,7 +2196,7 @@ void BattleGround::SendBcdToTeam(int32 bcdEntry, ChatMsg msgtype, Creature const
21672196
*/
21682197
void BattleGround::EndNow()
21692198
{
2170-
RemoveFromBgFreeSlotQueue();
2199+
RemovedFromBgFreeSlotQueue(true);
21712200
SetStatus(STATUS_WAIT_LEAVE);
21722201
SetEndTime(0);
21732202
}
@@ -2282,7 +2311,7 @@ void BattleGround::PlayerAddedToBgCheckIfBgIsRunning(Player* player)
22822311
sBattleGroundMgr.BuildPvpLogDataPacket(data, this);
22832312
player->GetSession()->SendPacket(data);
22842313

2285-
sBattleGroundMgr.BuildBattleGroundStatusPacket(data, this, player->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), player->GetBGTeam());
2314+
sBattleGroundMgr.BuildBattleGroundStatusPacket(data, true, GetTypeId(), GetClientInstanceId(), IsRated(), GetMapId(), player->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), player->GetBGTeam(), GetMinLevel(), GetMaxLevel());
22862315
player->GetSession()->SendPacket(data);
22872316
}
22882317

src/game/BattleGround/BattleGround.h

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -270,27 +270,6 @@ enum BattleGroundStartingEventsIds
270270
};
271271
#define BG_STARTING_EVENT_COUNT 4
272272

273-
enum BattleGroundGroupJoinStatus
274-
{
275-
// positive values are indexes in BattlemasterList.dbc
276-
BG_GROUP_JOIN_STATUS_BATTLEGROUND_FAIL = 0, // Your group has joined a battleground queue, but you are not eligible (showed for non existing BattlemasterList.dbc indexes)
277-
BG_GROUP_JOIN_STATUS_NOT_ELIGIBLE = -1, // not show anything
278-
BG_GROUP_JOIN_STATUS_DESERTERS = -2, // You cannot join the battleground yet because you or one of your party members is flagged as a Deserter.
279-
BG_GROUP_JOIN_STATUS_NOT_IN_TEAM = -3, // Incorrect party size for this arena.
280-
BG_GROUP_JOIN_STATUS_TOO_MANY_QUEUES = -4, // You can only be queued for 2 battles at once
281-
BG_GROUP_JOIN_STATUS_CANNOT_QUEUE_FOR_RATED = -5, // You cannot queue for a rated match while queued for other battles
282-
BG_GROUP_JOIN_STATUS_QUEUED_FOR_RATED = -6, // You cannot queue for another battle while queued for a rated arena match
283-
BG_GROUP_JOIN_STATUS_TEAM_LEFT_QUEUE = -7, // Your team has left the arena queue
284-
BG_GROUP_JOIN_STATUS_NOT_IN_BATTLEGROUND = -8, // You can't do that in a battleground.
285-
BG_GROUP_JOIN_STATUS_XP_GAIN = -9, // wtf, doesn't exist in client...
286-
BG_GROUP_JOIN_STATUS_JOIN_RANGE_INDEX = -10, // Cannot join the queue unless all members of your party are in the same battleground level range.
287-
BG_GROUP_JOIN_STATUS_JOIN_TIMED_OUT = -11, // %s was unavailable to join the queue. (uint64 guid exist in client cache)
288-
BG_GROUP_JOIN_STATUS_JOIN_FAILED = -12, // Join as a group failed (uint64 guid doesn't exist in client cache)
289-
BG_GROUP_JOIN_STATUS_LFG_CANT_USE_BATTLEGROUND = -13, // You cannot queue for a battleground or arena while using the dungeon system.
290-
BG_GROUP_JOIN_STATUS_IN_RANDOM_BG = -14, // Can't do that while in a Random Battleground queue.
291-
BG_GROUP_JOIN_STATUS_IN_NON_RANDOM_BG = -15, // Can't queue for Random Battleground while in another Battleground queue.
292-
};
293-
294273
/*
295274
This class is used to keep the battleground score for each individual player
296275
*/
@@ -383,7 +362,7 @@ class BattleGround
383362
void SetRandomTypeId(BattleGroundTypeId typeId) { m_randomTypeId = typeId; }
384363
// here we can count minlevel and maxlevel for players
385364
void SetBracket(PvPDifficultyEntry const* bracketEntry);
386-
void SetStatus(BattleGroundStatus status) { m_status = status; }
365+
void SetStatus(BattleGroundStatus status);
387366
void SetClientInstanceId(uint32 instanceId) { m_clientInstanceId = instanceId; }
388367
void SetStartTime(uint32 time) { m_startTime = time; }
389368
void SetEndTime(uint32 time) { m_endTime = time; }
@@ -402,12 +381,11 @@ class BattleGround
402381
void SetMaxPlayersPerTeam(uint32 maxPlayers) { m_maxPlayersPerTeam = maxPlayers; }
403382
void SetMinPlayersPerTeam(uint32 minPlayers) { m_minPlayersPerTeam = minPlayers; }
404383

405-
void AddToBgFreeSlotQueue(); // this queue will be useful when more battlegrounds instances will be available
406-
void RemoveFromBgFreeSlotQueue(); // this method could delete whole BG instance, if another free is available
384+
bool AddToBgFreeSlotQueue(); // this queue will be useful when more battlegrounds instances will be available
385+
void RemovedFromBgFreeSlotQueue(bool removeFromQueue); // this method could delete whole BG instance, if another free is available
407386

408387
// Functions to decrease or increase player count
409-
void DecreaseInvitedCount(Team team) { (team == ALLIANCE) ? --m_invitedAlliance : --m_invitedHorde; }
410-
void IncreaseInvitedCount(Team team) { (team == ALLIANCE) ? ++m_invitedAlliance : ++m_invitedHorde; }
388+
void SetInvitedCount(Team team, uint32 count);
411389
uint32 GetInvitedCount(Team team) const
412390
{
413391
if (team == ALLIANCE)

src/game/BattleGround/BattleGroundDefines.h

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,45 @@
1616
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1717
*/
1818

19-
#ifndef MANGOSSERVER_BATTLEGROUND_DEFINES_H
20-
#define MANGOSSERVER_BATTLEGROUND_DEFINES_H
19+
#ifndef _BG_DEFINES_H
20+
#define _BG_DEFINES_H
2121

2222
#include "Common.h"
2323

24+
#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
25+
#define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10
26+
27+
enum BattleGroundQueueGroupTypes
28+
{
29+
BG_QUEUE_PREMADE_ALLIANCE = 0,
30+
BG_QUEUE_PREMADE_HORDE = 1,
31+
BG_QUEUE_NORMAL_ALLIANCE = 2,
32+
BG_QUEUE_NORMAL_HORDE = 3
33+
};
34+
35+
#define BG_QUEUE_GROUP_TYPES_COUNT 4
36+
37+
enum BattleGroundGroupJoinStatus
38+
{
39+
// positive values are indexes in BattlemasterList.dbc
40+
BG_GROUP_JOIN_STATUS_BATTLEGROUND_FAIL = 0, // Your group has joined a battleground queue, but you are not eligible (showed for non existing BattlemasterList.dbc indexes)
41+
BG_GROUP_JOIN_STATUS_NOT_ELIGIBLE = -1, // not show anything
42+
BG_GROUP_JOIN_STATUS_DESERTERS = -2, // You cannot join the battleground yet because you or one of your party members is flagged as a Deserter.
43+
BG_GROUP_JOIN_STATUS_NOT_IN_TEAM = -3, // Incorrect party size for this arena.
44+
BG_GROUP_JOIN_STATUS_TOO_MANY_QUEUES = -4, // You can only be queued for 2 battles at once
45+
BG_GROUP_JOIN_STATUS_CANNOT_QUEUE_FOR_RATED = -5, // You cannot queue for a rated match while queued for other battles
46+
BG_GROUP_JOIN_STATUS_QUEUED_FOR_RATED = -6, // You cannot queue for another battle while queued for a rated arena match
47+
BG_GROUP_JOIN_STATUS_TEAM_LEFT_QUEUE = -7, // Your team has left the arena queue
48+
BG_GROUP_JOIN_STATUS_NOT_IN_BATTLEGROUND = -8, // You can't do that in a battleground.
49+
BG_GROUP_JOIN_STATUS_XP_GAIN = -9, // wtf, doesn't exist in client...
50+
BG_GROUP_JOIN_STATUS_JOIN_RANGE_INDEX = -10, // Cannot join the queue unless all members of your party are in the same battleground level range.
51+
BG_GROUP_JOIN_STATUS_JOIN_TIMED_OUT = -11, // %s was unavailable to join the queue. (uint64 guid exist in client cache)
52+
BG_GROUP_JOIN_STATUS_JOIN_FAILED = -12, // Join as a group failed (uint64 guid doesn't exist in client cache)
53+
BG_GROUP_JOIN_STATUS_LFG_CANT_USE_BATTLEGROUND = -13, // You cannot queue for a battleground or arena while using the dungeon system.
54+
BG_GROUP_JOIN_STATUS_IN_RANDOM_BG = -14, // Can't do that while in a Random Battleground queue.
55+
BG_GROUP_JOIN_STATUS_IN_NON_RANDOM_BG = -15, // Can't queue for Random Battleground while in another Battleground queue.
56+
};
57+
2458
// indexes of BattlemasterList.dbc
2559
enum BattleGroundTypeId
2660
{
@@ -43,13 +77,12 @@ enum BattleGroundTypeId
4377

4478
enum ArenaType
4579
{
46-
ARENA_TYPE_NONE = 0, // used for mark non-arenas or problematic cases
47-
ARENA_TYPE_2v2 = 2,
48-
ARENA_TYPE_3v3 = 3,
49-
ARENA_TYPE_5v5 = 5
80+
ARENA_TYPE_NONE = 0, // used for mark non-arenas or problematic cases
81+
ARENA_TYPE_2v2 = 2,
82+
ARENA_TYPE_3v3 = 3,
83+
ARENA_TYPE_5v5 = 5
5084
};
5185

5286
inline bool IsArenaTypeValid(ArenaType type) { return type == ARENA_TYPE_2v2 || type == ARENA_TYPE_3v3 || type == ARENA_TYPE_5v5; }
5387

54-
#endif // MANGOSSERVER_BATTLEGROUND_DEFINES_H
55-
88+
#endif

0 commit comments

Comments
 (0)