Core/Maps: Removed MapInstanced - no longer neccessary for grid data reference counting (moved to TerrainInfo)

This commit is contained in:
Shauren authored and Ovahlord committed 2022-12-29 22:10:44 +01:00
1 parent f879d95589
commit 81b2ff0d94
33 files changed
+538 -764

No files matched your search

@@ -28,12 +28,10 @@
#include "GroupMgr.h"
#include "Log.h"
#include "Map.h"
#include "MapManager.h"
#include "MiscPackets.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include <G3D/g3dmath.h>
Battlefield::Battlefield(Map* map)
@@ -39,7 +39,6 @@
#include "Formulas.h"
#include "GameEventMgr.h"
#include "Language.h"
#include "Map.h"
#include "MapManager.h"
#include "SharedDefines.h"
#include "ObjectMgr.h"
+1 -2
View File
@@ -68,7 +68,6 @@
#include "LootMgr.h"
#include "LootPackets.h"
#include "Mail.h"
#include "MapInstanced.h"
#include "MapManager.h"
#include "MiscPackets.h"
#include "MotionMaster.h"
@@ -1536,7 +1535,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;
//I think this always returns true. Correct me if I am wrong.
@@ -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"
+1
View File
@@ -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"
+3 -1
View File
@@ -41,8 +41,10 @@
#include "GuildMgr.h"
#include "InspectPackets.h"
#include "InstanceScript.h"
#include "InstanceSaveMgr.h"
#include "Language.h"
#include "Log.h"
#include "Map.h"
#include "MapManager.h"
#include "MiscPackets.h"
#include "Object.h"
@@ -702,7 +704,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData)
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)
@@ -21,6 +21,7 @@
#include "ObjectAccessor.h"
#include "Opcodes.h"
#include "Log.h"
#include "Map.h"
#include "Corpse.h"
#include "DBCStores.h"
#include "Player.h"
+16 -22
View File
@@ -27,7 +27,6 @@
#include "InstanceScript.h"
#include "Log.h"
#include "Map.h"
#include "MapInstanced.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "Player.h"
@@ -597,7 +596,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;
@@ -607,7 +606,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)
{
@@ -687,28 +686,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
+164 -111
View File
@@ -31,8 +31,8 @@
#include "Group.h"
#include "InstanceScript.h"
#include "InstancePackets.h"
#include "InstanceSaveMgr.h"
#include "Log.h"
#include "MapInstanced.h"
#include "MapManager.h"
#include "MMapFactory.h"
#include "MiscPackets.h"
@@ -121,7 +121,7 @@ void Map::DeleteStateMachine()
delete si_GridStates[GRID_STATE_REMOVAL];
}
Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* /*_parent*/) :
Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode) :
_creatureToMoveLock(false), _gameObjectsToMoveLock(false), _dynamicObjectsToMoveLock(false),
i_mapEntry(sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId),
m_unloadTimer(0), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE),
@@ -336,15 +336,9 @@ void Map::DeleteFromWorld(Player* player)
delete player;
}
void Map::EnsureGridCreated(const GridCoord &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(const GridCoord &p)
void Map::EnsureGridCreated(GridCoord const& p)
{
if (!getNGrid(p.x_coord, p.y_coord))
{
@@ -1594,6 +1588,87 @@ 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->GetDifficulty(entry->IsRaid());
// Get the highest available difficulty if current setting is higher than the instance allows
MapDifficulty const* mapDiff = sDBCManager.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;
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, entry->IsRaid()))
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;
@@ -2507,8 +2582,8 @@ template TC_GAME_API void Map::RemoveFromMap(AreaTrigger*, bool);
/* ******* Dungeon Instance Maps ******* */
InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent, TeamId InstanceTeam)
: Map(id, expiry, InstanceId, SpawnMode, _parent),
InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 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)
{
@@ -2575,113 +2650,98 @@ Map::EnterState InstanceMap::CannotEnter(Player* player)
*/
bool InstanceMap::AddPlayerToMap(Player* player)
{
/// @todo Not sure about checking player level: already done in HandleAreaTriggerOpcode
// GMs still can teleport player in instance.
// Is it needed?
Group* group = player->GetGroup();
// 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)
{
std::lock_guard<std::mutex> lock(_mapLock);
// Check moved to void WorldSession::HandleMoveWorldportAckOpcode()
//if (!CanEnter(player))
//return false;
TC_LOG_DEBUG("maps", "InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetDifficulty(), GetInstanceId());
mapSave = sInstanceSaveMgr->AddInstanceSave(GetId(), GetInstanceId(), GetDifficulty(), 0, 0, true);
}
// Dungeon only code
if (IsDungeon())
ASSERT(mapSave);
// check for existing instance binds
InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), GetDifficulty());
if (playerBind && playerBind->perm)
{
// cannot enter other instances if bound permanently
if (playerBind->save != mapSave)
{
Group* group = player->GetGroup();
// 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_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->GetDifficulty()), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), static_cast<uint32>(mapSave->GetDifficulty()), 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)
{
TC_LOG_DEBUG("maps", "InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId());
mapSave = sInstanceSaveMgr->AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true);
}
ASSERT(mapSave);
// check for existing instance binds
InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), Difficulty(GetSpawnMode()));
if (playerBind && playerBind->perm)
{
// cannot enter other instances if bound permanently
if (playerBind->save != mapSave)
{
TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) 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().GetCounter(), GetMapName(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), 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->GetDifficulty()), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), group->GetLeaderGUID().ToString().c_str(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), static_cast<uint32>(playerBind->save->GetDifficulty()), 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->GetDifficulty()), 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(%d) 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().GetCounter(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), group->GetLeaderGUID().ToString().c_str(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), 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(), groupBind->save->GetDifficulty(), 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->GetDifficulty()), group->GetLeaderGUID().ToString().c_str(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), static_cast<uint32>(groupBind->save->GetDifficulty()));
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(%d) 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().GetCounter(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), group->GetLeaderGUID().ToString().c_str(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty());
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 nullptr");
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);
}
}
}
// 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;
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);
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);
@@ -2990,8 +3050,8 @@ uint32 InstanceMap::GetMaxResetDelay() const
/* ******* Battleground Instance Maps ******* */
BattlegroundMap::BattlegroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent, uint8 spawnMode)
: Map(id, expiry, InstanceId, spawnMode, _parent), m_bg(nullptr)
BattlegroundMap::BattlegroundMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 spawnMode)
: Map(id, expiry, InstanceId, spawnMode), m_bg(nullptr)
{
//lets initialize visibility distance for BG/Arenas
BattlegroundMap::InitVisibilityDistance();
@@ -3033,14 +3093,7 @@ Map::EnterState BattlegroundMap::CannotEnter(Player* player)
bool BattlegroundMap::AddPlayerToMap(Player* player)
{
{
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);
}
+7 -12
View File
@@ -47,7 +47,6 @@ class Group;
class InstanceMap;
class InstanceSave;
class InstanceScript;
class MapInstanced;
class Object;
class PhaseShift;
class Player;
@@ -166,7 +165,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
{
friend class MapReference;
public:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = nullptr);
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
virtual ~Map();
MapEntry const* GetEntry() const { return i_mapEntry; }
@@ -294,6 +293,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
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; }
@@ -519,9 +516,9 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
bool _dynamicObjectsToMoveLock;
std::vector<DynamicObject*> _dynamicObjectsToMove;
bool IsGridLoaded(const GridCoord &) const;
void EnsureGridCreated(const GridCoord &);
void EnsureGridCreated_i(const GridCoord &);
bool IsGridLoaded(GridCoord const&) const;
void EnsureGridCreated(GridCoord const&);
void EnsureGridCreated_i(GridCoord const&);
bool EnsureGridLoaded(Cell const&);
void EnsureGridLoadedForActiveObject(Cell const&, WorldObject* object);
@@ -542,8 +539,6 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
void SendObjectUpdates();
protected:
std::mutex _mapLock;
std::mutex _gridLock;
MapEntry const* i_mapEntry;
uint8 i_spawnMode;
@@ -768,7 +763,7 @@ enum InstanceResetMethod
class TC_GAME_API InstanceMap : public Map
{
public:
InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent, TeamId InstanceTeam);
InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, TeamId InstanceTeam);
~InstanceMap();
bool AddPlayerToMap(Player*) override;
void RemovePlayerFromMap(Player*, bool) override;
@@ -805,7 +800,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, uint8 spawnMode);
BattlegroundMap(uint32 id, time_t, uint32 InstanceId, uint8 spawnMode);
~BattlegroundMap();
bool AddPlayerToMap(Player*) override;
-303
View File
@@ -1,303 +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 "DBCStores.h"
#include "Group.h"
#include "InstanceSaveMgr.h"
#include "Log.h"
#include "MapManager.h"
#include "MMapFactory.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "VMapFactory.h"
#include "VMapManager2.h"
#include "World.h"
MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DUNGEON_DIFFICULTY_NORMAL)
{
}
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)
{
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->GetDifficulty(IsRaid()));
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->GetDifficulty(), 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->GetDifficulty(IsRaid()));
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->GetDifficulty(), 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()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid());
//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());
}
}
return map;
}
InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty, TeamId InstanceTeam)
{
// 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();
}
InstanceTemplate const* iTemplate = sObjectMgr->GetInstanceTemplate(GetId());
if (!iTemplate)
{
TC_LOG_ERROR("maps", "CreateInstance: no instance template for map %d", GetId());
ABORT();
}
// some instances only have one difficulty
sDBCManager.GetDownscaledMapDifficultyData(GetId(), difficulty);
TC_LOG_DEBUG("maps", "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal");
InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this, InstanceTeam);
ASSERT(map->IsDungeon());
map->LoadRespawnTimes();
map->LoadCorpseData();
bool load_data = save != nullptr;
map->CreateInstanceData(load_data);
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());
PvPDifficultyEntry const* bracketEntry = sDBCManager.GetBattlegroundBracketByLevel(bg->GetMapId(), bg->GetMinLevel());
uint8 spawnMode;
if (bracketEntry)
spawnMode = bracketEntry->Difficulty;
else
spawnMode = REGULAR_DIFFICULTY;
BattlegroundMap* map = new BattlegroundMap(GetId(), GetGridExpiry(), InstanceId, this, spawnMode);
ASSERT(map->IsBattlegroundOrArena());
map->SetBG(bg);
bg->SetBgMap(map);
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;
}
-58
View File
@@ -1,58 +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"
#include "DBCEnums.h"
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() { }
// functions overwrite Map versions
void Update(uint32) 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 InstanceTeam);
BattlegroundMap* CreateBattleground(uint32 InstanceId, Battleground* bg);
InstancedMaps m_InstancedMaps;
};
#endif
+221 -115
View File
@@ -16,34 +16,31 @@
*/
#include "MapManager.h"
#include "InstanceSaveMgr.h"
#include "Battleground.h"
#include "Containers.h"
#include "DatabaseEnv.h"
#include "DBCStores.h"
#include "Log.h"
#include "ObjectAccessor.h"
#include "Transport.h"
#include "GridDefines.h"
#include "MapInstanced.h"
#include "InstanceScript.h"
#include "Config.h"
#include "World.h"
#include "Corpse.h"
#include "ObjectMgr.h"
#include "Language.h"
#include "WorldPacket.h"
#include "Group.h"
#include "Player.h"
#include "WorldSession.h"
#include "InstanceSaveMgr.h"
#include "Language.h"
#include "Log.h"
#include "Map.h"
#include "Opcodes.h"
#include "Player.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include <boost/dynamic_bitset.hpp>
#include <numeric>
MapManager::MapManager()
: _nextInstanceId(0), _scheduledScripts(0)
: _freeInstanceIds(std::make_unique<InstanceIds>()), _nextInstanceId(0), _scheduledScripts(0)
{
i_gridCleanUpDelay = sWorld->getIntConfig(CONFIG_INTERVAL_GRIDCLEAN);
i_timer.SetInterval(sWorld->getIntConfig(CONFIG_INTERVAL_MAPUPDATE));
}
MapManager::~MapManager() { }
MapManager::~MapManager() = default;
void MapManager::Initialize()
{
@@ -67,79 +64,182 @@ MapManager* MapManager::instance()
return &instance;
}
Map* MapManager::CreateBaseMap(uint32 id)
Map* MapManager::FindMap_i(uint32 mapId, uint32 instanceId) const
{
Map* map = FindBaseMap(id);
return Trinity::Containers::MapGetValuePtr(i_maps, { mapId, instanceId });
}
if (!map)
Map* MapManager::CreateWorldMap(uint32 mapId, uint32 instanceId)
{
Map* map = new Map(mapId, i_gridCleanUpDelay, instanceId, REGULAR_DIFFICULTY);
map->LoadRespawnTimes();
map->LoadCorpseData();
if (sWorld->getBoolConfig(CONFIG_BASEMAP_LOAD_GRIDS))
map->LoadAllCells();
return map;
}
InstanceMap* MapManager::CreateInstance(uint32 mapId, uint32 instanceId, InstanceSave* save, Difficulty difficulty, TeamId team)
{
// make sure we have a valid map id
MapEntry const* entry = sMapStore.LookupEntry(mapId);
if (!entry)
{
MapEntry const* entry = sMapStore.AssertEntry(id);
if (entry->ParentMapID != -1)
TC_LOG_ERROR("maps", "CreateInstance: no entry for map %d", mapId);
ABORT();
}
// some instances only have one difficulty
sDBCManager.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 (sWorld->getBoolConfig(CONFIG_INSTANCEMAP_LOAD_GRIDS))
map->LoadAllCells();
return map;
}
BattlegroundMap* MapManager::CreateBattleground(uint32 mapId, uint32 instanceId, Battleground* bg)
{
TC_LOG_DEBUG("maps", "MapInstanced::CreateBattleground: map bg %d for %d created.", instanceId, mapId);
BattlegroundMap* map = new BattlegroundMap(mapId, i_gridCleanUpDelay, instanceId, REGULAR_DIFFICULTY);
ASSERT(map->IsBattlegroundOrArena());
map->SetBG(bg);
bg->SetBgMap(map);
return map;
}
/*
- 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*/)
{
if (!player)
return nullptr;
MapEntry const* entry = sMapStore.LookupEntry(mapId);
if (!entry)
return nullptr;
std::unique_lock<std::shared_mutex> lock(_mapsLock);
Map* map = nullptr;
uint32 newInstanceId = 0; // instanceId of the resulting map
if (entry->IsBattlegroundOrArena())
{
// 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)
{
CreateBaseMap(entry->ParentMapID);
// must have been created by parent map
map = FindBaseMap(id);
return ASSERT_NOTNULL(map);
if (Battleground* bg = player->GetBattleground())
map = CreateBattleground(mapId, newInstanceId, bg);
else
{
player->TeleportToBGEntryPoint();
return nullptr;
}
}
std::lock_guard<std::mutex> lock(_mapsLock);
map = CreateBaseMap_i(entry);
}
ASSERT(map);
return map;
}
Map* MapManager::CreateBaseMap_i(MapEntry const* mapEntry)
{
Map* map;
if (mapEntry->Instanceable())
map = new MapInstanced(mapEntry->ID, i_gridCleanUpDelay);
else
map = new Map(mapEntry->ID, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY);
i_maps[mapEntry->ID] = map;
if (!mapEntry->Instanceable())
else if (entry->IsDungeon())
{
map->LoadRespawnTimes();
map->LoadCorpseData();
InstancePlayerBind* pBind = player->GetBoundInstance(mapId, player->GetDifficulty(entry->IsRaid()));
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->GetDifficulty(), 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->GetDifficulty(entry->IsRaid()));
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->GetDifficulty(), player->GetTeamId());
}
else
{
Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(entry->IsRaid()) : player->GetDifficulty(entry->IsRaid());
// if no instanceId via group members or instance saves is found
// the instance will be created for the first time
newInstanceId = GenerateInstanceId();
//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
{
newInstanceId = 0;
map = FindMap_i(mapId, newInstanceId);
if (!map)
map = CreateWorldMap(mapId, newInstanceId);
}
if (map)
i_maps[{ map->GetId(), map->GetInstanceId() }] = map;
return map;
}
Map* MapManager::FindBaseNonInstanceMap(uint32 mapId) const
Map* MapManager::FindMap(uint32 mapId, uint32 instanceId) const
{
Map* map = FindBaseMap(mapId);
if (map && map->Instanceable())
return nullptr;
return map;
}
Map* MapManager::CreateMap(uint32 id, Player* player, uint32 loginInstanceId)
{
Map* m = CreateBaseMap(id);
if (m && m->Instanceable())
m = ((MapInstanced*)m)->CreateInstanceForPlayer(id, player, loginInstanceId);
return m;
}
Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) const
{
Map* map = FindBaseMap(mapid);
if (!map)
return nullptr;
if (!map->Instanceable())
return instanceId == 0 ? map : nullptr;
return ((MapInstanced*)map)->FindInstanceMap(instanceId);
std::shared_lock<std::shared_mutex> lock(_mapsLock);
return FindMap_i(mapId, instanceId);
}
/*
Map::EnterState MapManager::PlayerCannotEnter(uint32 mapid, Player* player, bool loginCheck)
{
MapEntry const* entry = sMapStore.LookupEntry(mapid);
@@ -229,7 +329,7 @@ Map::EnterState MapManager::PlayerCannotEnter(uint32 mapid, Player* player, bool
else
return Map::CANNOT_ENTER_UNSPECIFIED_REASON;
}
*/
void MapManager::Update(uint32 diff)
{
i_timer.Update(diff);
@@ -237,12 +337,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();
@@ -253,7 +365,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, bool startUp)
{
@@ -285,37 +412,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()
@@ -323,18 +429,18 @@ void MapManager::InitInstanceIds()
_nextInstanceId = 1;
if (QueryResult result = CharacterDatabase.Query("SELECT IFNULL(MAX(id), 0) FROM instance"))
_freeInstanceIds.resize((*result)[0].GetUInt64() + 2, true); // make space for one extra to be able to access [_nextInstanceId] index in case all slots are taken
_freeInstanceIds->resize((*result)[0].GetUInt64() + 2, true); // make space for one extra to be able to access [_nextInstanceId] index in case all slots are taken
else
_freeInstanceIds.resize(_nextInstanceId + 1, true);
_freeInstanceIds->resize(_nextInstanceId + 1, true);
// never allow 0 id
_freeInstanceIds[0] = false;
_freeInstanceIds->set(0, false);
}
void MapManager::RegisterInstanceId(uint32 instanceId)
{
// Allocation and sizing was done in InitInstanceIds()
_freeInstanceIds[instanceId] = false;
_freeInstanceIds->set(instanceId, false);
// Instances are pulled in ascending order from db and nextInstanceId is initialized with 1,
// so if the instance id is used, increment until we find the first unused one for a potential new instance
@@ -352,15 +458,15 @@ uint32 MapManager::GenerateInstanceId()
}
uint32 newInstanceId = _nextInstanceId;
ASSERT(newInstanceId < _freeInstanceIds.size());
_freeInstanceIds[newInstanceId] = false;
ASSERT(newInstanceId < _freeInstanceIds->size());
_freeInstanceIds->set(newInstanceId, false);
// Find the lowest available id starting from the current NextInstanceId (which should be the lowest according to the logic in FreeInstanceId()
size_t nextFreedId = _freeInstanceIds.find_next(_nextInstanceId++);
size_t nextFreedId = _freeInstanceIds->find_next(_nextInstanceId++);
if (nextFreedId == InstanceIds::npos)
{
_nextInstanceId = uint32(_freeInstanceIds.size());
_freeInstanceIds.push_back(true);
_nextInstanceId = uint32(_freeInstanceIds->size());
_freeInstanceIds->push_back(true);
}
else
_nextInstanceId = uint32(nextFreedId);
@@ -372,5 +478,5 @@ void MapManager::FreeInstanceId(uint32 instanceId)
{
// If freed instance id is lower than the next id available for new instances, use the freed one instead
_nextInstanceId = std::min(instanceId, _nextInstanceId);
_freeInstanceIds[instanceId] = true;
_freeInstanceIds->set(instanceId, true);
}
+47 -60
View File
@@ -18,29 +18,41 @@
#ifndef TRINITY_MAPMANAGER_H
#define TRINITY_MAPMANAGER_H
#include "Object.h"
#include "Map.h"
#include "MapInstanced.h"
#include "GridStates.h"
#include "GridDefines.h"
#include "IteratorPair.h"
#include "MapUpdater.h"
#include <boost/dynamic_bitset.hpp>
#include "Position.h"
#include "SharedDefines.h"
#include <boost/dynamic_bitset_fwd.hpp>
#include <map>
#include <shared_mutex>
class PhaseShift;
class Transport;
struct TransportCreatureProto;
class Battleground;
class BattlegroundMap;
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)
{
@@ -59,7 +71,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, bool startUp);
@@ -89,14 +100,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();
@@ -118,29 +126,24 @@ 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);
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;
InstanceIds _freeInstanceIds;
std::unique_ptr<InstanceIds> _freeInstanceIds;
uint32 _nextInstanceId;
MapUpdater m_updater;
@@ -151,40 +154,24 @@ class TC_GAME_API MapManager
template<typename Worker>
inline 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& instancePair : instances)
worker(instancePair.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()
+15 -7
View File
@@ -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());
@@ -245,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*/)
@@ -254,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);
@@ -283,7 +291,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.count());
+3
View File
@@ -98,6 +98,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;
@@ -106,6 +108,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;
+1 -1
View File
@@ -22,7 +22,7 @@
#include "GameObjectData.h"
#include "InstanceScript.h"
#include "Log.h"
#include "MapManager.h"
#include "Map.h"
#include "MoveSplineInitArgs.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
@@ -19,7 +19,7 @@
#include "DBCStores.h"
#include "GameEventSender.h"
#include "Log.h"
#include "MapManager.h"
#include "Map.h"
#include "MoveSpline.h"
#include "MoveSplineInit.h"
#include "ObjectMgr.h"
@@ -190,7 +190,7 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
break;
if (_currentNode == _preloadTargetNode)
PreloadEndGrid();
PreloadEndGrid(player);
_currentNode += departureEvent ? 1 : 0;
departureEvent = !departureEvent;
} while (_currentNode < _path.size() - 1);
@@ -240,14 +240,18 @@ void FlightPathMovementGenerator::InitEndGridInfo()
uint32 nodeCount = _path.size(); //! Number of nodes in path.
_endMapId = _path[nodeCount - 1]->ContinentID; //! MapId of last node
_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);
// Used to preload the final grid where the flightmaster is
Map* endMap = owner->GetMap();
// Load the grid
if (endMap)
@@ -49,7 +49,7 @@ public:
bool GetResetPos(Player*, float& x, float& y, float& z);
void InitEndGridInfo();
void PreloadEndGrid();
void PreloadEndGrid(Player* owner);
private:
@@ -18,7 +18,6 @@
#include "WaypointManager.h"
#include "DatabaseEnv.h"
#include "GridDefines.h"
#include "MapManager.h"
#include "Log.h"
void WaypointMgr::Load()
@@ -22,7 +22,6 @@
#include "Group.h"
#include "Log.h"
#include "Map.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "OutdoorPvPMgr.h"
+1
View File
@@ -27,6 +27,7 @@
#include "Item.h"
#include "LFGScripts.h"
#include "Log.h"
#include "Map.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "OutdoorPvPMgr.h"
+1
View File
@@ -35,6 +35,7 @@
#include "GuildMgr.h"
#include "IpAddress.h"
#include "Log.h"
#include "Map.h"
#include "MapManager.h"
#include "Metric.h"
#include "ObjectAccessor.h"
+1 -1
View File
@@ -727,7 +727,7 @@ void Spell::EffectTriggerRitualOfSummoning(SpellEffIndex effIndex)
continue;
}
Map::EnterState enterState = sMapMgr->PlayerCannotEnter(player->GetMapId(), member, false);
Map::EnterState enterState = Map::PlayerCannotEnter(player->GetMapId(), member, false);
if (enterState != Map::CAN_ENTER)
{
if (enterState == Map::CANNOT_ENTER_INSTANCE_BIND_MISMATCH)
+1 -13
View File
@@ -59,6 +59,7 @@
#include "LootItemStorage.h"
#include "LootMgr.h"
#include "M2Stores.h"
#include "Map.h"
#include "MapManager.h"
#include "Metric.h"
#include "MMapFactory.h"
@@ -2346,19 +2347,6 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Calculate next currency reset time...");
InitCurrencyResetTime();
// 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));
@@ -28,7 +28,6 @@
#include "Creature.h"
#include "GameObject.h"
#include "GameTime.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "Random.h"
@@ -27,7 +27,6 @@
#include "GameObject.h"
#include "GameTime.h"
#include "Log.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
+20 -2
View File
@@ -31,6 +31,7 @@ EndScriptData */
#include "DBCStores.h"
#include "GossipDef.h"
#include "GridNotifiersImpl.h"
#include "InstanceSaveMgr.h"
#include "InstanceScript.h"
#include "Language.h"
#include "Log.h"
@@ -1622,14 +1623,31 @@ public:
if (*args)
{
int32 mapId = atoi(args);
map = sMapMgr->FindBaseNonInstanceMap(mapId);
sMapMgr->DoForAllMapsWithMapId(mapId, [&](Map* map)
{
HandleDebugLoadCellsCommandHelper(handler, map);
});
return true;
}
if (!map)
map = player->GetMap();
{
// Fallback to player's map if no map has been specified
return HandleDebugLoadCellsCommandHelper(handler, player->GetMap());
}
return false;
}
static bool HandleDebugLoadCellsCommandHelper(ChatHandler* handler, Map* map)
{
if (!map)
return false;
handler->PSendSysMessage("Loading all cells (mapId: %u). Current next GameObject %u, Creature %u", map->GetId(), map->GetMaxLowGuid<HighGuid::GameObject>(), map->GetMaxLowGuid<HighGuid::Unit>());
map->LoadAllCells();
handler->PSendSysMessage("Cells loaded (mapId: %u) After load - Next GameObject %u, Creature %u", map->GetId(), map->GetMaxLowGuid<HighGuid::GameObject>(), map->GetMaxLowGuid<HighGuid::Unit>());
return true;
}
@@ -31,6 +31,7 @@ EndScriptData */
#include "GameObject.h"
#include "Language.h"
#include "Log.h"
#include "Map.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
@@ -29,6 +29,7 @@ EndScriptData */
#include "InstanceSaveMgr.h"
#include "InstanceScript.h"
#include "Language.h"
#include "Map.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
+13 -32
View File
@@ -32,6 +32,7 @@ EndScriptData */
#include "GameTime.h"
#include "Language.h"
#include "Map.h"
#include "Map.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
@@ -129,28 +130,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<uint32, Creature*>::const_iterator itr = creBounds.first; itr != creBounds.second;)
{
if (handler->GetSession())
handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->IsAlive() ? "*" : " ");
else
handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, 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)
@@ -448,28 +439,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<uint32, GameObject*>::const_iterator itr = goBounds.first; itr != goBounds.second;)
{
if (handler->GetSession())
handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name.c_str(), x, y, z, mapId, itr->second->GetGUID().ToString().c_str(), itr->second->isSpawned() ? "*" : " ");
else
handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, 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)
@@ -16,20 +16,19 @@
*/
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "blackwing_descent.h"
#include "CommonPredicates.h"
#include "DBCStores.h"
#include "GridNotifiers.h"
#include "PassiveAI.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "SpellMgr.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "PassiveAI.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellAuraEffects.h"
#include "SpellMgr.h"
#include "SpellScript.h"
#include "TemporarySummon.h"
#include "MapInstanced.h"
#include "blackwing_descent.h"
enum Spells
{
@@ -17,7 +17,7 @@
#include "ScriptMgr.h"
#include "GameObject.h"
#include "MapManager.h"
#include "Map.h"
#include "OutdoorPvP.h"
#include "OutdoorPvPHP.h"
#include "OutdoorPvPMgr.h"
@@ -260,7 +260,7 @@ void OPvPCapturePointHP::ChangeState()
break;
}
Map* map = sMapMgr->FindMap(530, 0);
Map* map = m_PvP->GetMap();
auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId);
for (auto itr = bounds.first; itr != bounds.second; ++itr)
itr->second->SetGoArtKit(artkit);