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

15 KiB
Raw Blame History

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).

Архитектура

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) — баланс правится без кода

Протокол — контракт: клиенты зависят только от него, язык сервера можно сменить позже.

Структура репозитория

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: генератор фейковых зрителей/команд для разработки без живого стрима
  • Событие усталости: аватар временно перестаёт работать, зритель реагирует
  • Совместная работа: несколько аватаров у одной ноды дают небольшой бонус (социальная связка)
  • Рандомные события для удержания: золотая жила, дух леса и т.п.