Skip to content

Commit

Permalink
Abort server startup if we've reached max guid.
Browse files Browse the repository at this point in the history
  • Loading branch information
ratkosrb committed Jan 12, 2025
1 parent 9eec576 commit efe5d82
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 24 deletions.
4 changes: 2 additions & 2 deletions src/game/Maps/Map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId)
m_objUpdatesThreads(0), m_unitRelocationThreads(0), m_lastPlayerLeftTime(0),
m_lastMvtSpellsUpdate(0), m_bonesCleanupTimer(0), m_uiScriptedEventsTimer(1000)
{
m_CreatureGuids.Set(sObjectMgr.GetFirstTemporaryCreatureLowGuid());
m_GameObjectGuids.Set(sObjectMgr.GetFirstTemporaryGameObjectLowGuid());
m_CreatureGuids.SetMaxUsedGuid(sObjectMgr.GetFirstTemporaryCreatureLowGuid(), "Creature");
m_GameObjectGuids.SetMaxUsedGuid(sObjectMgr.GetFirstTemporaryGameObjectLowGuid(), "GameObject");

for (uint32 j = 0; j < MAX_NUMBER_OF_GRIDS; ++j)
{
Expand Down
12 changes: 12 additions & 0 deletions src/game/ObjectGuid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ void ObjectGuidGenerator<high>::GenerateRange(uint32& first, uint32& last)
last = m_nextGuid;
}

template<HighGuid high>
void ObjectGuidGenerator<high>::SetMaxUsedGuid(uint32 val, char const* guidType)
{
if (val == UINT32_MAX)
{
sLog.Out(LOG_BASIC, LOG_LVL_ERROR, "%s guids have been exhausted! Aborting startup.", guidType);
Log::WaitBeforeContinueIfNeed();
exit(1);
}
m_nextGuid = val + 1;
}

ByteBuffer& operator<< (ByteBuffer& buf, ObjectGuid const& guid)
{
buf << uint64(guid.GetRawValue());
Expand Down
2 changes: 1 addition & 1 deletion src/game/ObjectGuid.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ class ObjectGuidGenerator
explicit ObjectGuidGenerator(uint32 start = 1) : m_nextGuid(start) {}

public: // modifiers
void Set(uint32 val) { m_nextGuid = val; }
void SetMaxUsedGuid(uint32 val, char const* guidType);
uint32 Generate();
void GenerateRange(uint32& first, uint32& last);

Expand Down
44 changes: 28 additions & 16 deletions src/game/ObjectMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ T IdGenerator<T>::Generate()
return m_nextGuid++;
}

template<typename T>
void IdGenerator<T>::SetMaxUsedGuid(T val, char const* guidType)
{
if (val == std::numeric_limits<T>::max())
{
sLog.Out(LOG_BASIC, LOG_LVL_ERROR, "%s guids have been exhausted! Aborting startup.", guidType);
Log::WaitBeforeContinueIfNeed();
exit(1);
}
m_nextGuid = val + 1;
}

template uint32 IdGenerator<uint32>::Generate();
template uint64 IdGenerator<uint64>::Generate();

Expand Down Expand Up @@ -7540,7 +7552,7 @@ void ObjectMgr::PackGroupIds()
bar.step();
}

m_GroupIds.Set(groupId);
m_GroupIds.SetMaxUsedGuid(groupId, "Group");

