From bfd31d59c20f6130f1914ceb8b9b1f2d1e797bcd Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 8 Aug 2023 00:21:48 +0200 Subject: [PATCH] Core/MMaps: Fixed pathing for objects that have terrain swaps active --- .../Collision/Management/MMapManager.cpp | 41 ++++++++++--------- src/common/Collision/Management/MMapManager.h | 9 ++-- src/server/game/Maps/Map.cpp | 6 +-- src/server/game/Maps/TerrainMgr.cpp | 26 ++++++++++++ src/server/game/Maps/TerrainMgr.h | 4 ++ src/server/game/Movement/PathGenerator.cpp | 4 +- src/server/scripts/Commands/cs_mmaps.cpp | 4 +- 7 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/common/Collision/Management/MMapManager.cpp b/src/common/Collision/Management/MMapManager.cpp index 676b169255..f0367c01b7 100644 --- a/src/common/Collision/Management/MMapManager.cpp +++ b/src/common/Collision/Management/MMapManager.cpp @@ -211,13 +211,14 @@ namespace MMAP } } - bool MMapManager::loadMapInstance(std::string const& basePath, uint32 mapId, uint32 instanceId) + bool MMapManager::loadMapInstance(std::string const& basePath, uint32 meshMapId, uint32 instanceMapId, uint32 instanceId) { - if (!loadMapData(basePath, mapId)) + if (!loadMapData(basePath, meshMapId)) return false; - MMapData* mmap = loadedMMaps[mapId]; - if (mmap->navMeshQueries.find(instanceId) != mmap->navMeshQueries.end()) + MMapData* mmap = loadedMMaps[meshMapId]; + auto [queryItr, inserted] = mmap->navMeshQueries.try_emplace({ instanceMapId, instanceId }, nullptr); + if (!inserted) return true; // allocate mesh query @@ -226,12 +227,13 @@ namespace MMAP if (dtStatusFailed(query->init(mmap->navMesh, 1024))) { dtFreeNavMeshQuery(query); - TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + mmap->navMeshQueries.erase(queryItr); + TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", instanceMapId, instanceId); return false; } - TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); - mmap->navMeshQueries.insert(std::pair(instanceId, query)); + TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", instanceMapId, instanceId); + queryItr->second = query; return true; } @@ -310,29 +312,28 @@ namespace MMAP return true; } - bool MMapManager::unloadMapInstance(uint32 mapId, uint32 instanceId) + bool MMapManager::unloadMapInstance(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId) { // check if we have this map loaded - MMapDataSet::const_iterator itr = GetMMapData(mapId); + MMapDataSet::const_iterator itr = GetMMapData(meshMapId); if (itr == loadedMMaps.end()) { // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId); + TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", meshMapId); return false; } MMapData* mmap = itr->second; - if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) + auto queryItr = mmap->navMeshQueries.find({ instanceMapId, instanceId }); + if (queryItr == mmap->navMeshQueries.end()) { - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId); + TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", instanceMapId, instanceId); return false; } - dtNavMeshQuery* query = mmap->navMeshQueries[instanceId]; - - dtFreeNavMeshQuery(query); - mmap->navMeshQueries.erase(instanceId); - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId); + dtFreeNavMeshQuery(queryItr->second); + mmap->navMeshQueries.erase(queryItr); + TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", instanceMapId, instanceId); return true; } @@ -346,13 +347,13 @@ namespace MMAP return itr->second->navMesh; } - dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId) + dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId) { - auto itr = GetMMapData(mapId); + auto itr = GetMMapData(meshMapId); if (itr == loadedMMaps.end()) return nullptr; - auto queryItr = itr->second->navMeshQueries.find(instanceId); + auto queryItr = itr->second->navMeshQueries.find({ instanceMapId, instanceId }); if (queryItr == itr->second->navMeshQueries.end()) return nullptr; diff --git a/src/common/Collision/Management/MMapManager.h b/src/common/Collision/Management/MMapManager.h index 2f11f704d1..e8f533b49e 100644 --- a/src/common/Collision/Management/MMapManager.h +++ b/src/common/Collision/Management/MMapManager.h @@ -21,6 +21,7 @@ #include "Define.h" #include "DetourNavMesh.h" #include "DetourNavMeshQuery.h" +#include "Hash.h" #include #include #include @@ -29,7 +30,7 @@ namespace MMAP { typedef std::unordered_map MMapTileSet; - typedef std::unordered_map NavMeshQuerySet; + typedef std::unordered_map, dtNavMeshQuery*> NavMeshQuerySet; // dummy struct to hold map's mmap data struct TC_COMMON_API MMapData @@ -65,13 +66,13 @@ namespace MMAP void InitializeThreadUnsafe(std::unordered_map> const& mapData); bool loadMap(std::string const& basePath, uint32 mapId, int32 x, int32 y); - bool loadMapInstance(std::string const& basePath, uint32 mapId, uint32 instanceId); + bool loadMapInstance(std::string const& basePath, uint32 meshMapId, uint32 instanceMapId, uint32 instanceId); bool unloadMap(uint32 mapId, int32 x, int32 y); bool unloadMap(uint32 mapId); - bool unloadMapInstance(uint32 mapId, uint32 instanceId); + bool unloadMapInstance(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId); // the returned [dtNavMeshQuery const*] is NOT threadsafe - dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId); + dtNavMeshQuery const* GetNavMeshQuery(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId); dtNavMesh const* GetNavMesh(uint32 mapId); uint32 getLoadedTilesCount() const { return loadedTiles; } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index cb62189b01..5e954f43b1 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -21,7 +21,6 @@ #include "CellImpl.h" #include "DatabaseEnv.h" #include "DBCStores.h" -#include "DisableMgr.h" #include "DynamicTree.h" #include "GameObjectModel.h" #include "GameTime.h" @@ -34,7 +33,6 @@ #include "InstanceSaveMgr.h" #include "Log.h" #include "MapManager.h" -#include "MMapFactory.h" #include "MiscPackets.h" #include "MotionMaster.h" #include "ObjectAccessor.h" @@ -95,7 +93,7 @@ Map::~Map() sOutdoorPvPMgr->DestroyOutdoorPvPForMap(this); sBattlefieldMgr->DestroyBattlefieldsForMap(this); - MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId); + m_terrain->UnloadMMapInstance(GetId(), GetInstanceId()); } void Map::LoadAllCells() @@ -150,7 +148,7 @@ i_scriptLock(false), _respawnCheckTimer(0) sTransportMgr->CreateTransportsForMap(this); - MMAP::MMapFactory::createOrGetMMapManager()->loadMapInstance(sWorld->GetDataPath(), GetId(), i_InstanceId); + m_terrain->LoadMMapInstance(GetId(), GetInstanceId()); _worldStateValues = sWorldStateMgr->GetInitialWorldStatesForMap(this); diff --git a/src/server/game/Maps/TerrainMgr.cpp b/src/server/game/Maps/TerrainMgr.cpp index 461ffc566b..e7e12d761f 100644 --- a/src/server/game/Maps/TerrainMgr.cpp +++ b/src/server/game/Maps/TerrainMgr.cpp @@ -163,6 +163,14 @@ void TerrainInfo::LoadMapAndVMap(int32 gx, int32 gy) LoadMapAndVMapImpl(gx, gy); } +void TerrainInfo::LoadMMapInstance(uint32 mapId, uint32 instanceId) +{ + LoadMMapInstanceImpl(mapId, instanceId); + + for (std::shared_ptr const& childTerrain : _childTerrain) + childTerrain->LoadMMapInstanceImpl(mapId, instanceId); +} + void TerrainInfo::LoadMapAndVMapImpl(int32 gx, int32 gy) { LoadMap(gx, gy); @@ -175,6 +183,11 @@ void TerrainInfo::LoadMapAndVMapImpl(int32 gx, int32 gy) _loadedGrids[GetBitsetIndex(gx, gy)] = true; } +void TerrainInfo::LoadMMapInstanceImpl(uint32 mapId, uint32 instanceId) +{ + MMAP::MMapFactory::createOrGetMMapManager()->loadMapInstance(sWorld->GetDataPath(), _mapId, mapId, instanceId); +} + void TerrainInfo::LoadMap(int32 gx, int32 gy) { if (_gridMap[gx][gy]) @@ -240,6 +253,14 @@ void TerrainInfo::UnloadMap(int32 gx, int32 gy) // unload later } +void TerrainInfo::UnloadMMapInstance(uint32 mapId, uint32 instanceId) +{ + UnloadMMapInstanceImpl(mapId, instanceId); + + for (std::shared_ptr const& childTerrain : _childTerrain) + childTerrain->UnloadMMapInstanceImpl(mapId, instanceId); +} + void TerrainInfo::UnloadMapImpl(int32 gx, int32 gy) { _gridMap[gx][gy] = nullptr; @@ -252,6 +273,11 @@ void TerrainInfo::UnloadMapImpl(int32 gx, int32 gy) _loadedGrids[GetBitsetIndex(gx, gy)] = false; } +void TerrainInfo::UnloadMMapInstanceImpl(uint32 mapId, uint32 instanceId) +{ + MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(_mapId, mapId, instanceId); +} + GridMap* TerrainInfo::GetGrid(uint32 mapId, float x, float y, bool loadIfMissing /*= true*/) { // half opt method diff --git a/src/server/game/Maps/TerrainMgr.h b/src/server/game/Maps/TerrainMgr.h index 0e99e2204f..2114e02db1 100644 --- a/src/server/game/Maps/TerrainMgr.h +++ b/src/server/game/Maps/TerrainMgr.h @@ -57,18 +57,22 @@ public: void AddChildTerrain(std::shared_ptr childTerrain); void LoadMapAndVMap(int32 gx, int32 gy); + void LoadMMapInstance(uint32 mapId, uint32 instanceId); private: void LoadMapAndVMapImpl(int32 gx, int32 gy); + void LoadMMapInstanceImpl(uint32 mapId, uint32 instanceId); void LoadMap(int32 gx, int32 gy); void LoadVMap(int32 gx, int32 gy); void LoadMMap(int32 gx, int32 gy); public: void UnloadMap(int32 gx, int32 gy); + void UnloadMMapInstance(uint32 mapId, uint32 instanceId); private: void UnloadMapImpl(int32 gx, int32 gy); + void UnloadMMapInstanceImpl(uint32 mapId, uint32 instanceId); GridMap* GetGrid(uint32 mapId, float x, float y, bool loadIfMissing = true); diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 6e0c60e9b9..bb4d5cacd4 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -44,8 +44,8 @@ PathGenerator::PathGenerator(WorldObject const* owner) : if (DisableMgr::IsPathfindingEnabled(mapId)) { MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); - _navMesh = mmap->GetNavMesh(mapId); - _navMeshQuery = mmap->GetNavMeshQuery(mapId, _source->GetInstanceId()); + _navMeshQuery = mmap->GetNavMeshQuery(mapId, _source->GetMapId(), _source->GetInstanceId()); + _navMesh = _navMeshQuery ? _navMeshQuery->getAttachedNavMesh() : mmap->GetNavMesh(mapId); } CreateFilter(); diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 311830b429..175d1f362d 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -141,7 +141,7 @@ public: // calculate navmesh tile location uint32 terrainMapId = PhasingHandler::GetTerrainMapId(player->GetPhaseShift(), player->GetMapId(), player->GetMap()->GetTerrain(), x, y); dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(terrainMapId); - dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(terrainMapId, player->GetInstanceId()); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(terrainMapId, player->GetMapId(), player->GetInstanceId()); if (!navmesh || !navmeshquery) { handler->PSendSysMessage("NavMesh not loaded for current map."); @@ -192,7 +192,7 @@ public: Player* player = handler->GetSession()->GetPlayer(); uint32 terrainMapId = PhasingHandler::GetTerrainMapId(player->GetPhaseShift(), player->GetMapId(), player->GetMap()->GetTerrain(), player->GetPositionX(), player->GetPositionY()); dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(terrainMapId); - dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(terrainMapId, player->GetInstanceId()); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(terrainMapId, player->GetMapId(), player->GetInstanceId()); if (!navmesh || !navmeshquery) { handler->PSendSysMessage("NavMesh not loaded for current map.");