From e7462efaf62a362bd219c7cc7185f8a20b1c1f20 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 10:03:08 -0700 Subject: [PATCH] fix(wot): cap doodad/WMO placement count at 100k on load Same defense pattern as the editor JSON loaders. Real ADTs cap at ~64k MDDF entries and ~5k in practice; 100k matches the editor ObjectPlacer cap so an extreme WOT can't bloat the in-memory terrain past what the editor itself would accept. --- src/pipeline/wowee_terrain_loader.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pipeline/wowee_terrain_loader.cpp b/src/pipeline/wowee_terrain_loader.cpp index c0b5de3a..3a85e1a4 100644 --- a/src/pipeline/wowee_terrain_loader.cpp +++ b/src/pipeline/wowee_terrain_loader.cpp @@ -172,8 +172,13 @@ bool WoweeTerrainLoader::loadMetadata(const std::string& wotPath, ADTTerrain& te if (!std::isfinite(b)) b = 0.0f; if (!std::isfinite(c)) c = 0.0f; }; + // Caps match the editor-side ObjectPlacer (100k for objects). Per- + // tile, real ADTs cap at ~64k MDDF entries (uint32 indices) and + // far fewer in practice (~5k for dense zones). + constexpr size_t kMaxPlacements = 100'000; if (j.contains("doodads") && j["doodads"].is_array()) { for (const auto& jd : j["doodads"]) { + if (terrain.doodadPlacements.size() >= kMaxPlacements) break; ADTTerrain::DoodadPlacement dp{}; dp.nameId = jd.value("nameId", 0u); dp.uniqueId = jd.value("uniqueId", 0u); @@ -198,6 +203,7 @@ bool WoweeTerrainLoader::loadMetadata(const std::string& wotPath, ADTTerrain& te } if (j.contains("wmos") && j["wmos"].is_array()) { for (const auto& jw : j["wmos"]) { + if (terrain.wmoPlacements.size() >= kMaxPlacements) break; ADTTerrain::WMOPlacement wp{}; wp.nameId = jw.value("nameId", 0u); wp.uniqueId = jw.value("uniqueId", 0u);