aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp1
-rw-r--r--src/server/game/Battlegrounds/Battleground.h6
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp38
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.h9
-rw-r--r--src/server/game/Entities/Object/Object.cpp9
-rw-r--r--src/server/game/Entities/Object/Object.h7
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp14
-rw-r--r--src/server/game/Entities/Unit/Unit.h5
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp5
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.h11
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp18
-rw-r--r--src/server/game/Globals/ObjectMgr.h3
-rw-r--r--src/server/game/Groups/Group.cpp3
-rw-r--r--src/server/game/Groups/Group.h6
-rw-r--r--src/server/game/Guilds/Guild.cpp31
-rw-r--r--src/server/game/Guilds/Guild.h8
-rw-r--r--src/server/game/Guilds/GuildMgr.cpp26
-rw-r--r--src/server/game/Guilds/GuildMgr.h3
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp8
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.cpp15
-rw-r--r--src/server/game/Maps/Map.h5
-rw-r--r--src/server/game/Maps/MapInstanced.cpp13
-rw-r--r--src/server/game/Maps/MapInstanced.h9
-rw-r--r--src/server/game/Maps/MapManager.cpp37
-rw-r--r--src/server/game/Maps/MapManager.h13
-rw-r--r--src/server/game/Quests/QuestDef.h5
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp4
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h12
-rw-r--r--src/server/game/Spells/Spell.cpp35
-rw-r--r--src/server/game/Spells/Spell.h4
-rw-r--r--src/server/scripts/Commands/cs_guild.cpp4
-rw-r--r--src/server/scripts/Commands/cs_learn.cpp4
-rw-r--r--src/server/scripts/Commands/cs_lookup.cpp6
34 files changed, 218 insertions, 161 deletions
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index a06c87d2eeb..938ac559b4c 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -145,7 +145,6 @@ Battleground::~Battleground()
for (uint32 i = 0; i < size; ++i)
DelObject(i);
- sBattlegroundMgr->RemoveBattleground(GetTypeID(), GetInstanceID());
// unload map
if (m_Map)
{
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index 4671ba22780..76c98c3f6c2 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -23,6 +23,7 @@
#include "ObjectGuid.h"
#include "Position.h"
#include "SharedDefines.h"
+#include "UniqueTrackablePtr.h"
#include <deque>
#include <map>
@@ -496,6 +497,9 @@ class TC_GAME_API Battleground
// because BattleGrounds with different types and same level range has different m_BracketId
uint8 GetUniqueBracketId() const;
+ Trinity::unique_weak_ptr<Battleground> GetWeakPtr() const { return m_weakRef; }
+ void SetWeakPtr(Trinity::unique_weak_ptr<Battleground> weakRef) { m_weakRef = std::move(weakRef); }
+
protected:
// this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends Battleground
void EndNow();
@@ -626,5 +630,7 @@ class TC_GAME_API Battleground
Position StartPosition[PVP_TEAMS_COUNT];
float m_StartMaxDist;
uint32 ScriptId;
+
+ Trinity::unique_weak_ptr<Battleground> m_weakRef;
};
#endif
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index b59831ff05d..1b3d2f0c851 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -69,18 +69,6 @@ BattlegroundMgr::~BattlegroundMgr()
void BattlegroundMgr::DeleteAllBattlegrounds()
{
- for (BattlegroundDataContainer::iterator itr1 = bgDataStore.begin(); itr1 != bgDataStore.end(); ++itr1)
- {
- BattlegroundData& data = itr1->second;
-
- while (!data.m_Battlegrounds.empty())
- delete data.m_Battlegrounds.begin()->second;
- data.m_Battlegrounds.clear();
-
- while (!data.BGFreeSlotQueue.empty())
- delete data.BGFreeSlotQueue.front();
- }
-
bgDataStore.clear();
}
@@ -104,18 +92,19 @@ void BattlegroundMgr::Update(uint32 diff)
for (BattlegroundContainer::iterator itr = ++itrDelete; itr != bgs.end();)
{
itrDelete = itr++;
- Battleground* bg = itrDelete->second;
+ Battleground* bg = itrDelete->second.get();
bg->Update(m_UpdateTimer);
if (bg->ToBeDeleted())
{
- itrDelete->second = nullptr;
- bgs.erase(itrDelete);
BattlegroundClientIdsContainer& clients = itr1->second.m_ClientBattlegroundIds[bg->GetBracketId()];
if (!clients.empty())
clients.erase(bg->GetClientInstanceID());
- delete bg;
+ // move out unique_ptr to delete after erasing
+ Trinity::unique_trackable_ptr<Battleground> bgPtr = std::move(itrDelete->second);
+
+ bgs.erase(itrDelete);
}
}
}
@@ -274,7 +263,7 @@ Battleground* BattlegroundMgr::GetBattlegroundThroughClientInstance(uint32 insta
for (BattlegroundContainer::const_iterator itr = it->second.m_Battlegrounds.begin(); itr != it->second.m_Battlegrounds.end(); ++itr)
{
if (itr->second->GetClientInstanceID() == instanceId)
- return itr->second;
+ return itr->second.get();
}
return nullptr;
@@ -305,7 +294,7 @@ Battleground* BattlegroundMgr::GetBattleground(uint32 instanceId, BattlegroundTy
BattlegroundContainer const& bgs = it->second.m_Battlegrounds;
BattlegroundContainer::const_iterator itr = bgs.find(instanceId);
if (itr != bgs.end())
- return itr->second;
+ return itr->second.get();
}
return nullptr;
@@ -319,7 +308,7 @@ Battleground* BattlegroundMgr::GetBattlegroundTemplate(BattlegroundTypeId bgType
BattlegroundContainer const& bgs = itr->second.m_Battlegrounds;
//map is sorted and we can be sure that lowest instance id has only BG template
- return bgs.empty() ? nullptr : bgs.begin()->second;
+ return bgs.empty() ? nullptr : bgs.begin()->second.get();
}
uint32 BattlegroundMgr::CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
@@ -1015,10 +1004,9 @@ void BattlegroundMgr::RemoveFromBGFreeSlotQueue(BattlegroundTypeId bgTypeId, uin
void BattlegroundMgr::AddBattleground(Battleground* bg)
{
if (bg)
- bgDataStore[bg->GetTypeID()].m_Battlegrounds[bg->GetInstanceID()] = bg;
-}
-
-void BattlegroundMgr::RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId)
-{
- bgDataStore[bgTypeId].m_Battlegrounds.erase(instanceId);
+ {
+ Trinity::unique_trackable_ptr<Battleground>& ptr = bgDataStore[bg->GetTypeID()].m_Battlegrounds[bg->GetInstanceID()];
+ ptr.reset(bg);
+ bg->SetWeakPtr(ptr);
+ }
}
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index 7335abe190d..939d3ef87b1 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -22,11 +22,12 @@
#include "DBCEnums.h"
#include "Battleground.h"
#include "BattlegroundQueue.h"
+#include "UniqueTrackablePtr.h"
#include <unordered_map>
struct BattlemasterListEntry;
-typedef std::map<uint32, Battleground*> BattlegroundContainer;
+typedef std::map<uint32, Trinity::unique_trackable_ptr<Battleground>> BattlegroundContainer;
typedef std::set<uint32> BattlegroundClientIdsContainer;
typedef std::unordered_map<uint32, BattlegroundTypeId> BattleMastersMap;
@@ -68,6 +69,11 @@ class TC_GAME_API BattlegroundMgr
~BattlegroundMgr();
public:
+ BattlegroundMgr(BattlegroundMgr const& right) = delete;
+ BattlegroundMgr(BattlegroundMgr&& right) = delete;
+ BattlegroundMgr& operator=(BattlegroundMgr const& right) = delete;
+ BattlegroundMgr& operator=(BattlegroundMgr&& right) = delete;
+
static BattlegroundMgr* instance();
void Update(uint32 diff);
@@ -87,7 +93,6 @@ class TC_GAME_API BattlegroundMgr
Battleground* CreateNewBattleground(BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated);
void AddBattleground(Battleground* bg);
- void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId);
void AddToBGFreeSlotQueue(BattlegroundTypeId bgTypeId, Battleground* bg);
void RemoveFromBGFreeSlotQueue(BattlegroundTypeId bgTypeId, uint32 instanceId);
BGFreeSlotQueueContainer& GetBGFreeSlotQueueStore(BattlegroundTypeId bgTypeId);
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 416df2cce7b..9765ef91434 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -61,7 +61,7 @@ constexpr float VisibilityDistances[AsUnderlyingType(VisibilityDistanceType::Max
MAX_VISIBILITY_DISTANCE
};
-Object::Object()
+Object::Object() : m_scriptRef(this, NoopObjectDeleter())
{
m_objectTypeId = TYPEID_OBJECT;
m_objectType = TYPEMASK_OBJECT;
@@ -151,6 +151,11 @@ void Object::AddToWorld()
// synchronize values mirror with values array (changes will send in updatecreate opcode any way
ASSERT(!m_objectUpdated);
ClearUpdateMask(false);
+
+ // Set new ref when adding to world (except if we already have one - also set in constructor to allow scripts to work in initialization phase)
+ // Changing the ref when adding/removing from world prevents accessing players on different maps (possibly from another thread)
+ if (!m_scriptRef)
+ m_scriptRef.reset(this, NoopObjectDeleter());
}
void Object::RemoveFromWorld()
@@ -162,6 +167,8 @@ void Object::RemoveFromWorld()
// if we remove from world then sending changes not required
ClearUpdateMask(true);
+
+ m_scriptRef = nullptr;
}
void Object::BuildMovementUpdateBlock(UpdateData* data, uint32 flags) const
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 3a72759bb74..abf3bd3bf98 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -29,6 +29,7 @@
#include "Position.h"
#include "SharedDefines.h"
#include "SpellDefines.h"
+#include "UniqueTrackablePtr.h"
#include "UpdateFields.h"
#include "UpdateMask.h"
#include <list>
@@ -200,6 +201,8 @@ class TC_GAME_API Object
virtual std::string GetDebugInfo() const;
+ Trinity::unique_weak_ptr<Object> GetWeakPtr() const { return m_scriptRef; }
+
protected:
Object();
@@ -243,8 +246,12 @@ class TC_GAME_API Object
PackedGuid m_PackGUID;
+ struct NoopObjectDeleter { void operator()(Object*) const { /*noop - not managed*/ } };
+ Trinity::unique_trackable_ptr<Object> m_scriptRef;
+
// for output helpfull error messages from asserts
bool PrintIndexError(uint32 index, bool set) const;
+
Object(Object const& right) = delete;
Object(Object&& right) = delete;
Object& operator=(Object const& right) = delete;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index ef84452914b..b4c0139c766 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -4018,7 +4018,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
if (ObjectGuid::LowType guildId = sCharacterCache->GetCharacterGuildIdByGuid(playerguid))
if (Guild* guild = sGuildMgr->GetGuildById(guildId))
- guild->DeleteMember(trans, playerguid, false, false, true);
+ guild->DeleteMember(trans, playerguid, false, false);
// close player ticket if any
GmTicket* ticket = sTicketMgr->GetTicketByPlayer(playerguid);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index d31025c40ce..71ca198c61e 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -4177,8 +4177,8 @@ void Unit::RemoveAllAuras()
{
sstr << "m_ownedAuras:" << "\n";
- for (std::pair<uint32 const, Aura*>& auraPair : m_ownedAuras)
- sstr << auraPair.second->GetDebugInfo() << "\n";
+ for (auto const& [spellId, aura] : m_ownedAuras)
+ sstr << aura->GetDebugInfo() << "\n";
}
TC_LOG_ERROR("entities.unit", "{}", sstr.str());
@@ -9638,6 +9638,12 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup)
if (IsInWorld())
RemoveFromWorld();
+ else
+ {
+ // cleanup that must happen even if not in world
+ if (IsVehicle())
+ RemoveVehicleKit();
+ }
ASSERT(GetGUID());
@@ -11810,7 +11816,7 @@ bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry)
if (!vehInfo)
return false;
- m_vehicleKit = new Vehicle(this, vehInfo, creatureEntry);
+ m_vehicleKit = Trinity::make_unique_trackable<Vehicle>(this, vehInfo, creatureEntry);
m_updateFlag |= UPDATEFLAG_VEHICLE;
m_unitTypeMask |= UNIT_MASK_VEHICLE;
return true;
@@ -11822,8 +11828,6 @@ void Unit::RemoveVehicleKit()
return;
m_vehicleKit->Uninstall();
- delete m_vehicleKit;
-
m_vehicleKit = nullptr;
m_updateFlag &= ~UPDATEFLAG_VEHICLE;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index c39eb4328bc..970d55a274a 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1730,7 +1730,8 @@ class TC_GAME_API Unit : public WorldObject
ObjectGuid LastCharmerGUID;
bool CreateVehicleKit(uint32 id, uint32 creatureEntry);
void RemoveVehicleKit();
- Vehicle* GetVehicleKit() const { return m_vehicleKit; }
+ Vehicle* GetVehicleKit() const { return m_vehicleKit.get(); }
+ Trinity::unique_weak_ptr<Vehicle> GetVehicleKitWeakPtr() const { return m_vehicleKit; }
Vehicle* GetVehicle() const { return m_vehicle; }
void SetVehicle(Vehicle* vehicle) { m_vehicle = vehicle; }
bool IsOnVehicle(Unit const* vehicle) const;
@@ -1892,7 +1893,7 @@ class TC_GAME_API Unit : public WorldObject
uint32 m_regenTimer;
Vehicle* m_vehicle;
- Vehicle* m_vehicleKit;
+ Trinity::unique_trackable_ptr<Vehicle> m_vehicleKit;
uint32 m_unitTypeMask;
LiquidTypeEntry const* _lastLiquid;
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index c94ea836f06..4011703c7c2 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -989,3 +989,8 @@ std::string Vehicle::GetDebugInfo() const
return sstr.str();
}
+
+Trinity::unique_weak_ptr<Vehicle> Vehicle::GetWeakPtr() const
+{
+ return _me->GetVehicleKitWeakPtr();
+}
diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h
index b9cc63bc744..d59c440bfdf 100644
--- a/src/server/game/Entities/Vehicle/Vehicle.h
+++ b/src/server/game/Entities/Vehicle/Vehicle.h
@@ -20,8 +20,9 @@
#include "ObjectDefines.h"
#include "Object.h"
-#include "VehicleDefines.h"
+#include "UniqueTrackablePtr.h"
#include "Unit.h"
+#include "VehicleDefines.h"
#include <list>
struct VehicleEntry;
@@ -30,14 +31,10 @@ class VehicleJoinEvent;
class TC_GAME_API Vehicle : public TransportBase
{
- protected:
- friend bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry);
+ public:
Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry);
-
- friend void Unit::RemoveVehicleKit();
~Vehicle();
- public:
void Install();
void Uninstall();
void Reset(bool evading = false);
@@ -73,6 +70,8 @@ class TC_GAME_API Vehicle : public TransportBase
std::string GetDebugInfo() const;
+ Trinity::unique_weak_ptr<Vehicle> GetWeakPtr() const;
+
protected:
friend class VehicleJoinEvent;
uint32 UsableSeatNum; ///< Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 67bf9047c82..3aea616d607 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -4759,7 +4759,8 @@ void ObjectMgr::LoadQuests()
Field* fields = result->Fetch();
uint32 questId = fields[0].GetUInt32();
- _questTemplates.emplace(std::piecewise_construct, std::forward_as_tuple(questId), std::forward_as_tuple(fields));
+ auto itr = _questTemplates.emplace(std::piecewise_construct, std::forward_as_tuple(questId), std::forward_as_tuple(new Quest(fields))).first;
+ itr->second->_weakRef = itr->second;
} while (result->NextRow());
std::unordered_map<uint32, uint32> usedMailTemplates;
@@ -4808,7 +4809,7 @@ void ObjectMgr::LoadQuests()
auto itr = _questTemplates.find(questId);
if (itr != _questTemplates.end())
- (itr->second.*loader.LoaderFunction)(fields);
+ (itr->second.get()->*loader.LoaderFunction)(fields);
else
TC_LOG_ERROR("server.loading", "Table `{}` has data for quest {} but such quest does not exist", loader.TableName, questId);
} while (result->NextRow());
@@ -4822,7 +4823,7 @@ void ObjectMgr::LoadQuests()
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, questPair.first, nullptr))
continue;
- Quest* qinfo = &questPair.second;
+ Quest* qinfo = questPair.second.get();
// additional quest integrity checks (GO, creature_template and item_template must be loaded already)
@@ -5329,7 +5330,7 @@ void ObjectMgr::LoadQuests()
auto prevQuestItr = _questTemplates.find(prevQuestId);
if (prevQuestItr == _questTemplates.end())
TC_LOG_ERROR("sql.sql", "Quest {} has PrevQuestId {}, but no such quest", qinfo->GetQuestId(), qinfo->_prevQuestId);
- else if (prevQuestItr->second._breadcrumbForQuestId)
+ else if (prevQuestItr->second->_breadcrumbForQuestId)
TC_LOG_ERROR("sql.sql", "Quest {} should not be unlocked by breadcrumb quest {}", qinfo->_id, prevQuestId);
else if (qinfo->_prevQuestId > 0)
qinfo->DependentPreviousQuests.push_back(prevQuestId);
@@ -5341,7 +5342,7 @@ void ObjectMgr::LoadQuests()
if (nextQuestItr == _questTemplates.end())
TC_LOG_ERROR("sql.sql", "Quest {} has NextQuestId {}, but no such quest", qinfo->GetQuestId(), qinfo->_nextQuestId);
else
- nextQuestItr->second.DependentPreviousQuests.push_back(qinfo->GetQuestId());
+ nextQuestItr->second->DependentPreviousQuests.push_back(qinfo->GetQuestId());
}
if (uint32 breadcrumbForQuestId = std::abs(qinfo->_breadcrumbForQuestId))
@@ -5390,7 +5391,7 @@ void ObjectMgr::LoadQuests()
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, questPair.first, nullptr))
continue;
- Quest* qinfo = &questPair.second;
+ Quest* qinfo = questPair.second.get();
uint32 qid = qinfo->GetQuestId();
uint32 breadcrumbForQuestId = std::abs(qinfo->_breadcrumbForQuestId);
std::set<uint32> questSet;
@@ -6934,7 +6935,8 @@ uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt
Quest const* ObjectMgr::GetQuestTemplate(uint32 quest_id) const
{
- return Trinity::Containers::MapGetValuePtr(_questTemplates, quest_id);
+ auto itr = _questTemplates.find(quest_id);
+ return itr != _questTemplates.end() ? itr->second.get() : nullptr;
}
void ObjectMgr::LoadGraveyardZones()
@@ -10475,7 +10477,7 @@ void ObjectMgr::InitializeQueriesData(QueryDataGroup mask)
// Initialize Query Data for quests
if (mask & QUERY_DATA_QUESTS)
for (auto& questTemplatePair : _questTemplates)
- pool.PostWork([quest = &questTemplatePair.second]() { quest->InitializeQueryData(); });
+ pool.PostWork([quest = questTemplatePair.second.get()]() { quest->InitializeQueryData(); });
// Initialize Quest POI data
if (mask & QUERY_DATA_POIS)
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 6eb39767842..cdd1981ada0 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -34,6 +34,7 @@
#include "SharedDefines.h"
#include "Trainer.h"
#include "VehicleDefines.h"
+#include "UniqueTrackablePtr.h"
#include <iterator>
#include <map>
#include <unordered_map>
@@ -945,7 +946,7 @@ class TC_GAME_API ObjectMgr
static ObjectMgr* instance();
- typedef std::unordered_map<uint32, Quest> QuestContainer;
+ typedef std::unordered_map<uint32, Trinity::unique_trackable_ptr<Quest>> QuestContainer;
typedef std::unordered_map<uint32, AreaTrigger> AreaTriggerContainer;
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 3a8ba730fa7..e3b870cba51 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -62,7 +62,8 @@ Loot* Roll::getLoot()
Group::Group() : m_leaderGuid(), m_leaderName(""), m_groupType(GROUPTYPE_NORMAL),
m_dungeonDifficulty(DUNGEON_DIFFICULTY_NORMAL), m_raidDifficulty(RAID_DIFFICULTY_10MAN_NORMAL),
m_bgGroup(nullptr), m_bfGroup(nullptr), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(),
-m_masterLooterGuid(), m_subGroupsCounts(nullptr), m_guid(), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0), m_isLeaderOffline(false)
+m_masterLooterGuid(), m_subGroupsCounts(nullptr), m_guid(), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0), m_isLeaderOffline(false),
+ m_scriptRef(this, NoopGroupDeleter())
{
for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
m_targetIcons[i].Clear();
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 402264f19ef..f03a2fc44fa 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -24,6 +24,7 @@
#include "Loot.h"
#include "SharedDefines.h"
#include "Timer.h"
+#include "UniqueTrackablePtr.h"
#include <map>
class Battlefield;
@@ -338,6 +339,8 @@ class TC_GAME_API Group
// FG: evil hacks
void BroadcastGroupUpdate(void);
+ Trinity::unique_weak_ptr<Group> GetWeakPtr() const { return m_scriptRef; }
+
protected:
bool _setMembersGroup(ObjectGuid guid, uint8 group);
void _homebindIfInstance(Player* player);
@@ -373,5 +376,8 @@ class TC_GAME_API Group
uint32 m_dbStoreId; // Represents the ID used in database (Can be reused by other groups if group was disbanded)
bool m_isLeaderOffline;
TimeTracker m_leaderOfflineTimer;
+
+ struct NoopGroupDeleter { void operator()(Group*) const { /*noop - not managed*/ } };
+ Trinity::unique_trackable_ptr<Group> m_scriptRef;
};
#endif
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 568194d1f04..18fed0e33c6 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -1532,7 +1532,8 @@ void Guild::HandleAcceptMember(WorldSession* session)
void Guild::HandleLeaveMember(WorldSession* session)
{
Player* player = session->GetPlayer();
- bool disband = false;
+
+ sCalendarMgr->RemovePlayerGuildEventsAndSignups(player->GetGUID(), GetId());
// If leader is leaving
if (_IsLeader(player))
@@ -1544,7 +1545,6 @@ void Guild::HandleLeaveMember(WorldSession* session)
{
// Guild is disbanded if leader leaves.
Disband();
- disband = true;
}
}
else
@@ -1557,11 +1557,6 @@ void Guild::HandleLeaveMember(WorldSession* session)
SendCommandResult(session, GUILD_COMMAND_QUIT, ERR_GUILD_COMMAND_SUCCESS, m_name);
}
-
- sCalendarMgr->RemovePlayerGuildEventsAndSignups(player->GetGUID(), GetId());
-
- if (disband)
- delete this;
}
void Guild::HandleRemoveMember(WorldSession* session, std::string_view name)
@@ -1786,7 +1781,6 @@ void Guild::HandleDisband(WorldSession* session)
{
Disband();
TC_LOG_DEBUG("guild", "Guild Successfully Disbanded");
- delete this;
}
}
@@ -2110,13 +2104,8 @@ bool Guild::Validate()
if (!pLeader)
{
CharacterDatabaseTransaction dummy(nullptr);
- DeleteMember(dummy, m_leaderGuid);
- // If no more members left, disband guild
- if (m_members.empty())
- {
- Disband();
+ if (DeleteMember(dummy, m_leaderGuid))
return false;
- }
}
else if (!pLeader->IsRank(GR_GUILDMASTER))
_SetLeaderGUID(*pLeader);
@@ -2276,7 +2265,7 @@ bool Guild::AddMember(CharacterDatabaseTransaction trans, ObjectGuid guid, uint8
return true;
}
-void Guild::DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bool isDisbanding, bool isKicked, bool canDeleteGuild)
+bool Guild::DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bool isDisbanding, bool isKicked)
{
ObjectGuid::LowType lowguid = guid.GetCounter();
Player* player = ObjectAccessor::FindConnectedPlayer(guid);
@@ -2298,9 +2287,7 @@ void Guild::DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bo
if (!newLeader)
{
Disband();
- if (canDeleteGuild)
- delete this;
- return;
+ return true;
}
_SetLeaderGUID(*newLeader);
@@ -2333,6 +2320,14 @@ void Guild::DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bo
_DeleteMemberFromDB(trans, lowguid);
if (!isDisbanding)
_UpdateAccountsNumber();
+
+ if (m_members.empty())
+ {
+ Disband();
+ return true;
+ }
+
+ return false;
}
bool Guild::ChangeMemberRank(CharacterDatabaseTransaction trans, ObjectGuid guid, uint8 newRank)
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index ba11f5fb470..45e75a985e3 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -22,6 +22,7 @@
#include "ObjectGuid.h"
#include "Optional.h"
#include "SharedDefines.h"
+#include "UniqueTrackablePtr.h"
#include <set>
#include <unordered_map>
#include <unordered_set>
@@ -714,7 +715,7 @@ class TC_GAME_API Guild
// Members
// Adds member to guild. If rankId == GUILD_RANK_NONE, lowest rank is assigned.
bool AddMember(CharacterDatabaseTransaction trans, ObjectGuid guid, uint8 rankId = GUILD_RANK_NONE);
- void DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bool isDisbanding = false, bool isKicked = false, bool canDeleteGuild = false);
+ bool DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bool isDisbanding = false, bool isKicked = false);
bool ChangeMemberRank(CharacterDatabaseTransaction trans, ObjectGuid guid, uint8 newRank);
uint64 GetMemberAvailableMoneyForRepairItems(ObjectGuid guid) const;
@@ -727,6 +728,9 @@ class TC_GAME_API Guild
void ResetTimes();
+ Trinity::unique_weak_ptr<Guild> GetWeakPtr() const { return m_weakRef; }
+ void SetWeakPtr(Trinity::unique_weak_ptr<Guild> weakRef) { m_weakRef = std::move(weakRef); }
+
protected:
ObjectGuid::LowType m_id;
std::string m_name;
@@ -747,6 +751,8 @@ class TC_GAME_API Guild
LogHolder<EventLogEntry> m_eventLog;
std::array<LogHolder<BankEventLogEntry>, GUILD_BANK_MAX_TABS + 1> m_bankEventLog = {};
+ Trinity::unique_weak_ptr<Guild> m_weakRef;
+
private:
inline uint8 _GetRanksSize() const { return uint8(m_ranks.size()); }
inline RankInfo const* GetRankInfo(uint8 rankId) const { return rankId < _GetRanksSize() ? &m_ranks[rankId] : nullptr; }
diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp
index 21f58962514..bf804ecb9cb 100644
--- a/src/server/game/Guilds/GuildMgr.cpp
+++ b/src/server/game/Guilds/GuildMgr.cpp
@@ -26,15 +26,13 @@
GuildMgr::GuildMgr() : NextGuildId(1)
{ }
-GuildMgr::~GuildMgr()
-{
- for (GuildContainer::iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
- delete itr->second;
-}
+GuildMgr::~GuildMgr() = default;
void GuildMgr::AddGuild(Guild* guild)
{
- GuildStore[guild->GetId()] = guild;
+ Trinity::unique_trackable_ptr<Guild>& ptr = GuildStore[guild->GetId()];
+ ptr.reset(guild);
+ guild->SetWeakPtr(ptr);
}
void GuildMgr::RemoveGuild(ObjectGuid::LowType guildId)
@@ -57,16 +55,16 @@ Guild* GuildMgr::GetGuildById(ObjectGuid::LowType guildId) const
{
GuildContainer::const_iterator itr = GuildStore.find(guildId);
if (itr != GuildStore.end())
- return itr->second;
+ return itr->second.get();
return nullptr;
}
Guild* GuildMgr::GetGuildByName(std::string_view guildName) const
{
- for (auto [id, guild] : GuildStore)
+ for (auto const& [id, guild] : GuildStore)
if (StringEqualI(guild->GetName(), guildName))
- return guild;
+ return guild.get();
return nullptr;
}
@@ -89,7 +87,7 @@ Guild* GuildMgr::GetGuildByLeader(ObjectGuid guid) const
{
for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
if (itr->second->GetLeaderGUID() == guid)
- return itr->second;
+ return itr->second.get();
return nullptr;
}
@@ -387,10 +385,10 @@ void GuildMgr::LoadGuilds()
for (GuildContainer::iterator itr = GuildStore.begin(); itr != GuildStore.end();)
{
- Guild* guild = itr->second;
+ Guild* guild = itr->second.get();
++itr;
- if (guild && !guild->Validate())
- delete guild;
+ if (guild)
+ guild->Validate();
}
TC_LOG_INFO("server.loading", ">> Validated data of loaded guilds in {} ms", GetMSTimeDiffToNow(oldMSTime));
@@ -400,7 +398,7 @@ void GuildMgr::LoadGuilds()
void GuildMgr::ResetTimes()
{
for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
- if (Guild* guild = itr->second)
+ if (Guild* guild = itr->second.get())
guild->ResetTimes();
CharacterDatabase.DirectExecute("TRUNCATE guild_member_withdraw");
diff --git a/src/server/game/Guilds/GuildMgr.h b/src/server/game/Guilds/GuildMgr.h
index 00d2136623a..8a48ae32b2c 100644
--- a/src/server/game/Guilds/GuildMgr.h
+++ b/src/server/game/Guilds/GuildMgr.h
@@ -20,6 +20,7 @@
#include "Define.h"
#include "ObjectGuid.h"
+#include "UniqueTrackablePtr.h"
#include <unordered_map>
#include <vector>
@@ -50,7 +51,7 @@ public:
void ResetTimes();
protected:
- typedef std::unordered_map<ObjectGuid::LowType, Guild*> GuildContainer;
+ typedef std::unordered_map<ObjectGuid::LowType, Trinity::unique_trackable_ptr<Guild>> GuildContainer;
ObjectGuid::LowType NextGuildId;
GuildContainer GuildStore;
};
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 7e972ce874e..1678a942926 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1877,7 +1877,7 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
{
// Reset guild
if (Guild* guild = sGuildMgr->GetGuildById(characterInfo->GuildId))
- guild->DeleteMember(trans, factionChangeInfo->Guid, false, false, true);
+ guild->DeleteMember(trans, factionChangeInfo->Guid, false, false);
Player::LeaveAllArenaTeams(factionChangeInfo->Guid);
}
@@ -1992,14 +1992,14 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
// Disable all old-faction specific quests
{
ObjectMgr::QuestContainer const& questTemplates = sObjectMgr->GetQuestTemplates();
- for (auto const& questTemplatePair : questTemplates)
+ for (auto const& [questId, quest] : questTemplates)
{
uint32 newRaceMask = (newTeam == ALLIANCE) ? RACEMASK_ALLIANCE : RACEMASK_HORDE;
- if (questTemplatePair.second.GetAllowableRaces() && !(questTemplatePair.second.GetAllowableRaces() & newRaceMask))
+ if (quest->GetAllowableRaces() && !(quest->GetAllowableRaces() & newRaceMask))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST);
stmt->setUInt32(0, lowGuid);
- stmt->setUInt32(1, questTemplatePair.first);
+ stmt->setUInt32(1, questId);
trans->Append(stmt);
}
}
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index cfd11dcfb78..90914ba6218 100644
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -689,17 +689,12 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b
}
// note: this isn't fast but it's meant to be executed very rarely
- Map const* map = sMapMgr->CreateBaseMap(mapid); // _not_ include difficulty
- MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps();
- MapInstanced::InstancedMaps::iterator mitr;
+ Map* baseMap = sMapMgr->CreateBaseMap(mapid); // _not_ include difficulty
uint32 timeLeft;
- for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)
+ for (auto& [_, map] : baseMap->ToMapInstanced()->GetInstancedMaps())
{
- Map* map2 = mitr->second;
- if (!map2->IsDungeon())
- continue;
-
+ InstanceMap* instanceMap = map->ToInstanceMap();
if (warn)
{
if (now >= resetTime)
@@ -707,10 +702,10 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b
else
timeLeft = uint32(resetTime - now);
- ((InstanceMap*)map2)->SendResetWarnings(timeLeft);
+ instanceMap->SendResetWarnings(timeLeft);
}
else
- ((InstanceMap*)map2)->Reset(INSTANCE_RESET_GLOBAL);
+ instanceMap->Reset(INSTANCE_RESET_GLOBAL);
}
/// @todo delete creature/gameobject respawn times even if the maps are not loaded
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index dadd8cc14de..e51e50cbf7e 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -32,6 +32,7 @@
#include "SpawnData.h"
#include "Timer.h"
#include "Transaction.h"
+#include "UniqueTrackablePtr.h"
#include <bitset>
#include <list>
#include <memory>
@@ -429,6 +430,9 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
uint32 GetInstanceId() const { return i_InstanceId; }
uint8 GetSpawnMode() const { return (i_spawnMode); }
+ Trinity::unique_weak_ptr<Map> GetWeakPtr() const { return m_weakRef; }
+ void SetWeakPtr(Trinity::unique_weak_ptr<Map> weakRef) { m_weakRef = std::move(weakRef); }
+
enum EnterState
{
CAN_ENTER = 0,
@@ -710,6 +714,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
MapEntry const* i_mapEntry;
uint8 i_spawnMode;
uint32 i_InstanceId;
+ Trinity::unique_weak_ptr<Map> m_weakRef;
uint32 m_unloadTimer;
float m_VisibleDistance;
DynamicMapTree _dynamicTree;
diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp
index 141f1808ebe..ccd2d962152 100644
--- a/src/server/game/Maps/MapInstanced.cpp
+++ b/src/server/game/Maps/MapInstanced.cpp
@@ -97,10 +97,6 @@ void MapInstanced::UnloadAll()
for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
i->second->UnloadAll();
- // Delete the maps only after everything is unloaded to prevent crashes
- for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
- delete i->second;
-
m_InstancedMaps.clear();
// Unload own grids (just dummy(placeholder) grids, neccesary to unload GridMaps!)
@@ -237,7 +233,9 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save,
if (sWorld->getBoolConfig(CONFIG_INSTANCEMAP_LOAD_GRIDS))
map->LoadAllCells();
- m_InstancedMaps[InstanceId] = map;
+ Trinity::unique_trackable_ptr<Map>& ptr = m_InstancedMaps[InstanceId];
+ ptr.reset(map);
+ map->SetWeakPtr(ptr);
return map;
}
@@ -262,7 +260,9 @@ BattlegroundMap* MapInstanced::CreateBattleground(uint32 InstanceId, Battlegroun
map->SetBG(bg);
bg->SetBgMap(map);
- m_InstancedMaps[InstanceId] = map;
+ Trinity::unique_trackable_ptr<Map>& ptr = m_InstancedMaps[InstanceId];
+ ptr.reset(map);
+ map->SetWeakPtr(ptr);
return map;
}
@@ -292,7 +292,6 @@ bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr)
sMapMgr->FreeInstanceId(itr->second->GetInstanceId());
// erase map
- delete itr->second;
m_InstancedMaps.erase(itr++);
return true;
diff --git a/src/server/game/Maps/MapInstanced.h b/src/server/game/Maps/MapInstanced.h
index d60abbc25d1..2d26f559bad 100644
--- a/src/server/game/Maps/MapInstanced.h
+++ b/src/server/game/Maps/MapInstanced.h
@@ -18,15 +18,16 @@
#ifndef TRINITY_MAP_INSTANCED_H
#define TRINITY_MAP_INSTANCED_H
-#include "Map.h"
-#include "InstanceSaveMgr.h"
#include "DBCEnums.h"
+#include "InstanceSaveMgr.h"
+#include "Map.h"
+#include "UniqueTrackablePtr.h"
class TC_GAME_API MapInstanced : public Map
{
friend class MapManager;
public:
- typedef std::unordered_map< uint32, Map*> InstancedMaps;
+ typedef std::unordered_map<uint32, Trinity::unique_trackable_ptr<Map>> InstancedMaps;
MapInstanced(uint32 id, time_t expiry);
~MapInstanced() { }
@@ -42,7 +43,7 @@ class TC_GAME_API MapInstanced : public Map
Map* FindInstanceMap(uint32 instanceId) const
{
InstancedMaps::const_iterator i = m_InstancedMaps.find(instanceId);
- return(i == m_InstancedMaps.end() ? nullptr : i->second);
+ return(i == m_InstancedMaps.end() ? nullptr : i->second.get());
}
bool DestroyInstance(InstancedMaps::iterator &itr);
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index 1d17f6caa98..d340a85e4df 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -33,6 +33,7 @@
#include "Player.h"
#include "WorldSession.h"
#include "Opcodes.h"
+#include <numeric>
MapManager::MapManager()
: _nextInstanceId(0), _scheduledScripts(0)
@@ -85,7 +86,9 @@ Map* MapManager::CreateBaseMap(uint32 id)
map->LoadCorpseData();
}
- i_maps[id] = map;
+ Trinity::unique_trackable_ptr<Map>& ptr = i_maps[id];
+ ptr.reset(map);
+ map->SetWeakPtr(ptr);
}
ASSERT(map);
@@ -255,12 +258,12 @@ bool MapManager::IsValidMAP(uint32 mapid, bool startUp)
void MapManager::UnloadAll()
{
- for (MapMapType::iterator iter = i_maps.begin(); iter != i_maps.end();)
- {
+ // first unload maps
+ for (auto iter = i_maps.begin(); iter != i_maps.end(); ++iter)
iter->second->UnloadAll();
- delete iter->second;
- i_maps.erase(iter++);
- }
+
+ // then delete them
+ i_maps.clear();
if (m_updater.activated())
m_updater.deactivate();
@@ -273,14 +276,12 @@ uint32 MapManager::GetNumInstances()
std::lock_guard<std::mutex> lock(_mapsLock);
uint32 ret = 0;
- for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr)
+ for (auto const& [_, map] : i_maps)
{
- Map* map = itr->second;
- if (!map->Instanceable())
+ MapInstanced* mapInstanced = map->ToMapInstanced();
+ if (!mapInstanced)
continue;
- MapInstanced::InstancedMaps &maps = ((MapInstanced*)map)->GetInstancedMaps();
- for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr)
- if (mitr->second->IsDungeon()) ret++;
+ ret += mapInstanced->GetInstancedMaps().size();
}
return ret;
}
@@ -290,15 +291,13 @@ uint32 MapManager::GetNumPlayersInInstances()
std::lock_guard<std::mutex> lock(_mapsLock);
uint32 ret = 0;
- for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr)
+ for (auto& [_, map] : i_maps)
{
- Map* map = itr->second;
- if (!map->Instanceable())
+ MapInstanced* mapInstanced = map->ToMapInstanced();
+ if (!mapInstanced)
continue;
- MapInstanced::InstancedMaps &maps = ((MapInstanced*)map)->GetInstancedMaps();
- for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr)
- if (mitr->second->IsDungeon())
- ret += ((InstanceMap*)mitr->second)->GetPlayers().getSize();
+ MapInstanced::InstancedMaps& maps = mapInstanced->GetInstancedMaps();
+ ret += std::accumulate(maps.begin(), maps.end(), 0u, [](uint32 total, MapInstanced::InstancedMaps::value_type const& value) { return total + value.second->GetPlayers().getSize(); });
}
return ret;
}
diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h
index 2323e31ab9a..5754415ba73 100644
--- a/src/server/game/Maps/MapManager.h
+++ b/src/server/game/Maps/MapManager.h
@@ -23,6 +23,7 @@
#include "MapInstanced.h"
#include "GridStates.h"
#include "MapUpdater.h"
+#include "UniqueTrackablePtr.h"
#include <boost/dynamic_bitset.hpp>
class Transport;
@@ -140,7 +141,7 @@ class TC_GAME_API MapManager
bool IsScriptScheduled() const { return _scheduledScripts > 0; }
private:
- typedef std::unordered_map<uint32, Map*> MapMapType;
+ typedef std::unordered_map<uint32, Trinity::unique_trackable_ptr<Map>> MapMapType;
typedef boost::dynamic_bitset<size_t> InstanceIds;
MapManager();
@@ -149,7 +150,7 @@ class TC_GAME_API MapManager
Map* FindBaseMap(uint32 mapId) const
{
MapMapType::const_iterator iter = i_maps.find(mapId);
- return (iter == i_maps.end() ? nullptr : iter->second);
+ return (iter == i_maps.end() ? nullptr : iter->second.get());
}
MapManager(MapManager const&) = delete;
@@ -175,12 +176,12 @@ void MapManager::DoForAllMaps(Worker&& worker)
for (auto& mapPair : i_maps)
{
- Map* map = mapPair.second;
+ Map* map = mapPair.second.get();
if (MapInstanced* mapInstanced = map->ToMapInstanced())
{
MapInstanced::InstancedMaps& instances = mapInstanced->GetInstancedMaps();
for (auto& instancePair : instances)
- worker(instancePair.second);
+ worker(instancePair.second.get());
}
else
worker(map);
@@ -195,12 +196,12 @@ inline void MapManager::DoForAllMapsWithMapId(uint32 mapId, Worker&& worker)
auto itr = i_maps.find(mapId);
if (itr != i_maps.end())
{
- Map* map = itr->second;
+ Map* map = itr->second.get();
if (MapInstanced* mapInstanced = map->ToMapInstanced())
{
MapInstanced::InstancedMaps& instances = mapInstanced->GetInstancedMaps();
for (auto& p : instances)
- worker(p.second);
+ worker(p.second.get());
}
else
worker(map);
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index a8d3fa98661..6e9a0be33df 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -22,6 +22,7 @@
#include "DatabaseEnvFwd.h"
#include "DBCEnums.h"
#include "SharedDefines.h"
+#include "UniqueTrackablePtr.h"
#include "WorldPacket.h"
#include <vector>
@@ -332,6 +333,8 @@ class TC_GAME_API Quest
void BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player* player, bool sendHiddenRewards = false) const;
+ Trinity::unique_weak_ptr<Quest> GetWeakPtr() const { return _weakRef; }
+
std::vector<uint32> DependentPreviousQuests;
std::vector<uint32> DependentBreadcrumbQuests;
WorldPacket QueryData[TOTAL_LOCALES];
@@ -408,6 +411,8 @@ class TC_GAME_API Quest
// Helpers
static uint32 RoundXPValue(uint32 xp);
+
+ Trinity::unique_weak_ptr<Quest> _weakRef;
};
struct QuestStatusData
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 2543219d436..c987893f2bd 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -428,7 +428,7 @@ m_castItemGuid(createInfo.CastItemGUID), m_applyTime(GameTime::GetGameTime()),
m_owner(createInfo._owner), m_timeCla(0), m_updateTargetMapInterval(0),
_casterInfo(), m_procCharges(0), m_stackAmount(1),
m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr),
-m_procCooldown(TimePoint::min())
+m_procCooldown(TimePoint::min()), m_scriptRef(this, NoopAuraDeleter())
{
if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel)
m_timeCla = 1 * IN_MILLISECONDS;
@@ -618,6 +618,8 @@ void Aura::_Remove(AuraRemoveMode removeMode)
m_dropEvent->ScheduleAbort();
m_dropEvent = nullptr;
}
+
+ m_scriptRef = nullptr;
}
void Aura::UpdateTargetMap(Unit* caster, bool apply)
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index 126f11141b3..f392ad6fb2f 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -20,6 +20,7 @@
#include "SpellAuraDefines.h"
#include "SpellInfo.h"
+#include "UniqueTrackablePtr.h"
class SpellInfo;
struct SpellModifier;
@@ -269,6 +270,14 @@ class TC_GAME_API Aura
virtual std::string GetDebugInfo() const;
+ Trinity::unique_weak_ptr<Aura> GetWeakPtr() const { return m_scriptRef; }
+
+ Aura(Aura const&) = delete;
+ Aura(Aura&&) = delete;
+
+ Aura& operator=(Aura const&) = delete;
+ Aura& operator=(Aura&&) = delete;
+
private:
AuraScript* GetScriptByName(std::string const& scriptName) const;
void _DeleteRemovedApplications();
@@ -302,6 +311,9 @@ class TC_GAME_API Aura
private:
std::vector<AuraApplication*> _removedApplications;
+
+ struct NoopAuraDeleter { void operator()(Aura*) const { /*noop - not managed*/ } };
+ Trinity::unique_trackable_ptr<Aura> m_scriptRef;
};
class TC_GAME_API UnitAura : public Aura
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 13731b2679a..22b2b3a4c18 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -55,6 +55,7 @@
#include "Unit.h"
#include "UpdateData.h"
#include "UpdateMask.h"
+#include "UniqueTrackablePtr.h"
#include "Util.h"
#include "Vehicle.h"
#include "VMapFactory.h"
@@ -487,16 +488,20 @@ SpellValue::SpellValue(SpellInfo const* proto)
class TC_GAME_API SpellEvent : public BasicEvent
{
- public:
- SpellEvent(Spell* spell);
- ~SpellEvent();
+public:
+ explicit SpellEvent(Spell* spell);
+ ~SpellEvent();
+
+ bool Execute(uint64 e_time, uint32 p_time) override;
+ void Abort(uint64 e_time) override;
+ bool IsDeletable() const override;
+ Spell const* GetSpell() const { return m_Spell.get(); }
+ Trinity::unique_weak_ptr<Spell> GetSpellWeakPtr() const { return m_Spell; }
- bool Execute(uint64 e_time, uint32 p_time) override;
- void Abort(uint64 e_time) override;
- bool IsDeletable() const override;
+ std::string GetDebugInfo() const { return m_Spell->GetDebugInfo(); }
- protected:
- Spell* m_Spell;
+protected:
+ Trinity::unique_trackable_ptr<Spell> m_Spell;
};
Spell::Spell(WorldObject* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID) :
@@ -7430,9 +7435,8 @@ Unit* Spell::GetUnitCasterForEffectHandlers() const
return m_originalCaster ? m_originalCaster : m_caster->ToUnit();
}
-SpellEvent::SpellEvent(Spell* spell) : BasicEvent()
+SpellEvent::SpellEvent(Spell* spell) : BasicEvent(), m_Spell(spell)
{
- m_Spell = spell;
}
SpellEvent::~SpellEvent()
@@ -7440,11 +7444,7 @@ SpellEvent::~SpellEvent()
if (m_Spell->getState() != SPELL_STATE_FINISHED)
m_Spell->cancel();
- if (m_Spell->IsDeletable())
- {
- delete m_Spell;
- }
- else
+ if (!m_Spell->IsDeletable())
{
TC_LOG_ERROR("spells", "~SpellEvent: {} {} tried to delete non-deletable spell {}. Was not deleted, causes memory leak.",
(m_Spell->GetCaster()->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), m_Spell->GetCaster()->GetGUID().ToString(), m_Spell->m_spellInfo->Id);
@@ -8177,6 +8177,11 @@ std::string Spell::GetDebugInfo() const
return sstr.str();
}
+Trinity::unique_weak_ptr<Spell> Spell::GetWeakPtr() const
+{
+ return _spellEvent->GetSpellWeakPtr();
+}
+
void Spell::CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 3359bf6d730..8dbcdd9ad7d 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -24,6 +24,7 @@
#include "Position.h"
#include "SharedDefines.h"
#include "SpellDefines.h"
+#include "UniqueTrackablePtr.h"
#include <memory>
namespace WorldPackets
@@ -458,6 +459,9 @@ class TC_GAME_API Spell
Spell** m_selfContainer; // pointer to our spell container (if applicable)
std::string GetDebugInfo() const;
+
+ Trinity::unique_weak_ptr<Spell> GetWeakPtr() const;
+
void CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount);
protected:
diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp
index 73255185c67..bd3403fa40e 100644
--- a/src/server/scripts/Commands/cs_guild.cpp
+++ b/src/server/scripts/Commands/cs_guild.cpp
@@ -141,8 +141,6 @@ public:
return false;
targetGuild->Disband();
- delete targetGuild;
-
return true;
}
@@ -190,7 +188,7 @@ public:
return false;
CharacterDatabaseTransaction trans(nullptr);
- targetGuild->DeleteMember(trans, targetGuid, false, true, true);
+ targetGuild->DeleteMember(trans, targetGuid, false, true);
return true;
}
diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp
index 57fe66a981f..2da6946a2e3 100644
--- a/src/server/scripts/Commands/cs_learn.cpp
+++ b/src/server/scripts/Commands/cs_learn.cpp
@@ -140,8 +140,8 @@ public:
Player* player = handler->GetPlayer();
for (auto const& [id, quest] : sObjectMgr->GetQuestTemplates())
{
- if (quest.GetRequiredClasses() && player->SatisfyQuestClass(&quest, false))
- player->LearnQuestRewardedSpells(&quest);
+ if (quest->GetRequiredClasses() && player->SatisfyQuestClass(quest.get(), false))
+ player->LearnQuestRewardedSpells(quest.get());
}
return true;
}
diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp
index b14bc9661c9..dfdbdc39586 100644
--- a/src/server/scripts/Commands/cs_lookup.cpp
+++ b/src/server/scripts/Commands/cs_lookup.cpp
@@ -710,7 +710,7 @@ public:
}
if (handler->GetSession())
- handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, questTemplatePair.first, questTemplatePair.first, questTemplatePair.second.GetQuestLevel(), title.c_str(), statusStr);
+ handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, questTemplatePair.first, questTemplatePair.first, questTemplatePair.second->GetQuestLevel(), title.c_str(), statusStr);
else
handler->PSendSysMessage(LANG_QUEST_LIST_CONSOLE, questTemplatePair.first, title.c_str(), statusStr);
@@ -722,7 +722,7 @@ public:
}
}
- std::string const& title = questTemplatePair.second.GetTitle();
+ std::string const& title = questTemplatePair.second->GetTitle();
if (title.empty())
continue;
@@ -755,7 +755,7 @@ public:
}
if (handler->GetSession())
- handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, questTemplatePair.first, questTemplatePair.first, questTemplatePair.second.GetQuestLevel(), title.c_str(), statusStr);
+ handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, questTemplatePair.first, questTemplatePair.first, questTemplatePair.second->GetQuestLevel(), title.c_str(), statusStr);
else
handler->PSendSysMessage(LANG_QUEST_LIST_CONSOLE, questTemplatePair.first, title.c_str(), statusStr);