@rpgm-tools/neo-angband-mod-sdk 0.20.0 → 0.22.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/LICENSE.md CHANGED
@@ -32,8 +32,8 @@ Gervais tiles (CC BY 3.0, attribution given in that CREDITS.md) are available
32
32
  to tile packs under their own terms. The Shockbolt tile set is a distinct
33
33
  case and is **not** bundled: its license grants fee-free distribution *with*
34
34
  Angband but withholds modification without the author's permission, and
35
- withholds use with "other games or projects" absent explicit permission
36
- so whether this port may carry it turns on a question only the author can
35
+ withholds use with "other games or projects" absent explicit permission, so
36
+ whether this port may carry it turns on a question only the author can
37
37
  settle. CREDITS.md states the grants and the prohibitions in full.
38
38
 
39
39
  ## Mods
package/README.md CHANGED
@@ -12,7 +12,7 @@ npm install @rpgm-tools/neo-angband-mod-sdk
12
12
 
13
13
  The base game loads its own content **through this pipeline, as pack zero**. That
14
14
  is the point: there is no privileged path a mod cannot take, because the game
15
- itself does not have one. This package is that pipeline, with no engine attached
15
+ itself does not have one. This package is that pipeline, with no engine attached,
16
16
  so a mod's build script or test can validate a manifest, resolve a load order or
17
17
  compose records without pulling in a game.
18
18
 
@@ -23,12 +23,12 @@ compose records without pulling in a game.
23
23
  | Manifests | `validateManifest`, `PackManifest`, `PackShape`, `packFacets`, `hasFacet`, `packRef`, `slugify` |
24
24
  | Load order | `resolveLoadOrder` (enforces), `satisfies` (the semver subset the manifests use) |
25
25
  | Auto-sort | `sortModOrder` (proposes, and cannot fail), `collectSortEdges`, `SortPin`, `SortTier`, `PACK_GROUPS` |
26
- | Sections | `resolveSectionState`, `expandSections`, `sectionFlag`, `PackSection`, `SECTION_BANDS` the named parts of a mod |
27
- | Compatibility | `PackCompat`, `COMPAT_CLAIMS` what an author may claim about another mod (never binding) |
26
+ | Sections | `resolveSectionState`, `expandSections`, `sectionFlag`, `PackSection`, `SECTION_BANDS`: the named parts of a mod |
27
+ | Compatibility | `PackCompat`, `COMPAT_CLAIMS`: what an author may claim about another mod (never binding) |
28
28
  | Composition | `composePacks`, `composeContentPacks`, `mergePatch`, `applyFieldPatch`, `composeFieldPatches` |
29
29
  | Conflicts | `computeConflictReport` (records), `contestedSlots` / `describeContested` (every other layer), `Fold`, `foldDiscards` |
30
30
  | Record identity | `recordKey`, `keySpecFor`, `KEYED_RECORD_FILES`, `RECORD_KEY_SPECS` |
31
- | Capabilities | `CapabilitySet`, `parseCapability` what a scripted plugin is allowed to reach |
31
+ | Capabilities | `CapabilitySet`, `parseCapability`: what a scripted plugin is allowed to reach |
32
32
 
