146 lines
11 KiB
Markdown
146 lines
11 KiB
Markdown
# Город сверху — генератор OSM и клиент-серверная симуляция
|
||
|
||
Добавлен серверный режим по [плану](docs/PLAN.md): подготовленные города,
|
||
комнаты до 30 наблюдателей, жители по расписанию, общий календарь и голосования,
|
||
сохранения и очередь генерации. Браузерный генератор ниже остаётся режимом отладки.
|
||
|
||
## Сетевая игра
|
||
|
||
Нужны Node.js 22+ и Rust stable (на Windows — установленный MSVC linker).
|
||
Запускать команды из корня репозитория:
|
||
|
||
```bash
|
||
npm ci
|
||
npm run demo # готовый город из локального образца OSM, без запросов к Overpass
|
||
npm run build
|
||
npm run server:dev # http://localhost:3000/?play
|
||
```
|
||
|
||
В списке выберите Бальцерс, задайте ник и создайте комнату. Другие игроки входят
|
||
в ту же комнату из списка. Кнопка «Создать город на сервере» открывает выбор
|
||
области и запускает отдельную задачу генерации с прогрессом.
|
||
|
||
Можно экспортировать уже готовый мир и открыть только статику без симуляции:
|
||
|
||
```bash
|
||
npm run export-city -- world.json public/cities/my-city
|
||
# http://localhost:3000/?city=/cities/my-city/manifest.json
|
||
```
|
||
|
||
Экспорты не перезаписываются: новая версия города получает новый каталог.
|
||
Настройки, API, ограничения LOD и описание сохранений находятся в
|
||
[server/README.md](server/README.md).
|
||
|
||
Проверки: `npm run typecheck`, `npm test`, `npm run server:test`,
|
||
`npm run server:load`. Изменение протокола: `npm run proto:generate`.
|
||
|
||
## Браузерный генератор для отладки
|
||
|
||
Выделяете на карте небольшой город или район → по данным OSM строится подробная карта
|
||
с видом строго сверху: дороги реальной ширины с тротуарами и разметкой, парковки
|
||
с машинами, деревья, и **у каждого здания — этажи, комнаты, двери, окна, лестницы
|
||
и мебель**, нарисованные простыми геометрическими фигурами, как на плане квартиры.
|
||
|
||
В отладочном режиме всё работает в браузере: данные берутся из Overpass API, генерация
|
||
идёт в Web Worker'ах, готовый мир сохраняется в IndexedDB.
|
||
|
||
Машины появляются только на парковках и в гаражах; вдоль улиц они не генерируются.
|
||
|
||
## Запуск
|
||
|
||
Нужен Node.js 18+.
|
||
|
||
```bash
|
||
npm install
|
||
npm run dev # http://localhost:5173/ (пересборка на лету)
|
||
npm run build # сборка в dist/ — можно положить на любой статический хостинг
|
||
npm run typecheck
|
||
```
|
||
|
||
Для автоматических проверок сетевого клиента нужен Node.js 22+: `npm test`.
|
||
Тесты проверяют таймауты, переключение серверов и отмену без обращения к сети.
|
||
|
||
Данные сначала запрашиваются у `maps.mail.ru`, затем у `overpass-api.de` и
|
||
`overpass.private.coffee`. На каждый запрос отводится 45 секунд, включая загрузку
|
||
ответа; после ошибки или таймаута используется следующий сервер. Лимит обработки
|
||
запроса на стороне Overpass — 30 секунд. Кнопка «Отмена» прерывает запрос и ожидание
|
||
перед повтором.
|
||
|
||
Без интернета можно проверить на образце: «Другие способы» → «Сгенерировать из выгрузки
|
||
Overpass» → `samples/balzers-2013.json` (Бальцерс, Лихтенштейн, данные OSM 2013 года).
|
||
|
||
Генерация из файла без браузера (для отладки генератора):
|
||
|
||
```bash
|
||
npm run cli -- samples/balzers-2013.json 47.058 9.492 47.074 9.518 world.json
|
||
```
|
||
|
||
## Управление
|
||
|
||
- перетаскивание — сдвиг, колесо / щипок — масштаб, двойной клик — приблизить;
|
||
- справа — этаж для всей карты (⌂ — крыши), `PgUp`/`PgDn` или `[` `]`;
|
||
- клик по зданию — карточка: вид, этажность (из OSM или оценка), квартиры, спальные места,
|
||
свой переключатель этажей только для этого здания;
|
||
- «Экспорт мира» в отладочном режиме — весь мир одним файлом `.json.gz`; `export-city` преобразует его в серверный тайловый формат.
|
||
|
||
## Как устроена генерация
|
||
|
||
```
|
||
Overpass JSON ─► city.ts ──────────────► зоны, дороги, контуры зданий, деревья, парковки
|
||
│ classify.ts вид здания (по тегам, POI внутри, landuse, площади) и этажность
|
||
▼
|
||
interior.ts (в воркерах) ─► этажи: сетка 0.5 м в осях здания
|
||
│ схема: секции с подъездами | коридор | простая раскладка
|
||
│ деление на комнаты по программе (м²), несколько попыток с оценкой
|
||
│ двери = остовное дерево по графу смежности, санузлы и спальни — тупики
|
||
│ вход с фасада к дороге, окна с шагом по типу здания
|
||
▼
|
||
furnish.ts + catalog.ts ──► мебель по правилам для каждого типа комнаты
|
||
▼
|
||
finalize.ts ──────────────► общие модели предметов, округление до 1 см
|
||
```
|
||
|
||
- **Сид** здания = OSM-id ⊕ сид мира — один и тот же город всегда генерируется одинаково.
|
||
- Многоквартирные дома — **секционные**: подъезд с лестницей (и лифтом от 5 этажей),
|
||
площадка, 1–4 квартиры вокруг неё; на первом этаже — проход к входу, у домов с магазинами
|
||
вместо квартир магазины со своими входами с улицы.
|
||
- Офисы, школы, больницы, гостиницы — **коридорная** схема.
|
||
- Дома, магазины, кафе, цеха, склады, храмы, гаражи — **простая** раскладка
|
||
(у гаражных рядов — отдельные боксы с воротами).
|
||
|
||
## Модель данных мира (`src/types.ts`)
|
||
|
||
Статические данные уже используются сервером; для дальнейшего игрового слоя предусмотрены:
|
||
|
||
| Что | Зачем потом |
|
||
|---|---|
|
||
| `Door.rooms = [комната, комната \| 'outside']` | рёбра графа навигации внутри здания |
|
||
| `Stairs` (одно место на всех этажах, `up`/`down`), лифты | переходы между этажами |
|
||
| `Unit` — квартира / магазин / офис с `roomIds` и `beds` | домохозяйства и рабочие места для жителей |
|
||
| `Prop.blocksMove`, `Prop.blocksSight`, `tags` (`sleep:2`, `sit:4`, `work`, `cook`, `storage`…) | коллизии, линия обзора, что агент может сделать с предметом |
|
||
| `Wall` с разрывами под двери и окна, `Window` | коллизии и видимость (окна прозрачны для взгляда) |
|
||
| `Road` с шириной, тротуарами, `oneway`, слоями | граф улиц для перемещения по городу |
|
||
| все объекты с `id` | хранение состояния: открытая дверь, взятый предмет |
|
||
|
||
Координаты — метры в локальной проекции вокруг центра области (x — восток, y — юг).
|
||
|
||
## Ограничения MVP
|
||
|
||
- Область до 25 км²; предупреждение о времени генерации — свыше 10 км².
|
||
Скорость и расход памяти зависят от плотности застройки и этажности.
|
||
Публичные серверы Overpass рассчитаны на умеренную нагрузку; для
|
||
публичной игры понадобится своё зеркало или заранее нарезанные данные (например, экстракт
|
||
Geofabrik → статические файлы).
|
||
- Подвалы, мансарды, балконы, береговая линия морей пока не генерируются.
|
||
- Нестандартные контуры (сильно изломанные) дают менее аккуратные планировки.
|
||
|
||
## Данные и лицензии
|
||
|
||
Данные карты © участники OpenStreetMap, лицензия ODbL. Если вы распространяете
|
||
сгенерированные миры, укажите «© OpenStreetMap contributors». Тайлы на экране выбора
|
||
области — стандартные тайлы OSM по их [правилам использования](https://operations.osmfoundation.org/policies/tiles/);
|
||
поиск — Nominatim (не чаще раза в секунду).
|
||
|
||
Идеи частично подсказаны проектом [KnoxMap](https://github.com/spytheeuclidean-a11y/knoxmap);
|
||
код написан с нуля.
|