Skip to content
MoonGameTechnologyPublic

Latest commit

 

History

5,798 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Averion: Galactic War или Void Dominion: Galactic War (пока решаем)

Космическая стратегия в реальном времени для браузера и Android.

Развивайте планеты, собирайте флоты, высаживайте армии и договаривайтесь с другими командирами. Война здесь — не только бой: маршрут, разведка, экономика и вовремя отданный приказ определяют, с какими силами вы встретите противника.

Браузерная сборка · Android-альфа · Документация · Состояние проекта

Аудиоэскизы: музыка и сигналы событий — материалы для прослушивания, пока не подключённые к игре.

Проект в активной разработке. В репозитории есть играбельные альфа-сборки; интерфейс, баланс и состав контента продолжают меняться. Наличие механики в дизайн-документе не означает, что она уже доступна игроку.

Две игры — общий фундамент

Этот монорепозиторий содержит основную стратегию и самостоятельную PvE-игру во вселенной Averion:

Продукт Направление
Averion: Galactic War Сессионная космическая стратегия: развитие империи, войны и дипломатия, одиночные и сетевые матчи, корпорации.
Averion: Sector Zero Самостоятельная PvE-игра с кампанией, собственным прогрессом и противником — Роем. Использует общее ядро, но не является форком или просто урезанным режимом основной игры.

