[11534] Guild disban memory losses and unsafe code.

* Make sure that guild object deleted in all cases after disband.
* Avoid recusive like way call Disband from DelMember
This commit is contained in:
VladimirMangos 2011-05-25 03:19:42 +04:00
parent b5c3ec952f
commit 2cbde12458
6 changed files with 59 additions and 19 deletions

View file

@ -301,10 +301,8 @@ bool Guild::CheckGuildStructure()
int32 GM_rights = GetRank(m_LeaderGuid);
if (GM_rights == -1)
{
DelMember(m_LeaderGuid);
// check no members case (disbanded)
if (members.empty())
return false;
if (DelMember(m_LeaderGuid))
return false; // guild will disbanded and deleted in caller
}
else if (GM_rights != GR_GUILDMASTER)
SetLeader(m_LeaderGuid);
@ -488,7 +486,15 @@ void Guild::SetLeader(ObjectGuid guid)
CharacterDatabase.PExecute("UPDATE guild SET leaderguid='%u' WHERE guildid='%u'", guid.GetCounter(), m_Id);
}
void Guild::DelMember(ObjectGuid guid, bool isDisbanding)
/**
* Remove character from guild
*
* @param guid Character that removed from guild
* @param isDisbanding Flag set if function called from Guild::Disband, so not need update DB in per-member mode only or leader update
*
* @return true, if guild need to be disband and erase (no members or can't setup leader)
*/
bool Guild::DelMember(ObjectGuid guid, bool isDisbanding)
{
uint32 lowguid = guid.GetCounter();
@ -513,11 +519,9 @@ void Guild::DelMember(ObjectGuid guid, bool isDisbanding)
newLeaderGUID = ObjectGuid(HIGHGUID_PLAYER, i->first);
}
}
if (!best)
{
Disband();
return;
}
return true;
SetLeader(newLeaderGUID);
@ -547,6 +551,8 @@ void Guild::DelMember(ObjectGuid guid, bool isDisbanding)
if (!isDisbanding)
UpdateAccountsNumber();
return members.empty();
}
void Guild::BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language)
@ -685,6 +691,11 @@ void Guild::SetRankRights(uint32 rankId, uint32 rights)
CharacterDatabase.PExecute("UPDATE guild_rank SET rights='%u' WHERE rid='%u' AND guildid='%u'", rights, rankId, m_Id);
}
/**
* Disband guild including cleanup structures and DB
*
* Note: guild object need deleted after this in caller code.
*/
void Guild::Disband()
{
BroadcastEvent(GE_DISBANDED);

View file

@ -324,7 +324,7 @@ class Guild
void SetLeader(ObjectGuid guid);
bool AddMember(ObjectGuid plGuid, uint32 plRank);
void DelMember(ObjectGuid guid, bool isDisbanding = false);
bool DelMember(ObjectGuid guid, bool isDisbanding = false);
//lowest rank is the count of ranks - 1 (the highest rank_id in table)
uint32 GetLowestRank() const { return m_Ranks.size() - 1; }

View file

@ -177,7 +177,14 @@ void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket)
return;
}
guild->DelMember(slot->guid);
// possible last member removed, do cleanup, and no need events
if (guild->DelMember(slot->guid))
{
guild->Disband();
delete guild;
return;
}
// Put record into guild log
guild->LogGuildEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, GetPlayer()->GetObjectGuid(), slot->guid);
@ -376,16 +383,23 @@ void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/)
if (_player->GetObjectGuid() == guild->GetLeaderGuid())
{
guild->Disband();
delete guild;
return;
}
SendGuildCommandResult(GUILD_QUIT_S, guild->GetName(), ERR_PLAYER_NO_MORE_IN_GUILD);
if (guild->DelMember(_player->GetObjectGuid()))
{
guild->Disband();
delete guild;
return;
}
guild->DelMember(_player->GetObjectGuid());
// Put record into guild log
guild->LogGuildEvent(GUILD_EVENT_LOG_LEAVE_GUILD, _player->GetObjectGuid());
guild->BroadcastEvent(GE_LEFT, _player->GetObjectGuid(), _player->GetName());
SendGuildCommandResult(GUILD_QUIT_S, guild->GetName(), ERR_PLAYER_NO_MORE_IN_GUILD);
}
void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/)
@ -406,6 +420,7 @@ void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/)
}
guild->Disband();
delete guild;
DEBUG_LOG("WORLD: Guild Successfully Disbanded");
}

View file

@ -3608,7 +3608,12 @@ bool ChatHandler::HandleGuildUninviteCommand(char *args)
if (!targetGuild)
return false;
targetGuild->DelMember(target_guid);
if (targetGuild->DelMember(target_guid))
{
targetGuild->Disband();
delete targetGuild;
}
return true;
}
@ -3661,6 +3666,7 @@ bool ChatHandler::HandleGuildDeleteCommand(char* args)
return false;
targetGuild->Disband();
delete targetGuild;
return true;
}

View file

@ -4174,8 +4174,16 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
// remove from guild
if (uint32 guildId = GetGuildIdFromDB(playerguid))
{
if (Guild* guild = sGuildMgr.GetGuildById(guildId))
guild->DelMember(playerguid);
{
if (guild->DelMember(playerguid))
{
guild->Disband();
delete guild;
}
}
}
// remove from arena teams
LeaveAllArenaTeams(playerguid);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "11533"
#define REVISION_NR "11534"
#endif // __REVISION_NR_H__