Core/Groups: Reimplement group id recycling
This commit is contained in:
@@ -274,6 +274,7 @@ ObjectMgr::ObjectMgr()
|
||||
m_guildId = 1;
|
||||
m_arenaTeamId = 1;
|
||||
m_auctionid = 1;
|
||||
NextGroupStorageId = 1;
|
||||
}
|
||||
|
||||
ObjectMgr::~ObjectMgr()
|
||||
@@ -293,7 +294,7 @@ ObjectMgr::~ObjectMgr()
|
||||
delete[] playerInfo[race][class_].levelInfo;
|
||||
|
||||
// free group and guild objects
|
||||
for (GroupMap::iterator itr = mGroupMap.begin(); itr != mGroupMap.end(); ++itr)
|
||||
for (GroupSet::iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr)
|
||||
delete *itr;
|
||||
|
||||
for (GuildMap::iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr)
|
||||
@@ -311,12 +312,23 @@ ObjectMgr::~ObjectMgr()
|
||||
|
||||
Group * ObjectMgr::GetGroupByGUID(uint32 guid) const
|
||||
{
|
||||
// Make sure given index exists in collection
|
||||
if (guid < uint32(mGroupMap.size()))
|
||||
return mGroupMap[guid];
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Guild collection
|
||||
Guild* ObjectMgr::GetGuildById(uint32 guildId) const
|
||||
{
|
||||
@@ -4000,19 +4012,19 @@ void ObjectMgr::LoadGroups()
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
Group *group = new Group;
|
||||
group->LoadGroupFromDB(fields);
|
||||
AddGroup(group);
|
||||
|
||||
uint32 guid = fields[15].GetUInt32();
|
||||
//
|
||||
uint32 storageId = group->GetStorageId();
|
||||
|
||||
// Groups are pulled in ascending order from db and m_hiGroupGuid is initialized with 1,
|
||||
// so if the group slot is used increment until we find the first free one for a potential new group
|
||||
if (sObjectMgr->GetNextGroupGuid() == guid)
|
||||
sObjectMgr->SetNextGroupGuid(guid + 1);
|
||||
RegisterGroupStorageId(storageId, group);
|
||||
|
||||
if (storageId == NextGroupStorageId)
|
||||
NextGroupStorageId++;
|
||||
|
||||
++count;
|
||||
Group *group = new Group;
|
||||
group->LoadGroupFromDB(guid, result, false);
|
||||
// group load will never be false (we have run consistency sql's before loading)
|
||||
AddGroup(group);
|
||||
}
|
||||
while (result->NextRow());
|
||||
|
||||
@@ -4030,7 +4042,7 @@ void ObjectMgr::LoadGroups()
|
||||
// Delete all members that does not exist
|
||||
CharacterDatabase.Execute(CharacterDatabase.GetPreparedStatement(CHAR_DEL_NONEXISTENT_CHARACTER_GROUP_MEMBERS));
|
||||
|
||||
// 0 1 2 3 4
|
||||
// 0 1 2 3 4
|
||||
QueryResult result = CharacterDatabase.Query("SELECT guid, memberGuid, memberFlags, subgroup, roles FROM group_member ORDER BY guid");
|
||||
if (!result)
|
||||
{
|
||||
@@ -4039,21 +4051,18 @@ void ObjectMgr::LoadGroups()
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 groupLowGuid = 0;
|
||||
uint32 count = 0;
|
||||
Group* group = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
if (groupLowGuid != fields[0].GetUInt32())
|
||||
{
|
||||
groupLowGuid = fields[0].GetUInt32();
|
||||
group = GetGroupByGUID(groupLowGuid);
|
||||
}
|
||||
if (group) // Should never be null
|
||||
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 (lowguid %u)", groupLowGuid);
|
||||
sLog->outError("ObjectMgr::LoadGroups: Consistency failed, can't find group (storage id: %u)", fields[0].GetUInt32());
|
||||
|
||||
++count;
|
||||
}
|
||||
while (result->NextRow());
|
||||
@@ -4062,7 +4071,6 @@ void ObjectMgr::LoadGroups()
|
||||
sLog->outString();
|
||||
}
|
||||
|
||||
|
||||
sLog->outString("Loading Group instance saves...");
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
@@ -4084,7 +4092,7 @@ void ObjectMgr::LoadGroups()
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
Group *group = GetGroupByGUID(fields[0].GetUInt32());
|
||||
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());
|
||||
@@ -6658,10 +6666,9 @@ void ObjectMgr::SetHighestGuids()
|
||||
if (result)
|
||||
m_guildId = (*result)[0].GetUInt32()+1;
|
||||
|
||||
// The next free guid is determined during group loading, here we just preallocate the group holder
|
||||
result = CharacterDatabase.Query("SELECT MAX(guid) FROM groups");
|
||||
if (result)
|
||||
mGroupMap.resize((*result)[0].GetUInt32()+1);
|
||||
mGroupStorage.resize((*result)[0].GetUInt32()+1);
|
||||
}
|
||||
|
||||
uint32 ObjectMgr::GenerateArenaTeamId()
|
||||
@@ -6775,26 +6782,12 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
|
||||
}
|
||||
return m_hiDoGuid++;
|
||||
case HIGHGUID_GROUP:
|
||||
{
|
||||
uint32 newGuid = m_hiGroupGuid;
|
||||
|
||||
for (uint32 i = ++m_hiGroupGuid; i < 0xFFFFFFFF; ++i)
|
||||
{
|
||||
if (!GetGroupByGUID(i))
|
||||
{
|
||||
m_hiGroupGuid = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If newGuid doesn't differ from m_hiGroupGuid after the loop there is no free guid available
|
||||
if (newGuid == m_hiGroupGuid)
|
||||
if (m_hiGroupGuid >= 0xFFFFFFFE)
|
||||
{
|
||||
sLog->outError("Group guid overflow!! Can't continue, shutting down server. ");
|
||||
World::StopNow(ERROR_EXIT_CODE);
|
||||
}
|
||||
return newGuid;
|
||||
}
|
||||
return m_hiGroupGuid++;
|
||||
case HIGHGUID_MO_TRANSPORT:
|
||||
if (m_hiMoTransGuid >= 0xFFFFFFFE)
|
||||
{
|
||||
@@ -9449,17 +9442,43 @@ void ObjectMgr::LoadFactionChangeReputations()
|
||||
sLog->outString();
|
||||
}
|
||||
|
||||
void ObjectMgr::AddGroup(Group* group)
|
||||
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)
|
||||
{
|
||||
uint32 groupGuid = group->GetLowGUID();
|
||||
// Allocate space if necessary.
|
||||
if (groupGuid >= uint32(mGroupMap.size()))
|
||||
mGroupMap.resize(groupGuid + 1);
|
||||
if (storageId >= uint32(mGroupStorage.size()))
|
||||
mGroupStorage.resize(storageId + 1);
|
||||
|
||||
mGroupMap[groupGuid] = group;
|
||||
mGroupStorage[storageId] = group;
|
||||
}
|
||||
|
||||
void ObjectMgr::RemoveGroup(Group* group)
|
||||
void ObjectMgr::FreeGroupStorageId(Group* group)
|
||||
{
|
||||
mGroupMap[group->GetLowGUID()] = NULL;
|
||||
uint32 storageId = group->GetStorageId();
|
||||
|
||||
if (storageId < NextGroupStorageId)
|
||||
NextGroupStorageId = storageId;
|
||||
|
||||
mGroupStorage[storageId] = NULL;
|
||||
}
|
||||
|
||||
@@ -591,7 +591,8 @@ class ObjectMgr
|
||||
public:
|
||||
typedef UNORDERED_MAP<uint32, Item*> ItemMap;
|
||||
|
||||
typedef std::vector<Group *> GroupMap;
|
||||
typedef std::set<Group *> GroupSet;
|
||||
typedef std::vector<Group *> GroupStorage;
|
||||
|
||||
typedef std::vector <Guild *> GuildMap;
|
||||
|
||||
@@ -626,10 +627,14 @@ class ObjectMgr
|
||||
void AddGameobjectInfo(GameObjectInfo *goinfo);
|
||||
|
||||
Group * GetGroupByGUID(uint32 guid) const;
|
||||
void AddGroup(Group* group);
|
||||
void RemoveGroup(Group* group);
|
||||
uint32 GetNextGroupGuid() { return m_hiGroupGuid; };
|
||||
void SetNextGroupGuid(uint32 nextGuid) { m_hiGroupGuid = nextGuid; };
|
||||
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;
|
||||
|
||||
Guild* GetGuildByLeader(uint64 const&guid) const;
|
||||
Guild* GetGuildById(uint32 guildId) const;
|
||||
@@ -1264,6 +1269,10 @@ class ObjectMgr
|
||||
uint32 m_hiGroupGuid;
|
||||
uint32 m_hiMoTransGuid;
|
||||
|
||||
// Database storage IDs
|
||||
|
||||
uint32 NextGroupStorageId;
|
||||
|
||||
QuestMap mQuestTemplates;
|
||||
|
||||
typedef UNORDERED_MAP<uint32, GossipText> GossipTextMap;
|
||||
@@ -1271,7 +1280,8 @@ class ObjectMgr
|
||||
typedef std::set<uint32> TavernAreaTriggerSet;
|
||||
typedef std::set<uint32> GameObjectForQuestSet;
|
||||
|
||||
GroupMap mGroupMap;
|
||||
GroupSet mGroupSet;
|
||||
GroupStorage mGroupStorage;
|
||||
GuildMap mGuildMap;
|
||||
ArenaTeamMap mArenaTeamMap;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user