Files
2026-05-27 23:29:53 +01:00

169 lines
4.8 KiB
Markdown
Raw Permalink 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.
# OpenSpec Change: enterprise-gaming-npc
- **Change ID**: enterprise-gaming-npc
- **Package**: `@suaveplan/npc`
- **Category**: gaming/ai
- **Target path**: `gaming/ai/npc`
- **Status**: PROPOSED
- **Date**: 2026-04-24
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/npc.md`
---
## Summary
Deliver `@suaveplan/npc` on the genesis branch from scratch at enterprise quality. The package provides NPC lifecycle management with spawn pools, population control, and daily schedules. A `NpcRegistry` holds typed `NpcDefinition` descriptors; a `SpawnPool` manages active NPC instances with capacity limits, spawn/despawn, and respawn timers; a `PopulationController` enforces per-zone NPC density limits; a `DailySchedule` maps time-of-day windows to NPC activity states. Each NPC instance has a `BehaviorTree` (from `@suaveplan/behavior-tree`) and a typed Blackboard. Genesis adds Zod definition schemas, structured errors, OTel population gauge, injectable clock, and 100% coverage.
---
## Current-state audit (genesis)
Package does not exist on genesis yet — fresh build.
---
## Available workspace deps on genesis
| Package | Role |
|---|---|
| `@suaveplan/error` (`workspace:^`) | `NpcError`; `NPC.*` codes |
| `@suaveplan/types` (`workspace:^`) | `Clock`, `IdGenerator` |
| `@suaveplan/events` (`workspace:^`) | `npc:spawn`, `npc:despawn`, `npc:activity:change` events |
| `@suaveplan/behavior-tree` (`workspace:^`) | Per-NPC behavior tree runner |
| `zod` (`catalog:forms`) | `NpcDefinition`, `DailySchedule` schemas |
| `@opentelemetry/api` (`catalog:observability`) | Population gauge, activity-change counter |
---
## Public API surface
```ts
interface NpcDefinition {
id: string
displayName: string
faction?: string
behaviorTreeFactory: (bb: Blackboard) => TreeNode
activities: ActivityDefinition[]
respawnTime?: number // seconds; undefined = no respawn
}
interface ActivityDefinition {
name: string
startHour: number // 0–23
endHour: number
priority?: number
}
function createNpcRegistry(): NpcRegistry
interface NpcRegistry {
register(def: NpcDefinition): void
get(id: string): NpcDefinition | undefined
}
function createSpawnPool(options: SpawnPoolOptions): SpawnPool
interface SpawnPoolOptions {
maxCapacity: number
registry: NpcRegistry
clock?: Clock
}
interface SpawnPool {
spawn(defId: string, position: Vec3): NpcInstance
despawn(instanceId: string): void
tick(dt: number): void
getActive(): NpcInstance[]
readonly count: number
}
interface NpcInstance {
readonly instanceId: string
readonly definitionId: string
readonly position: Vec3
readonly activity: string
readonly blackboard: Blackboard
readonly treeRunner: BehaviorTreeRunner
setPosition(position: Vec3): void
setActivity(name: string): void
}
function createPopulationController(options: PopulationOptions): PopulationController
interface PopulationController {
setZoneLimit(zoneId: string, max: number): void
canSpawn(zoneId: string): boolean
onSpawn(zoneId: string, instanceId: string): void
onDespawn(zoneId: string, instanceId: string): void
getZoneCount(zoneId: string): number
}
```
### Error codes
```ts
type NpcErrorCode =
| 'NPC_DEF_NOT_FOUND'
| 'NPC_POOL_FULL'
| 'NPC_INSTANCE_NOT_FOUND'
| 'NPC_INVALID_ACTIVITY'
| 'NPC_ZONE_LIMIT_REACHED'
```
---
## New additions for genesis
1. **Respawn timer** — `SpawnPool.tick()` tracks despawned NPCs with respawn timers, auto-respawns at origin.
2. **Population controller** — per-zone density enforcement prevents spawning if limit reached.
3. **Daily schedule** — `ActivityDefinition` time windows drive `NpcInstance.activity` based on injected clock hour.
4. **OTel** — `npc.population` gauge per zone; `npc.activity_changes_total` counter.
---
## File layout
```text
gaming/ai/npc/
package.json
tsconfig.json
vitest.config.ts
src/
index.ts
error-codes.ts
constants/index.ts
types/common.ts
types/common.md
core/
npc-registry/
npc-registry.ts
npc-registry.md
npc-registry.test.ts
index.ts
spawn-pool/
spawn-pool.ts
spawn-pool.md
spawn-pool.types.ts
spawn-pool.test.ts
index.ts
population-controller/
population-controller.ts
population-controller.md
population-controller.types.ts
population-controller.test.ts
index.ts
daily-schedule/
daily-schedule.ts
daily-schedule.md
daily-schedule.types.ts
daily-schedule.test.ts
index.ts
tests/
integration.test.ts
```
---
## Impact
**Downstream**: `@suaveplan/r3f-npc` renders NPC meshes and nameplates; `@suaveplan/fauna` extends spawn-pool for wildlife. Prerequisites: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`, `@suaveplan/behavior-tree`.