[10378] Avoid double lookup member slot in guild operations.

Also more wide use ObjectGuid in guild code
and fixed some uint32->uint64 guid assigns.
This commit is contained in:
VladimirMangos 2010-08-19 07:35:43 +04:00
parent f2406c1962
commit 9b3d37f0cf
9 changed files with 189 additions and 190 deletions

View file

@ -29,11 +29,56 @@
#include "Language.h"
#include "World.h"
//// MemberSlot ////////////////////////////////////////////
void MemberSlot::SetMemberStats(Player* player)
{
Name = player->GetName();
Level = player->getLevel();
Class = player->getClass();
ZoneId = player->GetZoneId();
}
void MemberSlot::UpdateLogoutTime()
{
LogoutTime = time(NULL);
}
void MemberSlot::SetPNOTE(std::string pnote)
{
Pnote = pnote;
// pnote now can be used for encoding to DB
CharacterDatabase.escape_string(pnote);
CharacterDatabase.PExecute("UPDATE guild_member SET pnote = '%s' WHERE guid = '%u'", pnote.c_str(), guid.GetCounter());
}
void MemberSlot::SetOFFNOTE(std::string offnote)
{
OFFnote = offnote;
// offnote now can be used for encoding to DB
CharacterDatabase.escape_string(offnote);
CharacterDatabase.PExecute("UPDATE guild_member SET offnote = '%s' WHERE guid = '%u'", offnote.c_str(), guid.GetCounter());
}
void MemberSlot::ChangeRank(uint32 newRank)
{
RankId = newRank;
Player *player = sObjectMgr.GetPlayer(guid);
// If player not online data in data field will be loaded from guild tabs no need to update it !!
if (player)
player->SetRank(newRank);
CharacterDatabase.PExecute("UPDATE guild_member SET rank='%u' WHERE guid='%u'", newRank, guid.GetCounter());
}
//// Guild /////////////////////////////////////////////////
Guild::Guild()
{
m_Id = 0;
m_Name = "";
m_LeaderGuid = 0;
GINFO = MOTD = "";
m_EmblemStyle = 0;
m_EmblemColor = 0;
@ -66,7 +111,7 @@ bool Guild::Create(Player* leader, std::string gname)
if (!lSession)
return false;
m_LeaderGuid = leader->GetGUID();
m_LeaderGuid = leader->GetObjectGuid();
m_Name = gname;
GINFO = "";
MOTD = "No message set.";
@ -74,7 +119,7 @@ bool Guild::Create(Player* leader, std::string gname)
m_Id = sObjectMgr.GenerateGuildId();
m_CreatedDate = time(0);
DEBUG_LOG("GUILD: creating guild %s to leader: %u", gname.c_str(), GUID_LOPART(m_LeaderGuid));
DEBUG_LOG("GUILD: creating guild %s to leader: %s", gname.c_str(), m_LeaderGuid.GetString().c_str());
// gname already assigned to Guild::name, use it to encode string for DB
CharacterDatabase.escape_string(gname);
@ -89,7 +134,7 @@ bool Guild::Create(Player* leader, std::string gname)
CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guildid='%u'", m_Id);
CharacterDatabase.PExecute("INSERT INTO guild (guildid,name,leaderguid,info,motd,createdate,EmblemStyle,EmblemColor,BorderStyle,BorderColor,BackgroundColor,BankMoney) "
"VALUES('%u','%s','%u', '%s', '%s','" UI64FMTD "','%u','%u','%u','%u','%u','" UI64FMTD "')",
m_Id, gname.c_str(), GUID_LOPART(m_LeaderGuid), dbGINFO.c_str(), dbMOTD.c_str(), uint64(m_CreatedDate), m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor, m_BackgroundColor, m_GuildBankMoney);
m_Id, gname.c_str(), m_LeaderGuid.GetCounter(), dbGINFO.c_str(), dbMOTD.c_str(), uint64(m_CreatedDate), m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor, m_BackgroundColor, m_GuildBankMoney);
CharacterDatabase.CommitTransaction();
CreateDefaultGuildRanks(lSession->GetSessionDbLocaleIndex());
@ -111,7 +156,7 @@ void Guild::CreateDefaultGuildRanks(int locale_idx)
SetBankMoneyPerDay((uint32)GR_GUILDMASTER, WITHDRAW_MONEY_UNLIMITED);
}
bool Guild::AddMember(uint64 plGuid, uint32 plRank)
bool Guild::AddMember(ObjectGuid plGuid, uint32 plRank)
{
Player* pl = sObjectMgr.GetPlayer(plGuid);
if (pl)
@ -129,9 +174,13 @@ bool Guild::AddMember(uint64 plGuid, uint32 plRank)
// this will be prevent attempt joining player to many guilds and corrupt guild data integrity
Player::RemovePetitionsAndSigns(plGuid, 9);
uint32 lowguid = plGuid.GetCounter();
// fill player data
MemberSlot newmember;
newmember.guid = plGuid;
if (pl)
{
newmember.accountId = pl->GetSession()->GetAccountId();
@ -143,7 +192,7 @@ bool Guild::AddMember(uint64 plGuid, uint32 plRank)
else
{
// 0 1 2 3 4
QueryResult *result = CharacterDatabase.PQuery("SELECT name,level,class,zone,account FROM characters WHERE guid = '%u'", GUID_LOPART(plGuid));
QueryResult *result = CharacterDatabase.PQuery("SELECT name,level,class,zone,account FROM characters WHERE guid = '%u'", lowguid);
if (!result)
return false; // player doesn't exist
@ -157,7 +206,7 @@ bool Guild::AddMember(uint64 plGuid, uint32 plRank)
if (newmember.Level < 1 || newmember.Level > STRONG_MAX_LEVEL ||
newmember.Class < CLASS_WARRIOR || newmember.Class >= MAX_CLASSES)
{
sLog.outError("Player (GUID: %u) has a broken data in field `characters` table, cannot add him to guild.",GUID_LOPART(plGuid));
sLog.outError("%s has a broken data in field `characters` table, cannot add him to guild.", plGuid.GetString().c_str());
return false;
}
}
@ -169,7 +218,7 @@ bool Guild::AddMember(uint64 plGuid, uint32 plRank)
newmember.BankResetTimeMoney = 0; // this will force update at first query
for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
newmember.BankResetTimeTab[i] = 0;
members[GUID_LOPART(plGuid)] = newmember;
members[lowguid] = newmember;
std::string dbPnote = newmember.Pnote;
std::string dbOFFnote = newmember.OFFnote;
@ -177,7 +226,7 @@ bool Guild::AddMember(uint64 plGuid, uint32 plRank)
CharacterDatabase.escape_string(dbOFFnote);
CharacterDatabase.PExecute("INSERT INTO guild_member (guildid,guid,rank,pnote,offnote) VALUES ('%u', '%u', '%u','%s','%s')",
m_Id, GUID_LOPART(plGuid), newmember.RankId, dbPnote.c_str(), dbOFFnote.c_str());
m_Id, lowguid, newmember.RankId, dbPnote.c_str(), dbOFFnote.c_str());
// If player not in game data in data field will be loaded from guild tables, no need to update it!!
if (pl)
@ -219,7 +268,7 @@ bool Guild::LoadGuildFromDB(QueryResult *guildDataResult)
m_Id = fields[0].GetUInt32();
m_Name = fields[1].GetCppString();
m_LeaderGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
m_LeaderGuid = ObjectGuid(HIGHGUID_PLAYER, fields[2].GetUInt32());
m_EmblemStyle = fields[3].GetUInt32();
m_EmblemColor = fields[4].GetUInt32();
m_BorderStyle = fields[5].GetUInt32();
@ -248,7 +297,7 @@ bool Guild::CheckGuildStructure()
// Repair the structure of guild
// If the guildmaster doesn't exist or isn't the member of guild
// attempt to promote another member
int32 GM_rights = GetRank(GUID_LOPART(m_LeaderGuid));
int32 GM_rights = GetRank(m_LeaderGuid);
if (GM_rights == -1)
{
DelMember(m_LeaderGuid);
@ -259,13 +308,10 @@ bool Guild::CheckGuildStructure()
else if (GM_rights != GR_GUILDMASTER)
SetLeader(m_LeaderGuid);
// Allow only 1 guildmaster
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
{
if (itr->second.RankId == GR_GUILDMASTER && GUID_LOPART(m_LeaderGuid) != itr->first)
//set right of member to officer
ChangeRank(itr->first, GR_OFFICER);
}
// Allow only 1 guildmaster, set other to officer
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
if (itr->second.RankId == GR_GUILDMASTER && m_LeaderGuid != itr->second.guid)
itr->second.ChangeRank(GR_OFFICER);
return true;
}
@ -373,7 +419,7 @@ bool Guild::LoadMembersFromDB(QueryResult *guildMembersResult)
MemberSlot newmember;
uint32 lowguid = fields[1].GetUInt32();
ObjectGuid guid = ObjectGuid(HIGHGUID_PLAYER, lowguid);
newmember.guid = ObjectGuid(HIGHGUID_PLAYER, lowguid);
newmember.RankId = fields[2].GetUInt32();
// don't allow member to have not existing rank!
if (newmember.RankId >= m_Ranks.size())
@ -399,20 +445,20 @@ bool Guild::LoadMembersFromDB(QueryResult *guildMembersResult)
// this code will remove not existing character guids from guild
if (newmember.Level < 1 || newmember.Level > STRONG_MAX_LEVEL) // can be at broken `data` field
{
sLog.outError("%s has a broken data in field `characters`.`data`, deleting him from guild!", guid.GetString().c_str());
sLog.outError("%s has a broken data in field `characters`.`data`, deleting him from guild!", newmember.guid.GetString().c_str());
CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", lowguid);
continue;
}
if (!newmember.ZoneId)
{
sLog.outError("%s has broken zone-data", guid.GetString().c_str());
sLog.outError("%s has broken zone-data", newmember.guid.GetString().c_str());
// here it will also try the same, to get the zone from characters-table, but additional it tries to find
// the zone through xy coords .. this is a bit redundant, but shouldn't be called often
newmember.ZoneId = Player::GetZoneIdFromDB(guid);
newmember.ZoneId = Player::GetZoneIdFromDB(newmember.guid);
}
if (newmember.Class < CLASS_WARRIOR || newmember.Class >= MAX_CLASSES) // can be at broken `class` field
{
sLog.outError("%s has a broken data in field `characters`.`class`, deleting him from guild!", guid.GetString().c_str());
sLog.outError("%s has a broken data in field `characters`.`class`, deleting him from guild!", newmember.guid.GetString().c_str());
CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", lowguid);
continue;
}
@ -429,41 +475,32 @@ bool Guild::LoadMembersFromDB(QueryResult *guildMembersResult)
return true;
}
void Guild::SetMemberStats(uint64 guid)
void Guild::SetLeader(ObjectGuid guid)
{
MemberList::iterator itr = members.find(GUID_LOPART(guid));
if (itr == members.end() )
MemberSlot* slot = GetMemberSlot(guid);
if (!slot)
return;
Player *pl = ObjectAccessor::FindPlayer(guid);
if (!pl)
return;
itr->second.Name = pl->GetName();
itr->second.Level = pl->getLevel();
itr->second.Class = pl->getClass();
itr->second.ZoneId = pl->GetZoneId();
}
void Guild::SetLeader(uint64 guid)
{
m_LeaderGuid = guid;
ChangeRank(guid, GR_GUILDMASTER);
slot->ChangeRank(GR_GUILDMASTER);
CharacterDatabase.PExecute("UPDATE guild SET leaderguid='%u' WHERE guildid='%u'", GUID_LOPART(guid), m_Id);
CharacterDatabase.PExecute("UPDATE guild SET leaderguid='%u' WHERE guildid='%u'", guid.GetCounter(), m_Id);
}
void Guild::DelMember(uint64 guid, bool isDisbanding)
void Guild::DelMember(ObjectGuid guid, bool isDisbanding)
{
uint32 lowguid = guid.GetCounter();
// guild master can be deleted when loading guild and guid doesn't exist in characters table
// or when he is removed from guild by gm command
if (m_LeaderGuid == guid && !isDisbanding)
{
MemberSlot* oldLeader = NULL;
MemberSlot* best = NULL;
uint64 newLeaderGUID = 0;
ObjectGuid newLeaderGUID;
for (Guild::MemberList::iterator i = members.begin(); i != members.end(); ++i)
{
if (i->first == GUID_LOPART(guid))
if (i->first == lowguid)
{
oldLeader = &(i->second);
continue;
@ -472,7 +509,7 @@ void Guild::DelMember(uint64 guid, bool isDisbanding)
if (!best || best->RankId > i->second.RankId)
{
best = &(i->second);
newLeaderGUID = i->first;
newLeaderGUID = ObjectGuid(HIGHGUID_PLAYER, i->first);
}
}
if (!best)
@ -495,7 +532,7 @@ void Guild::DelMember(uint64 guid, bool isDisbanding)
}
}
members.erase(GUID_LOPART(guid));
members.erase(lowguid);
Player *player = sObjectMgr.GetPlayer(guid);
// If player not online data in data field will be loaded from guild tabs no need to update it !!
@ -505,50 +542,12 @@ void Guild::DelMember(uint64 guid, bool isDisbanding)
player->SetRank(0);
}
CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid));
CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", lowguid);
if (!isDisbanding)
UpdateAccountsNumber();
}
void Guild::ChangeRank(uint64 guid, uint32 newRank)
{
MemberList::iterator itr = members.find(GUID_LOPART(guid));
if (itr != members.end())
itr->second.RankId = newRank;
Player *player = sObjectMgr.GetPlayer(guid);
// If player not online data in data field will be loaded from guild tabs no need to update it !!
if (player)
player->SetRank(newRank);
CharacterDatabase.PExecute( "UPDATE guild_member SET rank='%u' WHERE guid='%u'", newRank, GUID_LOPART(guid) );
}
void Guild::SetPNOTE(uint64 guid,std::string pnote)
{
MemberList::iterator itr = members.find(GUID_LOPART(guid));
if (itr == members.end())
return;
itr->second.Pnote = pnote;
// pnote now can be used for encoding to DB
CharacterDatabase.escape_string(pnote);
CharacterDatabase.PExecute("UPDATE guild_member SET pnote = '%s' WHERE guid = '%u'", pnote.c_str(), itr->first);
}
void Guild::SetOFFNOTE(uint64 guid,std::string offnote)
{
MemberList::iterator itr = members.find(GUID_LOPART(guid));
if (itr == members.end())
return;
itr->second.OFFnote = offnote;
// offnote now can be used for encoding to DB
CharacterDatabase.escape_string(offnote);
CharacterDatabase.PExecute("UPDATE guild_member SET offnote = '%s' WHERE guid = '%u'", offnote.c_str(), itr->first);
}
void Guild::BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language)
{
if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_GCHATSPEAK))
@ -685,15 +684,6 @@ 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);
}
int32 Guild::GetRank(uint32 LowGuid)
{
MemberList::const_iterator itr = members.find(LowGuid);
if (itr == members.end())
return -1;
return itr->second.RankId;
}
void Guild::Disband()
{
BroadcastEvent(GE_DISBANDED);
@ -701,7 +691,7 @@ void Guild::Disband()
while (!members.empty())
{
MemberList::const_iterator itr = members.begin();
DelMember(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER), true);
DelMember(ObjectGuid(HIGHGUID_PLAYER, itr->first), true);
}
CharacterDatabase.BeginTransaction();
@ -813,15 +803,6 @@ void Guild::SetEmblem(uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle
CharacterDatabase.PExecute("UPDATE guild SET EmblemStyle=%u, EmblemColor=%u, BorderStyle=%u, BorderColor=%u, BackgroundColor=%u WHERE guildid = %u", m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor, m_BackgroundColor, m_Id);
}
void Guild::UpdateLogoutTime(uint64 guid)
{
MemberList::iterator itr = members.find(GUID_LOPART(guid));
if (itr == members.end() )
return;
itr->second.LogoutTime = time(NULL);
}
/**
* Return the number of accounts that are in the guild after possible update if required
* A player may have many characters in the guild, but with the same account
@ -909,14 +890,14 @@ void Guild::LoadGuildEventLogFromDB()
}
// Add entry to guild eventlog
void Guild::LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid2, uint8 NewRank)
void Guild::LogGuildEvent(uint8 EventType, ObjectGuid playerGuid1, ObjectGuid playerGuid2, uint8 newRank)
{
GuildEventLogEntry NewEvent;
// Create event
NewEvent.EventType = EventType;
NewEvent.PlayerGuid1 = PlayerGuid1;
NewEvent.PlayerGuid2 = PlayerGuid2;
NewEvent.NewRank = NewRank;
NewEvent.PlayerGuid1 = playerGuid1.GetCounter();
NewEvent.PlayerGuid2 = playerGuid2.GetCounter();
NewEvent.NewRank = newRank;
NewEvent.TimeStamp = uint32(time(NULL));
// Count new LogGuid
m_GuildEventLogNextGuid = (m_GuildEventLogNextGuid + 1) % sWorld.getConfig(CONFIG_UINT32_GUILD_EVENT_LOG_COUNT);