gmod-rs/docs/ARCHITECTURE.md

191 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Архитектура Source RS
## 1. Workspace
```
crates/
tier — tracing-логи, конвары, CommandLine, конфиг, время, пулы, interning
math — Vector/Angle (Source-семантика углов), Matrix, Quaternion, AABB, plane
fs — поисковые пути и порядок монтирования: dir, VPK v1/v2, GMA,
BSP pakfile, mount.cfg, mmap, кэш индексов (rkyv)
formats — kv (KeyValues), bsp, vtf, vmt, mdl (+vvd/vtx/anim), pcf, phy, snd, demo
net — netchan (UDP, фрагментация, bz2), dt (send/recv tables), stringtable,
usermessages, GMod-расширения, мост к Steam
engine — мир, entity-стор (архетипы/пулы), интерполяция, prediction, usercmd,
interest-система (классификация, важность, бюджеты)
render — wgpu: device/swapchain, HDR-таргет, material system (compat-семантика +
современный shading), шейдеры, инстансинг, RT-менеджер, post, pipeline cache
studio — StudioRender: mdl-инстансы, кости, blend-граф, IK, procedural bones, flex,
LOD, аттачменты
physics — Jolt (C-API + свой безопасный слой), hibernation, prediction-мир, рагдоллы
audio — kira (микс) + symphonia (декод), пространственность, звуковые скрипты
ui — нативный UI: меню, консоль, шрифты, HUD-рамка, загрузочные экраны
lua — mlua (vendored LuaJIT), sandbox, рельсы API, мосты к engine/render/studio
steam — фичи steamworks-rs (тикет, UGC/workshop), отдельный steam-поток
client — бинарь `gmod-rs`: сборка всего, главный цикл, конфиг, CLI
```
### Правило зависимостей
Строго «вниз по списку»:
```
tier, math → fs, formats → net → engine → render, studio, physics, audio, ui → lua → client
```
- `lua` и `client` вправе зависеть от всего (lua — движковый API, client — композиция).
- Обратные зависимости запрещены; `render` может зависеть от `studio` (модели),
`engine` — от `net` (типы снапшотов), но не наоборот.
## 2. Технологический стек и почему
| Задача | Выбор | Почему |
|---|---|---|
| GPU | **wgpu** (Vulkan на Linux) | Современные фичи, кроссплатформенность, pipeline cache, compute |
| Окно/ввод | **SDL3** (при проблемах — winit) | Геймпады, IME, зрелость, кроссплатформенность |
| Физика | **Jolt** через C-API | Де-факто замена VPhysics в современных Source-подобных; job-friendly |
| Lua | **mlua + vendored LuaJIT** | Семантика 5.1 как в GMod + производительность |
| Звук | **kira** + **symphonia** | Гибкий микс + декод mp3/ogg/wav |
| Steam | **steamworks-rs** | Тикет, UGC/workshop, браузер позже |
| Форматы | Свои парсеры + `bzip2`, LZMA (raw LZMA1) | Полный контроль, bounded, fuzzable |
| Кэши | `rkyv`/`bincode`, mmap (`memmap2`) | Быстрый старт, индекс VPK, обработанные ассеты |
| Логи | `tracing` | Каналы, фильтры, интеграция с dev-тулингом |
| Ошибки | `thiserror` (крейты) + `anyhow` (границы приложения) | Явные типы, удобный верхний уровень |
## 3. Подсистемы
### 3.1 FileSystem (`fs`)
Порядок монтирования (уточняется в M1 по поведению GMod):
```
platform → sourceengine (hl2-база) → garrysmod_*.vpk → garrysmod/addons/*
→ workshop (по списку сервера, через Steam) → download-кэш (lua/контент с сервера)
→ BSP pakfile (мапа) → write-пути (наш конфиг/cache)
```
- `mount.cfg` пользователя учитывается (`~/gmod_server/server/garrysmod/cfg/mount.cfg`).
- Все открытия — через единый интерфейс с нормализованными путями (защита от traversal).
- Индекс VPK кэшируется на диск (content-hash + версия парсера).
### 3.2 Сеть (`net`)
Конвейер:
```
UDP → netchan (сборка фрагментов, bz2) → потоки сообщений → signon/delta-декод
→ очередь «снапшот готов» → применение на главном потоке (тик интерполяции)
```
- Никаких блокировок в горячих путях: net-поток кладёт пакеты в lock-free очередь,
декод — в worker-пулах, применение — двойная буферизация.
- Все ограничения входных данных — явные (размеры строк/массивов, глубина, количество энтити).
- Dump/replay: `net` умеет писать/читать сырые потоки с метаданными (см. `NETWORK.md`).
### 3.3 Entity-система (`engine`)
- Хранение — архетипами/пулами (SoA-ish), стабильные ID, без аллокаций на сущность в кадре.
- Клиентские энтити — прокси для рендера/физики; Lua-фасад создаётся лениво,
только если аддоны реально трогают сущность.
- Интерполяция: буфер из 2–3 снапшотов, рендер с задержкой (как в Source MP).
- Prediction: локальный игрок (movement по SDK), usercmd, реконсиляция.
### 3.4 Interest & Visibility (`engine` + `render`)
«Принцип сандбокс-масштаба» (детали — `PROBLEMS.md` §P2):
- Состояния: `Static → Sleeping → Dynamic → Impostor → Skipped` (обратимо).
- Важность: экранный размер, дистанция, движение, свежесть сети, взаимодействие.
- Бюджеты: анимации (60/20/0 Гц), скиннинг, тени, партиклы, обновление костей.
- Инстансинг повторяющихся моделей; merge спящих пропов в статические батчи.
- Куллинг: PVS + frustum + octree, многопоточно; fallback без PVS.
- **Правило совместимости:** куллинг не влияет на существование сущностей и на
Lua-draw (PAC3/Starfall/HUD видят всё; у них свои бюджеты).
### 3.5 Рендер (`render`)
Два слоя:
1. **Compat-семантика** — точный render state и поведение материалов Source:
render modes (`$additive`, `$translucent`, `$alphatest`), RT, lightwarps, cubemaps,
eyes, skinning, decals, halos. Контракт: аддоны не должны отличать нашу картинку от GMod.
2. **Современный shading** — HDR-конвейер (RGBA16F), линейное освещение, tonemap, bloom,
SSAO, SMAA (TAA опцией), SSR воды, динамические тени моделей (опцией), анизотропия.
Прочее: pipeline cache на диске; параллельная запись команд; shadow/RT-бюджеты;
texture streaming и VRAM-бюджет (с M9).
Шейдеры по приоритету: LightmappedGeneric → VertexLitGeneric → UnlitGeneric → вода →
спрайты → декали/эффекты → прочее. Аддонские DXBC — вне первой фазы.
### 3.6 StudioRender (`studio`)
- Загрузка: MDL/VVD/VTX/ANIM, `$keyvalues`, bodygroups, аттачменты.
- Анимация: blend-граф (секвенции/жесты/activity layers), IK, procedural bones
(`$bonefollowers`), flex/eyeballs.
- LOD: по важности; GPU-скиннинг в storage buffers; фриз костей для дальних.
- Ragdoll-позы + клиентская физика (Jolt).
### 3.7 Потоки и конкурентность
- **Main** — ввод, применение снапшотов, Lua (как в GMod), запись кадра.
- **Pool** — куллинг, скиннинг-подготовка, декод ассетов, копирование данных на GPU.
- **Net** — сокет и netchan; декод в отдельных worker'ах.
- **Physics** — Jolt jobs (многоядерно), hibernation дальних островов.
- **Steam** — отдельный поток: Steam API не потокобезопасен, все вызовы там; наружу — каналы.
- **Lua** — главный поток (как в GMod); тяжёлые вычисления — только через явные API;
watchdog следит за зависаниями.
### 3.8 Ассет-пайплайн и кэши
Каталог кэша (по умолчанию `~/.cache/source-rs`, настраивается):
| Кэш | Содержимое | Инвалидция |
|---|---|---|
| `vpk-index/` | Индексы VPK/GMA | content-hash + версия парсера |
| `textures/` | Обработанные текстурные блобы+mips | хэш исходника + версия |
| `meshes/` | Готовые vertex/index-буферы, импосторы | хэш + версия |
| `pipelines/` | wgpu pipeline cache | версия драйвера/шейдеров |
| `lua-bc/` | Байткод LuaJIT (опц.) | хэш + версия LuaJIT |
| `downloads/` | Файлы, скачанные с серверов | хэш (вечный кэш) |
Цель: второй и последующие запуски — секунды; серверные файлы не качаются повторно.
### 3.9 Конфигурация
- `~/.config/source-rs/config.toml` (или `--config`): корни ассетов, каталог кэша,
серверы, фичи.
- Авто-детект ассетов: (1) явный путь; (2) `~/gmod_server/server`; (3) Steam common.
- Внутриигровые настройки — конвары (как в Source), сохраняются в `cfg/`.
## 4. Конвенции кода
1. `unwrap/expect/panic` запрещены в путях обработки внешних данных (сеть/диск/Lua).
Для внутренних инвариантов — `debug_assert` и явные ошибки.
2. FFI-границы (Jolt, Steam, Lua) оборачиваются в безопасные слои; все входы проверяются.
3. `catch_unwind` — на границах Lua/FFI/worker; паника одного аддона/задачи не убивает клиент.
4. Без `unsafe` вне FFI-обёрток; FFI-крейты изолированы.
5. Горячие пути — без аллокаций; interning строк; пулы.
6. Ошибки — типизированные (`thiserror`) в крейтах, `anyhow` на верхнем уровне.
7. Тесты — рядом с кодом; fuzz-таргеты для всех парсеров; бенчмарки для hot paths.
## 5. Бюджеты производительности (ориентиры для M9)
| Стадия | Бюджет (мс/кадр, RTX 3060, стресс-сцена) |
|---|---|
| Сеть/декод (не main) | ≤ 2 |
| Применение снапшотов | ≤ 1 |
| Interest/куллинг | ≤ 1 |
| Анимации (подготовка) | ≤ 2 |
| Запись рендер-команд | ≤ 3 |
| Main total | ≤ 8 (цель 60+ FPS со запасом) |
## 6. Схема кадра (упрощённо)
```
Input → Usercmd → Prediction(local)
Net queue → Snapshot apply → Entities → Interp states
Interest/Visibility → cull → instancing/static batches → anim LOD → render graph → present
Lua: Frame → HUD/Paint → Render hooks (в порядке как в GMod; sandbox)
Physics (client-side) → интерполяция/рагдоллы
```