aboutsummaryrefslogtreecommitdiff
path: root/src/game/ObjectMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/ObjectMgr.cpp')
-rw-r--r--src/game/ObjectMgr.cpp205
1 files changed, 95 insertions, 110 deletions
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index c10674f8bd7..8878d636e37 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -175,6 +175,7 @@ ObjectMgr::ObjectMgr()
m_hiDoGuid = 1;
m_hiCorpseGuid = 1;
m_hiPetNumber = 1;
+ m_hiGroupGuid = 1;
m_ItemTextId = 1;
m_mailid = 1;
m_equipmentSetGuid = 1;
@@ -219,10 +220,10 @@ ObjectMgr::~ObjectMgr()
itr->second.Clear();
}
-Group * ObjectMgr::GetGroupByLeader(const uint64 &guid) const
+Group * ObjectMgr::GetGroupByGUID(const uint64 &guid) const
{
for (GroupSet::const_iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr)
- if ((*itr)->GetLeaderGUID() == guid)
+ if ((*itr)->GetGUID() == guid)
return *itr;
return NULL;
@@ -3414,159 +3415,132 @@ void ObjectMgr::LoadArenaTeams()
void ObjectMgr::LoadGroups()
{
- // -- loading groups --
Group *group = NULL;
- uint64 leaderGuid = 0;
+ Field *fields = NULL;
+ uint64 groupGuid = 0;
uint32 count = 0;
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
- QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty, leaderGuid FROM groups");
+ // Consistency cleaning before load to avoid having to do some checks later
+ // Delete all members that does not exist
+ CharacterDatabase.PExecute("DELETE FROM group_member WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=memberGuid)");
+ // Delete all groups whose leader does not exist
+ CharacterDatabase.PExecute("DELETE FROM groups WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=leaderGuid)");
+ // Delete all groups with less than 2 members
+ CharacterDatabase.PExecute("DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)");
+ // Delete all rows from group_member or group_instance with no group
+ CharacterDatabase.PExecute("DELETE FROM group_member WHERE guid NOT IN (SELECT guid FROM groups)");
+ CharacterDatabase.PExecute("DELETE FROM group_instance WHERE guid NOT IN (SELECT guid FROM groups)");
+
+ // ----------------------- Load Group definitions
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty, guid FROM groups");
if (!result)
{
barGoLink bar(1);
-
bar.step();
sLog.outString();
- sLog.outString(">> Loaded %u group definitions", count);
+ sLog.outString(">> Loaded 0 group definitions");
return;
}
barGoLink bar(result->GetRowCount());
-
do
{
bar.step();
- Field *fields = result->Fetch();
+ fields = result->Fetch();
++count;
- leaderGuid = MAKE_NEW_GUID(fields[14].GetUInt32(),0,HIGHGUID_PLAYER);
-
group = new Group;
- if (!group->LoadGroupFromDB(leaderGuid, result, false))
- {
- group->Disband();
- delete group;
- continue;
- }
+ groupGuid = MAKE_NEW_GUID(fields[15].GetUInt32(),0,HIGHGUID_GROUP);
+ group->LoadGroupFromDB(groupGuid, result, false);
+ // group load will never be false (we have run consistency sql's before loading)
AddGroup(group);
}while (result->NextRow());
sLog.outString();
sLog.outString(">> Loaded %u group definitions", count);
- // -- loading members --
- count = 0;
- group = NULL;
- leaderGuid = 0;
- // 2 3 4 1 1
- result = CharacterDatabase.Query("SELECT memberGuid, memberFlags, subgroup, leaderGuid FROM group_member ORDER BY leaderGuid");
+ // ----------------------- Load member
+ // 0 1 2 3
+ result = CharacterDatabase.Query("SELECT guid, memberGuid, memberFlags, subgroup FROM group_member ORDER BY guid");
if (!result)
{
barGoLink bar2(1);
bar2.step();
- }
- else
- {
- barGoLink bar2(result->GetRowCount());
- do
- {
- bar2.step();
- Field *fields = result->Fetch();
- count++;
- leaderGuid = MAKE_NEW_GUID(fields[3].GetUInt32(), 0, HIGHGUID_PLAYER);
- if (!group || group->GetLeaderGUID() != leaderGuid)
- {
- group = GetGroupByLeader(leaderGuid);
- if (!group)
- {
- sLog.outErrorDb("Incorrect entry in group_member table : no group with leader %d for member %d!", fields[3].GetUInt32(), fields[0].GetUInt32());
- CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid = '%d'", fields[0].GetUInt32());
- continue;
- }
- }
-
- if (!group->LoadMemberFromDB(fields[0].GetUInt32(), fields[1].GetUInt8(), fields[2].GetUInt8()))
- {
- sLog.outErrorDb("Incorrect entry in group_member table : member %d cannot be added to player %d's group!", fields[0].GetUInt32(), fields[3].GetUInt32());
- CharacterDatabase.PExecute("DELETE FROM group_member WHERE memberGuid = '%d'", fields[0].GetUInt32());
- }
- }while (result->NextRow());
+ sLog.outString();
+ sLog.outString(">> Loaded 0 group members");
+ return;
}
- // clean groups
- // TODO: maybe delete from the DB before loading in this case
- for (GroupSet::iterator itr = mGroupSet.begin(); itr != mGroupSet.end();)
+ barGoLink bar2(result->GetRowCount());
+ uint32 groupLowGuid = 0;
+ count = 0;
+ do
{
- if ((*itr)->GetMembersCount() < 2)
+ bar2.step();
+ fields = result->Fetch();
+
+ if (groupLowGuid != fields[0].GetUInt32())
{
- (*itr)->Disband();
- delete *itr;
- mGroupSet.erase(itr++);
+ groupLowGuid = fields[0].GetUInt32();
+ groupGuid = MAKE_NEW_GUID(groupLowGuid, 0, HIGHGUID_GROUP);
+ group = GetGroupByGUID(groupGuid);
+ // group will never be NULL (we have run consistency sql's before loading)
}
- else
- ++itr;
- }
+ group->LoadMemberFromDB(fields[1].GetUInt32(), fields[2].GetUInt8(), fields[3].GetUInt8());
+ ++count;
+ }while (result->NextRow());
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u group members", count);
- // -- loading instances --
- count = 0;
- group = NULL;
- leaderGuid = 0;
- result = CharacterDatabase.Query(
- // 0 1 2 3 4 5
- "SELECT leaderGuid, map, instance, permanent, difficulty, resettime, "
- // 6
- "(SELECT COUNT(*) FROM character_instance WHERE guid = leaderGuid AND instance = group_instance.instance AND permanent = 1 LIMIT 1) "
- "FROM group_instance LEFT JOIN instance ON instance = id ORDER BY leaderGuid"
-);
+
+ // ----------------------- Load instance save
+ // 0 1 2 3 4 5
+ 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)
{
barGoLink bar2(1);
bar2.step();
+ sLog.outString();
+ sLog.outString(">> Loaded 0 group-instance saves");
+ return;
}
- else
- {
- barGoLink bar2(result->GetRowCount());
- do
- {
- bar2.step();
- Field *fields = result->Fetch();
- count++;
- leaderGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
- if (!group || group->GetLeaderGUID() != leaderGuid)
- {
- group = GetGroupByLeader(leaderGuid);
- if (!group)
- {
- sLog.outErrorDb("Incorrect entry in group_instance table : no group with leader %d", fields[0].GetUInt32());
- continue;
- }
- }
- 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 >= (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
- }
+ barGoLink bar3(result->GetRowCount());
+ count = 0;
+ do
+ {
+ bar3.step();
+ fields = result->Fetch();
+ groupGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_GROUP);
+ group = GetGroupByGUID(groupGuid);
+ // group will never be NULL (we have run consistency sql's before loading)
- InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), Difficulty(diff), (time_t)fields[5].GetUInt64(), (fields[6].GetUInt32() == 0), true);
- group->BindToInstance(save, fields[3].GetBool(), true);
- }while (result->NextRow());
- }
+ 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;
+ }
- sLog.outString();
- sLog.outString(">> Loaded %u group-instance binds total", count);
+ uint32 diff = fields[4].GetUInt8();
+ if (diff >= (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 = sInstanceSaveManager.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();
- sLog.outString(">> Loaded %u group members total", count);
+ sLog.outString(">> Loaded %u group-instance saves", count);
}
void ObjectMgr::LoadQuests()
@@ -5995,6 +5969,10 @@ void ObjectMgr::SetHighestGuids()
result = CharacterDatabase.Query("SELECT MAX(guildid) FROM guild");
if (result)
m_guildId = (*result)[0].GetUInt32()+1;
+
+ result = CharacterDatabase.Query("SELECT MAX(guid) FROM groups");
+ if (result)
+ m_hiGroupGuid = (*result)[0].GetUInt32()+1;
}
uint32 ObjectMgr::GenerateArenaTeamId()
@@ -6107,6 +6085,13 @@ 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++;
default:
ASSERT(0);
}