gmod-rs/docs/PLAN.md
Niko Marmeladkov 44b0ece2ab render: вода (SURF_WARP), area-скайбокс с правильным порядком глубины, лайтмапы диспов по UV
- Вода: детект Water-шейдера (/), отдельный полупрозрачный
  проход с френелем; поверхность/изнанка по нормали. Белая дыра на месте воды
  (2D-скайбокс «вниз») устранена.
- 3D-скайбокс: выбор граней по area листа sky_camera (движок: area bits), а не по
  AABB. Disp-грани не попадают в leaf_faces — выбор по листу центра грани; теперь
  в скайбоксе есть большая плоскость flatgrass_2 (пропадала — торчала «стена»
  бетонного пола). Защита >30% граней = скайбокс не выделяем (gm_flatgrass).
- Порядок: 2D-скайбокс фоном -> 3D-меш (depth Always, без записи) -> мир ->
  вода. Скайбокс больше не проступает сквозь дальние стены карты.
- Лайтмапы: блок грани (size+1)^2 с индексом v*width+u; для displacement'ов —
  плотная сетка по UV поверхности (CalcDispSurfCoords), а не проекция мира:
  убрана «шахматка» теней на рельефе. Скайбокс-меш тоже сэмплит лайтмапы.
- Тесты: gm_flatgrass-диспы живут в скайбоксе (z≈-16000), пороги обновлены.
- docs/RECON.md §12: форматы листьев/граней, лайтмапы, скайбокс, вода.
2026-10-12 08:28:28 +03:00

26 KiB
Raw Blame History

Source RS — план проекта

Статус: план зафиксирован (2026-10-11). Следующий шаг — спринт 0 (§7). Каталог: ~/garrysmod-rs · Цель №1: ClassicBox (194.147.90.27:24215).


1. Видение

Source RS — клиент Garry's Mod, написанный с нуля на Rust. Цель — комфортно и красиво играть на сандбокс-серверах с десятками игроков, тысячами сущностей (пропы, констрейны, эффекты) и кучей аддонов, оставаясь совместимым с реальными серверами эпохи Source 2013 (net protocol 24 + GMod-расширения).

Сверх-цели (из постановки задачи пользователя):

  1. Сандбокс-масштаб: оптимизация под много игроков / пропов / констрейнов.
  2. Современные технологии: wgpu/Vulkan, Jolt, SDL3, LuaJIT (через mlua), steamworks.
  3. Современный рендеринг (HDR, AA, SSAO, SSR, тени) — при строгой совместимости семантики материалов, иначе аддоны (PAC3/Starfall) визуально ломаются.
  4. Починка болячек GMod-клиента — см. PROBLEMS.md.
  5. Быстрые заходы: в игру и на сервер.
  6. Устойчивость к крашам от зловредных/кривых аддонов и серверов (Starfall, PAC3...).
  7. Полноценные анимации моделей игроков — главный видимый пробел Source.NET.

2. Рамки

В рамках первой фазы

  • Клиент, подключающийся к реальным GMod-серверам (Source 2013 protocol 24 + GMod-расширения).
  • Рендер GMod-контента: BSP, модели, материалы, партиклы, декали, звук.
  • Полный анимационный стек студийных моделей (скелеты, IK, procedural bones, flex, blends).
  • Клиентский Lua (LuaJIT) с движковым API в объёме, достаточном для аддонов (порядок и объём — см. LUA.md).
  • Steam: тикет для серверов с VAC, workshop-контент, монтирование.
  • Современный рендер по умолчанию + строгий compat-слой семантики материалов.

Вне рамок (первая фаза)

  • Свой dedicated-сервер и серверный Lua (геймоды, ULX, DarkRP...) — отдельная вселенная.
  • Нативные бинарные Lua-модули аддонов (.dll/.so внутри addons) — несовместимы by design.
  • Перераспространение ассетов и Lua-файлов Garry's Mod / Valve.
  • Windows-сборка (код кроссплатформенный, сборка и CI — позже).
  • HTML/Chromium-панели (небольшая часть дюжины аддонов).