Историческое название проекта — Void Dominion. Имя репозитория MoonGame, пакеты @void/* и файлы void-dominion*.html пока сохраняют прежние технические идентификаторы. В командах ниже используются реальные имена из репозитория.

Как играется Galactic War

Матч идёт в непрерывном реальном времени, а не по ходам. На работающем сервере перелёты, строительство и бои продолжаются, даже когда игрок отключён. Приказы можно отдавать заранее; в одиночной игре доступны пауза и настройка скорости.

Область Что есть в текущей альфе
Карта и разведка Провинции и маршруты между ними, туман войны, радары, шпионаж и контрразведка. Голографическая карта меняет детализацию при масштабировании.
Экономика и развитие Ресурсы, постройки, производство, исследования с советом учёных, торговля на сессионной бирже.
Флот и армия Корабли с модулями, герои, отдельные наземные дивизии и транспорт, орбитальные бои, бомбардировки и высадка десанта.
Приказы и дипломатия Стоячие приказы, патрулирование, «Хранитель» для делегирования управления ИИ, объявления войны и взаимные соглашения.
Режимы и связь Скирмиш с ботами, командные и сетевые матчи, чат и пинги на карте, интерфейс на русском и английском.
Между матчами Прогрессия командира, арсенал, корпорации и войны корпораций. Кабинет корпорации подключён к серверному API; отдельные разделы ещё дорабатываются.

Подробности механик — в описании игры. Реализация и известные ограничения — в снимке состояния; долгосрочный замысел — в GDD и документе метаигры.

Averion: Sector Zero

Sector Zero развивает отдельную PvE-кампанию: операции, сюжетные миссии, герои и противостояние Рою. Его память, связь и адаптация — часть игрового дизайна, а не просто другое оформление обычного противника.

У игры своя сборка sector-zero.html. Общие правила мира развиваются в общем ядре; миссии и прогресс кампании остаются на стороне Sector Zero. Состояние реализации и планы собраны в роадмапе продукта, устройство Роя — в документе его поведения.

В документах кампании есть сюжетные спойлеры. Сам README не раскрывает развязку.

Быстрый старт для разработки

Инструкции предназначены для участников проекта и пользователей, получивших разрешение правообладателя; условия использования приведены в LICENSE.

Нужны Git, Node.js 22 и pnpm. Версия pnpm закреплена в поле packageManager файла package.json; Corepack использует её из репозитория.

git clone https://github.com/MoonGameTechnology/MoonGame.git
cd MoonGame
corepack enable
pnpm install --frozen-lockfile
pnpm run prototype

Сборка создаёт HTML-файлы в prototype/dist/:

Файл Назначение
void-dominion.html Полный клиент для разработки и плейтестов, включая одиночную игру.
sector-zero.html Отдельная сборка Sector Zero.
void-dominion-player.html Сетевой клиент без одиночного скирмиша, тестового режима и управления ускорением времени.

Для локального знакомства откройте prototype/dist/void-dominion.html или prototype/dist/sector-zero.html в браузере. Для сетевого матча нужен запущенный игровой сервер: статическая публикация HTML его не заменяет.

Локальный сервер и игра по сети

Из корня репозитория:

pnpm host

Команда сама собирает клиент, запускает игровой хост и выводит адреса для подключения. По умолчанию используется порт 8788; локальный адрес — http://localhost:8788/. Хост слушает все сетевые интерфейсы, поэтому адрес из локальной сети можно передать участникам плейтеста.

Это путь для разработки, не готовая конфигурация публичного сервера. Без DATABASE_URL состояние хранится в памяти и теряется при перезапуске. Постоянному сетевому серверу нужны Postgres, аутентификация, HTTPS/WSS и настроенное окружение.

Сценарии приглашения игроков и диагностика — в ранбуке запуска. Docker Compose, TLS, резервное копирование и эксплуатация — в руководстве развёртывания. Команда pnpm stack запускает Compose, но не заменяет подготовку окружения по этому руководству.

Устройство репозитория

Основной стек: TypeScript, pnpm workspaces, Node.js / Fastify / WebSocket, Postgres; для проверок — Vitest и браузерные сценарии Playwright. Android-сборка использует обёртку Capacitor.

packages/
  shared-core/   Детерминированная симуляция и игровые модули
  action-layer/  Валидация, авторизация и порядок действий
  protocol/      Общий сетевой контракт клиента и сервера
  server/        Комнаты матчей, транспорт, хранение и серверные сервисы
  client/        Общие клиентские компоненты, транспорт, рендер и PWA-клиент
prototype/       Текущий игровой клиент, сборки и хост плейтестов
mobile/          Android-обёртка
decisions/      Общие чистые решения для клиентского поведения
data/           Игровые данные и контент
localization/   Тексты интерфейса
deploy/         Развёртывание и эксплуатация
scripts/        Проверки и вспомогательные инструменты
docs/           Дизайн, архитектура, состояние и планы

Название prototype/ историческое: именно здесь находится текущий клиент для игроков. Пакет packages/client развивается рядом с ним, но не подменяет этот вход.

Важно различать серверные точки входа. pnpm host использует prototype/netserver.ts. Dockerfile также собирает и запускает этот хост — как packages/server/dist/proto-server.mjs. Команда pnpm dev:server запускает отдельный вход packages/server/src/main.ts; изменение только этого файла не меняет поведение контейнерного хоста. Подробная навигация — в CODE-MAP.md.

Архитектурные принципы

  • Общее детерминированное ядро. Время и генератор случайных чисел передаются явно; одинаковые входные данные дают одинаковый результат симуляции.
  • Данные и независимые модули. Контент описывается данными, правила расширяются модулями через события, хуки и возможности. Новая механика не требует переписывать всё ядро.
  • Сервер определяет результат. В сетевой игре клиент отправляет намерение, действия проверяются сервером, а игрок получает только разрешённую ему проекцию состояния, включая ограничения тумана войны.

Подробности — в архитектуре, описании модульной системы и обосновании технического стека.

Техническое устройство

Технологии

Слой Технологии Зачем так
Язык TypeScript везде, от ядра до клиента Одно и то же ядро симуляции работает на сервере и в браузере без перевода между языками.
Ядро симуляции Чистый TS, zod для схем данных, свой seeded RNG Детерминизм: время и случайность передаются явно, Math.random() и Date.now() в ядре запрещены линтером.
Сервер Node.js, Fastify (HTTP API), ws (WebSocket), jose (JWT) Сырой ws даёт полный контроль над протоколом и рукопожатием; Fastify держит REST-часть рядом.
Хранилище PostgreSQL + JSONB, драйвер pg без ORM Состояние мира уже JSON и ложится в JSONB без преобразований; транзакции защищают от двойных начислений.
Уведомления web-push, nodemailer Push о событиях матча и письма восстановления пароля.
Клиент Веб-клиент (PWA-first), карта на Canvas 2D Одна кодовая база для браузера и мобильных; общее ядро даёт мгновенный предпросмотр приказа.
Мобильные Capacitor (Android APK) Тонкая нативная обёртка вокруг веб-клиента.
Инфраструктура Docker (distroless-образ, non-root), Docker Compose, Caddy (TLS) Минимальный образ без shell и пакетного менеджера; автоматические сертификаты.
Проверки Vitest, Playwright, ESLint, Prettier Модульные тесты рядом с кодом и сценарии в настоящем браузере.
CI/CD GitHub Actions, cosign, набор сканеров безопасности Гейт на каждый PR, подписанный образ для прода.

Redis, очереди сообщений и микросервисная оркестрация сознательно не используются, пока игра живёт в одном процессе: меньше движущихся частей — меньше точек отказа. Условия, при которых стек расширяется, записаны в ADR стека.

Сетевая архитектура

Браузер / Android (Capacitor)
        │  HTTPS — вход, профиль, список матчей, корпорации, магазин
        │  WSS   — игровой матч в реальном времени
        ▼
Caddy — TLS-терминация, заголовки безопасности
        │
        ▼
Игровой хост (Node.js)
  ├─ Fastify: REST API, статика клиента, /health и /ready
  ├─ ws: соединения матчей, маршрутизация по id матча
  ├─ реестр матчей: много изолированных комнат в одном процессе
  └─ драйвер часов: будит комнату к ближайшему запланированному событию
        │
        ▼
PostgreSQL — снимки матчей, квитанции действий, аккаунты, мета-прогресс

Протокол описан один раз в пакете @void/protocol и импортируется обеими сторонами, поэтому клиент и сервер не могут разойтись в формате сообщений. Клиент получает только типы, серверный код в браузерную сборку не попадает.

Как живёт соединение.

  1. Клиент входит по логину и паролю (POST /auth/login), выбирает матч и занимает место. Сервер выдаёт короткоживущий токен присоединения.
  2. При открытии WebSocket сервер проверяет токен и Origin, привязывает к соединению серверный идентификатор сессии и отправляет welcome с полным состоянием, видимым этому игроку.
  3. Дальше идут дельты: только изменившиеся сущности и поля плюс доменные события. Периодически к дельте прикладывается хеш состояния; клиент сверяет его со своей копией, и при расхождении сервер присылает полный снимок (state).
  4. Приказы клиент шлёт конвертом action.v1: идентификатор сессии, порядковый номер clientSeq, идентификатор действия и намерение. Ответ на отказ — стабильный код ошибки E_* без внутренних деталей.
  5. Пинги на карте, чат и служебные сообщения (ping/pong, отчёт о рассинхроне) идут по тому же сокету отдельными типами сообщений.

Серверная архитектура

Путь одного приказа:

сообщение → разбор и проверка формы (zod)
          → ActionGate: конверт → схема payload → сессия → идемпотентность → порядок clientSeq
          → комната матча: advanceTo(сейчас) → applyAction
          → атомарная запись снимка и квитанции в одной транзакции
          → рассылка: каждому игроку своя дельта с учётом тумана войны
  • Комната матча (MatchRoom) обрабатывает действия строго последовательно. Перед каждым приказом мир досчитывается до текущего момента, затем применяется приказ. Ядро — чистая функция: новое состояние строится на копии, исходное не меняется.
  • Сначала запись, потом рассылка. Результат приказа уходит игрокам только после того, как снимок матча и квитанция действия записаны в PostgreSQL одной транзакцией. Повтор того же действия возвращает сохранённую квитанцию, а не выполняется второй раз.
  • Время без тиков. Ядро продвигает мир событиями: перелёт, стройка или бой — это запись в расписании, а ресурсы начисляются формулой за отрезок времени. Драйвер часов спит до ближайшего события, поэтому простаивающая партия почти не тратит CPU, а мир продолжает жить без подключённых игроков.
  • Много матчей в одном процессе. Реестр держит изолированные комнаты. Матч без подключённых игроков выгружается из памяти и поднимается из базы к своему ближайшему событию или при первом подключении.
  • Туман войны на сервере. Каждый игрок получает свою проекцию состояния: скрытые флоты, постройки и поля в его снимок и дельты не попадают вообще, а не просто не рисуются на карте.
  • Отдельные сервисы. Корпорации и коммерция могут работать отдельными процессами со своими базами. Вызовы к ним идут через общий предохранитель зависимостей, поэтому отказ сервиса корпораций не останавливает матчи.
  • Наблюдаемость. Пробы /health и /ready для оркестратора, метрики для оператора закрыты токеном, журнал событий безопасности пишется отдельным потоком.

Действующий сервер для игроков собирается из prototype/netserver.ts (в образе — как packages/server/dist/proto-server.mjs) поверх компонентов packages/server.

Безопасность

Ниже — общие принципы и меры, которые уже работают в коде. Подробные результаты аудитов в публичный README не выносятся.

  • Авторитетный сервер. Клиент присылает намерение, а не состояние. Каждый приказ проходит проверку схемы, принадлежности сессии и игровых правил на сервере; результат боя, экономики и наград считает только сервер.
  • Античит через детерминизм. Одинаковые входы дают одинаковый результат, поэтому спорную ситуацию можно воспроизвести на тех же данных. Расхождение хеша состояния у клиента фиксируется как сигнал.
  • Идемпотентность и порядок. Квитанции действий хранятся долговременно, номер clientSeq строго растёт в пределах сессии: повтор или подмена порядка не дают второго списания или начисления.
  • Безопасный отказ. Любая ошибка — это отказ со стабильным кодом; внутренние детали остаются в серверных логах.
  • Аккаунты. Пароли хранятся как хеши scrypt; сессии и токены присоединения — подписанные JWT с проверкой срока. Смена пароля отзывает выданные ранее сессии. Письма сброса пароля ограничены по частоте.
  • Ограничения нагрузки. Лимиты частоты запросов к HTTP API, ограничение числа WebSocket-соединений с одного адреса, предел размера сообщения (с учётом распаковки сжатых кадров), квота на создание матчей.
  • Веб-защита. Список разрешённых Origin для WebSocket, заголовки безопасности и Content Security Policy на статике и API, HTTPS/WSS через Caddy.
  • Контейнер. Distroless-образ, процесс без root, базовые образы закреплены по дайджесту.
  • Цепочка поставки. Каждый PR проверяют Semgrep, CodeQL, Trivy, OSV-Scanner, Gitleaks, TruffleHog и zizmor (они же раз в неделю прогоняются по main). Образ для прода не публикуется, если Trivy находит уязвимость с доступным исправлением; иначе он публикуется в GHCR и подписывается cosign без долгоживущих ключей; перед запуском хост проверяет подпись.

Модель угроз и подход — в документе по угрозам, дорожной карте честности игры и описании пайплайна. Как сообщить об уязвимости — в SECURITY.md.

Сборка, CI и выпуск

Workflow Что делает
ci.yml pnpm run check и тесты с настоящим PostgreSQL на каждый PR и в очереди слияния.
security.yml Сканеры безопасности на PR и еженедельно по main.
image.yml Сборка образа сервера, Trivy, публикация в GHCR, подпись cosign.
android.yml Сборка Android APK через Capacitor.
pages.yml Публикация браузерной сборки на GitHub Pages.
automerge.yml Постановка готовых зелёных PR в очередь слияния.

main защищён: изменения попадают туда только через PR с зелёным CI и merge queue.

Проверки и рабочий процесс

Команда Назначение
pnpm run check Основной гейт: ESLint, проверка типов, тесты и целостность документации.
pnpm test Тесты Vitest.
pnpm run prototype Сборка игровых HTML-файлов.
pnpm run smoke:browser Проверка клиента в настоящем браузере.
pnpm run smoke:sector-zero Браузерные сценарии Sector Zero и ракетных мин.
pnpm run site Сборка и подготовка публичной статики в prototype/dist/site/.
pnpm doctor Диагностика подключения к игровому хосту.

Для браузерных проверок нужен Chromium; подготовка окружения описана в CONTRIBUTING.md. Проверки с Postgres требуют тестовую базу; CI поднимает её как сервис. Счётчики тестов и модулей не дублируются здесь — они живут в снимке состояния.

Изменения оформляются отдельным PR в main. Обязательные проверки выполняет CI; постановкой готовых PR в очередь слияния управляет штатный workflow репозитория. Правила участия — в CONTRIBUTING.md, инженерные ограничения — в CLAUDE.md, порядок работы агента — в AGENTS.md.

Куда читать дальше

Задача Документ
Узнать, что реализовано и что ограничено Готовность · Состояние проекта
Понять, что держит выход к игрокам Путь к выпуску
Найти документ по теме Индекс документации
Найти нужную часть кода Карта кода
Выбрать следующую задачу Роадмап · Бэклог
Разобраться с сетевой игрой Мультиплеер · Запуск
Выкатывать сервер без ручных касаний Zero Touch Prod
Разобраться с клиентами и платформами Кросс-платформенный клиент
Проектировать корабли, персонажей, здания и визуальный стиль Художественный фундамент PvP-игры
Работать над PvE-игрой Sector Zero

Права на проект

© 2026 Moonwuk Games. Все права защищены.

Проект проприетарный. Публичность репозитория не означает открытую лицензию на код, игровые данные, изображения или документацию. Условия и ограничения — в LICENSE.

Releases

Packages

Used by

Contributors

Languages