@onimaxxing/worldgen-node 0.21.1 → 0.21.3

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 tigin-backwards
3
+ Copyright (c) 2026 i must onimaxx. i MuSt oNiMaXx! I MUST ONIMAXX!!! onimaxxing.com
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -10,6 +10,7 @@ same cluster the game would generate for a given coordinate.
10
10
  - Geyser, building, pickupable, and other entity spawn positions.
11
11
  - Per-cell mass, temperature, and disease (raw after `worldgen.generate`; settled after `worldgen.advance`).
12
12
  - Both basegame and Spaced Out clusters, including story traits, mixing codes, and DLC toggles.
13
+ - Partial generation of selected worlds (`worldgen.partials`).
13
14
 
14
15
  Output is verified cell-by-cell against snapshots captured from the
15
16
  running game, with a slight modification to force determinism during
@@ -133,6 +134,31 @@ Generate a cluster from a game coordinate and return the decoded
133
134
  map (see [`MapData` shape](#mapdata-shape)). Caches the cluster
134
135
  internally, replacing anything previously cached.
135
136
 
137
+ ```ts
138
+ worldgen.partials(coord: string, opts: PartialsOptions): PartialsResult
139
+ ```
140
+
141
+ Generate only the selected worlds of a cluster. Stateless; does not
142
+ touch the cluster cache.
143
+
144
+ `opts.worlds` selects by placement index or world path (full path or
145
+ last segment, matched after mixing). Selectors that match nothing come
146
+ back in `absent` rather than erroring. `opts.omit` drops payload
147
+ blocks (`'cells'`, `'biomes'`, `'spawners'`). Cell grids are
148
+ pre-settle; for settled state use `worldgen.generate` +
149
+ `worldgen.advance`.
150
+
151
+ ```ts
152
+ const r = worldgen.partials('V-SNDST-C-42-0-4A-MUWF1', {
153
+ worlds: ['VanillaSandstoneDefault'],
154
+ omit: ['cells', 'biomes', 'spawners'],
155
+ });
156
+ for (const g of r.worlds[0]?.geysers ?? []) console.log(g.type, g.x, g.y);
157
+ ```
158
+
159
+ Geyser output matches a full generate exactly. Story-trait templates
160
+ and starmap locations are not generated in partial mode.
161
+
136
162
  ```ts
137
163
  worldgen.entities(): EntitySpawners
138
164
  ```
package/index.cjs CHANGED
@@ -87,6 +87,10 @@ const worldgen = {
87
87
  entities() {
88
88
  return JSON.parse(_wasm.get_entity_spawners());
89
89
  },
90
+ // Partial worldgen; see index.js for the full contract notes.
91
+ partials(coord, opts) {
92
+ return JSON.parse(_wasm.partials_from_coordinate(coord, JSON.stringify(opts ?? {})));
93
+ },
90
94
  clear() {
91
95
  _wasm.clear_cluster_cache();
92
96
  },
package/index.d.ts CHANGED
@@ -451,6 +451,105 @@ export interface EntitySpawnerWorld {
451
451
  other_entities: EntitySpawn[];
452
452
  }
453
453
 
454
+ // -----------------------------------------------------------------------
455
+ // Partial worldgen
456
+ // -----------------------------------------------------------------------
457
+
458
+ export interface PartialsOptions {
459
+ /**
460
+ * Placement indices and/or world-path strings. A string matches the
461
+ * POST-mixing world path for this seed, in full
462
+ * (`"expansion1::worlds/SandstoneDefault"`) or by its last segment,
463
+ * case-insensitive, not the localized display name ("Terra").
464
+ * Selectors that match nothing land in the result's `absent` list
465
+ * instead of erroring.
466
+ */
467
+ worlds: Array<number | string>;
468
+ /** `"templates"` (default) or `"notemplates"` (skip template placement). */
469
+ mode?: 'templates' | 'notemplates';
470
+ /**
471
+ * Payload blocks to drop. Serialization only; generation cost is
472
+ * identical. Geysers and traits are always included.
473
+ */
474
+ omit?: Array<'cells' | 'biomes' | 'spawners'>;
475
+ }
476
+
477
+ /**
478
+ * One generated world from `worldgen.partials`. Grid fields arrive as
479
+ * plain JSON arrays (not the typed arrays `generate` uses), hold
480
+ * pre-settle state, and are present unless the corresponding `omit`
481
+ * block was requested.
482
+ */
483
+ export interface PartialWorld {
484
+ /** Placement index in the cluster layout (stable slot identity). */
485
+ index: number;
486
+ /** Post-mixing world path; see `WorldMapData.name`. */
487
+ name: string;
488
+ remixed_from: string | null;
489
+ remixed_source: string | null;
490
+ width: number;
491
+ height: number;
492
+ is_starting: boolean;
493
+ world_traits: string[];
494
+ geysers: GeyserSpawn[];
495
+ /**
496
+ * Digest-format per-world geyser hashes (FNV-1a-64, uppercase hex,
497
+ * empty when count is 0): the exact values the committed parity
498
+ * digests store. The counts hash a fixed tag allowlist that excludes
499
+ * some DLC5 spawners (e.g. SmallReefGeyser), so `geyser_spawns_count`
500
+ * can be less than `geysers.length`; the `geysers` array is the
501
+ * complete list.
502
+ */
503
+ geyser_spawns_sha: string;
504
+ geyser_spawns_count: number;
505
+ geyser_stats_sha: string;
506
+ geyser_stats_count: number;
507
+ element_idx?: number[];
508
+ mass?: number[];
509
+ temperature?: number[];
510
+ disease_idx?: number[];
511
+ disease_count?: number[];
512
+ backwall_element_idx?: number[];
513
+ backwall_mass?: number[];
514
+ backwall_temperature?: number[];
515
+ zone_idx?: number[];
516
+ zone_table?: string[];
517
+ subworld_idx?: number[];
518
+ subworld_table?: string[];
519
+ biome_cells?: BiomeCell[];
520
+ buildings?: EntitySpawn[];
521
+ pickupables?: EntitySpawn[];
522
+ other_entities?: EntitySpawn[];
523
+ }
524
+
525
+ export interface PartialsMixingApplied {
526
+ /** Placement index whose vanilla world was substituted. */
527
+ slot: number;
528
+ from: string;
529
+ to: string;
530
+ source: string;
531
+ }
532
+
533
+ export interface PartialsResult {
534
+ coordinate: string;
535
+ seed: number;
536
+ cluster: string;
537
+ /**
538
+ * Markers: story-trait templates were skipped, so cell grids on
539
+ * worlds that would have received one differ from a full `generate`.
540
+ * Geysers are unaffected.
541
+ */
542
+ partial: true;
543
+ story_traits_skipped: true;
544
+ /** World-mixing substitutions applied for this seed (all slots). */
545
+ mixing_applied: PartialsMixingApplied[];
546
+ /** Generated worlds, one per selected slot present this seed. */
547
+ worlds: PartialWorld[];
548
+ /** Requested selectors that matched no slot this seed. */
549
+ absent: string[];
550
+ failure?: { stage: string; world_index: number; message: string } | null;
551
+ }
552
+
454
553
  // -----------------------------------------------------------------------
455
554
  // init + worldgen singleton
456
555
  // -----------------------------------------------------------------------
@@ -536,6 +635,17 @@ export const worldgen: {
536
635
  */
537
636
  entities(): EntitySpawners | { error: string };
538
637
 
638
+ /**
639
+ * Partial worldgen: generate only the selected worlds of a cluster.
640
+ * Geyser output is bit-identical to a full generate. Partial mode
641
+ * never places story-trait templates or assigns starmap locations.
642
+ * Stateless: does not populate the cluster cache used by
643
+ * `advance()` / `entities()`.
644
+ *
645
+ * Returns `{ error }` (not a throw) on parse/config failures.
646
+ */
647
+ partials(coordinate: string, opts: PartialsOptions): PartialsResult | { error: string };
648
+
539
649
  /**
540
650
  * Drop the cached generated cluster. Editor settings (if mutated)
541
651
  * are preserved.
package/oni_wasm.d.ts CHANGED
@@ -92,6 +92,25 @@ export function get_entity_spawners(): string;
92
92
  */
93
93
  export function noise_node_kinds(): string;
94
94
 
95
+ /**
96
+ * Partial worldgen: generate only the selected worlds of a cluster.
97
+ * Cluster-level pre-passes (mixing, trait selection) run over every
98
+ * placement; per-world phases run only for the selected slots.
99
+ * Stateless; does not touch `CLUSTER_CACHE`.
100
+ *
101
+ * Geyser output matches a full generate exactly, and each world
102
+ * carries the digest-format geyser hashes. Verified element-wise by
103
+ * `tests/partial_parity.rs` and against the digest corpus by
104
+ * `scripts/partials_geyser_verify.mjs`.
105
+ *
106
+ * Story-trait templates and starmap locations are never produced;
107
+ * both depend on cross-world state a partial run lacks. Stock story
108
+ * traits carry no geysers, so geyser output is unaffected. Cell
109
+ * grids are pre-settle, as with `generate`; there is no partial
110
+ * settle (use `generate` + `advance` for settled state).
111
+ */
112
+ export function partials_from_coordinate(coordinate: string, options_json: string): string;
113
+
95
114
  /**
96
115
  * Toggle template placement. WASM-side counterpart of the native
97
116
  * `SKIP_TEMPLATES` env var.
package/oni_wasm.js CHANGED
@@ -250,6 +250,44 @@ function noise_node_kinds() {
250
250
  }
251
251
  exports.noise_node_kinds = noise_node_kinds;
252
252
 
253
+ /**
254
+ * Partial worldgen: generate only the selected worlds of a cluster.
255
+ * Cluster-level pre-passes (mixing, trait selection) run over every
256
+ * placement; per-world phases run only for the selected slots.
257
+ * Stateless; does not touch `CLUSTER_CACHE`.
258
+ *
259
+ * Geyser output matches a full generate exactly, and each world
260
+ * carries the digest-format geyser hashes. Verified element-wise by
261
+ * `tests/partial_parity.rs` and against the digest corpus by
262
+ * `scripts/partials_geyser_verify.mjs`.
263
+ *
264
+ * Story-trait templates and starmap locations are never produced;
265
+ * both depend on cross-world state a partial run lacks. Stock story
266
+ * traits carry no geysers, so geyser output is unaffected. Cell
267
+ * grids are pre-settle, as with `generate`; there is no partial
268
+ * settle (use `generate` + `advance` for settled state).
269
+ * @param {string} coordinate
270
+ * @param {string} options_json
271
+ * @returns {string}
272
+ */
273
+ function partials_from_coordinate(coordinate, options_json) {
274
+ let deferred3_0;
275
+ let deferred3_1;
276
+ try {
277
+ const ptr0 = passStringToWasm0(coordinate, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
278
+ const len0 = WASM_VECTOR_LEN;
279
+ const ptr1 = passStringToWasm0(options_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
280
+ const len1 = WASM_VECTOR_LEN;
281
+ const ret = wasm.partials_from_coordinate(ptr0, len0, ptr1, len1);
282
+ deferred3_0 = ret[0];
283
+ deferred3_1 = ret[1];
284
+ return getStringFromWasm0(ret[0], ret[1]);
285
+ } finally {
286
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
287
+ }
288
+ }
289
+ exports.partials_from_coordinate = partials_from_coordinate;
290
+
253
291
  /**
254
292
  * Toggle template placement. WASM-side counterpart of the native
255
293
  * `SKIP_TEMPLATES` env var.
package/oni_wasm_bg.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@onimaxxing/worldgen-node",
3
3
  "description": "WASM entry point for ONI worldgen",
4
- "version": "0.21.1",
4
+ "version": "0.21.3",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -14,6 +14,7 @@
14
14
  "yaml.d.ts",
15
15
  "editor_settings.d.ts",
16
16
  "README.md",
17
+ "LICENSE",
17
18
  "oni_wasm.js",
18
19
  "oni_wasm.d.ts",
19
20
  "oni_wasm_bg.wasm"