aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2022-07-24 18:56:40 +0200
committerShauren <shauren.trinity@gmail.com>2022-07-24 18:56:40 +0200
commitfbe0b8efebca3bc2662b477bdf45627f9783d6c2 (patch)
tree6f5662045be0c4e5f06d8a97f9669b7f93cf2df1
parent8f2c5413d7a3775a304c793653d41caabf3ba997 (diff)
Core/Maps: Removed MapInstanced - no longer neccessary for grid data reference counting (moved to TerrainInfo)
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp1
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp2
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp1
-rw-r--r--src/server/game/Events/GameEventMgr.cpp1
-rw-r--r--src/server/game/Garrison/GarrisonMap.cpp4
-rw-r--r--src/server/game/Garrison/GarrisonMap.h2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp4
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp1
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.cpp38
-rw-r--r--src/server/game/Maps/Map.cpp272
-rw-r--r--src/server/game/Maps/Map.h15
-rw-r--r--src/server/game/Maps/MapInstanced.cpp311
-rw-r--r--src/server/game/Maps/MapInstanced.h64
-rw-r--r--src/server/game/Maps/MapManager.cpp340
-rw-r--r--src/server/game/Maps/MapManager.h106
-rw-r--r--src/server/game/Maps/TerrainMgr.cpp27
-rw-r--r--src/server/game/Maps/TerrainMgr.h3
-rw-r--r--src/server/game/Maps/TransportMgr.cpp2
-rw-r--r--src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp12
-rw-r--r--src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h2
-rw-r--r--src/server/game/Movement/Waypoints/WaypointManager.cpp1
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.cpp1
-rw-r--r--src/server/game/World/World.cpp14
-rw-r--r--src/server/scripts/Battlefield/BattlefieldTB.cpp1
-rw-r--r--src/server/scripts/Battlefield/BattlefieldWG.cpp1
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp18
-rw-r--r--src/server/scripts/Commands/cs_gobject.cpp1
-rw-r--r--src/server/scripts/Commands/cs_instance.cpp1
-rw-r--r--src/server/scripts/Commands/cs_list.cpp46
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp2
-rw-r--r--src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp2
-rw-r--r--src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp1
34 files changed, 496 insertions, 805 deletions
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index 02be080a4a7..4a81ad485d3 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -34,6 +34,7 @@
#include "Item.h"
#include "LanguageMgr.h"
#include "Log.h"
+#include "Map.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "PhasingHandler.h"
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index 94881ea0f32..9fc08c82604 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -28,11 +28,9 @@
#include "GroupMgr.h"
#include "Log.h"
#include "Map.h"
-#include "MapManager.h"
#include "MiscPackets.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
-#include "WorldSession.h"
#include <G3D/g3dmath.h>
Battlefield::Battlefield(Map* map)
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index 29fcc2c7719..58e8243b990 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -37,8 +37,6 @@
#include "GameEventMgr.h"
#include "Language.h"
#include "Log.h"
-#include "Map.h"
-#include "MapInstanced.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "Player.h"
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 4bc63a2c304..f2d7be4ae62 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1430,7 +1430,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// Check enter rights before map getting to avoid creating instance copy for player
// this check not dependent from map instance copy and same for all instance copies of selected map
- if (sMapMgr->PlayerCannotEnter(mapid, this, false))
+ if (Map::PlayerCannotEnter(mapid, this, false))
return false;
// Seamless teleport can happen only if cosmetic maps match
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index cd6d33e5f7b..eb8e5aea43a 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -24,7 +24,6 @@
#include "GameObjectAI.h"
#include "GameTime.h"
#include "Log.h"
-#include "MapManager.h"
#include "ObjectMgr.h"
#include "PhasingHandler.h"
#include "Player.h"
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index daf0a510deb..b18b36aeedc 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -26,6 +26,7 @@
#include "GameTime.h"
#include "Language.h"
#include "Log.h"
+#include "Map.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "Player.h"
diff --git a/src/server/game/Garrison/GarrisonMap.cpp b/src/server/game/Garrison/GarrisonMap.cpp
index 33058bac1b6..4bafb964dab 100644
--- a/src/server/game/Garrison/GarrisonMap.cpp
+++ b/src/server/game/Garrison/GarrisonMap.cpp
@@ -100,8 +100,8 @@ void GarrisonGridLoader::Visit(CreatureMapType& /*m*/)
}
-GarrisonMap::GarrisonMap(uint32 id, time_t expiry, uint32 instanceId, Map* parent, ObjectGuid const& owner)
- : Map(id, expiry, instanceId, DIFFICULTY_NORMAL, parent), _owner(owner), _loadingPlayer(nullptr)
+GarrisonMap::GarrisonMap(uint32 id, time_t expiry, uint32 instanceId, ObjectGuid const& owner)
+ : Map(id, expiry, instanceId, DIFFICULTY_NORMAL), _owner(owner), _loadingPlayer(nullptr)
{
GarrisonMap::InitVisibilityDistance();
}
diff --git a/src/server/game/Garrison/GarrisonMap.h b/src/server/game/Garrison/GarrisonMap.h
index dd9c41baf57..4fbcb240e39 100644
--- a/src/server/game/Garrison/GarrisonMap.h
+++ b/src/server/game/Garrison/GarrisonMap.h
@@ -26,7 +26,7 @@ class Player;
class TC_GAME_API GarrisonMap : public Map
{
public:
- GarrisonMap(uint32 id, time_t, uint32 instanceId, Map* parent, ObjectGuid const& owner);
+ GarrisonMap(uint32 id, time_t, uint32 instanceId, ObjectGuid const& owner);
void LoadGridObjects(NGridType* grid, Cell const& cell) override;
Garrison* GetGarrison();
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index aff58ca046d..b4b2ca8a98b 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -36,9 +36,11 @@
#include "Guild.h"
#include "GuildMgr.h"
#include "InstancePackets.h"
+#include "InstanceSaveMgr.h"
#include "InstanceScript.h"
#include "Language.h"
#include "Log.h"
+#include "Map.h"
#include "MapManager.h"
#include "MiscPackets.h"
#include "Object.h"
@@ -571,7 +573,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::AreaTrigger::AreaTrigge
bool teleported = false;
if (player->GetMapId() != at->target_mapId)
{
- if (Map::EnterState denyReason = sMapMgr->PlayerCannotEnter(at->target_mapId, player, false))
+ if (Map::EnterState denyReason = Map::PlayerCannotEnter(at->target_mapId, player, false))
{
bool reviveAtTrigger = false; // should we revive the player if he is trying to enter the correct instance?
switch (denyReason)
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 7e2d1a98129..0c027ea5f33 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -25,6 +25,7 @@
#include "InstancePackets.h"
#include "InstanceSaveMgr.h"
#include "Log.h"
+#include "Map.h"
#include "MapManager.h"
#include "MiscPackets.h"
#include "MovementPackets.h"
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index 6e40a6fc026..b566b4f0cf6 100644
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -28,7 +28,6 @@
#include "InstanceScript.h"
#include "Log.h"
#include "Map.h"
-#include "MapInstanced.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "Player.h"
@@ -607,7 +606,7 @@ void InstanceSaveManager::_ResetSave(InstanceSaveHashMap::iterator &itr)
void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId)
{
TC_LOG_DEBUG("maps", "InstanceSaveMgr::_ResetInstance %u, %u", mapid, instanceId);
- Map const* map = sMapMgr->CreateBaseMap(mapid);
+ MapEntry const* map = sMapStore.LookupEntry(mapid);
if (!map->IsDungeon())
return;
@@ -617,7 +616,7 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId)
DeleteInstanceFromDB(instanceId); // even if save not loaded
- Map* iMap = ((MapInstanced*)map)->FindInstanceMap(instanceId);
+ Map* iMap = sMapMgr->FindMap(mapid, instanceId);
if (iMap)
{
((InstanceMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY);
@@ -696,28 +695,23 @@ 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;
- uint32 timeLeft;
-
- for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)
+ if (mapEntry->IsDungeon())
{
- Map* map2 = mitr->second;
- if (!map2->IsDungeon())
- continue;
-
- if (warn)
+ sMapMgr->DoForAllMapsWithMapId(mapid, [=](Map* map)
{
- if (now >= resetTime)
- timeLeft = 0;
- else
- timeLeft = uint32(resetTime - now);
+ if (warn)
+ {
+ uint32 timeLeft;
+ if (now >= resetTime)
+ timeLeft = 0;
+ else
+ timeLeft = uint32(resetTime - now);
- ((InstanceMap*)map2)->SendResetWarnings(timeLeft);
- }
- else
- ((InstanceMap*)map2)->Reset(INSTANCE_RESET_GLOBAL);
+ ((InstanceMap*)map)->SendResetWarnings(timeLeft);
+ }
+ else
+ ((InstanceMap*)map)->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.cpp b/src/server/game/Maps/Map.cpp
index 440fe34bc70..1810b63d555 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -32,10 +32,10 @@
#include "GridStates.h"
#include "Group.h"
#include "InstancePackets.h"
+#include "InstanceSaveMgr.h"
#include "InstanceScenario.h"
#include "InstanceScript.h"
#include "Log.h"
-#include "MapInstanced.h"
#include "MapManager.h"
#include "Metric.h"
#include "MiscPackets.h"
@@ -126,7 +126,7 @@ void Map::DeleteStateMachine()
delete si_GridStates[GRID_STATE_REMOVAL];
}
-Map::Map(uint32 id, time_t expiry, uint32 InstanceId, Difficulty SpawnMode, Map* /*_parent*/) :
+Map::Map(uint32 id, time_t expiry, uint32 InstanceId, Difficulty SpawnMode) :
_creatureToMoveLock(false), _gameObjectsToMoveLock(false), _dynamicObjectsToMoveLock(false), _areaTriggersToMoveLock(false),
i_mapEntry(sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId),
m_unloadTimer(0), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE),
@@ -309,15 +309,9 @@ void Map::DeleteFromWorld(Player* player)
delete player;
}
-void Map::EnsureGridCreated(GridCoord const& p)
-{
- std::lock_guard<std::mutex> lock(_gridLock);
- EnsureGridCreated_i(p);
-}
-
//Create NGrid so the object can be added to it
//But object data is not loaded here
-void Map::EnsureGridCreated_i(GridCoord const& p)
+void Map::EnsureGridCreated(GridCoord const& p)
{
if (!getNGrid(p.x_coord, p.y_coord))
{
@@ -1760,6 +1754,86 @@ bool Map::getObjectHitPos(PhaseShift const& phaseShift, float x1, float y1, floa
return result;
}
+Map::EnterState Map::PlayerCannotEnter(uint32 mapid, Player* player, bool loginCheck)
+{
+ MapEntry const* entry = sMapStore.LookupEntry(mapid);
+ if (!entry)
+ return CANNOT_ENTER_NO_ENTRY;
+
+ if (!entry->IsDungeon())
+ return CAN_ENTER;
+
+ Difficulty targetDifficulty, requestedDifficulty;
+ targetDifficulty = requestedDifficulty = player->GetDifficultyID(entry);
+ // Get the highest available difficulty if current setting is higher than the instance allows
+ MapDifficultyEntry const* mapDiff = sDB2Manager.GetDownscaledMapDifficultyData(mapid, targetDifficulty);
+ if (!mapDiff)
+ return CANNOT_ENTER_DIFFICULTY_UNAVAILABLE;
+
+ //Bypass checks for GMs
+ if (player->IsGameMaster())
+ return CAN_ENTER;
+
+ //Other requirements
+ if (!player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true))
+ return CANNOT_ENTER_UNSPECIFIED_REASON;
+
+ char const* mapName = entry->MapName[sWorld->GetDefaultDbcLocale()];
+
+ Group* group = player->GetGroup();
+ if (entry->IsRaid() && entry->Expansion() >= sWorld->getIntConfig(CONFIG_EXPANSION)) // can only enter in a raid group but raids from old expansion don't need a group
+ if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID))
+ return CANNOT_ENTER_NOT_IN_RAID;
+
+ if (!player->IsAlive())
+ {
+ if (player->HasCorpse())
+ {
+ // let enter in ghost mode in instance that connected to inner instance with corpse
+ uint32 corpseMap = player->GetCorpseLocation().GetMapId();
+ do
+ {
+ if (corpseMap == mapid)
+ break;
+
+ InstanceTemplate const* corpseInstance = sObjectMgr->GetInstanceTemplate(corpseMap);
+ corpseMap = corpseInstance ? corpseInstance->Parent : 0;
+ } while (corpseMap);
+
+ if (!corpseMap)
+ return CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE;
+
+ TC_LOG_DEBUG("maps", "MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName().c_str(), mapName);
+ }
+ else
+ TC_LOG_DEBUG("maps", "Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName().c_str());
+ }
+
+ //Get instance where player's group is bound & its map
+ if (!loginCheck && group)
+ {
+ InstanceGroupBind* boundInstance = group->GetBoundInstance(entry);
+ if (boundInstance && boundInstance->save)
+ if (Map* boundMap = sMapMgr->FindMap(mapid, boundInstance->save->GetInstanceId()))
+ if (EnterState denyReason = boundMap->CannotEnter(player))
+ return denyReason;
+ }
+
+ // players are only allowed to enter 5 instances per hour
+ if (entry->IsDungeon() && (!player->GetGroup() || (player->GetGroup() && !player->GetGroup()->isLFGGroup())))
+ {
+ uint32 instanceIdToCheck = 0;
+ if (InstanceSave* save = player->GetInstanceSave(mapid))
+ instanceIdToCheck = save->GetInstanceId();
+
+ // instanceId can never be 0 - will not be found
+ if (!player->CheckInstanceCount(instanceIdToCheck) && !player->isDead())
+ return CANNOT_ENTER_TOO_MANY_INSTANCES;
+ }
+
+ return CAN_ENTER;
+}
+
char const* Map::GetMapName() const
{
return i_mapEntry->MapName[sWorld->GetDefaultDbcLocale()];
@@ -2695,8 +2769,8 @@ template TC_GAME_API void Map::RemoveFromMap(Conversation*, bool);
/* ******* Dungeon Instance Maps ******* */
-InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, Difficulty SpawnMode, Map* _parent, TeamId InstanceTeam)
- : Map(id, expiry, InstanceId, SpawnMode, _parent),
+InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, Difficulty SpawnMode, TeamId InstanceTeam)
+ : Map(id, expiry, InstanceId, SpawnMode),
m_resetAfterUnload(false), m_unloadWhenEmpty(false),
i_data(nullptr), i_script_id(0), i_script_team(InstanceTeam), i_scenario(nullptr)
{
@@ -2763,112 +2837,97 @@ Map::EnterState InstanceMap::CannotEnter(Player* player)
*/
bool InstanceMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
{
- /// @todo Not sure about checking player level: already done in HandleAreaTriggerOpcode
- // GMs still can teleport player in instance.
- // Is it needed?
-
- {
- std::lock_guard<std::mutex> lock(_mapLock);
- // Check moved to void WorldSession::HandleMoveWorldportAckOpcode()
- //if (!CanEnter(player))
- //return false;
-
- // Dungeon only code
- if (IsDungeon())
- {
- Group* group = player->GetGroup();
+ Group* group = player->GetGroup();
- // increase current instances (hourly limit)
- if (!group || !group->isLFGGroup())
- player->AddInstanceEnterTime(GetInstanceId(), GameTime::GetGameTime());
+ // increase current instances (hourly limit)
+ if (!group || !group->isLFGGroup())
+ player->AddInstanceEnterTime(GetInstanceId(), GameTime::GetGameTime());
- // get or create an instance save for the map
- InstanceSave* mapSave = sInstanceSaveMgr->GetInstanceSave(GetInstanceId());
- if (!mapSave)
- {
- TC_LOG_DEBUG("maps", "InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetDifficultyID(), GetInstanceId());
- mapSave = sInstanceSaveMgr->AddInstanceSave(GetId(), GetInstanceId(), GetDifficultyID(), 0, 0, true);
- }
+ // get or create an instance save for the map
+ InstanceSave* mapSave = sInstanceSaveMgr->GetInstanceSave(GetInstanceId());
+ if (!mapSave)
+ {
+ TC_LOG_DEBUG("maps", "InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetDifficultyID(), GetInstanceId());
+ mapSave = sInstanceSaveMgr->AddInstanceSave(GetId(), GetInstanceId(), GetDifficultyID(), 0, 0, true);
+ }
- ASSERT(mapSave);
+ ASSERT(mapSave);
- // check for existing instance binds
- InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), GetDifficultyID());
- if (playerBind && playerBind->perm)
+ // check for existing instance binds
+ InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), GetDifficultyID());
+ if (playerBind && playerBind->perm)
+ {
+ // cannot enter other instances if bound permanently
+ if (playerBind->save != mapSave)
+ {
+ TC_LOG_ERROR("maps", "InstanceMap::Add: player %s %s is permanently bound to instance %s %d, %d, %d, %d, %d, %d but he is being put into instance %s %d, %d, %d, %d, %d, %d", player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetMapName(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), static_cast<uint32>(playerBind->save->GetDifficultyID()), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), static_cast<uint32>(mapSave->GetDifficultyID()), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset());
+ return false;
+ }
+ }
+ else
+ {
+ if (group)
+ {
+ // solo saves should have been reset when the map was loaded
+ InstanceGroupBind* groupBind = group->GetBoundInstance(this);
+ if (playerBind && playerBind->save != mapSave)
{
- // cannot enter other instances if bound permanently
- if (playerBind->save != mapSave)
- {
- TC_LOG_ERROR("maps", "InstanceMap::Add: player %s %s is permanently bound to instance %s %d, %d, %d, %d, %d, %d but he is being put into instance %s %d, %d, %d, %d, %d, %d", player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetMapName(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), static_cast<uint32>(playerBind->save->GetDifficultyID()), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), static_cast<uint32>(mapSave->GetDifficultyID()), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset());
- return false;
- }
+ TC_LOG_ERROR("maps", "InstanceMap::Add: player %s %s is being put into instance %s %d, %d, %d, %d, %d, %d but he is in group %s and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), static_cast<uint32>(mapSave->GetDifficultyID()), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), group->GetLeaderGUID().ToString().c_str(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), static_cast<uint32>(playerBind->save->GetDifficultyID()), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
+ if (groupBind)
+ TC_LOG_ERROR("maps", "InstanceMap::Add: the group is bound to the instance %s %d, %d, %d, %d, %d, %d", GetMapName(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), static_cast<uint32>(groupBind->save->GetDifficultyID()), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset());
+ //ABORT();
+ return false;
}
+ // bind to the group or keep using the group save
+ if (!groupBind)
+ group->BindToInstance(mapSave, false);
else
{
- if (group)
+ // cannot jump to a different instance without resetting it
+ if (groupBind->save != mapSave)
{
- // solo saves should have been reset when the map was loaded
- InstanceGroupBind* groupBind = group->GetBoundInstance(this);
- if (playerBind && playerBind->save != mapSave)
- {
- TC_LOG_ERROR("maps", "InstanceMap::Add: player %s %s is being put into instance %s %d, %d, %d, %d, %d, %d but he is in group %s and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), static_cast<uint32>(mapSave->GetDifficultyID()), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), group->GetLeaderGUID().ToString().c_str(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), static_cast<uint32>(playerBind->save->GetDifficultyID()), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
- if (groupBind)
- TC_LOG_ERROR("maps", "InstanceMap::Add: the group is bound to the instance %s %d, %d, %d, %d, %d, %d", GetMapName(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), static_cast<uint32>(groupBind->save->GetDifficultyID()), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset());
- //ABORT();
- return false;
- }
- // bind to the group or keep using the group save
- if (!groupBind)
- group->BindToInstance(mapSave, false);
+ TC_LOG_ERROR("maps", "InstanceMap::Add: player %s %s is being put into instance %d, %d, %d but he is in group %s which is bound to instance %d, %d, %d!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), mapSave->GetMapId(), mapSave->GetInstanceId(), static_cast<uint32>(mapSave->GetDifficultyID()), group->GetLeaderGUID().ToString().c_str(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), static_cast<uint32>(groupBind->save->GetDifficultyID()));
+ TC_LOG_ERROR("maps", "MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount());
+ if (groupBind->save)
+ TC_LOG_ERROR("maps", "GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount());
else
- {
- // cannot jump to a different instance without resetting it
- if (groupBind->save != mapSave)
- {
- TC_LOG_ERROR("maps", "InstanceMap::Add: player %s %s is being put into instance %d, %d, %d but he is in group %s which is bound to instance %d, %d, %d!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), mapSave->GetMapId(), mapSave->GetInstanceId(), static_cast<uint32>(mapSave->GetDifficultyID()), group->GetLeaderGUID().ToString().c_str(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), static_cast<uint32>(groupBind->save->GetDifficultyID()));
- TC_LOG_ERROR("maps", "MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount());
- if (groupBind->save)
- TC_LOG_ERROR("maps", "GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount());
- else
- TC_LOG_ERROR("maps", "GroupBind save NULL");
- return false;
- }
- // if the group/leader is permanently bound to the instance
- // players also become permanently bound when they enter
- if (groupBind->perm)
- {
- WorldPackets::Instance::PendingRaidLock pendingRaidLock;
- pendingRaidLock.TimeUntilLock = 60000;
- pendingRaidLock.CompletedMask = i_data ? i_data->GetCompletedEncounterMask() : 0;
- pendingRaidLock.Extending = false;
- pendingRaidLock.WarningOnly = false; // events it throws: 1 : INSTANCE_LOCK_WARNING 0 : INSTANCE_LOCK_STOP / INSTANCE_LOCK_START
- player->SendDirectMessage(pendingRaidLock.Write());
- player->SetPendingBind(mapSave->GetInstanceId(), 60000);
- }
- }
+ TC_LOG_ERROR("maps", "GroupBind save NULL");
+ return false;
}
- else
+ // if the group/leader is permanently bound to the instance
+ // players also become permanently bound when they enter
+ if (groupBind->perm)
{
- // set up a solo bind or continue using it
- if (!playerBind)
- player->BindToInstance(mapSave, false);
- else
- // cannot jump to a different instance without resetting it
- ASSERT(playerBind->save == mapSave);
+ WorldPackets::Instance::PendingRaidLock pendingRaidLock;
+ pendingRaidLock.TimeUntilLock = 60000;
+ pendingRaidLock.CompletedMask = i_data ? i_data->GetCompletedEncounterMask() : 0;
+ pendingRaidLock.Extending = false;
+ pendingRaidLock.WarningOnly = false; // events it throws: 1 : INSTANCE_LOCK_WARNING 0 : INSTANCE_LOCK_STOP / INSTANCE_LOCK_START
+ player->SendDirectMessage(pendingRaidLock.Write());
+ player->SetPendingBind(mapSave->GetInstanceId(), 60000);
}
}
}
+ else
+ {
+ // set up a solo bind or continue using it
+ if (!playerBind)
+ player->BindToInstance(mapSave, false);
+ else
+ // cannot jump to a different instance without resetting it
+ ASSERT(playerBind->save == mapSave);
+ }
+ }
- // for normal instances cancel the reset schedule when the
- // first player enters (no players yet)
- SetResetSchedule(false);
+ // for normal instances cancel the reset schedule when the
+ // first player enters (no players yet)
+ SetResetSchedule(false);
- TC_LOG_DEBUG("maps", "MAP: Player '%s' entered instance '%u' of map '%s'", player->GetName().c_str(), GetInstanceId(), GetMapName());
- // initialize unload state
- m_unloadTimer = 0;
- m_resetAfterUnload = false;
- m_unloadWhenEmpty = false;
- }
+ TC_LOG_DEBUG("maps", "MAP: Player '%s' entered instance '%u' of map '%s'", player->GetName().c_str(), GetInstanceId(), GetMapName());
+ // initialize unload state
+ m_unloadTimer = 0;
+ m_resetAfterUnload = false;
+ m_unloadWhenEmpty = false;
// this will acquire the same mutex so it cannot be in the previous block
Map::AddPlayerToMap(player, initPlayer);
@@ -3213,8 +3272,8 @@ uint32 InstanceMap::GetMaxResetDelay() const
/* ******* Battleground Instance Maps ******* */
-BattlegroundMap::BattlegroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent, Difficulty spawnMode)
- : Map(id, expiry, InstanceId, spawnMode, _parent), m_bg(nullptr)
+BattlegroundMap::BattlegroundMap(uint32 id, time_t expiry, uint32 InstanceId, Difficulty spawnMode)
+ : Map(id, expiry, InstanceId, spawnMode), m_bg(nullptr)
{
//lets initialize visibility distance for BG/Arenas
BattlegroundMap::InitVisibilityDistance();
@@ -3256,14 +3315,7 @@ Map::EnterState BattlegroundMap::CannotEnter(Player* player)
bool BattlegroundMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
{
- {
- std::lock_guard<std::mutex> lock(_mapLock);
- //Check moved to void WorldSession::HandleMoveWorldportAckOpcode()
- //if (!CanEnter(player))
- //return false;
- // reset instance validity, battleground maps do not homebind
- player->m_InstanceValid = true;
- }
+ player->m_InstanceValid = true;
return Map::AddPlayerToMap(player, initPlayer);
}
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 471d1b64d5a..ae34acdd23b 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -53,7 +53,6 @@ class InstanceMap;
class InstanceSave;
class InstanceScript;
class InstanceScenario;
-class MapInstanced;
class Object;
class PhaseShift;
class Player;
@@ -145,7 +144,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
{
friend class MapReference;
public:
- Map(uint32 id, time_t, uint32 InstanceId, Difficulty SpawnMode, Map* _parent = nullptr);
+ Map(uint32 id, time_t, uint32 InstanceId, Difficulty SpawnMode);
virtual ~Map();
MapEntry const* GetEntry() const { return i_mapEntry; }
@@ -274,6 +273,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
CANNOT_ENTER_ZONE_IN_COMBAT, // A boss encounter is currently in progress on the target map
CANNOT_ENTER_UNSPECIFIED_REASON
};
+ static EnterState PlayerCannotEnter(uint32 mapid, Player* player, bool loginCheck = false);
virtual EnterState CannotEnter(Player* /*player*/) { return CAN_ENTER; }
char const* GetMapName() const;
@@ -402,9 +402,6 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
return nullptr;
}
- MapInstanced* ToMapInstanced() { if (Instanceable()) return reinterpret_cast<MapInstanced*>(this); return nullptr; }
- MapInstanced const* ToMapInstanced() const { if (Instanceable()) return reinterpret_cast<MapInstanced const*>(this); return nullptr; }
-
InstanceMap* ToInstanceMap() { if (IsDungeon()) return reinterpret_cast<InstanceMap*>(this); else return nullptr; }
InstanceMap const* ToInstanceMap() const { if (IsDungeon()) return reinterpret_cast<InstanceMap const*>(this); return nullptr; }
@@ -538,7 +535,6 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
bool IsGridLoaded(GridCoord const&) const;
void EnsureGridCreated(GridCoord const&);
- void EnsureGridCreated_i(GridCoord const&);
bool EnsureGridLoaded(Cell const&);
void EnsureGridLoadedForActiveObject(Cell const&, WorldObject const* object);
@@ -561,9 +557,6 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
protected:
virtual void LoadGridObjects(NGridType* grid, Cell const& cell);
- std::mutex _mapLock;
- std::mutex _gridLock;
-
MapEntry const* i_mapEntry;
Difficulty i_spawnMode;
uint32 i_InstanceId;
@@ -803,7 +796,7 @@ enum InstanceResetMethod
class TC_GAME_API InstanceMap : public Map
{
public:
- InstanceMap(uint32 id, time_t, uint32 InstanceId, Difficulty SpawnMode, Map* _parent, TeamId InstanceTeam);
+ InstanceMap(uint32 id, time_t, uint32 InstanceId, Difficulty SpawnMode, TeamId InstanceTeam);
~InstanceMap();
bool AddPlayerToMap(Player* player, bool initPlayer = true) override;
void RemovePlayerFromMap(Player*, bool) override;
@@ -846,7 +839,7 @@ class TC_GAME_API InstanceMap : public Map
class TC_GAME_API BattlegroundMap : public Map
{
public:
- BattlegroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent, Difficulty spawnMode);
+ BattlegroundMap(uint32 id, time_t, uint32 InstanceId, Difficulty spawnMode);
~BattlegroundMap();
bool AddPlayerToMap(Player* player, bool initPlayer = true) override;
diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp
deleted file mode 100644
index 7bb6c9a8460..00000000000
--- a/src/server/game/Maps/MapInstanced.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * 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 "MapInstanced.h"
-#include "Battleground.h"
-#include "DB2Stores.h"
-#include "GarrisonMap.h"
-#include "Group.h"
-#include "InstanceSaveMgr.h"
-#include "Log.h"
-#include "MapManager.h"
-#include "MMapFactory.h"
-#include "Player.h"
-#include "ScenarioMgr.h"
-#include "VMapFactory.h"
-#include "VMapManager2.h"
-#include "World.h"
-
-MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DIFFICULTY_NORMAL)
-{
-}
-
-MapInstanced::~MapInstanced() = default;
-
-void MapInstanced::InitVisibilityDistance()
-{
- if (m_InstancedMaps.empty())
- return;
- //initialize visibility distances for all instance copies
- for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
- {
- (*i).second->InitVisibilityDistance();
- }
-}
-
-void MapInstanced::Update(uint32 t)
-{
- // take care of loaded GridMaps (when unused, unload it!)
- Map::Update(t);
-
- // update the instanced maps
- InstancedMaps::iterator i = m_InstancedMaps.begin();
-
- while (i != m_InstancedMaps.end())
- {
- if (i->second->CanUnload(t))
- {
- if (!DestroyInstance(i)) // iterator incremented
- {
- //m_unloadTimer
- }
- }
- else
- {
- // update only here, because it may schedule some bad things before delete
- if (sMapMgr->GetMapUpdater()->activated())
- sMapMgr->GetMapUpdater()->schedule_update(*i->second, t);
- else
- i->second->Update(t);
- ++i;
- }
- }
-}
-
-void MapInstanced::DelayedUpdate(uint32 diff)
-{
- for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
- i->second->DelayedUpdate(diff);
-
- Map::DelayedUpdate(diff); // this may be removed
-}
-
-/*
-void MapInstanced::RelocationNotify()
-{
- for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
- i->second->RelocationNotify();
-}
-*/
-
-void MapInstanced::UnloadAll()
-{
- // Unload instanced maps
- 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!)
- Map::UnloadAll();
-}
-
-/*
-- return the right instance for the object, based on its InstanceId
-- create the instance if it's not created already
-- the player is not actually added to the instance (only in InstanceMap::Add)
-*/
-Map* MapInstanced::CreateInstanceForPlayer(uint32 mapId, Player* player, uint32 loginInstanceId /*= 0*/)
-{
- if (GetId() != mapId || !player)
- return nullptr;
-
- Map* map = nullptr;
- uint32 newInstanceId = 0; // instanceId of the resulting map
-
- if (IsBattlegroundOrArena())
- {
- // instantiate or find existing bg map for player
- // the instance id is set in battlegroundid
- newInstanceId = player->GetBattlegroundId();
- if (!newInstanceId)
- return nullptr;
-
- map = sMapMgr->FindMap(mapId, newInstanceId);
- if (!map)
- {
- if (Battleground* bg = player->GetBattleground())
- map = CreateBattleground(newInstanceId, bg);
- else
- {
- player->TeleportToBGEntryPoint();
- return nullptr;
- }
- }
- }
- else if (IsDungeon())
- {
- InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficultyID(GetEntry()));
- InstanceSave* pSave = pBind ? pBind->save : nullptr;
-
- // priority:
- // 1. player's permanent bind
- // 2. player's current instance id if this is at login
- // 3. group's current bind
- // 4. player's current bind
- if (!pBind || !pBind->perm)
- {
- if (loginInstanceId) // if the player has a saved instance id on login, we either use this instance or relocate him out (return null)
- {
- map = FindInstanceMap(loginInstanceId);
- if (!map && pSave && pSave->GetInstanceId() == loginInstanceId)
- map = CreateInstance(loginInstanceId, pSave, pSave->GetDifficultyID(), player->GetTeamId());
- return map;
- }
-
- InstanceGroupBind* groupBind = nullptr;
- Group* group = player->GetGroup();
- // use the player's difficulty setting (it may not be the same as the group's)
- if (group)
- {
- groupBind = group->GetBoundInstance(this);
- if (groupBind)
- {
- // solo saves should be reset when entering a group's instance
- player->UnbindInstance(GetId(), player->GetDifficultyID(GetEntry()));
- pSave = groupBind->save;
- }
- }
- }
- if (pSave)
- {
- // solo/perm/group
- newInstanceId = pSave->GetInstanceId();
- map = FindInstanceMap(newInstanceId);
- // it is possible that the save exists but the map doesn't
- if (!map)
- map = CreateInstance(newInstanceId, pSave, pSave->GetDifficultyID(), player->GetTeamId());
- }
- else
- {
- // if no instanceId via group members or instance saves is found
- // the instance will be created for the first time
- newInstanceId = sMapMgr->GenerateInstanceId();
-
- Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficultyID(GetEntry()) : player->GetDifficultyID(GetEntry());
- //Seems it is now possible, but I do not know if it should be allowed
- //ASSERT(!FindInstanceMap(NewInstanceId));
- map = FindInstanceMap(newInstanceId);
- if (!map)
- map = CreateInstance(newInstanceId, nullptr, diff, player->GetTeamId());
- }
- }
- else if (IsGarrison())
- {
- newInstanceId = player->GetGUID().GetCounter();
- map = FindInstanceMap(newInstanceId);
- if (!map)
- map = CreateGarrison(newInstanceId, player);
- }
-
- return map;
-}
-
-InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty, TeamId team)
-{
- // load/create a map
- std::lock_guard<std::mutex> lock(_mapLock);
-
- // make sure we have a valid map id
- MapEntry const* entry = sMapStore.LookupEntry(GetId());
- if (!entry)
- {
- TC_LOG_ERROR("maps", "CreateInstance: no entry for map %d", GetId());
- ABORT();
- }
-
- // some instances only have one difficulty
- sDB2Manager.GetDownscaledMapDifficultyData(GetId(), difficulty);
-
- TC_LOG_DEBUG("maps", "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %u", save ? "" : "new ", InstanceId, GetId(), static_cast<uint32>(difficulty));
-
- InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this, team);
- ASSERT(map->IsDungeon());
-
- map->LoadRespawnTimes();
- map->LoadCorpseData();
-
- bool load_data = save != nullptr;
- map->CreateInstanceData(load_data);
- if (InstanceScenario* instanceScenario = sScenarioMgr->CreateInstanceScenario(map, team))
- map->SetInstanceScenario(instanceScenario);
-
- if (sWorld->getBoolConfig(CONFIG_INSTANCEMAP_LOAD_GRIDS))
- map->LoadAllCells();
-
- m_InstancedMaps[InstanceId] = map;
- return map;
-}
-
-BattlegroundMap* MapInstanced::CreateBattleground(uint32 InstanceId, Battleground* bg)
-{
- // load/create a map
- std::lock_guard<std::mutex> lock(_mapLock);
-
- TC_LOG_DEBUG("maps", "MapInstanced::CreateBattleground: map bg %d for %d created.", InstanceId, GetId());
-
- BattlegroundMap* map = new BattlegroundMap(GetId(), GetGridExpiry(), InstanceId, this, DIFFICULTY_NONE);
- ASSERT(map->IsBattlegroundOrArena());
- map->SetBG(bg);
- bg->SetBgMap(map);
-
- m_InstancedMaps[InstanceId] = map;
- return map;
-}
-
-GarrisonMap* MapInstanced::CreateGarrison(uint32 instanceId, Player* owner)
-{
- std::lock_guard<std::mutex> lock(_mapLock);
-
- GarrisonMap* map = new GarrisonMap(GetId(), GetGridExpiry(), instanceId, this, owner->GetGUID());
- ASSERT(map->IsGarrison());
-
- m_InstancedMaps[instanceId] = map;
- return map;
-}
-
-// increments the iterator after erase
-bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr)
-{
- itr->second->RemoveAllPlayers();
- if (itr->second->HavePlayers())
- {
- ++itr;
- return false;
- }
-
- itr->second->UnloadAll();
- // should only unload VMaps if this is the last instance and grid unloading is enabled
- if (m_InstancedMaps.size() <= 1 && sWorld->getBoolConfig(CONFIG_GRID_UNLOAD))
- {
- VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(itr->second->GetId());
- MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(itr->second->GetId());
- // in that case, unload grids of the base map, too
- // so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded
- Map::UnloadAll();
- }
-
- // Free up the instance id and allow it to be reused for bgs and arenas (other instances are handled in the InstanceSaveMgr)
- if (itr->second->IsBattlegroundOrArena())
- sMapMgr->FreeInstanceId(itr->second->GetInstanceId());
-
- // erase map
- delete itr->second;
- m_InstancedMaps.erase(itr++);
-
- return true;
-}
-
-Map::EnterState MapInstanced::CannotEnter(Player* /*player*/)
-{
- //ABORT();
- return CAN_ENTER;
-}
diff --git a/src/server/game/Maps/MapInstanced.h b/src/server/game/Maps/MapInstanced.h
deleted file mode 100644
index 6b2b71ed37e..00000000000
--- a/src/server/game/Maps/MapInstanced.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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/>.
- */
-
-#ifndef TRINITY_MAP_INSTANCED_H
-#define TRINITY_MAP_INSTANCED_H
-
-#include "Map.h"
-#include "InstanceSaveMgr.h"
-
-class GarrisonMap;
-
-class TC_GAME_API MapInstanced : public Map
-{
- friend class MapManager;
- public:
- typedef std::unordered_map< uint32, Map*> InstancedMaps;
-
- MapInstanced(uint32 id, time_t expiry);
- MapInstanced(MapInstanced const& right) = delete;
- MapInstanced(MapInstanced&& right) = delete;
- MapInstanced& operator=(MapInstanced const& right) = delete;
- MapInstanced& operator=(MapInstanced&& right) = delete;
- ~MapInstanced();
-
- // functions overwrite Map versions
- void Update(uint32 diff) override;
- void DelayedUpdate(uint32 diff) override;
- //void RelocationNotify();
- void UnloadAll() override;
- EnterState CannotEnter(Player* /*player*/) override;
-
- Map* CreateInstanceForPlayer(uint32 mapId, Player* player, uint32 loginInstanceId = 0);
- Map* FindInstanceMap(uint32 instanceId) const
- {
- InstancedMaps::const_iterator i = m_InstancedMaps.find(instanceId);
- return(i == m_InstancedMaps.end() ? nullptr : i->second);
- }
- bool DestroyInstance(InstancedMaps::iterator &itr);
-
- InstancedMaps &GetInstancedMaps() { return m_InstancedMaps; }
- virtual void InitVisibilityDistance() override;
-
- private:
- InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty, TeamId team);
- BattlegroundMap* CreateBattleground(uint32 InstanceId, Battleground* bg);
- GarrisonMap* CreateGarrison(uint32 instanceId, Player* owner);
-
- InstancedMaps m_InstancedMaps;
-};
-#endif
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index 6d8f5bacdb7..108aad5b3ad 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -16,22 +16,20 @@
*/
#include "MapManager.h"
-#include "Config.h"
-#include "Corpse.h"
+#include "Battleground.h"
+#include "Containers.h"
#include "DatabaseEnv.h"
#include "DB2Stores.h"
-#include "GridDefines.h"
+#include "GarrisonMap.h"
#include "Group.h"
#include "InstanceSaveMgr.h"
-#include "InstanceScript.h"
#include "Log.h"
-#include "MapInstanced.h"
-#include "MiscPackets.h"
-#include "ObjectMgr.h"
+#include "Map.h"
#include "Player.h"
-#include "Transport.h"
+#include "ScenarioMgr.h"
#include "World.h"
#include <boost/dynamic_bitset.hpp>
+#include <numeric>
MapManager::MapManager()
: _freeInstanceIds(std::make_unique<InstanceIds>()), _nextInstanceId(0), _scheduledScripts(0)
@@ -40,7 +38,7 @@ MapManager::MapManager()
i_timer.SetInterval(sWorld->getIntConfig(CONFIG_INTERVAL_MAPUPDATE));
}
-MapManager::~MapManager() { }
+MapManager::~MapManager() = default;
void MapManager::Initialize()
{
@@ -64,157 +62,195 @@ MapManager* MapManager::instance()
return &instance;
}
-Map* MapManager::CreateBaseMap(uint32 id)
+Map* MapManager::FindMap_i(uint32 mapId, uint32 instanceId) const
{
- Map* map = FindBaseMap(id);
-
- if (!map)
- {
- MapEntry const* entry = sMapStore.AssertEntry(id);
- if (entry->ParentMapID != -1 || entry->CosmeticParentMapID != -1)
- {
- CreateBaseMap(entry->ParentMapID != -1 ? entry->ParentMapID : entry->CosmeticParentMapID);
+ return Trinity::Containers::MapGetValuePtr(i_maps, { mapId, instanceId });
+}
- // must have been created by parent map
- map = FindBaseMap(id);
- return ASSERT_NOTNULL(map);
- }
+Map* MapManager::CreateWorldMap(uint32 mapId, uint32 instanceId)
+{
+ Map* map = new Map(mapId, i_gridCleanUpDelay, instanceId, DIFFICULTY_NONE);
+ map->LoadRespawnTimes();
+ map->LoadCorpseData();
- std::lock_guard<std::mutex> lock(_mapsLock);
- map = CreateBaseMap_i(entry);
- }
+ if (sWorld->getBoolConfig(CONFIG_BASEMAP_LOAD_GRIDS))
+ map->LoadAllCells();
- ASSERT(map);
return map;
}
-Map* MapManager::CreateBaseMap_i(MapEntry const* mapEntry)
+InstanceMap* MapManager::CreateInstance(uint32 mapId, uint32 instanceId, InstanceSave* save, Difficulty difficulty, TeamId team)
{
- Map* map;
- if (mapEntry->Instanceable())
- map = new MapInstanced(mapEntry->ID, i_gridCleanUpDelay);
- else
- map = new Map(mapEntry->ID, i_gridCleanUpDelay, 0, DIFFICULTY_NONE);
-
- i_maps[mapEntry->ID] = map;
-
- if (!mapEntry->Instanceable())
+ // make sure we have a valid map id
+ MapEntry const* entry = sMapStore.LookupEntry(mapId);
+ if (!entry)
{
- map->LoadRespawnTimes();
- map->LoadCorpseData();
+ TC_LOG_ERROR("maps", "CreateInstance: no entry for map %d", mapId);
+ ABORT();
}
+ // some instances only have one difficulty
+ sDB2Manager.GetDownscaledMapDifficultyData(mapId, difficulty);
+
+ TC_LOG_DEBUG("maps", "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %u", save ? "" : "new ", instanceId, mapId, static_cast<uint32>(difficulty));
+
+ InstanceMap* map = new InstanceMap(mapId, i_gridCleanUpDelay, instanceId, difficulty, team);
+ ASSERT(map->IsDungeon());
+
+ map->LoadRespawnTimes();
+ map->LoadCorpseData();
+
+ bool load_data = save != nullptr;
+ map->CreateInstanceData(load_data);
+ if (InstanceScenario* instanceScenario = sScenarioMgr->CreateInstanceScenario(map, team))
+ map->SetInstanceScenario(instanceScenario);
+
+ if (sWorld->getBoolConfig(CONFIG_INSTANCEMAP_LOAD_GRIDS))
+ map->LoadAllCells();
+
return map;
}
-Map* MapManager::FindBaseNonInstanceMap(uint32 mapId) const
+BattlegroundMap* MapManager::CreateBattleground(uint32 mapId, uint32 instanceId, Battleground* bg)
{
- Map* map = FindBaseMap(mapId);
- if (map && map->Instanceable())
- return nullptr;
+ TC_LOG_DEBUG("maps", "MapInstanced::CreateBattleground: map bg %d for %d created.", instanceId, mapId);
+
+ BattlegroundMap* map = new BattlegroundMap(mapId, i_gridCleanUpDelay, instanceId, DIFFICULTY_NONE);
+ ASSERT(map->IsBattlegroundOrArena());
+ map->SetBG(bg);
+ bg->SetBgMap(map);
return map;
}
-Map* MapManager::CreateMap(uint32 id, Player* player, uint32 loginInstanceId)
+GarrisonMap* MapManager::CreateGarrison(uint32 mapId, uint32 instanceId, Player* owner)
{
- Map* m = CreateBaseMap(id);
-
- if (m && m->Instanceable())
- m = ((MapInstanced*)m)->CreateInstanceForPlayer(id, player, loginInstanceId);
-
- return m;
+ GarrisonMap* map = new GarrisonMap(mapId, i_gridCleanUpDelay, instanceId, owner->GetGUID());
+ ASSERT(map->IsGarrison());
+ return map;
}
-Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) const
+/*
+- return the right instance for the object, based on its InstanceId
+- create the instance if it's not created already
+- the player is not actually added to the instance (only in InstanceMap::Add)
+*/
+Map* MapManager::CreateMap(uint32 mapId, Player* player, uint32 loginInstanceId /*= 0*/)
{
- Map* map = FindBaseMap(mapid);
- if (!map)
+ if (!player)
return nullptr;
- if (!map->Instanceable())
- return instanceId == 0 ? map : nullptr;
-
- return ((MapInstanced*)map)->FindInstanceMap(instanceId);
-}
-
-Map::EnterState MapManager::PlayerCannotEnter(uint32 mapid, Player* player, bool loginCheck)
-{
- MapEntry const* entry = sMapStore.LookupEntry(mapid);
+ MapEntry const* entry = sMapStore.LookupEntry(mapId);
if (!entry)
- return Map::CANNOT_ENTER_NO_ENTRY;
-
- if (!entry->IsDungeon())
- return Map::CAN_ENTER;
-
- Difficulty targetDifficulty, requestedDifficulty;
- targetDifficulty = requestedDifficulty = player->GetDifficultyID(entry);
- // Get the highest available difficulty if current setting is higher than the instance allows
- MapDifficultyEntry const* mapDiff = sDB2Manager.GetDownscaledMapDifficultyData(mapid, targetDifficulty);
- if (!mapDiff)
- return Map::CANNOT_ENTER_DIFFICULTY_UNAVAILABLE;
-
- //Bypass checks for GMs
- if (player->IsGameMaster())
- return Map::CAN_ENTER;
-
- //Other requirements
- if (!player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, targetDifficulty), mapid, true))
- return Map::CANNOT_ENTER_UNSPECIFIED_REASON;
+ return nullptr;
- char const* mapName = entry->MapName[sWorld->GetDefaultDbcLocale()];
+ std::unique_lock<std::shared_mutex> lock(_mapsLock);
- Group* group = player->GetGroup();
- if (entry->IsRaid() && entry->Expansion() >= sWorld->getIntConfig(CONFIG_EXPANSION)) // can only enter in a raid group but raids from old expansion don't need a group
- if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID))
- return Map::CANNOT_ENTER_NOT_IN_RAID;
+ Map* map = nullptr;
+ uint32 newInstanceId = 0; // instanceId of the resulting map
- if (!player->IsAlive())
+ if (entry->IsBattlegroundOrArena())
{
- if (player->HasCorpse())
+ // instantiate or find existing bg map for player
+ // the instance id is set in battlegroundid
+ newInstanceId = player->GetBattlegroundId();
+ if (!newInstanceId)
+ return nullptr;
+
+ map = FindMap(mapId, newInstanceId);
+ if (!map)
{
- // let enter in ghost mode in instance that connected to inner instance with corpse
- uint32 corpseMap = player->GetCorpseLocation().GetMapId();
- do
+ if (Battleground* bg = player->GetBattleground())
+ map = CreateBattleground(mapId, newInstanceId, bg);
+ else
{
- if (corpseMap == mapid)
- break;
-
- InstanceTemplate const* corpseInstance = sObjectMgr->GetInstanceTemplate(corpseMap);
- corpseMap = corpseInstance ? corpseInstance->Parent : 0;
- } while (corpseMap);
+ player->TeleportToBGEntryPoint();
+ return nullptr;
+ }
+ }
+ }
+ else if (entry->IsDungeon())
+ {
+ InstancePlayerBind* pBind = player->GetBoundInstance(mapId, player->GetDifficultyID(entry));
+ InstanceSave* pSave = pBind ? pBind->save : nullptr;
+
+ // priority:
+ // 1. player's permanent bind
+ // 2. player's current instance id if this is at login
+ // 3. group's current bind
+ // 4. player's current bind
+ if (!pBind || !pBind->perm)
+ {
+ if (loginInstanceId) // if the player has a saved instance id on login, we either use this instance or relocate him out (return null)
+ {
+ map = FindMap_i(mapId, loginInstanceId);
+ if (!map && pSave && pSave->GetInstanceId() == loginInstanceId)
+ map = CreateInstance(mapId, loginInstanceId, pSave, pSave->GetDifficultyID(), player->GetTeamId());
+ return map;
+ }
+
+ InstanceGroupBind* groupBind = nullptr;
+ Group* group = player->GetGroup();
+ // use the player's difficulty setting (it may not be the same as the group's)
+ if (group)
+ {
+ groupBind = group->GetBoundInstance(entry);
+ if (groupBind)
+ {
+ // solo saves should be reset when entering a group's instance
+ player->UnbindInstance(mapId, player->GetDifficultyID(entry));
+ pSave = groupBind->save;
+ }
+ }
+ }
+ if (pSave)
+ {
+ // solo/perm/group
+ newInstanceId = pSave->GetInstanceId();
+ map = FindMap_i(mapId, newInstanceId);
+ // it is possible that the save exists but the map doesn't
+ if (!map)
+ map = CreateInstance(mapId, newInstanceId, pSave, pSave->GetDifficultyID(), player->GetTeamId());
+ }
+ else
+ {
+ Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficultyID(entry) : player->GetDifficultyID(entry);
- if (!corpseMap)
- return Map::CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE;
+ // if no instanceId via group members or instance saves is found
+ // the instance will be created for the first time
+ newInstanceId = GenerateInstanceId();
- TC_LOG_DEBUG("maps", "MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName().c_str(), mapName);
+ //Seems it is now possible, but I do not know if it should be allowed
+ //ASSERT(!FindInstanceMap(NewInstanceId));
+ map = FindMap_i(mapId, newInstanceId);
+ if (!map)
+ map = CreateInstance(mapId, newInstanceId, nullptr, diff, player->GetTeamId());
}
- else
- TC_LOG_DEBUG("maps", "Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName().c_str());
}
-
- //Get instance where player's group is bound & its map
- if (!loginCheck && group)
+ else if (entry->IsGarrison())
{
- InstanceGroupBind* boundInstance = group->GetBoundInstance(entry);
- if (boundInstance && boundInstance->save)
- if (Map* boundMap = sMapMgr->FindMap(mapid, boundInstance->save->GetInstanceId()))
- if (Map::EnterState denyReason = boundMap->CannotEnter(player))
- return denyReason;
+ newInstanceId = player->GetGUID().GetCounter();
+ map = FindMap_i(mapId, newInstanceId);
+ if (!map)
+ map = CreateGarrison(mapId, newInstanceId, player);
}
-
- // players are only allowed to enter 5 instances per hour
- if (entry->IsDungeon() && (!player->GetGroup() || (player->GetGroup() && !player->GetGroup()->isLFGGroup())))
+ else
{
- uint32 instanceIdToCheck = 0;
- if (InstanceSave* save = player->GetInstanceSave(mapid))
- instanceIdToCheck = save->GetInstanceId();
-
- // instanceId can never be 0 - will not be found
- if (!player->CheckInstanceCount(instanceIdToCheck) && !player->isDead())
- return Map::CANNOT_ENTER_TOO_MANY_INSTANCES;
+ newInstanceId = 0;
+ map = FindMap_i(mapId, newInstanceId);
+ if (!map)
+ map = CreateWorldMap(mapId, newInstanceId);
}
- return Map::CAN_ENTER;
+ if (map)
+ i_maps[{ map->GetId(), map->GetInstanceId() }] = map;
+
+ return map;
+}
+
+Map* MapManager::FindMap(uint32 mapId, uint32 instanceId) const
+{
+ std::shared_lock<std::shared_mutex> lock(_mapsLock);
+ return FindMap_i(mapId, instanceId);
}
void MapManager::Update(uint32 diff)
@@ -224,12 +260,24 @@ void MapManager::Update(uint32 diff)
return;
MapMapType::iterator iter = i_maps.begin();
- for (; iter != i_maps.end(); ++iter)
+ while (iter != i_maps.end())
{
+ if (iter->second->CanUnload(diff))
+ {
+ if (DestroyMap(iter->second))
+ iter = i_maps.erase(iter);
+ else
+ ++iter;
+
+ continue;
+ }
+
if (m_updater.activated())
m_updater.schedule_update(*iter->second, uint32(i_timer.GetCurrent()));
else
iter->second->Update(uint32(i_timer.GetCurrent()));
+
+ ++iter;
}
if (m_updater.activated())
m_updater.wait();
@@ -240,7 +288,22 @@ void MapManager::Update(uint32 diff)
i_timer.SetCurrent(0);
}
-void MapManager::DoDelayedMovesAndRemoves() { }
+bool MapManager::DestroyMap(Map* map)
+{
+ map->RemoveAllPlayers();
+ if (map->HavePlayers())
+ return false;
+
+ map->UnloadAll();
+
+ // Free up the instance id and allow it to be reused for bgs and arenas (other instances are handled in the InstanceSaveMgr)
+ if (map->IsBattlegroundOrArena())
+ sMapMgr->FreeInstanceId(map->GetInstanceId());
+
+ // erase map
+ delete map;
+ return true;
+}
bool MapManager::IsValidMAP(uint32 mapId)
{
@@ -265,37 +328,16 @@ void MapManager::UnloadAll()
Map::DeleteStateMachine();
}
-uint32 MapManager::GetNumInstances()
+uint32 MapManager::GetNumInstances() const
{
- std::lock_guard<std::mutex> lock(_mapsLock);
-
- uint32 ret = 0;
- for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr)
- {
- Map* map = itr->second;
- if (!map->IsDungeon())
- continue;
- MapInstanced::InstancedMaps &maps = ((MapInstanced*)map)->GetInstancedMaps();
- ret += maps.size();
- }
- return ret;
+ std::shared_lock<std::shared_mutex> lock(_mapsLock);
+ return std::count_if(i_maps.begin(), i_maps.end(), [](MapMapType::value_type const& value) { return value.second->IsDungeon(); });
}
-uint32 MapManager::GetNumPlayersInInstances()
+uint32 MapManager::GetNumPlayersInInstances() const
{
- std::lock_guard<std::mutex> lock(_mapsLock);
-
- uint32 ret = 0;
- for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr)
- {
- Map* map = itr->second;
- if (!map->IsDungeon())
- continue;
- MapInstanced::InstancedMaps &maps = ((MapInstanced*)map)->GetInstancedMaps();
- for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr)
- ret += mitr->second->GetPlayers().getSize();
- }
- return ret;
+ std::shared_lock<std::shared_mutex> lock(_mapsLock);
+ return std::accumulate(i_maps.begin(), i_maps.end(), 0u, [](uint32 total, MapMapType::value_type const& value) { return total + (value.second->IsDungeon() ? value.second->GetPlayers().getSize() : 0); });
}
void MapManager::InitInstanceIds()
diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h
index f2c3bbb1e86..8fb598dd8c2 100644
--- a/src/server/game/Maps/MapManager.h
+++ b/src/server/game/Maps/MapManager.h
@@ -18,27 +18,42 @@
#ifndef TRINITY_MAPMANAGER_H
#define TRINITY_MAPMANAGER_H
-#include "Map.h"
-#include "MapInstanced.h"
-#include "GridStates.h"
+#include "GridDefines.h"
+#include "IteratorPair.h"
#include "MapUpdater.h"
+#include "Position.h"
+#include "SharedDefines.h"
#include <boost/dynamic_bitset_fwd.hpp>
-
-class PhaseShift;
-class Transport;
+#include <map>
+#include <shared_mutex>
+
+class Battleground;
+class BattlegroundMap;
+class GarrisonMap;
+class InstanceMap;
+class InstanceSave;
+class Map;
+class Player;
+enum Difficulty : uint8;
class TC_GAME_API MapManager
{
+ MapManager();
+ ~MapManager();
+
public:
+ MapManager(MapManager const&) = delete;
+ MapManager(MapManager&&) = delete;
+ MapManager& operator=(MapManager const&) = delete;
+ MapManager& operator=(MapManager&&) = delete;
+
static MapManager* instance();
- Map* CreateBaseMap(uint32 mapId);
- Map* FindBaseNonInstanceMap(uint32 mapId) const;
- Map* CreateMap(uint32 mapId, Player* player, uint32 loginInstanceId=0);
+ Map* CreateMap(uint32 mapId, Player* player, uint32 loginInstanceId = 0);
Map* FindMap(uint32 mapId, uint32 instanceId) const;
void Initialize();
- void Update(uint32);
+ void Update(uint32 diff);
void SetGridCleanUpDelay(uint32 t)
{
@@ -57,7 +72,6 @@ class TC_GAME_API MapManager
i_timer.Reset();
}
- //void LoadGrid(int mapid, int instId, float x, float y, WorldObject const* obj, bool no_unload = false);
void UnloadAll();
static bool IsValidMAP(uint32 mapId);
@@ -87,14 +101,11 @@ class TC_GAME_API MapManager
return IsValidMapCoord(loc.GetMapId(), loc);
}
- void DoDelayedMovesAndRemoves();
-
- Map::EnterState PlayerCannotEnter(uint32 mapid, Player* player, bool loginCheck = false);
void InitializeVisibilityDistanceInfo();
/* statistics */
- uint32 GetNumInstances();
- uint32 GetNumPlayersInInstances();
+ uint32 GetNumInstances() const;
+ uint32 GetNumPlayersInInstances() const;
// Instance ID management
void InitInstanceIds();
@@ -116,24 +127,20 @@ class TC_GAME_API MapManager
bool IsScriptScheduled() const { return _scheduledScripts > 0; }
private:
- typedef std::unordered_map<uint32, Map*> MapMapType;
+ using MapKey = std::pair<uint32, uint32>;
+ typedef std::map<MapKey, Map*> MapMapType;
typedef boost::dynamic_bitset<size_t> InstanceIds;
- MapManager();
- ~MapManager();
+ Map* FindMap_i(uint32 mapId, uint32 instanceId) const;
- Map* FindBaseMap(uint32 mapId) const
- {
- MapMapType::const_iterator iter = i_maps.find(mapId);
- return (iter == i_maps.end() ? nullptr : iter->second);
- }
+ Map* CreateWorldMap(uint32 mapId, uint32 instanceId);
+ InstanceMap* CreateInstance(uint32 mapId, uint32 instanceId, InstanceSave* save, Difficulty difficulty, TeamId team);
+ BattlegroundMap* CreateBattleground(uint32 mapId, uint32 instanceId, Battleground* bg);
+ GarrisonMap* CreateGarrison(uint32 mapId, uint32 instanceId, Player* owner);
- Map* CreateBaseMap_i(MapEntry const* mapEntry);
+ bool DestroyMap(Map* map);
- MapManager(MapManager const&) = delete;
- MapManager& operator=(MapManager const&) = delete;
-
- std::mutex _mapsLock;
+ mutable std::shared_mutex _mapsLock;
uint32 i_gridCleanUpDelay;
MapMapType i_maps;
IntervalTimer i_timer;
@@ -149,41 +156,26 @@ class TC_GAME_API MapManager
template<typename Worker>
void MapManager::DoForAllMaps(Worker&& worker)
{
- std::lock_guard<std::mutex> lock(_mapsLock);
+ std::shared_lock<std::shared_mutex> lock(_mapsLock);
- for (auto& mapPair : i_maps)
- {
- Map* map = mapPair.second;
- if (MapInstanced* mapInstanced = map->ToMapInstanced())
- {
- MapInstanced::InstancedMaps& instances = mapInstanced->GetInstancedMaps();
- for (auto& instancePair : instances)
- worker(instancePair.second);
- }
- else
- worker(map);
- }
+ for (auto const& [key, map] : i_maps)
+ worker(map);
}
template<typename Worker>
-inline void MapManager::DoForAllMapsWithMapId(uint32 mapId, Worker&& worker)
+void MapManager::DoForAllMapsWithMapId(uint32 mapId, Worker&& worker)
{
- std::lock_guard<std::mutex> lock(_mapsLock);
+ std::shared_lock<std::shared_mutex> lock(_mapsLock);
- auto itr = i_maps.find(mapId);
- if (itr != i_maps.end())
- {
- Map* map = itr->second;
- if (MapInstanced* mapInstanced = map->ToMapInstanced())
- {
- MapInstanced::InstancedMaps& instances = mapInstanced->GetInstancedMaps();
- for (auto& p : instances)
- worker(p.second);
- }
- else
- worker(map);
- }
+ auto range = Trinity::Containers::MakeIteratorPair(
+ i_maps.lower_bound({ mapId, 0 }),
+ i_maps.upper_bound({ mapId, std::numeric_limits<uint32>::max() })
+ );
+
+ for (auto const& [key, map] : range)
+ worker(map);
}
#define sMapMgr MapManager::instance()
+
#endif
diff --git a/src/server/game/Maps/TerrainMgr.cpp b/src/server/game/Maps/TerrainMgr.cpp
index d1babe99ae1..e41cadf4808 100644
--- a/src/server/game/Maps/TerrainMgr.cpp
+++ b/src/server/game/Maps/TerrainMgr.cpp
@@ -35,7 +35,11 @@ TerrainInfo::TerrainInfo(uint32 mapId) : _mapId(mapId), _parentTerrain(nullptr),
{
}
-TerrainInfo::~TerrainInfo() = default;
+TerrainInfo::~TerrainInfo()
+{
+ VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId());
+ MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId());
+}
char const* TerrainInfo::GetMapName() const
{
@@ -69,7 +73,7 @@ void TerrainInfo::DiscoverGridMapFiles()
for (uint32 gx = 0; gx < MAX_NUMBER_OF_GRIDS; ++gx)
for (uint32 gy = 0; gy < MAX_NUMBER_OF_GRIDS; ++gy)
- _gridFileExists[gx * MAX_NUMBER_OF_GRIDS + gy] = ExistMap(GetId(), gx, gy, false);
+ _gridFileExists[GetBitsetIndex(gx, gy)] = ExistMap(GetId(), gx, gy, false);
}
bool TerrainInfo::ExistMap(uint32 mapid, int32 gx, int32 gy, bool log /*= true*/)
@@ -144,7 +148,7 @@ bool TerrainInfo::ExistVMap(uint32 mapid, int32 gx, int32 gy)
bool TerrainInfo::HasChildTerrainGridFile(uint32 mapId, int32 gx, int32 gy) const
{
auto childMapItr = std::find_if(_childTerrain.begin(), _childTerrain.end(), [mapId](std::shared_ptr<TerrainInfo> const& childTerrain) { return childTerrain->GetId() == mapId; });
- return childMapItr != _childTerrain.end() && (*childMapItr)->_gridFileExists[gx * MAX_NUMBER_OF_GRIDS + gy];
+ return childMapItr != _childTerrain.end() && (*childMapItr)->_gridFileExists[GetBitsetIndex(gx, gy)];
}
void TerrainInfo::AddChildTerrain(std::shared_ptr<TerrainInfo> childTerrain)
@@ -170,6 +174,8 @@ void TerrainInfo::LoadMapAndVMapImpl(int32 gx, int32 gy)
for (std::shared_ptr<TerrainInfo> const& childTerrain : _childTerrain)
childTerrain->LoadMapAndVMapImpl(gx, gy);
+
+ _loadedGrids[GetBitsetIndex(gx, gy)] = true;
}
void TerrainInfo::LoadMap(int32 gx, int32 gy)
@@ -177,7 +183,7 @@ void TerrainInfo::LoadMap(int32 gx, int32 gy)
if (_gridMap[gx][gy])
return;
- if (!_gridFileExists[gx * MAX_NUMBER_OF_GRIDS + gy])
+ if (!_gridFileExists[GetBitsetIndex(gx, gy)])
return;
// map file name
@@ -189,7 +195,7 @@ void TerrainInfo::LoadMap(int32 gx, int32 gy)
if (gridMapLoadResult == GridMap::LoadResult::Ok)
_gridMap[gx][gy] = std::move(gridMap);
else
- _gridFileExists[gx * MAX_NUMBER_OF_GRIDS + gy] = false;
+ _gridFileExists[GetBitsetIndex(gx, gy)] = false;
if (gridMapLoadResult == GridMap::LoadResult::InvalidFile)
TC_LOG_ERROR("maps", "Error loading map file: %s", fileName.c_str());
@@ -206,12 +212,15 @@ void TerrainInfo::LoadVMap(int32 gx, int32 gy)
case VMAP::LoadResult::Success:
TC_LOG_DEBUG("maps", "VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
break;
- default:
+ case VMAP::LoadResult::VersionMismatch:
+ case VMAP::LoadResult::ReadFromFileFailed:
TC_LOG_ERROR("maps", "Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
break;
case VMAP::LoadResult::DisabledInConfig:
TC_LOG_DEBUG("maps", "Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
break;
+ default:
+ break;
}
}
@@ -242,6 +251,8 @@ void TerrainInfo::UnloadMapImpl(int32 gx, int32 gy)
for (std::shared_ptr<TerrainInfo> const& childTerrain : _childTerrain)
childTerrain->UnloadMapImpl(gx, gy);
+
+ _loadedGrids[GetBitsetIndex(gx, gy)] = false;
}
GridMap* TerrainInfo::GetGrid(uint32 mapId, float x, float y, bool loadIfMissing /*= true*/)
@@ -251,7 +262,7 @@ GridMap* TerrainInfo::GetGrid(uint32 mapId, float x, float y, bool loadIfMissing
int32 gy = (int)(CENTER_GRID_ID - y / SIZE_OF_GRIDS); //grid y
// ensure GridMap is loaded
- if (!_gridMap[gx][gy] && loadIfMissing)
+ if (!_loadedGrids[GetBitsetIndex(gx, gy)] && loadIfMissing)
{
std::lock_guard<std::mutex> lock(_loadMutex);
LoadMapAndVMapImpl(gx, gy);
@@ -277,7 +288,7 @@ void TerrainInfo::CleanUpGrids(uint32 diff)
// delete those GridMap objects which have refcount = 0
for (int32 x = 0; x < MAX_NUMBER_OF_GRIDS; ++x)
for (int32 y = 0; y < MAX_NUMBER_OF_GRIDS; ++y)
- if (_gridMap[x][y] && !_referenceCountFromMap[x][y])
+ if (_loadedGrids[GetBitsetIndex(x, y)] && !_referenceCountFromMap[x][y])
UnloadMapImpl(x, y);
_cleanupTimer.Reset(CleanupInterval);
diff --git a/src/server/game/Maps/TerrainMgr.h b/src/server/game/Maps/TerrainMgr.h
index 0bf2ab35a05..54b9192109b 100644
--- a/src/server/game/Maps/TerrainMgr.h
+++ b/src/server/game/Maps/TerrainMgr.h
@@ -97,6 +97,8 @@ public:
float GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground = nullptr, bool swim = false, float collisionHeight = 2.03128f, DynamicMapTree const* dynamicMapTree = nullptr); // DEFAULT_COLLISION_HEIGHT in Object.h
private:
+ static constexpr int32 GetBitsetIndex(int32 gx, int32 gy) { return gx * MAX_NUMBER_OF_GRIDS + gy; }
+
uint32 _mapId;
TerrainInfo* _parentTerrain;
@@ -105,6 +107,7 @@ private:
std::mutex _loadMutex;
std::unique_ptr<GridMap> _gridMap[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
std::atomic<uint16> _referenceCountFromMap[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
+ std::bitset<MAX_NUMBER_OF_GRIDS* MAX_NUMBER_OF_GRIDS> _loadedGrids;
std::bitset<MAX_NUMBER_OF_GRIDS* MAX_NUMBER_OF_GRIDS> _gridFileExists; // cache what grids are available for this map (not including parent/child maps)
static constexpr Milliseconds CleanupInterval = 1min;
diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp
index f0e32ce98d6..59835a201f5 100644
--- a/src/server/game/Maps/TransportMgr.cpp
+++ b/src/server/game/Maps/TransportMgr.cpp
@@ -21,7 +21,7 @@
#include "DB2Stores.h"
#include "InstanceScript.h"
#include "Log.h"
-#include "MapManager.h"
+#include "Map.h"
#include "MoveSplineInitArgs.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
diff --git a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp
index a58b6b7f824..b34809b2f51 100644
--- a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.cpp
@@ -19,7 +19,7 @@
#include "DB2Stores.h"
#include "GameEventSender.h"
#include "Log.h"
-#include "MapManager.h"
+#include "Map.h"
#include "MovementDefines.h"
#include "MoveSpline.h"
#include "MoveSplineInit.h"
@@ -132,7 +132,7 @@ bool FlightPathMovementGenerator::DoUpdate(Player* owner, uint32 /*diff*/)
break;
if (_currentNode == _preloadTargetNode)
- PreloadEndGrid();
+ PreloadEndGrid(owner);
_currentNode += departureEvent ? 1 : 0;
departureEvent = !departureEvent;
@@ -284,14 +284,18 @@ void FlightPathMovementGenerator::InitEndGridInfo()
_preloadTargetNode = 0;
else
_preloadTargetNode = nodeCount - 3;
+
+ while (_path[_preloadTargetNode]->ContinentID != _endMapId)
+ ++_preloadTargetNode;
+
_endGridX = _path[nodeCount - 1]->Loc.X;
_endGridY = _path[nodeCount - 1]->Loc.Y;
}
-void FlightPathMovementGenerator::PreloadEndGrid()
+void FlightPathMovementGenerator::PreloadEndGrid(Player* owner)
{
// Used to preload the final grid where the flightmaster is
- Map* endMap = sMapMgr->FindBaseNonInstanceMap(_endMapId);
+ Map* endMap = owner->GetMap();
// Load the grid
if (endMap)
diff --git a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h
index 7252b1effe1..10bbab589e2 100644
--- a/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/FlightPathMovementGenerator.h
@@ -54,7 +54,7 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium<Player, Fligh
void SkipCurrentNode() { ++_currentNode; }
void DoEventIfAny(Player* owner, TaxiPathNodeEntry const* node, bool departure);
void InitEndGridInfo();
- void PreloadEndGrid();
+ void PreloadEndGrid(Player* owner);
std::string GetDebugInfo() const override;
diff --git a/src/server/game/Movement/Waypoints/WaypointManager.cpp b/src/server/game/Movement/Waypoints/WaypointManager.cpp
index a7c76ad3c90..182f7c35065 100644
--- a/src/server/game/Movement/Waypoints/WaypointManager.cpp
+++ b/src/server/game/Movement/Waypoints/WaypointManager.cpp
@@ -18,7 +18,6 @@
#include "WaypointManager.h"
#include "DatabaseEnv.h"
#include "GridDefines.h"
-#include "MapManager.h"
#include "Log.h"
void WaypointMgr::Load()
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
index 97ac8a83d4e..1e609b15272 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
@@ -23,7 +23,6 @@
#include "Group.h"
#include "Log.h"
#include "Map.h"
-#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "OutdoorPvPMgr.h"
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 0d2fd838d75..5b741bda0ca 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -67,6 +67,7 @@
#include "LootItemStorage.h"
#include "LootMgr.h"
#include "M2Stores.h"
+#include "Map.h"
#include "MapManager.h"
#include "Metric.h"
#include "MiscPackets.h"
@@ -2493,19 +2494,6 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading phase names...");
sObjectMgr->LoadPhaseNames();
- // Preload all cells, if required for the base maps
- if (sWorld->getBoolConfig(CONFIG_BASEMAP_LOAD_GRIDS))
- {
- sMapMgr->DoForAllMaps([](Map* map)
- {
- if (!map->Instanceable())
- {
- TC_LOG_INFO("server.loading", "Pre-loading base map data for map %u", map->GetId());
- map->LoadAllCells();
- }
- });
- }
-
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
TC_LOG_INFO("server.worldserver", "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000));
diff --git a/src/server/scripts/Battlefield/BattlefieldTB.cpp b/src/server/scripts/Battlefield/BattlefieldTB.cpp
index 93ed4da8131..c49d92eb6bc 100644
--- a/src/server/scripts/Battlefield/BattlefieldTB.cpp
+++ b/src/server/scripts/Battlefield/BattlefieldTB.cpp
@@ -29,7 +29,6 @@
#include "CreatureTextMgr.h"
#include "GameObject.h"
#include "GameTime.h"
-#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "Random.h"
diff --git a/src/server/scripts/Battlefield/BattlefieldWG.cpp b/src/server/scripts/Battlefield/BattlefieldWG.cpp
index 895868b9cec..07400151e52 100644
--- a/src/server/scripts/Battlefield/BattlefieldWG.cpp
+++ b/src/server/scripts/Battlefield/BattlefieldWG.cpp
@@ -28,7 +28,6 @@
#include "GameObject.h"
#include "GameTime.h"
#include "Log.h"
-#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "Random.h"
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index b3879bafd56..72e3ffc6838 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -37,6 +37,7 @@ EndScriptData */
#include "DB2Stores.h"
#include "GameTime.h"
#include "GridNotifiersImpl.h"
+#include "InstanceSaveMgr.h"
#include "InstanceScript.h"
#include "Language.h"
#include "Log.h"
@@ -1233,17 +1234,26 @@ public:
static bool HandleDebugLoadCellsCommand(ChatHandler* handler, Optional<uint32> mapId, Optional<uint32> tileX, Optional<uint32> tileY)
{
- Map* map = nullptr;
if (mapId)
{
- map = sMapMgr->FindBaseNonInstanceMap(*mapId);
+ sMapMgr->DoForAllMapsWithMapId(*mapId, [&](Map* map)
+ {
+ HandleDebugLoadCellsCommandHelper(handler, map, tileX, tileY);
+ });
+ return true;
}
- else if (Player* player = handler->GetPlayer())
+
+ if (Player* player = handler->GetPlayer())
{
// Fallback to player's map if no map has been specified
- map = player->GetMap();
+ return HandleDebugLoadCellsCommandHelper(handler, player->GetMap(), tileX, tileY);
}
+ return false;
+ }
+
+ static bool HandleDebugLoadCellsCommandHelper(ChatHandler* handler, Map* map, Optional<uint32> tileX, Optional<uint32> tileY)
+ {
if (!map)
return false;
diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp
index e389f535569..027c72e1c23 100644
--- a/src/server/scripts/Commands/cs_gobject.cpp
+++ b/src/server/scripts/Commands/cs_gobject.cpp
@@ -33,6 +33,7 @@ EndScriptData */
#include "GameTime.h"
#include "Language.h"
#include "Log.h"
+#include "Map.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
diff --git a/src/server/scripts/Commands/cs_instance.cpp b/src/server/scripts/Commands/cs_instance.cpp
index eb5173b1daf..a00853298c0 100644
--- a/src/server/scripts/Commands/cs_instance.cpp
+++ b/src/server/scripts/Commands/cs_instance.cpp
@@ -31,6 +31,7 @@ EndScriptData */
#include "InstanceSaveMgr.h"
#include "InstanceScript.h"
#include "Language.h"
+#include "Map.h"
#include "MapManager.h"
#include "Player.h"
#include "RBAC.h"
diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp
index 61668b98973..5ca3df7caca 100644
--- a/src/server/scripts/Commands/cs_list.cpp
+++ b/src/server/scripts/Commands/cs_list.cpp
@@ -32,7 +32,7 @@ EndScriptData */
#include "GameObject.h"
#include "GameTime.h"
#include "Language.h"
-#include "MapManager.h"
+#include "Map.h"
#include "ObjectMgr.h"
#include "PhasingHandler.h"
#include "Player.h"
@@ -120,28 +120,18 @@ public:
bool liveFound = false;
// Get map (only support base map from console)
- Map* thisMap;
+ Map* thisMap = nullptr;
if (handler->GetSession())
thisMap = handler->GetSession()->GetPlayer()->GetMap();
- else
- thisMap = sMapMgr->FindBaseNonInstanceMap(mapId);
// If map found, try to find active version of this creature
if (thisMap)
{
- auto const creBounds = thisMap->GetCreatureBySpawnIdStore().equal_range(guid);
- if (creBounds.first != creBounds.second)
- {
- for (std::unordered_multimap<ObjectGuid::LowType, Creature*>::const_iterator itr = creBounds.first; itr != creBounds.second;)
- {
- if (handler->GetSession())
- handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, std::to_string(guid).c_str(), std::to_string(guid).c_str(), cInfo->Name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->IsAlive() ? "*" : " ");
- else
- handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, std::to_string(guid).c_str(), cInfo->Name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->IsAlive() ? "*" : " ");
- ++itr;
- }
- liveFound = true;
- }
+ auto const creBounds = Trinity::Containers::MapEqualRange(thisMap->GetCreatureBySpawnIdStore(), guid);
+ for (auto& [spawnId, creature] : creBounds)
+ handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, std::to_string(guid).c_str(), std::to_string(guid).c_str(), cInfo->Name.c_str(),
+ x, y, z, mapId, creature->GetGUID().ToString().c_str(), creature->IsAlive() ? "*" : " ");
+ liveFound = creBounds.begin() != creBounds.end();
}
if (!liveFound)
@@ -401,28 +391,18 @@ public:
bool liveFound = false;
// Get map (only support base map from console)
- Map* thisMap;
+ Map* thisMap = nullptr;
if (handler->GetSession())
thisMap = handler->GetSession()->GetPlayer()->GetMap();
- else
- thisMap = sMapMgr->FindBaseNonInstanceMap(mapId);
// If map found, try to find active version of this object
if (thisMap)
{
- auto const goBounds = thisMap->GetGameObjectBySpawnIdStore().equal_range(guid);
- if (goBounds.first != goBounds.second)
- {
- for (std::unordered_multimap<ObjectGuid::LowType, GameObject*>::const_iterator itr = goBounds.first; itr != goBounds.second;)
- {
- if (handler->GetSession())
- handler->PSendSysMessage(LANG_GO_LIST_CHAT, std::to_string(guid).c_str(), entry, std::to_string(guid).c_str(), gInfo->name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->isSpawned() ? "*" : " ");
- else
- handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, std::to_string(guid).c_str(), gInfo->name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->isSpawned() ? "*" : " ");
- ++itr;
- }
- liveFound = true;
- }
+ auto const goBounds = Trinity::Containers::MapEqualRange(thisMap->GetGameObjectBySpawnIdStore(), guid);
+ for (auto& [spawnId, go] : goBounds)
+ handler->PSendSysMessage(LANG_GO_LIST_CHAT, std::to_string(guid).c_str(), entry, std::to_string(guid).c_str(), gInfo->name.c_str(), x, y, z, mapId,
+ go->GetGUID().ToString().c_str(), go->isSpawned() ? "*" : " ");
+ liveFound = goBounds.begin() != goBounds.end();
}
if (!liveFound)
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
index 763fa92044f..850f9fd886a 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
@@ -20,7 +20,7 @@
#include "GameObject.h"
#include "GameObjectAI.h"
#include "InstanceScript.h"
-#include "MapManager.h"
+#include "Map.h"
#include "MotionMaster.h"
#include "MoveSplineInit.h"
#include "PassiveAI.h"
diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp
index 1cca54645c5..1a880c0748e 100644
--- a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp
+++ b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp
@@ -17,7 +17,7 @@
#include "OutdoorPvPHP.h"
#include "GameObject.h"
-#include "MapManager.h"
+#include "Map.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "WorldStatePackets.h"
diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp
index 6534c86bfeb..20345358fe5 100644
--- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp
+++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp
@@ -19,7 +19,6 @@
#include "Creature.h"
#include "GameObject.h"
#include "GossipDef.h"
-#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Player.h"