- crates/net: битовые буферы Source (LSB), A2S, netchan (флаги/checksum/challenge), разбор net/SVC-сообщений, connect с GMod ChecksumXOR и Steam-тикетом - steamworks-rs: session ticket для VAC-серверов (appid 4000) - версия клиента в connect берётся из A2S (фикс #GameUI_ServerRejectNewVersion) - CLI: net info / net connect - Проверено: ClassicBox принимает подключение (auth_protocol=3, Steam) - Далее: подканалы надёжного потока → SVC_ServerInfo → signon - docs: прогресс M2, заметки (нумерация GMod, ChecksumXOR, версии, локальный DS)
12 KiB
12 KiB
Разведка (снято 2026-10-11)
1. Окружение разработки
- OS: Linux x86_64 · CPU: 16 ядер · RAM: 31 ГБ (доступно ~17) · Swap: 8 ГБ
- GPU: NVIDIA RTX 3060 (GA106) → Vulkan через wgpu
- Rust: 1.97.1 (cargo 1.97.1)
- Домашний каталог:
/home/niko
2. Каталоги
~/garrysmod-rs— корень проекта (на момент разведки пустой; сессия переведена сюда)~/source-rs— пустой, не используется (оставлен как есть)
3. Целевой сервер: ClassicBox
- Адрес:
194.147.90.27:24215 - A2S-инфо (2026-10-11): имя
ClassicBox, картаgm_mobenix_v3_final, играgarrysmod, типSandbox, 36/46 игроков, Linux DS, VAC=1 (\x01), теги:gm:sandbox gmc:other loc:ru ver:260917 - Вывод для плана: цель по нагрузке — 46–64 живых игрока и типичный сандбокс-набор (пропы, констрейны, PAC3/Starfall у игроков), открытая карта.
4. Локальные ассеты и полигон
- GMod Dedicated Server:
~/gmod_server/servergarrysmod/garrysmod_{000,001,002}.vpk(~772 МБ) +fallbacks_*.vpk(~104 МБ)sourceengine/*(hl2_* vpk),platform/*garrysmod/mount.cfg,gameinfo.txt— порядок монтирования и mountssrcds_linux— локальный сервер для автотестов (sv_lan)garrysmod.ver:260508 prerelease
- Steam-клиент GMod:
~/.local/share/Steam/steamapps/common/GarrysMod— заглушка ~32 КБ (полного клиентского контента нет). Для рендера используем DS-ассеты. - Workshop:
~/.local/share/Steam/steamapps/workshop/content/4000— пусто.
5. Инструменты пользователя
~/glua-steal(исходники, C++) и~/gluasteal(рабочий каталог сconfig.toml) — дампер клиентского/шаренного Lua с серверов, исполнитель Lua, блокировщик файлов. Полезен как:- источник тест-корпуса Lua (дампить ClassicBox);
- источник требований к защите путей при загрузке файлов с сервера. Лицензию glua-steal отдельно проверить перед заимствованием идей (код не копируем).
6. Референс-проекты
| Проект | Что даёт | Ограничения |
|---|---|---|
| SourceDotNET/Source.NET | Структура Stage-слоёв Source; рабочий сетевой стек и подключение к реальным GMod-серверам; зачатки Lua | C#, GL46, только UnlitGeneric, физика Jitter-враппер, нет анимаций, Source 1 SDK License |
| Leystryku/leysourceengineclient | Базовый сетевой протокол для внешних клиентов | — |
| ValveSoftware/source-sdk-2013 | Спецификация: net_chan, dt_*, studio, шейдеры, VGUI, предсказание | Лицензия SDK (только для модов Source) — берём как спеку |
| nillerusr/source-engine | Кроссплатформенный порт: Linux-специфика, шейдерные переводы | SDK-лицензия |
| wiki.facepunch.com/gmod | Lua API и поведение движка | — |
| gluasteal | Требования к безопасности загрузки файлов | проверить лицензию |
7. Ключевые факты о GMod, влияющие на план
- Клиент исторически 32-битный (есть 64-битная бета) → у нас сразу x86_64.
- Lua: LuaJIT (семантика 5.1).
- PAC3/Starfall — аддоны внутри GMod Lua (Starfall несёт свой интерпретатор) → наша задача = движковый API + sandbox; их логику не переписываем.
- Скачиваемые с сервера файлы: Lua + контент; LZMA-сжатие (уточнить capture'ами в M2).
- Сервер может требовать Steam-тикет (ClassicBox VAC=1) → steamworks-rs с M2, fallback noSteam конваром.
- В DS-установке есть базовые lua-файлы игры — референс порядка bootstrap Lua-рантайма.
8. Лицензии и правовая позиция
- Цель проекта — личный клиент для игры на серверах; ассеты берутся из локальных установок пользователя и не распространяются.
- Source SDK 2013 и Source.NET — Source 1 SDK License: код не копируем, используем как спецификацию форматов и поведения.
- Наш код — собственный (clean-room по форматам/поведению).
9. Тестовый контур
| Контур | Использование |
|---|---|
Локальный srcds_linux (~/gmod_server/server) |
Контролируемые сценарии, синтетика (2000 пропов, 500 констрейнов) |
| Packet dump/replay | Воспроизведение прод-нагрузки без сервера |
| ClassicBox (live) | Финальные проверки (36–46 игроков), аккуратно и по делу |
| Fuzz-стенды | vpk/bsp/mdl/vtf/pcf/сеть — cargo-fuzz |
10. Заметки спринта 0 (обновляется по ходу)
- VPK в установке: 9
*_dir.vpk(77 933 записи, 41 архив) — garrysmod (v2, 15 324 записи), fallbacks, hl2_{textures,misc,sound_misc,sound_vo_english}, content_hl2, content_cstrike, platform_misc. CS:S-контент присутствует (важно для gm_mobenix). - Формат VPK сверен с ValvePak (VRF): терминаторы, preload, встроенные данные,
внешние архивы
<stem>_NNN.vpk; парсер bounded и fuzz-устойчив. fs doctor: 0 ошибок CRC на выборке;fs catчитает MDL (IDST) и текстовые файлы из VPK.- Клиент: SDL3 (собран из исходников, feature
build-from-source) + wgpu 30. Запуск проверен: NVIDIA RTX 3060, Vulkan, ~58–63 FPS (vsync), чистое завершение по--frames. - wgpu 30: API проверено по примеру sdl3-rs (
raw-window-handle-with-wgpu); заголовок окна обновляется черезsdl3::sys(метод крейта требует&mut Window). - BSP v20: структуры
dnode_t/dleaf_tна диске выровнены до 32 байт (хвостовой паддинг) — иначе поля читаются как мусор;dnode_t.children—int[2], неshort. - gm_construct: геометрия валидна (14 079 вершин, 9 460 граней, 4 988 узлов), pakfile — ZIP 3.8 МБ, 599 записей (CRC проверен на выборке).
- VTF brickfloor001a.vtf: 7.1, DXT1 512×512, 10 мипов, миниатюра 16×16; раскладка данных совпадает с размером файла до байта; декод мипа 0 и миниатюры — ок.
- По 200 случайных VTF и VMT из VPK разбираются без единой ошибки.
- Полезные открытые референсы форматов (используем как спецификации, не код):
vformats(KV/VMT/VTF/PHY/GMA/SND),source-vtf(VTF 7.x), ValvePak (VPK), glua-steal. - MDL: базовый studiohdr_t = 408 байт (все версии); у v48+ за заголовком лежит
studiohdr2_t (256 байт,
studiohdr2index=408), данные костей начинаются после него. Смещения полей совпадают у v44–v48 (проверено на 53 моделях: v44 — 47, v45 — 1, v48 — 5,length == размер файлау всех). - VVD: заголовок 64 байта (
IDSVv4), вершина mstudiovertex_t = 48 байт. - VTX: структуры packed (
#pragma pack(1)); смещения вложенных структур отсчитываются от своей структуры, а не от начала файла (толькоbodyPartOffset— от файла). Проверено: oildrum001 — 270 вершин / 756 индексов / 1 стрип; 51 пара VVD/VTX — checksum совпадает. fs inspectдля модели показывает кости/аттачменты/текстуры/keyvalues и меш-статистику.- M3 v0 (рендер мира): gm_construct собирается за ~0.5 с — 6838 браш-граней + 110 displacement, 46 646 вершин, 41 324 треугольника, 47 материалов, 65 МиБ текстур.
- Запечённые VRAD-материалы карты лежат в pakfile BSP как VMT-патчи
(
maps/<map>/...,include→ базовый материал,replace $envmap→ кубмапа); pak монтируется как источник файлов VFS. VTFs в pak — кубмапы (.hdr.vtf). - Материалы без
$basetexture(шейдерlightmappedreflective— стекло/вода) в v0 пропускаются как прозрачные, а не красятся заглушкой. - Скриншоты: на NVIDIA/Vulkan формат поверхности — BGRA; readback обязан менять местами R/B (иначе цвета инвертируются, что однажды уже сбило диагностику).
- Спавн gm_construct — внутри «color room» (большой белой комнаты): для эффектных
скриншотов камеру надо выносить наружу (
--pos/--angles). - Скайбокс: небо «painted» — это реально почти равномерная светлая текстура (256×256 DXT5); проверять отрисовку скайбокса надо через смену clear color.
- Скайбокс рисуется на дальней плоскости:
clip.z = clip.w * 0.99995— ровноz=wотбрасывается клиппингом (симптом: скайбокс «не рисуется», видно цвет очистки). - M2 v0: нумерация net/SVC-сообщений в GMod сдвинута относительно Source 2013 (NET_Tick=3, NET_SignonState=6, SVC_Print=7, SVC_ServerInfo=8); сверено с Source.NET.
- GMod требует в connectionless
connectполеChecksumXOR(зависит от первого байта и длины буфера) — без него сервер молчит. - ClassicBox (VAC=1) требует Steam-тикет (auth_protocol=3): steamworks-rs
Client::init_app(4000)+authentication_session_ticket_with_steam_id; в connect пишетсяu16(размер+8),u64 steamid, тикет. - Сервер сравнивает версию клиента: при старой версии —
#GameUI_ServerRejectNewVersion; наша версия берётся из A2S-ответа сервера. - Локальный GMod DS (
srcds_linux) в этом окружении виснет после «VAC secure mode disabled» (Steam-инициализация), поэтому живой полигон — ClassicBox.