mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-20 01:15:35 +01:00
Core/Maps: Removed MapInstanced - no longer neccessary for grid data reference counting (moved to TerrainInfo)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user