Merge branch 'master' of ssh://git.horooko.com:2222/horooko/TheDeclineOfWarriors into feature/attrubute-system-gdd

# Conflicts:
#	docs/tasks/Index.md
#	docs/tasks/items/TASK-0027.md
This commit is contained in:
2026-04-09 16:14:38 +07:00
54 changed files with 4045 additions and 86 deletions
+4 -2
View File
@@ -62,8 +62,10 @@
| TASK-0020 | BackLog | High | security | unassigned | 1d | docs/tasks/items/TASK-0020.md | Добавить серверные ограничения и валидации против читов и некорректных клиентских команд. |
| TASK-0021 | ToDo | High | architecture | unassigned | 2d | docs/tasks/items/TASK-0021.md | Привести проект в порядок: разнести код по asmdef, навести структуру Editor/Runtime и добавить базовые автотесты. |
| TASK-0022 | ToDo | Highest | worldgen | unassigned | 1d | docs/tasks/items/TASK-0022.md | Интегрировать спавн врагов в VoxelWorldGenerator: спавнить по загрузке чанка и учитывать kill-state. |
| TASK-0023 | InProgress | Highest | ai | abysscion | 2d | `docs/tasks/items/TASK-0023.md` | Реализовать runtime NavMesh bake для voxel-чанка и интегрировать обновление навигации при загрузке/изменении чанков. |
| TASK-0023 | Done | Highest | ai | abysscion | 2d | `docs/tasks/items/TASK-0023.md` | Реализовать runtime NavMesh bake для voxel-чанка и интегрировать обновление навигации при загрузке/изменении чанков. |
| TASK-0024 | ToDo | Highest | art | unassigned | 2d | docs/tasks/items/TASK-0024.md | Заменить Minecraft-placeholder арт на легальные ассеты для продакшена и зафиксировать источник/лицензии. |
| TASK-0025 | ToDo | Highest | build | unassigned | 1d | docs/tasks/items/TASK-0025.md | Описать и зафиксировать flow локального теста билда: сборка, запуск, host/client сценарий и обязательный smoke checklist. |
| TASK-0026 | BackLog | High | ui | unassigned | 2d | docs/tasks/items/TASK-0026.md | Реализовать миникарту и механизм сохранения открытой карты у хоста так, чтобы состояние миникарты было общим для всех игроков мира. |
| TASK-0027 | ToDo | Highest | gameplay-core | unassigned | 1d | docs/tasks/items/TASK-0027.md | Реализовать пять канонических атрибутов, их derived combat scaling и интеграцию с классами Воина, Мага и Лучника. |
| TASK-0027 | ToDo | Highest | gameplay-core | unassigned | 3d | docs/tasks/items/TASK-0027.md | Перевести player movement на host-authoritative NavMesh pipeline с server-side path planning и shared debug path preview для всех клиентов. |
| TASK-0028 | Done | Highest | ai | unassigned | 2d | docs/tasks/items/TASK-0028.md | Перевести основной runtime pathing mode на interest-cluster-based coverage windows, чтобы убрать seam-разрывы region-based NavMesh и учитывать multiplayer interest set. |
| TASK-0029 | ToDo | Highest | gameplay-core | unassigned | 1d | docs/tasks/items/TASK-0027.md | Реализовать пять канонических атрибутов, их derived combat scaling и интеграцию с классами Воина, Мага и Лучника. |
+9 -2
View File
@@ -6,12 +6,14 @@ priority: Highest
area: ai
owner: abysscion
created: 2026-03-31
updated: 2026-04-07
updated: 2026-04-08
execution_time: 2d
depends_on:
- TASK-0003
canonical_docs:
- docs/tasks/Index.md
- docs/architecture/mvp-world-authority-navmesh.md
- docs/plans/TASK-0023-runtime-navmesh-implementation-plan.md
related_files:
- Assets/Features/VoxelWorld/Runtime/VoxelWorldGenerator.cs
---
@@ -91,7 +93,12 @@ AI врагов (`TASK-0012`) опирается на NavMesh. Воксельн
## Decision Log
- `2026-03-31` - runtime bake вынесен в отдельную задачу как prerequisite для enemy NavMesh AI.
- `2026-04-08` - runtime NavMesh sidecar реализован через contracts + DI + MessagePipe, а базовый local-build pipeline переведен на clustered coverage windows отдельной follow-up задачей.
## Handoff Notes
Если в проекте нет пакета NavMeshComponents, возможно придется добавить его или реализовать минимальный runtime builder.
Реализация задачи должна идти с учетом принятых решений и уже проведенного ресерча в `docs/architecture/mvp-world-authority-navmesh.md`, `docs/plans/TASK-0023-runtime-navmesh-implementation-plan.md` и текущего runtime-контекста `Assets/Features/VoxelWorld/Runtime/VoxelWorldGenerator.cs`. Если формулировки task-card расходятся с каноническими решениями и зафиксированным ресерчем, приоритет у этих файлов.
Если в проекте нет пакета NavMeshComponents, возможно придется добавить его или реализовать минимальный runtime builder.
Задача закрыта как базовый infrastructural milestone. Дальнейшие улучшения pathing, player navigation и coverage policy должны идти отдельными задачами, а не переоткрывать этот базовый runtime NavMesh foundation.
+439 -75
View File
@@ -1,127 +1,489 @@
---
id: TASK-0027
title: Реализовать систему атрибутов и интеграцию с классами
summary: Ввести пять канонических атрибутов персонажа, их derived combat scaling и привязать классы Воина, Мага и Лучника к своим стартовым и приоритетным статам.
title: Host-authoritative player navigation с shared debug path preview
summary: Перевести player movement на host-authoritative NavMesh pipeline с server-side path planning, authoritative path following и общим debug path preview для всех клиентов.
priority: Highest
area: gameplay-core
owner: unassigned
created: 2026-04-09
updated: 2026-04-09
execution_time: 1d
created: 2026-04-08
updated: 2026-04-08
execution_time: 3d
depends_on:
- TASK-0007
- TASK-0002
- TASK-0023
canonical_docs:
- docs/tasks/Index.md
- docs/gameplay/attribute-system-gdd.md
- docs/gameplay/attribute-reference.md
- docs/gameplay/stat-catalog-mvp.md
- docs/gameplay/combat-resolution-gdd.md
- docs/architecture/mvp-world-authority-navmesh.md
- docs/plans/TASK-0023-runtime-navmesh-implementation-plan.md
related_files:
- Assets/Features/
- Assets/Scripts/
- Assets/Scripts/Players/PlayerMoving.cs
- Assets/Features/VoxelWorld/Prefabs/TestPlayer.prefab
- Assets/Features/VoxelWorld/Scenes/VoxelWorldTestScene.unity
- Assets/Features/VoxelWorld/Runtime/VoxelWorldGenerator.cs
- Assets/Features/VoxelWorld/Contracts/NavMeshWorldContracts.cs
- Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshService.cs
---
# TASK-0027 - Реализовать систему атрибутов и интеграцию с классами
# TASK-0027 - Host-authoritative player navigation с shared debug path preview
## Status
Статус задачи ведется в `docs/tasks/Index.md` и является каноническим там.
Допустимые значения статуса:
- `BackLog`
- `ToDo`
- `InProgress`
- `Review`
- `Done`
## Why
Combat core и классовая система пока не имеют канонической runtime-модели атрибутов. Без этого классы останутся набором стартовых исключений, а боевые формулы не получат устойчивую точку расширения для билдов, оружия и навыков.
Если игрок тоже должен двигаться по NavMesh, текущий local/client-authoritative movement pipeline становится архитектурно слабым для multiplayer:
- клиент не должен быть источником канонического movement outcome;
- локальный `NavMeshAgent` не должен быть authoritative mover для player actor;
- path planning и path following должны принадлежать хосту;
- shared debug path preview для движущихся игроков должен отображать именно authoritative path, который принят хостом, а не локальную клиентскую догадку.
Без этого возрастает риск:
- desync между client local movement и host state;
- race-condition между player spawn и nav coverage readiness;
- неотлаживаемых расхождений path preview между peers;
- ошибок вроде `Failed to create agent because it is not close enough to the NavMesh`, если movement pipeline завязан на lifecycle локального `NavMeshAgent`.
## Expected Outcome
В проекте существует единая система пяти атрибутов: `Мощь`, `Ловкость`, `Фокус`, `Стойкость`, `Мастерство`. Атрибуты конвертируются в понятные боевые эффекты, а классы Воин, Маг и Лучник используют их как часть стартовой конфигурации и class identity. Ресурсная модель явно разделяет `HP`, `Stamina` и `Mana`, причем у каждого ресурса есть свое автопополнение.
- Игрок отправляет только команду перемещения, а не итог движения.
- Хост валидирует destination на своем NavMesh, строит authoritative path и двигает actor канонически.
- Клиенты получают authoritative movement state и сглаживают presentation.
- Для каждого движущегося игрока существует authoritative debug path preview, который видят все клиенты.
- Player spawn и first move command не зависят от hidden scene hacks и не требуют client-authoritative `NavMeshAgent`.
## Current Context
Канонический GDD по атрибутам уже зафиксирован в `docs/gameplay/attribute-system-gdd.md`, но отдельной реализации и явной интеграции с class model пока нет. Эта задача закрывает разрыв между design intent и runtime-моделью.
В проекте уже зафиксированы и частично реализованы базовые решения по миру и runtime NavMesh:
- `TASK-0023` ввел runtime NavMesh как sidecar-модуль поверх voxel world.
- `VoxelWorldGenerator` уже публикует nav source snapshots и world interest.
- `VoxelWorldNavMeshService` строит NavMesh локально на каждом peer по region-based схеме.
При этом current player flow пока не соответствует целевой модели:
- `Assets/Scripts/Players/PlayerMoving.cs` ориентирован на локальное movement execution;
- `Assets/Features/VoxelWorld/Prefabs/TestPlayer.prefab` все еще держит player movement в client-oriented конфигурации;
- spawn/nav readiness для player-on-navmesh еще не оформлены как отдельный контракт;
- shared debug path preview для player movement отсутствует.
## Source Of Truth
- `docs/gameplay/attribute-system-gdd.md`
- `docs/gameplay/attribute-reference.md`
- `docs/gameplay/stat-catalog-mvp.md`
- `docs/gameplay/combat-resolution-gdd.md`
- `docs/tasks/items/TASK-0007.md`
- `docs/tasks/items/TASK-0011.md`
- runtime реализация combat stats и class definitions
- `docs/architecture/mvp-world-authority-navmesh.md`
- `docs/plans/TASK-0023-runtime-navmesh-implementation-plan.md`
- фактический player/network/world flow в текущем коде проекта
## Read First
- `docs/gameplay/attribute-system-gdd.md`
- `docs/gameplay/attribute-reference.md`
- `docs/gameplay/stat-catalog-mvp.md`
- `docs/gameplay/combat-resolution-gdd.md`
- `docs/tasks/items/TASK-0007.md`
- `docs/tasks/items/TASK-0009.md`
- `docs/tasks/items/TASK-0010.md`
- `docs/tasks/items/TASK-0011.md`
- `Assets/Scripts/Players/PlayerMoving.cs`
- `Assets/Scripts/Players/CameraFollow.cs`
- `Assets/Features/VoxelWorld/Prefabs/TestPlayer.prefab`
- `Assets/Features/VoxelWorld/Scenes/VoxelWorldTestScene.unity`
- `Assets/Features/VoxelWorld/Runtime/VoxelWorldGenerator.cs`
- `Assets/Features/VoxelWorld/Contracts/NavMeshWorldContracts.cs`
- `Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshService.cs`
- `Assets/Scripts/VoxelWorld/VoxelWorldNavMeshLifetimeScope.cs`
## Fixed Decisions
### 1. Player movement outcome is host-authoritative
Клиент отправляет только move intent. Канонические:
- target acceptance/rejection;
- path corners;
- progress по path;
- итоговая позиция;
- movement completion/cancel.
Все это вычисляется и хранится на хосте.
### 2. Player uses NavMesh for movement, but client NavMesh is not authoritative
Клиент может использовать локальный NavMesh только для optional preview/query UX, но не как source of truth для gameplay movement state.
### 3. Do not use client-local `NavMeshAgent` as canonical player mover
Нельзя строить player movement correctness на `NavMeshAgent`, который локально двигает owner-клиента.
Предпочтительный путь:
- host-side `NavMesh.SamplePosition`;
- host-side `NavMesh.CalculatePath`;
- host-side explicit path follower;
- movement execution через контролируемый mover, предпочтительно `CharacterController.Move` или эквивалентный deterministic-ish explicit mover.
### 4. Client does not send path corners or final movement outcome
Клиенту нельзя отправлять:
- path corners;
- velocity как authoritative instruction;
- final position;
- movement completion.
Клиент отправляет только request:
- sequence id;
- requested destination;
- при необходимости легкий UX/debug metadata, не влияющий на authority.
### 5. Shared debug path preview must be authoritative-path-based
Обязательный debug preview, который видят все клиенты, должен строиться из authoritative path, рассчитанного хостом.
Допустим временный local provisional preview у инициирующего клиента, но он:
- не считается каноническим;
- должен визуально отличаться;
- должен исчезать или заменяться после host accept/reject.
### 6. Spawn/nav readiness must be explicit
Нельзя строить pipeline по модели:
- player actor spawned;
- NavMesh может быть еще не готов;
- movement runtime надеется, что agent потом сам корректно «встанет» на NavMesh.
Нужен явный readiness contract или equivalent bootstrap policy для spawn regions / first move command.
## Scope In
- базовая runtime-модель пяти атрибутов персонажа
- конвертация атрибутов в derived combat stats по каноническим направлениям
- явное разделение `HP`, `Stamina` и `Mana` как разных runtime resource pools
- автопополнение для `HP`, `Stamina` и `Mana`
- стартовые или базовые классовые приоритеты атрибутов для Воина, Мага и Лучника
- интеграция атрибутов в class definition и стартовую конфигурацию персонажа
- точки расширения для weapon scaling, skill scaling и будущих гибридных классов
- host-authoritative player movement по NavMesh;
- client command pipeline для выбора destination;
- host-side destination validation;
- host-side path planning;
- host-side path following;
- replication authoritative movement state на клиентов;
- shared debug path preview для каждого движущегося игрока на всех клиентах;
- optional local provisional preview для owner-клиента;
- nav-aware spawn/bootstrap и первый move command;
- интеграция через contracts + DI + MessagePipe, совместимая с `TASK-0023`.
## Scope Out
- глубокая UI-визуализация всех статов и их breakdown на каждом экране
- полноценная talent tree или perk-система
- тонкая финальная балансировка числовых коэффициентов для late game
- NPC navigation system;
- crowd simulation;
- сложная prediction/reconciliation система для player nav movement;
- production UI polish path markers;
- ownership migration;
- репликация NavMesh data blob;
- multi-agent support beyond current single-agent MVP;
- сохранение movement path через reconnect/persistence beyond current runtime session.
## Constraints
## Required Architecture
- реализовывать только пять канонических атрибутов из `docs/gameplay/attribute-system-gdd.md`
- не сливать offensive pressure и survivability в один стат
- `Мастерство` должно усиливать class-specific специализацию, а не заменять основной стат класса
- классы должны использовать общую систему атрибутов, а не отдельные class-only формулы
### Movement flow
## If You Find Drift
#### Client
- если код урона, оружия или навыков начинает обходить общую attribute-конвертацию, это drift
- если классы получают уникальные скрытые статы вместо работы через общую модель атрибутов, это drift
1. Игрок выбирает destination.
2. Input layer определяет world point.
3. Optional: строит provisional local preview path для UX owner-клиента.
4. Отправляет host command с sequence id и requested destination.
## Suggested Approach
#### Host
1. Ввести каноническую runtime-структуру для пяти атрибутов персонажа.
2. Зафиксировать derived combat stats и правила конверсии без избыточного усложнения формул.
3. Добавить в class definitions стартовые значения, приоритеты или affinity по атрибутам для Воина, Мага и Лучника.
4. Проверить, что оружие и навыки могут опираться на эти атрибуты без class-specific обходов.
1. Проверяет ownership и допустимость команды.
2. Проверяет movement lock/state.
3. Проверяет nav readiness для области.
4. Делает `NavMesh.SamplePosition`.
5. Делает `NavMesh.CalculatePath`.
6. Если путь валиден, обновляет canonical movement state.
7. Публикует/реплицирует accepted authoritative path и path preview.
8. Если путь невалиден, отправляет reject reason.
#### Host tick
1. Берет текущий active path.
2. Вычисляет движение к текущему corner.
3. Двигает player actor через explicit mover.
4. Продвигает current corner index.
5. По завершении очищает active path preview и переводит actor в `Idle`.
#### Clients
1. Получают authoritative movement state.
2. Сглаживают presentation.
3. Отображают authoritative debug path preview для всех moving players.
### Assembly boundaries
Рекомендуется отдельный feature-модуль:
- `Assets/Features/PlayerNavigation/Contracts/PlayerNavigation.Contracts.asmdef`
- `Assets/Features/PlayerNavigation/Runtime/PlayerNavigation.Runtime.asmdef`
Нельзя вшивать player navigation hardwired внутрь `VoxelWorldGenerator` или `VoxelWorldNavMeshService`.
### DI and integration model
Использовать:
- contracts;
- DI через `VContainer`;
- typed `MessagePipe` publishers/subscribers;
- reader interfaces для текущего snapshot state.
Не использовать `GlobalMessagePipe`.
### Message vs reader split
Через MessagePipe:
- lifecycle movement events;
- accept/reject events;
- preview invalidation/update events.
Через reader contracts:
- текущее состояние movement state;
- текущее состояние authoritative path preview;
- nav readiness / spawn readiness snapshot, если требуется queryable access.
## Required New Contracts
### Reader interfaces
Нужны как минимум:
- `IPlayerMovementStateReader`
- `IPlayerPathPreviewReader`
- `ISpawnNavReadinessReader` или эквивалентный узкий readiness contract
Минимальная ответственность:
- `IPlayerMovementStateReader` умеет вернуть current movement snapshot игрока;
- `IPlayerPathPreviewReader` умеет вернуть active authoritative preview для игрока или списка игроков;
- `ISpawnNavReadinessReader` умеет ответить, готова ли nav coverage для spawn/first-move области.
### DTO / snapshots
Ожидаются как минимум:
- `PlayerMovementStateSnapshot`
- `PlayerPathPreviewSnapshot`
- `PlayerMoveRequest`
- `PlayerMoveCommandResult`
Минимальный состав `PlayerMovementStateSnapshot`:
- player network id;
- status;
- command sequence;
- current position;
- target position;
- move speed;
- current corner index;
- authoritative path corners;
- updated timestamp/network tick.
Минимальный состав `PlayerPathPreviewSnapshot`:
- player network id;
- command sequence;
- corners;
- `IsAuthoritative`;
- `IsActive`.
### Enums
Нужны как минимум:
- `PlayerMovementStatus`
- `PlayerMoveRejectReason`
Примерные состояния:
- `Idle`
- `AwaitingPath`
- `Moving`
- `Blocked`
- `Completed`
- `Cancelled`
- `Rejected`
Примерные reject reasons:
- `NoNavCoverage`
- `DestinationNotOnNavMesh`
- `PathInvalid`
- `PathPartial`
- `MovementLocked`
- `NotOwner`
## Required Messages
Нужны typed MessagePipe messages для:
- `PlayerMoveRequestedMessage`
- `PlayerMoveAcceptedMessage`
- `PlayerMoveRejectedMessage`
- `PlayerMoveStateChangedMessage`
- `PlayerPathPreviewChangedMessage`
- `PlayerMovementStoppedMessage`
Если для spawn/bootstrap это необходимо, допустим дополнительный readiness message, но только как supplement к reader contract, а не как единственный источник истины.
## Required Runtime Responsibilities
### 1. Client input sender
Должен:
- собирать local click-to-move input;
- вычислять world destination;
- отправлять network command хосту;
- optional: запускать provisional local preview.
Не должен:
- канонически двигать actor;
- принимать final authoritative решения по path validity.
### 2. Host command validator / planner
Должен:
- валидировать ownership;
- валидировать destination;
- делать `NavMesh.SamplePosition`;
- делать `NavMesh.CalculatePath`;
- обновлять canonical movement state;
- публиковать accepted/rejected results.
### 3. Host path follower
Должен:
- исполнять movement по accepted path;
- отслеживать current corner index;
- завершать, отменять или репланить путь;
- синхронизировать authoritative transform/state.
### 4. Shared preview state + renderer
Должны:
- хранить authoritative debug path data;
- раздавать snapshot presentation-слою;
- визуализировать active path preview для всех observed players.
Shared preview не должен строиться заново локально на каждом клиенте по его client NavMesh. Источник preview для всех клиентов должен быть authoritative path state от хоста.
## FishNet Requirements
### Client -> Host
Использовать `ServerRpc` для move command:
- `RequestMoveTo(uint sequence, Vector3 requestedWorldPoint)`
### Host -> Clients
Допустимы:
- authoritative replicated movement state;
- отдельные `TargetRpc` / `ObserversRpc` для accept/reject;
- отдельная lightweight replication для shared path preview.
Клиент не должен иметь возможности двигать чужого player actor.
## Required Changes In Existing Code
### `Assets/Scripts/Players/PlayerMoving.cs`
Нужно перестроить из local movement executor в input sender / thin player navigation entrypoint.
### `Assets/Features/VoxelWorld/Prefabs/TestPlayer.prefab`
Нужно пересмотреть:
- текущий movement pipeline;
- конфигурацию `NetworkTransform`;
- player navigation components;
- visual debug preview attachment points.
Client-authoritative movement не должен оставаться каноническим режимом для nav-based player movement.
### `Assets/Features/VoxelWorld/Scenes/VoxelWorldTestScene.unity`
Нужно проверить:
- spawn bootstrap;
- nav warmup around spawn points;
- наличие всего необходимого для тестирования shared path preview.
### Nav readiness bootstrap
Нужно добавить явную стратегию, чтобы player spawn / first command не зависели от случайного отсутствия NavMesh в стартовой области.
## Debug Path Preview Requirements
Это обязательная часть задачи.
### Functional requirement
Каждый движущийся игрок должен иметь debug path preview, который видят все клиенты.
Примеры:
- игрок A движется -> path видят A, B, C;
- игрок B движется -> path видят A, B, C.
### Canonical rule
Shared preview должен отображать именно authoritative path, рассчитанный хостом.
### Optional owner-local preview
Допустим provisional local preview до host ответа, но он должен:
- визуально отличаться;
- не считаться каноническим;
- исчезать или заменяться после accept/reject.
### Minimal rendering expectation
Минимально допустимо:
- `LineRenderer` или эквивалентный lightweight renderer;
- обновление при accept/replan/stop/complete;
- очистка при completion/cancel/reject.
## Acceptance Criteria
- в системе существуют `Мощь`, `Ловкость`, `Фокус`, `Стойкость`, `Мастерство` как канонические runtime-атрибуты
- атрибуты влияют на боевые параметры по правилам, совместимым с GDD
- `HP`, `Stamina` и `Mana` существуют как разные runtime resource pools
- у `HP`, `Stamina` и `Mana` есть отдельные механики автопополнения
- классы Воин, Маг и Лучник имеют явную интеграцию с системой атрибутов
- downstream системы могут использовать атрибуты без дублирования class-specific формул
- Клиент может отправить move request по клику в мир.
- Хост валидирует destination на своем NavMesh.
- Хост строит authoritative path.
- Игрок движется по host-side path, а не по client-authoritative local mover.
- Недопустимые destination/path корректно reject'ятся с reason.
- Для каждого moving player существует authoritative path preview.
- Этот preview виден на всех клиентах.
- Preview корректно обновляется при новой команде, replan, stop, cancel и completion.
- Если реализован provisional local preview, он визуально отделен от authoritative shared preview.
- Player spawn и first move command не зависят от hidden `NavMeshAgent` attach hacks.
- Pipeline не опирается на `Camera.main` как канонический источник authority/interest.
## Verification
- вычитка runtime-модели против `docs/gameplay/attribute-system-gdd.md`
- ручная проверка, что классы получают разные стартовые stat priorities
- ручная проверка, что derived stats меняются от изменения атрибутов по ожидаемым направлениям
- ручной тест: single host, single client, move command accepted/rejected;
- ручной тест: host + 2 clients, оба клиента видят preview друг друга;
- ручной тест: invalid destination вне walkable area, host reject без runtime errors;
- ручной тест: новая команда во время движения корректно заменяет active path;
- ручной тест: late join видит текущее движение и active preview moving players;
- ручной тест: первый move command после старта сцены не приводит к runtime ошибкам из-за отсутствия nav coverage;
- ручной тест: completion/cancel очищает preview на всех клиентах.
## Risks / Open Questions
- нужно решить, какие именно конверсии будут обязательными уже в MVP, а какие можно оставить extension points
- нужно не перегрузить class model слишком ранней детализацией формул
- Если оставить рядом client-authoritative movement и host-side nav movement, возникнет двойная симуляция и несогласованное состояние.
- Если shared preview строить по локальному client NavMesh, разные peers могут видеть разный path debug.
- Если spawn/nav readiness не будет оформлен явно, lifecycle race останется даже при правильном movement flow.
- Возможно потребуется отдельный узкий contract для nav coverage readiness, которого пока нет в `TASK-0023` runtime-поверхности.
## Human Decisions Needed
@@ -129,8 +491,10 @@ Combat core и классовая система пока не имеют кан
## Decision Log
- `2026-04-09` - задача добавлена после фиксации канонического GDD по атрибутам.
- `2026-04-08` - задача создана после фиксации runtime NavMesh sidecar и обсуждения правильной host-authoritative модели player movement по NavMesh.
## Handoff Notes
Если позже появятся формульные документы по MVP-коэффициентам, они должны уточнять эту задачу, но не подменять канонический смысл атрибутов из GDD.
Реализация задачи должна опираться на уже принятые решения по world authority и runtime NavMesh. Если в ходе реализации возникнет соблазн повесить `NavMeshAgent` на player prefab как client-local authoritative mover, это нужно считать архитектурно неправильным shortcut'ом и не делать.
Shared debug path preview обязателен и должен отображать authoritative path для всех клиентов, а не purely local preview инициатора.
+304
View File
@@ -0,0 +1,304 @@
---
id: TASK-0028
title: Перевести runtime NavMesh на interest-cluster-based coverage
summary: Заменить основной runtime pathing mode с множества region-based NavMeshData на небольшой набор крупных cluster-based coverage windows, чтобы убрать seam-разрывы и сделать покрытие совместимым с multiplayer interest set.
priority: Highest
area: ai
owner: unassigned
created: 2026-04-08
updated: 2026-04-08
execution_time: 2d
depends_on:
- TASK-0023
canonical_docs:
- docs/tasks/Index.md
- docs/architecture/mvp-world-authority-navmesh.md
- docs/plans/TASK-0023-runtime-navmesh-implementation-plan.md
related_files:
- Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshService.cs
- Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshConfig.cs
- Assets/Features/VoxelWorld/Contracts/NavMeshWorldContracts.cs
- Assets/Features/VoxelWorld/Runtime/VoxelWorldGenerator.cs
---
# TASK-0028 - Перевести runtime NavMesh на interest-cluster-based coverage
## Status
Статус задачи ведется в `docs/tasks/Index.md` и является каноническим там.
## Why
Текущая region-based runtime NavMesh схема подтверждает локальную работоспособность build pipeline, но уже показала архитектурно важную проблему: pathfinding между соседними зонами покрытия дает `PathPartial`, даже когда destination сам лежит на NavMesh.
Это означает, что текущий основной runtime pathing mode опирается на набор разрозненных nav islands и не гарантирует непрерывный navigation graph между активными зонами симуляции.
Для multiplayer host-authoritative pathing этого недостаточно. Хосту нужен не просто локально построенный NavMesh, а непрерывное coverage в активной области симуляции без систематических seam-разрывов на границах мелких регионов.
## Expected Outcome
- Основной runtime pathing mode больше не строится как множество мелких независимых `NavMeshData` по nav regions.
- Вместо этого используется небольшой набор крупных `coverage windows`, каждый из которых покрывает `interest cluster`.
- Внутри активной области симуляции pathfinding не ломается на границах бывших nav regions.
- Coverage учитывает не только одного игрока, а multiplayer interest set: `spawn anchors + players + active NPC`.
- Модуль остается sidecar-решением поверх `VoxelWorld`, без hardwiring внутрь `VoxelWorldGenerator`.
## Current Context
Сейчас runtime NavMesh уже вынесен в sidecar-модуль и строится локально на каждом peer:
- `VoxelWorldGenerator` отдает nav sources через contracts;
- `VoxelWorldNavMeshService` собирает sources из chunk snapshots;
- build идет локально и не реплицируется по сети;
- authority gameplay сохраняется у хоста.
Однако unit of build и unit of scheduling пока выбраны неудачно как основной pathing mode:
- много мелких `NavMeshData` по region-based сетке;
- pathfinding между region surfaces может распадаться на отдельные islands;
- visual continuity overlay не гарантирует graph connectivity для `NavMesh.CalculatePath` / `NavMeshAgent`.
## Source Of Truth
- `docs/architecture/mvp-world-authority-navmesh.md`
- `docs/plans/TASK-0023-runtime-navmesh-implementation-plan.md`
- фактическая реализация `VoxelWorldNavMeshService`
- подтвержденные smoke-test результаты с `PathPartial` на границах region coverage
## Read First
- `Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshService.cs`
- `Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshConfig.cs`
- `Assets/Features/VoxelWorld/Contracts/NavMeshWorldContracts.cs`
- `Assets/Features/VoxelWorld/Runtime/VoxelWorldGenerator.cs`
- `docs/architecture/mvp-world-authority-navmesh.md`
## Fixed Decisions
### 1. NavMesh remains local-build sidecar state
NavMesh по-прежнему:
- строится локально на каждом peer;
- не реплицируется как data blob;
- остается derived cache от world state;
- не является authoritative network state.
### 2. Chunk stays source/invalidation unit, not build unit
`Chunk` остается:
- источником nav build sources;
- unit of invalidation для world lifecycle;
- источником dirty notifications.
`Chunk` не должен оставаться каноническим unit of nav coverage build.
### 3. Coverage window is built from interest clusters, not from one player and not from camera
Нельзя строить канонический runtime pathing вокруг:
- `Camera.main`;
- только одного tracked player;
- presentation-level сущности.
Coverage должен строиться вокруг `interest clusters`, формируемых из:
- spawn anchors;
- players;
- active NPC.
### 4. One player does not imply one dedicated volume
Нельзя закреплять правило `один игрок = один volume`.
Правильная модель:
- один spatially coherent interest cluster = один coverage window;
- близкие игроки и NPC должны merge'иться в один cluster;
- число active windows должно быть bounded.
### 5. Scene scan through `NavMeshSurface` sample is not the canonical integration model
Подход из sample `NavMeshSurfaceVolumeUpdater` полезен как диагностическая подсказка, но не должен становиться буквальной production integration model.
Канонический путь для проекта:
- bounds уровня sliding coverage window;
- build sources из `IChunkNavSourceReader` / world contracts;
- DI + typed MessagePipe + reader contracts.
### 6. Spawn readiness must become first-class
Покрытие должно учитывать spawn anchors до player movement activation. Нельзя полагаться на то, что NavMesh magically появится только после того, как actor уже стал единственной точкой интереса.
## Scope In
- замена основного runtime pathing mode с region-based surfaces на cluster-based coverage windows;
- новый scheduler по coverage windows;
- cluster builder для `players + active NPC + spawn anchors`;
- build source collection по bounds окна, а не по одному nav region;
- read-model для current nav coverage state;
- explicit coverage readiness для spawn / first path command / AI activation;
- bounded merge policy для близких interest points;
- debug visibility coverage windows.
## Scope Out
- изменение authority model NPC/AI;
- репликация NavMesh;
- полноценная crowd avoidance система;
- multi-agent taxonomy beyond current single-agent MVP;
- player host-authoritative navigation system как отдельная feature-задача;
- большой рефактор world feature вне необходимого nav contracts surface.
## Required Architecture
### New canonical unit: interest cluster
Нужна новая внутренняя модель coverage:
- `WorldInterestPoint` остается atomic input;
- `NavInterestCluster` становится unit of grouping;
- `NavCoverageWindow` становится unit of build and readiness.
Минимальная ответственность cluster builder:
- собрать текущий interest set;
- spatially merge близкие точки интереса;
- стабилизировать cluster ids между обновлениями;
- строить quantized window bounds с margin.
### Coverage window replaces region as primary build unit
`Coverage window` должен хранить:
- cluster id;
- current bounds;
- `NavMeshData` / `NavMeshDataInstance`;
- dirty/building/ready state;
- список covered chunks или equivalent cached source membership.
### Source collection remains contract-driven
Build sources должны собираться:
- не через scene scan;
- не через direct references на private world internals;
- а через `IChunkNavSourceReader` и chunk nav source snapshots.
`Chunk` используется как source/invalidation unit, но не как primary coverage unit.
### Coverage state must be queryable
Нужен reader contract уровня:
- `INavCoverageReader`
Минимальная ответственность:
- `IsPositionCovered(Vector3 worldPosition)`;
- возможность получить current active coverage windows;
- возможность проверить readiness для spawn/path activation.
### Scheduler must be bounded and quantized
Нельзя rebuild'ить coverage window на каждый микрошаг игрока.
Нужны:
- quantized movement threshold;
- bounded number of active windows;
- bounded builds per frame;
- rebuild только при существенном смещении cluster bounds, изменении cluster composition или chunk invalidation внутри covered bounds.
## Suggested Runtime Structure
### New or refactored runtime types
- `NavInterestClusterBuilder`
- `NavCoverageWindowRuntime`
- `NavCoverageWindowSnapshot`
- `NavBuildSourceCollector`
- `INavCoverageReader`
- `VoxelWorldClusteredNavMeshService` или equivalent refactor текущего `VoxelWorldNavMeshService`
### Config changes
Текущий config должен сместиться от region-centric параметров к cluster/window-centric:
- `clusterMergeDistance`
- `clusterBoundsPadding`
- `clusterRebuildQuantization`
- `maxActiveCoverageWindows`
- `chunkCollectionMarginInChunks`
- `maxBuildsPerFrame`
Если старые region-centric поля остаются временно ради миграции, они не должны продолжать определять основной runtime pathing mode.
## Main Highlights Of Changes
1. **Смена unit of build**
- было: `nav region`
- станет: `interest cluster coverage window`
2. **Смена unit of scheduling**
- было: очередь dirty regions
- станет: очередь dirty coverage windows
3. **Смена unit of readiness**
- было: неявная region-local готовность
- станет: явная coverage readiness по world position
4. **Смена логики multiplayer coverage**
- было: первая practical привязка к локальному player interest
- станет: `spawn anchors + players + active NPC`
5. **Уход от seam-first topology**
- было: pathing через сеть мелких surfaces с риском disconnected islands
- станет: меньшее число более цельных coverage windows
## Acceptance Criteria
- Основной runtime pathing mode больше не опирается на множество мелких region-based `NavMeshData` как на primary navigation graph.
- Destination на NavMesh в соседней активной области больше не приводит систематически к `PathPartial` только из-за seam между бывшими nav regions.
- Coverage формируется по interest clusters, а не по одному tracked player и не по `Camera.main`.
- Spawn anchors участвуют в initial nav coverage.
- Нужное coverage state можно query'ить через reader contract.
- Sidecar-модуль остается отключаемым без переписывания `VoxelWorld` core.
- Build pipeline остается bounded и пригодным для WebGL-host бюджета.
## Verification
- ручной тест: pathfinding между соседними активными областями больше не обрывается на границе бывших region surfaces;
- ручной тест: при удалении игроков друг от друга coverage windows корректно split/merge'ятся по кластерам;
- ручной тест: spawn area получает nav coverage до first path command;
- ручной тест: pathfinding внутри cluster window и между близкими covered areas дает `PathComplete`, где раньше получался `PathPartial` из-за seam;
- debug visualization coverage windows подтверждает ожидаемую cluster topology.
## Risks / Open Questions
- Один большой coverage window может снять seam-problem, но оказаться слишком тяжелым для host CPU budget; поэтому bounded cluster windows важнее, чем просто "один volume на весь мир".
- Слишком агрессивное merge policy может раздуть rebuild cost; слишком слабое merge policy вернет seam-problem в другой форме.
- Нужна аккуратная стратегия стабильных cluster ids, иначе scheduler и debug tooling будут шумными.
- Возможно понадобится временный dual-mode rollout: region mode как fallback, clustered mode как новый primary pathing mode до подтверждения стабильности.
## Human Decisions Needed
- none currently
## Decision Log
- `2026-04-08` - подзадача выделена после smoke-test'а runtime NavMesh, который подтвердил локальную работоспособность build pipeline, но выявил `PathPartial` на границах region-based coverage.
- `2026-04-08` - region-based primary pathing mode заменен на clustered coverage windows; дополнительно введены transient nav coverage hints для prewarm вдоль активного маршрута.
## Handoff Notes
Эта задача не отменяет базовые решения `TASK-0023`, а уточняет основной runtime pathing mode. Не возвращать интеграцию к `Camera.main` или scene-scan-driven sample как к канонической архитектуре. Sample `NavMeshSurfaceVolumeUpdater` использовать только как источник идеи sliding coverage, но не как буквальную production integration model.
Задача закрыта как переход на новый основной runtime pathing mode. Дополнительные улучшения interest composition, NPC interest expansion, debug visualization и route-aware coverage policy нужно развивать отдельными follow-up задачами.
+136
View File
@@ -0,0 +1,136 @@
---
id: TASK-0027
title: Реализовать систему атрибутов и интеграцию с классами
summary: Ввести пять канонических атрибутов персонажа, их derived combat scaling и привязать классы Воина, Мага и Лучника к своим стартовым и приоритетным статам.
priority: Highest
area: gameplay-core
owner: unassigned
created: 2026-04-09
updated: 2026-04-09
execution_time: 1d
depends_on:
- TASK-0007
canonical_docs:
- docs/tasks/Index.md
- docs/gameplay/attribute-system-gdd.md
- docs/gameplay/attribute-reference.md
- docs/gameplay/stat-catalog-mvp.md
- docs/gameplay/combat-resolution-gdd.md
related_files:
- Assets/Features/
- Assets/Scripts/
---
# TASK-0027 - Реализовать систему атрибутов и интеграцию с классами
## Status
Статус задачи ведется в `docs/tasks/Index.md` и является каноническим там.
Допустимые значения статуса:
- `BackLog`
- `ToDo`
- `InProgress`
- `Review`
- `Done`
## Why
Combat core и классовая система пока не имеют канонической runtime-модели атрибутов. Без этого классы останутся набором стартовых исключений, а боевые формулы не получат устойчивую точку расширения для билдов, оружия и навыков.
## Expected Outcome
В проекте существует единая система пяти атрибутов: `Мощь`, `Ловкость`, `Фокус`, `Стойкость`, `Мастерство`. Атрибуты конвертируются в понятные боевые эффекты, а классы Воин, Маг и Лучник используют их как часть стартовой конфигурации и class identity. Ресурсная модель явно разделяет `HP`, `Stamina` и `Mana`, причем у каждого ресурса есть свое автопополнение.
## Current Context
Канонический GDD по атрибутам уже зафиксирован в `docs/gameplay/attribute-system-gdd.md`, но отдельной реализации и явной интеграции с class model пока нет. Эта задача закрывает разрыв между design intent и runtime-моделью.
## Source Of Truth
- `docs/gameplay/attribute-system-gdd.md`
- `docs/gameplay/attribute-reference.md`
- `docs/gameplay/stat-catalog-mvp.md`
- `docs/gameplay/combat-resolution-gdd.md`
- `docs/tasks/items/TASK-0007.md`
- `docs/tasks/items/TASK-0011.md`
- runtime реализация combat stats и class definitions
## Read First
- `docs/gameplay/attribute-system-gdd.md`
- `docs/gameplay/attribute-reference.md`
- `docs/gameplay/stat-catalog-mvp.md`
- `docs/gameplay/combat-resolution-gdd.md`
- `docs/tasks/items/TASK-0007.md`
- `docs/tasks/items/TASK-0009.md`
- `docs/tasks/items/TASK-0010.md`
- `docs/tasks/items/TASK-0011.md`
## Scope In
- базовая runtime-модель пяти атрибутов персонажа
- конвертация атрибутов в derived combat stats по каноническим направлениям
- явное разделение `HP`, `Stamina` и `Mana` как разных runtime resource pools
- автопополнение для `HP`, `Stamina` и `Mana`
- стартовые или базовые классовые приоритеты атрибутов для Воина, Мага и Лучника
- интеграция атрибутов в class definition и стартовую конфигурацию персонажа
- точки расширения для weapon scaling, skill scaling и будущих гибридных классов
## Scope Out
- глубокая UI-визуализация всех статов и их breakdown на каждом экране
- полноценная talent tree или perk-система
- тонкая финальная балансировка числовых коэффициентов для late game
## Constraints
- реализовывать только пять канонических атрибутов из `docs/gameplay/attribute-system-gdd.md`
- не сливать offensive pressure и survivability в один стат
- `Мастерство` должно усиливать class-specific специализацию, а не заменять основной стат класса
- классы должны использовать общую систему атрибутов, а не отдельные class-only формулы
## If You Find Drift
- если код урона, оружия или навыков начинает обходить общую attribute-конвертацию, это drift
- если классы получают уникальные скрытые статы вместо работы через общую модель атрибутов, это drift
## Suggested Approach
1. Ввести каноническую runtime-структуру для пяти атрибутов персонажа.
2. Зафиксировать derived combat stats и правила конверсии без избыточного усложнения формул.
3. Добавить в class definitions стартовые значения, приоритеты или affinity по атрибутам для Воина, Мага и Лучника.
4. Проверить, что оружие и навыки могут опираться на эти атрибуты без class-specific обходов.
## Acceptance Criteria
- в системе существуют `Мощь`, `Ловкость`, `Фокус`, `Стойкость`, `Мастерство` как канонические runtime-атрибуты
- атрибуты влияют на боевые параметры по правилам, совместимым с GDD
- `HP`, `Stamina` и `Mana` существуют как разные runtime resource pools
- у `HP`, `Stamina` и `Mana` есть отдельные механики автопополнения
- классы Воин, Маг и Лучник имеют явную интеграцию с системой атрибутов
- downstream системы могут использовать атрибуты без дублирования class-specific формул
## Verification
- вычитка runtime-модели против `docs/gameplay/attribute-system-gdd.md`
- ручная проверка, что классы получают разные стартовые stat priorities
- ручная проверка, что derived stats меняются от изменения атрибутов по ожидаемым направлениям
## Risks / Open Questions
- нужно решить, какие именно конверсии будут обязательными уже в MVP, а какие можно оставить extension points
- нужно не перегрузить class model слишком ранней детализацией формул
## Human Decisions Needed
- none currently
## Decision Log
- `2026-04-09` - задача добавлена после фиксации канонического GDD по атрибутам.
## Handoff Notes
Если позже появятся формульные документы по MVP-коэффициентам, они должны уточнять эту задачу, но не подменять канонический смысл атрибутов из GDD.