diff --git a/tools/editor/object_placer.cpp b/tools/editor/object_placer.cpp index 9f59c938..f3dfb49d 100644 --- a/tools/editor/object_placer.cpp +++ b/tools/editor/object_placer.cpp @@ -337,7 +337,17 @@ bool ObjectPlacer::loadFromFile(const std::string& path) { selectedIndices_.clear(); uniqueIdCounter_ = 1; + // Cap object count — a stale autosave or biome-populate runaway + // could produce 100k+ entries that bloat the renderer instance + // SSBO and drag the editor framerate to single digits. + constexpr size_t kMaxObjects = 100'000; + for (const auto& jo : arr) { + if (objects_.size() >= kMaxObjects) { + LOG_WARNING("Object cap reached (", kMaxObjects, + ") — remaining entries dropped"); + break; + } PlacedObject obj; obj.type = static_cast(jo.value("type", 0)); obj.path = jo.value("path", ""); diff --git a/tools/editor/quest_editor.cpp b/tools/editor/quest_editor.cpp index 1558ed87..59d5ae8f 100644 --- a/tools/editor/quest_editor.cpp +++ b/tools/editor/quest_editor.cpp @@ -77,7 +77,18 @@ bool QuestEditor::loadFromFile(const std::string& path) { quests_.clear(); uint32_t maxId = 0; + // Cap total quest count — a stale autosave or hand-edited file + // could carry thousands of empty quests, each emitting a + // quest_template INSERT (and queststarter/questender + chain + // walks) on export. 4096 covers any realistic zone. + constexpr size_t kMaxQuests = 4096; + for (const auto& jq : arr) { + if (quests_.size() >= kMaxQuests) { + LOG_WARNING("Quest cap reached (", kMaxQuests, + ") — remaining entries dropped"); + break; + } Quest q; q.id = jq.value("id", 0u); q.title = jq.value("title", "Untitled");