3. Принципы

  1. Совместимость — контракт. Форматы, сетевой протокол и Lua-семантика важнее «как удобнее написать код».
  2. Modern-by-default, compat-семантика всегда. Освещение и пост — современные; render-state и семантика материалов ($additive, $translucent, $alphatest, render targets, lightwarps, eyes, skinning) — ровно как в Source.
  3. Принцип сандбокс-масштаба. Мелкое и далёкое можно вообще не рисовать и не анимировать. Дефолты агрессивные, всё регулируется конварами. Детали — PROBLEMS.md §P2.
  4. Never-crash. Никакой ввод из сети/диска и никакой аддон не может уронить клиент: bounded-парсеры, лимиты, catch_unwind на границах, safe mode.
  5. Speed-first. Быстрый заход в игру и на сервер — фича №1: параллельный декод, дисковые кэши, монтирование локального контента, pipeline cache.
  6. Data-oriented hot paths. ECS-подобное хранение сущностей, инстансинг, бюджетные очереди; без аллокаций в кадровом цикле.
  7. Clean-room. SDK 2013 / Source.NET / прочие референсы — спецификация, не код.
  8. Linux-first. wgpu/SDL3/Jolt кроссплатформенные, но отладка и CI — Linux.

4. Критерии успеха

Рубеж Критерий
M4 «Играбельно» Заход на ClassicBox, видим 36+ игроков, ходим, стабильный FPS
M6 «Как надо» Играем: движение, оружие, звук, HUD
M6+ «Сандбокс-масштаб» 64 игрока + 2000 пропов + 500 констрейнов → 60+ FPS на RTX 3060; карта без PVS не убивает кадр
M8 «Аддоны» HUD-аддоны, Derma, PAC3, Starfall работают; их сбои не крашат клиент
Итог Заходы заметно быстрее GMod; картинка современнее; ноль киллов клиента на Chaos-тестах

5. Этапы (обзор)

Этап Название Главный результат
M0 Каркас Workspace, tier-слой, конфиг ассетов, окно+wгpu «пустое»
M1 Форматы и FS VPK/GMA/BSP/VTF/VMT/MDL/PCF/PHY/SND парсятся, fuzz-тесты
M2 Сеть + Steam + dump/replay Подключение к серверу, лог мира, Steam-тикет, workshop, replay-стенд
M3 Рендер мира + interest v1 BSP-мир «как в GMod», современный конвейер, куллинг/инстансинг, pipeline cache
M4 Онлайн: мир и игроки ClassicBox онлайн: 36 игроков, интерполяция, смена карт; стресс-полигон 2000 пропов
M5 StudioRender + анимации Полноценные анимации игроков/рагов, animation LOD, статик-батчи
M6 Геймплей-клиент Prediction, оружие, звук, физика/Jolt, база HUD
M7 Lua: машинерия + HUD/UI LuaJIT-рантайм, sandbox, safe mode, серверные HUD-аддоны
M8 Derma → PAC3 → Starfall Меню, PAC3-модели, Starfall-экраны, стойкость к Chaos
M9 Перф, кэши, полировка Texture streaming, дисковые кэши, импосторы, тюнинг, бенчмарки CI

6. Детализация этапов

M0 — Каркас

  • Cargo workspace; crates/tier: tracing-логи, конвары, CommandLine, конфиг, время, interning строк.
  • Авто-детект корня ассетов: настроенный путь → ~/gmod_server/server (DS) → Steam-инсталлы.
  • .gitignore, CI-скелет (fmt/clippy/test), README/docs, AGENTS.md.
  • steamworks в зависимостях (feature на будущее, выключен по умолчанию до M2).
  • Приёмка: cargo run -p client открывает окно SDL3 + wgpu (clear), в логе — найденные пути ассетов и список конваров.

