@onimaxxing/worldgen-node 0.15.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/index.d.ts ADDED
@@ -0,0 +1,682 @@
1
+ // Consumer-facing type surface for
2
+ // `@onimaxxing/worldgen`.
3
+ //
4
+ // This is the single types entry point for the package. The nested
5
+ // settings types (World, Subworld, BiomeSettings, NoiseTree, etc.)
6
+ // live in `editor_settings.d.ts` and are re-exported here so consumers
7
+ // can import every type by name from the package root.
8
+
9
+ // Klei-faithful YAML → JS parser. Pair with `worldgen.snapshot.merge`
10
+ // to ingest mod content (which ships as `.yaml`):
11
+ //
12
+ // const json = parseKleiYaml(readFileSync('mod/cluster.yaml', 'utf8'));
13
+ // worldgen.snapshot.merge({ 'expansion1::worldgen/clusters/X.yaml': JSON.stringify(json) });
14
+ export { parseKleiYaml } from './yaml.js';
15
+
16
+ // -----------------------------------------------------------------------
17
+ // Settings types (imported and re-exported from editor_settings.d.ts).
18
+ // `ClusterLayout`, `World`, `Subworld`, etc. are the typed schemas for
19
+ // the JSON-string values in each entry of the `path → JSON-string`
20
+ // snapshot files map.
21
+ // -----------------------------------------------------------------------
22
+
23
+ import type {
24
+ MinMax,
25
+ Vector2I,
26
+ WorldSize,
27
+ LayoutMethod,
28
+ WorldCategory,
29
+ ListRule,
30
+ TagCommand,
31
+ FilterCommand,
32
+ SampleBehaviour,
33
+ ZoneType,
34
+ TemperatureRange,
35
+ AllowedCellsFilter,
36
+ TraitRule,
37
+ SubworldMixingRule,
38
+ ModifyLayoutTagsRule,
39
+ TemplateSpawnRules,
40
+ World,
41
+ WeightedSubworldName,
42
+ Sampler,
43
+ Subworld,
44
+ Feature,
45
+ InternalMob,
46
+ CountRange,
47
+ WeightedBiome,
48
+ BaseLocation,
49
+ StartingWorldElement,
50
+ DefaultSettings,
51
+ MinMaxConfig,
52
+ MobLocation,
53
+ MobConfig,
54
+ RoomConfig,
55
+ TemplateVec2I,
56
+ TemplateInfo,
57
+ TemplateCell,
58
+ TemplateStorageItem,
59
+ TemplatePrefab,
60
+ TemplateContainer,
61
+ ClusterLayout,
62
+ NoiseTree,
63
+ BiomeSettings,
64
+ WorldTrait,
65
+ FeatureSettings,
66
+ DlcMixingSettings,
67
+ WorldMixingSettings,
68
+ SubworldMixingSettings,
69
+ } from './editor_settings.js';
70
+
71
+ export type {
72
+ MinMax,
73
+ Vector2I,
74
+ WorldSize,
75
+ LayoutMethod,
76
+ WorldCategory,
77
+ ListRule,
78
+ TagCommand,
79
+ FilterCommand,
80
+ SampleBehaviour,
81
+ ZoneType,
82
+ TemperatureRange,
83
+ AllowedCellsFilter,
84
+ TraitRule,
85
+ SubworldMixingRule,
86
+ ModifyLayoutTagsRule,
87
+ TemplateSpawnRules,
88
+ World,
89
+ WeightedSubworldName,
90
+ Sampler,
91
+ Subworld,
92
+ Feature,
93
+ InternalMob,
94
+ CountRange,
95
+ WeightedBiome,
96
+ BaseLocation,
97
+ StartingWorldElement,
98
+ DefaultSettings,
99
+ MinMaxConfig,
100
+ MobLocation,
101
+ MobConfig,
102
+ RoomConfig,
103
+ TemplateVec2I,
104
+ TemplateInfo,
105
+ TemplateCell,
106
+ TemplateStorageItem,
107
+ TemplatePrefab,
108
+ TemplateContainer,
109
+ ClusterLayout,
110
+ NoiseTree,
111
+ BiomeSettings,
112
+ WorldTrait,
113
+ FeatureSettings,
114
+ DlcMixingSettings,
115
+ WorldMixingSettings,
116
+ SubworldMixingSettings,
117
+ };
118
+
119
+ // -----------------------------------------------------------------------
120
+ // Map data types (returned by worldgen.generate)
121
+ // -----------------------------------------------------------------------
122
+
123
+ /**
124
+ * Full map payload returned by `worldgen.generate(coordinate)`. One
125
+ * top-level envelope for cluster metadata plus a per-world array with
126
+ * element grid, biome polygons, and entity spawns.
127
+ */
128
+ export interface MapData {
129
+ coordinate: string;
130
+ seed: number;
131
+ cluster_id: string;
132
+ /**
133
+ * Short cluster tag from the coord grammar, e.g. `SNDST-C`, `V-BAD-C`,
134
+ * `M-FRZ-C`, `VOLCA`. Matches the `coordinatePrefix` in the cluster
135
+ * YAML. Stable across seeds; use it to group results by cluster type
136
+ * without parsing the full coord string (prefixes can contain hyphens,
137
+ * so naive splitting is unreliable).
138
+ */
139
+ coordinate_prefix: string;
140
+ /** Element ids, indexed by the `element_idx` values in each world's cell grid. */
141
+ element_table: string[];
142
+ /** Spaced Out hex-grid world locations. One entry per asteroid. */
143
+ starmap: StarmapEntry[];
144
+ /** Spaced Out non-asteroid hex POIs (harvestable clouds, artifact sites, etc). */
145
+ starmap_pois: StarmapPoi[];
146
+ /** Basegame (non-SpacedOut) rocket destinations. Empty on SpacedOut clusters. */
147
+ vanilla_starmap: VanillaStarmapEntry[];
148
+ worlds: WorldMapData[];
149
+ /**
150
+ * Populated when the worldgen pipeline detected a fatal failure
151
+ * (e.g. "Could not guarantee minCount of Subworld X", story trait
152
+ * couldn't place on any world, layout collapse). Mirrors the game's
153
+ * `ReportWorldGenError` + abort path. `null` on successful generation.
154
+ */
155
+ failure: WorldgenFailure | null;
156
+ /**
157
+ * Recoverable per-world or cluster-level warnings that didn't abort
158
+ * worldgen. Per-world entries have the world index prepended to the
159
+ * message. Empty array on clean runs.
160
+ */
161
+ telemetry: WorldgenEvent[];
162
+ }
163
+
164
+ export interface WorldgenFailure {
165
+ /** Where in the pipeline the failure was detected (e.g. "AssignClusterLocations", "render_to_map"). */
166
+ stage: string;
167
+ /** World index where the failure happened. `-1` for cluster-level failures. */
168
+ world_index: number;
169
+ /** Human-readable description. */
170
+ message: string;
171
+ }
172
+
173
+ export interface WorldgenEvent {
174
+ /** Stable short tag for grouping (e.g. "layout", "noise", "mob_spawning", "template_rules"). */
175
+ category: string;
176
+ /** Free-form description. Per-world entries are prefixed with `world[N]:`. */
177
+ message: string;
178
+ }
179
+
180
+ export interface WorldMapData {
181
+ /**
182
+ * World config path — **post-substitution** when the placement was
183
+ * swapped via `WorldgenMixing.DoWorldMixing`. On seeds where a
184
+ * Ceres / Prehistoric / Aquatic Asteroid Mixing fragment took this
185
+ * slot, `name` is the fragment path (e.g.
186
+ * `"dlc5::worlds/MixingAquaticAsteroid"`). Use `remixed_from` to
187
+ * recover the vanilla identity that the cluster picker showed.
188
+ */
189
+ name: string;
190
+ /**
191
+ * Pre-substitution world path when this slot was swapped by
192
+ * world-mixing, else `null`. Set from the `MixingApplied.from_world`
193
+ * recorded during `Cluster.generate_with_settings`. Consumers that
194
+ * query by the world they see in the cluster picker
195
+ * (`"TundraMoonlet"`, `"MarshyMoonlet"`, …) should substring-match
196
+ * this field as a fallback when `name` — which is post-substitution
197
+ * — doesn't contain the vanilla needle. Mirrors
198
+ * `ClusterSummary.remixed_from` in the gambling wasm.
199
+ */
200
+ remixed_from: string | null;
201
+ /**
202
+ * CGM-style mixing source id when this slot was swapped, else
203
+ * `null`. One of `"CeresAsteroidMixing"`,
204
+ * `"PrehistoricAsteroidMixing"`, `"AquaticAsteroidMixing"`. Stable
205
+ * across builds; safe to use for badge-rendering.
206
+ */
207
+ remixed_source: string | null;
208
+ width: number;
209
+ height: number;
210
+ is_starting: boolean;
211
+ world_traits: string[];
212
+ /**
213
+ * u16 per cell, row-major (`width * height`). Backed by a
214
+ * freshly-allocated JS typed array (`wasm-bindgen` copies out of
215
+ * WASM linear memory), so it's safe to retain across subsequent
216
+ * `worldgen.generate` calls without being invalidated.
217
+ */
218
+ element_idx: Uint16Array;
219
+ mass: Float32Array;
220
+ temperature: Float32Array;
221
+ /** u8 per cell; 255 means no disease. */
222
+ disease_idx: Uint8Array;
223
+ /** i32 per cell. */
224
+ disease_count: Int32Array;
225
+ /**
226
+ * U59 backwall element ids, one u16 per cell. Vacuum-filled (the
227
+ * Vacuum element's index in `MapData.element_table`) for worlds
228
+ * whose subworld YAML doesn't declare a `backwallNoise` channel —
229
+ * only DLC5 aquatic biomes (Reef / Abyss / shallows) populate
230
+ * non-Vacuum backwall.
231
+ */
232
+ backwall_element_idx: Uint16Array;
233
+ /** U59 backwall mass per cell, in kg. Zero on Vacuum cells. */
234
+ backwall_mass: Float32Array;
235
+ /** U59 backwall temperature per cell, in K. Zero on Vacuum cells. */
236
+ backwall_temperature: Float32Array;
237
+ biome_cells: BiomeCell[];
238
+ geysers: GeyserSpawn[];
239
+ buildings: EntitySpawn[];
240
+ pickupables: EntitySpawn[];
241
+ other_entities: EntitySpawn[];
242
+ }
243
+
244
+ export interface BiomeCell {
245
+ id: number;
246
+ /** Subworld type path, e.g. `"expansion1::subworlds/jungle/med_Jungle"`. */
247
+ type: string;
248
+ /**
249
+ * The Subworld's `ZoneType` enum value as a string (matches the
250
+ * `ZoneType` union in `editor_settings.d.ts`). `null` when the
251
+ * subworld path couldn't be resolved in the current settings.
252
+ */
253
+ zone_type: ZoneType | null;
254
+ x: number;
255
+ y: number;
256
+ /** Flat polygon vertex array: `[x0, y0, x1, y1,...]`. */
257
+ poly: number[];
258
+ /**
259
+ * The layout tags this overworld node carries — e.g. `"AtSurface"`,
260
+ * `"AtDepths"`, `"AtEdge"`, distance tags (`"AtSurface_Distance2"`),
261
+ * the subworld's `ZoneType` tag, and its subworld tags. These are the
262
+ * keys `AllowedCellsFilter` matches against, so they let you
263
+ * visualize/explain why a subworld landed here and interpret the
264
+ * filter chain client-side. Not a closed vocabulary (subworld/world
265
+ * YAML can declare arbitrary tags).
266
+ */
267
+ tags: string[];
268
+ }
269
+
270
+ export interface EntitySpawn {
271
+ /** Game prefab name. */
272
+ tag: string;
273
+ /** Grid cell index. */
274
+ cell: number;
275
+ /** `cell % width`. */
276
+ x: number;
277
+ /** `cell / width`. */
278
+ y: number;
279
+ /**
280
+ * Connections bitmask preserved from the source
281
+ * `TemplatePrefab.connections`. Present only for template-placed
282
+ * conduit-aware buildings (LogicGate, LogicWire, etc.). Absent for
283
+ * ambient / terrain mob spawns and for prefabs that had no
284
+ * connections field in the YAML.
285
+ */
286
+ connections?: number;
287
+ /**
288
+ * Rotation / orientation preserved from
289
+ * `TemplatePrefab.rotationOrientation`. e.g. `"R90"`, `"R180"`,
290
+ * `"R270"`, `"FlipH"`. Present only for rotated template buildings
291
+ * (e.g. the R270 LiquidValve in `poi_old_pool`). Absent otherwise.
292
+ */
293
+ rotationOrientation?: string;
294
+ }
295
+
296
+ /**
297
+ * Geyser spawn. `type` is the resolved template id (what the game
298
+ * rolls `GeyserGeneric_*` into); `scaled_*` fields come from the
299
+ * per-geyser stats roll and are absent for non-random geysers.
300
+ */
301
+ export interface GeyserSpawn extends EntitySpawn {
302
+ type: string;
303
+ scaled_rate?: number;
304
+ scaled_iter_len?: number;
305
+ scaled_iter_pct?: number;
306
+ scaled_year_len?: number;
307
+ scaled_year_pct?: number;
308
+ }
309
+
310
+ export interface StarmapEntry {
311
+ world_index: number;
312
+ q: number;
313
+ r: number;
314
+ }
315
+
316
+ export interface StarmapPoi {
317
+ /** e.g. `"HarvestableSpacePOI_*"`, `"ArtifactSpacePOI"`. */
318
+ poi_type: string;
319
+ q: number;
320
+ r: number;
321
+ // Present only on harvestable POIs:
322
+ capacity_roll?: number;
323
+ recharge_roll?: number;
324
+ total_capacity?: number;
325
+ recharge_time?: number;
326
+ }
327
+
328
+ export interface VanillaStarmapEntry {
329
+ type: string;
330
+ distance: number;
331
+ }
332
+
333
+ // -----------------------------------------------------------------------
334
+ // Settle snapshot (returned by worldgen.advance)
335
+ // -----------------------------------------------------------------------
336
+
337
+ /**
338
+ * A per-tick snapshot of settle state, one decoded v4 binary frame.
339
+ * Arrays are parallel (indexed by row-major cell position).
340
+ */
341
+ export interface SettleSnapshot {
342
+ /** Tick this snapshot was taken at. Monotonic, 1..=499. */
343
+ tick: number;
344
+ worlds: SettleWorld[];
345
+ }
346
+
347
+ export interface SettleWorld {
348
+ width: number;
349
+ height: number;
350
+ element_idx: Uint16Array;
351
+ mass: Float32Array;
352
+ temperature: Float32Array;
353
+ /** 255 = no disease on that cell. */
354
+ disease_idx: Uint8Array;
355
+ disease_count: Int32Array;
356
+ /**
357
+ * U59 backwall element ids, live at the snapshot's `tick`. Vacuum
358
+ * (`element_table.indexOf("Vacuum")` from `MapData`) on worlds
359
+ * without `backwallNoise` in their subworld YAML — populated only
360
+ * for DLC5 aquatic biomes.
361
+ */
362
+ backwall_element_idx: Uint16Array;
363
+ /** U59 backwall mass per cell, in kg. Zero on Vacuum cells. */
364
+ backwall_mass: Float32Array;
365
+ /** U59 backwall temperature per cell, in K. Zero on Vacuum cells. */
366
+ backwall_temperature: Float32Array;
367
+ }
368
+
369
+ // -----------------------------------------------------------------------
370
+ // Entity spawners (returned by worldgen.entities)
371
+ // -----------------------------------------------------------------------
372
+
373
+ /**
374
+ * Refreshed entity spawns against the cached cluster's current sim
375
+ * state. Shape mirrors the per-world entity arrays in `MapData`.
376
+ */
377
+ export interface EntitySpawners {
378
+ worlds: EntitySpawnerWorld[];
379
+ }
380
+
381
+ export interface EntitySpawnerWorld {
382
+ geysers: GeyserSpawn[];
383
+ buildings: EntitySpawn[];
384
+ pickupables: EntitySpawn[];
385
+ other_entities: EntitySpawn[];
386
+ }
387
+
388
+ // -----------------------------------------------------------------------
389
+ // init + worldgen singleton
390
+ // -----------------------------------------------------------------------
391
+
392
+ export interface InitOptions {
393
+ /**
394
+ * Custom URL / Request / pre-compiled module for the .wasm binary.
395
+ * Omit to use the bundler-rewritten default.
396
+ */
397
+ module_or_path?:
398
+ | string
399
+ | URL
400
+ | Request
401
+ | Response
402
+ | BufferSource
403
+ | WebAssembly.Module
404
+ | Promise<
405
+ string | URL | Request | Response | BufferSource | WebAssembly.Module
406
+ >;
407
+
408
+ /**
409
+ * - `'auto'` (default): pick parallel when `crossOriginIsolated` and
410
+ * `SharedArrayBuffer` are available, with
411
+ * `navigator.hardwareConcurrency` workers. Otherwise serial.
412
+ * - `'serial'`: force the serial build.
413
+ * - `number`: force parallel with this many workers (falls back to
414
+ * serial when parallel isn't available).
415
+ */
416
+ threads?: number | 'auto' | 'serial';
417
+ }
418
+
419
+ /**
420
+ * Initialise the WASM module. The web package ships both a serial and
421
+ * a parallel (rayon + SharedArrayBuffer) build; `init()` feature-detects
422
+ * the runtime, loads the appropriate one, and on parallel hosts also
423
+ * spawns the worker pool. Memoized — extra calls short-circuit.
424
+ */
425
+ export default function init(options?: InitOptions): Promise<void>;
426
+
427
+ /** `true` for parallel, `false` for serial, `null` before init resolves. */
428
+ export function isParallel(): boolean | null;
429
+
430
+ /**
431
+ * Singleton that wraps the one-slot cluster cache in WASM. All methods
432
+ * (except `generate`, `reset`, and `version`) operate on whatever
433
+ * cluster is currently cached; call `generate(coord)` first to populate.
434
+ */
435
+ export const worldgen: {
436
+ /**
437
+ * Generate a cluster from a game coordinate. Caches the cluster in
438
+ * the WASM thread-local slot, replacing any previously cached cluster.
439
+ */
440
+ generate(coordinate: string): MapData;
441
+
442
+ /**
443
+ * Advance the cached cluster's settle sim to `targetTick` (in
444
+ * `1..=499`) and return a decoded snapshot at that tick. Call
445
+ * repeatedly with increasing ticks for progressive rendering. The
446
+ * settle runs 499 ticks total; the final call with `targetTick = 499`
447
+ * finalises the cluster.
448
+ *
449
+ * Throws if the cache is empty or `targetTick` is out of range.
450
+ */
451
+ advance(targetTick: number): SettleSnapshot;
452
+
453
+ /**
454
+ * Re-run ambient mob spawning against the cached cluster's current
455
+ * cell state and return the refreshed entity lists. Pairs with
456
+ * `advance()`. liquid/gas settling can invalidate earlier mob
457
+ * placements. Template-placed entities persist across calls.
458
+ */
459
+ entities(): EntitySpawners;
460
+
461
+ /**
462
+ * Drop the cached generated cluster. Editor settings (if mutated)
463
+ * are preserved.
464
+ */
465
+ clear(): void;
466
+
467
+ /**
468
+ * Snapshot-based settings I/O. Each entry of the `files` map keys a
469
+ * Klei config path (e.g.
470
+ * `expansion1::worldgen/clusters/CGMCluster.yaml`) to that file's
471
+ * JSON-encoded content — the same shape Klei's YAML loader produces
472
+ * after parsing. `load*` / `merge` / `remove` calls evict the
473
+ * cluster cache; the next `generate()` rebuilds with the new
474
+ * settings.
475
+ *
476
+ * ### Stability contracts
477
+ *
478
+ * - **Canonical stringification.** `files()[path]` for an unchanged
479
+ * file is byte-equivalent across calls and across processes.
480
+ * JSON object-key order is alphabetical for `HashMap`-backed
481
+ * storage (the four `ComposableDict<K,V>` tables — mobs, rooms,
482
+ * borders, temperatures); `IndexMap`-backed fields preserve
483
+ * insertion order (the load order from the source bytes); struct
484
+ * fields use declared order. No floating-point reformatting.
485
+ * - **Idempotent `load(files())`.** Calling `load(files())` is a
486
+ * no-op against engine state; the very next `files()` returns
487
+ * byte-equivalent strings to the input. Verified across all 913
488
+ * vanilla paths.
489
+ * - **Deep-copy returns.** `files()` returns a fresh, freely
490
+ * mutable plain object (the engine `JSON.parse`s its internal
491
+ * string representation per call). Mutating the returned map
492
+ * does not affect the engine's snapshot. The `Readonly<...>`
493
+ * typing below is advisory: it nudges callers toward
494
+ * defensive-copy hygiene at the API surface even though the
495
+ * underlying object is yours to mutate.
496
+ * - **Path-set preservation.** `load(filesMap)` neither adds nor
497
+ * drops paths. The set of keys in the next `files()` exactly
498
+ * matches the keys you passed in.
499
+ * - **Merge collision = last-wins.** When `merge(files)` is called
500
+ * with a path already present in SETTINGS, the new value
501
+ * replaces the old one. Within a single `merge()` call the same
502
+ * semantics apply: later entries in the input map win over
503
+ * earlier ones for the same path.
504
+ */
505
+ snapshot: {
506
+ /** Reset SETTINGS to the embedded vanilla baseline. Strict mode
507
+ * (closed parity surface — rejects mod-defined enum extensions
508
+ * like custom TemperatureRange values). */
509
+ loadVanilla(): void;
510
+ /** Extensions-mode `loadVanilla`. Identical bytes for the vanilla
511
+ * case; the difference surfaces on subsequent `merge(modFiles)`
512
+ * calls, where Extensions mode accepts `TemperatureRange::Custom(X)`
513
+ * and similar mod-defined enum extensions provided the mod also
514
+ * registers them in `tables.temperatures.add`. Use this when
515
+ * bootstrapping the slot for a mod-overlay flow (e.g. Baator's
516
+ * HellHot temperature, custom Tag definitions). */
517
+ loadVanillaExtensions(): void;
518
+ /** Replace SETTINGS with the `path → JSON-string` `files` map.
519
+ * Strict mode. The next `files()` call returns byte-equivalent
520
+ * strings to the input (idempotent round-trip; see contract
521
+ * above). */
522
+ load(files: Readonly<Record<string, string>>): void;
523
+ /** Extensions-mode counterpart of `load`. Accepts mod-defined
524
+ * enum extensions when the mod registers them in the
525
+ * corresponding `add` table. Subsequent `merge`s on the slot
526
+ * inherit the Extensions mode — no need to call `_extensions`
527
+ * variants for merges. */
528
+ loadExtensions(files: Readonly<Record<string, string>>): void;
529
+ /**
530
+ * Merge `files` into the active SETTINGS (last-wins on duplicate
531
+ * paths — both vs. existing SETTINGS and within the same input
532
+ * map). Auto-loads vanilla as the base if SETTINGS hasn't been
533
+ * initialised. Typical mod-overlay entry point.
534
+ */
535
+ merge(files: Readonly<Record<string, string>>): void;
536
+ /**
537
+ * Return the active SETTINGS as a `path → JSON-string` files map.
538
+ * Auto-loads vanilla if SETTINGS hasn't been initialised.
539
+ *
540
+ * Returns a fresh deep copy each call — the engine does not share
541
+ * state with the returned object. Mutate it freely; it won't
542
+ * affect the engine. Subsequent `files()` calls re-emit from the
543
+ * engine state, not the previously-returned object.
544
+ */
545
+ files(): Readonly<Record<string, string>>;
546
+ /**
547
+ * Stable hex hash of the active snapshot's canonical projection
548
+ * (the same projection `files()` returns). Auto-loads vanilla if
549
+ * SETTINGS hasn't been initialised.
550
+ *
551
+ * Contract: two snapshots with the same logical content produce
552
+ * the same hash regardless of HashMap/IndexMap iteration order or
553
+ * load history. `client.load(server.files())` followed by
554
+ * `client.checksum()` reproduces `server.checksum()` — that's the
555
+ * worker fast-path: client posts its checksum, worker fast-paths
556
+ * if equal instead of demanding a full `load(fullMap)`.
557
+ *
558
+ * Use to decide between `merge(delta)` (fast-path) and
559
+ * `load(fullMap)` (re-sync) when reconciling client + worker
560
+ * settings.
561
+ *
562
+ * Cached: the hash is computed once per snapshot version, on the
563
+ * first call after any `loadVanilla` / `load` / `merge` / `remove`
564
+ * / `reset`. Subsequent calls return the cached string until the
565
+ * next mutation. Cold recompute is ≈80 ms on the full vanilla
566
+ * snapshot; steady-state cache hit is a single property read.
567
+ */
568
+ checksum(): string;
569
+ /**
570
+ * Drop `paths` from the active SETTINGS. Auto-loads vanilla as
571
+ * the base if SETTINGS hasn't been initialised. Paths not present
572
+ * in the snapshot are silently ignored.
573
+ *
574
+ * Closes the additive-only gap in `merge` — lets the worker
575
+ * apply a "user deleted a custom world" delta without forcing a
576
+ * full re-sync. Surgical: O(paths × categories) in-place drops
577
+ * on the engine-side snapshot, no `to_files` / `from_files`
578
+ * round-trip.
579
+ */
580
+ remove(paths: readonly string[]): void;
581
+ /**
582
+ * The ONI game build this WASM was baselined against (e.g.
583
+ * `"737195"`). Same value as `worldgen.version()`; exposed under
584
+ * `snapshot` for persistence flows.
585
+ *
586
+ * Recommended use: editors persist
587
+ * `{snapshot: files(), schemaVersion: snapshot.schemaVersion()}`
588
+ * to IndexedDB / share URLs / disk. On load, compare the
589
+ * persisted `schemaVersion` against the current
590
+ * `snapshot.schemaVersion()` and warn / migrate / refuse before
591
+ * calling `load(snapshot)`. Without the stamp, a checkpoint from
592
+ * an older engine silently coerces missing or renamed fields.
593
+ */
594
+ schemaVersion(): string;
595
+ };
596
+
597
+ /**
598
+ * Drop both the editor settings and the cluster cache. Next
599
+ * `generate()` reloads the embedded stock settings from scratch.
600
+ */
601
+ reset(): void;
602
+
603
+ /**
604
+ * Evaluate a noise tree over a `width × height` 2D grid and return one
605
+ * scalar per cell, row-major (`y * width + x`). Values are
606
+ * **unnormalised** — the consumer applies any colour ramp / contrast
607
+ * on the JS side, avoiding a hidden contract about how a particular
608
+ * range maps to biomes.
609
+ *
610
+ * Pass `{ kind: "named", name }` to evaluate one of the trees in the
611
+ * live SETTINGS' noise map (sourced from `worldgen/noise/*.yaml`
612
+ * — preview reflects pending edits made via `snapshot.merge` /
613
+ * `snapshot.load` without re-running cluster generation). Pass
614
+ * `{ kind: "inline", yaml }` to evaluate a YAML document parsed in
615
+ * isolation, useful for previewing edits that haven't been merged
616
+ * back into the active SETTINGS yet.
617
+ *
618
+ * Sample coords map `width × height` linearly onto the tree's
619
+ * `settings.lowerBound..upperBound` rectangle (cell-centred), so the
620
+ * preview honours the editor's `SampleSettings.zoom` / bounds.
621
+ *
622
+ * Throws if the named tree doesn't exist, the inline YAML fails to
623
+ * parse, or the tree has no terminator link.
624
+ */
625
+ evaluateNoise(
626
+ tree: NoiseTreeRef,
627
+ width: number,
628
+ height: number,
629
+ seed: number,
630
+ ): Float32Array;
631
+
632
+ /**
633
+ * Enumerate every noise-node variant the engine recognises plus its
634
+ * param schema. Drives the editor's "Add node" palette + per-node
635
+ * form generation in worldgen-editor; without this, the editor would
636
+ * hard-code the node list and drift from the engine whenever a new
637
+ * generator is added.
638
+ *
639
+ * The list is static across the lifetime of the build — call once
640
+ * and cache the result.
641
+ */
642
+ noiseNodeKinds(): NoiseNodeKindSpec[];
643
+
644
+ /**
645
+ * The ONI game build this WASM was parity-baselined against (e.g.
646
+ * `"737195"`).
647
+ */
648
+ version(): string;
649
+ };
650
+
651
+ /** Discriminated union accepted by `worldgen.evaluateNoise`. */
652
+ export type NoiseTreeRef =
653
+ /** Look up `name` in the active SETTINGS' noise map (sourced from
654
+ * `worldgen/noise/*.yaml`). */
655
+ | { kind: "named"; name: string }
656
+ /** Parse the YAML document in isolation. */
657
+ | { kind: "inline"; yaml: string };
658
+
659
+ /** One entry returned by `worldgen.noiseNodeKinds()`. */
660
+ export interface NoiseNodeKindSpec {
661
+ /** Which `NoiseTree.<category>s` map this node variant lives in. */
662
+ category: "primitive" | "filter" | "modifier" | "transformer" | "selector" | "combiner";
663
+ /** Discriminator value (e.g. `"ImprovedPerlin"`, `"SumFractal"`, `"Add"`). */
664
+ kind: string;
665
+ /** Number of input links this node consumes. `0` for primitives. */
666
+ sources: number;
667
+ /** Param-form schema. Field names match the YAML field on the corresponding struct. */
668
+ params: NoiseNodeParam[];
669
+ }
670
+
671
+ /** One field in a `NoiseNodeKindSpec.params` array. */
672
+ export interface NoiseNodeParam {
673
+ /** YAML field name (e.g. `"frequency"`, `"modifyType"`). */
674
+ name: string;
675
+ /** Scalar type the editor should render. */
676
+ type: "f32" | "i32" | "bool" | "enum" | "vec2" | "vec3" | "string";
677
+ /** Default value matching the corresponding struct's `Default` impl. */
678
+ default: number | string | boolean | { X: number; Y: number } | { X: number; Y: number; Z: number };
679
+ /** When `type === "enum"`, the allowed string values. */
680
+ enumValues?: string[];
681
+ }
682
+