33
33
  ```ts
34
34
  import { validateManifest, ManifestError } from "@rpgm-tools/neo-angband-mod-sdk";
@@ -43,10 +43,10 @@ try {
43
43
 
44
44
  ## The three pack shapes
45
45
 
46
- - **content** declarative JSON validated against the record schemas. Safe by
46
+ - **content**: declarative JSON validated against the record schemas. Safe by
47
47
  construction: it cannot execute anything.
48
- - **tiles** a tile pack, either a tilesheet re-skin or a loose Linoleum pack.
49
- - **plugin** a scripted mod. It default-exports a `ModPlugin` and receives the
48
+ - **tiles**: a tile pack, either a tilesheet re-skin or a loose Linoleum pack.
49
+ - **plugin**: a scripted mod. It default-exports a `ModPlugin` and receives the
50
50
  running engine as `ctx.core`, because a module loaded out of a mod folder cannot
51
51
  resolve a bare specifier and a bundled copy of the engine would give the plugin
52
52
  its own registries while the game ran on another set.
@@ -56,11 +56,11 @@ reads them.
56
56
 
57
57
  ## Related
58
58
 
59
- - [`@rpgm-tools/neo-angband-core`](https://www.npmjs.com/package/@rpgm-tools/neo-angband-core) the engine itself
60
- - [docs/MODS.md](https://github.com/neostryder/neo-angband/blob/master/docs/MODS.md) the full modding guide
61
- - First-party mods: [qol](https://github.com/neostryder/neo-angband-mod-qol) ·
62
- [bug-fixes](https://github.com/neostryder/neo-angband-mod-bug-fixes) ·
63
- [neo-linoleum](https://github.com/neostryder/neo-angband-mod-linoleum) ·
59
+ - [`@rpgm-tools/neo-angband-core`](https://www.npmjs.com/package/@rpgm-tools/neo-angband-core): the engine itself
60
+ - [docs/MODS.md](https://github.com/neostryder/neo-angband/blob/master/docs/MODS.md): the full modding guide
61
+ - First-party mods: [qol](https://github.com/neostryder/neo-angband-mod-qol),
62
+ [bug-fixes](https://github.com/neostryder/neo-angband-mod-bug-fixes),
63
+ [neo-linoleum](https://github.com/neostryder/neo-angband-mod-linoleum),
64
64
  [borg](https://github.com/neostryder/neo-angband-mod-borg)
65
65
 
66
66
  ## Versioning
@@ -70,6 +70,6 @@ reserved for the game's public release.
70
70
 
71
71
  ## Licence
72
72
 
73
- GNU GPL v2, or the Angband licence, at your option Angband's dual licence, kept
73
+ GNU GPL v2, or the Angband licence, at your option: Angband's dual licence, kept
74
74
  as the Angband project asks of its variants. npm carries one SPDX identifier so the
75
75
  manifest says `GPL-2.0-only`; both texts are in [LICENSE.md](LICENSE.md).
@@ -1 +1 @@
1
- {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}
package/dist/compose.js CHANGED
@@ -16,8 +16,97 @@
16
16
  * and every record carries provenance (owner plus every pack that
17
17
  * modified it) for savefiles and debugging.
18
18
  */
19
+ import { RECORD_BLUEPRINTS } from "./blueprints.js";
19
20
  import { applyFieldPatch } from "./patch.js";
20
21
  import { keyDescription, keySpecFor, legacyRecordKey, recordRefKeys, } from "./record-key.js";
22
+ /**
23
+ * A value's JSON shape, in the vocabulary `RECORD_BLUEPRINTS` measured core in.
24
+ *
25
+ * `null` IS ITS OWN SHAPE HERE, and that is the one deliberate difference from
26
+ * authoring.ts's `shapeOf`, which folds it into "object". The blueprint reader
27
+ * only has to name a shape; this decides whether a binder can READ the value,
28
+ * and `null.map(...)` throws exactly as loudly as `"a string".map(...)` does.
29
+ */
30
+ function jsonShape(value) {
31
+ if (value === null)
32
+ return "null";
33
+ if (Array.isArray(value))
34
+ return "array";
35
+ return typeof value;
36
+ }
37
+ const CONTAINERS = new Set(["array", "object"]);
38
+ /**
39
+ * Whether every shape core writes for a field is a container, none of them is,
40
+ * or the field is written both ways.
41
+ *
42
+ * "mixed" is not a failure to decide - it is core writing the field both ways,
43
+ * and a field core itself spells two ways cannot be proved unreadable from its
44
+ * shape alone.
45
+ */
46
+ function coreShapeClass(types) {
47
+ const containers = types.filter((t) => CONTAINERS.has(t)).length;
48
+ if (containers === types.length)
49
+ return "container";
50
+ if (containers === 0)
51
+ return "scalar";
52
+ return "mixed";
53
+ }
54
+ /**
55
+ * Why this field of this record cannot be given this value, or null if it can.
56
+ *
57
+ * THE LINE THIS DRAWS, and why it is drawn there. `RECORD_BLUEPRINTS` is a
58
+ * MEASUREMENT of core's shipped records, not a schema, and blueprints.ts's own
59
+ * header says an unlisted value is legal - a mod inventing a new tval is doing
60
+ * something the mod system exists to allow. So a value that merely disagrees
61
+ * with the measurement is reported and kept (validate.ts, rule `field/type`),
62
+ * and that is right.
63
+ *
64
+ * It is not right for CONTAINER-NESS. Every binder in the port reads a list
65
+ * field by iterating it: `rec.owner.map(...)` in the store binder is the case
66
+ * that surfaced this, and a string, a number, `null` and a missing field all
67
+ * throw a TypeError there. That throw happens inside `bindCore` inside
68
+ * `startGame`, which the host runs at module top level, so the player gets the
69
+ * crash screen and no game - the whole cost of one patched field of one shop.
70
+ * No amount of experimentation makes a string iterable, so this class is not
71
+ * experimentation, and it is refused rather than reported.
72
+ *
73
+ * DELIBERATELY NARROW, in two ways that are both load-bearing.
74
+ *
75
+ * A scalar swapped for another scalar (`weight` written "40" instead of 40)
76
+ * stays a finding: a binder can usually read it, some of them coerce it, and
77
+ * refusing it would take the measurement's word for something it cannot prove.
78
+ *
79
+ * And a field that is simply GONE is not refused either, even though reading a
80
+ * missing list throws the same TypeError a string does. Dropping a field is how
81
+ * a total conversion works - `replaces` swaps the whole record, and a monster
82
+ * rewritten as `{name, hp}` legitimately has no `blows` - so refusing an absent
83
+ * field would put back the fields the mod meant to remove and quietly undo a
84
+ * supported feature. An absent required field is already reported
85
+ * (`field/required` in authoring.ts), and the binders are where a record the
86
+ * mod OWNS should be refused; see docs/PLANNED.md.
87
+ */
88
+ function unreadableShape(file, key, value) {
89
+ if (value === undefined)
90
+ return null;
91
+ const shape = RECORD_BLUEPRINTS[file]?.fields[key];
92
+ /* No blueprint for the file, or a field core does not have: nothing to
93
+ * contradict. A mod's own namespaced field lands here, which is correct - it
94
+ * is the mod's field and the mod decides its shape. */
95
+ if (!shape)
96
+ return null;
97
+ const want = coreShapeClass(shape.types);
98
+ if (want === "mixed")
99
+ return null;
100
+ const got = jsonShape(value);
101
+ const isContainer = CONTAINERS.has(got);
102
+ if (want === "container" && !isContainer) {
103
+ return `\`${key}\` is ${got}, and core writes it as ${shape.types.join(" or ")} on every record that has it - nothing can read it`;
104
+ }
105
+ if (want === "scalar" && isContainer) {
106
+ return `\`${key}\` is ${got}, and core writes it as ${shape.types.join(" or ")} - nothing can read it`;
107
+ }
108
+ return null;
109
+ }
21
110
  /** Start the transient field provenance for a record a pack contributes. */
22
111
  export function fieldProvenanceFor(record, packId) {
23
112
  const provenance = { writers: new Map(), writes: new Map() };
@@ -281,6 +370,41 @@ export function composePacks(packs, options = {}) {
281
370
  }
282
371
  }
283
372
  });
