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

This commit is contained in:
Shauren
2022-07-24 18:56:40 +02:00
parent 8f2c5413d7
commit fbe0b8efeb
34 changed files with 515 additions and 824 deletions
@@ -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"
@@ -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)
@@ -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"
+1 -1
View File
@@ -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
@@ -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"
+2 -2
View File
@@ -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();
}
+1 -1
View File
@@ -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();
+3 -1
View File
@@ -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)
@@ -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"
+16 -22
View File
@@ -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
+163 -111
View File
@@ -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,113 +2837,98 @@ 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?
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(), GetDifficultyID(), GetInstanceId());
mapSave = sInstanceSaveMgr->AddInstanceSave(GetId(), GetInstanceId(), GetDifficultyID(), 0, 0, true);
}
// Dungeon only code
if (IsDungeon())
ASSERT(mapSave);
// 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)
{
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->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)
{
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);
// 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;
}
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);
}
}
}
// 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, 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);
}
+4 -11
View File
@@ -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;
-311
View File
@@ -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;
}
-64
View File
@@ -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
+207 -165
View File
@@ -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);
// must have been created by parent map
map = FindBaseMap(id);
return ASSERT_NOTNULL(map);
}
std::lock_guard<std::mutex> lock(_mapsLock);
map = CreateBaseMap_i(entry);
}
ASSERT(map);
return map;
return Trinity::Containers::MapGetValuePtr(i_maps, { mapId, instanceId });
}
Map* MapManager::CreateBaseMap_i(MapEntry const* mapEntry)
Map* MapManager::CreateWorldMap(uint32 mapId, uint32 instanceId)
{
Map* map;
if (mapEntry->Instanceable())
map = new MapInstanced(mapEntry->ID, i_gridCleanUpDelay);
else
map = new Map(mapEntry->ID, i_gridCleanUpDelay, 0, DIFFICULTY_NONE);
Map* map = new Map(mapId, i_gridCleanUpDelay, instanceId, DIFFICULTY_NONE);
map->LoadRespawnTimes();
map->LoadCorpseData();
i_maps[mapEntry->ID] = map;
if (!mapEntry->Instanceable())
{
map->LoadRespawnTimes();
map->LoadCorpseData();
}
if (sWorld->getBoolConfig(CONFIG_BASEMAP_LOAD_GRIDS))
map->LoadAllCells();
return map;
}
Map* MapManager::FindBaseNonInstanceMap(uint32 mapId) const
InstanceMap* MapManager::CreateInstance(uint32 mapId, uint32 instanceId, InstanceSave* save, Difficulty difficulty, TeamId team)
{
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);
}
Map::EnterState MapManager::PlayerCannotEnter(uint32 mapid, Player* player, bool loginCheck)
{
MapEntry const* entry = sMapStore.LookupEntry(mapid);
// make sure we have a valid map id
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;
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 Map::CANNOT_ENTER_NOT_IN_RAID;
if (!player->IsAlive())
{
if (player->HasCorpse())
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;
}
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, DIFFICULTY_NONE);
ASSERT(map->IsBattlegroundOrArena());
map->SetBG(bg);
bg->SetBgMap(map);
return map;
}
GarrisonMap* MapManager::CreateGarrison(uint32 mapId, uint32 instanceId, Player* owner)
{
GarrisonMap* map = new GarrisonMap(mapId, i_gridCleanUpDelay, instanceId, owner->GetGUID());
ASSERT(map->IsGarrison());
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)
{
// 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;
player->TeleportToBGEntryPoint();
return nullptr;
}
}
}
else if (entry->IsDungeon())
{
InstancePlayerBind* pBind = player->GetBoundInstance(mapId, player->GetDifficultyID(entry));
InstanceSave* pSave = pBind ? pBind->save : nullptr;
InstanceTemplate const* corpseInstance = sObjectMgr->GetInstanceTemplate(corpseMap);
corpseMap = corpseInstance ? corpseInstance->Parent : 0;
} while (corpseMap);
// 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;
}
if (!corpseMap)
return Map::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);
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
TC_LOG_DEBUG("maps", "Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName().c_str());
}
{
Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficultyID(entry) : player->GetDifficultyID(entry);
//Get instance where player's group is bound & its map
if (!loginCheck && group)
// 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 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()
+48 -56
View File
@@ -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>
#include <map>
#include <shared_mutex>
class PhaseShift;
class Transport;
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
+19 -8
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());
@@ -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);
+3
View File
@@ -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;
+1 -1
View File
@@ -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"
@@ -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)
@@ -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;
@@ -18,7 +18,6 @@
#include "WaypointManager.h"
#include "DatabaseEnv.h"
#include "GridDefines.h"
#include "MapManager.h"
#include "Log.h"
void WaypointMgr::Load()
@@ -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"
+1 -13
View File
@@ -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));
@@ -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"
@@ -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"
+17 -7
View File
@@ -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);
}
else if (Player* player = handler->GetPlayer())
{
// Fallback to player's map if no map has been specified
map = player->GetMap();
sMapMgr->DoForAllMapsWithMapId(*mapId, [&](Map* map)
{
HandleDebugLoadCellsCommandHelper(handler, map, tileX, tileY);
});
return true;
}
if (Player* player = handler->GetPlayer())
{
// Fallback to player's map if no map has been specified
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;
@@ -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"
@@ -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"
+13 -33
View File
@@ -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)
@@ -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"
@@ -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"
@@ -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"