aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Phasing/PersonalPhaseTracker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Phasing/PersonalPhaseTracker.cpp')
-rw-r--r--src/server/game/Phasing/PersonalPhaseTracker.cpp203
1 files changed, 203 insertions, 0 deletions
diff --git a/src/server/game/Phasing/PersonalPhaseTracker.cpp b/src/server/game/Phasing/PersonalPhaseTracker.cpp
new file mode 100644
index 00000000000..db73485b352
--- /dev/null
+++ b/src/server/game/Phasing/PersonalPhaseTracker.cpp
@@ -0,0 +1,203 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "PersonalPhaseTracker.h"
+#include "Containers.h"
+#include "Log.h"
+#include "Map.h"
+#include "Object.h"
+#include "ObjectGridLoader.h"
+#include "ObjectMgr.h"
+#include "PhasingHandler.h"
+
+ /*********************************************************/
+ /*** PlayerPersonalPhasesTracker ***/
+ /*********************************************************/
+
+void PlayerPersonalPhasesTracker::RegisterTrackedObject(uint32 phaseId, WorldObject* object)
+{
+ _spawns[phaseId].Objects.insert(object);
+}
+
+void PlayerPersonalPhasesTracker::UnregisterTrackedObject(WorldObject* object)
+{
+ for (auto& [_, spawns] : _spawns)
+ spawns.Objects.erase(object);
+}
+
+void PlayerPersonalPhasesTracker::OnOwnerPhasesChanged(WorldObject const* owner)
+{
+ PhaseShift const& phaseShift = owner->GetPhaseShift();
+
+ // Loop over all our tracked phases. If any don't exist - delete them
+ for (auto& [phaseId, spawns] : _spawns)
+ if (!spawns.DurationRemaining && !phaseShift.HasPhase(phaseId))
+ spawns.DurationRemaining = PersonalPhaseSpawns::DELETE_TIME_DEFAULT;
+
+ // loop over all owner phases. If any exist and marked for deletion - reset delete
+ for (PhaseShift::PhaseRef const& phaseRef : phaseShift.GetPhases())
+ if (PersonalPhaseSpawns* spawns = Trinity::Containers::MapGetValuePtr(_spawns, phaseRef.Id))
+ spawns->DurationRemaining.reset();
+}
+
+void PlayerPersonalPhasesTracker::MarkAllPhasesForDeletion()
+{
+ for (auto& [_, spawns] : _spawns)
+ spawns.DurationRemaining = PersonalPhaseSpawns::DELETE_TIME_DEFAULT;
+}
+
+void PlayerPersonalPhasesTracker::Update(Map* map, uint32 diff)
+{
+ for (auto itr = _spawns.begin(); itr != _spawns.end(); )
+ {
+ if (itr->second.DurationRemaining)
+ {
+ itr->second.DurationRemaining = *itr->second.DurationRemaining - Milliseconds(diff);
+ if (itr->second.DurationRemaining <= Milliseconds::zero())
+ {
+ DespawnPhase(map, itr->second);
+ itr = _spawns.erase(itr);
+ continue;
+ }
+ }
+ ++itr;
+ }
+}
+
+bool PlayerPersonalPhasesTracker::IsGridLoadedForPhase(uint32 gridId, uint32 phaseId) const
+{
+ if (PersonalPhaseSpawns const* spawns = Trinity::Containers::MapGetValuePtr(_spawns, phaseId))
+ return spawns->Grids.find(gridId) != spawns->Grids.cend();
+
+ return false;
+}
+
+void PlayerPersonalPhasesTracker::SetGridLoadedForPhase(uint32 gridId, uint32 phaseId)
+{
+ PersonalPhaseSpawns& group = _spawns[phaseId];
+ group.Grids.insert(gridId);
+}
+
+void PlayerPersonalPhasesTracker::SetGridUnloaded(uint32 gridId)
+{
+ for (auto itr = _spawns.begin(); itr != _spawns.end(); )
+ {
+ itr->second.Grids.erase(gridId);
+ if (itr->second.IsEmpty())
+ itr = _spawns.erase(itr);
+ else
+ ++itr;
+ }
+}
+
+void PlayerPersonalPhasesTracker::DespawnPhase(Map* map, PersonalPhaseSpawns& spawns)
+{
+ for (WorldObject* obj : spawns.Objects)
+ map->AddObjectToRemoveList(obj);
+
+ spawns.Objects.clear();
+ spawns.Grids.clear();
+}
+
+/*********************************************************/
+/*** MultiPersonalPhaseTracker ***/
+/*********************************************************/
+
+void MultiPersonalPhaseTracker::LoadGrid(PhaseShift const& phaseShift, NGridType& grid, Map* map, Cell const& cell)
+{
+ if (!phaseShift.HasPersonalPhase())
+ return;
+
+ PersonalPhaseGridLoader loader(grid, map, cell, phaseShift.GetPersonalGuid());
+ PlayerPersonalPhasesTracker& playerTracker = _playerData[phaseShift.GetPersonalGuid()];
+
+ for (PhaseShift::PhaseRef const& phaseRef : phaseShift.GetPhases())
+ {
+ if (!phaseRef.IsPersonal())
+ continue;
+
+ if (!sObjectMgr->HasPersonalSpawns(map->GetId(), map->GetDifficultyID(), phaseRef.Id))
+ continue;
+
+ if (playerTracker.IsGridLoadedForPhase(grid.GetGridId(), phaseRef.Id))
+ continue;
+
+ TC_LOG_DEBUG("maps", "Loading personal phase objects (phase %u) in grid[%u, %u] for map %u instance %u",
+ phaseRef.Id, cell.GridX(), cell.GridY(), map->GetId(), map->GetInstanceId());
+
+ loader.Load(phaseRef.Id);
+
+ playerTracker.SetGridLoadedForPhase(grid.GetGridId(), phaseRef.Id);
+ }
+
+ if (loader.GetLoadedGameObjects())
+ map->Balance();
+}
+
+void MultiPersonalPhaseTracker::UnloadGrid(NGridType& grid)
+{
+ for (auto itr = _playerData.begin(); itr != _playerData.end(); )
+ {
+ itr->second.SetGridUnloaded(grid.GetGridId());
+ if (itr->second.IsEmpty())
+ itr = _playerData.erase(itr);
+ else
+ ++itr;
+ }
+}
+
+void MultiPersonalPhaseTracker::RegisterTrackedObject(uint32 phaseId, ObjectGuid const& phaseOwner, WorldObject* object)
+{
+ ASSERT(phaseId);
+ ASSERT(!phaseOwner.IsEmpty());
+ ASSERT(object);
+
+ _playerData[phaseOwner].RegisterTrackedObject(phaseId, object);
+}
+
+void MultiPersonalPhaseTracker::UnregisterTrackedObject(WorldObject* object)
+{
+ if (PlayerPersonalPhasesTracker* playerTracker = Trinity::Containers::MapGetValuePtr(_playerData, object->GetPhaseShift().GetPersonalGuid()))
+ playerTracker->UnregisterTrackedObject(object);
+}
+
+void MultiPersonalPhaseTracker::OnOwnerPhaseChanged(WorldObject const* phaseOwner, NGridType* grid, Map* map, Cell const& cell)
+{
+ if (PlayerPersonalPhasesTracker* playerTracker = Trinity::Containers::MapGetValuePtr(_playerData, phaseOwner->GetGUID()))
+ playerTracker->OnOwnerPhasesChanged(phaseOwner);
+
+ if (grid)
+ LoadGrid(phaseOwner->GetPhaseShift(), *grid, map, cell);
+}
+
+void MultiPersonalPhaseTracker::MarkAllPhasesForDeletion(ObjectGuid const& phaseOwner)
+{
+ if (PlayerPersonalPhasesTracker* playerTracker = Trinity::Containers::MapGetValuePtr(_playerData, phaseOwner))
+ playerTracker->MarkAllPhasesForDeletion();
+}
+
+void MultiPersonalPhaseTracker::Update(Map* map, uint32 diff)
+{
+ for (auto itr = _playerData.begin(); itr != _playerData.end(); )
+ {
+ itr->second.Update(map, diff);
+ if (itr->second.IsEmpty())
+ itr = _playerData.erase(itr);
+ else
+ ++itr;
+ }
+}