M1 — Форматы и файловая система

Сделано (2026-10-11/12):

  • KeyValues: толерантный bounded-парсер (VMT/gameinfo/entities), лимиты, тесты
  • BSP: заголовок + 64 лумпа, LZMA-лумпы, ENTITIES (KeyValues), TEXDATA/имена текстур, game lumps, PAKFILE (ZIP: Store/Deflate, CRC)
  • Геометрия BSP v20: вершины/рёбра/surfedges/грани/texinfo/узлы/листья/модели, validate() по перекрёстным ссылкам (gm_construct/gm_flatgrass — валидно)
  • VTF 7.0–7.5: заголовок (+таблица ресурсов 7.3+), раскладка мипов, миниатюра, декод в RGBA8 (DXT1/3/5, RGBA/BGRA/ABGR/ARGB, RGB/BGR, I8/A8/IA88, RGB565/BGR565)
  • VMT: шейдер, параметры, patch (include/replace/insert), Proxies, render-modes
  • MDL: заголовок (v44–49, studiohdr2), кости, аттачменты, хитбоксы, текстуры, бодипарты, include-модели, $keyvalues, surfaceprop (проверено на реальных моделях)
  • VVD/VTX: вершины (позиция/нормаль/UV/веса костей), fixup'ы, полное дерево BodyPart→Model→LOD→Mesh→StripGroup→Strip с валидацией индексов (51 пара на реальных моделях)
  • CLI: fs doctor, fs list, fs cat, fs inspect (BSP/VTF/VMT/MDL + VVD/VTX)
  • Тесты на реальных данных: 2 карты, 200 VTF, 200 VMT, 53 MDL, 51 пара VVD/VTX, pakfile 599 записей
  • MDL: ANIM (анимации) — следующая итерация
  • PCF, PHY (collision), WAV/MP3/OGG
  • crates/fs: GMA (workshop), mount.cfg, aliases |all_source_engine_paths|, mmap, кэш индексов VPK
  • fuzz-таргеты на kv/bsp/vtf/pakfile (пока есть VPK)

Приёмка (частично достигнута): fs doctor/fs inspect работают на реальных ассетах.

M2 — Сеть + Steam + dump/replay

