mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-09 08:17:56 +00:00
fix(Core/LFG): prevent RDF anti-kick exploit via loot rolls (#25112)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13040,7 +13040,7 @@ PartyResult Player::CanUninviteFromGroup(ObjectGuid targetPlayerGUID) const
|
|||||||
if (state == lfg::LFG_STATE_FINISHED_DUNGEON)
|
if (state == lfg::LFG_STATE_FINISHED_DUNGEON)
|
||||||
return ERR_PARTY_LFG_BOOT_DUNGEON_COMPLETE;
|
return ERR_PARTY_LFG_BOOT_DUNGEON_COMPLETE;
|
||||||
|
|
||||||
if (grp->isRollLootActive())
|
if (grp->isRollLootActive() && ObjectAccessor::FindConnectedPlayer(targetPlayerGUID))
|
||||||
return ERR_PARTY_LFG_BOOT_LOOT_ROLLS;
|
return ERR_PARTY_LFG_BOOT_LOOT_ROLLS;
|
||||||
|
|
||||||
/// @todo: Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer.
|
/// @todo: Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer.
|
||||||
|
|||||||
@@ -600,35 +600,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove player from loot rolls
|
// Remove player from loot rolls
|
||||||
for (Rolls::iterator it = RollId.begin(); it != RollId.end();)
|
RemovePlayerFromRolls(guid);
|
||||||
{
|
|
||||||
Roll* roll = *it;
|
|
||||||
Roll::PlayerVote::iterator itr2 = roll->playerVote.find(guid);
|
|
||||||
if (itr2 == roll->playerVote.end())
|
|
||||||
{
|
|
||||||
++it;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itr2->second == GREED || itr2->second == DISENCHANT)
|
|
||||||
--roll->totalGreed;
|
|
||||||
else if (itr2->second == NEED)
|
|
||||||
--roll->totalNeed;
|
|
||||||
else if (itr2->second == PASS)
|
|
||||||
--roll->totalPass;
|
|
||||||
|
|
||||||
if (itr2->second != NOT_VALID)
|
|
||||||
--roll->totalPlayersRolling;
|
|
||||||
|
|
||||||
roll->playerVote.erase(itr2);
|
|
||||||
|
|
||||||
// Xinef: itr can be erased inside
|
|
||||||
// Xinef: player is removed from all vote lists so it will not pass above playerVote == playerVote.end statement during second iteration
|
|
||||||
if (CountRollVote(guid, roll->itemGUID, MAX_ROLL_TYPE))
|
|
||||||
it = RollId.begin();
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update subgroups
|
// Update subgroups
|
||||||
member_witerator slot = _getMemberWSlot(guid);
|
member_witerator slot = _getMemberWSlot(guid);
|
||||||
@@ -1422,6 +1394,37 @@ void Group::EndRoll(Loot* pLoot, Map* allowedMap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Group::RemovePlayerFromRolls(ObjectGuid guid)
|
||||||
|
{
|
||||||
|
for (Rolls::iterator it = RollId.begin(); it != RollId.end();)
|
||||||
|
{
|
||||||
|
Roll* roll = *it;
|
||||||
|
Roll::PlayerVote::iterator itr2 = roll->playerVote.find(guid);
|
||||||
|
if (itr2 == roll->playerVote.end())
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itr2->second == GREED || itr2->second == DISENCHANT)
|
||||||
|
--roll->totalGreed;
|
||||||
|
else if (itr2->second == NEED)
|
||||||
|
--roll->totalNeed;
|
||||||
|
else if (itr2->second == PASS)
|
||||||
|
--roll->totalPass;
|
||||||
|
|
||||||
|
if (itr2->second != NOT_VALID)
|
||||||
|
--roll->totalPlayersRolling;
|
||||||
|
|
||||||
|
roll->playerVote.erase(itr2);
|
||||||
|
|
||||||
|
if (CountRollVote(guid, roll->itemGUID, MAX_ROLL_TYPE))
|
||||||
|
it = RollId.begin();
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap)
|
void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap)
|
||||||
{
|
{
|
||||||
Roll* roll = *rollI;
|
Roll* roll = *rollI;
|
||||||
|
|||||||
@@ -299,6 +299,7 @@ public:
|
|||||||
void CountTheRoll(Rolls::iterator roll, Map* allowedMap);
|
void CountTheRoll(Rolls::iterator roll, Map* allowedMap);
|
||||||
bool CountRollVote(ObjectGuid playerGUID, ObjectGuid Guid, uint8 Choise);
|
bool CountRollVote(ObjectGuid playerGUID, ObjectGuid Guid, uint8 Choise);
|
||||||
void EndRoll(Loot* loot, Map* allowedMap);
|
void EndRoll(Loot* loot, Map* allowedMap);
|
||||||
|
void RemovePlayerFromRolls(ObjectGuid guid);
|
||||||
|
|
||||||
// related to disenchant rolls
|
// related to disenchant rolls
|
||||||
void ResetMaxEnchantingLevel();
|
void ResetMaxEnchantingLevel();
|
||||||
|
|||||||
@@ -702,6 +702,10 @@ void WorldSession::LogoutPlayer(bool save)
|
|||||||
// a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) d) LeaveGroupOnLogout is enabled
|
// a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) d) LeaveGroupOnLogout is enabled
|
||||||
if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && !_player->GetGroup()->isLFGGroup() && m_Socket && sWorld->getBoolConfig(CONFIG_LEAVE_GROUP_ON_LOGOUT))
|
if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && !_player->GetGroup()->isLFGGroup() && m_Socket && sWorld->getBoolConfig(CONFIG_LEAVE_GROUP_ON_LOGOUT))
|
||||||
_player->RemoveFromGroup();
|
_player->RemoveFromGroup();
|
||||||
|
// Remove player from active loot rolls in LFG groups (player stays in group but should not block rolls)
|
||||||
|
else if (Group* group = _player->GetGroup())
|
||||||
|
if (group->isLFGGroup())
|
||||||
|
group->RemovePlayerFromRolls(_player->GetGUID());
|
||||||
|
|
||||||
// pussywizard: checked second time after being removed from a group
|
// pussywizard: checked second time after being removed from a group
|
||||||
if (!_player->IsBeingTeleportedFar() && !_player->m_InstanceValid && !_player->IsGameMaster())
|
if (!_player->IsBeingTeleportedFar() && !_player->m_InstanceValid && !_player->IsGameMaster())
|
||||||
|
|||||||
Reference in New Issue
Block a user