From ac8b20922bead9de97039915eac84a35d943ee90 Mon Sep 17 00:00:00 2001 From: Barbz Date: Mon, 8 Jul 2019 11:27:52 +0200 Subject: [PATCH] feat(Core): GUID recycler (#1820) Automatically recycle GUIDs, thus avoiding crashes when reaching the limit of data type "int" in MySQL. --- src/server/game/Globals/ObjectMgr.cpp | 43 ++++++++++++++++++++-- src/server/game/Globals/ObjectMgr.h | 12 ++++-- src/server/scripts/Commands/cs_gobject.cpp | 4 +- src/server/scripts/Commands/cs_npc.cpp | 6 +-- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 0913f09ec..67ad37dc5 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -3863,7 +3863,7 @@ void ObjectMgr::LoadQuests() "RewardFactionID1, RewardFactionValue1, RewardFactionOverride1, RewardFactionID2, RewardFactionValue2, RewardFactionOverride2, RewardFactionID3, RewardFactionValue3, RewardFactionOverride3, RewardFactionID4, RewardFactionValue4, RewardFactionOverride4, RewardFactionID5, RewardFactionValue5, RewardFactionOverride5," // 62 63 64 65 "POIContinent, POIx, POIy, POIPriority, " - // 66 67 68 69 70 + // 66 67 68 69 70 "LogTitle, LogDescription, QuestDescription, AreaDescription, QuestCompletionLog, " // 71 72 73 74 75 76 77 78 "RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, " @@ -5416,7 +5416,7 @@ void ObjectMgr::LoadGossipText() do { - + cic = 0; Field* fields = result->Fetch(); @@ -6198,7 +6198,12 @@ void ObjectMgr::SetHighestGuids() result = WorldDatabase.Query("SELECT MAX(guid) FROM creature"); if (result) + { _hiCreatureGuid = (*result)[0].GetUInt32()+1; + _hiCreatureRecycledGuid = _hiCreatureGuid; + _hiCreatureRecycledGuidMax = _hiCreatureRecycledGuid + 10000; + _hiCreatureGuid = _hiCreatureRecycledGuidMax + 1; + } result = CharacterDatabase.Query("SELECT MAX(guid) FROM item_instance"); if (result) @@ -6212,7 +6217,12 @@ void ObjectMgr::SetHighestGuids() result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject"); if (result) + { _hiGoGuid = (*result)[0].GetUInt32()+1; + _hiGoRecycledGuid = _hiGoGuid; + _hiGoRecycledGuidMax = _hiGoRecycledGuid + 1; + _hiGoGuid = _hiGoRecycledGuidMax + 1; + } result = WorldDatabase.Query("SELECT MAX(guid) FROM transports"); if (result) @@ -6341,6 +6351,31 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) } } +uint32 ObjectMgr::GenerateRecycledLowGuid(HighGuid guidHigh) +{ + switch (guidHigh) + { + case HIGHGUID_UNIT: + { + ASSERT(_hiCreatureRecycledGuid < 0x00FFFFFE && "Creature recycled guid overflow!"); + if (_hiCreatureRecycledGuid < _hiCreatureRecycledGuidMax) + return _hiCreatureRecycledGuid++; + break; + } + case HIGHGUID_GAMEOBJECT: + { + ASSERT(_hiGoRecycledGuid < 0x00FFFFFE && "Gameobject recycled guid overflow!"); + if (_hiGoRecycledGuid < _hiGoRecycledGuidMax) + return _hiGoRecycledGuid++; + break; + } + default: // Default case is not handled by the recycler + break; + } + + return GenerateLowGuid(guidHigh); +} + void ObjectMgr::LoadGameObjectLocales() { uint32 oldMSTime = getMSTime(); @@ -7804,7 +7839,7 @@ void ObjectMgr::ChangeFishingBaseSkillLevel(uint32 entry, int32 skill) sLog->outErrorDb("AreaId %u defined in `skill_fishing_base_level` does not exist", entry); return; } - + _fishingBaseForAreaStore[entry] = skill; sLog->outString(">> Fishing base skill level of area %u changed to %u", entry, skill); @@ -8359,7 +8394,7 @@ void ObjectMgr::LoadGossipMenuItems() _gossipMenuItemsStore.clear(); QueryResult result = WorldDatabase.Query( - // 0 1 2 3 4 5 6 7 8 9 10 11 12 + // 0 1 2 3 4 5 6 7 8 9 10 11 12 "SELECT MenuID, OptionID, OptionIcon, OptionText, OptionBroadcastTextID, OptionType, OptionNpcFlag, ActionMenuID, ActionPoiID, BoxCoded, BoxMoney, BoxText, BoxBroadcastTextID " "FROM gossip_menu_option ORDER BY MenuID, OptionID"); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 70ed19585..b0fb77a9c 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -813,7 +813,7 @@ class ObjectMgr return _tavernAreaTriggerStore.find(Trigger_ID) != _tavernAreaTriggerStore.end(); } - GossipText const* GetGossipText(uint32 Text_ID) const; + GossipText const* GetGossipText(uint32 Text_ID) const; AreaTrigger const* GetAreaTrigger(uint32 trigger) const { @@ -1057,6 +1057,7 @@ class ObjectMgr void SetHighestGuids(); uint32 GenerateLowGuid(HighGuid guidhigh); + uint32 GenerateRecycledLowGuid(HighGuid guidHigh); uint32 GenerateAuctionID(); uint64 GenerateEquipmentSetGuid(); uint32 GenerateMailID(); @@ -1114,7 +1115,7 @@ class ObjectMgr TempSummonDataContainer::const_iterator itr = _tempSummonDataStore.find(TempSummonGroupKey(summonerId, summonerType, group)); if (itr != _tempSummonDataStore.end()) return &itr->second; - + return NULL; } @@ -1214,7 +1215,7 @@ class ObjectMgr } GameObjectData& NewGOData(uint32 guid) { return _gameObjectDataStore[guid]; } void DeleteGOData(uint32 guid); - + TrinityString const* GetTrinityString(uint32 entry) const { TrinityStringContainer::const_iterator itr = _trinityStringStore.find(entry); @@ -1354,6 +1355,11 @@ class ObjectMgr uint32 _hiCorpseGuid; ACE_Thread_Mutex _hiCorpseGuidMutex; uint32 _hiMoTransGuid; ACE_Thread_Mutex _hiMoTransGuidMutex; + uint32 _hiCreatureRecycledGuidMax; + uint32 _hiCreatureRecycledGuid; + uint32 _hiGoRecycledGuidMax; + uint32 _hiGoRecycledGuid; + QuestMap _questTemplates; std::vector _questTemplatesFast; // pussywizard diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 95ee9ab60..034a665b5 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -137,7 +137,7 @@ public: Map* map = player->GetMap(); GameObject* object = sObjectMgr->IsGameObjectStaticTransport(objectInfo->entry) ? new StaticTransport() : new GameObject(); - uint32 guidLow = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT); + uint32 guidLow = sObjectMgr->GenerateRecycledLowGuid(HIGHGUID_GAMEOBJECT); if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMaskForSpawn(), x, y, z, o, G3D::Quat(), 0, GO_STATE_READY)) { @@ -655,7 +655,7 @@ public: if (!object) { - + handler->PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, abs(guidLow)); handler->SetSentErrorMessage(true); return false; diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 3654f4bc8..7f3eb2dbf 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -212,7 +212,7 @@ public: if (Transport* tt = chr->GetTransport()) if (MotionTransport* trans = tt->ToMotionTransport()) { - uint32 guid = sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT); + uint32 guid = sObjectMgr->GenerateRecycledLowGuid(HIGHGUID_UNIT); CreatureData& data = sObjectMgr->NewOrExistCreatureData(guid); data.id = id; data.phaseMask = chr->GetPhaseMaskForSpawn(); @@ -230,7 +230,7 @@ public: } Creature* creature = new Creature(); - if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, x, y, z, o)) + if (!creature->Create(sObjectMgr->GenerateRecycledLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, x, y, z, o)) { delete creature; return false; @@ -741,7 +741,7 @@ public: for (uint8 i = 0; i < NPCFLAG_COUNT; i++) if (npcflags & npcFlagTexts[i].flag) handler->PSendSysMessage(npcFlagTexts[i].text, npcFlagTexts[i].flag); - + handler->PSendSysMessage(LANG_NPCINFO_MECHANIC_IMMUNE, mechanicImmuneMask); for (uint8 i = 1; i < MAX_MECHANIC; ++i) if (mechanicImmuneMask & (1 << (mechanicImmunes[i].flag - 1)))