373
+ /**
374
+ * The record as it should be kept, and the fields that really changed.
375
+ *
376
+ * Every write below goes through this. A field the patch made unreadable
377
+ * is PUT BACK to what the record had before - not dropped, and not left
378
+ * broken - because the alternative outcomes are both worse than the
379
+ * defect: leaving it takes the game down at boot, and dropping the record
380
+ * would renumber a positional table (the store list is read by index, so
381
+ * removing one shop moves another shop's stock).
382
+ *
383
+ * The refused key is also withheld from `noteFieldWrites`, which is the
384
+ * subtle half. Provenance's `was[field]` is what tells core's own line
385
+ * from a mod's later on (see the store binder's `fieldOwner`), so
386
+ * recording a write that was refused would hand the mod the blame for a
387
+ * field it did not change.
388
+ */
389
+ const vetted = (ref, before, after, changed) => {
390
+ const wrote = [];
391
+ let value = after;
392
+ for (const key of new Set(changed)) {
393
+ const why = unreadableShape(file, key, value[key]);
394
+ if (why === null) {
395
+ wrote.push(key);
396
+ continue;
397
+ }
398
+ if (value === after)
399
+ value = { ...after };
400
+ if (Object.hasOwn(before, key))
401
+ value[key] = before[key];
402
+ else
403
+ delete value[key];
404
+ refuse(`${file} "${ref}": ${why}, so that field was left as it was`, `${file}: unreadable shape for ${key} on ${ref}`);
405
+ }
406
+ return { value, wrote };
407
+ };
284
408
  for (const kind of ["patches", "replaces"]) {
285
409
  for (const [refStr, body] of Object.entries(contrib[kind] ?? {})) {
286
410
  const at = addressable(kind, refStr);
@@ -290,8 +414,11 @@ export function composePacks(packs, options = {}) {
290
414
  const changed = kind === "patches"
291
415
  ? Object.keys(body)
292
416
  : new Set([...Object.keys(existing.value), ...Object.keys(body)]);
293
- existing.value = kind === "patches" ? mergePatch(existing.value, body) : body;
294
- noteFieldWrites(fieldProvenanceOf(existing), changed, pid, existing.value);
417
+ const before = existing.value;
418
+ const next = kind === "patches" ? mergePatch(existing.value, body) : body;
419
+ const ok = vetted(at, before, next, changed);
420
+ existing.value = ok.value;
421
+ noteFieldWrites(fieldProvenanceOf(existing), ok.wrote, pid, existing.value);
295
422
  existing.modifiedBy.push(pid);
296
423
  }
297
424
  }
@@ -300,8 +427,10 @@ export function composePacks(packs, options = {}) {
300
427
  if (at === null)
301
428
  continue;
302
429
  const existing = table.get(at);
303
- existing.value = applyFieldPatch(existing.value, ops);
304
- noteFieldWrites(fieldProvenanceOf(existing), ops.map((op) => op.path.split(".")[0]), pid, existing.value);
430
+ const before = existing.value;
431
+ const ok = vetted(at, before, applyFieldPatch(existing.value, ops), ops.map((op) => op.path.split(".")[0]));
432
+ existing.value = ok.value;
433
+ noteFieldWrites(fieldProvenanceOf(existing), ok.wrote, pid, existing.value);
305
434
  existing.modifiedBy.push(pid);
306
435
  }
307
436
  for (const refStr of contrib.removes ?? []) {
@@ -1 +1 @@
1
- {"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}
package/dist/manifest.js CHANGED
@@ -411,7 +411,7 @@ const TILE_ENGINES = ["tilesheet", "linoleum"];
411
411
  * `path` is checked for being MOD-RELATIVE, and that check is the point rather than
412
412
  * tidiness. It used to be a site-root-relative URL base, which only a bundled mod
413
413
  * could ever get right; a manifest carrying the old form would resolve to
414
- * `mods/<id>/mods/<id>/…` and 404 into ASCII with nothing said. An absolute path, a
414
+ * `mods/<id>/mods/<id>/...` and 404 into ASCII with nothing said. An absolute path, a
415
415
  * scheme, or a `..` escape is refused for the same reason a pack's code files are
416
416
  * read by pack-relative path: the host decides where a mod's bytes live.
417
417
  */
package/dist/patch.d.ts CHANGED
@@ -55,6 +55,31 @@ export type FieldOp =
55
55
  op: "mul";
56
56
  path: string;
57
57
  value: number;
58
+ }
59
+ /**
60
+ * Append values to the array at path (missing = []), preserving what is
61
+ * already there. This is the op that lets a mod add ONE entry to a list -
62
+ * an item to a store's `normal` stock table, an owner to a store, a blow to
63
+ * a monster - without restating the list, so two mods can both add to the
64
+ * same list and neither loses. Duplicates are kept: a list is not a set, and
65
+ * a store's stock table uses repetition as weighting.
66
+ */
67
+ | {
68
+ op: "append";
69
+ path: string;
70
+ values: JsonValue[];
71
+ }
72
+ /**
73
+ * Remove every entry deep-equal to `value` from the array at path. The
74
+ * counterpart to `append`, so a mod can take an entry OUT of a list. Unlike
75
+ * `append` this is order-dependent, because it can erase another pack's
76
+ * appended entry - which is exactly the same-resource collision load order
77
+ * is meant to settle, so it is reported as a conflict.
78
+ */
79
+ | {
80
+ op: "removeValue";
81
+ path: string;
82
+ value: JsonValue;
58
83
  };
59
84
  /** An ordered list of field operations - one pack's patch of one record. */
60
85
  export type FieldPatch = FieldOp[];
@@ -1 +1 @@
1
- {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAG1D,qBAAa,UAAW,SAAQ,KAAK;CAAG;AAExC,2EAA2E;AAC3E,MAAM,MAAM,OAAO;AACjB,0CAA0C;AACxC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE;AAC/C,+EAA+E;GAC7E;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE;AAClD,wEAAwE;GACtE;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAC/C,+DAA+D;GAC7D;IAAE,EAAE,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAClD,+DAA+D;GAC7D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAC5C,wDAAwD;GACtD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC;AA2FnC,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,GAAG,UAAU,CAI/E;AAgED,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,KAAK,EAAE,UAAU,CAAC;IAClB,4EAA4E;IAC5E,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,aAAa,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,UAAU,CAAA;CAAE,CAAC,GACzD,aAAa,CAwBf;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAI1D"}
1
+ {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAG1D,qBAAa,UAAW,SAAQ,KAAK;CAAG;AAExC,2EAA2E;AAC3E,MAAM,MAAM,OAAO;AACjB,0CAA0C;AACxC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE;AAC/C,+EAA+E;GAC7E;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE;AAClD,wEAAwE;GACtE;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAC/C,+DAA+D;GAC7D;IAAE,EAAE,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAClD,+DAA+D;GAC7D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAC5C,wDAAwD;GACtD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAC5C;;;;;;;GAOG;GACD;IAAE,EAAE,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,EAAE,CAAA;CAAE;AACrD;;;;;;GAMG;GACD;IAAE,EAAE,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,CAAC;AAE1D,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC;AAiGnC,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,GAAG,UAAU,CAI/E;AAsID,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,KAAK,EAAE,UAAU,CAAC;IAClB,4EAA4E;IAC5E,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,aAAa,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,UAAU,CAAA;CAAE,CAAC,GACzD,aAAa,CAwBf;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAI1D"}
package/dist/patch.js CHANGED
@@ -18,9 +18,15 @@
18
18
  import { mergePatch } from "./compose.js";
19
19
  export class PatchError extends Error {
20
20
  }
21
- /** The flag ops compose as set operations; the rest are order-dependent. */
21
+ /**
22
+ * Which ops compose without anybody losing a contribution. The flag ops are
23
+ * set operations; `append` is pure addition - two packs appending to one list
24
+ * both keep their entries, so a shared list is NOT a collision the way a
25
+ * shared scalar is. Everything else is order-dependent and a second writer
26
+ * means load order decides.
27
+ */
22
28
  function isCommutative(op) {
23
- return op === "addFlag" || op === "removeFlag";
29
+ return op === "addFlag" || op === "removeFlag" || op === "append";
24
30
  }
25
31
  /* ------------------------------------------------------------------ *
26
32
  * Dot-path access.
@@ -109,9 +115,11 @@ function applyOp(record, op) {
109
115
  return;
110
116
  case "merge": {
111
117
  const cur = getPath(record, op.path);
112
- const base = typeof cur === "object" && cur !== null && !Array.isArray(cur)
113
- ? cur
114
- : {};
118
+ if (Array.isArray(cur)) {
119
+ throw new PatchError(`patch: cannot merge into field ${op.path}, which is a list - ` +
120
+ `use "append" to add entries, or "set" to replace the whole list`);
121
+ }
122
+ const base = typeof cur === "object" && cur !== null ? cur : {};
115
123
  setPath(record, op.path, mergePatch(base, op.value));
116
124
  return;
117
125
  }
@@ -128,19 +136,77 @@ function applyOp(record, op) {
128
136
  return;
129
137
  }
130
138
  case "add": {
131
- const cur = getPath(record, op.path);
132
- const n = typeof cur === "number" ? cur : 0;
139
+ const n = asNumber(getPath(record, op.path), op.path, "add");
133
140
  setPath(record, op.path, n + op.value);
134
141
  return;
135
142
  }
136
143
  case "mul": {
137
- const cur = getPath(record, op.path);
138
- const n = typeof cur === "number" ? cur : 0;
144
+ const n = asNumber(getPath(record, op.path), op.path, "mul");
139
145
  setPath(record, op.path, n * op.value);
140
146
  return;
141
147
  }
148
+ case "append": {
149
+ const list = asList(getPath(record, op.path), op.path, "append");
150
+ list.push(...op.values);
151
+ setPath(record, op.path, list);
152
+ return;
153
+ }
154
+ case "removeValue": {
155
+ const list = asList(getPath(record, op.path), op.path, "removeValue");
156
+ const target = JSON.stringify(op.value);
157
+ setPath(record, op.path, list.filter((v) => JSON.stringify(v) !== target));
158
+ return;
159
+ }
160
+ default:
161
+ /*
162
+ * A TYPO IS NOT A NO-OP. The switch above is exhaustive over FieldOp, so
163
+ * TypeScript never reaches here - but a mod's ops arrive as JSON, and
164
+ * nothing between the file and this function checks the op NAME. Without
165
+ * this arm `{"op": "apend"}` fell out of the switch, changed nothing, and
166
+ * left `composeContentPacks` reporting no problems at all: the author's
167
+ * patch simply did not happen and the game said everything was fine.
168
+ * There are eight op names now and two of them are new, so the odds of
169
+ * that misspelling went up rather than down.
170
+ */
171
+ throw new PatchError(`patch: unknown op ${JSON.stringify(op.op)} at ` +
172
+ `${JSON.stringify(op.path ?? "")} - expected one of ` +
173
+ `set, merge, addFlag, removeFlag, add, mul, append, removeValue`);
142
174
  }
143
175
  }
176
+ /**
177
+ * The numeric value at a path, treating ABSENT as 0 but refusing a value that
178
+ * is present and not a number. Coercing those to 0 silently destroyed data: an
179
+ * `add` aimed at a list path replaced the whole list with a number, and an
180
+ * earlier documentation example did exactly that while the composer reported no
181
+ * problems at all. A wrong path is now an error rather than a quiet deletion.
182
+ */
183
+ function asNumber(value, path, op) {
184
+ if (value === undefined)
185
+ return 0;
186
+ if (typeof value !== "number") {
187
+ throw new PatchError(`patch: cannot ${op} field ${path}, which is ${describe(value)}, not a number`);
188
+ }
189
+ return value;
190
+ }
191
+ /** The array at a path (absent = empty), copied so the base record is untouched. */
192
+ function asList(value, path, op) {
193
+ if (value === undefined)
194
+ return [];
195
+ if (!Array.isArray(value)) {
196
+ throw new PatchError(`patch: cannot ${op} field ${path}, which is ${describe(value)}, not a list`);
197
+ }
198
+ return [...value];
199
+ }
200
+ /** A value's shape, for an error message that says what was actually there. */
201
+ function describe(value) {
202
+ if (Array.isArray(value))
203
+ return "a list";
204
+ if (value === null)
205
+ return "null";
206
+ if (typeof value === "object")
207
+ return "an object";
208
+ return `${typeof value} (${JSON.stringify(value)})`;
209
+ }
144
210
  /** A flag field must be a string array (or absent, treated as empty). */
145
211
  function asFlagList(value, path) {
146
212
  if (value === undefined)
package/dist/patch.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"patch.js","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"patch.js","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,OAAO,UAAW,SAAQ,KAAK;CAAG;AAqCxC;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,EAAiB;IACtC,OAAO,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,YAAY,IAAI,EAAE,KAAK,QAAQ,CAAC;AACpE,CAAC;AAED;;;;;;;;;;;;wEAYwE;AAExE,+EAA+E;AAC/E,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAChE,CAAC;AAED,4EAA4E;AAC5E,SAAS,OAAO,CAAC,GAA0B,EAAE,IAAY;IACvD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAQ,GAAkB,CAAC,IAAI,CAAC,CAAC;IAC9E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,OAAO,CAAC,MAAkB,EAAE,IAAY;IAC/C,IAAI,GAAG,GAA0B,MAAM,CAAC;IACxC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;IAC1C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yDAAyD;AACzD,SAAS,QAAQ,CACf,SAAmC,EACnC,IAAY,EACZ,KAAgB;IAEhB,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,UAAU,CAClB,WAAW,IAAI,kEAAkE,CAClF,CAAC;QACJ,CAAC;QACD,SAAS,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC;QACtB,OAAO;IACT,CAAC;IACD,SAAS,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,SAAS,OAAO,CAAC,MAAkB,EAAE,IAAY,EAAE,KAAgB;IACjE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,GAAG,GAA6B,MAAM,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAW,CAAC;QAChC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAgB,EAAE,IAAI,CAAC,CAAC;QAC7C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAC9C,MAAM,KAAK,GACT,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAW,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAC3B,GAAG,GAAG,KAAiC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,IAAgC,CAAC;QACzC,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAW,EAAE,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED;;wEAEwE;AAExE,wEAAwE;AACxE,MAAM,UAAU,eAAe,CAAC,MAAkB,EAAE,GAAe;IACjE,MAAM,GAAG,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACxC,KAAK,MAAM,EAAE,IAAI,GAAG;QAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACvC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,OAAO,CAAC,MAAkB,EAAE,EAAW;IAC9C,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;QACd,KAAK,KAAK;YACR,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;YACnC,OAAO;QACT,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvB,MAAM,IAAI,UAAU,CAClB,kCAAkC,EAAE,CAAC,IAAI,sBAAsB;oBAC7D,iEAAiE,CACpE,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,GACR,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAE,GAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;YACrD,OAAO;QACT,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YAC3D,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YAChD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YAC3D,OAAO,CACL,MAAM,EACN,EAAE,CAAC,IAAI,EACP,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAClC,CAAC;YACF,OAAO;QACT,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC7D,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;YACvC,OAAO;QACT,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC7D,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;YACvC,OAAO;QACT,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACjE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;YACxB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;YACtE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YACxC,OAAO,CACL,MAAM,EACN,EAAE,CAAC,IAAI,EACP,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CACjD,CAAC;YACF,OAAO;QACT,CAAC;QACD;YACE;;;;;;;;;eASG;YACH,MAAM,IAAI,UAAU,CAClB,qBAAqB,IAAI,CAAC,SAAS,CAAE,EAAsB,CAAC,EAAE,CAAC,MAAM;gBACnE,GAAG,IAAI,CAAC,SAAS,CAAE,EAAyB,CAAC,IAAI,IAAI,EAAE,CAAC,qBAAqB;gBAC7E,gEAAgE,CACnE,CAAC;IACN,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,KAA4B,EAAE,IAAY,EAAE,EAAU;IACtE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,UAAU,CAClB,iBAAiB,EAAE,UAAU,IAAI,cAAc,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAC/E,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,oFAAoF;AACpF,SAAS,MAAM,CAAC,KAA4B,EAAE,IAAY,EAAE,EAAU;IACpE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAClB,iBAAiB,EAAE,UAAU,IAAI,cAAc,QAAQ,CAAC,KAAK,CAAC,cAAc,CAC7E,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC;AAED,+EAA+E;AAC/E,SAAS,QAAQ,CAAC,KAAgB;IAChC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC1C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,WAAW,CAAC;IAClD,OAAO,GAAG,OAAO,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC;AACtD,CAAC;AAED,yEAAyE;AACzE,SAAS,UAAU,CAAC,KAA4B,EAAE,IAAY;IAC5D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,UAAU,CAAC,gBAAgB,IAAI,gCAAgC,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,CAAC,GAAI,KAAkB,CAAC,CAAC;AAClC,CAAC;AAED,oEAAoE;AACpE,SAAS,mBAAmB,CAAC,MAAkB;IAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAe,CAAC;AAC1D,CAAC;AAsBD;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAgB,EAChB,OAA0D;IAE1D,IAAI,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACtC,iFAAiF;IACjF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkD,CAAC;IAE1E,KAAK,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,OAAO,EAAE,CAAC;QACrC,KAAK,GAAG,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACrE,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;gBACpD,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,CAAC;gBAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAoB,EAAE,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAC9B,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,aAAa,CAAC,GAAe;IAC3C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,EAAE,IAAI,GAAG;QAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,GAAG,CAAC;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpgm-tools/neo-angband-mod-sdk",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "Pack schemas, validation, and tooling for Neo Angband mods (content packs, tile packs, scripted plugins)",
5
5
  "license": "GPL-2.0-only",
6
6
  "author": "neostryder (RPGM Tools)",
package/src/compose.ts CHANGED
@@ -17,6 +17,7 @@
17
17
  * modified it) for savefiles and debugging.
18
18
  */
19
19
 
20
+ import { RECORD_BLUEPRINTS } from "./blueprints.js";
20
21
  import type { PackManifest, PackRef } from "./manifest.js";
21
22
  import { applyFieldPatch } from "./patch.js";
22
23
  import type { FieldPatch } from "./patch.js";
@@ -36,6 +37,91 @@ export type JsonValue =
36
37
  | { [key: string]: JsonValue };
37
38
  export type JsonRecord = { [key: string]: JsonValue };
38
39
 
40
+ /**
41
+ * A value's JSON shape, in the vocabulary `RECORD_BLUEPRINTS` measured core in.
42
+ *
43
+ * `null` IS ITS OWN SHAPE HERE, and that is the one deliberate difference from
44
+ * authoring.ts's `shapeOf`, which folds it into "object". The blueprint reader
45
+ * only has to name a shape; this decides whether a binder can READ the value,
46
+ * and `null.map(...)` throws exactly as loudly as `"a string".map(...)` does.
47
+ */
48
+ function jsonShape(value: JsonValue): string {
49
+ if (value === null) return "null";
50
+ if (Array.isArray(value)) return "array";
51
+ return typeof value;
52
+ }
53
+
54
+ const CONTAINERS = new Set(["array", "object"]);
55
+
56
+ /**
57
+ * Whether every shape core writes for a field is a container, none of them is,
58
+ * or the field is written both ways.
59
+ *
60
+ * "mixed" is not a failure to decide - it is core writing the field both ways,
61
+ * and a field core itself spells two ways cannot be proved unreadable from its
62
+ * shape alone.
63
+ */
64
+ function coreShapeClass(types: readonly string[]): "container" | "scalar" | "mixed" {
65
+ const containers = types.filter((t) => CONTAINERS.has(t)).length;
66
+ if (containers === types.length) return "container";
67
+ if (containers === 0) return "scalar";
68
+ return "mixed";
69
+ }
70
+
71
+ /**
72
+ * Why this field of this record cannot be given this value, or null if it can.
73
+ *
74
+ * THE LINE THIS DRAWS, and why it is drawn there. `RECORD_BLUEPRINTS` is a
75
+ * MEASUREMENT of core's shipped records, not a schema, and blueprints.ts's own
76
+ * header says an unlisted value is legal - a mod inventing a new tval is doing
77
+ * something the mod system exists to allow. So a value that merely disagrees
78
+ * with the measurement is reported and kept (validate.ts, rule `field/type`),
79
+ * and that is right.
80
+ *
81
+ * It is not right for CONTAINER-NESS. Every binder in the port reads a list
82
+ * field by iterating it: `rec.owner.map(...)` in the store binder is the case
83
+ * that surfaced this, and a string, a number, `null` and a missing field all
84
+ * throw a TypeError there. That throw happens inside `bindCore` inside
85
+ * `startGame`, which the host runs at module top level, so the player gets the
86
+ * crash screen and no game - the whole cost of one patched field of one shop.
87
+ * No amount of experimentation makes a string iterable, so this class is not
88
+ * experimentation, and it is refused rather than reported.
89
+ *
90
+ * DELIBERATELY NARROW, in two ways that are both load-bearing.
91
+ *
92
+ * A scalar swapped for another scalar (`weight` written "40" instead of 40)
93
+ * stays a finding: a binder can usually read it, some of them coerce it, and
94
+ * refusing it would take the measurement's word for something it cannot prove.
95
+ *
96
+ * And a field that is simply GONE is not refused either, even though reading a
97
+ * missing list throws the same TypeError a string does. Dropping a field is how
98
+ * a total conversion works - `replaces` swaps the whole record, and a monster
99
+ * rewritten as `{name, hp}` legitimately has no `blows` - so refusing an absent
100
+ * field would put back the fields the mod meant to remove and quietly undo a
101
+ * supported feature. An absent required field is already reported
102
+ * (`field/required` in authoring.ts), and the binders are where a record the
103
+ * mod OWNS should be refused; see docs/PLANNED.md.
104
+ */
105
+ function unreadableShape(file: string, key: string, value: JsonValue | undefined): string | null {
106
+ if (value === undefined) return null;
107
+ const shape = RECORD_BLUEPRINTS[file]?.fields[key];
108
+ /* No blueprint for the file, or a field core does not have: nothing to
109
+ * contradict. A mod's own namespaced field lands here, which is correct - it
110
+ * is the mod's field and the mod decides its shape. */
111
+ if (!shape) return null;
112
+ const want = coreShapeClass(shape.types);
113
+ if (want === "mixed") return null;
114
+ const got = jsonShape(value);
115
+ const isContainer = CONTAINERS.has(got);
116
+ if (want === "container" && !isContainer) {
117
+ return `\`${key}\` is ${got}, and core writes it as ${shape.types.join(" or ")} on every record that has it - nothing can read it`;
118
+ }
119
+ if (want === "scalar" && isContainer) {
120
+ return `\`${key}\` is ${got}, and core writes it as ${shape.types.join(" or ")} - nothing can read it`;
121
+ }
122
+ return null;
123
+ }
124
+
39
125
  /**
40
126
  * The packs that wrote each top-level key of one composed record.
41
127
  *
@@ -442,6 +528,47 @@ export function composePacks(
442
528
  }
443
529
  });
444
530
 
531
+ /**
532
+ * The record as it should be kept, and the fields that really changed.
533
+ *
534
+ * Every write below goes through this. A field the patch made unreadable
535
+ * is PUT BACK to what the record had before - not dropped, and not left
536
+ * broken - because the alternative outcomes are both worse than the
537
+ * defect: leaving it takes the game down at boot, and dropping the record
538
+ * would renumber a positional table (the store list is read by index, so
539
+ * removing one shop moves another shop's stock).
540
+ *
541
+ * The refused key is also withheld from `noteFieldWrites`, which is the
542
+ * subtle half. Provenance's `was[field]` is what tells core's own line
543
+ * from a mod's later on (see the store binder's `fieldOwner`), so
544
+ * recording a write that was refused would hand the mod the blame for a
545
+ * field it did not change.
546
+ */
547
+ const vetted = (
548
+ ref: PackRef,
549
+ before: JsonRecord,
550
+ after: JsonRecord,
551
+ changed: Iterable<string>,
552
+ ): { value: JsonRecord; wrote: string[] } => {
553
+ const wrote: string[] = [];
554
+ let value = after;
555
+ for (const key of new Set(changed)) {
556
+ const why = unreadableShape(file, key, value[key]);
557
+ if (why === null) {
558
+ wrote.push(key);
559
+ continue;
560
+ }
561
+ if (value === after) value = { ...after };
562
+ if (Object.hasOwn(before, key)) value[key] = before[key] as JsonValue;
563
+ else delete value[key];
564
+ refuse(
565
+ `${file} "${ref}": ${why}, so that field was left as it was`,
566
+ `${file}: unreadable shape for ${key} on ${ref}`,
567
+ );
568
+ }
569
+ return { value, wrote };
570
+ };
571
+
445
572
  for (const kind of ["patches", "replaces"] as const) {
446
573
  for (const [refStr, body] of Object.entries(contrib[kind] ?? {})) {
447
574
  const at = addressable(kind, refStr as PackRef);
@@ -451,8 +578,11 @@ export function composePacks(
451
578
  kind === "patches"
452
579
  ? Object.keys(body)
453
580
  : new Set([...Object.keys(existing.value), ...Object.keys(body)]);
454
- existing.value = kind === "patches" ? mergePatch(existing.value, body) : body;
455
- noteFieldWrites(fieldProvenanceOf(existing), changed, pid, existing.value);
581
+ const before = existing.value;
582
+ const next = kind === "patches" ? mergePatch(existing.value, body) : body;
583
+ const ok = vetted(at, before, next, changed);
584
+ existing.value = ok.value;
585
+ noteFieldWrites(fieldProvenanceOf(existing), ok.wrote, pid, existing.value);
456
586
  existing.modifiedBy.push(pid);
457
587
  }
458
588
  }
@@ -461,13 +591,15 @@ export function composePacks(
461
591
  const at = addressable("fieldPatches", refStr as PackRef);
462
592
  if (at === null) continue;
463
593
  const existing = table.get(at) as ComposedRecord;
464
- existing.value = applyFieldPatch(existing.value, ops);
465
- noteFieldWrites(
466
- fieldProvenanceOf(existing),
594
+ const before = existing.value;
595
+ const ok = vetted(
596
+ at,
597
+ before,
598
+ applyFieldPatch(existing.value, ops),
467
599
  ops.map((op) => op.path.split(".")[0] as string),
468
- pid,
469
- existing.value,
470
600
  );
601
+ existing.value = ok.value;
602
+ noteFieldWrites(fieldProvenanceOf(existing), ok.wrote, pid, existing.value);
471
603
  existing.modifiedBy.push(pid);
472
604
  }
473
605
 
package/src/manifest.ts CHANGED
@@ -928,7 +928,7 @@ const TILE_ENGINES: readonly string[] = ["tilesheet", "linoleum"];
928
928
  * `path` is checked for being MOD-RELATIVE, and that check is the point rather than
929
929
  * tidiness. It used to be a site-root-relative URL base, which only a bundled mod
930
930
  * could ever get right; a manifest carrying the old form would resolve to
931
- * `mods/<id>/mods/<id>/…` and 404 into ASCII with nothing said. An absolute path, a
931
+ * `mods/<id>/mods/<id>/...` and 404 into ASCII with nothing said. An absolute path, a
932
932
  * scheme, or a `..` escape is refused for the same reason a pack's code files are
933
933
  * read by pack-relative path: the host decides where a mod's bytes live.
934
934
  */
package/src/patch.ts CHANGED
@@ -34,14 +34,37 @@ export type FieldOp =
34
34
  /** Add a number to the numeric value at path (missing = 0). */
35
35
  | { op: "add"; path: string; value: number }
36
36
  /** Multiply the numeric value at path (missing = 0). */
37
- | { op: "mul"; path: string; value: number };
37
+ | { op: "mul"; path: string; value: number }
38
+ /**
39
+ * Append values to the array at path (missing = []), preserving what is
40
+ * already there. This is the op that lets a mod add ONE entry to a list -
41
+ * an item to a store's `normal` stock table, an owner to a store, a blow to
42
+ * a monster - without restating the list, so two mods can both add to the
43
+ * same list and neither loses. Duplicates are kept: a list is not a set, and
44
+ * a store's stock table uses repetition as weighting.
45
+ */
46
+ | { op: "append"; path: string; values: JsonValue[] }
47
+ /**
48
+ * Remove every entry deep-equal to `value` from the array at path. The
49
+ * counterpart to `append`, so a mod can take an entry OUT of a list. Unlike
50
+ * `append` this is order-dependent, because it can erase another pack's
51
+ * appended entry - which is exactly the same-resource collision load order
52
+ * is meant to settle, so it is reported as a conflict.
53
+ */
54
+ | { op: "removeValue"; path: string; value: JsonValue };
38
55
 
39
56
  /** An ordered list of field operations - one pack's patch of one record. */
40
57
  export type FieldPatch = FieldOp[];
41
58
 
42
- /** The flag ops compose as set operations; the rest are order-dependent. */
59
+ /**
60
+ * Which ops compose without anybody losing a contribution. The flag ops are
61
+ * set operations; `append` is pure addition - two packs appending to one list
62
+ * both keep their entries, so a shared list is NOT a collision the way a
63
+ * shared scalar is. Everything else is order-dependent and a second writer
64
+ * means load order decides.
65
+ */
43
66
  function isCommutative(op: FieldOp["op"]): boolean {
44
- return op === "addFlag" || op === "removeFlag";
67
+ return op === "addFlag" || op === "removeFlag" || op === "append";
45
68
  }
46
69
 
47
70
  /* ------------------------------------------------------------------ *
@@ -142,10 +165,14 @@ function applyOp(record: JsonRecord, op: FieldOp): void {
142
165
  return;
143
166
  case "merge": {
144
167
  const cur = getPath(record, op.path);
168
+ if (Array.isArray(cur)) {
169
+ throw new PatchError(
170
+ `patch: cannot merge into field ${op.path}, which is a list - ` +
171
+ `use "append" to add entries, or "set" to replace the whole list`,
172
+ );
173
+ }
145
174
  const base =
146
- typeof cur === "object" && cur !== null && !Array.isArray(cur)
147
- ? (cur as JsonRecord)
148
- : {};
175
+ typeof cur === "object" && cur !== null ? (cur as JsonRecord) : {};
149
176
  setPath(record, op.path, mergePatch(base, op.value));
150
177
  return;
151
178
  }
@@ -165,18 +192,84 @@ function applyOp(record: JsonRecord, op: FieldOp): void {
165
192
  return;
166
193
  }
167
194
  case "add": {
168
- const cur = getPath(record, op.path);
169
- const n = typeof cur === "number" ? cur : 0;
195
+ const n = asNumber(getPath(record, op.path), op.path, "add");
170
196
  setPath(record, op.path, n + op.value);
171
197
  return;
172
198
  }
173
199
  case "mul": {
174
- const cur = getPath(record, op.path);
175
- const n = typeof cur === "number" ? cur : 0;
200
+ const n = asNumber(getPath(record, op.path), op.path, "mul");
176
201
  setPath(record, op.path, n * op.value);
177
202
  return;
178
203
  }
204
+ case "append": {
205
+ const list = asList(getPath(record, op.path), op.path, "append");
206
+ list.push(...op.values);
207
+ setPath(record, op.path, list);
208
+ return;
209
+ }
210
+ case "removeValue": {
211
+ const list = asList(getPath(record, op.path), op.path, "removeValue");
212
+ const target = JSON.stringify(op.value);
213
+ setPath(
214
+ record,
215
+ op.path,
216
+ list.filter((v) => JSON.stringify(v) !== target),
217
+ );
218
+ return;
219
+ }
220
+ default:
221
+ /*
222
+ * A TYPO IS NOT A NO-OP. The switch above is exhaustive over FieldOp, so
223
+ * TypeScript never reaches here - but a mod's ops arrive as JSON, and
224
+ * nothing between the file and this function checks the op NAME. Without
225
+ * this arm `{"op": "apend"}` fell out of the switch, changed nothing, and
226
+ * left `composeContentPacks` reporting no problems at all: the author's
227
+ * patch simply did not happen and the game said everything was fine.
228
+ * There are eight op names now and two of them are new, so the odds of
229
+ * that misspelling went up rather than down.
230
+ */
231
+ throw new PatchError(
232
+ `patch: unknown op ${JSON.stringify((op as { op: unknown }).op)} at ` +
233
+ `${JSON.stringify((op as { path?: unknown }).path ?? "")} - expected one of ` +
234
+ `set, merge, addFlag, removeFlag, add, mul, append, removeValue`,
235
+ );
236
+ }
237
+ }
238
+
239
+ /**
240
+ * The numeric value at a path, treating ABSENT as 0 but refusing a value that
241
+ * is present and not a number. Coercing those to 0 silently destroyed data: an
242
+ * `add` aimed at a list path replaced the whole list with a number, and an
243
+ * earlier documentation example did exactly that while the composer reported no
244
+ * problems at all. A wrong path is now an error rather than a quiet deletion.
245
+ */
246
+ function asNumber(value: JsonValue | undefined, path: string, op: string): number {
247
+ if (value === undefined) return 0;
248
+ if (typeof value !== "number") {
249
+ throw new PatchError(
250
+ `patch: cannot ${op} field ${path}, which is ${describe(value)}, not a number`,
251
+ );
179
252
  }
253
+ return value;
254
+ }
255
+
256
+ /** The array at a path (absent = empty), copied so the base record is untouched. */
257
+ function asList(value: JsonValue | undefined, path: string, op: string): JsonValue[] {
258
+ if (value === undefined) return [];
259
+ if (!Array.isArray(value)) {
260
+ throw new PatchError(
261
+ `patch: cannot ${op} field ${path}, which is ${describe(value)}, not a list`,
262
+ );
263
+ }
264
+ return [...value];
265
+ }
266
+
267
+ /** A value's shape, for an error message that says what was actually there. */
268
+ function describe(value: JsonValue): string {
269
+ if (Array.isArray(value)) return "a list";
270
+ if (value === null) return "null";
271
+ if (typeof value === "object") return "an object";
272
+ return `${typeof value} (${JSON.stringify(value)})`;
180
273
  }
181
274
 
182
275
  /** A flag field must be a string array (or absent, treated as empty). */