135 lines
3.9 KiB
Markdown
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`.
|