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

4.0 KiB
Raw Permalink Blame History

OpenSpec Change: enterprise-gaming-weather

  • Change ID: enterprise-gaming-weather
  • Package: @suaveplan/weather
  • Category: gaming/world
  • Target path: gaming/world/weather
  • Status: PROPOSED
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/weather.md

Summary

Deliver @suaveplan/weather on the genesis branch from scratch at enterprise quality. The package provides dynamic weather simulation with smooth transitions, regional zones, and gameplay effects. A WeatherSystem holds the current WeatherState (temperature, precipitation, wind, visibility, lightning) and advances it by transitioning toward a WeatherPreset; WeatherZone maps world regions to preset overrides; a WeatherTransition interpolates between two presets over a configurable duration. Genesis adds Zod preset schemas, structured errors, OTel weather-state gauge, injectable clock and RNG, 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:^) WeatherError; WEATHER.* codes
@suaveplan/types (workspace:^) Clock, Rng
@suaveplan/events (workspace:^) weather:changed, weather:lightning, weather:zone_entered events
@suaveplan/day-night (workspace:^) DayNightClock for time-based weather probability
zod (catalog:forms) WeatherPreset, WeatherZone schemas
@opentelemetry/api (catalog:observability) Weather-state change counter

Public API surface

interface WeatherPreset {
  name: string
  temperature: number      // celsius
  precipitation: number    // 0–1
  windSpeed: number        // m/s
  windDirection: number    // degrees
  visibility: number       // 0–1 (1=clear, 0=zero visibility)
  fogDensity: number       // 0–1
  cloudCover: number       // 0–1
  lightningProbability?: number  // per-minute probability 0–1
}

interface WeatherState extends WeatherPreset {
  readonly isTransitioning: boolean
  readonly transitionProgress: number  // 0–1
}

function createWeatherSystem(options: WeatherSystemOptions): WeatherSystem

interface WeatherSystemOptions {
  initialPreset: WeatherPreset
  transitionDuration?: number   // seconds, default 60
  clock?: Clock
  rng?: Rng
}

interface WeatherSystem {
  transitionTo(preset: WeatherPreset, duration?: number): void
  tick(dt: number): void
  readonly state: WeatherState
  readonly currentPreset: WeatherPreset
}

// Weather zones
function createWeatherZone(options: WeatherZoneOptions): WeatherZone

interface WeatherZoneOptions {
  id: string
  center: Vec3
  radius: number
  preset: WeatherPreset
  blendRadius?: number    // blend distance at zone edge
}

interface WeatherZone {
  readonly id: string
  getBlendFactor(position: Vec3): number   // 0 = outside, 1 = fully inside
}

function blendWeather(base: WeatherPreset, override: WeatherPreset, factor: number): WeatherPreset

Error codes

type WeatherErrorCode =
  | 'WEATHER_INVALID_PRESET'
  | 'WEATHER_ZONE_NOT_FOUND'
  | 'WEATHER_TRANSITION_INVALID'

File layout

gaming/world/weather/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    constants/index.ts
    types/common.ts
    types/common.md
    core/
      weather-system/
        weather-system.ts
        weather-system.md
        weather-system.types.ts
        weather-system.test.ts
        index.ts
      weather-zone/
        weather-zone.ts
        weather-zone.md
        weather-zone.types.ts
        weather-zone.test.ts
        index.ts
    presets/
      index.ts    # CLEAR, RAIN, STORM, SNOW, FOG built-in presets
    utils/
      blend.ts
      blend.md
      blend.test.ts
  tests/
    integration.test.ts

Impact

Downstream: @suaveplan/r3f-weather renders rain particles, fog, lightning effects driven by WeatherState. Prerequisites: @suaveplan/error, @suaveplan/types, @suaveplan/events, @suaveplan/day-night.