diff --git a/TODO.md b/TODO.md index c733d76..9902924 100644 --- a/TODO.md +++ b/TODO.md @@ -93,8 +93,21 @@ boilerplate на класс), а в Rust/TypeScript тот же объём ло Overhaul 2026-09-11; Gps/HitBubbles/AmbientParticles/EndCrystal/Balancer/Trinket/ HandsShader — 2026-09-15…16, см. ниже) - [ ] Фаза 8.5: Аудит структуры ≤200/≤4 — 8.5.1 (папки >4) ЗАВЕРШЕНА 2026-09-10 - (0 папок >4, коммиты 8846d53…303b17e); далее 8.5.2 (гиганты >600), + (0 папок >4, коммиты 8846d53…303b17e); 8.5.2 (гиганты >600) ЗАВЕРШЕНА + 2026-09-28 (0 файлов >600, крупнейший — Renderer2D 474, фасад-исключение); план в `mod/TODO.md` +- [ ] Задача «Скачивание» (2026-09-29, В РАБОТЕ, детали в конце файла) — страница + `/download` с двумя кнопками: прямая скачка jar с нашего бэкенда + кнопка + GitHub под лентой «временно не работает»; jar ≥55 МБ живёт на VDS и + отдаётся gateway (`GET /downloads/lovisual.jar`); кнопки лендинга/футера + ведут на страницу, а не на файл +- [ ] Фаза 11: Серверный плагин — сервер может отключать функции мода (идея + владельца 2026-09-29, скетч в конце файла) — дизайн не написан, + реализация не начата +- [ ] Фаза 8.5.3: остаток разбивки гигантов мода (файлы >200 → ≤200; + крупнейшие сейчас: ConfigDiffPanelComponent 393, RotationManager 391, + ScriptedTriangulatorHudPanel 386, BetterButtons 381) — не марафон, + по мере касания, план в `mod/TODO.md` - [x] Фаза 9: Оптимизация FPS — 9.1 (мёртвые грузы) ЗАВЕРШЕНА 2026-09-11 (137121e…4d60d3d); 9.2 Optimize ЗАВЕРШЕНА 2026-09-25 (ade82f06…8746074d, 4 тумблера + OptimizeState); 9.3 A/B-мерка убрана из плана (решение владельца 2026-09-25: нужен запуск @@ -122,6 +135,9 @@ boilerplate на класс), а в Rust/TypeScript тот же объём ло `https://api.lovisual.example` (реальный прод-домен ещё нигде в репо не зафиксирован). HTTP-клиент и сама интеграция (auth/device-link/витрина) — отдельная будущая задача. + Решение 2026-09-29 (см. задачу «Скачивание» ниже): прямая ссылка на GitHub + из кнопок убрана — jar отдаёт наш бэкенд, GitHub остаётся второй кнопкой + под лентой «временно не работает». --- @@ -492,3 +508,75 @@ S3-совместимом хранилище (MinIO), не в Postgres. Превышение → `429 Too Many Requests` с `Retry-After`; для WebSocket — локальный drop сообщения с уведомлением клиенту, без разрыва соединения. + +--- + +## Задача «Скачивание»: две кнопки + jar с нашего бэкенда (2026-09-29, В РАБОТЕ) + +Проблема: кнопка «Скачать» вела на `/downloads/lovisual.jar`, но на проде такого +файла нет — nginx по `try_files` отдаёт `index.html`, то есть вместо мода +скачивалась HTML-страница (проверено 2026-09-29: `content-length: 2458`). + +Решение владельца 2026-09-29: + +1. Все кнопки «Скачать» (hero лендинга, FaqDownload, футер) ведут на страницу + `/download`, а не на файл напрямую. +2. На `/download` две кнопки: + - **«Скачать напрямую»** — рабочая, тянет jar с нашего бэкенда + (`/api/downloads/lovisual.jar` → nginx `/api/` → gateway → файл на диске); + - **«Скачать с GitHub»** — закрыта лентой «временно не работает» (релизы в + GitHub сейчас не публикуются), пока её не уберут вручную. +3. Gateway: новый маршрут `GET /downloads/{file}` — отдаёт файл из каталога + `DOWNLOADS_DIR` (env) с `Content-Type: application/java-archive`, + `Content-Length`, `Cache-Control: public, max-age=...`. Только известные + имена (allowlist), без обхода каталога. +4. Артефакт: `./gradlew build` в `mod/`, jar ≥55 МБ, кладётся на VDS в + `DOWNLOADS_DIR/lovisual.jar`, деплой gateway, проверка curl'ом. +5. Релизный процесс: пересобрать мод → положить jar на VDS вручную + (мод остаётся отдельным Gradle-проектом, в `deploy.sh` не встраивается). + +Проверка: `curl -I https://visual.loki-code.dev/api/downloads/lovisual.jar` → +200, `content-type: application/java-archive`, `content-length` ≥ 55 МБ; +страница `/download` показывает две кнопки; `bun run test` зелёный. + +--- + +## Фаза 11: Серверный плагин — сервер может отключать функции мода (скетч 2026-09-29) + +> Идея владельца 2026-09-29. Статус: обсуждение, дизайн не написан, кода нет. + +**Что это.** Отдельный серверный плагин (Paper/Spigot или Fabric-сервер), который +публикует подключившимся игрокам «политику»: какие возможности LoVisual на этом +сервере запрещены. Мод применяет её автоматически — честный игрок не может включить +запрещённое, пока находится на этом сервере. + +**Как связываемся.** Plugin message channel (custom payload) `lovisual:policy`: +сервер шлёт политику при входе и по запросу. Надёжнее HTTP к нашему бэкенду — +работает и без интернета, и без бэкенда. + +**Формат (черновик):** +```json +{ "deny": ["reach", "esp", "freecam"], "mode": "lock", + "reason": "правила сервера" } +``` +- `mode: lock` — модули выключены и не включаются, ClickGui показывает замок + с подписью «отключено сервером»; +- `mode: suggest` — только предупреждение, игрок сам решает. + +**Где код.** +- `server-plugin/` — новый Gradle-проект в корне репо (серверная Java, не + Fabric-клиент, поэтому отдельно от `mod/`); +- в моде — `features/platform/serverpolicy/` рядом с существующей + платформенной папкой (`PlatformHttpClient`, `BackendEndpoint` переиспользуем, + если политика однажды будет тянуться с бэкенда); +- конфиг политики сервера — YAML в папке плагина. + +**Честные ограничения (записать заранее):** применение политики — на клиенте, +читер может её игнорировать. Это не античит: цель — правила сервера и удобство +честных игроков, а не защита от нарушителей. Настоящая защита — серверный +античит, он отдельно. + +**Открытые вопросы:** целевой серверный софт (Paper vs Fabric-server vs Velocity); +публикация политики через наш бэкенд (`/policy/{server}`) или только локальным +конфигом плагина; команды `%policy` в чате; не конфликтует ли это с Подсистемой 2 +(там realtime-слой и друзья, здесь достаточно одного payload при входе).