- 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)
262 lines
22 KiB
Markdown
262 lines
22 KiB
Markdown
# 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):**
|
||
- [x] KeyValues: толерантный bounded-парсер (VMT/gameinfo/entities), лимиты, тесты
|
||
- [x] BSP: заголовок + 64 лумпа, LZMA-лумпы, ENTITIES (KeyValues), TEXDATA/имена текстур,
|
||
game lumps, PAKFILE (ZIP: Store/Deflate, CRC)
|
||
- [x] Геометрия BSP v20: вершины/рёбра/surfedges/грани/texinfo/узлы/листья/модели,
|
||
`validate()` по перекрёстным ссылкам (gm_construct/gm_flatgrass — валидно)
|
||
- [x] VTF 7.0–7.5: заголовок (+таблица ресурсов 7.3+), раскладка мипов, миниатюра,
|
||
декод в RGBA8 (DXT1/3/5, RGBA/BGRA/ABGR/ARGB, RGB/BGR, I8/A8/IA88, RGB565/BGR565)
|
||
- [x] VMT: шейдер, параметры, patch (include/replace/insert), Proxies, render-modes
|
||
- [x] MDL: заголовок (v44–49, studiohdr2), кости, аттачменты, хитбоксы, текстуры,
|
||
бодипарты, include-модели, `$keyvalues`, `surfaceprop` (проверено на реальных моделях)
|
||
- [x] VVD/VTX: вершины (позиция/нормаль/UV/веса костей), fixup'ы, полное дерево
|
||
BodyPart→Model→LOD→Mesh→StripGroup→Strip с валидацией индексов (51 пара на реальных моделях)
|
||
- [x] CLI: `fs doctor`, `fs list`, `fs cat`, `fs inspect` (BSP/VTF/VMT/MDL + VVD/VTX)
|
||
- [x] Тесты на реальных данных: 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
|
||
|
||
- [x] `git init` + `.gitignore` + README + docs (первый коммит)
|
||
- [x] Cargo workspace `~/garrysmod-rs`: `crates/tier` (логи/конвары/конфиг/CLI), `crates/fs` (VPK v1/v2, листинг, CRC-проверка)
|
||
- [x] `crates/math` (базовый Vec3/Angle/Aabb)
|
||
- [x] `client`: окно SDL3 + wgpu clear + FPS в заголовке и логе (проверено: NVIDIA RTX 3060, Vulkan, ~58–63 FPS, чистое завершение)
|
||
- [x] Тесты: реальные VPK из `~/gmod_server/server` парсятся, CRC-выборка проходит; мусор не роняет парсер
|
||
- [x] 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`.
|