- Препроцессор GMod: continue внутри for/while/repeat -> goto + уникальная метка; учтены строки/комментарии, вложенные циклы и функции, завершающие break/return (оборачиваются в do ... end). widget_bones.lua грузится: энтити 6 из 6. - include(): поиск рядом с текущим файлом и в lua/ игры, тот же препроцессор, лимиты размера/глубины, защита от циклов и выхода за каталог игры. - LuaRuntime::load_gamemode(): init.lua и cl_init.lua, сбор ошибок без падения. Sandbox init.lua выполняется, cl_init.lua упирается в VGUI (AccessorFunc); реестры list/scripted_ents после загрузки целы. - Безопасные заглушки загрузочного слоя Sandbox: CLIENT/SERVER, is*, FindMetaTable, cleanup, drive, duplicator, net, cvars, player_manager. - Тесты: юнит-тесты препроцессора, include на временных файлах и реальных lua/includes, загрузка sandbox на ассетах.
332 lines
27 KiB
Markdown
332 lines
27 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
|
||
|
||
**Сделано (v0, 2026-10-12):**
|
||
- [x] `crates/net`: битовые буферы (Source LSB-порядок), A2S (info с challenge),
|
||
netchan-заголовок (флаги, checksum CRC32→u16, challenge, choked),
|
||
разбор net/SVC-сообщений (tick, signon, serverinfo, print, setconvar)
|
||
- [x] Хендшейк: `getchallenge` → `S2C.Challenge` → `connect` (с GMod `ChecksumXOR`)
|
||
→ `S2C.Connection`; повтор getchallenge раз в секунду как `CheckForResend`
|
||
- [x] **Steam-аутентификация** (steamworks-rs): session ticket + steamid в connect;
|
||
**подключение к ClassicBox принято** (VAC-сервер, auth_protocol=3)
|
||
- [x] Версия клиента в connect берётся из A2S-версии сервера (иначе
|
||
`#GameUI_ServerRejectNewVersion`)
|
||
- [x] CLI: `net info <addr>`, `net connect <addr>`
|
||
- [x] Подканалы/фрагменты надёжного потока: `NetChan` (single/fragments, сжатие,
|
||
varint, сборка потоков, разбор сообщений); GMod-флаги (Challenge=0x20,
|
||
subchannel 4 бита) сверены с трафиком ClassicBox
|
||
- [x] 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):**
|
||
- [x] `engine::world`: браш-грани, displacement'ы (ориентация по startPosition +
|
||
порядок обхода, нормали наружу), лайтмапы в вершинах, VMT/VTF-материалы,
|
||
pakfile карты, скайбокс 2D (`skyname`)
|
||
- [x] `render::WorldRenderer`: батчи по материалам, depth, PNG-захват (BGRA-фикс),
|
||
debug-материалы, `--only-material`, `--dump-textures`
|
||
- [x] Камера + ходьба: `engine::player` — AABB против брашей (BSP v20) и
|
||
displacement-треугольников (SAT + сетка), гравитация/прыжок/присед/noclip
|
||
- [x] Энтити-модели: `engine::model` (MDL+VVD+VTX, bind pose), prop_static/
|
||
prop_dynamic/prop_physics в общий меш мира
|
||
- [x] 3D-скайбокс: выделение скайбокс-граней по area листа `sky_camera`
|
||
(disp-грани в `leaf_faces` не попадают — выбор по листу центра грани),
|
||
сжатие 1/scale; 2D-скайбокс рисуется фоном, мир поверх
|
||
- [x] Вода: `SURF_WARP` + VMT шейдера Water (`$abovewater`/`$fogcolor`) —
|
||
отдельный полупрозрачный проход с френелем (поверхность/изнанка)
|
||
- [x] Лайтмапы: блок грани `(size+1)²` (индекс `v*width+u`); для displacement'ов
|
||
плотная сетка по UV поверхности (`CalcDispSurfCoords`), а не проекция мира
|
||
- [x] HUD: 2D-текст (bitmap 8x8, `render::text`), FPS/позиция/режим/лог
|
||
- [x] Меню: `menu` (выбор карты из VFS, Enter — запуск)
|
||
- [ ] Куллинг/инстансинг, прозрачность (стекло), туман
|
||
- [x] Атлас лайтмапов: `Rgba16Float` 2048², UV блока в вершине, билинейная
|
||
выборка на пиксель (A10)
|
||
- [ ] Анимации моделей (парсинг seqdesc/animdesc начат; форматы RLE/raw сверяются)
|
||
- [ ] Звук, частицы, декали, оверлеи
|
||
|
||
### M7 — Lua: машинерия + HUD/UI (частично, 2026-10-12)
|
||
|
||
**Сделано (v0):**
|
||
- [x] `glua`: LuaJIT (mlua vendored), print/Msg, hook.Add/Remove/Call,
|
||
timer.Simple, concommand.Add, CreateConVar/GetConVar, util/engine/game
|
||
заглушки, FCVAR_*
|
||
- [x] Препроцессор GMod-синтаксиса: `!` → `not`, `!=` → `~=`, `&&` → `and`,
|
||
`||` → `or`, `continue` → `goto` + метка в конце тела цикла (вне
|
||
строк/комментариев) — оригинальные клиентские скрипты GMod
|
||
(demo_recording.lua, gm_demo.lua, widget_bones.lua) грузятся
|
||
- [x] `include()`: поиск рядом с текущим файлом и в `lua/`, тот же
|
||
препроцессор, лимиты размера/глубины, защита от циклов и выхода за
|
||
каталог игры
|
||
- [x] `LuaRuntime::load_gamemode`: `gamemodes/<mode>/gamemode/init.lua` и
|
||
`cl_init.lua`, сбор ошибок без падения; Sandbox `init.lua` выполняется,
|
||
`cl_init.lua` упирается в VGUI (`AccessorFunc`)
|
||
- [x] Автозагрузка `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):**
|
||
- [x] `crates/engine`: сборка мира из BSP (браши, displacement'ы, лайтмапы в вершинах,
|
||
материалы через VMT (patch/include), общий кэш текстур, пропуск прозрачных материалов)
|
||
- [x] `crates/render`: wgpu-рендерер мира (один VB/IB, батчи по материалам, глубина),
|
||
камера-полёт, скриншоты PNG (с учётом BGRA), debug-режимы (материалы, only-material)
|
||
- [x] `gmod-rs map <карта>`: загрузка с диска/из VPK, монтирование pakfile карты, полёт WASD+мышь
|
||
- [x] Проверено: gm_construct (6838 граней + 110 disp, 41 324 треугольника, 47 материалов,
|
||
0 заглушек, 65 МиБ текстур, сборка ~0.5 с), gm_flatgrass
|
||
- [x] Скайбокс: 6 граней из `skyname` worldspawn (куб вокруг камеры, глубина на дальней плоскости)
|
||
- [ ] Вода (refract/reflect), прозрачность (glass), туман, detail-спрайты
|
||
- [x] HDR-конвейер: мир в `Rgba16Float`, экспозиция, ACES, bloom (порог →
|
||
размытие → аддитивно); UI по-прежнему в sRGB после тон-маппинга
|
||
- [ ] Второй слой лайтмапы (+2-lightmap)
|
||
- [ ] 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
|
||
|
||
- [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`.
|