From cfe60008d58663234a10442091e2362440f23ec8 Mon Sep 17 00:00:00 2001 From: agatho Date: Mon, 2 Feb 2026 15:26:03 +0100 Subject: [PATCH] perf(vmap): Cache failed VMAP load attempts to prevent repeated retries Problem: VMAP loading for maps without data (Boost Experience, phased zones, newer dungeons) was retried on EVERY access, causing: - Thousands of file access attempts per session - Log spam with "Could not load VMAP" errors - Server slowdown from repeated disk I/O Solution: Added _vmapLoadFailed bitset to TerrainInfo that caches failed VMAP load attempts, similar to existing _gridFileExists pattern for maps. Changes: - TerrainMgr.h: Added _vmapLoadFailed bitset - TerrainMgr.cpp: Check bitset before load, cache failures, reduce log level Maps affected: 1949, 1950 (8.0 Boost), 1554, 1557 (7.0 Boost), 1465 (Tanaan), 2648, 2649, 2662, 2669 (TWW dungeons), and others without VMAP data. Co-Authored-By: Claude Opus 4.5 Signed-off-by: luis --- src/server/game/Maps/TerrainMgr.cpp | 10 +++++++++- src/server/game/Maps/TerrainMgr.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/server/game/Maps/TerrainMgr.cpp b/src/server/game/Maps/TerrainMgr.cpp index b0afc102f..9f6e428e1 100644 --- a/src/server/game/Maps/TerrainMgr.cpp +++ b/src/server/game/Maps/TerrainMgr.cpp @@ -222,6 +222,12 @@ void TerrainInfo::LoadVMap(int32 gx, int32 gy) if (!VMAP::VMapFactory::createOrGetVMapManager()->isMapLoadingEnabled()) return; + // PLAYERBOT FIX: Skip loading if we already know this tile failed + // Prevents repeated file access attempts and log spam for maps without VMAP data + // (e.g., Boost Experience maps, phased zones, newer dungeons) + if (_vmapLoadFailed[GetBitsetIndex(gx, gy)]) + return; + switch (VMAP::VMapFactory::createOrGetVMapManager()->loadMap(sWorld->GetDataPath() + "vmaps", GetId(), gx, gy)) { case VMAP::LoadResult::Success: @@ -229,7 +235,9 @@ void TerrainInfo::LoadVMap(int32 gx, int32 gy) break; case VMAP::LoadResult::VersionMismatch: case VMAP::LoadResult::ReadFromFileFailed: - TC_LOG_ERROR("maps", "Could not load VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy); + // PLAYERBOT FIX: Cache the failure to prevent repeated load attempts + _vmapLoadFailed[GetBitsetIndex(gx, gy)] = true; + TC_LOG_DEBUG("maps", "VMAP not available name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{}) - will not retry", GetMapName(), GetId(), gx, gy, gx, gy); break; case VMAP::LoadResult::DisabledInConfig: TC_LOG_DEBUG("maps", "Ignored VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy); diff --git a/src/server/game/Maps/TerrainMgr.h b/src/server/game/Maps/TerrainMgr.h index f0e35556f..08535ebe9 100644 --- a/src/server/game/Maps/TerrainMgr.h +++ b/src/server/game/Maps/TerrainMgr.h @@ -115,6 +115,7 @@ private: std::atomic _referenceCountFromMap[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; std::array _loadedGrids; std::bitset _gridFileExists; // cache what grids are available for this map (not including parent/child maps) + std::bitset _vmapLoadFailed; // PLAYERBOT FIX: cache failed VMAP loads to prevent repeated attempts static constexpr Milliseconds CleanupInterval = 1min;