diff options
| -rwxr-xr-x | src/server/game/DungeonFinding/LFGMgr.cpp | 7 | ||||
| -rwxr-xr-x | src/server/game/Entities/Creature/Creature.cpp | 5 | ||||
| -rwxr-xr-x | src/server/game/Entities/GameObject/GameObject.cpp | 3 | ||||
| -rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 5 | ||||
| -rwxr-xr-x | src/server/game/Globals/ObjectMgr.cpp | 209 | ||||
| -rwxr-xr-x | src/server/game/Globals/ObjectMgr.h | 24 | ||||
| -rwxr-xr-x | src/server/game/Groups/Group.cpp | 43 | ||||
| -rwxr-xr-x | src/server/game/Groups/Group.h | 4 | ||||
| -rw-r--r-- | src/server/game/Groups/GroupMgr.cpp | 242 | ||||
| -rw-r--r-- | src/server/game/Groups/GroupMgr.h | 57 | ||||
| -rwxr-xr-x | src/server/game/Server/Protocol/Handlers/GroupHandler.cpp | 3 | ||||
| -rwxr-xr-x | src/server/game/Server/Protocol/Handlers/LFGHandler.cpp | 3 | ||||
| -rwxr-xr-x | src/server/game/World/World.cpp | 3 |
13 files changed, 343 insertions, 265 deletions
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index ae4c7ebe263..c8a3b7a81b0 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -23,6 +23,7 @@ #include "ObjectMgr.h" #include "SocialMgr.h" #include "LFGMgr.h" +#include "GroupMgr.h" #include "LFGScripts.h" #include "LFGGroupData.h" #include "LFGPlayerData.h" @@ -816,7 +817,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) if (IS_GROUP(guid)) { uint32 lowGuid = GUID_LOPART(guid); - if (Group* grp = sObjectMgr->GetGroupByGUID(lowGuid)) + if (Group* grp = sGroupMgr->GetGroupByGUID(lowGuid)) if (grp->isLFGGroup()) { if (!numLfgGroups) @@ -1325,7 +1326,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, const uint64& guid, bool accept) // Create a new group (if needed) LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_GROUP_FOUND); - Group* grp = pProposal->groupLowGuid ? sObjectMgr->GetGroupByGUID(pProposal->groupLowGuid) : NULL; + Group* grp = pProposal->groupLowGuid ? sGroupMgr->GetGroupByGUID(pProposal->groupLowGuid) : NULL; for (LfgPlayerList::const_iterator it = players.begin(); it != players.end(); ++it) { Player* plr = (*it); @@ -1349,7 +1350,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, const uint64& guid, bool accept) grp->ConvertToLFG(); uint64 gguid = grp->GetGUID(); SetState(gguid, LFG_STATE_PROPOSAL); - sObjectMgr->AddGroup(grp); + sGroupMgr->AddGroup(grp); } else if (group != grp) grp->AddMember(plr); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index aaa6b9e7713..9e7aa5871ef 100755 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -21,6 +21,7 @@ #include "WorldPacket.h" #include "World.h" #include "ObjectMgr.h" +#include "GroupMgr.h" #include "SpellMgr.h" #include "Creature.h" #include "QuestDef.h" @@ -480,7 +481,7 @@ void Creature::Update(uint32 diff) if (m_groupLootTimer <= diff) { - Group* group = sObjectMgr->GetGroupByGUID(lootingGroupLowGUID); + Group* group = sGroupMgr->GetGroupByGUID(lootingGroupLowGUID); if (group) group->EndRoll(&loot); m_groupLootTimer = 0; @@ -977,7 +978,7 @@ Group *Creature::GetLootRecipientGroup() const { if (!m_lootRecipientGroup) return NULL; - return sObjectMgr->GetGroupByGUID(m_lootRecipientGroup); + return sGroupMgr->GetGroupByGUID(m_lootRecipientGroup); } void Creature::SetLootRecipient(Unit *unit) diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 2cd9f7140ad..b329123cc0b 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -20,6 +20,7 @@ #include "QuestDef.h" #include "GameObjectAI.h" #include "ObjectMgr.h" +#include "GroupMgr.h" #include "PoolMgr.h" #include "SpellMgr.h" #include "Spell.h" @@ -500,7 +501,7 @@ void GameObject::Update(uint32 diff) { if (m_groupLootTimer <= diff) { - Group* group = sObjectMgr->GetGroupByGUID(lootingGroupLowGUID); + Group* group = sGroupMgr->GetGroupByGUID(lootingGroupLowGUID); if (group) group->EndRoll(&loot); m_groupLootTimer = 0; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ab2173b86fe..a3de9c30321 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -43,6 +43,7 @@ #include "ObjectMgr.h" #include "ArenaTeamMgr.h" #include "GuildMgr.h" +#include "GroupMgr.h" #include "ObjectAccessor.h" #include "CreatureAI.h" #include "Formulas.h" @@ -4736,7 +4737,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC // the player was uninvited already on logout so just remove from group QueryResult resultGroup = CharacterDatabase.PQuery("SELECT guid FROM group_member WHERE memberGuid=%u", guid); if (resultGroup) - if (Group* group = sObjectMgr->GetGroupByStorageId((*resultGroup)[0].GetUInt32())) + if (Group* group = sGroupMgr->GetGroupByDbStoreId((*resultGroup)[0].GetUInt32())) RemoveFromGroup(group, playerguid); // Remove signs from petitions (also remove petitions if owner); @@ -17722,7 +17723,7 @@ void Player::_LoadGroup(PreparedQueryResult result) //QueryResult *result = CharacterDatabase.PQuery("SELECT guid FROM group_member WHERE memberGuid=%u", GetGUIDLow()); if (result) { - if (Group* group = sObjectMgr->GetGroupByStorageId((*result)[0].GetUInt32())) + if (Group* group = sGroupMgr->GetGroupByDbStoreId((*result)[0].GetUInt32())) { uint8 subgroup = group->GetMemberGroup(GetGUID()); SetGroup(group, subgroup); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 870e3cc2790..9a2f078de15 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -23,10 +23,10 @@ #include "ObjectMgr.h" #include "ArenaTeamMgr.h" #include "GuildMgr.h" +#include "GroupMgr.h" #include "SpellMgr.h" #include "UpdateMask.h" #include "World.h" -#include "Group.h" #include "ArenaTeam.h" #include "Transport.h" #include "Language.h" @@ -265,13 +265,11 @@ ObjectMgr::ObjectMgr() m_hiDoGuid = 1; m_hiCorpseGuid = 1; m_hiPetNumber = 1; - m_hiGroupGuid = 1; m_hiMoTransGuid = 1; m_ItemTextId = 1; m_mailid = 1; m_equipmentSetGuid = 1; m_auctionid = 1; - NextGroupStorageId = 1; } ObjectMgr::~ObjectMgr() @@ -290,33 +288,12 @@ ObjectMgr::~ObjectMgr() for (int class_ = 0; class_ < MAX_CLASSES; ++class_) delete[] playerInfo[race][class_].levelInfo; - // free group and guild objects - for (GroupSet::iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr) - delete *itr; - for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) itr->second.Clear(); m_mCacheTrainerSpellMap.clear(); } -Group * ObjectMgr::GetGroupByGUID(uint32 guid) const -{ - for (GroupSet::const_iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr) - if ((*itr)->GetLowGUID() == guid) - return *itr; - - return NULL; -} - -Group* ObjectMgr::GetGroupByStorageId(uint32 storageId) const -{ - if (storageId < mGroupStorage.size()) - return mGroupStorage[storageId]; - - return NULL; -} - void ObjectMgr::AddLocaleString(std::string& s, LocaleConstant locale, StringVector& data) { if (!s.empty()) @@ -3787,140 +3764,6 @@ void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, Play } } -void ObjectMgr::LoadGroups() -{ - { - uint32 oldMSTime = getMSTime(); - - // Delete all groups whose leader does not exist - CharacterDatabase.DirectExecute("DELETE FROM groups WHERE leaderGuid NOT IN (SELECT guid FROM characters)"); - // Delete all groups with less than 2 members - CharacterDatabase.DirectExecute("DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)"); - - // 0 1 2 3 4 5 6 7 8 9 - QueryResult result = CharacterDatabase.PQuery("SELECT leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6" - // 10 11 12 13 14 15 - ", icon7, icon8, groupType, difficulty, raiddifficulty, guid FROM groups ORDER BY guid ASC"); - if (!result) - { - sLog->outString(">> Loaded 0 group definitions. DB table `groups` is empty!"); - sLog->outString(); - return; - } - - uint32 count = 0; - - do - { - Field *fields = result->Fetch(); - Group *group = new Group; - group->LoadGroupFromDB(fields); - AddGroup(group); - - // - uint32 storageId = group->GetStorageId(); - - RegisterGroupStorageId(storageId, group); - - if (storageId == NextGroupStorageId) - NextGroupStorageId++; - - ++count; - } - while (result->NextRow()); - - sLog->outString(">> Loaded %u group definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); - sLog->outString(); - } - - sLog->outString("Loading Group members..."); - { - uint32 oldMSTime = getMSTime(); - - // Delete all rows from group_member or group_instance with no group - CharacterDatabase.DirectExecute("DELETE FROM group_member WHERE guid NOT IN (SELECT guid FROM groups)"); - CharacterDatabase.DirectExecute("DELETE FROM group_instance WHERE guid NOT IN (SELECT guid FROM groups)"); - // Delete all members that does not exist - CharacterDatabase.DirectExecute("DELETE FROM group_member WHERE memberGuid NOT IN (SELECT guid FROM characters)"); - - // 0 1 2 3 4 - QueryResult result = CharacterDatabase.Query("SELECT guid, memberGuid, memberFlags, subgroup, roles FROM group_member ORDER BY guid"); - if (!result) - { - sLog->outString(">> Loaded 0 group members. DB table `group_member` is empty!"); - sLog->outString(); - return; - } - - uint32 count = 0; - - do - { - Field* fields = result->Fetch(); - Group* group = GetGroupByStorageId(fields[0].GetUInt32()); - - if (group) - group->LoadMemberFromDB(fields[1].GetUInt32(), fields[2].GetUInt8(), fields[3].GetUInt8(), fields[4].GetUInt8()); - else - sLog->outError("ObjectMgr::LoadGroups: Consistency failed, can't find group (storage id: %u)", fields[0].GetUInt32()); - - ++count; - } - while (result->NextRow()); - - sLog->outString(">> Loaded %u group members in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); - sLog->outString(); - } - - sLog->outString("Loading Group instance saves..."); - { - uint32 oldMSTime = getMSTime(); - - // 0 1 2 3 4 5 - QueryResult result = CharacterDatabase.Query("SELECT guid, map, instance, permanent, difficulty, resettime, " - // 6 - "(SELECT COUNT(1) FROM groups JOIN character_instance ON leaderGuid = groups.guid WHERE instance = group_instance.instance AND permanent = 1 LIMIT 1) " - "FROM group_instance LEFT JOIN instance ON instance = id ORDER BY guid"); - - if (!result) - { - sLog->outString(); - sLog->outString(">> Loaded 0 group-instance saves. DB table `group_instance` is empty!"); - return; - } - - uint32 count = 0; - do - { - Field *fields = result->Fetch(); - Group *group = GetGroupByStorageId(fields[0].GetUInt32()); - // group will never be NULL (we have run consistency sql's before loading) - - MapEntry const* mapEntry = sMapStore.LookupEntry(fields[1].GetUInt32()); - if (!mapEntry || !mapEntry->IsDungeon()) - { - sLog->outErrorDb("Incorrect entry in group_instance table : no dungeon map %d", fields[1].GetUInt32()); - continue; - } - - uint32 diff = fields[4].GetUInt8(); - if (diff >= uint32(mapEntry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY)) - { - sLog->outErrorDb("Wrong dungeon difficulty use in group_instance table: %d", diff + 1); - diff = 0; // default for both difficaly types - } - - InstanceSave *save = sInstanceSaveMgr->AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), Difficulty(diff), time_t(fields[5].GetUInt64()), fields[6].GetBool(), true); - group->BindToInstance(save, fields[3].GetBool(), true); - ++count; - } - while (result->NextRow()); - - sLog->outString(">> Loaded %u group-instance saves in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); - sLog->outString(); - } -} - void ObjectMgr::LoadQuests() { uint32 oldMSTime = getMSTime(); @@ -6474,7 +6317,7 @@ void ObjectMgr::SetHighestGuids() result = CharacterDatabase.Query("SELECT MAX(guid) FROM groups"); if (result) - mGroupStorage.resize((*result)[0].GetUInt32()+1); + sGroupMgr->SetGroupDbStoreSize((*result)[0].GetUInt32()+1); } @@ -6569,13 +6412,6 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) World::StopNow(ERROR_EXIT_CODE); } return m_hiDoGuid++; - case HIGHGUID_GROUP: - if (m_hiGroupGuid >= 0xFFFFFFFE) - { - sLog->outError("Group guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_hiGroupGuid++; case HIGHGUID_MO_TRANSPORT: if (m_hiMoTransGuid >= 0xFFFFFFFE) { @@ -9221,47 +9057,6 @@ void ObjectMgr::LoadFactionChangeReputations() sLog->outString(); } -uint32 ObjectMgr::GenerateNewGroupStorageId() -{ - uint32 newStorageId = NextGroupStorageId; - - for (uint32 i = ++NextGroupStorageId; i < 0xFFFFFFFF; ++i) - { - if ((i < mGroupStorage.size() && mGroupStorage[i] == NULL) || i >= mGroupStorage.size()) - { - NextGroupStorageId = i; - break; - } - } - - if (newStorageId == NextGroupStorageId) - { - sLog->outError("Group storage ID overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - - return newStorageId; -} - -void ObjectMgr::RegisterGroupStorageId(uint32 storageId, Group* group) -{ - // Allocate space if necessary. - if (storageId >= uint32(mGroupStorage.size())) - mGroupStorage.resize(storageId + 1); - - mGroupStorage[storageId] = group; -} - -void ObjectMgr::FreeGroupStorageId(Group* group) -{ - uint32 storageId = group->GetStorageId(); - - if (storageId < NextGroupStorageId) - NextGroupStorageId = storageId; - - mGroupStorage[storageId] = NULL; -} - GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry) { GameObjectTemplateContainer::const_iterator itr = GameObjectTemplateStore.find(entry); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index dfa1494199a..4ed3a598c7e 100755 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -43,7 +43,6 @@ #include "ConditionMgr.h" #include <functional> -class Group; class Item; // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform @@ -605,9 +604,6 @@ class ObjectMgr public: typedef UNORDERED_MAP<uint32, Item*> ItemMap; - typedef std::set<Group *> GroupSet; - typedef std::vector<Group *> GroupStorage; - typedef UNORDERED_MAP<uint32, Quest*> QuestMap; typedef UNORDERED_MAP<uint32, AreaTrigger> AreaTriggerMap; @@ -637,17 +633,6 @@ class ObjectMgr void LoadGameObjectTemplate(); void AddGameobjectInfo(GameObjectTemplate *goinfo); - Group * GetGroupByGUID(uint32 guid) const; - void AddGroup(Group* group) { mGroupSet.insert(group); } - void RemoveGroup(Group* group) { mGroupSet.erase(group); } - - uint32 GenerateNewGroupStorageId(); - void RegisterGroupStorageId(uint32 storageId, Group* group); - void FreeGroupStorageId(Group* group); - void SetNextGroupStorageId(uint32 storageId) { NextGroupStorageId = storageId; }; - Group* GetGroupByStorageId(uint32 storageId) const; - - CreatureTemplate const* GetCreatureTemplate(uint32 entry); CreatureTemplateContainer const* GetCreatureTemplates() { return &CreatureTemplateStore; } CreatureModelInfo const* GetCreatureModelInfo(uint32 modelId); @@ -828,7 +813,6 @@ class ObjectMgr return NULL; } - void LoadGroups(); void LoadQuests(); void LoadQuestRelations() { @@ -1261,13 +1245,8 @@ class ObjectMgr uint32 m_hiGoGuid; uint32 m_hiDoGuid; uint32 m_hiCorpseGuid; - uint32 m_hiGroupGuid; uint32 m_hiMoTransGuid; - // Database storage IDs - - uint32 NextGroupStorageId; - QuestMap mQuestTemplates; typedef UNORDERED_MAP<uint32, GossipText> GossipTextMap; @@ -1275,9 +1254,6 @@ class ObjectMgr typedef std::set<uint32> TavernAreaTriggerSet; typedef std::set<uint32> GameObjectForQuestSet; - GroupSet mGroupSet; - GroupStorage mGroupStorage; - QuestAreaTriggerMap mQuestAreaTriggerMap; TavernAreaTriggerSet mTavernAreaTriggerSet; GameObjectForQuestSet mGameObjectForQuestSet; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 0eb65395e91..d4f0b6a2d04 100755 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -23,6 +23,7 @@ #include "Player.h" #include "World.h" #include "ObjectMgr.h" +#include "GroupMgr.h" #include "Group.h" #include "Formulas.h" #include "ObjectAccessor.h" @@ -57,7 +58,7 @@ Loot* Roll::getLoot() Group::Group() : m_leaderGuid(0), m_leaderName(""), m_groupType(GROUPTYPE_NORMAL), m_dungeonDifficulty(DUNGEON_DIFFICULTY_NORMAL), m_raidDifficulty(RAID_DIFFICULTY_10MAN_NORMAL), m_bgGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(0), -m_subGroupsCounts(NULL), m_guid(0), m_counter(0), m_maxEnchantingLevel(0), m_storageId(0) +m_subGroupsCounts(NULL), m_guid(0), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0) { for (uint8 i = 0; i < TARGETICONCOUNT; ++i) m_targetIcons[i] = 0; @@ -95,7 +96,7 @@ Group::~Group() bool Group::Create(Player *leader) { uint64 leaderGuid = leader->GetGUID(); - uint32 lowguid = sObjectMgr->GenerateLowGuid(HIGHGUID_GROUP); + uint32 lowguid = sGroupMgr->GenerateGroupId(); m_guid = MAKE_NEW_GUID(lowguid, 0, HIGHGUID_GROUP); m_leaderGuid = leaderGuid; @@ -118,14 +119,14 @@ bool Group::Create(Player *leader) m_dungeonDifficulty = leader->GetDungeonDifficulty(); m_raidDifficulty = leader->GetRaidDifficulty(); - m_storageId = sObjectMgr->GenerateNewGroupStorageId(); + m_dbStoreId = sGroupMgr->GenerateNewGroupDbStoreId(); - sObjectMgr->RegisterGroupStorageId(m_storageId, this); + sGroupMgr->RegisterGroupDbStoreId(m_dbStoreId, this); // store group in database CharacterDatabase.PExecute("INSERT INTO groups (guid, leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty) " "VALUES ('%u', '%u', '%u', '%u', '%u', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '" UI64FMTD "', '%u', '%u', '%u')", - m_storageId, GUID_LOPART(m_leaderGuid), uint32(m_lootMethod), + m_dbStoreId, GUID_LOPART(m_leaderGuid), uint32(m_lootMethod), GUID_LOPART(m_looterGuid), uint32(m_lootThreshold), m_targetIcons[0], m_targetIcons[1], m_targetIcons[2], m_targetIcons[3], m_targetIcons[4], m_targetIcons[5], m_targetIcons[6], m_targetIcons[7], uint8(m_groupType), uint32(m_dungeonDifficulty), m_raidDifficulty); @@ -141,8 +142,8 @@ bool Group::Create(Player *leader) void Group::LoadGroupFromDB(Field *fields) { - m_storageId = fields[15].GetUInt32(); - m_guid = MAKE_NEW_GUID(sObjectMgr->GenerateLowGuid(HIGHGUID_GROUP), 0, HIGHGUID_GROUP); + m_dbStoreId = fields[15].GetUInt32(); + m_guid = MAKE_NEW_GUID(sGroupMgr->GenerateGroupId(), 0, HIGHGUID_GROUP); m_leaderGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); // group leader not exist @@ -200,7 +201,7 @@ void Group::ConvertToLFG() m_groupType = GroupType(m_groupType | GROUPTYPE_LFG | GROUPTYPE_UNK1); m_lootMethod = NEED_BEFORE_GREED; if (!isBGGroup()) - CharacterDatabase.PExecute("UPDATE groups SET groupType='%u' WHERE guid='%u'", uint8(m_groupType), m_storageId); + CharacterDatabase.PExecute("UPDATE groups SET groupType='%u' WHERE guid='%u'", uint8(m_groupType), m_dbStoreId); SendUpdate(); } @@ -211,7 +212,7 @@ void Group::ConvertToRaid() _initRaidSubGroupsCounter(); if (!isBGGroup()) - CharacterDatabase.PExecute("UPDATE groups SET groupType='%u' WHERE guid='%u'", uint8(m_groupType), m_storageId); + CharacterDatabase.PExecute("UPDATE groups SET groupType='%u' WHERE guid='%u'", uint8(m_groupType), m_dbStoreId); SendUpdate(); // update quest related GO states (quest activity dependent from raid membership) @@ -344,7 +345,7 @@ bool Group::AddMember(Player *player) // insert into the table if we're not a battleground group if (!isBGGroup()) CharacterDatabase.PExecute("INSERT INTO group_member (guid, memberGuid, memberFlags, subgroup, roles) VALUES(%u, %u, %u, %u, %u)", - m_storageId, GUID_LOPART(member.guid), member.flags, member.group, member.roles); + m_dbStoreId, GUID_LOPART(member.guid), member.flags, member.group, member.roles); SendUpdate(); sScriptMgr->OnGroupAddMember(this, player->GetGUID()); @@ -531,13 +532,13 @@ void Group::ChangeLeader(const uint64 &guid) // Same in the database CharacterDatabase.PExecute("DELETE FROM group_instance WHERE guid=%u AND (permanent = 1 OR instance IN (SELECT instance FROM character_instance WHERE guid = '%u'))", - m_storageId, player->GetGUIDLow()); + m_dbStoreId, player->GetGUIDLow()); // Copy the permanent binds from the new leader to the group Player::ConvertInstancesToGroup(player, this, true); // update the group leader - CharacterDatabase.PExecute("UPDATE groups SET leaderGuid='%u' WHERE guid='%u'", player->GetGUIDLow(), m_storageId); + CharacterDatabase.PExecute("UPDATE groups SET leaderGuid='%u' WHERE guid='%u'", player->GetGUIDLow(), m_dbStoreId); } m_leaderGuid = player->GetGUID(); @@ -610,16 +611,16 @@ void Group::Disband(bool hideDestroy /* = false */) if (!isBGGroup()) { SQLTransaction trans = CharacterDatabase.BeginTransaction(); - trans->PAppend("DELETE FROM groups WHERE guid = %u", m_storageId); - trans->PAppend("DELETE FROM group_member WHERE guid = %u", m_storageId); + trans->PAppend("DELETE FROM groups WHERE guid = %u", m_dbStoreId); + trans->PAppend("DELETE FROM group_member WHERE guid = %u", m_dbStoreId); CharacterDatabase.CommitTransaction(trans); ResetInstances(INSTANCE_RESET_GROUP_DISBAND, false, NULL); ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, NULL); - sObjectMgr->FreeGroupStorageId(this); + sGroupMgr->FreeGroupDbStoreId(this); } - sObjectMgr->RemoveGroup(this); + sGroupMgr->RemoveGroup(this); delete this; } @@ -1538,7 +1539,7 @@ void Group::SetDungeonDifficulty(Difficulty difficulty) { m_dungeonDifficulty = difficulty; if (!isBGGroup()) - CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE guid ='%u'", m_dungeonDifficulty, m_storageId); + CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE guid ='%u'", m_dungeonDifficulty, m_dbStoreId); for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) { @@ -1555,7 +1556,7 @@ void Group::SetRaidDifficulty(Difficulty difficulty) { m_raidDifficulty = difficulty; if (!isBGGroup()) - CharacterDatabase.PExecute("UPDATE groups SET raiddifficulty = %u WHERE guid ='%u'", m_raidDifficulty, m_storageId); + CharacterDatabase.PExecute("UPDATE groups SET raiddifficulty = %u WHERE guid ='%u'", m_raidDifficulty, m_dbStoreId); for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) { @@ -1696,7 +1697,7 @@ InstanceGroupBind* Group::BindToInstance(InstanceSave *save, bool permanent, boo InstanceGroupBind& bind = m_boundInstances[save->GetDifficulty()][save->GetMapId()]; if (!load && (!bind.save || permanent != bind.perm || save != bind.save)) - CharacterDatabase.PExecute("REPLACE INTO group_instance (guid, instance, permanent) VALUES (%u, %u, %u)", m_storageId, save->GetInstanceId(), permanent); + CharacterDatabase.PExecute("REPLACE INTO group_instance (guid, instance, permanent) VALUES (%u, %u, %u)", m_dbStoreId, save->GetInstanceId(), permanent); if (bind.save != save) { @@ -1709,7 +1710,7 @@ InstanceGroupBind* Group::BindToInstance(InstanceSave *save, bool permanent, boo bind.perm = permanent; if (!load) sLog->outDebug(LOG_FILTER_MAPS, "Group::BindToInstance: Group (guid: %u, storage id: %u) is now bound to map %d, instance %d, difficulty %d", - GUID_LOPART(GetGUID()), m_storageId, save->GetMapId(), save->GetInstanceId(), save->GetDifficulty()); + GUID_LOPART(GetGUID()), m_dbStoreId, save->GetMapId(), save->GetInstanceId(), save->GetDifficulty()); return &bind; } @@ -1720,7 +1721,7 @@ void Group::UnbindInstance(uint32 mapid, uint8 difficulty, bool unload) if (itr != m_boundInstances[difficulty].end()) { if (!unload) - CharacterDatabase.PExecute("DELETE FROM group_instance WHERE guid=%u AND instance=%u", m_storageId, itr->second.save->GetInstanceId()); + CharacterDatabase.PExecute("DELETE FROM group_instance WHERE guid=%u AND instance=%u", m_dbStoreId, itr->second.save->GetInstanceId()); itr->second.save->RemoveGroup(this); // save can become invalid m_boundInstances[difficulty].erase(itr); } diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 1387b6eca35..de45aa8098a 100755 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -213,7 +213,7 @@ class Group const uint64& GetLooterGuid() const; ItemQualities GetLootThreshold() const; - uint32 GetStorageId() { return m_storageId; }; + uint32 GetDbStoreId() { return m_dbStoreId; }; // member manipulation methods bool IsMember(const uint64& guid) const; @@ -329,6 +329,6 @@ class Group uint64 m_guid; uint32 m_counter; // used only in SMSG_GROUP_LIST uint32 m_maxEnchantingLevel; - uint32 m_storageId; // Represents the ID used in database (Can be reused by other groups if group was disbanded) + uint32 m_dbStoreId; // Represents the ID used in database (Can be reused by other groups if group was disbanded) }; #endif diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp new file mode 100644 index 00000000000..47acfe063bb --- /dev/null +++ b/src/server/game/Groups/GroupMgr.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Common.h" +#include "GroupMgr.h" +#include "InstanceSaveMgr.h" + +GroupMgr::GroupMgr() +{ +} + +GroupMgr::~GroupMgr() +{ + for (GroupContainer::iterator itr = GroupStore.begin(); itr != GroupStore.end(); ++itr) + delete itr->second; +} + +uint32 GroupMgr::GenerateNewGroupDbStoreId() +{ + uint32 newStorageId = NextGroupDbStoreId; + + for (uint32 i = ++NextGroupDbStoreId; i < 0xFFFFFFFF; ++i) + { + if ((i < GroupDbStore.size() && GroupDbStore[i] == NULL) || i >= GroupDbStore.size()) + { + NextGroupDbStoreId = i; + break; + } + } + + if (newStorageId == NextGroupDbStoreId) + { + sLog->outError("Group storage ID overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + + return newStorageId; +} + +void GroupMgr::RegisterGroupDbStoreId(uint32 storageId, Group* group) +{ + // Allocate space if necessary. + if (storageId >= uint32(GroupDbStore.size())) + GroupDbStore.resize(storageId + 1); + + GroupDbStore[storageId] = group; +} + +void GroupMgr::FreeGroupDbStoreId(Group* group) +{ + uint32 storageId = group->GetDbStoreId(); + + if (storageId < NextGroupDbStoreId) + NextGroupDbStoreId = storageId; + + GroupDbStore[storageId] = NULL; +} + +Group* GroupMgr::GetGroupByDbStoreId(uint32 storageId) const +{ + if (storageId < GroupDbStore.size()) + return GroupDbStore[storageId]; + + return NULL; +} + +uint32 GroupMgr::GenerateGroupId() +{ + if (NextGroupId >= 0xFFFFFFFE) + { + sLog->outError("Group guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return NextGroupId++; +} + +Group* GroupMgr::GetGroupByGUID(uint32 groupId) const +{ + GroupContainer::const_iterator itr = GroupStore.find(groupId); + if (itr != GroupStore.end()) + return itr->second; + + return NULL; +} + +void GroupMgr::AddGroup(Group* group) +{ + GroupStore[group->GetGUID()] = group; +} + +void GroupMgr::RemoveGroup(Group* group) +{ + GroupStore.erase(group->GetGUID()); +} + +void GroupMgr::LoadGroups() +{ + { + uint32 oldMSTime = getMSTime(); + + // Delete all groups whose leader does not exist + CharacterDatabase.DirectExecute("DELETE FROM groups WHERE leaderGuid NOT IN (SELECT guid FROM characters)"); + // Delete all groups with less than 2 members + CharacterDatabase.DirectExecute("DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)"); + + // 0 1 2 3 4 5 6 7 8 9 + QueryResult result = CharacterDatabase.PQuery("SELECT leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6" + // 10 11 12 13 14 15 + ", icon7, icon8, groupType, difficulty, raiddifficulty, guid FROM groups ORDER BY guid ASC"); + if (!result) + { + sLog->outString(">> Loaded 0 group definitions. DB table `groups` is empty!"); + sLog->outString(); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + Group* group = new Group; + group->LoadGroupFromDB(fields); + AddGroup(group); + + // Get the ID used for storing the group in the database and register it in the pool. + uint32 storageId = group->GetDbStoreId(); + + RegisterGroupDbStoreId(storageId, group); + + // Increase the next available storage ID + if (storageId == NextGroupDbStoreId) + NextGroupDbStoreId++; + + ++count; + } + while (result->NextRow()); + + sLog->outString(">> Loaded %u group definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(); + } + + sLog->outString("Loading Group members..."); + { + uint32 oldMSTime = getMSTime(); + + // Delete all rows from group_member or group_instance with no group + CharacterDatabase.DirectExecute("DELETE FROM group_member WHERE guid NOT IN (SELECT guid FROM groups)"); + CharacterDatabase.DirectExecute("DELETE FROM group_instance WHERE guid NOT IN (SELECT guid FROM groups)"); + // Delete all members that does not exist + CharacterDatabase.DirectExecute("DELETE FROM group_member WHERE memberGuid NOT IN (SELECT guid FROM characters)"); + + // 0 1 2 3 4 + QueryResult result = CharacterDatabase.Query("SELECT guid, memberGuid, memberFlags, subgroup, roles FROM group_member ORDER BY guid"); + if (!result) + { + sLog->outString(">> Loaded 0 group members. DB table `group_member` is empty!"); + sLog->outString(); + return; + } + + uint32 count = 0; + + do + { + Field* fields = result->Fetch(); + Group* group = GetGroupByDbStoreId(fields[0].GetUInt32()); + + if (group) + group->LoadMemberFromDB(fields[1].GetUInt32(), fields[2].GetUInt8(), fields[3].GetUInt8(), fields[4].GetUInt8()); + else + sLog->outError("GroupMgr::LoadGroups: Consistency failed, can't find group (storage id: %u)", fields[0].GetUInt32()); + + ++count; + } + while (result->NextRow()); + + sLog->outString(">> Loaded %u group members in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(); + } + + sLog->outString("Loading Group instance saves..."); + { + uint32 oldMSTime = getMSTime(); + + // 0 1 2 3 4 5 + QueryResult result = CharacterDatabase.Query("SELECT guid, map, instance, permanent, difficulty, resettime, " + // 6 + "(SELECT COUNT(1) FROM groups JOIN character_instance ON leaderGuid = groups.guid WHERE instance = group_instance.instance AND permanent = 1 LIMIT 1) " + "FROM group_instance LEFT JOIN instance ON instance = id ORDER BY guid"); + + if (!result) + { + sLog->outString(">> Loaded 0 group-instance saves. DB table `group_instance` is empty!"); + sLog->outString(); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + Group* group = GetGroupByDbStoreId(fields[0].GetUInt32()); + // group will never be NULL (we have run consistency sql's before loading) + + MapEntry const* mapEntry = sMapStore.LookupEntry(fields[1].GetUInt32()); + if (!mapEntry || !mapEntry->IsDungeon()) + { + sLog->outErrorDb("Incorrect entry in group_instance table : no dungeon map %d", fields[1].GetUInt32()); + continue; + } + + uint32 diff = fields[4].GetUInt8(); + if (diff >= uint32(mapEntry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY)) + { + sLog->outErrorDb("Wrong dungeon difficulty use in group_instance table: %d", diff + 1); + diff = 0; // default for both difficaly types + } + + InstanceSave* save = sInstanceSaveMgr->AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), Difficulty(diff), time_t(fields[5].GetUInt64()), fields[6].GetBool(), true); + group->BindToInstance(save, fields[3].GetBool(), true); + ++count; + } + while (result->NextRow()); + + sLog->outString(">> Loaded %u group-instance saves in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(); + } +} diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h new file mode 100644 index 00000000000..5950bb65246 --- /dev/null +++ b/src/server/game/Groups/GroupMgr.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _GROUPMGR_H +#define _GROUPMGR_H + +#include "Group.h" + +class GroupMgr +{ + friend class ACE_Singleton<GroupMgr, ACE_Null_Mutex>; + GroupMgr(); + ~GroupMgr(); + +public: + typedef std::map<uint32, Group *> GroupContainer; + typedef std::vector<Group *> GroupDbContainer; + + Group* GetGroupByGUID(uint32 guid) const; + + uint32 GenerateNewGroupDbStoreId(); + void RegisterGroupDbStoreId(uint32 storageId, Group* group); + void FreeGroupDbStoreId(Group* group); + void SetNextGroupDbStoreId(uint32 storageId) { NextGroupDbStoreId = storageId; }; + Group* GetGroupByDbStoreId(uint32 storageId) const; + void SetGroupDbStoreSize(uint32 newSize) { GroupDbStore.resize(newSize); } + + void LoadGroups(); + uint32 GenerateGroupId(); + void AddGroup(Group* group); + void RemoveGroup(Group* group); + + +protected: + uint32 NextGroupId; + uint32 NextGroupDbStoreId; + GroupContainer GroupStore; + GroupDbContainer GroupDbStore; +}; + +#define sGroupMgr ACE_Singleton<GroupMgr, ACE_Null_Mutex>::instance() + +#endif diff --git a/src/server/game/Server/Protocol/Handlers/GroupHandler.cpp b/src/server/game/Server/Protocol/Handlers/GroupHandler.cpp index c66ea546cb7..af76ef53f47 100755 --- a/src/server/game/Server/Protocol/Handlers/GroupHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/GroupHandler.cpp @@ -24,6 +24,7 @@ #include "WorldSession.h" #include "World.h" #include "ObjectMgr.h" +#include "GroupMgr.h" #include "Player.h" #include "Group.h" #include "SocialMgr.h" @@ -233,7 +234,7 @@ void WorldSession::HandleGroupAcceptOpcode(WorldPacket& recv_data) ASSERT(leader); group->RemoveInvite(leader); group->Create(leader); - sObjectMgr->AddGroup(group); + sGroupMgr->AddGroup(group); } // Everything is fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!! diff --git a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp index b1a7ee6e264..56de97aaddc 100755 --- a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp @@ -22,6 +22,7 @@ #include "Group.h" #include "LFGMgr.h" #include "ObjectMgr.h" +#include "GroupMgr.h" #include "InstanceScript.h" void BuildPlayerLockDungeonBlock(WorldPacket& data, const LfgLockMap& lock) @@ -554,7 +555,7 @@ void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal* p uint32 dungeonId = pProp->dungeonId; bool isSameDungeon = false; bool isContinue = false; - Group* grp = dLowGuid ? sObjectMgr->GetGroupByGUID(dLowGuid) : NULL; + Group* grp = dLowGuid ? sGroupMgr->GetGroupByGUID(dLowGuid) : NULL; uint32 completedEncounters = 0; if (grp) { diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 8c026bdb238..143c1cc3480 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -42,6 +42,7 @@ #include "TicketMgr.h" #include "CreatureEventAIMgr.h" #include "SpellMgr.h" +#include "GroupMgr.h" #include "Chat.h" #include "DBCStores.h" #include "LootMgr.h" @@ -1523,7 +1524,7 @@ void World::SetInitialWorldSettings() sArenaTeamMgr->LoadArenaTeams(); sLog->outString("Loading Groups..."); - sObjectMgr->LoadGroups(); + sGroupMgr->LoadGroups(); sLog->outString("Loading ReservedNames..."); sObjectMgr->LoadReservedPlayersNames(); |
