- VVD (IDSV v4): заголовок 64 байта, mstudiovertex_t 48 байт (веса/кости/позиция/нормаль/UV), тангенты, таблица fixup - VTX (packed): BodyPart→Model→LOD→Mesh→StripGroup→Strip, валидация индексов и смещений; смещения вложенных структур относительны своей структуры - fs inspect: для .mdl показывает VVD/VTX-статистику и сверку checksum - тесты: oildrum (270 вершин/756 индексов), 51 пара VVD/VTX с совпадающим checksum - docs: прогресс M1 (остался ANIM, PCF/PHY/SND, GMA/mount.cfg)
22 KiB
22 KiB
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-расширения).
Сверх-цели (из постановки задачи пользователя):
- Сандбокс-масштаб: оптимизация под много игроков / пропов / констрейнов.
- Современные технологии: wgpu/Vulkan, Jolt, SDL3, LuaJIT (через mlua), steamworks.
- Современный рендеринг (HDR, AA, SSAO, SSR, тени) — при строгой совместимости семантики материалов, иначе аддоны (PAC3/Starfall) визуально ломаются.
- Починка болячек GMod-клиента — см.
PROBLEMS.md. - Быстрые заходы: в игру и на сервер.
- Устойчивость к крашам от зловредных/кривых аддонов и серверов (Starfall, PAC3...).
- Полноценные анимации моделей игроков — главный видимый пробел 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. Принципы
- Совместимость — контракт. Форматы, сетевой протокол и Lua-семантика важнее «как удобнее написать код».
- Modern-by-default, compat-семантика всегда. Освещение и пост — современные;
render-state и семантика материалов (
$additive,$translucent,$alphatest, render targets, lightwarps, eyes, skinning) — ровно как в Source. - Принцип сандбокс-масштаба. Мелкое и далёкое можно вообще не рисовать и не
анимировать. Дефолты агрессивные, всё регулируется конварами. Детали —
PROBLEMS.md§P2. - Never-crash. Никакой ввод из сети/диска и никакой аддон не может уронить
клиент: bounded-парсеры, лимиты,
catch_unwindна границах, safe mode. - Speed-first. Быстрый заход в игру и на сервер — фича №1: параллельный декод, дисковые кэши, монтирование локального контента, pipeline cache.
- Data-oriented hot paths. ECS-подобное хранение сущностей, инстансинг, бюджетные очереди; без аллокаций в кадровом цикле.
- Clean-room. SDK 2013 / Source.NET / прочие референсы — спецификация, не код.
- 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
- UDP-netchan: последовательность/надёжность, фрагментация, bz2, лимиты.
- Signon: server info, stringtables, server classes/datatables, baselines, знаковые данные.
- Игра: delta-снапшоты (по классам, PVS-интерес), usermessages,
clc_*, usercmd. - GMod-расширения: передача Lua/LZMA, каналы
net.*, usermessage-регистрация скриптами, userinfo (steamid/имя/модель). - Steam:
steamworks-rs— AuthSessionTicket; ISteamUGC — подписка/скачивание workshop и монтирование локально. Fallback noSteam — конваром. - A2S-info (для отладки/меню позже). Идентификация клиента (версия из
garrysmod.ver). - Packet capture + replay стенд: сырые UDP-дампы с метаданными → оффлайн-реплей в декодер.
- Приёмка: подключение к локальному srcds и ClassicBox; в консоли — корректные игроки/энтити/строки; replay дампа воспроизводит ту же картину без сервера.
M3 — Рендер мира + interest-система (v1)
- SDL3 (окно/ввод) + wgpu: swapchain, HDR-таргет (RGBA16F), композитор, tonemap, bloom.
- BSP-рендер: worldspawn, lightmaps (+2-lightmap), displacement, вода, скайбокс, туман, detail-спрайты, прозрачные проходы.
- Материалы: два слоя — compat-семантика (render state как в Source) и современный shading; стартовый набор шейдеров: LightmappedGeneric, VertexLitGeneric, UnlitGeneric, вода, спрайт.
- Видимость: PVS + frustum + octree; screen-size пороги; инстансинг повторяющихся моделей; многопоточный куллинг; fallback для карт без PVS.
- Pipeline cache на диске (первый запуск компилирует — дальше мгновенно).
- Приёмка: оффлайн-полёт по
gm_mobenix_v3_final; 200+ FPS; на втором запуске — ни одного шейдерного стуттера.
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.