@adatechnology/game-weather 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -2
- package/dist/index.d.ts +181 -2
- package/dist/index.global.js +376 -17
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +210 -17
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/blend.ts","../src/daylight.ts","../src/heat.ts","../src/effects.ts","../src/rng.ts","../src/lightning.ts","../src/data/climates.json","../src/data/states.json","../src/registry.ts","../src/scheduler.ts","../src/wetness.ts","../src/weather.ts","../src/bench/locale.ts","../src/bench/module.ts"],"sourcesContent":["import type { StateValueKey, StateValues, WeatherState } from './types'\n\nexport const STATE_VALUE_KEYS: readonly StateValueKey[] = [\n 'rain',\n 'drops',\n 'sheets',\n 'windX',\n 'windZ',\n 'gust',\n 'fogFar',\n 'fogDensity',\n 'skyScale',\n 'visibility',\n 'humidity',\n 'temperatureDeltaC',\n 'wetness',\n 'hearingScale',\n 'footstepScale',\n 'dryingScale',\n 'debrisPush',\n 'haze',\n 'mistPerSecond',\n 'ashPerSecond',\n]\n\nexport function valuesOf(state: WeatherState): StateValues {\n const values: Record<string, number> = {}\n for (const key of STATE_VALUE_KEYS) values[key] = state[key]\n return values as unknown as StateValues\n}\n\n/** Every number between two states: `progress` 0 is `from`, 1 is `to`. */\nexport function blendValues(from: StateValues, to: StateValues, progress: number): StateValues {\n const amount = Math.min(1, Math.max(0, progress))\n const blended: Record<string, number> = {}\n for (const key of STATE_VALUE_KEYS) blended[key] = from[key] + (to[key] - from[key]) * amount\n return blended as unknown as StateValues\n}\n","/** A game day lasts 20 real minutes in the slice (jogo.js L69127: `dayT + dt / 1200`). */\nexport const DAY_REAL_SECONDS = 1200\nexport const GAME_DAY_SECONDS = 86400\n/** Game seconds per real second of the 20-minute day. */\nexport const DEFAULT_TIME_SCALE = GAME_DAY_SECONDS / DAY_REAL_SECONDS\n\nconst NIGHT_SPAN = 2.2\n\nconst clamp = (value: number, low: number, high: number): number => (value < low ? low : value > high ? high : value)\n\nexport type Daylight = {\n /** Sun height 0..1 (`s` of the game). */\n readonly sun: number\n /** 0 in full daylight, 1 in the darkest night. */\n readonly nightFactor: number\n}\n\n/** jogo.js L69128-L69130: `s = clamp(sin(dayT·2π − π/2)·0.5 + 0.5, 0, 1)`, `nightF = 1 − clamp(s·2.2, 0, 1)`. `dayFraction` 0 is midnight. */\nexport function daylight(dayFraction: number): Daylight {\n const sun = clamp(Math.sin(dayFraction * Math.PI * 2 - Math.PI / 2) * 0.5 + 0.5, 0, 1)\n return { sun, nightFactor: 1 - clamp(sun * NIGHT_SPAN, 0, 1) }\n}\n\n/** The fraction of the day after `gameSeconds` from `startHour`. */\nexport function dayFractionAt(startHour: number, gameSeconds: number): number {\n const fraction = (startHour / 24 + gameSeconds / GAME_DAY_SECONDS) % 1\n return fraction < 0 ? fraction + 1 : fraction\n}\n","const HEAT_STRESS_BANDS: ReadonlyArray<readonly [indexC: number, stress: number]> = [\n [27, 0],\n [32, 1 / 3],\n [41, 2 / 3],\n [54, 1],\n]\nconst NOAA_REGRESSION_FROM_F = 80\n\nconst toFahrenheit = (celsius: number): number => (celsius * 9) / 5 + 32\nconst toCelsius = (fahrenheit: number): number => ((fahrenheit - 32) * 5) / 9\n\n/**\n * NOAA heat index in °C: the Steadman estimate averaged with the temperature, and from 80 °F up the Rothfusz regression with the low-humidity and\n * high-humidity adjustments. Built from + - * / and `sqrt` only, so it is the same on every engine.\n */\nexport function heatIndexC(temperatureC: number, relativeHumidityPercent: number): number {\n const t = toFahrenheit(temperatureC)\n const r = relativeHumidityPercent\n const steadman = 0.5 * (t + 61 + (t - 68) * 1.2 + r * 0.094)\n const simple = (steadman + t) / 2\n if (simple < NOAA_REGRESSION_FROM_F) return toCelsius(simple)\n let index =\n -42.379 +\n 2.04901523 * t +\n 10.14333127 * r -\n 0.22475541 * t * r -\n 0.00683783 * t * t -\n 0.05481717 * r * r +\n 0.00122874 * t * t * r +\n 0.00085282 * t * r * r -\n 0.00000199 * t * t * r * r\n if (r < 13 && t >= 80 && t <= 112) index -= ((13 - r) / 4) * Math.sqrt((17 - Math.abs(t - 95)) / 17)\n else if (r > 85 && t >= 80 && t <= 87) index += ((r - 85) / 10) * ((87 - t) / 5)\n return toCelsius(index)\n}\n\n/** 0..1 across the NOAA bands (caution 27, extreme caution 32, danger 41, extreme danger 54 °C), linear between them. */\nexport function heatStress(heatIndex: number): number {\n const first = HEAT_STRESS_BANDS[0]!\n const last = HEAT_STRESS_BANDS[HEAT_STRESS_BANDS.length - 1]!\n if (heatIndex <= first[0]) return first[1]\n if (heatIndex >= last[0]) return last[1]\n for (let index = 1; index < HEAT_STRESS_BANDS.length; index++) {\n const [upperC, upperStress] = HEAT_STRESS_BANDS[index]!\n const [lowerC, lowerStress] = HEAT_STRESS_BANDS[index - 1]!\n if (heatIndex <= upperC) return lowerStress + ((heatIndex - lowerC) / (upperC - lowerC)) * (upperStress - lowerStress)\n }\n return last[1]\n}\n","import { heatIndexC, heatStress } from './heat'\nimport type { StateValues, WeatherEffects } from './types'\n\n/** Gameplay visibility of a dry day (the game's dry fog far, jogo.js L69141): `sightScale` is the visibility against it. */\nexport const DRY_VISIBILITY_METERS = 220\n/** jogo.js L66872: sight is `perc[0] × (1 − 0.4 × nightF)`. */\nexport const NIGHT_SIGHT_LOSS = 0.4\n\nexport type EffectsInput = {\n readonly values: StateValues\n readonly nightFactor: number\n readonly temperatureC: number\n readonly humidityPercent: number\n readonly lightningReveal: number\n}\n\n/** What the weather means for gameplay, as numbers for whoever has eyes, ears or feet in the world (perception, footsteps, heat). */\nexport function deriveEffects(input: EffectsInput): WeatherEffects {\n const { values, nightFactor } = input\n const weatherSight = Math.min(1, Math.max(0, values.visibility / DRY_VISIBILITY_METERS))\n const heatIndex = heatIndexC(input.temperatureC, input.humidityPercent)\n return {\n visibility: values.visibility,\n sightScale: weatherSight * (1 - NIGHT_SIGHT_LOSS * nightFactor),\n hearingScale: values.hearingScale,\n footstepScale: values.footstepScale,\n heatIndexC: heatIndex,\n heatStress: heatStress(heatIndex),\n lightningReveal: input.lightningReveal,\n dryingScale: values.dryingScale,\n debrisPush: values.debrisPush,\n }\n}\n","const FNV_OFFSET = 0x811c9dc5\nconst FNV_PRIME = 0x01000193\nconst MIX = 0x9e3779b1\n\n/** Deterministic mulberry32 generator; returns floats in [0, 1). */\nexport function createRng(seed: number): () => number {\n let state = seed >>> 0\n return () => {\n state = (state + 0x6d2b79f5) >>> 0\n let mixed = Math.imul(state ^ (state >>> 15), state | 1)\n mixed ^= mixed + Math.imul(mixed ^ (mixed >>> 7), mixed | 61)\n return ((mixed ^ (mixed >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** A seed for the stream called `name`: the same seed gives each name its own sequence, so lightning never shifts the schedule. */\nexport function streamSeed(seed: number, name: string): number {\n let hash = FNV_OFFSET\n for (let index = 0; index < name.length; index++) hash = Math.imul(hash ^ name.charCodeAt(index), FNV_PRIME) >>> 0\n return Math.imul((seed >>> 0) ^ hash, MIX) >>> 0\n}\n\nexport function createStream(seed: number, name: string): () => number {\n return createRng(streamSeed(seed, name))\n}\n\nexport function drawBetween(rng: () => number, range: readonly [min: number, max: number]): number {\n return range[0] + rng() * (range[1] - range[0])\n}\n","import { createStream, drawBetween } from './rng'\nimport type { LightningConfig } from './types'\n\n/** Speed of sound in air, m/s: a physical constant, so it is not configurable. */\nexport const SPEED_OF_SOUND = 343\n\n/** Seconds a flash goes on after a strike before the scene is back to normal (Workshop W1068: `k > .4`). */\nexport const FLASH_END_SECONDS = 0.4\n\n/** Seconds from the flash to the thunder for a strike `distance` metres away. */\nexport function thunderDelay(distance: number): number {\n return distance / SPEED_OF_SOUND\n}\n\n/** The Workshop double flash (W1068): full for 0.08 s, 0.2 until 0.16 s, 0.8 until 0.26 s, then dark. `elapsed` is seconds since the strike. */\nexport function flashIntensity(elapsed: number): number {\n if (elapsed < 0 || elapsed >= FLASH_END_SECONDS) return 0\n if (elapsed < 0.08) return 1\n if (elapsed < 0.16) return 0.2\n if (elapsed < 0.26) return 0.8\n return 0\n}\n\nexport type LightningStream = {\n /** Seconds from entering a state with lightning to its first strike. */\n first(config: LightningConfig): number\n /** Seconds from a strike to the next one. */\n interval(config: LightningConfig): number\n /** Where a strike lands: metres and degrees clockwise from north. Draws the distance, then the bearing. */\n place(config: LightningConfig): { readonly distance: number; readonly bearing: number }\n}\n\n/** The lightning's own seeded stream, apart from the scheduler's: the server can send the seed and every client sees the same strikes. */\nexport function createLightningStream(seed: number): LightningStream {\n const rng = createStream(seed, 'lightning')\n return {\n first: (config) => drawBetween(rng, config.first),\n interval: (config) => drawBetween(rng, config.interval),\n place(config) {\n const distance = drawBetween(rng, config.distance)\n return { distance, bearing: rng() * 360 }\n },\n }\n}\n","[\n {\n \"id\": \"temperate\",\n \"sources\": [\"galeria-vale-cinzento:L1393 (changes every 2-6 h, arrives from the west)\", \"design:T6 3.2 kit default: mostly clear and overcast, no extremes\"],\n \"start\": \"clear\",\n \"dwellHours\": [2, 6],\n \"blendMinutes\": 10,\n \"frontDirection\": [1, 0],\n \"temperatureC\": { \"mean\": 16, \"swing\": 6 },\n \"humidityOffset\": 0,\n \"transitions\": {\n \"clear\": { \"overcast\": 4, \"windy\": 1, \"fog\": 1, \"light_rain\": 1 },\n \"overcast\": { \"clear\": 3, \"light_rain\": 3, \"heavy_rain\": 1, \"fog\": 1, \"windy\": 1 },\n \"light_rain\": { \"overcast\": 3, \"clear\": 2, \"heavy_rain\": 2 },\n \"heavy_rain\": { \"light_rain\": 3, \"overcast\": 2, \"storm\": 1 },\n \"storm\": { \"heavy_rain\": 3, \"light_rain\": 2, \"overcast\": 1 },\n \"fog\": { \"clear\": 3, \"overcast\": 2 },\n \"windy\": { \"clear\": 3, \"overcast\": 3, \"light_rain\": 1 }\n }\n },\n {\n \"id\": \"tropical\",\n \"sources\": [\"galeria-vale-cinzento:L1393 (changes every 2-6 h, arrives from the west)\", \"design:T6 3.2 and Q3: extremes rare and enabled\"],\n \"start\": \"clear\",\n \"dwellHours\": [2, 6],\n \"blendMinutes\": 10,\n \"frontDirection\": [1, 0],\n \"temperatureC\": { \"mean\": 29, \"swing\": 3 },\n \"humidityOffset\": 0.1,\n \"transitions\": {\n \"clear\": { \"overcast\": 3, \"light_rain\": 2, \"windy\": 1, \"extreme_heat\": 0.8 },\n \"overcast\": { \"clear\": 3, \"light_rain\": 3, \"heavy_rain\": 2, \"fog\": 0.5 },\n \"light_rain\": { \"overcast\": 3, \"clear\": 2, \"heavy_rain\": 2 },\n \"heavy_rain\": { \"light_rain\": 3, \"overcast\": 2, \"storm\": 1.5 },\n \"storm\": { \"heavy_rain\": 3, \"light_rain\": 2, \"overcast\": 1, \"cyclone\": 0.5 },\n \"fog\": { \"clear\": 3, \"overcast\": 2 },\n \"windy\": { \"clear\": 3, \"overcast\": 2, \"light_rain\": 1, \"storm\": 0.5 },\n \"extreme_heat\": { \"clear\": 4, \"overcast\": 2, \"storm\": 0.8 },\n \"cyclone\": { \"storm\": 3, \"heavy_rain\": 2, \"typhoon\": 0.5 },\n \"typhoon\": { \"cyclone\": 3, \"storm\": 2 }\n }\n }\n]\n","[\n {\n \"id\": \"clear\",\n \"sources\": [\"jogo:L69141 (fog far 220 dry)\", \"showroom.js:L1693-1710 (breeze 3.5, 1.5 m/s)\"],\n \"rain\": 0, \"drops\": 0, \"sheets\": 0,\n \"windX\": 3.5, \"windZ\": 1.5, \"gust\": 5,\n \"fogFar\": 220, \"fogDensity\": 0, \"skyScale\": 1, \"visibility\": 220,\n \"humidity\": 0.5, \"temperatureDeltaC\": 0, \"wetness\": 0,\n \"hearingScale\": 1, \"footstepScale\": 1, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n },\n {\n \"id\": \"overcast\",\n \"sources\": [\"cena-de-arte:L413 (wind .35, .12)\", \"cena-de-arte:L36 (FogExp2 .03)\", \"design:T6 sky x0.9\"],\n \"rain\": 0, \"drops\": 0, \"sheets\": 0,\n \"windX\": 0.35, \"windZ\": 0.12, \"gust\": 0.6,\n \"fogFar\": 220, \"fogDensity\": 0.03, \"skyScale\": 0.9, \"visibility\": 200,\n \"humidity\": 0.65, \"temperatureDeltaC\": -1, \"wetness\": 0,\n \"hearingScale\": 1, \"footstepScale\": 1, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n },\n {\n \"id\": \"light_rain\",\n \"sources\": [\"oficina-vfx:W1065 (Garoa: 900 drops, slant .3)\", \"jogo:L70416-70427 (rain level .035)\", \"design:T6 2.5 mm/h, wetness .35, visibility 160, hearing x0.8 (Q4)\"],\n \"rain\": 2.5, \"drops\": 900, \"sheets\": 0,\n \"windX\": 0.3, \"windZ\": 0, \"gust\": 0.6,\n \"fogFar\": 180, \"fogDensity\": 0, \"skyScale\": 0.9, \"visibility\": 160,\n \"humidity\": 0.85, \"temperatureDeltaC\": -2, \"wetness\": 0.35,\n \"hearingScale\": 0.8, \"footstepScale\": 0.85, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n },\n {\n \"id\": \"heavy_rain\",\n \"sources\": [\"oficina-vfx:W1065 (Chuva: 2200 drops, slant 1.2)\", \"cena-de-arte:L1314 (rain gain .06)\", \"jogo:L69141 (fog far 140, sky x0.8)\", \"galeria-vale-cinzento:L1393 (vision 120 m, quieter steps)\", \"design:T6 15 mm/h, hearing x0.6 (Q4)\"],\n \"rain\": 15, \"drops\": 2200, \"sheets\": 0,\n \"windX\": 1.2, \"windZ\": 0, \"gust\": 2,\n \"fogFar\": 140, \"fogDensity\": 0, \"skyScale\": 0.8, \"visibility\": 120,\n \"humidity\": 0.9, \"temperatureDeltaC\": -4, \"wetness\": 0.8,\n \"hearingScale\": 0.6, \"footstepScale\": 0.7, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n },\n {\n \"id\": \"storm\",\n \"sources\": [\"oficina-vfx:W1065-1069 (Temporal: 4000 drops, slant 4.5, lightning 3.5-6 s, first at 2-4 s, sheets)\", \"showroom.js (60 mm/h)\", \"design:T6 hearing x0.5 (Q4)\"],\n \"rain\": 60, \"drops\": 4000, \"sheets\": 1,\n \"windX\": 4.5, \"windZ\": 0, \"gust\": 6,\n \"fogFar\": 110, \"fogDensity\": 0, \"skyScale\": 0.7, \"visibility\": 100,\n \"humidity\": 0.92, \"temperatureDeltaC\": -5, \"wetness\": 1,\n \"hearingScale\": 0.5, \"footstepScale\": 0.6, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0,\n \"lightning\": { \"interval\": [3.5, 6], \"first\": [2, 4], \"distance\": [200, 4000], \"reveal\": 0.2 }\n },\n {\n \"id\": \"fog\",\n \"sources\": [\"oficina-vfx:W1073-1080 (density .075, ground mist 5/s, ash 14/s)\", \"jogo:L69101 (zone fog far 60)\"],\n \"rain\": 0, \"drops\": 0, \"sheets\": 0,\n \"windX\": 0.3, \"windZ\": 0.1, \"gust\": 0.5,\n \"fogFar\": 60, \"fogDensity\": 0.075, \"skyScale\": 0.85, \"visibility\": 40,\n \"humidity\": 0.95, \"temperatureDeltaC\": -3, \"wetness\": 0.15,\n \"hearingScale\": 1, \"footstepScale\": 1, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 5, \"ashPerSecond\": 14\n },\n {\n \"id\": \"windy\",\n \"sources\": [\"cena-de-arte:L1315 (wind loop)\", \"design:T6 Q3 8 m/s, gust 12\"],\n \"rain\": 0, \"drops\": 0, \"sheets\": 0,\n \"windX\": 8, \"windZ\": 0, \"gust\": 12,\n \"fogFar\": 220, \"fogDensity\": 0, \"skyScale\": 1, \"visibility\": 220,\n \"humidity\": 0.45, \"temperatureDeltaC\": -1, \"wetness\": 0,\n \"hearingScale\": 0.85, \"footstepScale\": 0.9, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n },\n {\n \"id\": \"cyclone\",\n \"sources\": [\"design:T6 Q3 physics preset, no team source: tropical cyclone 33 m/s sustained, gust x1.3, storm rain, debris push\"],\n \"rain\": 60, \"drops\": 4000, \"sheets\": 1,\n \"windX\": 33, \"windZ\": 0, \"gust\": 42.9,\n \"fogFar\": 80, \"fogDensity\": 0, \"skyScale\": 0.6, \"visibility\": 60,\n \"humidity\": 0.9, \"temperatureDeltaC\": 0, \"wetness\": 1,\n \"hearingScale\": 0.3, \"footstepScale\": 0.5, \"dryingScale\": 1, \"debrisPush\": 8,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0,\n \"lightning\": { \"interval\": [3.5, 6], \"first\": [2, 4], \"distance\": [200, 4000], \"reveal\": 0.2 }\n },\n {\n \"id\": \"typhoon\",\n \"sources\": [\"design:T6 Q3 physics preset, no team source: typhoon 50 m/s sustained, gust x1.3, storm rain, debris push\"],\n \"rain\": 60, \"drops\": 4000, \"sheets\": 1,\n \"windX\": 50, \"windZ\": 0, \"gust\": 65,\n \"fogFar\": 60, \"fogDensity\": 0, \"skyScale\": 0.5, \"visibility\": 40,\n \"humidity\": 0.9, \"temperatureDeltaC\": 0, \"wetness\": 1,\n \"hearingScale\": 0.25, \"footstepScale\": 0.4, \"dryingScale\": 1, \"debrisPush\": 18,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0,\n \"lightning\": { \"interval\": [3.5, 6], \"first\": [2, 4], \"distance\": [200, 4000], \"reveal\": 0.2 }\n },\n {\n \"id\": \"extreme_heat\",\n \"sources\": [\"design:T6 Q3 no team source: 38 C at the tropical noon (+6 over the climate), 60 % humidity, haze, drying x2\"],\n \"rain\": 0, \"drops\": 0, \"sheets\": 0,\n \"windX\": 0.8, \"windZ\": 0.3, \"gust\": 1.5,\n \"fogFar\": 220, \"fogDensity\": 0, \"skyScale\": 1, \"visibility\": 200,\n \"humidity\": 0.6, \"temperatureDeltaC\": 6, \"wetness\": 0,\n \"hearingScale\": 1, \"footstepScale\": 1, \"dryingScale\": 2, \"debrisPush\": 0,\n \"haze\": 1, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n }\n]\n","import climatesJson from './data/climates.json'\nimport statesJson from './data/states.json'\nimport type { Climate, DeepPartial, WeatherState } from './types'\n\nexport const WEATHER_STATES: readonly WeatherState[] = statesJson as unknown as readonly WeatherState[]\nexport const CLIMATES: readonly Climate[] = climatesJson as unknown as readonly Climate[]\n\nexport type RegistryOptions = {\n /** Added to the shipped states or, when the id exists, replacing it. */\n readonly states?: readonly WeatherState[]\n readonly climates?: readonly Climate[]\n /** Merged into a shipped or added entry by id; a patch for an id that does not exist is ignored. */\n readonly patch?: {\n readonly states?: Readonly<Record<string, DeepPartial<WeatherState>>>\n readonly climates?: Readonly<Record<string, DeepPartial<Climate>>>\n }\n readonly remove?: { readonly states?: readonly string[]; readonly climates?: readonly string[] }\n}\n\nexport type WeatherRegistry = {\n state(id: string): WeatherState | undefined\n climate(id: string): Climate | undefined\n stateIds(): string[]\n climateIds(): string[]\n registerState(state: WeatherState): void\n registerClimate(climate: Climate): void\n patchState(id: string, patch: DeepPartial<WeatherState>): void\n patchClimate(id: string, patch: DeepPartial<Climate>): void\n removeState(id: string): void\n removeClimate(id: string): void\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction mergeRecords(base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...base }\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) continue\n const current = merged[key]\n merged[key] = isPlainObject(current) && isPlainObject(value) ? mergeRecords(current, value) : value\n }\n return merged\n}\n\nfunction deepMerge<TValue>(base: TValue, patch: DeepPartial<TValue>): TValue {\n return mergeRecords(base as Record<string, unknown>, patch as Record<string, unknown>) as TValue\n}\n\ntype Entry = { readonly id: string }\n\nfunction createTable<TEntry extends Entry>(shipped: readonly TEntry[]): Map<string, TEntry> {\n return new Map(shipped.map((entry) => [entry.id, entry]))\n}\n\nfunction patchEntry<TEntry extends Entry>(table: Map<string, TEntry>, id: string, patch: DeepPartial<TEntry>): void {\n const entry = table.get(id)\n if (entry) table.set(id, deepMerge(entry, patch))\n}\n\n/** The shipped states and climates with yours added, patched or removed; change it later with the same verbs. */\nexport function createWeatherRegistry(options: RegistryOptions = {}): WeatherRegistry {\n const states = createTable(WEATHER_STATES)\n const climates = createTable(CLIMATES)\n for (const state of options.states ?? []) states.set(state.id, state)\n for (const climate of options.climates ?? []) climates.set(climate.id, climate)\n for (const [id, patch] of Object.entries(options.patch?.states ?? {})) patchEntry(states, id, patch)\n for (const [id, patch] of Object.entries(options.patch?.climates ?? {})) patchEntry(climates, id, patch)\n for (const id of options.remove?.states ?? []) states.delete(id)\n for (const id of options.remove?.climates ?? []) climates.delete(id)\n return {\n state: (id) => states.get(id),\n climate: (id) => climates.get(id),\n stateIds: () => [...states.keys()],\n climateIds: () => [...climates.keys()],\n registerState: (state) => void states.set(state.id, state),\n registerClimate: (climate) => void climates.set(climate.id, climate),\n patchState: (id, patch) => patchEntry(states, id, patch),\n patchClimate: (id, patch) => patchEntry(climates, id, patch),\n removeState: (id) => void states.delete(id),\n removeClimate: (id) => void climates.delete(id),\n }\n}\n","import { createStream, drawBetween } from './rng'\nimport type { Climate } from './types'\n\nconst SECONDS_PER_HOUR = 3600\n/** A state lasts at least this long, so a climate patched to a zero dwell cannot stall the clock. */\nconst MIN_DWELL_SECONDS = 1\n\nexport type Scheduler = {\n /** Game seconds at which the current state ends. */\n nextChangeAt(): number\n /** Picks the state after `current`, then draws how long it lasts from `at`. Returns the new state's id. */\n next(current: string, at: number): string\n /** Draws a new duration from `at` (after a forced change). */\n restart(at: number): void\n}\n\n/**\n * A seeded Markov chain in game time. Draw order, fixed so the timeline repeats: at start one dwell; at each change the next state first\n * (one draw, over the weights in the climate's order), then its dwell. States `isKnown` rejects are left out of the weights.\n */\nexport function createScheduler(climate: Climate, seed: number, isKnown: (id: string) => boolean): Scheduler {\n const rng = createStream(seed, 'schedule')\n let changeAt = 0\n const drawDwell = (from: number): number => from + Math.max(MIN_DWELL_SECONDS, drawBetween(rng, climate.dwellHours) * SECONDS_PER_HOUR)\n changeAt = drawDwell(0)\n return {\n nextChangeAt: () => changeAt,\n next(current, at) {\n const options = Object.entries(climate.transitions[current] ?? {}).filter(([id, weight]) => weight > 0 && isKnown(id))\n const total = options.reduce((sum, [, weight]) => sum + weight, 0)\n let chosen = current\n if (total > 0) {\n let pick = rng() * total\n chosen = options[options.length - 1]![0]\n for (const [id, weight] of options) {\n if (pick < weight) {\n chosen = id\n break\n }\n pick -= weight\n }\n }\n changeAt = drawDwell(at)\n return chosen\n },\n restart(at) {\n changeAt = drawDwell(at)\n },\n }\n}\n","export const DEFAULT_WET_RISE_SECONDS = 120\n/** The Workshop sheet: the water goes back to the colour of the ground 3 minutes after the rain stops. */\nexport const DEFAULT_DRY_OUT_SECONDS = 180\n\nexport type WetnessOptions = {\n /** Seconds of rain to wet the ground fully. */\n readonly riseSeconds?: number\n /** Seconds from the end of the rain until the ground is dry. */\n readonly dryOutSeconds?: number\n}\n\nexport type Wetness = {\n value(): number\n /** Moves `seconds` toward `target` (the wetness the weather asks for); `dryingScale` speeds the dry-out up. Returns the new value. */\n update(seconds: number, target: number, dryingScale?: number): number\n reset(value?: number): void\n}\n\n/** Ground wetness: rises while the weather asks for more, then falls in a straight line that ends `dryOutSeconds` after the start of the fall. */\nexport function createWetness(options: WetnessOptions = {}): Wetness {\n const riseSeconds = options.riseSeconds ?? DEFAULT_WET_RISE_SECONDS\n const dryOutSeconds = options.dryOutSeconds ?? DEFAULT_DRY_OUT_SECONDS\n let current = 0\n let peak = 0\n let isDrying = false\n return {\n value: () => current,\n update(seconds, target, dryingScale = 1) {\n if (target > current) {\n isDrying = false\n current = Math.min(target, current + seconds / riseSeconds)\n } else if (target < current) {\n if (!isDrying) {\n isDrying = true\n peak = current\n }\n current = Math.max(target, current - (peak * seconds * dryingScale) / dryOutSeconds)\n } else isDrying = false\n return current\n },\n reset(value = 0) {\n current = value\n peak = value\n isDrying = false\n },\n }\n}\n","import { blendValues, valuesOf } from './blend'\nimport { DEFAULT_TIME_SCALE, daylight, dayFractionAt } from './daylight'\nimport { deriveEffects } from './effects'\nimport { createLightningStream, flashIntensity, thunderDelay } from './lightning'\nimport { createWeatherRegistry } from './registry'\nimport type { RegistryOptions, WeatherRegistry } from './registry'\nimport { createScheduler } from './scheduler'\nimport type { Climate, StateValues, Strike, WeatherEventMap, WeatherSample, WeatherState } from './types'\nimport { createWetness } from './wetness'\nimport type { WetnessOptions } from './wetness'\n\nexport const DEFAULT_START_HOUR = 8\nconst SECONDS_PER_MINUTE = 60\nconst WETNESS_STEP_SECONDS = 1\n\nexport type WeatherOptions = RegistryOptions & {\n /** Seed of the schedule and of the lightning (each has its own stream). Default 1. */\n readonly seed?: number\n /** Climate id. Default `temperate`. */\n readonly climate?: string\n /** First state; default the climate's `start`, which is `clear`: the normal world comes first. */\n readonly start?: string\n /** Game seconds per real second. Default 72 (the 20-minute day). */\n readonly timeScale?: number\n /** Hour of the day the world starts at. Default 8. */\n readonly startHour?: number\n /** `false` keeps the state until `force` changes it. Default true. */\n readonly autoSchedule?: boolean\n readonly wetness?: WetnessOptions\n /** An existing registry, instead of building one from the registry options. */\n readonly registry?: WeatherRegistry\n}\n\nexport type WeatherTimeline = {\n readonly seed: number\n readonly climate: string\n readonly start: string\n readonly hours: number\n readonly sampleMinutes: number\n readonly transitions: ReadonlyArray<{ readonly gameSeconds: number; readonly from: string; readonly to: string }>\n readonly strikes: readonly Strike[]\n readonly samples: ReadonlyArray<Readonly<Record<string, number | string>>>\n}\n\nexport type Weather = {\n readonly registry: WeatherRegistry\n /** Moves the world forward by `dt` real seconds (game time moves `timeScale` times as fast). Events fire in order as they are crossed. */\n advance(dt: number): void\n sample(): WeatherSample\n /** The state being blended to, or settled in. */\n state(): string\n /** Changes state now, blending over `blendSeconds` real seconds (0 is at once); the new state then lasts a normal dwell. */\n force(id: string, blendSeconds?: number): void\n setTimeScale(timeScale: number): void\n setAutoSchedule(isOn: boolean): void\n /** What a fresh world with these options does over `hours` game hours; the live world is not touched. */\n timeline(hours: number, sampleMinutes?: number): WeatherTimeline\n on<TEvent extends keyof WeatherEventMap>(event: TEvent, listener: (payload: WeatherEventMap[TEvent]) => void): () => void\n}\n\ntype Blend = { startedAt: number; duration: number }\n\nconst clamp01 = (value: number): number => Math.min(1, Math.max(0, value))\n\nfunction requireClimate(registry: WeatherRegistry, id: string): Climate {\n const climate = registry.climate(id)\n if (!climate) throw new Error(`game-weather: unknown climate \"${id}\"`)\n return climate\n}\n\nfunction requireState(registry: WeatherRegistry, id: string): WeatherState {\n const state = registry.state(id)\n if (!state) throw new Error(`game-weather: unknown state \"${id}\"`)\n return state\n}\n\nexport function createWeather(options: WeatherOptions = {}): Weather {\n const registry = options.registry ?? createWeatherRegistry(options)\n const seed = options.seed ?? 1\n const climateId = options.climate ?? 'temperate'\n const startClimate = requireClimate(registry, climateId)\n const startState = requireState(registry, options.start ?? startClimate.start)\n const startHour = options.startHour ?? DEFAULT_START_HOUR\n const scheduler = createScheduler(startClimate, seed, (id) => registry.state(id) !== undefined)\n const lightning = createLightningStream(seed)\n const wetness = createWetness(options.wetness)\n const listeners = new Map<keyof WeatherEventMap, Set<(payload: never) => void>>()\n\n let timeScale = options.timeScale ?? DEFAULT_TIME_SCALE\n let isAutoSchedule = options.autoSchedule ?? true\n let gameSeconds = 0\n let simSeconds = 0\n let target = startState\n let targetValues = valuesOf(startState)\n let fromValues: StateValues = targetValues\n let previousId: string | undefined\n let blend: Blend = { startedAt: 0, duration: 0 }\n let nextStrikeAt: number | undefined\n let strikeCount = 0\n let lastStrike: Strike | undefined\n const pendingThunder: Strike[] = []\n\n const climate = (): Climate => registry.climate(climateId) ?? startClimate\n\n const emit = <TEvent extends keyof WeatherEventMap>(event: TEvent, payload: WeatherEventMap[TEvent]): void => {\n for (const listener of [...(listeners.get(event) ?? [])]) (listener as (value: WeatherEventMap[TEvent]) => void)(payload)\n }\n\n const progressAt = (at: number): number => (blend.duration <= 0 ? 1 : clamp01((at - blend.startedAt) / blend.duration))\n const valuesAt = (at: number): StateValues => blendValues(fromValues, targetValues, progressAt(at))\n\n const scheduleFirstStrike = (atSim: number): void => {\n nextStrikeAt = target.lightning ? atSim + lightning.first(target.lightning) : undefined\n }\n\n const enter = (id: string, atGame: number, atSim: number, blendGameSeconds: number): void => {\n const next = requireState(registry, id)\n fromValues = valuesAt(atGame)\n previousId = target.id\n target = next\n targetValues = valuesOf(next)\n blend = { startedAt: atGame, duration: blendGameSeconds }\n scheduleFirstStrike(atSim)\n emit('transition', { from: previousId, to: id, gameSeconds: atGame })\n }\n\n const strikeAt = (atSim: number, startGame: number, startSim: number): void => {\n const config = target.lightning!\n const place = lightning.place(config)\n const strike: Strike = {\n id: strikeCount++,\n time: atSim,\n gameSeconds: startGame + (atSim - startSim) * timeScale,\n distance: place.distance,\n bearing: place.bearing,\n thunderDelay: thunderDelay(place.distance),\n }\n lastStrike = strike\n pendingThunder.push(strike)\n pendingThunder.sort((a, b) => a.time + a.thunderDelay - (b.time + b.thunderDelay))\n nextStrikeAt = atSim + lightning.interval(config)\n emit('strike', strike)\n }\n\n scheduleFirstStrike(0)\n\n const runEvents = (startGame: number, startSim: number, endSim: number): void => {\n for (;;) {\n const changeSim = isAutoSchedule ? Math.max(startSim, startSim + (scheduler.nextChangeAt() - startGame) / timeScale) : Infinity\n const strikeSim = nextStrikeAt ?? Infinity\n const thunder = pendingThunder[0]\n const thunderSim = thunder ? thunder.time + thunder.thunderDelay : Infinity\n const earliest = Math.min(changeSim, strikeSim, thunderSim)\n if (earliest > endSim) return\n if (earliest === changeSim) {\n const atGame = Math.max(startGame, scheduler.nextChangeAt())\n const next = scheduler.next(target.id, atGame)\n enter(next, atGame, changeSim, climate().blendMinutes * SECONDS_PER_MINUTE)\n } else if (earliest === strikeSim) strikeAt(strikeSim, startGame, startSim)\n else emit('thunder', pendingThunder.shift()!)\n }\n }\n\n const wet = (startGame: number, endGame: number, seconds: number): void => {\n const steps = Math.max(1, Math.ceil(seconds / WETNESS_STEP_SECONDS))\n for (let step = 1; step <= steps; step++) {\n const values = valuesAt(startGame + ((endGame - startGame) * step) / steps)\n wetness.update(seconds / steps, values.wetness, values.dryingScale)\n }\n }\n\n const api: Weather = {\n registry,\n advance(dt) {\n if (!(dt > 0)) return\n const startGame = gameSeconds\n const startSim = simSeconds\n const endGame = startGame + dt * timeScale\n runEvents(startGame, startSim, startSim + dt)\n gameSeconds = endGame\n simSeconds = startSim + dt\n wet(startGame, endGame, dt)\n },\n sample() {\n const values = valuesAt(gameSeconds)\n const dayFraction = dayFractionAt(startHour, gameSeconds)\n const { sun, nightFactor } = daylight(dayFraction)\n const current = climate()\n const temperatureC = current.temperatureC.mean + current.temperatureC.swing * (2 * sun - 1) + values.temperatureDeltaC\n const humidityPercent = clamp01(values.humidity + current.humidityOffset) * 100\n const progress = progressAt(gameSeconds)\n return {\n ...values,\n gameSeconds,\n dayFraction,\n hour: dayFraction * 24,\n nightFactor,\n sun,\n state: target.id,\n previous: progress < 1 ? previousId : undefined,\n blend: progress,\n front: { direction: current.frontDirection, progress },\n windSpeed: Math.sqrt(values.windX * values.windX + values.windZ * values.windZ),\n temperatureC,\n humidityPercent,\n groundWetness: wetness.value(),\n flash: lastStrike ? flashIntensity(simSeconds - lastStrike.time) : 0,\n effects: deriveEffects({ values, nightFactor, temperatureC, humidityPercent, lightningReveal: target.lightning?.reveal ?? 0 }),\n }\n },\n state: () => target.id,\n force(id, blendSeconds = 0) {\n enter(id, gameSeconds, simSeconds, blendSeconds * timeScale)\n scheduler.restart(gameSeconds)\n },\n setTimeScale(next) {\n if (!(next > 0)) throw new Error('game-weather: timeScale must be above 0')\n timeScale = next\n },\n setAutoSchedule(isOn) {\n if (isOn && !isAutoSchedule) scheduler.restart(gameSeconds)\n isAutoSchedule = isOn\n },\n timeline: (hours, sampleMinutes) => createTimeline({ ...options, registry, hours, ...(sampleMinutes === undefined ? {} : { sampleMinutes }) }),\n on(event, listener) {\n const set = listeners.get(event) ?? new Set()\n set.add(listener as (payload: never) => void)\n listeners.set(event, set)\n return () => void set.delete(listener as (payload: never) => void)\n },\n }\n return api\n}\n\nexport type TimelineOptions = WeatherOptions & {\n readonly hours: number\n /** Game minutes between samples. Default 10. */\n readonly sampleMinutes?: number\n}\n\nconst TIMELINE_DECIMALS = 6\nconst round = (value: number): number => Math.round(value * 10 ** TIMELINE_DECIMALS) / 10 ** TIMELINE_DECIMALS + 0\n\n/**\n * What a fresh world does over `hours` game hours, stepping one game minute at a time: the state changes, the strikes (time, distance, bearing) and\n * a sample every `sampleMinutes`. Plain JSON, rounded to 6 decimals, so it can be a golden.\n */\nexport function createTimeline(options: TimelineOptions): WeatherTimeline {\n const weather = createWeather(options)\n const timeScale = options.timeScale ?? DEFAULT_TIME_SCALE\n const sampleMinutes = options.sampleMinutes ?? 10\n const transitions: Array<{ gameSeconds: number; from: string; to: string }> = []\n const strikes: Strike[] = []\n weather.on('transition', (event) => transitions.push({ gameSeconds: round(event.gameSeconds), from: event.from, to: event.to }))\n weather.on('strike', (strike) =>\n strikes.push({ id: strike.id, time: round(strike.time), gameSeconds: round(strike.gameSeconds), distance: round(strike.distance), bearing: round(strike.bearing), thunderDelay: round(strike.thunderDelay) }),\n )\n const samples: Array<Record<string, number | string>> = []\n const record = (minute: number): void => {\n const sample = weather.sample()\n samples.push({\n at: minute * SECONDS_PER_MINUTE,\n hour: round(sample.hour),\n state: sample.state,\n blend: round(sample.blend),\n rain: round(sample.rain),\n windSpeed: round(sample.windSpeed),\n gust: round(sample.gust),\n visibility: round(sample.effects.visibility),\n sightScale: round(sample.effects.sightScale),\n hearingScale: round(sample.effects.hearingScale),\n temperatureC: round(sample.temperatureC),\n heatIndexC: round(sample.effects.heatIndexC),\n heatStress: round(sample.effects.heatStress),\n wetness: round(sample.groundWetness),\n nightFactor: round(sample.nightFactor),\n })\n }\n record(0)\n const minutes = Math.round(options.hours * 60)\n for (let minute = 1; minute <= minutes; minute++) {\n weather.advance(SECONDS_PER_MINUTE / timeScale)\n if (minute % sampleMinutes === 0) record(minute)\n }\n return {\n seed: options.seed ?? 1,\n climate: options.climate ?? 'temperate',\n start: options.start ?? weather.registry.climate(options.climate ?? 'temperate')!.start,\n hours: options.hours,\n sampleMinutes,\n transitions,\n strikes,\n samples,\n }\n}\n","export type WeatherBenchText = {\n readonly group: string\n readonly name: string\n readonly controls: Readonly<Record<'state' | 'transition' | 'time_of_day' | 'auto_schedule' | 'seed', string>>\n readonly hints: Readonly<Record<'transition' | 'time_of_day' | 'auto_schedule' | 'seed', string>>\n readonly options: Readonly<Record<'instant' | 'ten_seconds', string>>\n readonly layers: Readonly<Record<'environment' | 'fog', string>>\n readonly metrics: Readonly<Record<'state' | 'hour' | 'rain' | 'visibility' | 'sight' | 'hearing' | 'wind' | 'heat_index' | 'wetness' | 'strikes' | 'blend' | 'temperature', string>>\n readonly scenarios: Readonly<Record<'storm' | 'blend' | 'determinism' | 'dry_ground', string>>\n /** Names of the states and climates by id; the bench falls back to the id. */\n readonly states: Readonly<Record<string, string>>\n}\n\nconst EN: WeatherBenchText = {\n group: 'Weather',\n name: 'Weather area',\n controls: { state: 'Weather', transition: 'Transition', time_of_day: 'Time of day', auto_schedule: 'Automatic schedule', seed: 'Seed' },\n hints: {\n transition: 'How long the change to the chosen weather takes, in real seconds.',\n time_of_day: 'Hour of the day (the world restarts the clock there and keeps the weather).',\n auto_schedule: 'On: the climate changes the weather by itself and the clock runs 600 times faster than real time. Off: the weather stays until you change it.',\n seed: 'The same seed gives the same schedule and the same lightning.',\n },\n options: { instant: 'At once', ten_seconds: '10 seconds' },\n layers: { environment: 'Write host environment', fog: 'Fog in the scene' },\n metrics: {\n state: 'Weather',\n hour: 'Hour',\n rain: 'Rain',\n visibility: 'Visibility',\n sight: 'Sight scale',\n hearing: 'Hearing scale',\n wind: 'Wind',\n heat_index: 'Heat index',\n wetness: 'Ground wetness',\n strikes: 'Lightning strikes',\n blend: 'Blend',\n temperature: 'Temperature',\n },\n scenarios: {\n storm: 'A storm sees less and is heard less than a clear day, and strikes lightning',\n blend: 'A change blends over its time and settles in the new weather',\n determinism: 'The same seed gives the same day, another seed another one',\n dry_ground: 'Rain wets the ground and it dries after the rain stops',\n },\n states: {\n clear: 'Clear',\n overcast: 'Overcast',\n light_rain: 'Light rain',\n heavy_rain: 'Heavy rain',\n storm: 'Storm',\n fog: 'Fog',\n windy: 'Windy',\n cyclone: 'Cyclone',\n typhoon: 'Typhoon',\n extreme_heat: 'Extreme heat',\n },\n}\n\nconst PT_BR: WeatherBenchText = {\n group: 'Clima',\n name: 'Área de clima',\n controls: { state: 'Clima', transition: 'Transição', time_of_day: 'Hora do dia', auto_schedule: 'Sorteio automático', seed: 'Semente' },\n hints: {\n transition: 'Quanto demora a mudança para o clima escolhido, em segundos reais.',\n time_of_day: 'Hora do dia (o mundo reinicia o relógio nela e mantém o clima).',\n auto_schedule: 'Ligado: o clima do lugar muda sozinho e o relógio corre 600 vezes mais rápido que o real. Desligado: o clima fica até você trocar.',\n seed: 'A mesma semente dá o mesmo sorteio e os mesmos raios.',\n },\n options: { instant: 'De uma vez', ten_seconds: '10 segundos' },\n layers: { environment: 'Escrever no ambiente do host', fog: 'Névoa na cena' },\n metrics: {\n state: 'Clima',\n hour: 'Hora',\n rain: 'Chuva',\n visibility: 'Visibilidade',\n sight: 'Escala de visão',\n hearing: 'Escala de audição',\n wind: 'Vento',\n heat_index: 'Índice de calor',\n wetness: 'Chão molhado',\n strikes: 'Raios',\n blend: 'Mistura',\n temperature: 'Temperatura',\n },\n scenarios: {\n storm: 'Tempestade enxerga e é ouvida menos que um dia limpo, e solta raios',\n blend: 'Uma mudança se mistura no tempo dela e assenta no clima novo',\n determinism: 'A mesma semente dá o mesmo dia, outra semente dá outro',\n dry_ground: 'A chuva molha o chão e ele seca depois que a chuva para',\n },\n states: {\n clear: 'Limpo',\n overcast: 'Nublado',\n light_rain: 'Chuva fraca',\n heavy_rain: 'Chuva forte',\n storm: 'Tempestade',\n fog: 'Neblina',\n windy: 'Ventania',\n cyclone: 'Ciclone',\n typhoon: 'Tufão',\n extreme_heat: 'Calor extremo',\n },\n}\n\nexport const weatherBenchTextOf = (locale: string): WeatherBenchText => (locale === 'en' ? EN : PT_BR)\n","import type { BenchChange, EnvironmentBus, ModuleControl, ModuleHost, ModuleLayer, ModuleMetric, ModuleScenario, TestableModule } from '@adatechnology/game-contracts'\n\nimport { createWeather } from '../weather'\nimport type { Weather, WeatherOptions } from '../weather'\nimport type { Strike, WeatherSample } from '../types'\nimport { weatherBenchTextOf } from './locale'\nimport type { WeatherBenchText } from './locale'\n\nexport type WeatherTestModuleOptions = WeatherOptions & {\n locale?: string\n /** Text of a state id in the game's words; without it the bench uses its own names, then the id. */\n translate?: (key: string, locale: string) => string | undefined\n /** The weather to test (default a new one built from the other options). */\n weather?: Weather\n /** Whether the scene fog follows the weather at first (default true; the layer can be switched either way). A room that is not about weather starts it off. */\n fog?: boolean\n}\n\n/** What the scenarios use of the context the test room passes. */\nexport interface WeatherScenarioLike {\n expect(condition: boolean, label: string, data?: Record<string, unknown>): void\n}\n\nexport type WeatherTestModule = TestableModule<WeatherScenarioLike> & {\n /** The weather in use (replaced when the bench changes the seed or the hour). */\n readonly weather: Weather\n}\n\nconst FAST_SCALE = 600\nconst NORMAL_SCALE = 72\nconst BLEND_SECONDS = 10\nconst HOURS_PER_DAY = 24\nconst FOG_NEAR = 1\n\ntype FogLike = new (color: number, near: number, far: number) => { far: number }\ntype SceneLike = { fog?: unknown }\ntype ThreeLike = { Fog?: FogLike }\n\n/**\n * The weather area of a test room, written against the generic contracts only: it drives a `createWeather` world, writes the result into the host's\n * environment bus (`host.environment`) every frame and shows the numbers a game reads from it. It also sets the scene fog from the weather's render fog.\n * Pure: no three.js beyond the host's own `Fog`, and the sky, rain, lightning and sound wait for the packages that draw and play them.\n */\nexport function createWeatherTestModule(options: WeatherTestModuleOptions = {}): WeatherTestModule {\n const locale = options.locale ?? 'pt-BR'\n const text: WeatherBenchText = weatherBenchTextOf(locale)\n const { locale: _locale, translate, weather: given, fog: _fog, ...weatherOptions } = options\n void _locale\n void _fog\n const state = {\n seed: options.seed ?? 1,\n hour: options.startHour ?? 8,\n transition: 0,\n auto: options.autoSchedule ?? false,\n environment: true,\n fog: options.fog ?? true,\n }\n let host: ModuleHost | null = null\n let strikes = 0\n let offStrike: (() => void) | undefined\n let weather: Weather = given ?? createWeather({ ...weatherOptions, autoSchedule: state.auto, ...(state.auto ? { timeScale: FAST_SCALE } : {}) })\n\n const watch = (): void => {\n offStrike?.()\n offStrike = weather.on('strike', (_strike: Strike) => void (strikes += 1))\n }\n watch()\n\n const nameOf = (id: string): string => translate?.(`weather.${id}`, locale) ?? text.states[id] ?? id\n\n // the world restarts with the new seed or hour and keeps the weather it was in\n const rebuild = (): void => {\n const current = weather.state()\n weather = createWeather({ ...weatherOptions, seed: state.seed, start: current, startHour: state.hour, autoSchedule: state.auto, timeScale: state.auto ? FAST_SCALE : NORMAL_SCALE })\n strikes = 0\n watch()\n }\n\n const toEnvironment = (sample: WeatherSample): Parameters<EnvironmentBus['set']>[0] => ({\n rain: sample.rain,\n windX: sample.windX,\n windZ: sample.windZ,\n windSpeed: sample.windSpeed,\n gust: sample.gust,\n fogFar: sample.fogFar,\n visibility: sample.effects.visibility,\n nightFactor: sample.nightFactor,\n temperatureC: sample.temperatureC,\n wetness: sample.groundWetness,\n })\n\n const applyFog = (far: number): void => {\n const scene = host?.scene as SceneLike | undefined\n const Fog = (host?.THREE as ThreeLike | undefined)?.Fog\n if (!scene || typeof Fog !== 'function') return\n const fog = scene.fog as { far: number } | undefined | null\n if (fog && typeof fog.far === 'number') fog.far = far\n else scene.fog = new Fog(0xa8b4c0, FOG_NEAR, far)\n }\n\n const publish = (): void => {\n const sample = weather.sample()\n if (state.environment) host?.environment?.set(toEnvironment(sample))\n if (state.fog) applyFog(sample.fogFar)\n }\n\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'layer') {\n if (change.id === 'environment' || change.id === 'fog') state[change.id] = change.on\n return\n }\n if (change.kind === 'action') return\n const { id, value } = change\n if (id === 'state' && typeof value === 'string') weather.force(value, state.transition)\n else if (id === 'transition' && typeof value === 'string') state.transition = value === 'instant' ? 0 : BLEND_SECONDS\n else if (id === 'time_of_day' && typeof value === 'number') {\n state.hour = value\n rebuild()\n } else if (id === 'auto_schedule' && typeof value === 'boolean') {\n state.auto = value\n weather.setAutoSchedule(value)\n weather.setTimeScale(value ? FAST_SCALE : NORMAL_SCALE)\n } else if (id === 'seed' && typeof value === 'number') {\n state.seed = value\n rebuild()\n }\n }\n\n const controls = (): ModuleControl[] => [\n { kind: 'choice', id: 'state', name: text.controls.state, options: weather.registry.stateIds().map((id) => ({ id, name: nameOf(id) })), default: weather.state() },\n {\n kind: 'choice',\n id: 'transition',\n name: text.controls.transition,\n hint: text.hints.transition,\n options: [\n { id: 'instant', name: text.options.instant },\n { id: 'ten_seconds', name: text.options.ten_seconds },\n ],\n default: 'instant',\n },\n { kind: 'number', id: 'time_of_day', name: text.controls.time_of_day, hint: text.hints.time_of_day, unit: 'h', min: 0, max: HOURS_PER_DAY - 1, step: 1, default: state.hour },\n { kind: 'boolean', id: 'auto_schedule', name: text.controls.auto_schedule, hint: text.hints.auto_schedule, default: state.auto },\n { kind: 'number', id: 'seed', name: text.controls.seed, hint: text.hints.seed, min: 1, max: 9999, step: 1, default: state.seed },\n ]\n\n const layers = (): ModuleLayer[] => [\n { id: 'environment', name: text.layers.environment },\n { id: 'fog', name: text.layers.fog, default: state.fog },\n ]\n\n const metrics = (): ModuleMetric[] => [\n { id: 'current_state', name: text.metrics.state, read: () => nameOf(weather.state()) },\n { id: 'hour', name: text.metrics.hour, unit: 'h', digits: 1, read: () => weather.sample().hour },\n { id: 'blend', name: text.metrics.blend, digits: 2, read: () => weather.sample().blend },\n { id: 'rain', name: text.metrics.rain, unit: 'mm/h', digits: 1, read: () => weather.sample().rain },\n { id: 'visibility', name: text.metrics.visibility, unit: 'm', digits: 0, read: () => weather.sample().effects.visibility },\n { id: 'sight', name: text.metrics.sight, digits: 2, read: () => weather.sample().effects.sightScale },\n { id: 'hearing', name: text.metrics.hearing, digits: 2, read: () => weather.sample().effects.hearingScale },\n { id: 'wind', name: text.metrics.wind, unit: 'm/s', digits: 1, read: () => weather.sample().windSpeed },\n { id: 'temperature', name: text.metrics.temperature, unit: '°C', digits: 1, read: () => weather.sample().temperatureC },\n { id: 'heat_index', name: text.metrics.heat_index, unit: '°C', digits: 1, read: () => weather.sample().effects.heatIndexC },\n { id: 'wetness', name: text.metrics.wetness, digits: 2, read: () => weather.sample().groundWetness },\n { id: 'strikes', name: text.metrics.strikes, digits: 0, read: () => strikes },\n ]\n\n // each scenario runs its own worlds, so the bench's live one is not touched\n const fresh = (extra: WeatherOptions = {}): Weather => createWeather({ ...weatherOptions, autoSchedule: false, ...extra })\n const run = (world: Weather, seconds: number): void => {\n for (let elapsed = 0; elapsed < seconds; elapsed += 0.5) world.advance(0.5)\n }\n\n const scenarios = (): Array<ModuleScenario<WeatherScenarioLike>> => [\n {\n id: 'storm',\n name: text.scenarios.storm,\n run: ({ expect }) => {\n const clear = fresh({ seed: 3, start: 'clear' })\n const storm = fresh({ seed: 3, start: 'storm' })\n let hits = 0\n storm.on('strike', () => void (hits += 1))\n run(storm, 120)\n const calm = clear.sample().effects\n const rough = storm.sample().effects\n expect(rough.visibility < calm.visibility, 'a storm sees less far', { storm: rough.visibility, clear: calm.visibility })\n expect(rough.hearingScale < calm.hearingScale, 'rain masks sound', { storm: rough.hearingScale, clear: calm.hearingScale })\n expect(hits > 0, 'a storm strikes lightning', { strikes: hits })\n },\n },\n {\n id: 'blend',\n name: text.scenarios.blend,\n run: ({ expect }) => {\n const world = fresh({ seed: 3, start: 'clear' })\n world.force('heavy_rain', 10)\n run(world, 5)\n const middle = world.sample()\n expect(middle.blend > 0 && middle.blend < 1, 'halfway through the change it is still blending', { blend: middle.blend })\n expect(middle.rain > 0 && middle.rain < 15, 'the rain is between the two weathers', { rain: middle.rain })\n run(world, 6)\n expect(world.sample().blend === 1 && world.sample().state === 'heavy_rain', 'after its time it has settled', { blend: world.sample().blend })\n },\n },\n {\n id: 'determinism',\n name: text.scenarios.determinism,\n run: ({ expect }) => {\n const day = (seed: number): string => JSON.stringify(createWeather({ ...weatherOptions, seed }).timeline(48).samples)\n expect(day(5) === day(5), 'the same seed gives the same two days')\n expect(day(5) !== day(6), 'another seed gives another one')\n },\n },\n {\n id: 'dry_ground',\n name: text.scenarios.dry_ground,\n run: ({ expect }) => {\n const world = fresh({ seed: 3, start: 'heavy_rain' })\n run(world, 60)\n const wet = world.sample().groundWetness\n expect(wet > 0.3, 'rain wets the ground', { wetness: wet })\n world.force('clear', 0)\n run(world, 600)\n expect(world.sample().groundWetness < wet, 'it dries after the rain stops', { wet, after: world.sample().groundWetness })\n },\n },\n ]\n\n const module: WeatherTestModule = {\n id: 'weather_area',\n name: text.name,\n group: text.group,\n get weather() {\n return weather\n },\n items: () => [],\n controls: () => controls(),\n layers: () => layers(),\n metrics: () => metrics(),\n scenarios: () => scenarios(),\n attach(lent) {\n host = lent\n const off = lent.bench?.onChange(onChange)\n publish()\n const offFrame = lent.onFrame((dt) => {\n weather.advance(dt)\n publish()\n })\n return () => {\n off?.()\n offFrame()\n host = null\n }\n },\n }\n return module\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/blend.ts","../src/daylight.ts","../src/heat.ts","../src/effects.ts","../src/rng.ts","../src/lightning.ts","../src/data/climates.json","../src/data/states.json","../src/registry.ts","../src/scheduler.ts","../src/wetness.ts","../src/weather.ts","../src/audio/recipes.ts","../src/audio/sound.ts","../src/bridges.ts","../src/bench/locale.ts","../src/bench/module.ts"],"sourcesContent":["import type { StateValueKey, StateValues, WeatherState } from './types'\n\nexport const STATE_VALUE_KEYS: readonly StateValueKey[] = [\n 'rain',\n 'drops',\n 'sheets',\n 'windX',\n 'windZ',\n 'gust',\n 'fogFar',\n 'fogDensity',\n 'skyScale',\n 'visibility',\n 'humidity',\n 'temperatureDeltaC',\n 'wetness',\n 'hearingScale',\n 'footstepScale',\n 'dryingScale',\n 'debrisPush',\n 'haze',\n 'mistPerSecond',\n 'ashPerSecond',\n]\n\nexport function valuesOf(state: WeatherState): StateValues {\n const values: Record<string, number> = {}\n for (const key of STATE_VALUE_KEYS) values[key] = state[key]\n return values as unknown as StateValues\n}\n\n/** Every number between two states: `progress` 0 is `from`, 1 is `to`. */\nexport function blendValues(from: StateValues, to: StateValues, progress: number): StateValues {\n const amount = Math.min(1, Math.max(0, progress))\n const blended: Record<string, number> = {}\n for (const key of STATE_VALUE_KEYS) blended[key] = from[key] + (to[key] - from[key]) * amount\n return blended as unknown as StateValues\n}\n","/** A game day lasts 20 real minutes in the slice (jogo.js L69127: `dayT + dt / 1200`). */\nexport const DAY_REAL_SECONDS = 1200\nexport const GAME_DAY_SECONDS = 86400\n/** Game seconds per real second of the 20-minute day. */\nexport const DEFAULT_TIME_SCALE = GAME_DAY_SECONDS / DAY_REAL_SECONDS\n\nconst NIGHT_SPAN = 2.2\n\nconst clamp = (value: number, low: number, high: number): number => (value < low ? low : value > high ? high : value)\n\nexport type Daylight = {\n /** Sun height 0..1 (`s` of the game). */\n readonly sun: number\n /** 0 in full daylight, 1 in the darkest night. */\n readonly nightFactor: number\n}\n\n/** jogo.js L69128-L69130: `s = clamp(sin(dayT·2π − π/2)·0.5 + 0.5, 0, 1)`, `nightF = 1 − clamp(s·2.2, 0, 1)`. `dayFraction` 0 is midnight. */\nexport function daylight(dayFraction: number): Daylight {\n const sun = clamp(Math.sin(dayFraction * Math.PI * 2 - Math.PI / 2) * 0.5 + 0.5, 0, 1)\n return { sun, nightFactor: 1 - clamp(sun * NIGHT_SPAN, 0, 1) }\n}\n\n/** The fraction of the day after `gameSeconds` from `startHour`. */\nexport function dayFractionAt(startHour: number, gameSeconds: number): number {\n const fraction = (startHour / 24 + gameSeconds / GAME_DAY_SECONDS) % 1\n return fraction < 0 ? fraction + 1 : fraction\n}\n","const HEAT_STRESS_BANDS: ReadonlyArray<readonly [indexC: number, stress: number]> = [\n [27, 0],\n [32, 1 / 3],\n [41, 2 / 3],\n [54, 1],\n]\nconst NOAA_REGRESSION_FROM_F = 80\n\nconst toFahrenheit = (celsius: number): number => (celsius * 9) / 5 + 32\nconst toCelsius = (fahrenheit: number): number => ((fahrenheit - 32) * 5) / 9\n\n/**\n * NOAA heat index in °C: the Steadman estimate averaged with the temperature, and from 80 °F up the Rothfusz regression with the low-humidity and\n * high-humidity adjustments. Built from + - * / and `sqrt` only, so it is the same on every engine.\n */\nexport function heatIndexC(temperatureC: number, relativeHumidityPercent: number): number {\n const t = toFahrenheit(temperatureC)\n const r = relativeHumidityPercent\n const steadman = 0.5 * (t + 61 + (t - 68) * 1.2 + r * 0.094)\n const simple = (steadman + t) / 2\n if (simple < NOAA_REGRESSION_FROM_F) return toCelsius(simple)\n let index =\n -42.379 +\n 2.04901523 * t +\n 10.14333127 * r -\n 0.22475541 * t * r -\n 0.00683783 * t * t -\n 0.05481717 * r * r +\n 0.00122874 * t * t * r +\n 0.00085282 * t * r * r -\n 0.00000199 * t * t * r * r\n if (r < 13 && t >= 80 && t <= 112) index -= ((13 - r) / 4) * Math.sqrt((17 - Math.abs(t - 95)) / 17)\n else if (r > 85 && t >= 80 && t <= 87) index += ((r - 85) / 10) * ((87 - t) / 5)\n return toCelsius(index)\n}\n\n/** 0..1 across the NOAA bands (caution 27, extreme caution 32, danger 41, extreme danger 54 °C), linear between them. */\nexport function heatStress(heatIndex: number): number {\n const first = HEAT_STRESS_BANDS[0]!\n const last = HEAT_STRESS_BANDS[HEAT_STRESS_BANDS.length - 1]!\n if (heatIndex <= first[0]) return first[1]\n if (heatIndex >= last[0]) return last[1]\n for (let index = 1; index < HEAT_STRESS_BANDS.length; index++) {\n const [upperC, upperStress] = HEAT_STRESS_BANDS[index]!\n const [lowerC, lowerStress] = HEAT_STRESS_BANDS[index - 1]!\n if (heatIndex <= upperC) return lowerStress + ((heatIndex - lowerC) / (upperC - lowerC)) * (upperStress - lowerStress)\n }\n return last[1]\n}\n","import { heatIndexC, heatStress } from './heat'\nimport type { StateValues, WeatherEffects } from './types'\n\n/** Gameplay visibility of a dry day (the game's dry fog far, jogo.js L69141): `sightScale` is the visibility against it. */\nexport const DRY_VISIBILITY_METERS = 220\n/** jogo.js L66872: sight is `perc[0] × (1 − 0.4 × nightF)`. */\nexport const NIGHT_SIGHT_LOSS = 0.4\n\nexport type EffectsInput = {\n readonly values: StateValues\n readonly nightFactor: number\n readonly temperatureC: number\n readonly humidityPercent: number\n readonly lightningReveal: number\n}\n\n/** What the weather means for gameplay, as numbers for whoever has eyes, ears or feet in the world (perception, footsteps, heat). */\nexport function deriveEffects(input: EffectsInput): WeatherEffects {\n const { values, nightFactor } = input\n const weatherSight = Math.min(1, Math.max(0, values.visibility / DRY_VISIBILITY_METERS))\n const heatIndex = heatIndexC(input.temperatureC, input.humidityPercent)\n return {\n visibility: values.visibility,\n sightScale: weatherSight * (1 - NIGHT_SIGHT_LOSS * nightFactor),\n hearingScale: values.hearingScale,\n footstepScale: values.footstepScale,\n heatIndexC: heatIndex,\n heatStress: heatStress(heatIndex),\n lightningReveal: input.lightningReveal,\n dryingScale: values.dryingScale,\n debrisPush: values.debrisPush,\n }\n}\n","const FNV_OFFSET = 0x811c9dc5\nconst FNV_PRIME = 0x01000193\nconst MIX = 0x9e3779b1\n\n/** Deterministic mulberry32 generator; returns floats in [0, 1). */\nexport function createRng(seed: number): () => number {\n let state = seed >>> 0\n return () => {\n state = (state + 0x6d2b79f5) >>> 0\n let mixed = Math.imul(state ^ (state >>> 15), state | 1)\n mixed ^= mixed + Math.imul(mixed ^ (mixed >>> 7), mixed | 61)\n return ((mixed ^ (mixed >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** A seed for the stream called `name`: the same seed gives each name its own sequence, so lightning never shifts the schedule. */\nexport function streamSeed(seed: number, name: string): number {\n let hash = FNV_OFFSET\n for (let index = 0; index < name.length; index++) hash = Math.imul(hash ^ name.charCodeAt(index), FNV_PRIME) >>> 0\n return Math.imul((seed >>> 0) ^ hash, MIX) >>> 0\n}\n\nexport function createStream(seed: number, name: string): () => number {\n return createRng(streamSeed(seed, name))\n}\n\nexport function drawBetween(rng: () => number, range: readonly [min: number, max: number]): number {\n return range[0] + rng() * (range[1] - range[0])\n}\n","import { createStream, drawBetween } from './rng'\nimport type { LightningConfig } from './types'\n\n/** Speed of sound in air, m/s: a physical constant, so it is not configurable. */\nexport const SPEED_OF_SOUND = 343\n\n/** Seconds a flash goes on after a strike before the scene is back to normal (Workshop W1068: `k > .4`). */\nexport const FLASH_END_SECONDS = 0.4\n\n/** Seconds from the flash to the thunder for a strike `distance` metres away. */\nexport function thunderDelay(distance: number): number {\n return distance / SPEED_OF_SOUND\n}\n\n/** The Workshop double flash (W1068): full for 0.08 s, 0.2 until 0.16 s, 0.8 until 0.26 s, then dark. `elapsed` is seconds since the strike. */\nexport function flashIntensity(elapsed: number): number {\n if (elapsed < 0 || elapsed >= FLASH_END_SECONDS) return 0\n if (elapsed < 0.08) return 1\n if (elapsed < 0.16) return 0.2\n if (elapsed < 0.26) return 0.8\n return 0\n}\n\nexport type LightningStream = {\n /** Seconds from entering a state with lightning to its first strike. */\n first(config: LightningConfig): number\n /** Seconds from a strike to the next one. */\n interval(config: LightningConfig): number\n /** Where a strike lands: metres and degrees clockwise from north. Draws the distance, then the bearing. */\n place(config: LightningConfig): { readonly distance: number; readonly bearing: number }\n}\n\n/** The lightning's own seeded stream, apart from the scheduler's: the server can send the seed and every client sees the same strikes. */\nexport function createLightningStream(seed: number): LightningStream {\n const rng = createStream(seed, 'lightning')\n return {\n first: (config) => drawBetween(rng, config.first),\n interval: (config) => drawBetween(rng, config.interval),\n place(config) {\n const distance = drawBetween(rng, config.distance)\n return { distance, bearing: rng() * 360 }\n },\n }\n}\n","[\n {\n \"id\": \"temperate\",\n \"sources\": [\"galeria-vale-cinzento:L1393 (changes every 2-6 h, arrives from the west)\", \"design:T6 3.2 kit default: mostly clear and overcast, no extremes\"],\n \"start\": \"clear\",\n \"dwellHours\": [2, 6],\n \"blendMinutes\": 10,\n \"frontDirection\": [1, 0],\n \"temperatureC\": { \"mean\": 16, \"swing\": 6 },\n \"humidityOffset\": 0,\n \"transitions\": {\n \"clear\": { \"overcast\": 4, \"windy\": 1, \"fog\": 1, \"light_rain\": 1 },\n \"overcast\": { \"clear\": 3, \"light_rain\": 3, \"heavy_rain\": 1, \"fog\": 1, \"windy\": 1 },\n \"light_rain\": { \"overcast\": 3, \"clear\": 2, \"heavy_rain\": 2 },\n \"heavy_rain\": { \"light_rain\": 3, \"overcast\": 2, \"storm\": 1 },\n \"storm\": { \"heavy_rain\": 3, \"light_rain\": 2, \"overcast\": 1 },\n \"fog\": { \"clear\": 3, \"overcast\": 2 },\n \"windy\": { \"clear\": 3, \"overcast\": 3, \"light_rain\": 1 }\n }\n },\n {\n \"id\": \"tropical\",\n \"sources\": [\"galeria-vale-cinzento:L1393 (changes every 2-6 h, arrives from the west)\", \"design:T6 3.2 and Q3: extremes rare and enabled\"],\n \"start\": \"clear\",\n \"dwellHours\": [2, 6],\n \"blendMinutes\": 10,\n \"frontDirection\": [1, 0],\n \"temperatureC\": { \"mean\": 29, \"swing\": 3 },\n \"humidityOffset\": 0.1,\n \"transitions\": {\n \"clear\": { \"overcast\": 3, \"light_rain\": 2, \"windy\": 1, \"extreme_heat\": 0.8 },\n \"overcast\": { \"clear\": 3, \"light_rain\": 3, \"heavy_rain\": 2, \"fog\": 0.5 },\n \"light_rain\": { \"overcast\": 3, \"clear\": 2, \"heavy_rain\": 2 },\n \"heavy_rain\": { \"light_rain\": 3, \"overcast\": 2, \"storm\": 1.5 },\n \"storm\": { \"heavy_rain\": 3, \"light_rain\": 2, \"overcast\": 1, \"cyclone\": 0.5 },\n \"fog\": { \"clear\": 3, \"overcast\": 2 },\n \"windy\": { \"clear\": 3, \"overcast\": 2, \"light_rain\": 1, \"storm\": 0.5 },\n \"extreme_heat\": { \"clear\": 4, \"overcast\": 2, \"storm\": 0.8 },\n \"cyclone\": { \"storm\": 3, \"heavy_rain\": 2, \"typhoon\": 0.5 },\n \"typhoon\": { \"cyclone\": 3, \"storm\": 2 }\n }\n }\n]\n","[\n {\n \"id\": \"clear\",\n \"sources\": [\"jogo:L69141 (fog far 220 dry)\", \"showroom.js:L1693-1710 (breeze 3.5, 1.5 m/s)\"],\n \"rain\": 0, \"drops\": 0, \"sheets\": 0,\n \"windX\": 3.5, \"windZ\": 1.5, \"gust\": 5,\n \"fogFar\": 220, \"fogDensity\": 0, \"skyScale\": 1, \"visibility\": 220,\n \"humidity\": 0.5, \"temperatureDeltaC\": 0, \"wetness\": 0,\n \"hearingScale\": 1, \"footstepScale\": 1, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n },\n {\n \"id\": \"overcast\",\n \"sources\": [\"cena-de-arte:L413 (wind .35, .12)\", \"cena-de-arte:L36 (FogExp2 .03)\", \"design:T6 sky x0.9\"],\n \"rain\": 0, \"drops\": 0, \"sheets\": 0,\n \"windX\": 0.35, \"windZ\": 0.12, \"gust\": 0.6,\n \"fogFar\": 220, \"fogDensity\": 0.03, \"skyScale\": 0.9, \"visibility\": 200,\n \"humidity\": 0.65, \"temperatureDeltaC\": -1, \"wetness\": 0,\n \"hearingScale\": 1, \"footstepScale\": 1, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n },\n {\n \"id\": \"light_rain\",\n \"sources\": [\"oficina-vfx:W1065 (Garoa: 900 drops, slant .3)\", \"jogo:L70416-70427 (rain level .035)\", \"design:T6 2.5 mm/h, wetness .35, visibility 160, hearing x0.8 (Q4)\"],\n \"rain\": 2.5, \"drops\": 900, \"sheets\": 0,\n \"windX\": 0.3, \"windZ\": 0, \"gust\": 0.6,\n \"fogFar\": 180, \"fogDensity\": 0, \"skyScale\": 0.9, \"visibility\": 160,\n \"humidity\": 0.85, \"temperatureDeltaC\": -2, \"wetness\": 0.35,\n \"hearingScale\": 0.8, \"footstepScale\": 0.85, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n },\n {\n \"id\": \"heavy_rain\",\n \"sources\": [\"oficina-vfx:W1065 (Chuva: 2200 drops, slant 1.2)\", \"cena-de-arte:L1314 (rain gain .06)\", \"jogo:L69141 (fog far 140, sky x0.8)\", \"galeria-vale-cinzento:L1393 (vision 120 m, quieter steps)\", \"design:T6 15 mm/h, hearing x0.6 (Q4)\"],\n \"rain\": 15, \"drops\": 2200, \"sheets\": 0,\n \"windX\": 1.2, \"windZ\": 0, \"gust\": 2,\n \"fogFar\": 140, \"fogDensity\": 0, \"skyScale\": 0.8, \"visibility\": 120,\n \"humidity\": 0.9, \"temperatureDeltaC\": -4, \"wetness\": 0.8,\n \"hearingScale\": 0.6, \"footstepScale\": 0.7, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n },\n {\n \"id\": \"storm\",\n \"sources\": [\"oficina-vfx:W1065-1069 (Temporal: 4000 drops, slant 4.5, lightning 3.5-6 s, first at 2-4 s, sheets)\", \"showroom.js (60 mm/h)\", \"design:T6 hearing x0.5 (Q4)\"],\n \"rain\": 60, \"drops\": 4000, \"sheets\": 1,\n \"windX\": 4.5, \"windZ\": 0, \"gust\": 6,\n \"fogFar\": 110, \"fogDensity\": 0, \"skyScale\": 0.7, \"visibility\": 100,\n \"humidity\": 0.92, \"temperatureDeltaC\": -5, \"wetness\": 1,\n \"hearingScale\": 0.5, \"footstepScale\": 0.6, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0,\n \"lightning\": { \"interval\": [3.5, 6], \"first\": [2, 4], \"distance\": [200, 4000], \"reveal\": 0.2 }\n },\n {\n \"id\": \"fog\",\n \"sources\": [\"oficina-vfx:W1073-1080 (density .075, ground mist 5/s, ash 14/s)\", \"jogo:L69101 (zone fog far 60)\"],\n \"rain\": 0, \"drops\": 0, \"sheets\": 0,\n \"windX\": 0.3, \"windZ\": 0.1, \"gust\": 0.5,\n \"fogFar\": 60, \"fogDensity\": 0.075, \"skyScale\": 0.85, \"visibility\": 40,\n \"humidity\": 0.95, \"temperatureDeltaC\": -3, \"wetness\": 0.15,\n \"hearingScale\": 1, \"footstepScale\": 1, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 5, \"ashPerSecond\": 14\n },\n {\n \"id\": \"windy\",\n \"sources\": [\"cena-de-arte:L1315 (wind loop)\", \"design:T6 Q3 8 m/s, gust 12\"],\n \"rain\": 0, \"drops\": 0, \"sheets\": 0,\n \"windX\": 8, \"windZ\": 0, \"gust\": 12,\n \"fogFar\": 220, \"fogDensity\": 0, \"skyScale\": 1, \"visibility\": 220,\n \"humidity\": 0.45, \"temperatureDeltaC\": -1, \"wetness\": 0,\n \"hearingScale\": 0.85, \"footstepScale\": 0.9, \"dryingScale\": 1, \"debrisPush\": 0,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n },\n {\n \"id\": \"cyclone\",\n \"sources\": [\"design:T6 Q3 physics preset, no team source: tropical cyclone 33 m/s sustained, gust x1.3, storm rain, debris push\"],\n \"rain\": 60, \"drops\": 4000, \"sheets\": 1,\n \"windX\": 33, \"windZ\": 0, \"gust\": 42.9,\n \"fogFar\": 80, \"fogDensity\": 0, \"skyScale\": 0.6, \"visibility\": 60,\n \"humidity\": 0.9, \"temperatureDeltaC\": 0, \"wetness\": 1,\n \"hearingScale\": 0.3, \"footstepScale\": 0.5, \"dryingScale\": 1, \"debrisPush\": 8,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0,\n \"lightning\": { \"interval\": [3.5, 6], \"first\": [2, 4], \"distance\": [200, 4000], \"reveal\": 0.2 }\n },\n {\n \"id\": \"typhoon\",\n \"sources\": [\"design:T6 Q3 physics preset, no team source: typhoon 50 m/s sustained, gust x1.3, storm rain, debris push\"],\n \"rain\": 60, \"drops\": 4000, \"sheets\": 1,\n \"windX\": 50, \"windZ\": 0, \"gust\": 65,\n \"fogFar\": 60, \"fogDensity\": 0, \"skyScale\": 0.5, \"visibility\": 40,\n \"humidity\": 0.9, \"temperatureDeltaC\": 0, \"wetness\": 1,\n \"hearingScale\": 0.25, \"footstepScale\": 0.4, \"dryingScale\": 1, \"debrisPush\": 18,\n \"haze\": 0, \"mistPerSecond\": 0, \"ashPerSecond\": 0,\n \"lightning\": { \"interval\": [3.5, 6], \"first\": [2, 4], \"distance\": [200, 4000], \"reveal\": 0.2 }\n },\n {\n \"id\": \"extreme_heat\",\n \"sources\": [\"design:T6 Q3 no team source: 38 C at the tropical noon (+6 over the climate), 60 % humidity, haze, drying x2\"],\n \"rain\": 0, \"drops\": 0, \"sheets\": 0,\n \"windX\": 0.8, \"windZ\": 0.3, \"gust\": 1.5,\n \"fogFar\": 220, \"fogDensity\": 0, \"skyScale\": 1, \"visibility\": 200,\n \"humidity\": 0.6, \"temperatureDeltaC\": 6, \"wetness\": 0,\n \"hearingScale\": 1, \"footstepScale\": 1, \"dryingScale\": 2, \"debrisPush\": 0,\n \"haze\": 1, \"mistPerSecond\": 0, \"ashPerSecond\": 0\n }\n]\n","import climatesJson from './data/climates.json'\nimport statesJson from './data/states.json'\nimport type { Climate, DeepPartial, WeatherState } from './types'\n\nexport const WEATHER_STATES: readonly WeatherState[] = statesJson as unknown as readonly WeatherState[]\nexport const CLIMATES: readonly Climate[] = climatesJson as unknown as readonly Climate[]\n\nexport type RegistryOptions = {\n /** Added to the shipped states or, when the id exists, replacing it. */\n readonly states?: readonly WeatherState[]\n readonly climates?: readonly Climate[]\n /** Merged into a shipped or added entry by id; a patch for an id that does not exist is ignored. */\n readonly patch?: {\n readonly states?: Readonly<Record<string, DeepPartial<WeatherState>>>\n readonly climates?: Readonly<Record<string, DeepPartial<Climate>>>\n }\n readonly remove?: { readonly states?: readonly string[]; readonly climates?: readonly string[] }\n}\n\nexport type WeatherRegistry = {\n state(id: string): WeatherState | undefined\n climate(id: string): Climate | undefined\n stateIds(): string[]\n climateIds(): string[]\n registerState(state: WeatherState): void\n registerClimate(climate: Climate): void\n patchState(id: string, patch: DeepPartial<WeatherState>): void\n patchClimate(id: string, patch: DeepPartial<Climate>): void\n removeState(id: string): void\n removeClimate(id: string): void\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction mergeRecords(base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...base }\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) continue\n const current = merged[key]\n merged[key] = isPlainObject(current) && isPlainObject(value) ? mergeRecords(current, value) : value\n }\n return merged\n}\n\nfunction deepMerge<TValue>(base: TValue, patch: DeepPartial<TValue>): TValue {\n return mergeRecords(base as Record<string, unknown>, patch as Record<string, unknown>) as TValue\n}\n\ntype Entry = { readonly id: string }\n\nfunction createTable<TEntry extends Entry>(shipped: readonly TEntry[]): Map<string, TEntry> {\n return new Map(shipped.map((entry) => [entry.id, entry]))\n}\n\nfunction patchEntry<TEntry extends Entry>(table: Map<string, TEntry>, id: string, patch: DeepPartial<TEntry>): void {\n const entry = table.get(id)\n if (entry) table.set(id, deepMerge(entry, patch))\n}\n\n/** The shipped states and climates with yours added, patched or removed; change it later with the same verbs. */\nexport function createWeatherRegistry(options: RegistryOptions = {}): WeatherRegistry {\n const states = createTable(WEATHER_STATES)\n const climates = createTable(CLIMATES)\n for (const state of options.states ?? []) states.set(state.id, state)\n for (const climate of options.climates ?? []) climates.set(climate.id, climate)\n for (const [id, patch] of Object.entries(options.patch?.states ?? {})) patchEntry(states, id, patch)\n for (const [id, patch] of Object.entries(options.patch?.climates ?? {})) patchEntry(climates, id, patch)\n for (const id of options.remove?.states ?? []) states.delete(id)\n for (const id of options.remove?.climates ?? []) climates.delete(id)\n return {\n state: (id) => states.get(id),\n climate: (id) => climates.get(id),\n stateIds: () => [...states.keys()],\n climateIds: () => [...climates.keys()],\n registerState: (state) => void states.set(state.id, state),\n registerClimate: (climate) => void climates.set(climate.id, climate),\n patchState: (id, patch) => patchEntry(states, id, patch),\n patchClimate: (id, patch) => patchEntry(climates, id, patch),\n removeState: (id) => void states.delete(id),\n removeClimate: (id) => void climates.delete(id),\n }\n}\n","import { createStream, drawBetween } from './rng'\nimport type { Climate } from './types'\n\nconst SECONDS_PER_HOUR = 3600\n/** A state lasts at least this long, so a climate patched to a zero dwell cannot stall the clock. */\nconst MIN_DWELL_SECONDS = 1\n\nexport type Scheduler = {\n /** Game seconds at which the current state ends. */\n nextChangeAt(): number\n /** Picks the state after `current`, then draws how long it lasts from `at`. Returns the new state's id. */\n next(current: string, at: number): string\n /** Draws a new duration from `at` (after a forced change). */\n restart(at: number): void\n}\n\n/**\n * A seeded Markov chain in game time. Draw order, fixed so the timeline repeats: at start one dwell; at each change the next state first\n * (one draw, over the weights in the climate's order), then its dwell. States `isKnown` rejects are left out of the weights.\n */\nexport function createScheduler(climate: Climate, seed: number, isKnown: (id: string) => boolean): Scheduler {\n const rng = createStream(seed, 'schedule')\n let changeAt = 0\n const drawDwell = (from: number): number => from + Math.max(MIN_DWELL_SECONDS, drawBetween(rng, climate.dwellHours) * SECONDS_PER_HOUR)\n changeAt = drawDwell(0)\n return {\n nextChangeAt: () => changeAt,\n next(current, at) {\n const options = Object.entries(climate.transitions[current] ?? {}).filter(([id, weight]) => weight > 0 && isKnown(id))\n const total = options.reduce((sum, [, weight]) => sum + weight, 0)\n let chosen = current\n if (total > 0) {\n let pick = rng() * total\n chosen = options[options.length - 1]![0]\n for (const [id, weight] of options) {\n if (pick < weight) {\n chosen = id\n break\n }\n pick -= weight\n }\n }\n changeAt = drawDwell(at)\n return chosen\n },\n restart(at) {\n changeAt = drawDwell(at)\n },\n }\n}\n","export const DEFAULT_WET_RISE_SECONDS = 120\n/** The Workshop sheet: the water goes back to the colour of the ground 3 minutes after the rain stops. */\nexport const DEFAULT_DRY_OUT_SECONDS = 180\n\nexport type WetnessOptions = {\n /** Seconds of rain to wet the ground fully. */\n readonly riseSeconds?: number\n /** Seconds from the end of the rain until the ground is dry. */\n readonly dryOutSeconds?: number\n}\n\nexport type Wetness = {\n value(): number\n /** Moves `seconds` toward `target` (the wetness the weather asks for); `dryingScale` speeds the dry-out up. Returns the new value. */\n update(seconds: number, target: number, dryingScale?: number): number\n reset(value?: number): void\n}\n\n/** Ground wetness: rises while the weather asks for more, then falls in a straight line that ends `dryOutSeconds` after the start of the fall. */\nexport function createWetness(options: WetnessOptions = {}): Wetness {\n const riseSeconds = options.riseSeconds ?? DEFAULT_WET_RISE_SECONDS\n const dryOutSeconds = options.dryOutSeconds ?? DEFAULT_DRY_OUT_SECONDS\n let current = 0\n let peak = 0\n let isDrying = false\n return {\n value: () => current,\n update(seconds, target, dryingScale = 1) {\n if (target > current) {\n isDrying = false\n current = Math.min(target, current + seconds / riseSeconds)\n } else if (target < current) {\n if (!isDrying) {\n isDrying = true\n peak = current\n }\n current = Math.max(target, current - (peak * seconds * dryingScale) / dryOutSeconds)\n } else isDrying = false\n return current\n },\n reset(value = 0) {\n current = value\n peak = value\n isDrying = false\n },\n }\n}\n","import { blendValues, valuesOf } from './blend'\nimport { DEFAULT_TIME_SCALE, daylight, dayFractionAt } from './daylight'\nimport { deriveEffects } from './effects'\nimport { createLightningStream, flashIntensity, thunderDelay } from './lightning'\nimport { createWeatherRegistry } from './registry'\nimport type { RegistryOptions, WeatherRegistry } from './registry'\nimport { createScheduler } from './scheduler'\nimport type { Climate, StateValues, Strike, WeatherEventMap, WeatherSample, WeatherState } from './types'\nimport { createWetness } from './wetness'\nimport type { WetnessOptions } from './wetness'\n\nexport const DEFAULT_START_HOUR = 8\nconst SECONDS_PER_MINUTE = 60\nconst WETNESS_STEP_SECONDS = 1\n\nexport type WeatherOptions = RegistryOptions & {\n /** Seed of the schedule and of the lightning (each has its own stream). Default 1. */\n readonly seed?: number\n /** Climate id. Default `temperate`. */\n readonly climate?: string\n /** First state; default the climate's `start`, which is `clear`: the normal world comes first. */\n readonly start?: string\n /** Game seconds per real second. Default 72 (the 20-minute day). */\n readonly timeScale?: number\n /** Hour of the day the world starts at. Default 8. */\n readonly startHour?: number\n /** `false` keeps the state until `force` changes it. Default true. */\n readonly autoSchedule?: boolean\n readonly wetness?: WetnessOptions\n /** An existing registry, instead of building one from the registry options. */\n readonly registry?: WeatherRegistry\n}\n\nexport type WeatherTimeline = {\n readonly seed: number\n readonly climate: string\n readonly start: string\n readonly hours: number\n readonly sampleMinutes: number\n readonly transitions: ReadonlyArray<{ readonly gameSeconds: number; readonly from: string; readonly to: string }>\n readonly strikes: readonly Strike[]\n readonly samples: ReadonlyArray<Readonly<Record<string, number | string>>>\n}\n\nexport type Weather = {\n readonly registry: WeatherRegistry\n /** Moves the world forward by `dt` real seconds (game time moves `timeScale` times as fast). Events fire in order as they are crossed. */\n advance(dt: number): void\n sample(): WeatherSample\n /** The state being blended to, or settled in. */\n state(): string\n /** Changes state now, blending over `blendSeconds` real seconds (0 is at once); the new state then lasts a normal dwell. */\n force(id: string, blendSeconds?: number): void\n setTimeScale(timeScale: number): void\n setAutoSchedule(isOn: boolean): void\n /** What a fresh world with these options does over `hours` game hours; the live world is not touched. */\n timeline(hours: number, sampleMinutes?: number): WeatherTimeline\n on<TEvent extends keyof WeatherEventMap>(event: TEvent, listener: (payload: WeatherEventMap[TEvent]) => void): () => void\n}\n\ntype Blend = { startedAt: number; duration: number }\n\nconst clamp01 = (value: number): number => Math.min(1, Math.max(0, value))\n\nfunction requireClimate(registry: WeatherRegistry, id: string): Climate {\n const climate = registry.climate(id)\n if (!climate) throw new Error(`game-weather: unknown climate \"${id}\"`)\n return climate\n}\n\nfunction requireState(registry: WeatherRegistry, id: string): WeatherState {\n const state = registry.state(id)\n if (!state) throw new Error(`game-weather: unknown state \"${id}\"`)\n return state\n}\n\nexport function createWeather(options: WeatherOptions = {}): Weather {\n const registry = options.registry ?? createWeatherRegistry(options)\n const seed = options.seed ?? 1\n const climateId = options.climate ?? 'temperate'\n const startClimate = requireClimate(registry, climateId)\n const startState = requireState(registry, options.start ?? startClimate.start)\n const startHour = options.startHour ?? DEFAULT_START_HOUR\n const scheduler = createScheduler(startClimate, seed, (id) => registry.state(id) !== undefined)\n const lightning = createLightningStream(seed)\n const wetness = createWetness(options.wetness)\n const listeners = new Map<keyof WeatherEventMap, Set<(payload: never) => void>>()\n\n let timeScale = options.timeScale ?? DEFAULT_TIME_SCALE\n let isAutoSchedule = options.autoSchedule ?? true\n let gameSeconds = 0\n let simSeconds = 0\n let target = startState\n let targetValues = valuesOf(startState)\n let fromValues: StateValues = targetValues\n let previousId: string | undefined\n let blend: Blend = { startedAt: 0, duration: 0 }\n let nextStrikeAt: number | undefined\n let strikeCount = 0\n let lastStrike: Strike | undefined\n const pendingThunder: Strike[] = []\n\n const climate = (): Climate => registry.climate(climateId) ?? startClimate\n\n const emit = <TEvent extends keyof WeatherEventMap>(event: TEvent, payload: WeatherEventMap[TEvent]): void => {\n for (const listener of [...(listeners.get(event) ?? [])]) (listener as (value: WeatherEventMap[TEvent]) => void)(payload)\n }\n\n const progressAt = (at: number): number => (blend.duration <= 0 ? 1 : clamp01((at - blend.startedAt) / blend.duration))\n const valuesAt = (at: number): StateValues => blendValues(fromValues, targetValues, progressAt(at))\n\n const scheduleFirstStrike = (atSim: number): void => {\n nextStrikeAt = target.lightning ? atSim + lightning.first(target.lightning) : undefined\n }\n\n const enter = (id: string, atGame: number, atSim: number, blendGameSeconds: number): void => {\n const next = requireState(registry, id)\n fromValues = valuesAt(atGame)\n previousId = target.id\n target = next\n targetValues = valuesOf(next)\n blend = { startedAt: atGame, duration: blendGameSeconds }\n scheduleFirstStrike(atSim)\n emit('transition', { from: previousId, to: id, gameSeconds: atGame })\n }\n\n const strikeAt = (atSim: number, startGame: number, startSim: number): void => {\n const config = target.lightning!\n const place = lightning.place(config)\n const strike: Strike = {\n id: strikeCount++,\n time: atSim,\n gameSeconds: startGame + (atSim - startSim) * timeScale,\n distance: place.distance,\n bearing: place.bearing,\n thunderDelay: thunderDelay(place.distance),\n }\n lastStrike = strike\n pendingThunder.push(strike)\n pendingThunder.sort((a, b) => a.time + a.thunderDelay - (b.time + b.thunderDelay))\n nextStrikeAt = atSim + lightning.interval(config)\n emit('strike', strike)\n }\n\n scheduleFirstStrike(0)\n\n const runEvents = (startGame: number, startSim: number, endSim: number): void => {\n for (;;) {\n const changeSim = isAutoSchedule ? Math.max(startSim, startSim + (scheduler.nextChangeAt() - startGame) / timeScale) : Infinity\n const strikeSim = nextStrikeAt ?? Infinity\n const thunder = pendingThunder[0]\n const thunderSim = thunder ? thunder.time + thunder.thunderDelay : Infinity\n const earliest = Math.min(changeSim, strikeSim, thunderSim)\n if (earliest > endSim) return\n if (earliest === changeSim) {\n const atGame = Math.max(startGame, scheduler.nextChangeAt())\n const next = scheduler.next(target.id, atGame)\n enter(next, atGame, changeSim, climate().blendMinutes * SECONDS_PER_MINUTE)\n } else if (earliest === strikeSim) strikeAt(strikeSim, startGame, startSim)\n else emit('thunder', pendingThunder.shift()!)\n }\n }\n\n const wet = (startGame: number, endGame: number, seconds: number): void => {\n const steps = Math.max(1, Math.ceil(seconds / WETNESS_STEP_SECONDS))\n for (let step = 1; step <= steps; step++) {\n const values = valuesAt(startGame + ((endGame - startGame) * step) / steps)\n wetness.update(seconds / steps, values.wetness, values.dryingScale)\n }\n }\n\n const api: Weather = {\n registry,\n advance(dt) {\n if (!(dt > 0)) return\n const startGame = gameSeconds\n const startSim = simSeconds\n const endGame = startGame + dt * timeScale\n runEvents(startGame, startSim, startSim + dt)\n gameSeconds = endGame\n simSeconds = startSim + dt\n wet(startGame, endGame, dt)\n },\n sample() {\n const values = valuesAt(gameSeconds)\n const dayFraction = dayFractionAt(startHour, gameSeconds)\n const { sun, nightFactor } = daylight(dayFraction)\n const current = climate()\n const temperatureC = current.temperatureC.mean + current.temperatureC.swing * (2 * sun - 1) + values.temperatureDeltaC\n const humidityPercent = clamp01(values.humidity + current.humidityOffset) * 100\n const progress = progressAt(gameSeconds)\n return {\n ...values,\n gameSeconds,\n dayFraction,\n hour: dayFraction * 24,\n nightFactor,\n sun,\n state: target.id,\n previous: progress < 1 ? previousId : undefined,\n blend: progress,\n front: { direction: current.frontDirection, progress },\n windSpeed: Math.sqrt(values.windX * values.windX + values.windZ * values.windZ),\n temperatureC,\n humidityPercent,\n groundWetness: wetness.value(),\n flash: lastStrike ? flashIntensity(simSeconds - lastStrike.time) : 0,\n effects: deriveEffects({ values, nightFactor, temperatureC, humidityPercent, lightningReveal: target.lightning?.reveal ?? 0 }),\n }\n },\n state: () => target.id,\n force(id, blendSeconds = 0) {\n enter(id, gameSeconds, simSeconds, blendSeconds * timeScale)\n scheduler.restart(gameSeconds)\n },\n setTimeScale(next) {\n if (!(next > 0)) throw new Error('game-weather: timeScale must be above 0')\n timeScale = next\n },\n setAutoSchedule(isOn) {\n if (isOn && !isAutoSchedule) scheduler.restart(gameSeconds)\n isAutoSchedule = isOn\n },\n timeline: (hours, sampleMinutes) => createTimeline({ ...options, registry, hours, ...(sampleMinutes === undefined ? {} : { sampleMinutes }) }),\n on(event, listener) {\n const set = listeners.get(event) ?? new Set()\n set.add(listener as (payload: never) => void)\n listeners.set(event, set)\n return () => void set.delete(listener as (payload: never) => void)\n },\n }\n return api\n}\n\nexport type TimelineOptions = WeatherOptions & {\n readonly hours: number\n /** Game minutes between samples. Default 10. */\n readonly sampleMinutes?: number\n}\n\nconst TIMELINE_DECIMALS = 6\nconst round = (value: number): number => Math.round(value * 10 ** TIMELINE_DECIMALS) / 10 ** TIMELINE_DECIMALS + 0\n\n/**\n * What a fresh world does over `hours` game hours, stepping one game minute at a time: the state changes, the strikes (time, distance, bearing) and\n * a sample every `sampleMinutes`. Plain JSON, rounded to 6 decimals, so it can be a golden.\n */\nexport function createTimeline(options: TimelineOptions): WeatherTimeline {\n const weather = createWeather(options)\n const timeScale = options.timeScale ?? DEFAULT_TIME_SCALE\n const sampleMinutes = options.sampleMinutes ?? 10\n const transitions: Array<{ gameSeconds: number; from: string; to: string }> = []\n const strikes: Strike[] = []\n weather.on('transition', (event) => transitions.push({ gameSeconds: round(event.gameSeconds), from: event.from, to: event.to }))\n weather.on('strike', (strike) =>\n strikes.push({ id: strike.id, time: round(strike.time), gameSeconds: round(strike.gameSeconds), distance: round(strike.distance), bearing: round(strike.bearing), thunderDelay: round(strike.thunderDelay) }),\n )\n const samples: Array<Record<string, number | string>> = []\n const record = (minute: number): void => {\n const sample = weather.sample()\n samples.push({\n at: minute * SECONDS_PER_MINUTE,\n hour: round(sample.hour),\n state: sample.state,\n blend: round(sample.blend),\n rain: round(sample.rain),\n windSpeed: round(sample.windSpeed),\n gust: round(sample.gust),\n visibility: round(sample.effects.visibility),\n sightScale: round(sample.effects.sightScale),\n hearingScale: round(sample.effects.hearingScale),\n temperatureC: round(sample.temperatureC),\n heatIndexC: round(sample.effects.heatIndexC),\n heatStress: round(sample.effects.heatStress),\n wetness: round(sample.groundWetness),\n nightFactor: round(sample.nightFactor),\n })\n }\n record(0)\n const minutes = Math.round(options.hours * 60)\n for (let minute = 1; minute <= minutes; minute++) {\n weather.advance(SECONDS_PER_MINUTE / timeScale)\n if (minute % sampleMinutes === 0) record(minute)\n }\n return {\n seed: options.seed ?? 1,\n climate: options.climate ?? 'temperate',\n start: options.start ?? weather.registry.climate(options.climate ?? 'temperate')!.start,\n hours: options.hours,\n sampleMinutes,\n transitions,\n strikes,\n samples,\n }\n}\n","// Rain, wind and thunder as recipes of @adatechnology/game-audio. The loops are the teams' (the art scene's `initAudio`, cena L1314-L1315, and the game's\n// `chuva` loop, jogo L62116); the thunder is the game's `boom` (jogo L68278, a sine from 70 to 28 Hz) with a low rumble under it, the kit's choice.\nimport { sceneNoise, sceneTone } from '@adatechnology/game-audio'\nimport type { LoopRecipe, SoundBank, SoundRecipe } from '@adatechnology/game-audio'\n\n/** Rain of the art scene: noise through a highpass at 600 Hz and a lowpass at 6000 Hz (cena L1314), opened at its volume. */\nexport const RAIN_LOOP: LoopRecipe = {\n id: 'rain_loop',\n bus: 'weather',\n order: 'chain_loop',\n source: { kind: 'noise', loop: true },\n filters: {\n mode: 'serial',\n bank: [\n { type: 'highpass', frequency: { set: 600 } },\n { type: 'lowpass', frequency: { set: 6000 } },\n ],\n },\n sources: ['cena:L1314'],\n}\n\n/** Wind of the art scene: noise through a lowpass at 320 Hz whose gain swings 0.035 at 0.07 Hz (cena L1315). */\nexport const WIND_LOOP: LoopRecipe = {\n id: 'wind_loop',\n bus: 'weather',\n order: 'chain_loop',\n source: { kind: 'noise', loop: true },\n filters: { mode: 'serial', bank: [{ type: 'lowpass', frequency: { set: 320 } }] },\n modulators: [{ target: 'gain', rate: 0.07, depth: 0.035 }],\n sources: ['cena:L1315'],\n}\n\n/** Rain of the game: noise through a highpass at 2500 Hz, created when the volume first passes 0.002 (jogo L62116 `chuva`). */\nexport const RAIN_HISS_GAME: LoopRecipe = {\n id: 'rain_hiss_game',\n bus: 'weather',\n order: 'game_loop',\n source: { kind: 'noise', loop: true },\n filters: { mode: 'serial', bank: [{ type: 'highpass', frequency: { set: 2500 } }] },\n sources: ['jogo:L62116 chuva'],\n}\n\n/**\n * Thunder. The thump is the game's boom (a sine from 70 to 28 Hz over 1.2 s); the rumble is a lowpassed noise that slides from 260 to 50 Hz over 3.2 s\n * with a reverb send, the kit's choice (no team has a thunder). It carries much farther than a blast: `k` is 0.00001, so a strike 1 km away is still at\n * 0.13 and one 4 km away (the farthest the weather places) at 0.009.\n */\nexport const THUNDER: SoundRecipe = {\n id: 'thunder',\n bus: 'weather',\n pan: true,\n layers: [sceneTone({ f: 70, f2: 28, d: 1.2, vol: 1 }), sceneNoise({ f: 260, f2: 50, d: 3.2, vol: 0.9, wet: 0.8 })],\n falloff: { model: 'inverse_square', k: 0.00001, scale: 1.4 },\n sources: ['jogo:L68278-68285 boom', 'sdk: rumble and falloff'],\n}\n\nexport const WEATHER_BANK: SoundBank = { id: 'weather', sounds: [THUNDER], loops: [RAIN_LOOP, WIND_LOOP, RAIN_HISS_GAME] }\nexport const WEATHER_SOUNDS: readonly SoundRecipe[] = WEATHER_BANK.sounds ?? []\nexport const WEATHER_LOOPS: readonly LoopRecipe[] = WEATHER_BANK.loops ?? []\n","import type { AudioSink, LoopHandle, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { Strike, WeatherSample } from '../types'\nimport { WEATHER_BANK } from './recipes'\n\nexport type WeatherSoundStyle = 'art_scene' | 'game'\n\nexport type WeatherSoundOptions = {\n /** Which team's rain: `art_scene` (default, the kit mix) or `game` (a highpass hiss). The wind and the thunder are the same. */\n readonly style?: WeatherSoundStyle\n /**\n * Level of the rain loop. It is `light` at `lightAt` mm/h (the game's rain, 0.035) and `heavy` from `heavyAt` mm/h (the art scene's, 0.06), a straight\n * line between, and 0 when it does not rain.\n */\n readonly rain?: { readonly light?: number; readonly heavy?: number; readonly lightAt?: number; readonly heavyAt?: number }\n /** Level of the wind loop: `base` (the art scene's 0.05) at `referenceSpeed` m/s, in proportion to the speed, at most `max`. */\n readonly wind?: { readonly base?: number; readonly referenceSpeed?: number; readonly max?: number }\n /** Where the listener is, to place the thunder around it (default the origin). */\n readonly listener?: () => Vec3\n /** Level of the thunder (default 1). */\n readonly thunderVolume?: number\n /** `false` keeps the sink's bank as it is (the host registered `WEATHER_BANK` itself). */\n readonly register?: boolean\n}\n\nexport const DEFAULT_RAIN_SOUND = { light: 0.035, heavy: 0.06, lightAt: 2.5, heavyAt: 15 } as const\n/** The art scene opens its wind at 0.05 with the breeze of its day (3.8 m/s, the `clear` state's wind): the level follows the speed from there. */\nexport const DEFAULT_WIND_SOUND = { base: 0.05, referenceSpeed: 3.8, max: 0.12 } as const\n\n/** The level of the rain loop for `rain` mm/h. */\nexport function rainVolume(rain: number, options: WeatherSoundOptions['rain'] = {}): number {\n if (!(rain > 0)) return 0\n const { light, heavy, lightAt, heavyAt } = { ...DEFAULT_RAIN_SOUND, ...options }\n if (heavyAt <= lightAt) return rain >= heavyAt ? heavy : light\n const t = Math.min(1, Math.max(0, (rain - lightAt) / (heavyAt - lightAt)))\n return light + (heavy - light) * t\n}\n\n/** The level of the wind loop for a wind of `speed` m/s. */\nexport function windVolume(speed: number, options: WeatherSoundOptions['wind'] = {}): number {\n const { base, referenceSpeed, max } = { ...DEFAULT_WIND_SOUND, ...options }\n return Math.min(max, (base * Math.max(0, speed)) / referenceSpeed)\n}\n\n/** Where a strike is, around `origin`: `bearing` is degrees clockwise from north, and north is -z. */\nexport function strikePosition(strike: Pick<Strike, 'distance' | 'bearing'>, origin: Vec3 = [0, 0, 0]): Vec3 {\n const angle = (strike.bearing * Math.PI) / 180\n return [origin[0] + Math.sin(angle) * strike.distance, origin[1], origin[2] - Math.cos(angle) * strike.distance]\n}\n\nexport type WeatherSound = {\n /** Sets the level of the loops from the weather of now (opens a loop the first time it is above 0). */\n update(sample: Pick<WeatherSample, 'rain' | 'windSpeed'>): void\n /** Plays a clap of thunder at the strike (call it when the thunder arrives: the weather delays it by `distance / 343`). */\n thunder(strike: Pick<Strike, 'distance' | 'bearing'>): void\n dispose(): void\n}\n\n/** The sound of the weather on the host's `audio`: the rain loop, the wind loop and the thunder. Without a sink (or one without loops) it does nothing. */\nexport function createWeatherSound(sink: AudioSink | undefined, options: WeatherSoundOptions = {}): WeatherSound {\n if (sink && options.register !== false) sink.register?.(WEATHER_BANK)\n const rainSound = options.style === 'game' ? 'rain_hiss_game' : 'rain_loop'\n const loops = new Map<string, LoopHandle>()\n const set = (id: string, volume: number): void => {\n let loop = loops.get(id)\n if (!loop) {\n if (!(volume > 0) || !sink?.loop) return\n loop = sink.loop(id)\n loops.set(id, loop)\n }\n loop.set({ volume })\n }\n return {\n update(sample) {\n set(rainSound, rainVolume(sample.rain, options.rain))\n set('wind_loop', windVolume(sample.windSpeed, options.wind))\n },\n thunder(strike) {\n sink?.play({ sound: 'thunder', position: strikePosition(strike, options.listener?.()), ...(options.thunderVolume === undefined ? {} : { volume: options.thunderVolume }) })\n },\n dispose() {\n for (const loop of loops.values()) loop.stop()\n loops.clear()\n },\n }\n}\n","import type { AudioSink, EnvironmentBus, EnvironmentState } from '@adatechnology/game-contracts'\n\nimport { createWeatherSound } from './audio/sound'\nimport type { WeatherSound, WeatherSoundOptions } from './audio/sound'\nimport type { Strike, WeatherSample } from './types'\nimport type { Weather } from './weather'\n\n/** The shape of the film of `game-fluids-three` (`FilmBridge`) this needs: no import, so the weather does not depend on it. */\nexport type FilmTarget = {\n setWeather(weather: { rain: number; drying?: number }): void\n wash?(maxDryness?: number): number\n}\n/** The interactables world (`game-interactables`): its water takes the rain, the soft volumes the wind. */\nexport type InteractablesTarget = { water: { setRain(mmPerHour: number): void }; setWind(x: number, z: number): void }\n/** The vegetation renderer (`game-vegetation`). `direction` is normalised by the renderer, `strength` and `gust` are 0..1. */\nexport type VegetationTarget = { setWind(wind: { direction?: [number, number]; strength?: number; gust?: number }): void }\n/** The effects world (`game-vfx`'s `VfxWorld`): smoke and dust drift with its wind. */\nexport type VfxTarget = { setWind(wind: readonly [number, number, number]): void }\n\nexport type WeatherTargets = {\n readonly film?: FilmTarget\n readonly interactables?: InteractablesTarget\n readonly vegetation?: VegetationTarget\n readonly vfx?: VfxTarget\n /** The host's environment bus (`ModuleHost.environment`). */\n readonly environment?: Pick<EnvironmentBus, 'set'>\n /** The host's sound (`ModuleHost.audio`): the rain and wind loops, and the thunder. */\n readonly audio?: AudioSink\n}\n\n/** The rules the bridges apply; every number can be replaced. */\nexport type WeatherBridgeRules = {\n /** Rain in mm/h at which the film counts as fully rained on (it stops drying, spreads 1.5 times faster). Default 2.5, the light rain. */\n readonly filmRainFullAt?: number\n /** Rain in mm/h from which the rain washes the fresh stain (Workshop and visor: heavy rain and stronger). Default 15; light rain does not wash. */\n readonly washFrom?: number\n /** Stains less dry than this are washed (visor L13494). Default 0.5. */\n readonly washBelow?: number\n /** Seconds between two washes while it pours. Default 1. */\n readonly washEvery?: number\n /** Wind speed in m/s that is 1 for the vegetation (`strength = min(1, speed / this)`). Default 20. */\n readonly windFull?: number\n}\n\nexport type WeatherBridgeOptions = WeatherBridgeRules & {\n readonly sound?: WeatherSoundOptions | false\n}\n\nexport const DEFAULT_BRIDGE_RULES = { filmRainFullAt: 2.5, washFrom: 15, washBelow: 0.5, washEvery: 1, windFull: 20 } as const\n\n/** The weather as the environment bus holds it. */\nexport function environmentOf(sample: WeatherSample): Partial<EnvironmentState> {\n return {\n rain: sample.rain,\n windX: sample.windX,\n windZ: sample.windZ,\n windSpeed: sample.windSpeed,\n gust: sample.gust,\n fogFar: sample.fogFar,\n visibility: sample.effects.visibility,\n nightFactor: sample.nightFactor,\n temperatureC: sample.temperatureC,\n wetness: sample.groundWetness,\n }\n}\n\nexport type WeatherBridges = {\n /** Follows this weather (the one before is let go) and pushes its values at once. */\n bind(weather: Weather): void\n /** Pushes the weather of now to every target; call it each frame after `weather.advance(dt)`. */\n update(dt: number): void\n dispose(): void\n}\n\n/**\n * Pushes one weather to the packages that react to it, each through a small interface of its own, so the weather depends on none of them and every\n * target is optional:\n * - fluids film: `setWeather({ rain: min(1, rain / filmRainFullAt), drying: dryingScale })`, and `wash()` every `washEvery` seconds while the rain is at\n * `washFrom` or stronger (light rain stops the drying and does not wash);\n * - interactables: `water.setRain(mm/h)` and `setWind(x, z)`;\n * - vegetation: `setWind({ direction: [x, z], strength: min(1, speed / windFull), gust: min(1, gust / windFull) })`;\n * - vfx: `setWind([x, 0, z])`;\n * - the environment bus: every value of `environmentOf`;\n * - sound: the rain and wind loops follow the weather, and each thunder that arrives plays at its bearing.\n */\nexport function createWeatherBridges(targets: WeatherTargets, options: WeatherBridgeOptions = {}): WeatherBridges {\n const rules = { ...DEFAULT_BRIDGE_RULES, ...options }\n const sound: WeatherSound | undefined = options.sound === false || !targets.audio ? undefined : createWeatherSound(targets.audio, options.sound ?? {})\n let weather: Weather | undefined\n let offThunder: (() => void) | undefined\n let sinceWash = 0\n let last: { rain?: number; windX?: number; windZ?: number; filmRain?: number; drying?: number } = {}\n\n const push = (): void => {\n if (!weather) return\n const sample = weather.sample()\n const { film, interactables, vegetation, vfx, environment } = targets\n environment?.set(environmentOf(sample))\n if (film) {\n const rain = Math.min(1, Math.max(0, sample.rain / rules.filmRainFullAt))\n const drying = sample.effects.dryingScale\n if (rain !== last.filmRain || drying !== last.drying) film.setWeather({ rain, drying })\n last.filmRain = rain\n last.drying = drying\n }\n if (interactables && sample.rain !== last.rain) interactables.water.setRain(sample.rain)\n const windChanged = sample.windX !== last.windX || sample.windZ !== last.windZ\n if (windChanged) {\n interactables?.setWind(sample.windX, sample.windZ)\n vfx?.setWind([sample.windX, 0, sample.windZ])\n if (vegetation) {\n const wind = { strength: Math.min(1, sample.windSpeed / rules.windFull), gust: Math.min(1, sample.gust / rules.windFull) }\n vegetation.setWind(sample.windSpeed > 1e-6 ? { direction: [sample.windX, sample.windZ], ...wind } : wind)\n }\n }\n last = { ...last, rain: sample.rain, windX: sample.windX, windZ: sample.windZ }\n sound?.update(sample)\n }\n\n const onThunder = (strike: Strike): void => sound?.thunder(strike)\n\n return {\n bind(next) {\n offThunder?.()\n weather = next\n offThunder = next.on('thunder', onThunder)\n last = {}\n sinceWash = 0\n push()\n },\n update(dt) {\n push()\n if (!weather || !targets.film?.wash) return\n if (weather.sample().rain < rules.washFrom) {\n sinceWash = 0\n return\n }\n sinceWash += dt\n if (sinceWash >= rules.washEvery) {\n sinceWash = 0\n targets.film.wash(rules.washBelow)\n }\n },\n dispose() {\n offThunder?.()\n offThunder = undefined\n weather = undefined\n sound?.dispose()\n },\n }\n}\n","export type WeatherBenchText = {\n readonly group: string\n readonly name: string\n readonly controls: Readonly<Record<'state' | 'transition' | 'time_of_day' | 'auto_schedule' | 'seed', string>>\n readonly hints: Readonly<Record<'transition' | 'time_of_day' | 'auto_schedule' | 'seed', string>>\n readonly options: Readonly<Record<'instant' | 'ten_seconds', string>>\n readonly layers: Readonly<Record<'environment' | 'fog', string>>\n readonly metrics: Readonly<Record<'state' | 'hour' | 'rain' | 'visibility' | 'sight' | 'hearing' | 'wind' | 'heat_index' | 'wetness' | 'strikes' | 'blend' | 'temperature', string>>\n readonly scenarios: Readonly<Record<'storm' | 'blend' | 'determinism' | 'dry_ground', string>>\n /** Names of the states and climates by id; the bench falls back to the id. */\n readonly states: Readonly<Record<string, string>>\n}\n\nconst EN: WeatherBenchText = {\n group: 'Weather',\n name: 'Weather area',\n controls: { state: 'Weather', transition: 'Transition', time_of_day: 'Time of day', auto_schedule: 'Automatic schedule', seed: 'Seed' },\n hints: {\n transition: 'How long the change to the chosen weather takes, in real seconds.',\n time_of_day: 'Hour of the day (the world restarts the clock there and keeps the weather).',\n auto_schedule: 'On: the climate changes the weather by itself and the clock runs 600 times faster than real time. Off: the weather stays until you change it.',\n seed: 'The same seed gives the same schedule and the same lightning.',\n },\n options: { instant: 'At once', ten_seconds: '10 seconds' },\n layers: { environment: 'Write host environment', fog: 'Fog in the scene' },\n metrics: {\n state: 'Weather',\n hour: 'Hour',\n rain: 'Rain',\n visibility: 'Visibility',\n sight: 'Sight scale',\n hearing: 'Hearing scale',\n wind: 'Wind',\n heat_index: 'Heat index',\n wetness: 'Ground wetness',\n strikes: 'Lightning strikes',\n blend: 'Blend',\n temperature: 'Temperature',\n },\n scenarios: {\n storm: 'A storm sees less and is heard less than a clear day, and strikes lightning',\n blend: 'A change blends over its time and settles in the new weather',\n determinism: 'The same seed gives the same day, another seed another one',\n dry_ground: 'Rain wets the ground and it dries after the rain stops',\n },\n states: {\n clear: 'Clear',\n overcast: 'Overcast',\n light_rain: 'Light rain',\n heavy_rain: 'Heavy rain',\n storm: 'Storm',\n fog: 'Fog',\n windy: 'Windy',\n cyclone: 'Cyclone',\n typhoon: 'Typhoon',\n extreme_heat: 'Extreme heat',\n },\n}\n\nconst PT_BR: WeatherBenchText = {\n group: 'Clima',\n name: 'Área de clima',\n controls: { state: 'Clima', transition: 'Transição', time_of_day: 'Hora do dia', auto_schedule: 'Sorteio automático', seed: 'Semente' },\n hints: {\n transition: 'Quanto demora a mudança para o clima escolhido, em segundos reais.',\n time_of_day: 'Hora do dia (o mundo reinicia o relógio nela e mantém o clima).',\n auto_schedule: 'Ligado: o clima do lugar muda sozinho e o relógio corre 600 vezes mais rápido que o real. Desligado: o clima fica até você trocar.',\n seed: 'A mesma semente dá o mesmo sorteio e os mesmos raios.',\n },\n options: { instant: 'De uma vez', ten_seconds: '10 segundos' },\n layers: { environment: 'Escrever no ambiente do host', fog: 'Névoa na cena' },\n metrics: {\n state: 'Clima',\n hour: 'Hora',\n rain: 'Chuva',\n visibility: 'Visibilidade',\n sight: 'Escala de visão',\n hearing: 'Escala de audição',\n wind: 'Vento',\n heat_index: 'Índice de calor',\n wetness: 'Chão molhado',\n strikes: 'Raios',\n blend: 'Mistura',\n temperature: 'Temperatura',\n },\n scenarios: {\n storm: 'Tempestade enxerga e é ouvida menos que um dia limpo, e solta raios',\n blend: 'Uma mudança se mistura no tempo dela e assenta no clima novo',\n determinism: 'A mesma semente dá o mesmo dia, outra semente dá outro',\n dry_ground: 'A chuva molha o chão e ele seca depois que a chuva para',\n },\n states: {\n clear: 'Limpo',\n overcast: 'Nublado',\n light_rain: 'Chuva fraca',\n heavy_rain: 'Chuva forte',\n storm: 'Tempestade',\n fog: 'Neblina',\n windy: 'Ventania',\n cyclone: 'Ciclone',\n typhoon: 'Tufão',\n extreme_heat: 'Calor extremo',\n },\n}\n\nexport const weatherBenchTextOf = (locale: string): WeatherBenchText => (locale === 'en' ? EN : PT_BR)\n","import type { BenchChange, ModuleControl, ModuleHost, ModuleLayer, ModuleMetric, ModuleScenario, TestableModule } from '@adatechnology/game-contracts'\n\nimport { createWeatherBridges, environmentOf } from '../bridges'\nimport type { WeatherBridges, WeatherTargets } from '../bridges'\nimport type { WeatherSoundOptions } from '../audio/sound'\nimport { createWeather } from '../weather'\nimport type { Weather, WeatherOptions } from '../weather'\nimport type { Strike, WeatherSample } from '../types'\nimport { weatherBenchTextOf } from './locale'\nimport type { WeatherBenchText } from './locale'\n\n/** What a renderer of the weather (game-weather-three) gives the bench: its layers, a step per frame and the switch of each layer. */\nexport type WeatherVisual = {\n update(dt: number): void\n setLayer(id: string, on: boolean): void\n dispose(): void\n}\n\n/** The bench hands a visual the weather it shows (always the live one, even after the bench restarts it) and what the room lends. */\nexport type WeatherVisualContext = { readonly host: ModuleHost; readonly locale: string; readonly weather: { sample(): WeatherSample } }\n\n/** The bench declares its layers before the room lends anything, so the factory tells them first (`fog` is the bench's own layer and reaches the visual through `setLayer` too). */\nexport type WeatherVisualFactory = {\n layers(locale: string): readonly ModuleLayer[]\n create(context: WeatherVisualContext): WeatherVisual\n}\n\nexport type WeatherTestModuleOptions = WeatherOptions & {\n locale?: string\n /** Text of a state id in the game's words; without it the bench uses its own names, then the id. */\n translate?: (key: string, locale: string) => string | undefined\n /** The weather to test (default a new one built from the other options). */\n weather?: Weather\n /** Whether the scene fog follows the weather at first (default true; the layer can be switched either way). A room that is not about weather starts it off. */\n fog?: boolean\n /** The packages the weather drives besides the host's environment bus and sound (fluids film, interactables, vegetation, vfx), from the example. */\n targets?: Omit<WeatherTargets, 'environment' | 'audio'>\n /** The rain, wind and thunder on the host's `audio`; `false` keeps the area silent. */\n sound?: WeatherSoundOptions | false\n /** The picture of the weather (rain, fog, sky, lightning, headlights, haze), from `@adatechnology/game-weather-three`. With it the bench leaves the scene fog to the visual. */\n visual?: WeatherVisualFactory\n}\n\n/** What the scenarios use of the context the test room passes. */\nexport interface WeatherScenarioLike {\n expect(condition: boolean, label: string, data?: Record<string, unknown>): void\n}\n\nexport type WeatherTestModule = TestableModule<WeatherScenarioLike> & {\n /** The weather in use (replaced when the bench changes the seed or the hour). */\n readonly weather: Weather\n}\n\nconst FAST_SCALE = 600\nconst NORMAL_SCALE = 72\nconst BLEND_SECONDS = 10\nconst HOURS_PER_DAY = 24\nconst FOG_NEAR = 1\n\ntype FogLike = new (color: number, near: number, far: number) => { far: number }\ntype SceneLike = { fog?: unknown }\ntype ThreeLike = { Fog?: FogLike }\n\n/**\n * The weather area of a test room, written against the generic contracts only: it drives a `createWeather` world, writes the result into the host's\n * environment bus (`host.environment`) every frame and shows the numbers a game reads from it. It also sets the scene fog from the weather's render fog.\n * Pure: no three.js beyond the host's own `Fog`, and the sky, rain, lightning and sound wait for the packages that draw and play them.\n */\nexport function createWeatherTestModule(options: WeatherTestModuleOptions = {}): WeatherTestModule {\n const locale = options.locale ?? 'pt-BR'\n const text: WeatherBenchText = weatherBenchTextOf(locale)\n const { locale: _locale, translate, weather: given, fog: _fog, targets: _targets, sound: _sound, visual: _visual, ...weatherOptions } = options\n void _locale\n void _fog\n void _targets\n void _sound\n void _visual\n const state = {\n seed: options.seed ?? 1,\n hour: options.startHour ?? 8,\n transition: 0,\n auto: options.autoSchedule ?? false,\n environment: true,\n fog: options.fog ?? true,\n }\n let host: ModuleHost | null = null\n let strikes = 0\n let offStrike: (() => void) | undefined\n let bridges: WeatherBridges | undefined\n let visual: WeatherVisual | undefined\n let weather: Weather = given ?? createWeather({ ...weatherOptions, autoSchedule: state.auto, ...(state.auto ? { timeScale: FAST_SCALE } : {}) })\n\n const watch = (): void => {\n offStrike?.()\n offStrike = weather.on('strike', (_strike: Strike) => void (strikes += 1))\n }\n watch()\n\n const nameOf = (id: string): string => translate?.(`weather.${id}`, locale) ?? text.states[id] ?? id\n\n // the world restarts with the new seed or hour and keeps the weather it was in\n const rebuild = (): void => {\n const current = weather.state()\n weather = createWeather({ ...weatherOptions, seed: state.seed, start: current, startHour: state.hour, autoSchedule: state.auto, timeScale: state.auto ? FAST_SCALE : NORMAL_SCALE })\n strikes = 0\n watch()\n bridges?.bind(weather)\n }\n\n const applyFog = (far: number): void => {\n const scene = host?.scene as SceneLike | undefined\n const Fog = (host?.THREE as ThreeLike | undefined)?.Fog\n if (!scene || typeof Fog !== 'function') return\n const fog = scene.fog as { far: number } | undefined | null\n if (fog && typeof fog.far === 'number') fog.far = far\n else scene.fog = new Fog(0xa8b4c0, FOG_NEAR, far)\n }\n\n const publish = (): void => {\n const sample = weather.sample()\n if (state.environment) host?.environment?.set(environmentOf(sample))\n if (state.fog && !visual) applyFog(sample.fogFar)\n }\n\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'layer') {\n if (change.id === 'environment' || change.id === 'fog') state[change.id] = change.on\n visual?.setLayer(change.id, change.on)\n return\n }\n if (change.kind === 'action') return\n const { id, value } = change\n if (id === 'state' && typeof value === 'string') weather.force(value, state.transition)\n else if (id === 'transition' && typeof value === 'string') state.transition = value === 'instant' ? 0 : BLEND_SECONDS\n else if (id === 'time_of_day' && typeof value === 'number') {\n state.hour = value\n rebuild()\n } else if (id === 'auto_schedule' && typeof value === 'boolean') {\n state.auto = value\n weather.setAutoSchedule(value)\n weather.setTimeScale(value ? FAST_SCALE : NORMAL_SCALE)\n } else if (id === 'seed' && typeof value === 'number') {\n state.seed = value\n rebuild()\n }\n }\n\n const controls = (): ModuleControl[] => [\n { kind: 'choice', id: 'state', name: text.controls.state, options: weather.registry.stateIds().map((id) => ({ id, name: nameOf(id) })), default: weather.state() },\n {\n kind: 'choice',\n id: 'transition',\n name: text.controls.transition,\n hint: text.hints.transition,\n options: [\n { id: 'instant', name: text.options.instant },\n { id: 'ten_seconds', name: text.options.ten_seconds },\n ],\n default: 'instant',\n },\n { kind: 'number', id: 'time_of_day', name: text.controls.time_of_day, hint: text.hints.time_of_day, unit: 'h', min: 0, max: HOURS_PER_DAY - 1, step: 1, default: state.hour },\n { kind: 'boolean', id: 'auto_schedule', name: text.controls.auto_schedule, hint: text.hints.auto_schedule, default: state.auto },\n { kind: 'number', id: 'seed', name: text.controls.seed, hint: text.hints.seed, min: 1, max: 9999, step: 1, default: state.seed },\n ]\n\n const layers = (): ModuleLayer[] => [\n { id: 'environment', name: text.layers.environment },\n { id: 'fog', name: text.layers.fog, default: state.fog },\n ...(options.visual?.layers(locale) ?? []),\n ]\n\n const metrics = (): ModuleMetric[] => [\n { id: 'current_state', name: text.metrics.state, read: () => nameOf(weather.state()) },\n { id: 'hour', name: text.metrics.hour, unit: 'h', digits: 1, read: () => weather.sample().hour },\n { id: 'blend', name: text.metrics.blend, digits: 2, read: () => weather.sample().blend },\n { id: 'rain', name: text.metrics.rain, unit: 'mm/h', digits: 1, read: () => weather.sample().rain },\n { id: 'visibility', name: text.metrics.visibility, unit: 'm', digits: 0, read: () => weather.sample().effects.visibility },\n { id: 'sight', name: text.metrics.sight, digits: 2, read: () => weather.sample().effects.sightScale },\n { id: 'hearing', name: text.metrics.hearing, digits: 2, read: () => weather.sample().effects.hearingScale },\n { id: 'wind', name: text.metrics.wind, unit: 'm/s', digits: 1, read: () => weather.sample().windSpeed },\n { id: 'temperature', name: text.metrics.temperature, unit: '°C', digits: 1, read: () => weather.sample().temperatureC },\n { id: 'heat_index', name: text.metrics.heat_index, unit: '°C', digits: 1, read: () => weather.sample().effects.heatIndexC },\n { id: 'wetness', name: text.metrics.wetness, digits: 2, read: () => weather.sample().groundWetness },\n { id: 'strikes', name: text.metrics.strikes, digits: 0, read: () => strikes },\n ]\n\n // each scenario runs its own worlds, so the bench's live one is not touched\n const fresh = (extra: WeatherOptions = {}): Weather => createWeather({ ...weatherOptions, autoSchedule: false, ...extra })\n const run = (world: Weather, seconds: number): void => {\n for (let elapsed = 0; elapsed < seconds; elapsed += 0.5) world.advance(0.5)\n }\n\n const scenarios = (): Array<ModuleScenario<WeatherScenarioLike>> => [\n {\n id: 'storm',\n name: text.scenarios.storm,\n run: ({ expect }) => {\n const clear = fresh({ seed: 3, start: 'clear' })\n const storm = fresh({ seed: 3, start: 'storm' })\n let hits = 0\n storm.on('strike', () => void (hits += 1))\n run(storm, 120)\n const calm = clear.sample().effects\n const rough = storm.sample().effects\n expect(rough.visibility < calm.visibility, 'a storm sees less far', { storm: rough.visibility, clear: calm.visibility })\n expect(rough.hearingScale < calm.hearingScale, 'rain masks sound', { storm: rough.hearingScale, clear: calm.hearingScale })\n expect(hits > 0, 'a storm strikes lightning', { strikes: hits })\n },\n },\n {\n id: 'blend',\n name: text.scenarios.blend,\n run: ({ expect }) => {\n const world = fresh({ seed: 3, start: 'clear' })\n world.force('heavy_rain', 10)\n run(world, 5)\n const middle = world.sample()\n expect(middle.blend > 0 && middle.blend < 1, 'halfway through the change it is still blending', { blend: middle.blend })\n expect(middle.rain > 0 && middle.rain < 15, 'the rain is between the two weathers', { rain: middle.rain })\n run(world, 6)\n expect(world.sample().blend === 1 && world.sample().state === 'heavy_rain', 'after its time it has settled', { blend: world.sample().blend })\n },\n },\n {\n id: 'determinism',\n name: text.scenarios.determinism,\n run: ({ expect }) => {\n const day = (seed: number): string => JSON.stringify(createWeather({ ...weatherOptions, seed }).timeline(48).samples)\n expect(day(5) === day(5), 'the same seed gives the same two days')\n expect(day(5) !== day(6), 'another seed gives another one')\n },\n },\n {\n id: 'dry_ground',\n name: text.scenarios.dry_ground,\n run: ({ expect }) => {\n const world = fresh({ seed: 3, start: 'heavy_rain' })\n run(world, 60)\n const wet = world.sample().groundWetness\n expect(wet > 0.3, 'rain wets the ground', { wetness: wet })\n world.force('clear', 0)\n run(world, 600)\n expect(world.sample().groundWetness < wet, 'it dries after the rain stops', { wet, after: world.sample().groundWetness })\n },\n },\n ]\n\n const module: WeatherTestModule = {\n id: 'weather_area',\n name: text.name,\n group: text.group,\n get weather() {\n return weather\n },\n items: () => [],\n controls: () => controls(),\n layers: () => layers(),\n metrics: () => metrics(),\n scenarios: () => scenarios(),\n attach(lent) {\n host = lent\n const off = lent.bench?.onChange(onChange)\n bridges = createWeatherBridges({ ...options.targets, ...(lent.audio ? { audio: lent.audio } : {}) }, { sound: options.sound ?? {} })\n bridges.bind(weather)\n visual = options.visual?.create({ host: lent, locale, weather: { sample: () => weather.sample() } })\n if (visual && !state.fog) visual.setLayer('fog', false)\n publish()\n const offFrame = lent.onFrame((dt) => {\n weather.advance(dt)\n publish()\n bridges?.update(dt)\n visual?.update(dt)\n })\n return () => {\n visual?.dispose()\n visual = undefined\n off?.()\n offFrame()\n bridges?.dispose()\n bridges = undefined\n host = null\n }\n },\n }\n return module\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adatechnology/game-weather",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Pure, seeded weather for games: states (clear to typhoon), climates with a Markov scheduler in game time, fronts from the west, lightning with thunder delay, ground wetness, gameplay effects, heat index and the day-night formula. Knows nothing about any game.",
|
|
6
6
|
"keywords": [
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"dist"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@adatechnology/game-contracts": "0.
|
|
41
|
+
"@adatechnology/game-contracts": "0.13.0",
|
|
42
|
+
"@adatechnology/game-audio": "0.2.0"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
45
|
"@types/node": "^22.10.7",
|