Files
citygen/server/README.md
T

100 lines
9.3 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.
# Сервер симуляции
Из корня репозитория: `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 в минуту.
Снимки 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. Задания очереди не переживают
перезапуск; готовые города и снимки комнат сохраняются на диске.
`/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](../deploy/README.md).
## Игровой слой
Голод, усталость и настроение моделируются как усреднённые показатели
населения комнаты. Они меняются по игровому календарю независимо от камеры.
Сон ночью восстанавливает силы; питание трижды в день тратит запасы еды.
Голод и усталость снижают производство и доход казны в рабочие часы.
Почасовые события (урожай, болезнь, дождь) детерминированы seed и временем.
История ограничена 16 событиями. Это базовая экономика общего города;
индивидуальные кошельки, машины и детальное использование мебели не включены.
Все игроки имеют одинаковые права на три команды: покупка запасов
(2 единицы казны на жителя), общий обед (1), отдых (3). Цена списывается
при приёме, действие исполняется в следующую игровую минуту. Сервер проверяет
ресурсы, паузу, очередь (до 8), общий интервал 60 игровых минут и интервал
сессии 30 реальных секунд. Общий интервал переживает переподключение.
Пауза и скорость по-прежнему требуют большинства голосов.
Снимки v2 сохраняют экономику, потребности, историю, очередь и общий интервал.
Для v1 игровой слой инициализируется по числу жителей и сохранённому времени;
позиции, seed и расписания сохраняются. Неизвестные версии не перезаписываются.
Квота проверяется под общей блокировкой писателей комнат; при нехватке места
прежние снимки остаются. Один снимок ограничен 128 МиБ.
`/?admin` и API с Bearer-токеном показывают каталог, ошибки, квоту
и позволяют сохранить активную комнату.