sLog.Out(LOG_BASIC, LOG_LVL_MINIMAL, "");
sLog.Out(LOG_BASIC, LOG_LVL_MINIMAL, ">> Group Ids remapped, next group id is %u", groupId);
Expand All @@ -7550,15 +7562,11 @@ void ObjectMgr::SetHighestGuids()
{
std::unique_ptr<QueryResult> result(CharacterDatabase.Query("SELECT MAX(`guid`) FROM `characters`"));
if (result)
m_CharGuids.Set((*result)[0].GetUInt32() + 1);

result = WorldDatabase.Query("SELECT MAX(`guid`) FROM `creature`");
if (result)
m_FirstTemporaryCreatureGuid = (*result)[0].GetUInt32() + 1;
m_CharGuids.SetMaxUsedGuid((*result)[0].GetUInt32(), "Character");

result = CharacterDatabase.Query("SELECT MAX(`guid`) FROM `item_instance`");
if (result)
m_ItemGuids.Set((*result)[0].GetUInt32() + 1);
m_ItemGuids.SetMaxUsedGuid((*result)[0].GetUInt32(), "Item");

// Cleanup other tables from nonexistent guids (>=m_hiItemGuid)
CharacterDatabase.BeginTransaction();
Expand All @@ -7567,9 +7575,13 @@ void ObjectMgr::SetHighestGuids()
CharacterDatabase.PExecute("DELETE FROM `auction` WHERE `item_guid` >= '%u'", m_ItemGuids.GetNextAfterMaxUsed());
CharacterDatabase.CommitTransaction();

result = WorldDatabase.Query("SELECT MAX(`guid`) FROM `creature`");
if (result)
m_FirstTemporaryCreatureGuid = (*result)[0].GetUInt32();

result = WorldDatabase.Query("SELECT MAX(`guid`) FROM `gameobject`");
if (result)
m_FirstTemporaryGameObjectGuid = (*result)[0].GetUInt32() + 1;
m_FirstTemporaryGameObjectGuid = (*result)[0].GetUInt32();

result = CharacterDatabase.Query("SELECT `id` FROM `auction`");
if (result)
Expand All @@ -7584,33 +7596,33 @@ void ObjectMgr::SetHighestGuids()

result = CharacterDatabase.Query("SELECT MAX(`id`) FROM `mail`");
if (result)
m_MailIds.Set((*result)[0].GetUInt32() + 1);
m_MailIds.SetMaxUsedGuid((*result)[0].GetUInt32(), "Mail");

result = CharacterDatabase.Query("SELECT MAX(`id`) FROM `item_text`");
if (result)
m_ItemTextIds.Set((*result)[0].GetUInt32() + 1);
m_ItemTextIds.SetMaxUsedGuid((*result)[0].GetUInt32(), "Item Text");

result = CharacterDatabase.Query("SELECT MAX(`guid`) FROM `corpse`");
if (result)
m_CorpseGuids.Set((*result)[0].GetUInt32() + 1);
m_CorpseGuids.SetMaxUsedGuid((*result)[0].GetUInt32(), "Corpse");

result = CharacterDatabase.Query("SELECT MAX(`guild_id`) FROM `guild`");
if (result)
m_GuildIds.Set((*result)[0].GetUInt32() + 1);
m_GuildIds.SetMaxUsedGuid((*result)[0].GetUInt32(), "Guild");

result = CharacterDatabase.Query("SELECT MAX(`group_id`) FROM `groups`");
if (result)
m_GroupIds.Set((*result)[0].GetUInt32() + 1);
m_GroupIds.SetMaxUsedGuid((*result)[0].GetUInt32(), "Group");

result = CharacterDatabase.Query("SELECT MAX(`petition_guid`) FROM `petition`");
if (result)
m_PetitionIds.Set((*result)[0].GetUInt32() + 1);
m_PetitionIds.SetMaxUsedGuid((*result)[0].GetUInt32(), "Petition");

// setup reserved ranges for static guids spawn
m_StaticCreatureGuids.Set(m_FirstTemporaryCreatureGuid);
m_StaticCreatureGuids.SetMaxUsedGuid(m_FirstTemporaryCreatureGuid, "Creature");
m_FirstTemporaryCreatureGuid += sWorld.getConfig(CONFIG_UINT32_GUID_RESERVE_SIZE_CREATURE);

m_StaticGameObjectGuids.Set(m_FirstTemporaryGameObjectGuid);
m_StaticGameObjectGuids.SetMaxUsedGuid(m_FirstTemporaryGameObjectGuid, "GameObject");
m_FirstTemporaryGameObjectGuid += sWorld.getConfig(CONFIG_UINT32_GUID_RESERVE_SIZE_GAMEOBJECT);
}

Expand Down
2 changes: 1 addition & 1 deletion src/game/ObjectMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ class IdGenerator
explicit IdGenerator(char const* _name) : m_name(_name), m_nextGuid(1) {}

public: // modifiers
void Set(T val) { m_nextGuid = val; }
void SetMaxUsedGuid(T val, char const* guidType);
T Generate();

public: // accessors
Expand Down
16 changes: 12 additions & 4 deletions src/game/PlayerDump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,12 +675,20 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
CharacterDatabase.CommitTransaction();

//FIXME: current code with post-updating guids not safe for future per-map threads
sObjectMgr.m_ItemGuids.Set(sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed() + items.size());
sObjectMgr.m_MailIds.Set(sObjectMgr.m_MailIds.GetNextAfterMaxUsed() + mails.size());
sObjectMgr.m_ItemTextIds.Set(sObjectMgr.m_ItemTextIds.GetNextAfterMaxUsed() + itemTexts.size());
uint64 newMaxItemGuid = sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed() + items.size();
MANGOS_ASSERT(newMaxItemGuid < UINT32_MAX);
sObjectMgr.m_ItemGuids.SetMaxUsedGuid(newMaxItemGuid, "Item");

uint32 newMaxMailId = sObjectMgr.m_MailIds.GetNextAfterMaxUsed() + mails.size();
MANGOS_ASSERT(newMaxMailId < UINT32_MAX);
sObjectMgr.m_MailIds.SetMaxUsedGuid(newMaxMailId, "Mail");

uint32 newMaxItemTextId = sObjectMgr.m_ItemTextIds.GetNextAfterMaxUsed() + itemTexts.size();
MANGOS_ASSERT(newMaxItemTextId < UINT32_MAX);
sObjectMgr.m_ItemTextIds.SetMaxUsedGuid(newMaxItemTextId, "Item Text");

if (incHighest)
sObjectMgr.m_CharGuids.Set(sObjectMgr.m_CharGuids.GetNextAfterMaxUsed() + 1);
sObjectMgr.m_CharGuids.SetMaxUsedGuid(sObjectMgr.m_CharGuids.GetNextAfterMaxUsed() + 1, "Character");

fclose(fin);

Expand Down

0 comments on commit efe5d82

Please sign in to comment.