diff options
| author | Shauren <shauren.trinity@gmail.com> | 2025-12-20 15:56:32 +0100 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2025-12-20 15:56:32 +0100 |
| commit | 3919b82a63c873b8632ef63d3af4b9d95eb8f87d (patch) | |
| tree | caa6b89ae5d86be03bee127b33fef9e8c626164a /src/common | |
| parent | 503cecb75b2fa6e4ead31ff5d64a242adef2ca03 (diff) | |
Core/MMaps: Fix crash during mmap unload happening on maps not marked for dynamic rebuilding
Closes #31585
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/mmaps_common/Management/MMapManager.cpp | 86 |
1 files changed, 36 insertions, 50 deletions
diff --git a/src/common/mmaps_common/Management/MMapManager.cpp b/src/common/mmaps_common/Management/MMapManager.cpp index a45c1ee5fbb..32d77959d6e 100644 --- a/src/common/mmaps_common/Management/MMapManager.cpp +++ b/src/common/mmaps_common/Management/MMapManager.cpp @@ -29,8 +29,6 @@ namespace MMAP constexpr char MAP_FILE_NAME_FORMAT[] = "{}mmaps/{:04}.mmap"; constexpr char TILE_FILE_NAME_FORMAT[] = "{}mmaps/{:04}_{:02}_{:02}.mmtile"; - static thread_local bool thread_safe_environment = false; - using NavMeshQuerySet = std::unordered_map<std::pair<uint32, uint32>, dtNavMeshQuery>; using MMapTileSet = std::unordered_map<uint32, dtTileRef>; @@ -71,15 +69,18 @@ namespace MMAP std::pair<MeshDataMap::iterator, bool> GetMeshData(uint32 mapId, uint32 instanceId) { - // for maps that won't have dynamic mesh, return 0 to reuse the same mesh across all instances return meshData.try_emplace(GetInstanceIdForMeshLookup(mapId, instanceId)); } MeshDataMap::iterator FindMeshData(uint32 mapId, uint32 instanceId) { - // for maps that won't have dynamic mesh, return 0 to reuse the same mesh across all instances return meshData.find(GetInstanceIdForMeshLookup(mapId, instanceId)); } + + MeshDataMap::node_type RemoveMeshData(uint32 mapId, uint32 instanceId) + { + return meshData.extract(GetInstanceIdForMeshLookup(mapId, instanceId)); + } }; // ######################## MMapManager ######################## @@ -97,13 +98,10 @@ namespace MMAP // the caller must pass the list of all mapIds that will be used in the MMapManager lifetime for (auto const& [mapId, childMapIds] : mapData) { - loadedMMaps[mapId].reset(new MMapData()); + loadedMMaps.try_emplace(mapId, new MMapData()); for (uint32 childMapId : childMapIds) parentMapData[childMapId] = mapId; } - - // mark the loading main thread as safe - thread_safe_environment = true; } MMapDataSet::const_iterator MMapManager::GetMMapData(uint32 mapId) const @@ -124,20 +122,8 @@ namespace MMAP LoadResult MMapManager::loadMapData(std::string_view basePath, uint32 mapId, uint32 instanceId) { // we already have this map loaded? - MMapDataSet::iterator itr; - if (thread_safe_environment) - { - bool needsLoading; - std::tie(itr, needsLoading) = loadedMMaps.try_emplace(mapId); - if (needsLoading) - itr->second.reset(new MMapData()); - } - else - { - itr = loadedMMaps.find(mapId); - if (itr == loadedMMaps.end()) - ABORT_MSG("Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId); - } + MMapDataSet::iterator itr = loadedMMaps.find(mapId); + ASSERT(itr != loadedMMaps.end(), "Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId); auto [meshItr, needsLoading] = itr->second->GetMeshData(mapId, instanceId); if (!needsLoading) @@ -230,7 +216,7 @@ namespace MMAP } // get this mmap data - MMapData* mmap = loadedMMaps[mapId].get(); + MMapData* mmap = Trinity::Containers::MapGetValuePtr(loadedMMaps, mapId); MMapMapData& meshData = mmap->GetMeshData(mapId, instanceId).first->second; // check if we already have this tile loaded @@ -327,7 +313,7 @@ namespace MMAP return false; } - MMapData* mmap = loadedMMaps[meshMapId].get(); + MMapData* mmap = Trinity::Containers::MapGetValuePtr(loadedMMaps, meshMapId); auto [queryItr, inserted] = mmap->navMeshQueries.try_emplace({ instanceMapId, instanceId }); if (!inserted) return true; @@ -340,7 +326,6 @@ namespace MMAP // allocate mesh query if (dtStatusFailed(queryItr->second.init(&mmap->GetMeshData(meshMapId, instanceId).first->second.navMesh, 1024))) { - mmap->navMeshQueries.erase(queryItr); TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId {:04} instanceId {}", instanceMapId, instanceId); return false; } @@ -397,20 +382,21 @@ namespace MMAP return; } - if (MMapData::GetInstanceIdForMeshLookup(mapId, std::numeric_limits<uint32>::max()) == 0) + if (!isRebuildingTilesEnabledOnMap(mapId)) { - // unload all tiles from given map - MMapMapData& mesh = itr->second->meshData[0]; - for (auto const& [tileId, tileRef] : mesh.loadedTileRefs) + if (MeshDataMap::node_type meshNode = itr->second->RemoveMeshData(mapId, 0)) { - uint32 x = (tileId >> 16); - uint32 y = (tileId & 0x0000FFFF); - if (dtStatusFailed(mesh.navMesh.removeTile(tileRef, nullptr, nullptr))) - TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", mapId, x, y); - else + for (auto const& [tileId, tileRef] : meshNode.mapped().loadedTileRefs) { - --loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", mapId, x, y, mapId); + uint32 x = (tileId >> 16); + uint32 y = (tileId & 0x0000FFFF); + if (dtStatusFailed(meshNode.mapped().navMesh.removeTile(tileRef, nullptr, nullptr))) + TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", mapId, x, y); + else + { + --loadedTiles; + TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", mapId, x, y, mapId); + } } } } @@ -436,24 +422,24 @@ namespace MMAP if (!erased) TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId {:04} instanceId {}", instanceMapId, instanceId); - MeshDataMap::iterator meshItr = mmap->FindMeshData(meshMapId, instanceId); - if (meshItr != mmap->meshData.end()) + if (isRebuildingTilesEnabledOnMap(meshMapId)) { - // unload all tiles from given map - for (auto const& [tileId, tileRef] : meshItr->second.loadedTileRefs) + if (MeshDataMap::node_type meshNode = mmap->RemoveMeshData(meshMapId, instanceId)) { - uint32 x = (tileId >> 16); - uint32 y = (tileId & 0x0000FFFF); - if (dtStatusFailed(meshItr->second.navMesh.removeTile(tileRef, nullptr, nullptr))) - TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", meshMapId, x, y); - else + // unload all tiles from given map + for (auto const& [tileId, tileRef] : meshNode.mapped().loadedTileRefs) { - --loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", meshMapId, x, y, meshMapId); + uint32 x = (tileId >> 16); + uint32 y = (tileId & 0x0000FFFF); + if (dtStatusFailed(meshNode.mapped().navMesh.removeTile(tileRef, nullptr, nullptr))) + TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", meshMapId, x, y); + else + { + --loadedTiles; + TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", meshMapId, x, y, meshMapId); + } } } - - mmap->meshData.erase(meshItr); } TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId {:04} instanceId {}", instanceMapId, instanceId); @@ -474,7 +460,7 @@ namespace MMAP dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId) { - auto itr = GetMMapData(meshMapId); + MMapDataSet::const_iterator itr = GetMMapData(meshMapId); if (itr == loadedMMaps.end()) return nullptr; |
