diff options
author | megamage <none@none> | 2009-08-24 20:23:54 -0500 |
---|---|---|
committer | megamage <none@none> | 2009-08-24 20:23:54 -0500 |
commit | aa86640fdfef00e1394d4ea3a6febf7f3e7b775c (patch) | |
tree | 843dfcc8ff6b8e1b85a01cd3a0f36703a3353434 /src/game | |
parent | 0d5028eea43dab5a2a96af5939243bae2e8a5d87 (diff) |
[8408] Optimized guild_member loading during startup. Changed rank ids in guild_rank table.
First start of mangos will take more time then usually, because of guild_rank change. If you want to speed first start up, execute command:
UPDATE guild_rank SET rid = rid - 1;
Signed-off-by: Triply <triply@getmangos.com>
--HG--
branch : trunk
Diffstat (limited to 'src/game')
-rw-r--r-- | src/game/Guild.cpp | 288 | ||||
-rw-r--r-- | src/game/Guild.h | 24 | ||||
-rw-r--r-- | src/game/GuildHandler.cpp | 53 | ||||
-rw-r--r-- | src/game/ObjectMgr.cpp | 5 | ||||
-rw-r--r-- | src/game/SharedDefines.h | 3 | ||||
-rw-r--r-- | src/game/WorldSession.cpp | 2 |
6 files changed, 206 insertions, 169 deletions
diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index 77a667d7f37..b6ac79ad8f3 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -93,22 +93,29 @@ bool Guild::Create(Player* leader, std::string gname) CharacterDatabase.BeginTransaction(); // CharacterDatabase.PExecute("DELETE FROM guild WHERE guildid='%u'", Id); - MAX(guildid)+1 not exist - CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", m_Id); 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', NOW(),'%u','%u','%u','%u','%u','" UI64FMTD "')", m_Id, gname.c_str(), GUID_LOPART(m_LeaderGuid), dbGINFO.c_str(), dbMOTD.c_str(), m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor, m_BackgroundColor, m_GuildBankMoney); CharacterDatabase.CommitTransaction(); - CreateRank(lSession->GetMangosString(LANG_GUILD_MASTER), GR_RIGHT_ALL); - CreateRank(lSession->GetMangosString(LANG_GUILD_OFFICER), GR_RIGHT_ALL); - CreateRank(lSession->GetMangosString(LANG_GUILD_VETERAN), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); - CreateRank(lSession->GetMangosString(LANG_GUILD_MEMBER), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); - CreateRank(lSession->GetMangosString(LANG_GUILD_INITIATE),GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + CreateDefaultGuildRanks(lSession->GetSessionDbLocaleIndex()); return AddMember(m_LeaderGuid, (uint32)GR_GUILDMASTER); } +void Guild::CreateDefaultGuildRanks(int locale_idx) +{ + CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", m_Id); + CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u'", m_Id); + + CreateRank(objmgr.GetMangosString(LANG_GUILD_MASTER, locale_idx), GR_RIGHT_ALL); + CreateRank(objmgr.GetMangosString(LANG_GUILD_OFFICER, locale_idx), GR_RIGHT_ALL); + CreateRank(objmgr.GetMangosString(LANG_GUILD_VETERAN, locale_idx), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + CreateRank(objmgr.GetMangosString(LANG_GUILD_MEMBER, locale_idx), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + CreateRank(objmgr.GetMangosString(LANG_GUILD_INITIATE, locale_idx), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); +} + bool Guild::AddMember(uint64 plGuid, uint32 plRank) { Player* pl = objmgr.GetPlayer(plGuid); @@ -130,8 +137,33 @@ bool Guild::AddMember(uint64 plGuid, uint32 plRank) // fill player data MemberSlot newmember; - if(!FillPlayerData(plGuid, &newmember)) // problems with player data collection - return false; + if(pl) + { + newmember.name = pl->GetName(); + newmember.zoneId = pl->GetZoneId(); + newmember.level = pl->getLevel(); + newmember.Class = pl->getClass(); + } + else + { + QueryResult *result = CharacterDatabase.PQuery("SELECT name,zone,level,class FROM characters WHERE guid = '%u'", GUID_LOPART(plGuid)); + if(!result) + return false; // player doesn't exist + + Field *fields = result->Fetch(); + newmember.name = fields[0].GetCppString(); + newmember.zoneId = fields[1].GetUInt32(); + newmember.level = fields[2].GetUInt32(); + newmember.Class = fields[3].GetUInt32(); + delete result; + if(newmember.level < 1 || newmember.level > STRONG_MAX_LEVEL + || !newmember.zoneId + || 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)); + return false; + } + } newmember.RankId = plRank; newmember.OFFnote = (std::string)""; @@ -180,21 +212,24 @@ void Guild::SetGINFO(std::string ginfo) bool Guild::LoadGuildFromDB(uint32 GuildId) { - if(!LoadRanksFromDB(GuildId)) - return false; - - if(!LoadMembersFromDB(GuildId)) - return false; + //set m_Id in case guild data are broken in DB and Guild will be Disbanded (deleted from DB) + m_Id = GuildId; QueryResult *result = CharacterDatabase.PQuery("SELECT MAX(TabId) FROM guild_bank_tab WHERE guildid='%u'", GuildId); if(result) { Field *fields = result->Fetch(); - m_PurchasedTabs = fields[0].GetUInt8()+1; // Because TabId begins at 0 + m_PurchasedTabs = fields[0].GetUInt8() + 1; // Because TabId begins at 0 + if (m_PurchasedTabs > GUILD_BANK_MAX_TABS) + m_PurchasedTabs = GUILD_BANK_MAX_TABS; delete result; } - else - m_PurchasedTabs = 0; + + if(!LoadRanksFromDB(GuildId)) + return false; + + if(!LoadMembersFromDB(GuildId)) + return false; LoadBankRightsFromDB(GuildId); // Must be after LoadRanksFromDB because it populates rank struct @@ -229,15 +264,27 @@ bool Guild::LoadGuildFromDB(uint32 GuildId) m_CreatedMonth = (dTime/100)%100; m_CreatedYear = (dTime/10000)%10000; - // If the leader does not exist attempt to promote another member - if(!objmgr.GetPlayerAccountIdByGUID(m_LeaderGuid )) + // Repair the structure of guild + // If the guildmaster does not exist attempt to promote another member + // or guildmaster isn't present in guild + int32 GM_rights = GetRank(GUID_LOPART(m_LeaderGuid)); + if(!objmgr.GetPlayerAccountIdByGUID(m_LeaderGuid) || GM_rights == -1) { DelMember(m_LeaderGuid); - // check no members case (disbanded) if(members.empty()) return false; } + 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); + } sLog.outDebug("Guild %u Creation time Loaded day: %u, month: %u, year: %u", GuildId, m_CreatedDay, m_CreatedMonth, m_CreatedYear); @@ -247,51 +294,59 @@ bool Guild::LoadGuildFromDB(uint32 GuildId) bool Guild::LoadRanksFromDB(uint32 GuildId) { Field *fields; - QueryResult *result = CharacterDatabase.PQuery("SELECT rname,rights,BankMoneyPerDay,rid FROM guild_rank WHERE guildid = '%u' ORDER BY rid ASC", GuildId); + // 0 1 2 3 + QueryResult *result = CharacterDatabase.PQuery("SELECT rid,rname,rights,BankMoneyPerDay FROM guild_rank WHERE guildid = '%u' ORDER BY rid ASC", GuildId); if(!result) return false; bool broken_ranks = false; + //GUILD RANKS are sequence starting from 0 = GUILD_MASTER (ALL PRIVILEGES) to max 9 (lowest privileges) + //the lower rank id is considered higher rank - so promotion does rank-- and demotion does rank++ + //between ranks in sequence cannot be gaps - so 0,1,2,4 cannot be + //min ranks count is 5 and max is 10. + do { fields = result->Fetch(); - std::string rankName = fields[0].GetCppString(); - uint32 rankRights = fields[1].GetUInt32(); - uint32 rankMoney = fields[2].GetUInt32(); - uint32 rankRID = fields[3].GetUInt32(); + uint32 rankID = fields[0].GetUInt32(); + std::string rankName = fields[1].GetCppString(); + uint32 rankRights = fields[2].GetUInt32(); + uint32 rankMoney = fields[3].GetUInt32(); - if(rankRID != m_Ranks.size()+1) // guild_rank.rid always store rank+1 + if(rankID != m_Ranks.size()) // guild_rank.ids are sequence 0,1,2,3.. broken_ranks = true; - if(m_Ranks.size() == GR_GUILDMASTER) // prevent loss leader rights + //first rank is guildmaster, prevent loss leader rights + if(m_Ranks.empty()) rankRights |= GR_RIGHT_ALL; AddRank(rankName,rankRights,rankMoney); }while( result->NextRow() ); delete result; - if(m_Ranks.size()==0) // empty rank table? + if(m_Ranks.size() < GUILD_RANKS_MIN_COUNT) // if too few ranks, renew them { - AddRank("Guild Master",GR_RIGHT_ALL,0); - broken_ranks = true; + m_Ranks.clear(); + sLog.outError("Guild %u has broken `guild_rank` data, creating new...",GuildId); + CreateDefaultGuildRanks(0); // 0 is default locale_idx + broken_ranks = false; } - // guild_rank have wrong numbered ranks, repair if(broken_ranks) { - sLog.outError("Guild %u have broken `guild_rank` data, repairing...",GuildId); + sLog.outError("Guild %u has broken `guild_rank` data, repairing...",GuildId); CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", GuildId); - for(size_t i =0; i < m_Ranks.size(); ++i) + for(size_t i = 0; i < m_Ranks.size(); ++i) { // guild_rank.rid always store rank+1 std::string name = m_Ranks[i].name; uint32 rights = m_Ranks[i].rights; CharacterDatabase.escape_string(name); - CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", GuildId, uint32(i+1), name.c_str(), rights); + CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", GuildId, uint32(i), name.c_str(), rights); } CharacterDatabase.CommitTransaction(); } @@ -307,8 +362,9 @@ bool Guild::LoadMembersFromDB(uint32 GuildId) "BankResetTimeTab0, BankRemSlotsTab0, BankResetTimeTab1, BankRemSlotsTab1, BankResetTimeTab2, BankRemSlotsTab2," // 12 13 14 15 16 17 "BankResetTimeTab3, BankRemSlotsTab3, BankResetTimeTab4, BankRemSlotsTab4, BankResetTimeTab5, BankRemSlotsTab5," - // 18 - "logout_time FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid WHERE guildid = '%u'", GuildId); + // 18 19 20 21 22 + "characters.name, characters.level, characters.zone, characters.class, characters.logout_time " + "FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid WHERE guildid = '%u'", GuildId); if(!result) return false; @@ -317,12 +373,11 @@ bool Guild::LoadMembersFromDB(uint32 GuildId) { Field *fields = result->Fetch(); MemberSlot newmember; - newmember.RankId = fields[1].GetUInt32(); uint64 guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - - // Player does not exist - if(!FillPlayerData(guid, &newmember)) - continue; + newmember.RankId = fields[1].GetUInt32(); + //don't allow member to have not existing rank! + if (newmember.RankId >= m_Ranks.size()) + newmember.RankId = GetLowestRank(); newmember.Pnote = fields[2].GetCppString(); newmember.OFFnote = fields[3].GetCppString(); @@ -333,94 +388,45 @@ bool Guild::LoadMembersFromDB(uint32 GuildId) newmember.BankResetTimeTab[i] = fields[6+(2*i)].GetUInt32(); newmember.BankRemSlotsTab[i] = fields[7+(2*i)].GetUInt32(); } - newmember.logout_time = fields[18].GetUInt64(); - members[GUID_LOPART(guid)] = newmember; - }while( result->NextRow() ); - delete result; + newmember.name = fields[18].GetCppString(); + newmember.level = fields[19].GetUInt32(); + newmember.zoneId = fields[20].GetUInt32(); + newmember.Class = fields[21].GetUInt32(); + newmember.logout_time = fields[22].GetUInt64(); - if(members.empty()) - return false; - - return true; -} - -bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot) -{ - std::string plName; - uint32 plLevel; - uint32 plClass; - uint32 plZone; - - Player* pl = objmgr.GetPlayer(guid); - if(pl) - { - plName = pl->GetName(); - plLevel = pl->getLevel(); - plClass = pl->getClass(); - plZone = pl->GetZoneId(); - } - else - { - PCachePlayerInfo pInfo = objmgr.GetPlayerInfoFromCache(GUID_LOPART(guid)); - if(pInfo) + if(newmember.level < 1 || newmember.level > STRONG_MAX_LEVEL) // can be at broken `data` field { - plName = pInfo->sPlayerName; - plClass = pInfo->unClass; - if(plClass<CLASS_WARRIOR||plClass>=MAX_CLASSES) // can be at broken `class` field - { - sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`.",GUID_LOPART(guid)); - return false; - } - plLevel = pInfo->unLevel; - plZone = Player::GetZoneIdFromDB(guid); + sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`, deleting him from guild!",GUID_LOPART(guid)); + CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid)); + continue; } - else - { - QueryResult *result = CharacterDatabase.PQuery("SELECT name,level,zone,class FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); - if(!result) - return false; // player doesn't exist - - Field *fields = result->Fetch(); - - plName = fields[0].GetCppString(); - plLevel = fields[1].GetUInt32(); - plZone = fields[2].GetUInt32(); - plClass = fields[3].GetUInt32(); - delete result; - - if(plLevel<1||plLevel>STRONG_MAX_LEVEL) // can be at broken `data` field + if(!newmember.zoneId) { - sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`.",GUID_LOPART(guid)); - return false; + sLog.outError("Player (GUID: %u) has broken zone-data", GUID_LOPART(guid)); + // 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); } - - if(!plZone) + if(newmember.Class < CLASS_WARRIOR || newmember.Class >= MAX_CLASSES) // can be at broken `class` field { - sLog.outError("Player (GUID: %u) has broken zone-data",GUID_LOPART(guid)); - //here it will also try the same, to get the zone from characters-table, but additional it tries to find - plZone = Player::GetZoneIdFromDB(guid); - //the zone through xy coords.. this is a bit redundant, but - //shouldn't be called often + sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`, deleting him from guild!",GUID_LOPART(guid)); + CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid)); + continue; } - if(plClass<CLASS_WARRIOR||plClass>=MAX_CLASSES) // can be at broken `class` field - { - sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`.",GUID_LOPART(guid)); - return false; - } - } - } + members[GUID_LOPART(guid)] = newmember; + + }while( result->NextRow() ); + delete result; - memslot->name = plName; - memslot->level = plLevel; - memslot->Class = plClass; - memslot->zoneId = plZone; + if(members.empty()) + return false; - return(true); + return true; } -void Guild::LoadPlayerStatsByGuid(uint64 guid) +void Guild::SetMemberStats(uint64 guid) { MemberList::iterator itr = members.find(GUID_LOPART(guid)); if (itr == members.end() ) @@ -429,9 +435,10 @@ void Guild::LoadPlayerStatsByGuid(uint64 guid) 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.name = pl->GetName(); + itr->second.level = pl->getLevel(); + itr->second.Class = pl->getClass(); + itr->second.zoneId = pl->GetZoneId(); } void Guild::SetLeader(uint64 guid) @@ -444,6 +451,8 @@ void Guild::SetLeader(uint64 guid) void Guild::DelMember(uint64 guid, bool isDisbanding) { + //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; @@ -605,21 +614,24 @@ void Guild::BroadcastPacketToRank(WorldPacket *packet, uint32 rankId) void Guild::CreateRank(std::string name_,uint32 rights) { - if(m_Ranks.size() >= GUILD_MAX_RANKS) + if(m_Ranks.size() >= GUILD_RANKS_MAX_COUNT) return; - AddRank(name_,rights,0); + // ranks are sequence 0,1,2,... where 0 means guildmaster + uint32 new_rank_id = m_Ranks.size(); - for (int i = 0; i < m_PurchasedTabs; ++i) - { - CreateBankRightForTab(m_Ranks.size()-1, uint8(i)); - } + AddRank(name_, rights, 0); - // guild_rank.rid always store rank+1 value + //existing records in db should be deleted before calling this procedure and m_PurchasedTabs must be loaded already + for (uint32 i = 0; i < m_PurchasedTabs; ++i) + { + //create bank rights with 0 + CharacterDatabase.PExecute("INSERT INTO guild_bank_right (guildid,TabId,rid) VALUES ('%u','%u','%u')", m_Id, i, new_rank_id); + } // name now can be used for encoding to DB CharacterDatabase.escape_string(name_); - CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", m_Id, (unsigned int)m_Ranks.size(), name_.c_str(), rights ); + CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", m_Id, new_rank_id, name_.c_str(), rights ); } void Guild::AddRank(const std::string& name_,uint32 rights, uint32 money) @@ -632,9 +644,9 @@ void Guild::DelRank() if(m_Ranks.empty()) return; - // guild_rank.rid always store rank+1 value - uint32 rank = m_Ranks.size()-1; - CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE rid>='%u' AND guildid='%u'", (rank+1), m_Id); + // delete lowest guild_rank + uint32 rank = GetLowestRank(); + CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE rid>='%u' AND guildid='%u'", rank, m_Id); m_Ranks.pop_back(); } @@ -1134,20 +1146,6 @@ void Guild::SetGuildBankTabInfo(uint8 TabId, std::string Name, std::string Icon) CharacterDatabase.PExecute("UPDATE guild_bank_tab SET TabName='%s',TabIcon='%s' WHERE guildid='%u' AND TabId='%u'", Name.c_str(), Icon.c_str(), m_Id, uint32(TabId)); } -void Guild::CreateBankRightForTab(uint32 rankId, uint8 TabId) -{ - sLog.outDebug("CreateBankRightForTab. rank: %u, TabId: %u", rankId, uint32(TabId)); - if (rankId >= m_Ranks.size() || TabId >= GUILD_BANK_MAX_TABS) - return; - - m_Ranks[rankId].TabRight[TabId]=0; - m_Ranks[rankId].TabSlotPerDay[TabId]=0; - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u' AND TabId = '%u' AND rid = '%u'", m_Id, uint32(TabId), rankId); - CharacterDatabase.PExecute("INSERT INTO guild_bank_right (guildid,TabId,rid) VALUES ('%u','%u','%u')", m_Id, uint32(TabId), rankId); - CharacterDatabase.CommitTransaction(); -} - uint32 Guild::GetBankRights(uint32 rankId, uint8 TabId) const { if(rankId >= m_Ranks.size() || TabId >= GUILD_BANK_MAX_TABS) @@ -1417,8 +1415,8 @@ void Guild::SetBankRightsAndSlots(uint32 rankId, uint8 TabId, uint32 right, uint right = GUILD_BANK_RIGHT_FULL; } - m_Ranks[rankId].TabSlotPerDay[TabId]=nbSlots; - m_Ranks[rankId].TabRight[TabId]=right; + m_Ranks[rankId].TabSlotPerDay[TabId] = nbSlots; + m_Ranks[rankId].TabRight[TabId] = right; if (db) { diff --git a/src/game/Guild.h b/src/game/Guild.h index f9696493cc6..e17d2e201c8 100644 --- a/src/game/Guild.h +++ b/src/game/Guild.h @@ -28,13 +28,19 @@ class Item; +#define GUILD_RANKS_MIN_COUNT 5 +#define GUILD_RANKS_MAX_COUNT 10 + enum GuildDefaultRanks { + //these ranks can be modified, but they cannot be deleted GR_GUILDMASTER = 0, GR_OFFICER = 1, - //GR_VETERAN = 2, -- not used anywhere and possible incorrect in modified rank list - //GR_MEMBER = 3, - //GR_INITIATE = 4, -- use Guild::GetLowestRank() instead for lowest rank + GR_VETERAN = 2, + GR_MEMBER = 3, + GR_INITIATE = 4, + //When promoting member server does: rank--;! + //When demoting member server does: rank++;! }; enum GuildRankRights @@ -283,6 +289,7 @@ class Guild ~Guild(); bool Create(Player* leader, std::string gname); + void CreateDefaultGuildRanks(int locale_idx); void Disband(); typedef std::map<uint32, MemberSlot> MemberList; @@ -307,8 +314,9 @@ class Guild void SetLeader(uint64 guid); bool AddMember(uint64 plGuid, uint32 plRank); void ChangeRank(uint64 guid, uint32 newRank); - void DelMember(uint64 guid, bool isDisbanding=false); - uint32 GetLowestRank() const { return GetNrRanks()-1; } + void DelMember(uint64 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; } void SetMOTD(std::string motd); void SetGINFO(std::string ginfo); @@ -322,8 +330,7 @@ class Guild bool LoadRanksFromDB(uint32 GuildId); bool LoadMembersFromDB(uint32 GuildId); - bool FillPlayerData(uint64 guid, MemberSlot* memslot); - void LoadPlayerStatsByGuid(uint64 guid); + void SetMemberStats(uint64 guid); void BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL); void BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL); @@ -343,7 +350,7 @@ class Guild void DelRank(); std::string GetRankName(uint32 rankId); uint32 GetRankRights(uint32 rankId); - uint32 GetNrRanks() const { return m_Ranks.size(); } + uint32 GetRanksSize() const { return m_Ranks.size(); } void SetRankName(uint32 rankId, std::string name); void SetRankRights(uint32 rankId, uint32 rights); @@ -394,7 +401,6 @@ class Guild void SetGuildBankTabText(uint8 TabId, std::string text); void SendGuildBankTabText(WorldSession *session, uint8 TabId); void SetGuildBankTabInfo(uint8 TabId, std::string name, std::string icon); - void CreateBankRightForTab(uint32 rankid, uint8 TabId); const GuildBankTab *GetBankTab(uint8 index) { if(index >= m_TabListMap.size()) return NULL; return m_TabListMap[index]; } const uint8 GetPurchasedTabs() const { return m_PurchasedTabs; } uint32 GetBankRights(uint32 rankId, uint8 TabId) const; diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index 70fb1880789..1362366fdcb 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -178,6 +178,13 @@ void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket) return; } + //do not allow to kick player with same or higher rights + if(GetPlayer()->GetRank() >= slot->RankId) + { + SendGuildCommandResult(GUILD_QUIT_S, plName, GUILD_RANK_TOO_HIGH_S); + return; + } + guild->DelMember(plGuid); // Put record into guildlog guild->LogGuildEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), 0); @@ -212,7 +219,7 @@ void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/) WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size data << (uint8)GE_JOINED; - data << (uint8)1; + data << (uint8)1; // strings count data << player->GetName(); guild->BroadcastPacket(&data); @@ -299,14 +306,20 @@ void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket) return; } - if(slot->RankId < 2 || (slot->RankId-1) < GetPlayer()->GetRank()) + //allow to promote only to lower rank than member's rank + //guildmaster's rank = 0 + //GetPlayer()->GetRank() + 1 is highest rank that current player can promote to + if(GetPlayer()->GetRank() + 1 >= slot->RankId) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_RANK_TOO_HIGH_S); return; + } - uint32 newRankId = slot->RankId < guild->GetNrRanks() ? slot->RankId-1 : guild->GetNrRanks()-1; + uint32 newRankId = slot->RankId - 1; //when promoting player, rank is decreased WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size data << (uint8)GE_PROMOTION; - data << (uint8)3; + data << (uint8)3; // strings count data << GetPlayer()->GetName(); data << plName; data << guild->GetRankName(newRankId); @@ -357,16 +370,29 @@ void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket) return; } - if((slot->RankId+1) >= guild->GetNrRanks() || slot->RankId <= GetPlayer()->GetRank()) + //do not allow to demote same or higher rank + if(GetPlayer()->GetRank() >= slot->RankId) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_RANK_TOO_HIGH_S); return; + } - guild->ChangeRank(plGuid, (slot->RankId+1)); + //do not allow to demote lowest rank + if(slot->RankId >= guild->GetLowestRank()) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_ALREADY_LOWEST_RANK_S); + return; + } + + uint32 newRankId = slot->RankId + 1; //when demoting player, rank is increased + + guild->ChangeRank(plGuid, newRankId); // Put record into guildlog - guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), slot->RankId); + guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId); WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size data << (uint8)GE_DEMOTION; - data << (uint8)3; + data << (uint8)3; // strings count data << GetPlayer()->GetName(); data << plName; data << guild->GetRankName(slot->RankId); @@ -406,7 +432,7 @@ void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/) WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size data << (uint8)GE_LEFT; - data << (uint8)1; + data << (uint8)1; // strings count data << plName; guild->BroadcastPacket(&data); @@ -480,7 +506,7 @@ void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket) WorldPacket data(SMSG_GUILD_EVENT, (2+20)); // guess size data << (uint8)GE_LEADER_CHANGED; - data << (uint8)2; + data << (uint8)2; // strings count data << oldLeader->GetName(); data << name.c_str(); guild->BroadcastPacket(&data); @@ -516,7 +542,7 @@ void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket) WorldPacket data(SMSG_GUILD_EVENT, (2+MOTD.size()+1)); data << (uint8)GE_MOTD; - data << (uint8)1; + data << (uint8)1; // strings count data << MOTD; guild->BroadcastPacket(&data); @@ -646,7 +672,7 @@ void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket) guild->SetBankMoneyPerDay(rankId, MoneyPerDay); guild->SetRankName(rankId, rankname); - if(rankId==GR_GUILDMASTER) // prevent loss leader rights + if (rankId == GR_GUILDMASTER) // prevent loss leader rights rights = GR_RIGHT_ALL; guild->SetRankRights(rankId, rights); @@ -675,7 +701,7 @@ void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket) return; } - if(guild->GetNrRanks() >= GUILD_MAX_RANKS) // client not let create more 10 than ranks + if(guild->GetRanksSize() >= GUILD_RANKS_MAX_COUNT) // client not let create more 10 than ranks return; recvPacket >> rankname; @@ -866,6 +892,7 @@ void WorldSession::HandleGuildPermissions( WorldPacket& /* recv_data */ ) // money per day left data << uint32(pGuild->GetMemberMoneyWithdrawRem(GetPlayer()->GetGUIDLow())); data << uint8(pGuild->GetPurchasedTabs()); // tabs count + // why sending all info when not all tabs are purchased??? for(int i = 0; i < GUILD_BANK_MAX_TABS; ++i) { data << uint32(pGuild->GetBankRights(rankId, uint8(i))); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 5e293c3c960..084c7fe0b8d 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3230,6 +3230,11 @@ void ObjectMgr::LoadGuilds() delete result; + //delete unused LogGuid records in guild_eventlog and guild_bank_eventlog table + //you can comment these lines if you don't plan to change CONFIG_GUILD_EVENT_LOG_COUNT and CONFIG_GUILD_BANK_EVENT_LOG_COUNT + CharacterDatabase.PQuery("DELETE FROM guild_eventlog WHERE LogGuid > '%u'", sWorld.getConfig(CONFIG_GUILD_EVENT_LOG_COUNT)); + CharacterDatabase.PQuery("DELETE FROM guild_bank_eventlog WHERE LogGuid > '%u'", sWorld.getConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT)); + sLog.outString(); sLog.outString( ">> Loaded %u guild definitions", count ); } diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 521223ec09d..644a5d03d83 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -2421,7 +2421,8 @@ enum PetDiet #define GUILD_BANK_MAX_LOGS 25 #define GUILD_BANK_MONEY_LOGS_TAB 100 #define GUILD_EVENTLOG_MAX_RECORDS 100 -#define GUILD_MAX_RANKS 10 +#define GUILD_RANKS_MIN_COUNT 5 +#define GUILD_RANKS_MAX_COUNT 10 enum AiReaction { diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 824ba785e48..3ec1675ca49 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -368,7 +368,7 @@ void WorldSession::LogoutPlayer(bool Save) Guild *guild = objmgr.GetGuildById(_player->GetGuildId()); if(guild) { - guild->LoadPlayerStatsByGuid(_player->GetGUID()); + guild->SetMemberStats(_player->GetGUID()); guild->UpdateLogoutTime(_player->GetGUID()); WorldPacket data(SMSG_GUILD_EVENT, (1+1+12+8)); // name limited to 12 in character table. |