16 KiB
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 (почти бесплатно сейчас)
Локально для себя, но с прицелом на будущий мультистримерный хостинг:
channelIdвезде с первого дня: колонки в таблицах БД, поле в командах и WS-сообщениях- Интерфейс
TwitchSource: локально = свой bot-токен через twurple; на хостинге замена на OAuth-flow без изменений в остальном коде - Тонкий слой persist над SQLite — заменим при необходимости
- Контент как данные (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 персональных вкладов
- Декей съедает вклады → визуальный откат, если долго никто не работает
- Уровни костра 1–5
Отдых (бафф за активность, не за силу)
!отдыху костра тратит рыбу → +20% добычи на 5 минут за 1 минуту отдыха- Стакается ограниченно; влияет почти незаметно — механика вовлечения, не прогресса
Антиспам
Кулдаун на смену действия, троттлинг ответов бота (пишет только при значимых событиях).
Милстоуны
- M0 — каркас. Монорепа, overlay+web скелеты, WS-эхо. ✅ аватар-заглушка виден в OBS
- M1 — вертикальный срез.
!рубить/!стоп, спавн аватара (спрайт-человечек, ник над головой в цвете чата), ходьба к дереву, брёвна + XP + уровень, автосейв, WS-снапшот+дельты, камера-окно + простейший автотур, FakeTwitchSource — отладка команд без живого чата. ✅ зритель пишет!рубитьи видит себя рубящим в лесу - M2 — руда и кузница.
!копать+!ковать+ тиры топоров/кирок. ✅ скрафтил железный топор → рубишь заметно быстрее - M3 — рыба и кухня.
!рыбачить+!готовить+!отдыху костра. ✅ рыба → жареная рыба → бафф +20%/5 мин - M4 — кооп-костёр. Ledger вкладов, декей с откатом, уровни 1–5. ✅ растёт общими силами, без активности откатывается
- M5 — экономика и полировка. Спотлайт через Channel Points (EventSub, очередь),
!подарить,!топ, дашборд стримера (баланс-конфиги, сбросы). ✅ полная экономика + управление без правки кода
Риски / известные ловушки
- bitecs 0.4: мало примеров под новый API — время на чтение исходников; системы оборачиваем тонким интерфейсом для дешёвого fallback
- OBS browser source кэширует: dev через отдельный порт, версионирование протокола в рукопожатии клиента/сервера
- Free-версии паков (Sprout Lands, Mystic Woods) — только некоммерческое: для монетизированного канала — CC0 или платная лицензия
- Rate limits чата: бот отвечает дозированно
- EventSub: нужен Twitch-апп (client id/secret) у стримера; EventSub WebSocket работает локально без публичного webhook-URL — ок для локального MVP
Ассеты
Аватар зрителя = обычный спрайт-человечек целиком — лицо и тело из пака, фото профиля Twitch не используем. На старте все зрители с одним и тем же спрайтом; личность читается по нику над головой в цвете ника чата. Разные скины — на будущее (донатеры/сабы), поэтому пак желателен с запасом: генератор персонажей или палитрные свопы.
Человечки + скины
- LimeZu — Modern Interiors / Modern Exteriors (itch.io, name-your-own-price ≈ $5, лицензия CC-BY: коммерция ок с указанием авторства) — основной кандидат: домики, мебель, здания уровня «ратуша», предметы — всё в одном стиле; генератор персонажей в платной версии пригодится, когда дойдёт до скинов донатеров
- Universal LPC Spritesheet Generator (бесплатно, онлайн) — сборка спрайт-листов с ходьбой/анимациями из тысяч деталей. Лицензия GPL/CC-BY-SA — проверить перед коммерциализацией
- Kenney.nl — CC0 (тайлы, предметы, простые человечки) — текущая база проекта; конкретные паки подбираем при M1 (нужны: персонаж с ходьбой, деревья/камни, вода)
Домики, костёр, ратуша
- Sprout Lands (Cup Nooble, itch.io) — милый фермерский стиль; free-версия только для некоммерческого, premium от ~$4 снимает ограничение
- Mystic Woods (Game Endeavor, itch.io) — есть бесплатная lite-версия: домики, костёр, природа; free-версия тоже только для некоммерческого
- OpenGameArt.org — много RPG-паков зданий, лицензии смешанные — читать каждую
- CraftPix freebies — бесплатные наборы зданий/персонажей
Правила выбора
- Для стрим-игры (канал может быть монетизирован) — CC0 или платная лицензия; CC-BY только с готовностью указать авторство (можно в дашборде)
- Один стиль важнее качества каждого пака — брать линейку у одного автора (LimeZu закрывает людей, дома, ратушу и предметы)
- Решено: идём полностью на бесплатном. База — Kenney (CC0); OpenGameArt — с проверкой лицензии каждого ассета. Платные паки (LimeZu ≈ $5) — опция на потом, если захочется единого стиля
Идеи на потом
- Скины для донатеров/сабов: разные внешности аватаров (генератор персонажей LimeZu или палитрные свопы)
- Событие усталости: аватар временно перестаёт работать, зритель реагирует
- Совместная работа: несколько аватаров у одной ноды дают небольшой бонус (социальная связка)
- Рандомные события для удержания: золотая жила, дух леса и т.п.