aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorleak <leakzx@googlemail.com>2011-02-26 19:49:56 +0100
committerleak <leakzx@googlemail.com>2011-02-27 00:55:45 +0100
commitaa2455b586f5db22a1fa2f844a182c7e5478aee8 (patch)
treed3dba2671935252a60e7c36cf0a42cde443e6172 /src
parent3ac80ee3a48223f25a2a633130de177ffcd5df11 (diff)
Core/Groups: Reimplement group id recycling
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Battlegrounds/Battleground.cpp1
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.cpp119
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.h22
-rwxr-xr-xsrc/server/game/Groups/Group.cpp78
-rwxr-xr-xsrc/server/game/Groups/Group.h7
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.cpp2
6 files changed, 119 insertions, 110 deletions
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 5791b504d6e..e0844cdcccd 100755
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -1203,7 +1203,6 @@ void Battleground::AddOrSetPlayerToCorrectBgGroup(Player *player, uint32 team)
group = new Group;
SetBgRaid(team, group);
group->Create(player);
- sObjectMgr->AddGroup(group);
}
else // raid already exist
{
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 815f1cbc770..691c647862a 100755
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -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;
}
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 2a588c40f61..a593d369799 100755
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -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;
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index a118e1c1837..992be9b0308 100755
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -57,7 +57,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_subGroupsCounts(NULL), m_guid(0), m_counter(0), m_maxEnchantingLevel(0), m_storageId(0)
{
for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
m_targetIcons[i] = 0;
@@ -96,6 +96,7 @@ bool Group::Create(Player *leader)
{
uint64 leaderGuid = leader->GetGUID();
uint32 lowguid = sObjectMgr->GenerateLowGuid(HIGHGUID_GROUP);
+
m_guid = MAKE_NEW_GUID(lowguid, 0, HIGHGUID_GROUP);
m_leaderGuid = leaderGuid;
m_leaderName = leader->GetName();
@@ -117,17 +118,20 @@ bool Group::Create(Player *leader)
m_dungeonDifficulty = leader->GetDungeonDifficulty();
m_raidDifficulty = leader->GetRaidDifficulty();
+ m_storageId = sObjectMgr->GenerateNewGroupStorageId();
+
+ sObjectMgr->RegisterGroupStorageId(m_storageId, 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')",
- lowguid, GUID_LOPART(m_leaderGuid), uint32(m_lootMethod),
+ m_storageId, 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);
ASSERT(AddMember(leader)); // If the leader can't be added to a new group because it appears full, something is clearly wrong.
Player::ConvertInstancesToGroup(leader, this, false);
-
}
else if (!AddMember(leader))
return false;
@@ -135,18 +139,15 @@ bool Group::Create(Player *leader)
return true;
}
-bool Group::LoadGroupFromDB(const uint32 &groupGuid, QueryResult result, bool loadMembers)
+void Group::LoadGroupFromDB(Field *fields)
{
- if (isBGGroup())
- return false;
-
- Field *fields = result->Fetch();
- m_guid = MAKE_NEW_GUID(groupGuid, 0, HIGHGUID_GROUP);
+ m_storageId = fields[15].GetUInt32();
+ m_guid = MAKE_NEW_GUID(sObjectMgr->GenerateLowGuid(HIGHGUID_GROUP), 0, HIGHGUID_GROUP);
m_leaderGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
// group leader not exist
if (!sObjectMgr->GetPlayerNameByGUID(fields[0].GetUInt32(), m_leaderName))
- return false;
+ return;
m_lootMethod = LootMethod(fields[1].GetUInt8());
m_looterGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
@@ -171,27 +172,9 @@ bool Group::LoadGroupFromDB(const uint32 &groupGuid, QueryResult result, bool lo
else
m_raidDifficulty = Difficulty(r_diff);
- if (loadMembers)
- {
- // 0 1 2 3
- result = CharacterDatabase.PQuery("SELECT memberGuid, memberFlags, subgroup, roles FROM group_member WHERE guid=%u", groupGuid);
- if (!result)
- return false;
-
- do
- {
- fields = result->Fetch();
- LoadMemberFromDB(fields[0].GetUInt32(), fields[1].GetUInt8(), fields[2].GetUInt8(), fields[3].GetUInt8());
- } while (result->NextRow());
-
- if (GetMembersCount() < 2) // group too small
- return false;
- }
-
- return true;
}
-bool Group::LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles)
+void Group::LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles)
{
MemberSlot member;
member.guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER);
@@ -200,7 +183,7 @@ bool Group::LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup,
if (!sObjectMgr->GetPlayerNameByGUID(member.guid, member.name))
{
CharacterDatabase.PQuery("DELETE FROM group_member WHERE memberGuid=%u", guidLow);
- return false;
+ return;
}
member.group = subgroup;
@@ -210,8 +193,6 @@ bool Group::LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup,
m_memberSlots.push_back(member);
SubGroupCounterIncrease(subgroup);
-
- return true;
}
void Group::ConvertToLFG()
@@ -219,7 +200,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), GUID_LOPART(m_guid));
+ CharacterDatabase.PExecute("UPDATE groups SET groupType='%u' WHERE guid='%u'", uint8(m_groupType), m_storageId);
SendUpdate();
}
@@ -230,7 +211,7 @@ void Group::ConvertToRaid()
_initRaidSubGroupsCounter();
if (!isBGGroup())
- CharacterDatabase.PExecute("UPDATE groups SET groupType='%u' WHERE guid='%u'", uint8(m_groupType), GUID_LOPART(m_guid));
+ CharacterDatabase.PExecute("UPDATE groups SET groupType='%u' WHERE guid='%u'", uint8(m_groupType), m_storageId);
SendUpdate();
// update quest related GO states (quest activity dependent from raid membership)
@@ -363,7 +344,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)",
- GUID_LOPART(m_guid), GUID_LOPART(member.guid), member.flags, member.group, member.roles);
+ m_storageId, GUID_LOPART(member.guid), member.flags, member.group, member.roles);
SendUpdate();
sScriptMgr->OnGroupAddMember(this, player->GetGUID());
@@ -550,13 +531,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'))",
- GUID_LOPART(m_guid), player->GetGUIDLow());
+ m_storageId, 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(), GUID_LOPART(m_guid));
+ CharacterDatabase.PExecute("UPDATE groups SET leaderGuid='%u' WHERE guid='%u'", player->GetGUIDLow(), m_storageId);
}
m_leaderGuid = player->GetGUID();
@@ -628,19 +609,14 @@ void Group::Disband(bool hideDestroy /* = false */)
if (!isBGGroup())
{
- uint32 lowguid = GUID_LOPART(m_guid);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
- trans->PAppend("DELETE FROM groups WHERE guid=%u", lowguid);
- trans->PAppend("DELETE FROM group_member WHERE guid=%u", lowguid);
+ trans->PAppend("DELETE FROM groups WHERE guid = %u", m_storageId);
+ trans->PAppend("DELETE FROM group_member WHERE guid = %u", m_storageId);
CharacterDatabase.CommitTransaction(trans);
ResetInstances(INSTANCE_RESET_GROUP_DISBAND, false, NULL);
ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, NULL);
- // If the deleted group guid is lower than the one we have stored for the next group creation,
- // use this one instead.
- if (lowguid < sObjectMgr->GetNextGroupGuid())
- sObjectMgr->SetNextGroupGuid(lowguid);
-
+ sObjectMgr->FreeGroupStorageId(this);
}
sObjectMgr->RemoveGroup(this);
@@ -1584,7 +1560,7 @@ void Group::SetDungeonDifficulty(Difficulty difficulty)
{
m_dungeonDifficulty = difficulty;
if (!isBGGroup())
- CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE guid ='%u'", m_dungeonDifficulty, GUID_LOPART(m_guid));
+ CharacterDatabase.PExecute("UPDATE groups SET difficulty = %u WHERE guid ='%u'", m_dungeonDifficulty, m_storageId);
for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
@@ -1601,7 +1577,7 @@ void Group::SetRaidDifficulty(Difficulty difficulty)
{
m_raidDifficulty = difficulty;
if (!isBGGroup())
- CharacterDatabase.PExecute("UPDATE groups SET raiddifficulty = %u WHERE guid ='%u'", m_raidDifficulty, GUID_LOPART(m_guid));
+ CharacterDatabase.PExecute("UPDATE groups SET raiddifficulty = %u WHERE guid ='%u'", m_raidDifficulty, m_storageId);
for (GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
@@ -1743,7 +1719,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)", GUID_LOPART(GetGUID()), save->GetInstanceId(), permanent);
+ CharacterDatabase.PExecute("REPLACE INTO group_instance (guid, instance, permanent) VALUES (%u, %u, %u)", m_storageId, save->GetInstanceId(), permanent);
if (bind.save != save)
{
@@ -1755,7 +1731,9 @@ InstanceGroupBind* Group::BindToInstance(InstanceSave *save, bool permanent, boo
bind.save = save;
bind.perm = permanent;
if (!load)
- sLog->outDebug(LOG_FILTER_MAPS, "Group::BindToInstance: %d is now bound to map %d, instance %d, difficulty %d", GUID_LOPART(GetGUID()), save->GetMapId(), save->GetInstanceId(), save->GetDifficulty());
+ 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());
+
return &bind;
}
@@ -1765,7 +1743,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", GUID_LOPART(GetGUID()), itr->second.save->GetInstanceId());
+ CharacterDatabase.PExecute("DELETE FROM group_instance WHERE guid=%u AND instance=%u", m_storageId, 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 3928b6ee54a..8858767d19c 100755
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -183,8 +183,8 @@ class Group
// group manipulation methods
bool Create(Player *leader);
- bool LoadGroupFromDB(const uint32 &guid, QueryResult result, bool loadMembers = true);
- bool LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles);
+ void LoadGroupFromDB(Field *field);
+ void LoadMemberFromDB(uint32 guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles);
bool AddInvite(Player *player);
void RemoveInvite(Player *player);
void RemoveAllInvites();
@@ -213,6 +213,8 @@ class Group
const uint64& GetLooterGuid() const;
ItemQualities GetLootThreshold() const;
+ uint32 GetStorageId() { return m_storageId; };
+
// member manipulation methods
bool IsMember(const uint64& guid) const;
bool IsLeader(const uint64& guid) const;
@@ -328,5 +330,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)
};
#endif
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index b46f3a79e3a..1d001962526 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -31,7 +31,7 @@ bool CharacterDatabaseConnection::Open()
PREPARE_STATEMENT(CHAR_DEL_OLD_GUILD_EVENT_LOGS, "DELETE FROM guild_eventlog WHERE LogGuid > ?", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_OLD_GUILD_BANK_EVENT_LOGS, "DELETE FROM guild_bank_eventlog WHERE LogGuid > ?", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM, "DELETE FROM guild_bank_item WHERE guildid = ? AND TabId = ? AND SlotId = ?", CONNECTION_ASYNC)
- PREPARE_STATEMENT(CHAR_DEL_NONEXISTENT_CHARACTER_GROUP_MEMBERS, "DELETE FROM group_member WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=memberGuid)", CONNECTION_ASYNC)
+ PREPARE_STATEMENT(CHAR_DEL_NONEXISTENT_CHARACTER_GROUP_MEMBERS, "DELETE FROM group_member WHERE memberGuid NOT IN (SELECT guid FROM characters)", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_LEADERLESS_GROUPS, "DELETE FROM groups WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=leaderGuid)", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_DEL_TINY_GROUPS, "DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_DEL_NONEXISTENT_GROUP_MEMBERS, "DELETE FROM group_member WHERE guid NOT IN (SELECT guid FROM groups)", CONNECTION_ASYNC)