Files
TheDeclineOfWarriors/docs/architecture/mvp-world-authority-navmesh.md
T
Alexander Borisov 36c67558dd document runtime navmesh architecture decisions
Fix the authority and world-state assumptions before implementation so runtime NavMesh work can stay consistent with the project's future DI and peer-host multiplayer model.
2026-04-08 01:47:31 +03:00

220 lines
15 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.
# MVP World, Authority And Runtime NavMesh
## Status
Этот документ считается каноническим для решений по детерминированному миру, authority model и runtime NavMesh, пока его явно не заменят более новым архитектурным решением.
## Purpose
Зафиксировать долгосрочные решения для MVP, чтобы downstream-задачи по FishNet, worldgen, AI и persistence не уехали в разные стороны.
## Scope
- deterministic voxel world generation
- authority model для session gameplay
- runtime NavMesh в procedural world
- риски WebGL-host режима
## Fixed Decisions
### 1. Базовый мир генерируется детерминированно и локально на каждом peer
Решение:
- базовая геометрия мира не стримится от хоста по сети
- каждый peer генерирует чанк локально из одинакового `seed`, одинакового `VoxelWorldConfig` и одинаковой версии world rules
Почему выбрано:
- для WebGL и peer-host модели это минимизирует сетевой трафик
- убирает постоянную сетевую репликацию геометрии чанков
- снимает с хоста роль единственной точки генерации базового мира
- хорошо сочетается с уже существующим `VoxelWorldGenerator`, который строит чанк из deterministic inputs
Почему не выбран host-generated world streaming:
- хост получал бы лишнюю CPU-нагрузку на генерацию и лишнюю сетевую нагрузку на раздачу чанков
- late join и догрузка дальних областей становились бы тяжелее по сети
- это хуже укладывается в бюджет WebGL-host
Последствия:
- `seed`, world config и их версия становятся частью session handshake
- любое расхождение по config/version между peers недопустимо и должно считаться protocol drift
### 2. Host остается authoritative для NPC, AI и другого gameplay state
Решение:
- NPC симулируются на хосте
- pathfinding NPC, агро, боевые решения и каноническое положение NPC принадлежат хосту
- клиенты получают состояние NPC по сети и могут делать только визуальное сглаживание
Почему выбрано:
- NPC влияют на бой, урон, столкновения и progression, значит их нельзя отдавать в authority случайному клиенту
- это радикально снижает риск читов и эксплуатационных багов
- упрощает late join, reconnect и дебаг сетевой симуляции
Почему не выбран client-owned NPC:
- ownership у первого встретившего игрока нестабилен при совместной игре
- миграция owner во время боя ломает воспроизводимость path state, aggro state и hit timing
- возрастает риск desync и эксплойтов
- резко усложняется отладка и сопровождение
Последствия:
- `client-authority` допустим только для ввода игрока и только при отдельной валидации на сервере
- для NPC authority migration в MVP не используется
### 3. У чанков нет owner и нет chunk ownership migration
Решение:
- чанк не закрепляется за конкретным игроком как за владельцем
- базовый чанк является общей детерминированной сущностью мира, а не network-owned объектом
Почему выбрано:
- при deterministic world generation ownership чанка не дает полезного выигрыша
- chunk ownership добавляет coordination cost, миграцию ответственности и новые классы сетевых гонок без пользы для MVP
- это плохо совместимо с late join и с будущими world deltas
Почему не выбран owner-per-chunk:
- первый увидевший чанк игрок не является надежным authority source
- потребуется сложная логика передачи владения при сближении игроков и при disconnect
- любые расхождения по владельцу чанка приводят к hidden state drift
Последствия:
- изменения чанка в будущем пойдут не через owner migration, а через authoritative world deltas от хоста
### 4. Runtime NavMesh строится локально на каждом peer по фактической локальной геометрии чанка
Решение:
- NavMesh не реплицируется по сети как data blob
- каждый peer строит NavMesh у себя локально из актуальной локальной геометрии мира
- NavMesh всегда считается производным кэшем от world state, а не каноническим состоянием сессии
Почему выбрано:
- NavMesh data тяжелая и плохо подходит для сетевой репликации в peer-host модели
- при deterministic base world и одинаковых world deltas peers могут независимо прийти к одинаковой walkable topology
- это сохраняет сеть для gameplay state, а не для производных навигационных артефактов
Почему не выбран network-streamed NavMesh:
- лишний трафик и высокая сложность синхронизации
- плохая масштабируемость для догрузки чанков и late join
- NavMesh все равно пришлось бы пересобирать при локальных изменениях геометрии
Последствия:
- каноничность gameplay не должна зависеть от клиентского NavMesh
- client NavMesh используется для локальных потребностей, но authoritative decisions по NPC остаются у хоста
### 5. Будущие изменения проходимости мира передаются как authoritative world deltas
Решение:
- базовый мир идет из deterministic generation
- любые будущие баррикады, спеллы, разрушаемость, carve и другие изменения мира передаются как authoritative deltas от хоста
- после применения delta каждый peer локально перестраивает затронутые nav regions
Почему выбрано:
- это отделяет immutable base generation от mutable session state
- обеспечивает late join: новому игроку можно отдать base seed/config и журнал world deltas
- не требует вводить ownership migration для чанков
Почему не выбран fully local mutable world:
- local-first изменения мира не могут быть каноническими в кооперативной сетевой игре
- конфликтуют с античитом, late join и persistence
Последствия:
- NavMesh pipeline обязан уметь маркировать локальные nav regions как dirty после world delta
### 6. NavMesh pipeline должен работать в single-thread budget; многопоточность в WebGL считается только опциональным ускорением
Решение:
- архитектура runtime NavMesh не должна зависеть от наличия потоков
- базовый режим должен укладываться в бюджет кадра на одном потоке
- если deployment позже подтвердит поддержку `SharedArrayBuffer` и `COOP/COEP`, можно добавить threaded optimization, но не делать ее обязательной
Почему выбрано:
- WebGL-host остается одной из целевых платформ
- WebGL multithreading требует специальных заголовков и эксплуатационной дисциплины на стороне хостинга
- завязка critical gameplay pipeline на эту инфраструктуру слишком рискованна для MVP
Почему не выбран threaded-only pipeline:
- он может работать в editor/desktop и развалиться в реальном WebGL deployment
- создаст ложное ощущение приемлемого бюджета, которого не будет на production-hosting
Последствия:
- rebuild должен быть incremental, throttled и bounded
- полносценовый bake вокруг камеры не подходит как каноническая модель
### 7. Первая итерация NavMesh покрывает область вокруг player actor, но долгосрочный контракт расширяется до players + active NPC
Решение:
- для первой проверки гипотезы build priority привязывается к player actor
- целевой контракт для multiplayer host: nav coverage должна учитывать игроков и активных NPC
Почему выбрано:
- это минимальный объем для MVP-проверки без ранней переплаты за сложную interest model
- при этом заранее фиксируется, что player-only coverage не является конечной архитектурой
Почему не выбран camera-driven center:
- камера не является каноническим gameplay actor
- в multiplayer и especially on host камера может не совпадать с зоной активной симуляции
- привязка к `Camera.main` ломает переносимость решения из test scene в сетевую сессию
Последствия:
- в коде нельзя оставлять `Camera.main` как канонический источник world/nav interest
- target должен представлять actor-level interest, а не presentation-level camera
### 8. Для MVP поддерживается один тип NavMesh agent
Решение:
- сейчас поддерживается только один `agentTypeID`
Почему выбрано:
- проект на стадии hypothesis/MVP
- это уменьшает стоимость runtime bake и настройки AI Navigation
- не раздувает матрицу тестирования до появления реальной необходимости
Почему не выбран multi-agent bake сразу:
- рост CPU и memory costs
- усложнение отладки при почти нулевой текущей пользе
Последствия:
- при появлении разных классов существ нужно отдельно пересмотреть agent taxonomy
### 9. В этой фазе решение остается scene-local и не привязывается к VContainer или Addressables
Решение:
- runtime NavMesh реализуется как часть текущего scene-local world runtime
- VContainer и Addressables в этой задаче не вводятся
Почему выбрано:
- в проекте пока нет production-ready composition root поверх gameplay world
- принудительное добавление DI boundary сейчас даст больше шума, чем пользы
- Addressables не подключены и не требуются для гипотезы NavMesh generation
Почему не выбран ранний DI/bootstrap refactor:
- это отвлекает от основной гипотезы по производительности и корректности NavMesh
- возникает преждевременная архитектурная сложность при еще нестабильных правилах мира
Последствия:
- код должен оставаться достаточно изолированным, чтобы позже его можно было вынести в runtime service
## Long-Term Risks
### Critical
- WebGL-host может не выдержать одновременно world streaming, runtime NavMesh rebuild и server-authoritative NPC AI.
- Любой drift по `seed`, `VoxelWorldConfig` или world rules между peers приведет к расхождению геометрии и локального NavMesh.
### High
- Цель в `50` активных NPC может упереться не в один subsystem, а в суммарный CPU budget хоста.
- Будущие изменения геометрии потребуют точной invalidation strategy по nav regions; без нее rebuild cost быстро выйдет из-под контроля.
- Если client movement в будущем начнет опираться на локальный NavMesh как на authority source, появятся расхождения с host simulation.
### Medium
- Late join требует не только `seed/config`, но и корректного воспроизведения authoritative world deltas.
- Если region size выбрать слишком крупным, rebuild будет дорогим; если слишком мелким, возрастет число build operations и seam-risk на границах.
## Downstream Implications
- `TASK-0001`: этот документ закрывает часть канонических MVP-решений по world/authority/navmesh.
- `TASK-0002`: session handshake должен включать world seed, config/version и protocol compatibility checks.
- `TASK-0012`: enemy AI проектируется только как host-authoritative.
- `TASK-0023`: runtime NavMesh обязан быть local-build, throttled и без camera-driven assumptions.