From 927cc32a761405cf44b60b3b2a8621818f1574be Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Thu, 12 Nov 2009 16:00:23 +0100 Subject: [PATCH] [8809] Revert "[8799] Implemented thread safe bg queue updates." This reverts commit 72f7a7ee56c63672faa7786b1d162a7a3b9ab406. This is temporary revert due to bug in ACE_Thread_Mutex. Original code itself in commit has no problem. Conflicts: src/shared/revision_nr.h --- src/game/BattleGround.cpp | 2 +- src/game/BattleGroundHandler.cpp | 281 +++++++++++++++++++++++---------------- src/game/BattleGroundMgr.cpp | 80 ++++------- src/game/BattleGroundMgr.h | 20 +-- src/shared/revision_nr.h | 2 +- 5 files changed, 202 insertions(+), 183 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index fa41ad7ea..9517b206a 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -1084,7 +1084,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac { // a player has left the battleground, so there are free slots -> add to queue AddToBGFreeSlotQueue(); - sBattleGroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, GetQueueId()); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId()); } // Let others know diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 30d98ee3e..903a5de89 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -148,9 +148,8 @@ void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) // if we're here, then the conditions to join a bg are met. We can proceed in joining. // _player->GetGroup() was already checked, grp is already initialized - BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; - GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, bgTypeId, 0, false, isPremade, 0); - uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel()); + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0); + uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel()); if (joinAsGroup /* && _player->GetGroup()*/) { sLog.outDebug("Battleground: the following players are joining as group:"); @@ -167,7 +166,7 @@ void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); - bgQueue.AddPlayer(member, ginfo); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } sLog.outDebug("Battleground: group end"); @@ -182,11 +181,12 @@ void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); SendPacket(&data); - bgQueue.AddPlayer(_player, ginfo); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } - sBattleGroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); - //we should announce queue status here, if we want + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); + if (!ginfo->IsInvitedToBGInstanceGUID) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket & /*recv_data*/ ) @@ -303,6 +303,7 @@ void WorldSession::HandleBattleFieldPortOpcode( WorldPacket &recv_data ) uint8 type; // arenatype if arena uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 + uint32 instanceId; uint32 bgTypeId_; // type id from dbc uint16 unk; // 0x1F90 constant? uint8 action; // enter battle 0x1, leave queue 0x0 @@ -311,130 +312,182 @@ void WorldSession::HandleBattleFieldPortOpcode( WorldPacket &recv_data ) if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { - sLog.outError("BattlegroundHandler: invalid bgtype (%u) received.", bgTypeId_); - return; - } - if (!_player->InBattleGroundQueue()) - { - sLog.outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), he is not in bg_queue.", _player->GetGUIDLow()); + sLog.outError("Battleground: invalid bgtype (%u) received.", bgTypeId_); + // update battleground slots for the player to fix his UI and sent data. + // this is a HACK, I don't know why the client starts sending invalid packets in the first place. + // it usually happens with extremely high latency (if debugging / stepping in the code for example) + if (_player->InBattleGroundQueue()) + { + // update all queues, send invitation info if player is invited, queue info if queued + for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) + { + BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); + if (!bgQueueTypeId) + continue; + BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); + BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); + // if the player is not in queue, continue or no group information - this should never happen + if (itrPlayerStatus == qpMap.end() || !itrPlayerStatus->second.GroupInfo) + continue; + + BattleGround * bg = NULL; + // get possibly needed data from groupinfo + uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; + uint8 status = 0; + + if (!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) + { + // not invited to bg, get template + bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + status = STATUS_WAIT_QUEUE; + } + else + { + // get the bg we're invited to + bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID, bgTypeId); + status = STATUS_WAIT_JOIN; + } + + // if bg not found, then continue, don't invite if already in the instance + if (!bg || (_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID())) + continue; + + // re - invite player with proper data + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype); + SendPacket(&data); + } + } return; } //get GroupQueueInfo from BattleGroundQueue BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, type); - BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; - //we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function - GroupQueueInfo ginfo; - if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) + BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); + if (itrPlayerStatus == qpMap.end()) { - sLog.outError("BattlegroundHandler: itrplayerstatus not found."); + sLog.outError("Battleground: itrplayerstatus not found."); return; } + + instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID; // if action == 1, then instanceId is required - if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) + if (!instanceId && action == 1) { - sLog.outError("BattlegroundHandler: instance not found."); + sLog.outError("Battleground: instance not found."); return; } - BattleGround *bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); + BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId, bgTypeId); // bg template might and must be used in case of leaving queue, when instance is not created yet if (!bg && action == 0) bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if (!bg) { - sLog.outError("BattlegroundHandler: bg_template not found for type id %u.", bgTypeId); + sLog.outError("Battleground: bg_template not found for type id %u.", bgTypeId); return; } - //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it - if (action == 1 && ginfo.ArenaType == 0) + if (_player->InBattleGroundQueue()) { - //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue - if (!_player->CanJoinToBattleground()) + //we must use temporary variables, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function! + uint32 team = itrPlayerStatus->second.GroupInfo->Team; + uint32 arenaType = itrPlayerStatus->second.GroupInfo->ArenaType; + uint32 isRated = itrPlayerStatus->second.GroupInfo->IsRated; + uint32 rating = itrPlayerStatus->second.GroupInfo->ArenaTeamRating; + uint32 opponentsRating = itrPlayerStatus->second.GroupInfo->OpponentsTeamRating; + + //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it + if (action == 1 && arenaType == 0) { - //send bg command result to show nice message - WorldPacket data2(SMSG_GROUP_JOINED_BATTLEGROUND, 4); - data2 << uint32(0xFFFFFFFE); - _player->GetSession()->SendPacket(&data2); - action = 0; - sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); - } - //if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue - if (_player->getLevel() > bg->GetMaxLevel()) - { - sLog.outError("Battleground: Player %s (%u) has level higher than maxlevel of battleground! Do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); - action = 0; - } - } - uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); - WorldPacket data; - switch( action ) - { - case 1: // port to battleground - if (!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) - return; // cheating? - - _player->SetBattleGroundEntryPoint(); - - // resurrect the player - if (!_player->isAlive()) + //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue + if (!_player->CanJoinToBattleground()) { - _player->ResurrectPlayer(1.0f); - _player->SpawnCorpseBones(); + //send bg command result to show nice message + WorldPacket data2(SMSG_GROUP_JOINED_BATTLEGROUND, 4); + data2 << uint32(0xFFFFFFFE); + _player->GetSession()->SendPacket(&data2); + action = 0; + sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); } - // stop taxi flight at port - if (_player->isInFlight()) + //if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue + if (_player->getLevel() > bg->GetMaxLevel()) { - _player->GetMotionMaster()->MovementExpired(); - _player->m_taxi.ClearTaxiDestinations(); + sLog.outError("Battleground: Player %s (%u) has level higher than maxlevel of battleground! Do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); + action = 0; } + } + uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); + WorldPacket data; + switch( action ) + { + case 1: // port to battleground + if (!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) + return; // cheating? - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType()); - _player->GetSession()->SendPacket(&data); - // remove battleground queue status from BGmgr - bgQueue.RemovePlayer(_player->GetGUID(), false); - // this is still needed here if battleground "jumping" shouldn't add deserter debuff - // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new - if (BattleGround *currentBg = _player->GetBattleGround()) - currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); - - // set the destination instance id - _player->SetBattleGroundId(bg->GetInstanceID(), bgTypeId); - // set the destination team - _player->SetBGTeam(ginfo.Team); - // bg->HandleBeforeTeleportToBattleGround(_player); - sBattleGroundMgr.SendToBattleGround(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); - // add only in HandleMoveWorldPortAck() - // bg->AddPlayer(_player,team); - sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId); - break; - case 0: // leave queue - // if player leaves rated arena match before match start, it is counted as he played but he lost - if (ginfo.IsRated) - { - ArenaTeam * at = sObjectMgr.GetArenaTeamById(ginfo.Team); - if (at) + _player->SetBattleGroundEntryPoint(); + + // resurrect the player + if (!_player->isAlive()) { - sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), ginfo.OpponentsTeamRating); - at->MemberLost(_player, ginfo.OpponentsTeamRating); - at->SaveToDB(); + _player->ResurrectPlayer(1.0f); + _player->SpawnCorpseBones(); } - } - _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0); - bgQueue.RemovePlayer(_player->GetGUID(), true); - // player left queue, we should update it - do not update Arena Queue - if (!ginfo.ArenaType) - sBattleGroundMgr.ScheduleQueueUpdate(ginfo.ArenaTeamRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); - SendPacket(&data); - sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId); - break; - default: - sLog.outError("Battleground port: unknown action %u", action); - break; + // stop taxi flight at port + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType()); + _player->GetSession()->SendPacket(&data); + // remove battleground queue status from BGmgr + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false); + // this is still needed here if battleground "jumping" shouldn't add deserter debuff + // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new + if (BattleGround *currentBg = _player->GetBattleGround()) + currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); + + // set the destination instance id + _player->SetBattleGroundId(bg->GetInstanceID(), bgTypeId); + // set the destination team + _player->SetBGTeam(team); + // bg->HandleBeforeTeleportToBattleGround(_player); + sBattleGroundMgr.SendToBattleGround(_player, instanceId, bgTypeId); + // add only in HandleMoveWorldPortAck() + // bg->AddPlayer(_player,team); + sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId); + break; + case 0: // leave queue + // if player leaves rated arena match before match start, it is counted as he played but he lost + if (isRated) + { + ArenaTeam * at = sObjectMgr.GetArenaTeamById(team); + if (at) + { + sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), opponentsRating); + at->MemberLost(_player, opponentsRating); + at->SaveToDB(); + } + } + _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); + // player left queue, we should update it - do not update Arena Queue + if (!arenaType) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenaType, isRated, rating); + SendPacket(&data); + sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId); + break; + default: + sLog.outError("Battleground port: unknown action %u", action); + break; + } } } @@ -491,16 +544,16 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) } //we are sending update to player about queue - he can be invited there! //get GroupQueueInfo for queue status - BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; - GroupQueueInfo ginfo; - if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) + BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); + if (itrPlayerStatus == qpMap.end()) continue; - if (ginfo.IsInvitedToBGInstanceGUID) + if (itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) { - bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); + bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID, bgTypeId); if (!bg) continue; - uint32 remainingTime = getMSTimeDiff(getMSTime(), ginfo.RemoveInviteTime); + uint32 remainingTime = getMSTimeDiff(getMSTime(), itrPlayerStatus->second.GroupInfo->RemoveInviteTime); // send status invited to BattleGround sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0, arenaType); SendPacket(&data); @@ -510,9 +563,9 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if (!bg) continue; - uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, _player->GetBattleGroundQueueIdFromLevel()); + uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(itrPlayerStatus->second.GroupInfo, _player->GetBattleGroundQueueIdFromLevel()); // send status in BattleGround Queue - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(ginfo.JoinTime, getMSTime()), arenaType); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(itrPlayerStatus->second.GroupInfo->JoinTime, getMSTime()), arenaType); SendPacket(&data); } } @@ -672,9 +725,8 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) arenaRating = avg_pers_rating; } - BattleGroundQueue &bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; - GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId); - uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel()); + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId); + uint32 avgTime = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundQueueIdFromLevel()); if (asGroup) { sLog.outDebug("Battleground: arena join as group start"); @@ -693,11 +745,12 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); - bgQueue.AddPlayer(member, ginfo); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } sLog.outDebug("Battleground: arena join as group end"); - //announce to world ... removed + if (isRated) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } else { @@ -707,10 +760,10 @@ void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); SendPacket(&data); - bgQueue.AddPlayer(_player, ginfo); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } - sBattleGroundMgr.ScheduleQueueUpdate(arenaRating, arenatype, bgQueueTypeId, bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); } void WorldSession::HandleReportPvPAFK( WorldPacket & recv_data ) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 471c5d427..2f23cbd5e 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -177,7 +177,6 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId index++; sLog.outDebug("Adding Group to BattleGroundQueue bgTypeId : %u, queue_id : %u, index : %u", BgTypeId, queue_id, index); - ACE_Guard guard(m_Lock); m_QueuedGroups[queue_id][index].push_back(ginfo); // return ginfo, because it is needed to add players to this group info @@ -187,8 +186,6 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId //add player to playermap void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) { - ACE_Guard guard(m_Lock); - //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak PlayerQueueInfo& info = m_QueuedPlayers[plr->GetGUID()]; info.LastOnlineTime = getMSTime(); @@ -251,7 +248,6 @@ uint32 BattleGroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueue void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCount) { //Player *plr = sObjectMgr.GetPlayer(guid); - ACE_Guard guard(m_Lock); int32 queue_id = -1; // signed for proper for-loop finish QueuedPlayersMap::iterator itr; @@ -368,26 +364,6 @@ void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCou } } -//returns true when player pl_guid is in queue and is invited to bgInstanceGuid -bool BattleGroundQueue::IsPlayerInvited(const uint64& pl_guid, const uint32 bgInstanceGuid, const uint32 removeTime) -{ - ACE_Guard g(m_Lock); - QueuedPlayersMap::const_iterator qItr = m_QueuedPlayers.find(pl_guid); - return ( qItr != m_QueuedPlayers.end() - && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == bgInstanceGuid - && qItr->second.GroupInfo->RemoveInviteTime == removeTime ); -} - -bool BattleGroundQueue::GetPlayerGroupInfoData(const uint64& guid, GroupQueueInfo* ginfo) -{ - ACE_Guard g(m_Lock); - QueuedPlayersMap::const_iterator qItr = m_QueuedPlayers.find(guid); - if (qItr == m_QueuedPlayers.end()) - return false; - *ginfo = *(qItr->second.GroupInfo); - return true; -} - //Announce world message void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue) { @@ -485,7 +461,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b plr->SetInviteForBattleGroundQueueType(bgQueueTypeId, ginfo->IsInvitedToBGInstanceGUID); // create remind invite events - BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, ginfo->ArenaType, ginfo->RemoveInviteTime); + BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, ginfo->RemoveInviteTime); plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITATION_REMIND_TIME)); // create automatic remove events BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, bgQueueTypeId, ginfo->RemoveInviteTime); @@ -756,7 +732,6 @@ should be called from BattleGround::RemovePlayer function in some cases */ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated, uint32 arenaRating) { - ACE_Guard guard(m_Lock); //if no players in queue - do nothing if( m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty() && @@ -1046,15 +1021,17 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); - if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue or in battleground + if( queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES ) // player is in queue or in battleground { // check if player is invited to this bg - BattleGroundQueue &bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; - if (bgQueue.IsPlayerInvited(m_PlayerGuid, m_BgInstanceGUID, m_RemoveTime)) + BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; + BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); + if( qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID + && qItr->second.GroupInfo->RemoveInviteTime == m_RemoveTime ) { WorldPacket data; //we must send remaining time in queue - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, 0, m_ArenaType); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, 0, qItr->second.GroupInfo->ArenaType); plr->GetSession()->SendPacket(&data); } } @@ -1087,19 +1064,22 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) //bg pointer can be NULL! so use it carefully! uint32 queueSlot = plr->GetBattleGroundQueueIndex(m_BgQueueTypeId); - if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue, or in Battleground + if( queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES ) // player is in queue, or in Battleground { // check if player is in queue for this BG and if we are removing his invite event - BattleGroundQueue &bgQueue = sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId]; - if (bgQueue.IsPlayerInvited(m_PlayerGuid, m_BgInstanceGUID, m_RemoveTime)) + BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].m_QueuedPlayers; + BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = qpMap.find(m_PlayerGuid); + if( qMapItr != qpMap.end() && qMapItr->second.GroupInfo + && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID + && qMapItr->second.GroupInfo->RemoveInviteTime == m_RemoveTime ) { sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID); plr->RemoveBattleGroundQueueId(m_BgQueueTypeId); - bgQueue.RemovePlayer(m_PlayerGuid, true); + sBattleGroundMgr.m_BattleGroundQueues[m_BgQueueTypeId].RemovePlayer(m_PlayerGuid, true); //update queues if battleground isn't ended - if (bg && bg->isBattleGround() && bg->GetStatus() != STATUS_WAIT_LEAVE) - sBattleGroundMgr.ScheduleQueueUpdate(0, 0, m_BgQueueTypeId, m_BgTypeId, bg->GetQueueId()); + if (bg) + sBattleGroundMgr.ScheduleQueueUpdate(m_BgQueueTypeId, m_BgTypeId, bg->GetQueueId()); WorldPacket data; sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0); @@ -1187,24 +1167,18 @@ void BattleGroundMgr::Update(uint32 diff) // update scheduled queues if (!m_QueueUpdateScheduler.empty()) { - std::vector scheduled; - { - //create mutex - ACE_Guard guard(SchedulerLock); - //copy vector and clear the other - scheduled = std::vector(m_QueueUpdateScheduler); - m_QueueUpdateScheduler.clear(); - //release lock - } - + //copy vector and clear the other + // TODO add lock + // TODO maybe std::list would be better and then unlock after end of cycle + std::vector scheduled(m_QueueUpdateScheduler); + m_QueueUpdateScheduler.clear(); + // TODO drop lock for (uint8 i = 0; i < scheduled.size(); i++) { - uint32 arenaRating = scheduled[i] >> 32; - uint8 arenaType = scheduled[i] >> 24 & 255; - BattleGroundQueueTypeId bgQueueTypeId = BattleGroundQueueTypeId(scheduled[i] >> 16 & 255); + BattleGroundQueueTypeId bgQueueTypeId = BattleGroundQueueTypeId(scheduled[i] >> 16); BattleGroundTypeId bgTypeId = BattleGroundTypeId((scheduled[i] >> 8) & 255); BGQueueIdBasedOnLevel queue_id = BGQueueIdBasedOnLevel(scheduled[i] & 255); - m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, queue_id, arenaType, arenaRating > 0, arenaRating); + m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, queue_id); } } @@ -2034,11 +2008,11 @@ void BattleGroundMgr::ToggleArenaTesting() sWorld.SendWorldText(LANG_DEBUG_ARENA_OFF); } -void BattleGroundMgr::ScheduleQueueUpdate(uint32 arenaRating, uint8 arenaType, BattleGroundQueueTypeId bgQueueTypeId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id) +void BattleGroundMgr::ScheduleQueueUpdate(BattleGroundQueueTypeId bgQueueTypeId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id) { - ACE_Guard guard(SchedulerLock); + //This method must be atomic, TODO add mutex //we will use only 1 number created of bgTypeId and queue_id - uint64 schedule_id = ((uint64)arenaRating << 32) | (arenaType << 24) | (bgQueueTypeId << 16) | (bgTypeId << 8) | queue_id; + uint32 schedule_id = (bgQueueTypeId << 16) | (bgTypeId << 8) | queue_id; bool found = false; for (uint8 i = 0; i < m_QueueUpdateScheduler.size(); i++) { diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 36f097cdb..4d72d9656 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -23,7 +23,6 @@ #include "Policies/Singleton.h" #include "Utilities/EventProcessor.h" #include "BattleGround.h" -#include "ace/Recursive_Thread_Mutex.h" typedef std::map BattleGroundSet; @@ -84,19 +83,12 @@ class BattleGroundQueue GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0); void AddPlayer(Player *plr, GroupQueueInfo *ginfo); void RemovePlayer(const uint64& guid, bool decreaseInvitedCount); - bool IsPlayerInvited(const uint64& pl_guid, const uint32 bgInstanceGuid, const uint32 removeTime); - bool GetPlayerGroupInfoData(const uint64& guid, GroupQueueInfo* ginfo); void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id); uint32 GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BGQueueIdBasedOnLevel queue_id); void DecreaseGroupLength(uint32 queueId, uint32 AsGroup); void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue); - private: - //mutex that should not allow changing private data, nor allowing to update Queue during private data change. - ACE_Recursive_Thread_Mutex m_Lock; - - typedef std::map QueuedPlayersMap; QueuedPlayersMap m_QueuedPlayers; @@ -131,6 +123,8 @@ class BattleGroundQueue //one selection pool for horde, other one for alliance SelectionPool m_SelectionPools[BG_TEAMS_COUNT]; + private: + bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side); uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME]; uint32 m_WaitTimeLastPlayer[BG_TEAMS_COUNT][MAX_BATTLEGROUND_QUEUES]; @@ -144,8 +138,8 @@ class BattleGroundQueue class BGQueueInviteEvent : public BasicEvent { public: - BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId, uint8 arenaType, uint32 removeTime) : - m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId), m_ArenaType(arenaType), m_RemoveTime(removeTime) + BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID, BattleGroundTypeId BgTypeId, uint32 removeTime) : + m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID), m_BgTypeId(BgTypeId), m_RemoveTime(removeTime) { }; virtual ~BGQueueInviteEvent() {}; @@ -156,7 +150,6 @@ class BGQueueInviteEvent : public BasicEvent uint64 m_PlayerGuid; uint32 m_BgInstanceGUID; BattleGroundTypeId m_BgTypeId; - uint8 m_ArenaType; uint32 m_RemoveTime; }; @@ -226,7 +219,7 @@ class BattleGroundMgr BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPE_ID]; - void ScheduleQueueUpdate(uint32 arenaRating, uint8 arenaType, BattleGroundQueueTypeId bgQueueTypeId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id); + void ScheduleQueueUpdate(BattleGroundQueueTypeId bgQueueTypeId, BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id); uint32 GetMaxRatingDifference() const; uint32 GetRatingDiscardTimer() const; uint32 GetPrematureFinishTime() const; @@ -272,14 +265,13 @@ class BattleGroundMgr static bool IsBGWeekend(BattleGroundTypeId bgTypeId); private: - ACE_Thread_Mutex SchedulerLock; BattleMastersMap mBattleMastersMap; CreatureBattleEventIndexesMap m_CreatureBattleEventIndexMap; GameObjectBattleEventIndexesMap m_GameObjectBattleEventIndexMap; /* Battlegrounds */ BattleGroundSet m_BattleGrounds[MAX_BATTLEGROUND_TYPE_ID]; - std::vector m_QueueUpdateScheduler; + std::vectorm_QueueUpdateScheduler; std::set m_ClientBattleGroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_QUEUES]; //the instanceids just visible for the client uint32 m_NextRatingDiscardUpdate; time_t m_NextAutoDistributionTime; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3cfd385e5..8bf574e41 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8808" + #define REVISION_NR "8809" #endif // __REVISION_NR_H__ -- 2.11.4.GIT