Files
idle-xboct/docs/PLAN.md
T
2026-08-26 06:42:50 +05:00

195 lines
15 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.
# Idle-XBOCT — план игры для Twitch-чата
Смесь Stream Avatars и idle-игр (Melvor Idle / Idle Iktah) с кооп-задачами.
Аватары зрителей живут на экране стрима; команды чата управляют ими.
**Ключевой принцип:** весь геймплей через команды чата — клиенты только отображают состояние.
---
## Стек
| Слой | Выбор |
| -------- | ------------------------------------------------------------------------------------------- |
| Монорепа | pnpm workspaces + TypeScript strict |
| Клиенты | Svelte 5 + PixiJS 8 (8.x) + bitecs 0.4 |
| Сервер | Node.js, `node:http` + `ws` + `sirv` (без фреймворка), симуляция на bitecs |
| Twitch | `@twurple/easy-bot` (чтение команд + ответы в чат), `@twurple/eventsub-ws` (Channel Points) |
| БД | SQLite (`better-sqlite3`) через тонкий слой репозиториев |
Решения по ECS: **bitecs, новый API 0.4** (в 0.4 API переписан; старый доступен как `bitecs/legacy`).
Запасной вариант — koota (pmndrs), если новый API окажется слишком зубодробительным.
miniplex отклонён (объектный оверхед + не развивается с 2023).
## Архитектура
```txt
Twitch IRC ──> [сервер: очередь команд] ──> тик 1 Гц
SQLite <── persist WS-снапшот+дельты ──> overlay (OBS browser source)
└──> web-страница-мир
```
**Сервер полностью авторитарный.** Все зрители видят одно и то же; OBS произвольно
перезагружает browser source; сейвы в одном месте.
### Два слоя состояния
Не тащить всё в ECS:
- **Симуляционный слой (bitecs)** — то, что тикает и рендерится:
аватары (позиция, цель, прогресс действия), ноды ресурсов, костёр на сцене.
- **Мета-слой (plain TS records + SQLite)** — инвентарь, XP/скиллы, рецепты,
вклад в костёр, подарки. Живёт вне ECS, сохраняется напрямую.
## Синхронизация
- Подключение → полный снапшот; далее дельты раз в тик + события («+XP», «скрафчено», «вклад в костёр»)
- **Команды обрабатываются сразу при приходе**, не ждут тика → мгновенная реакция на `!рубить`
- **Движение — декларативные твины**: сервер один раз шлёт «идёт из A в B, скорость v»,
клиент анимирует сам. Позиции и прогресс-бары дорисовываются локально между тиками
- Тик фиксированный 1 сек (захочется отзывчивее — константа → 2–4 Гц)
- Симуляция от wall-clock таймстемпов: при старте сервера пропущенное время
догоняется ретроактивно (декей костра копился, пока стрим был оффлайн)
## Хостинг-ready (почти бесплатно сейчас)
Локально для себя, но с прицелом на будущий мультистримерный хостинг:
1. **`channelId` везде с первого дня**: колонки в таблицах БД, поле в командах и WS-сообщениях
2. **Интерфейс `TwitchSource`**: локально = свой bot-токен через twurple;
на хостинге замена на OAuth-flow без изменений в остальном коде
3. **Тонкий слой persist** над SQLite — заменим при необходимости
4. **Контент как данные** (JSON-in-TS в `shared`) — баланс правится без кода
Протокол — контракт: клиенты зависят только от него, язык сервера можно сменить позже.
## Структура репозитория
```txt
idle-xboct/
├─ packages/
│ ├─ shared/ # протокол WS, контент (предметы/скиллы/ноды/рецепты), XP-кривые.
│ │ # Чистые данные, без DOM/canvas зависимостей — импортируется и сервером
│ ├─ server/ # node:http + ws + twurple-bot + bitecs-sim + sqlite
│ │ └─ src/{twitch, sim, game, net, persist}
│ ├─ render/ # pixi-зависимый общий рендер (аватары, ноды, интерполяция)
│ ├─ overlay/ # Svelte 5 + Pixi 8 — компактный, прозрачный фон, для OBS
│ └─ web/ # Svelte 5 + Pixi 8 — страница-мир: большой канвас + панели
```
`web` = богатый спектатор, OAuth зрителям не нужен: read-only панели
(свой инвентарь по нику, дерево рецептов, лидерборды, прогресс костра).
Кликабельные действия — возможное будущее расширение с Twitch OAuth.
## Игровые механики MVP
Навыки: Рубка леса, Добыча руды, Кузнечное дело, Рыбалка, Кулинария.
XP-кривая Melvor-подобная, уровни открывают ноды/рецепты.
- Действие = 15–60 сек с видимым прогрессом (зритель должен увидеть аватар за работой)
- Ноды ресурсов: тиры деревьев/руды/рыбных мест, респавн
- Крафт: топоры/кирки тирами; предметы — стаки, строковые slug-id
- Инструменты можно менять и дарить (`!подарить @ник предмет`); подарки только
**перемещают** предметы — нельзя подарить то, чего у тебя нет
- Аватар продолжает текущее действие, пока не придёт другая команда (`!стоп` — остановиться)
- Онбординг — в самом виджете (HUD-подсказки), чат ботом не засоряем
- Команды: `!рубить`, `!копать`, `!ковать`, `!рыбачить`, `!готовить`, `!отдых`,
`!стоп`, `!подарить`, `!топ`; спотлайт — не команда, а Channel Point награда.
RU сейчас, EN-алиасы потом через конфиг
### Камера и «показать меня»
Оверлей показывает не весь мир, а окно-видеоискатель. Мир — горизонтальная полоса зон:
лес | рудник | река | костёр/кузница | кухня.
- **Автотур**: камера сама плавно переезжает между зонами с активностью,
стоянка ~30–60 сек на зону; без активности — медленный дрейф
- **Спотлайт через Channel Points**: стример создаёт кастомную награду «Показать меня»
в твитч-панели → зритель выкупает за свои очки канала (Twitch сам начисляет и списывает,
своя экономика не нужна) → сервер ловит redemption по EventSub → камера едет к аватару
на ~1 минуту → возврат в тур. Очередь спотлайтов; балансировка спроса — позже,
другими наградами за те же очки
- Камера стрима **авторитарна на сервере** — все клиенты стрима видят одно и то же;
веб-страница-мир получает свободную камеру + «следовать за мной»
### Кооп-костёр
- Общий пул прогресса + ledger персональных вкладов
- Декей съедает вклады → визуальный откат, если долго никто не работает
- Уровни костра 15
### Отдых (бафф за активность, не за силу)
- `!отдых` у костра тратит рыбу → **+20% добычи на 5 минут за 1 минуту отдыха**
- Стакается ограниченно; влияет почти незаметно — механика вовлечения, не прогресса
### Антиспам
Кулдаун на смену действия, троттлинг ответов бота (пишет только при значимых событиях).
## Милстоуны
- **M0 — каркас.** Монорепа, overlay+web скелеты, WS-эхо.
✅ аватар-заглушка виден в OBS
- **M1 — вертикальный срез.** `!рубить`/`!стоп`, спавн аватара (аватарка из тегов чата),
ходьба к дереву, брёвна + XP + уровень, автосейв, WS-снапшот+дельты,
камера-окно + простейший автотур.
✅ зритель пишет `!рубить` и видит себя рубящим в лесу
- **M2 — руда и кузница.** `!копать` + `!ковать` + тиры топоров/кирок.
✅ скрафтил железный топор → рубишь заметно быстрее
- **M3 — рыба и кухня.** `!рыбачить` + `!готовить` + `!отдых` у костра.
✅ рыба → жареная рыба → бафф +20%/5 мин
- **M4 — кооп-костёр.** Ledger вкладов, декей с откатом, уровни 1–5.
✅ растёт общими силами, без активности откатывается
- **M5 — экономика и полировка.** Спотлайт через Channel Points (EventSub, очередь),
`!подарить`, `!топ`, дашборд стримера (баланс-конфиги, сбросы).
✅ полная экономика + управление без правки кода
## Риски / известные ловушки
- **bitecs 0.4**: мало примеров под новый API — время на чтение исходников;
системы оборачиваем тонким интерфейсом для дешёвого fallback
- **OBS browser source кэширует**: dev через отдельный порт, версионирование протокола
в рукопожатии клиента/сервера
- **Аватарки Twitch CDN**: ленивая загрузка + фолбэк-спрайт
- **Rate limits чата**: бот отвечает дозированно
- **EventSub**: нужен Twitch-апп (client id/secret) у стримера; EventSub WebSocket
работает локально без публичного webhook-URL — ок для локального MVP
## Ассеты
Аватар зрителя = фото профиля Twitch в кольце; спрайтовые человечки — «тела» под ними
и фолбэк. Поэтому берём паки, где тело и голова разделены.
### Человечки + скины
- **LimeZu — Modern Interiors / Modern Exteriors** (itch.io, ~$1015) — основной кандидат:
генератор персонажей с сотнями скинов/одежды, домики, мебель, здания уровня «ратуша»,
всё в одном стиле
- **Universal LPC Spritesheet Generator** (бесплатно, онлайн) — сборка спрайт-листов
с ходьбой/анимациями из тысяч деталей. Лицензия GPL/CC-BY-SA — проверить перед коммерциализацией
- **Kenney.nl** — CC0, человечки простые геометрические — для прототипа M0–M1
### Домики, костёр, ратуша
- **Sprout Lands** (Cup Nooble, itch.io) — милый фермерский стиль
- **Mystic Woods** (Game Endeavor, itch.io) — есть бесплатная lite-версия: домики, костёр, природа
- **OpenGameArt.org** — много RPG-паков зданий, лицензии смешанные — читать каждую
- **CraftPix freebies** — бесплатные наборы зданий/персонажей
### Правила выбора
1. Для стрим-игры (канал может быть монетизирован) — CC0 или платная лицензия;
CC-BY только с готовностью указать авторство (можно в дашборде)
2. Один стиль важнее качества каждого пака — брать линейку у одного автора
(LimeZu закрывает людей, дома, ратушу и предметы)
3. Прототип M0M1 — на CC0/Kenney, красивые паки подключаем с M2+
## Идеи на потом
- FakeTwitchSource: генератор фейковых зрителей/команд для разработки без живого стрима
- Событие усталости: аватар временно перестаёт работать, зритель реагирует
- Совместная работа: несколько аватаров у одной ноды дают небольшой бонус (социальная связка)
- Рандомные события для удержания: золотая жила, дух леса и т.п.