# Реестр проблем: болячки GMod/Source и что с ними делаем Формат: **симптом → почему так у Source/GMod → решение → этап**. --- ## P1. Нет анимаций игроков (пробел Source.NET) - **Симптом:** модели видны, но статичны (замечено в Source.NET на ClassicBox). - **Почему:** нет реализованного studio-анимационного стека. - **Решение:** полный StudioRender (**M5**): VVD/VTX/ANIM, blend-граф, `$sequence`, activity layers/gestures, IK, procedural bones (`$bonefollowers`), flex/eyeballs, аттачменты, GPU-скиннинг, animation LOD. - **Этап:** M5. ## P2. Сандбокс-масштаб: кучи пропов, энтити, констрейнов ⭐ - **Симптом:** 2000+ пропов, кучи констрейнов и аддоновых сущностей превращают клиент в слайдшоу; открытые карты (gm_mobenix и подобные) — худший случай. - **Почему Source «не задумывался»:** - draw call на каждый проп — без инстансинга/батчинга; - PVS — единственный механизм видимости; нет LOD от экранного размера; - нет animation LOD: все скелеты обновляются, пока модель в кадре; - клиентская физика тикает независимо от близости игрока; - один поток на запись рендера; - констрейны = шторм сетевых сущностей + аллокации + ребилд ропов. - **Принцип сандбокс-масштаба (подтверждён пользователем):** > Мелкое и далёкое можно вообще не рисовать. Дефолты агрессивные, > всё регулируется конварами. - **Решение — Interest & Visibility subsystem:** 1. Состояния: `Static → Sleeping → Dynamic → Impostor → Skipped` (обратимо). 2. Screen-space importance: `pixels ≈ r / dist · (h / 2·tan(fov/2))`. Пороги (черновые): skip < 1–2 px, impostor < 8 px, low-LOD < 24 px. 3. Инстансинг одинаковых моделей (indirect draw); merge спящих физикой пропов в статические батчи (пробуждение возвращает в dynamic). 4. Animation LOD: 60/20/0 Гц + фриз костей; критерии: дистанция, в кадре ли, движение, свежесть сетевых апдейтов, взаимодействие. 5. Physics hibernation: island sleep + принудительная заморозка дальних островов; пробуждение по сети/подходу/взаимодействию; Jolt на worker-пулах. 6. Авто-импосторы с дисковым кэшем для дальних мелких пропов. 7. Сеть под шторм: интернирование, пул сущностей без аллокаций, параллельный дельта-декод. 8. **Совместимость:** куллинг не трогает существование сущностей и Lua-draw (PAC3/Starfall/HUD получают всё; у их рисования свои бюджеты). - **Черновые конвары:** `r_imp_minscreen`, `r_imp_impostor_screen`, `r_imp_lod_screen`, `r_animlod_hz`/`r_animlod_dist`, `phys_hibernate_dist`/`phys_hibernate_delay`, `r_nopvs_maxdist` (для карт без PVS). - **Этапы:** M3 (каркас) → M4 (стресс-полигон) → M5 (anim LOD, статик-батчи) → M6 (hibernation) → M9 (импосторы-кэш, тюнинг). - **Вне нашей власти (клиент):** серверный CPU от констрейнов и серверного Lua, серверный сетевой бюджет. У нас «констрейны» — это сеть/декод/визуал. ## P3. Долгий заход в игру и на сервер - **Симптом:** GMod грузит аддоны и контент минутами; вход на сервер — минуты (UDP-скачивание Lua/карты даже при наличии контента локально). - **Решение:** - параллельная LZMA-декомпрессия и запись в постоянный download-кэш; - приоритет локального контента: workshop/аддоны, что уже есть, не качаем; - стриминг-парсинг BSP по мере прихода; - фоновый precache ассетов во время коннекта (загрузочный экран без чёрного экрана); - быстрый старт меню: ленивое монтирование и фоновый warmup в игре. - **Этап:** M2/M4/M9. ## P4. Шейдерные стуттеры и подгрузки на ходу - **Почему:** компиляция шейдеров в рантайме; синхронный декод текстур/моделей; отсутствие streaming. - **Решение:** wgpu pipeline cache + прогрев; асинхронный декод в worker-пулах; VRAM-бюджет и деградация; дисковый кэш обработанных ассетов; mip-стриминг. - **Этап:** M3/M9. ## P5. 32-битность, OOM и лимиты - **Почему:** исторически 32-битный клиент (есть 64-битная бета). - **Решение:** сразу x86_64; собственные лимиты по бюджету RAM/VRAM с деградацией (скип/импостор/уменьшение качества), а не падение. - **Этап:** архитектурно с M0. ## P6. Однопоточный рендер - **Решение:** параллельная запись команд, worker-пулы (куллинг/декод/скиннинг), многопоточная физика Jolt. - **Этап:** M3/M6. ## P7. PVS-only и дырявые открытые карты - **Симптом:** карты с плохим/отсутствующим PVS рендерят всё. - **Решение:** PVS + frustum + octree + screen-size пороги; fallback по дистанции для плохих PVS (`r_nopvs_maxdist`). - **Этап:** M3. ## P8. Краши от злоумышленников (Starfall/PAC3) и кривых данных - **Векторы:** бесконечные/вложенные циклы Lua, OOM Lua, гигантские RT/меши/материалы, path traversal при загрузке файлов, битые снапшоты, огромные строки. - **Решение:** - Lua-sandbox: лимит памяти, instruction-watchdog, запрет `io/os/ffi/debug`, изоляция ошибок, лимиты на таймеры/RT/меши; - защита путей как требования gluasteal (никаких `..`, абсолютных путей, NaN); - bounded-парсеры + fuzz; никаких `unwrap` на внешних данных; - `catch_unwind` на границах; краш одного аддона не убивает клиент; - **safe mode**: пометка «загружался файл X» → при нечистом завершении X добавляется в чёрный список следующего запуска. - **Этап:** cross-cutting; ядро — M7; PAC3/Starfall — M8. ## P9. Качество картинки (HDR/AA/вода/тени) - **Решение:** HDR-конвейер (RGBA16F, tonemap, bloom), SMAA (TAA опцией), SSAO, анизотропия 16x, SSR воды, динамические тени моделей/игроков (опция), корректные color-space и alpha. - **Контракт:** семантика материалов Source (`$additive`, RT, lightwarps, alpha) не меняется — иначе аддоны визуально ломаются. - **Этап:** M3; тюнинг дефолтов — M9. ## P10. VGUI тяжёлый и медленный - **Решение:** нативный UI-слой (меню/консоль/HUD-рамка) на Rust; Derma — совместимый слой поверх быстрого бэкенда; шрифты TTF вместо медленного VGUI-пути. - **Этап:** M7/M8. ## P11. UX-мелочи - Быстрый старт без чёрного экрана; информативный загрузочный экран; реконнект без перезапуска; стабильные alt-tab и курсор; громкость/аудио-устройства; консольные команды как в Source. - **Этап:** по мере появления соответствующих систем.