Сделано (v0, 2026-10-12):

  • crates/net: битовые буферы (Source LSB-порядок), A2S (info с challenge), netchan-заголовок (флаги, checksum CRC32→u16, challenge, choked), разбор net/SVC-сообщений (tick, signon, serverinfo, print, setconvar)
  • Хендшейк: getchallenge → S2C.Challenge → connect (с GMod ChecksumXOR) → S2C.Connection; повтор getchallenge раз в секунду как CheckForResend
  • Steam-аутентификация (steamworks-rs): session ticket + steamid в connect; подключение к ClassicBox принято (VAC-сервер, auth_protocol=3)
  • Версия клиента в connect берётся из A2S-версии сервера (иначе #GameUI_ServerRejectNewVersion)
  • CLI: net info <addr>, net connect <addr>
  • Подканалы/фрагменты надёжного потока: NetChan (single/fragments, сжатие, varint, сборка потоков, разбор сообщений); GMod-флаги (Challenge=0x20, subchannel 4 бита) сверены с трафиком ClassicBox
  • Steam-тикет: клиент живёт всю сессию, ждём AuthSessionTicketResponse, свежий тикет при повторных connect (challenge одноразовый)
  • Нерешённое: сервер после S2C.Connection шлёт challenge-пакеты и через ~1.5 с отключает (NET_Disconnect: Client dropped by server); кик не зависит от наших пакетов (подробности и все проверенные гипотезы — в docs/RECON.md §11)
  • Полный signon: stringtables, datatables, baselines, снапшоты
  • Packet dump/replay стенд
  • Workshop через ISteamUGC (подписка/скачивание/монтирование)

Приёмка v0 достигнута: хендшейк и Steam-вход работают на живом ClassicBox (до кика сервером; причина кика исследуется).

M3 — Рендер мира + interest-система (v1)

Сделано (v0/v1, 2026-10-11/12):

  • engine::world: браш-грани, displacement'ы (ориентация по startPosition + порядок обхода, нормали наружу), лайтмапы в вершинах, VMT/VTF-материалы, pakfile карты, скайбокс 2D (skyname)
  • render::WorldRenderer: батчи по материалам, depth, PNG-захват (BGRA-фикс), debug-материалы, --only-material, --dump-textures
  • Камера + ходьба: engine::player — AABB против брашей (BSP v20) и displacement-треугольников (SAT + сетка), гравитация/прыжок/присед/noclip
  • Энтити-модели: engine::model (MDL+VVD+VTX, bind pose), prop_static/ prop_dynamic/prop_physics в общий меш мира
  • 3D-скайбокс: выделение скайбокс-граней по area листа sky_camera (disp-грани в leaf_faces не попадают — выбор по листу центра грани), сжатие 1/scale; 2D-скайбокс рисуется фоном, мир поверх
  • Вода: SURF_WARP + VMT шейдера Water ($abovewater/$fogcolor) — отдельный полупрозрачный проход с френелем (поверхность/изнанка)
  • Лайтмапы: блок грани (size+1)² (индекс v*width+u); для displacement'ов плотная сетка по UV поверхности (CalcDispSurfCoords), а не проекция мира
  • HUD: 2D-текст (bitmap 8x8, render::text), FPS/позиция/режим/лог
  • Меню: menu (выбор карты из VFS, Enter — запуск)
  • Куллинг/инстансинг, атлас лайтмапов, прозрачность (стекло), туман
  • Анимации моделей (парсинг seqdesc/animdesc начат; форматы RLE/raw сверяются)
  • Звук, частицы, декали, оверлеи

M7 — Lua: машинерия + HUD/UI (частично, 2026-10-12)

Сделано (v0):

  • glua: LuaJIT (mlua vendored), print/Msg, hook.Add/Remove/Call, timer.Simple, concommand.Add, CreateConVar/GetConVar, util/engine/game заглушки, FCVAR_*
  • Препроцессор GMod-синтаксиса: ! → not, != → ~=, && → and, || → or (вне строк/комментариев) — оригинальные клиентские скрипты GMod (demo_recording.lua, gm_demo.lua) грузятся
  • Автозагрузка lua/autorun/client/*.lua из VFS, Think-хук и таймеры в кадре, вывод в HUD-лог; lua run <file>, lua list
  • surface/draw/render-таргеты, Derma, Entity/Player API, серверный Lua
  • Загрузка lua с сервера (download-кэш), safe mode

M3 — Рендер мира + interest-система (v1)

Сделано (v0, 2026-10-11/12):

  • crates/engine: сборка мира из BSP (браши, displacement'ы, лайтмапы в вершинах, материалы через VMT (patch/include), общий кэш текстур, пропуск прозрачных материалов)
  • crates/render: wgpu-рендерер мира (один VB/IB, батчи по материалам, глубина), камера-полёт, скриншоты PNG (с учётом BGRA), debug-режимы (материалы, only-material)
  • gmod-rs map <карта>: загрузка с диска/из VPK, монтирование pakfile карты, полёт WASD+мышь
  • Проверено: gm_construct (6838 граней + 110 disp, 41 324 треугольника, 47 материалов, 0 заглушек, 65 МиБ текстур, сборка ~0.5 с), gm_flatgrass
  • Скайбокс: 6 граней из skyname worldspawn (куб вокруг камеры, глубина на дальней плоскости)
  • Вода (refract/reflect), прозрачность (glass), туман, detail-спрайты
  • Атлас лайтмапов (+2-lightmap), HDR-конвейер (RGBA16F, tonemap, bloom)
  • Compat-шейдеры: LightmappedGeneric (полный), VertexLitGeneric, UnlitGeneric, вода
  • Interest-система: PVS + frustum + octree, screen-size пороги, инстансинг, куллинг
  • Pipeline cache на диске

Приёмка v0 достигнута: оффлайн-полёт по gm_construct/gm_flatgrass с текстурами и лайтмапами.

M4 — Онлайн: мир и игроки

  • Применение снапшотов к сцене: модели/позиции/углы, интерполяция; скины, аттачменты.
  • Игроки как модели (пока без анимаций).
  • Смена карт, загрузочный экран, реконнект, базовые уведомления.
  • Стресс-полигон: локальный srcds + скрипт-спавнер (2000 пропов, 500 констрейнов); replay busy-сессий ClassicBox.
  • Приёмка: заход на ClassicBox; видим 36 игроков; стресс-полигон держит бюджет кадра (v1 — без анимаций и полной физики).

M5 — StudioRender + анимации (главный фикс Source.NET)

  • Полный скелетный пайплайн: VVD/VTX/ANIM, blend-граф, $sequence, activity layers, gestures.
  • IK-цепочки, procedural bones ($bonefollowers), flex/eyeballs, аттачменты, bodygroups.
  • GPU-скиннинг (storage buffers), morph targets.
  • Animation LOD (60/20/0 Гц по важности), статик-батчи спящих моделей, начало авто-импосторов.
  • Приёмка: игроки ходят/прыгают/приседают/держат оружие; ragdoll-позы; анимации не бьют по FPS при 64 игроках.

M6 — Геймплей-клиент

  • Prediction движения игрока (по SDK), usercmd, viewmodel, оружие, прицелы.
  • Звук: kira + WAV/MP3/OGG, пространственность, звуковые скрипты, шаги/выстрелы.
  • Физика: Jolt, hibernation островов, интерполяция физики, рагдоллы; визуальные ропы/бимы/эффекты констрейнов.
  • HUD-рамка: консоль, чат, уведомления (до Lua-аддонов — базовое).
  • Приёмка: полноценная игра на ClassicBox; 60+ FPS в замесе.

M7 — Lua: машинерия + HUD/UI

  • mlua + vendored LuaJIT (семантика 5.1, как в GMod); загрузка lua с сервера из download-кэша.
  • Bootstrap геймода как в GMod; ядро API: hook, net, timer, util, concommand, surface, draw, render, cam, input; render targets.
  • Sandbox v1: лимиты памяти, instruction-watchdog, запреты (io/os/ffi/debug), изоляция ошибок; safe mode — чёрный список упавшего файла при следующем запуске.
  • Инструмент lua-api-report: скан дампов (gluasteal) → рейтинг недостающих API.
  • Приёмка: серверные HUD-аддоны (HP/чат/killfeed) работают; сбоящий аддон не роняет клиент и отключается при следующем запуске.

M8 — Derma → PAC3 → Starfall

  • Derma/VGUI API: панели, layout, шрифты (TTF), анимации; «достаточно для типовых меню».
  • PAC3: compat API (кости, RT, материалы, вложения), бюджеты, safe mode.
  • Starfall: поддержка API, который использует аддон (он тащит свой Lua-интерпретатор внутрь GMod Lua), усиленный sandbox, лимиты.
  • Приёмка: F1-меню сервера открывается; PAC3-модели видны и анимируются; Starfall-экраны рисуются; Chaos-тесты (бесконечные циклы, гигантские меши/RT, битые данные) не крашат клиент.

M9 — Перф, кэши, полировка

  • Texture streaming и VRAM-бюджет; дисковые кэши: VPK-индексы, обработанные текстуры/меши, импосторы, pipeline cache; инвалидация по content-hash + версии парсера.
  • Авто-импосторы и merge спящих пропов с дисковым кэшем.
  • Тюнинг конваров interest-системы; бенчмарки-регрессии в CI.
  • Опции рендера: SSAO, SMAA (TAA опцией), SSR воды, динамические тени пропов/игроков; дефолты.
  • Приёмка: второй запуск и заход — секунды; страница бенчмарков; гайд по конварам.

7. Спринт 0

  • git init + .gitignore + README + docs (первый коммит)
  • Cargo workspace ~/garrysmod-rs: crates/tier (логи/конвары/конфиг/CLI), crates/fs (VPK v1/v2, листинг, CRC-проверка)
  • crates/math (базовый Vec3/Angle/Aabb)
  • client: окно SDL3 + wgpu clear + FPS в заголовке и логе (проверено: NVIDIA RTX 3060, Vulkan, ~58–63 FPS, чистое завершение)
  • Тесты: реальные VPK из ~/gmod_server/server парсятся, CRC-выборка проходит; мусор не роняет парсер
  • CI-скелет (fmt/clippy/test для tier/math/fs), fuzz-заглушка (fuzz/fuzz_targets/vpk_parse.rs)

Спринт 0 завершён (2026-10-11): fs doctor — 9 VPK, 77 933 записи, 41 архив, 0 ошибок CRC; fs cat читает MDL/текст из VPK; окно открывается на Vulkan.

8. Тестовая стратегия

  • Локальный srcds (~/gmod_server/server) — контролируемые сценарии (sv_lan).
  • Стресс-полигон: консольный спавнер на srcds + replay: 2000 пропов, 500 констрейнов, боты/игроки; отдельный тест «карта без PVS».
  • Packet dump/replay: клиент пишет сырые сетевые потоки; replay в декодер без сервера; регрессии и стресс-сцены.
  • Fuzz: VPK/BSP/MDL/VTF/PCF/снапшоты — cargo-fuzz, ночные прогоны.
  • Chaos-тесты: зловредный Lua (бесконечный цикл, гигабайтные меши, битые RT, path traversal), кривые снапшоты, огромные строки — клиент обязан выживать.
  • Бенчмарки: сцены стресс-полигона, регрессии кадра, логи в CI.

9. Риски

Риск Митигация
GMod-специфика протокола недокументирована Референс Source.NET/leysourceengineclient/SDK, packet capture, replay-стенд; изоляция слоя net
Огромный объём Lua API Рельсы + приоритеты по аддонам; lua-api-report по дампам gluasteal
Steam-лицензия/клиент на машине не установлены (только заглушка) Проверка в M2; fallback noSteam; при необходимости установить Steam+лицензию
1:1 Derma сложен Сначала «достаточно для типовых меню», итерации по реальным аддонам
Производительность при 64 игроках interest-система с M3, бенчмарки с M4, animation LOD с M5, физика-хайбернейт с M6
Юридические ограничения SDK Код — свой; SDK/референсы только как спека; ассеты — локально
Нет реального клиента GMod для captures DS-ассеты + srcds; при появлении клиента (Proton) — tcpdump; иначе дампы нашего клиента

10. Зафиксированные решения

# Решение Статус
D1 Каталог проекта — ~/garrysmod-rs принято
D2 Первая фаза — только клиент (сервер — потом) принято
D3 Linux-first, x86_64, wgpu/Vulkan принято
D4 Lua: все 4 цели, порядок HUD/UI → Derma → PAC3 → Starfall принято
D5 Рендер: современный по умолчанию; семантика материалов Source — контракт принято
D6 Steam (steamworks-rs) с M2; noSteam fallback конваром принято
D7 Стек: wgpu, SDL3, Jolt, mlua (LuaJIT), kira/symphonia, steamworks принято
D8 Принцип сандбокс-масштаба: агрессивные дефолты, всё конварами подтверждено

11. Процесс

  • Каждый этап заканчивается демо + бенчмарком + обновлением docs/.
  • Коммиты — по этапам/подсистемам, сообщения на русском.
  • Отклонения от плана фиксируются в §10 и в PROBLEMS.md.