Files
suaveplan/openspec/changes/enterprise-gaming-spatial-hash/proposal.md
2026-05-27 23:29:53 +01:00

135 lines
3.9 KiB
Markdown

# OpenSpec Change: enterprise-gaming-spatial-hash
- **Change ID**: enterprise-gaming-spatial-hash
- **Package**: `@suaveplan/spatial-hash`
- **Category**: gaming/engine
- **Target path**: `gaming/engine/spatial-hash`
- **Status**: PROPOSED
- **Date**: 2026-04-24
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/spatial-hash.md`
---
## Summary
Deliver `@suaveplan/spatial-hash` on the genesis branch from scratch at enterprise quality. The package provides spatial hashing for O(1) broad-phase 2D/3D proximity queries — used by physics, AI, and rendering culling systems. A uniform grid divides world space into cells; each cell maps to a hash bucket holding entity IDs. Insertion, removal, and range queries run in O(1) amortised time assuming uniform entity distribution. Genesis adds typed 2D and 3D variants, Zod option schemas, OTel instrumentation, structured errors, and property-based tests verifying query completeness.
---
## Current-state audit (genesis)
Package does not exist on genesis yet — fresh build.
---
## Available workspace deps on genesis
| Package | Role |
|---|---|
| `@suaveplan/error` (`workspace:^`) | `SpatialHashError`; `SPATIAL_HASH.*` codes |
| `@suaveplan/types` (`workspace:^`) | `IdGenerator` |
| `zod` (`catalog:forms`) | Option schemas |
| `@opentelemetry/api` (`catalog:observability`) | Query time histogram, cell-count gauge |
---
## Public API surface
```ts
// 2D
function createSpatialHash2D(options: SpatialHash2DOptions): SpatialHash2D
interface SpatialHash2DOptions {
cellSize: number
initialCapacity?: number
}
interface SpatialHash2D {
insert(id: number, x: number, y: number): void
remove(id: number): void
move(id: number, x: number, y: number): void
queryRadius(x: number, y: number, radius: number): number[]
queryAABB(minX: number, minY: number, maxX: number, maxY: number): number[]
clear(): void
readonly size: number
}
// 3D
function createSpatialHash3D(options: SpatialHash3DOptions): SpatialHash3D
interface SpatialHash3DOptions {
cellSize: number
initialCapacity?: number
}
interface SpatialHash3D {
insert(id: number, x: number, y: number, z: number): void
remove(id: number): void
move(id: number, x: number, y: number, z: number): void
queryRadius(x: number, y: number, z: number, radius: number): number[]
queryAABB(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): number[]
clear(): void
readonly size: number
}
```
### Error codes
```ts
type SpatialHashErrorCode =
| 'SPATIAL_HASH_ENTITY_NOT_FOUND'
| 'SPATIAL_HASH_INVALID_CELL_SIZE'
| 'SPATIAL_HASH_QUERY_OUT_OF_BOUNDS'
```
---
## New additions for genesis
1. **Typed 2D and 3D implementations** — separate factories; 3D uses cantor-triple hash for cell keys.
2. **Float32Array-backed position cache** — tracks entity positions to support O(1) `move()` without caller re-inserting.
3. **OTel** — `spatial_hash.query_duration_ms` histogram, `spatial_hash.entity_count` gauge.
4. **Property-based tests** — fast-check: `queryRadius` completeness (every inserted entity within radius is returned), no false negatives.
---
## File layout
```text
gaming/engine/spatial-hash/
package.json
tsconfig.json
vitest.config.ts
src/
index.ts
error-codes.ts
constants/index.ts
types/common.ts
types/common.md
core/
spatial-hash-2d/
spatial-hash-2d.ts
spatial-hash-2d.md
spatial-hash-2d.types.ts
spatial-hash-2d.test.ts
index.ts
spatial-hash-3d/
spatial-hash-3d.ts
spatial-hash-3d.md
spatial-hash-3d.types.ts
spatial-hash-3d.test.ts
index.ts
utils/
hash.ts
hash.md
hash.test.ts
tests/
property.test.ts
```
---
## Impact
**Downstream**: `@suaveplan/hitbox`, `@suaveplan/r3f-pathfinding`, AI packages use spatial hash for broad-phase. Prerequisites: `@suaveplan/error`, `@suaveplan/types`.