mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-04 22:07:52 +00:00
fix(Core/Battlegrounds): fix invited-count accounting on BG entry (#26556)
This commit is contained in:
@@ -647,7 +647,7 @@ void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, ObjectGuid
|
||||
}
|
||||
}
|
||||
|
||||
void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, BattlegroundTypeId bgTypeId)
|
||||
bool BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, BattlegroundTypeId bgTypeId)
|
||||
{
|
||||
if (Battleground* bg = GetBattleground(instanceId, bgTypeId))
|
||||
{
|
||||
@@ -655,12 +655,11 @@ void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, Batt
|
||||
Position const* pos = bg->GetTeamStartPosition(player->GetBgTeamId());
|
||||
|
||||
LOG_DEBUG("bg.battleground", "BattlegroundMgr::SendToBattleground: Sending {} to map {}, {} (bgType {})", player->GetName(), mapid, pos->ToString(), bgTypeId);
|
||||
player->TeleportTo(mapid, pos->GetPositionX(), pos->GetPositionY(), pos->GetPositionZ(), pos->GetOrientation());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("bg.battleground", "BattlegroundMgr::SendToBattleground: Instance {} (bgType {}) not found while trying to teleport player {}", instanceId, bgTypeId, player->GetName());
|
||||
return player->TeleportTo(mapid, pos->GetPositionX(), pos->GetPositionY(), pos->GetPositionZ(), pos->GetOrientation());
|
||||
}
|
||||
|
||||
LOG_ERROR("bg.battleground", "BattlegroundMgr::SendToBattleground: Instance {} (bgType {}) not found while trying to teleport player {}", instanceId, bgTypeId, player->GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
void BattlegroundMgr::SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid guid)
|
||||
|
||||
@@ -93,7 +93,10 @@ public:
|
||||
void LoadBattlegroundTemplates();
|
||||
void DeleteAllBattlegrounds();
|
||||
|
||||
void SendToBattleground(Player* player, uint32 InstanceID, BattlegroundTypeId bgTypeId);
|
||||
// Returns false when the teleport could not start (instance gone, or a
|
||||
// synchronous TeleportTo failure) so the accept path can release the
|
||||
// otherwise-orphaned invited reservation.
|
||||
bool SendToBattleground(Player* player, uint32 InstanceID, BattlegroundTypeId bgTypeId);
|
||||
|
||||
/* Battleground queues */
|
||||
BattlegroundQueue& GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId) { return m_BattlegroundQueues[bgQueueTypeId]; }
|
||||
|
||||
@@ -1302,13 +1302,16 @@ int32 BattlegroundQueue::GetQueueAnnouncementTimer(uint32 bracketId) const
|
||||
|
||||
void BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId)
|
||||
{
|
||||
// An already-invited group keeps the side it was invited under: writing
|
||||
// teamId here would split a future re-invite's IncreaseInvitedCount from the
|
||||
// original side's DecreaseInvitedCount at leave, desyncing the ledger.
|
||||
if (ginfo->IsInvitedToBGInstanceGUID)
|
||||
return;
|
||||
|
||||
// set side if needed
|
||||
if (teamId != TEAM_NEUTRAL)
|
||||
ginfo->teamId = teamId;
|
||||
|
||||
if (ginfo->IsInvitedToBGInstanceGUID)
|
||||
return;
|
||||
|
||||
// set invitation
|
||||
ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
|
||||
|
||||
|
||||
@@ -544,7 +544,31 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
|
||||
sLFGMgr->LeaveAllLfgQueues(_player->GetGUID(), false);
|
||||
|
||||
_player->SetBattlegroundId(bg->GetInstanceID(), bg->GetBgTypeID(), queueSlot, true, bgTypeId == BATTLEGROUND_RB, teamId);
|
||||
sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
|
||||
|
||||
if (!sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId))
|
||||
{
|
||||
// The teleport never started (instance gone, or a synchronous
|
||||
// TeleportTo veto such as a DK still locked to Ebon Hold). The accept
|
||||
// already pulled the player out of the queue and he can't decline
|
||||
// now, so undo the accept here -- otherwise the invited reservation
|
||||
// leaks forever, permanently skewing team selection and blocking the
|
||||
// empty instance's cleanup.
|
||||
bg->DecreaseInvitedCount(teamId);
|
||||
_player->RemoveBattlegroundQueueId(bgQueueTypeId);
|
||||
_player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE, PLAYER_MAX_BATTLEGROUND_QUEUES, false, false, TEAM_NEUTRAL);
|
||||
|
||||
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, TEAM_NEUTRAL);
|
||||
SendPacket(&data);
|
||||
|
||||
// Free slot -> let the queue refill it. BG only, like the sibling
|
||||
// leave-queue path: an arena update needs its own type/rating.
|
||||
if (!ginfo.ArenaType)
|
||||
sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
|
||||
|
||||
LOG_ERROR("bg.battleground", "Battleground: player {} {} failed to teleport into bg {}, bgtype {}; released the invited reservation.",
|
||||
_player->GetName(), _player->GetGUID().ToString(), bg->GetInstanceID(), bg->GetBgTypeID());
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG("bg.battleground", "Battleground: player {} {} joined battle for bg {}, bgtype {}, queue type {}.", _player->GetName(), _player->GetGUID().ToString(), bg->GetInstanceID(), bg->GetBgTypeID(), bgQueueTypeId);
|
||||
}
|
||||
|
||||
@@ -499,8 +499,21 @@ public:
|
||||
// Remove from LFG queues
|
||||
sLFGMgr->LeaveAllLfgQueues(player->GetGUID(), false);
|
||||
|
||||
// Book the reservation like the queue path does, so it is symmetric
|
||||
// with RemovePlayerAtLeave's decrement and the 0-players/0-invited
|
||||
// state can't let Battleground::Update delete the arena while players
|
||||
// are still on the loading screen.
|
||||
bg->IncreaseInvitedCount(teamId);
|
||||
player->SetBattlegroundId(bg->GetInstanceID(), bgTypeId, queueSlot, true, false, teamId);
|
||||
sBattlegroundMgr->SendToBattleground(player, bg->GetInstanceID(), bgTypeId);
|
||||
|
||||
// A synchronous teleport failure would strand that reservation (the
|
||||
// player never enters and never reaches RemovePlayerAtLeave), leaving
|
||||
// the arena undeletable; release it and reset his bg data.
|
||||
if (!sBattlegroundMgr->SendToBattleground(player, bg->GetInstanceID(), bgTypeId))
|
||||
{
|
||||
bg->DecreaseInvitedCount(teamId);
|
||||
player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE, PLAYER_MAX_BATTLEGROUND_QUEUES, false, false, TEAM_NEUTRAL);
|
||||
}
|
||||
}
|
||||
|
||||
handler->PSendSysMessage("Success! Players are now being teleported to the arena.");
|
||||
|
||||
Reference in New Issue
Block a user