Files
citygen/server/README.md
T

8.3 KiB
Raw Blame History

Сервер симуляции

Из корня репозитория: npm run server:dev, затем открыть http://localhost:3000/?play. Нужны Node.js 22+ и Rust stable с системным компилятором/linker. Обёртка также находит локальную установку в .tools/.

axum обслуживает клиент, каталог, очередь генерации и бинарный WebSocket. Каждая активная комната владеет отдельным bevy_ecs::World в своём потоке. Симуляция работает на 10 Гц, репликация — на 5 Гц. Один реальный шаг соответствует шести игровым секундам при скорости ×1.

Жители идут по дорожному графу между ближайшими к дому и работе узлами утром и возвращаются вечером. Если в OSM нет подходящих домов/рабочих мест, используются демонстрационные маршруты по связным дорогам. Интерьерная геометрия, двери, лестницы и слоты загружаются по области наблюдения; детальный поиск пути на этаже учитывает стены, проёмы и мебель. Перемещение жителей между этажами и использование мебели относятся к игровому слою.

Далёкие маршруты обновляются раз в десять реальных секунд. Положение при подписке вычисляется точно из календаря. AOI ограничен 2×2 км, снимок — 1000 жителями по умолчанию; клиент увеличивает LOD при переполнении. Плотные области показывают стабильную выборку жителей. Репликация ограничена 90 КБ/с на клиента с запасом 180 КБ на начальный снимок; пропущенные дельты объединяются.

Ник уникален в комнате, сессия выдаётся сервером. Пауза и скорости 1/2/4 принимаются большинством более половины подключённых игроков. Голосование длится 20 с; интервал предложений игрока — 30 с. Владелец и привилегии создателя отсутствуют. Создание ограничено одним новым городом и одной новой комнатой с IP в минуту (независимые лимиты). Повторный запрос той же области возвращает уже принятую задачу без расхода лимита. Отказ 429 содержит Retry-After и retryAfterSeconds с оставшимся временем ожидания.

Снимки Protobuf кодируются и записываются отдельным ограниченным по очереди потоком, атомарно заменяются и ротируются; голоса и подключения не сохраняются. При старте восстанавливается каталог комнат, World загружается при первом подключении. Изменившийся манифест блокирует восстановление с понятной ошибкой. Новые экспорты содержат SHA-256 тайлов и навигационного индекса; существующий каталог города не перезаписывается.

Переменные окружения:

  • CITYGEN_BIND: 127.0.0.1:3000.
  • CITYGEN_CITIES: public/cities; CITYGEN_SAVES: data/rooms.
  • CITYGEN_MAX_ROOMS: 5; CITYGEN_AGENTS: 1000, максимум 1000000.
  • CITYGEN_MAX_VISIBLE: 1000, максимум 5000; CITYGEN_SIM_THREADS: до четырёх CPU по умолчанию, общий пул ECS на процесс.
  • CITYGEN_EMPTY_TIMEOUT: 300 с; CITYGEN_SAVE_INTERVAL: 60 с.
  • CITYGEN_KEEP_SNAPSHOTS: 3.
  • CITYGEN_SAVE_QUOTA_BYTES: 2147483648 (2 ГиБ, включая временный снимок).
  • CITYGEN_ADMIN_TOKEN: пусто; для включения API требуется минимум 32 символа.
  • CITYGEN_MAX_GENERATION_KM2: 25; CITYGEN_MAX_BUILDINGS: 10000.
  • CITYGEN_GENERATION_WORKERS: 2; CITYGEN_GENERATION_QUEUE: 8.
  • CITYGEN_GENERATION_TIMEOUT: 600 с.
  • CITYGEN_OSM_FIXTURE: путь к локальной выгрузке Overpass для офлайн-проверки очереди; по умолчанию используется Overpass API.

Очередь запускает TS-генератор отдельным Node-процессом. CreateCity и CityJob из общей схемы передаются по HTTP как application/x-protobuf. Каталог и создание комнаты используют JSON. Задания очереди не переживают перезапуск; готовые города и снимки комнат сохраняются на диске. Ссылка /?create-city&job=ID возобновляет ожидание после обновления страницы. Серверные запросы Overpass используют User-Agent приложения и таймаут 90 с (браузерный отладочный генератор — 45 с). Прогресс включает выбранный сервер и повторные попытки; технический stderr воркера остаётся в логах сервера.

/health проверяет доступность; /metrics отдаёт число игроков/комнат, тик, время последнего и максимального шага, число сущностей и байты очереди рассылки каждой комнаты в формате Prometheus. Медленные тики и ошибки снимков идут в stderr. При Ctrl+C сервер останавливает комнаты с сохранением.

Проверки: npm run server:test, npm run server:load. Второй стенд использует миллион жителей, 4096 синтетических маршрутов и 30 небольших областей наблюдения, включая кодирование полных снимков как верхнюю оценку трафика. Он не моделирует RTT, диск, браузеры или плотную толпу в одной точке. Отдельный интеграционный тест подключает 30 настоящих WebSocket-клиентов к 1000 жителей.

Настоящая нагрузка на выбранный город: запустить npm run server:release с CITYGEN_AGENTS=1000000, затем npm run server:bots -- http://localhost:3000 balzers-demo 20. Боты создают комнату, подключаются, подписываются на 30 областей, адаптируют LOD и выводят трафик, выборку длительности тиков и ошибки соединений.

Compose, постоянные тома, лимиты, healthcheck и профиль Prometheus описаны в deploy/README.md.

Совместимость сохранений

Снимки v3 загружаются вместе с прежними v1/v2. Удалённые поля городской экономики отбрасываются; жители, маршруты, время и seed сохраняются. Общегородская казна, запасы, усреднённые потребности и массовые команды удалены. Пауза и скорость по-прежнему принимаются голосованием. Квота снимков и администрирование продолжают работать.