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

4.8 KiB
Raw Permalink Blame History

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

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

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

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.