@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 +2 -2
- package/README.md +13 -13
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +133 -4
- package/dist/compose.js.map +1 -1
- package/dist/manifest.js +1 -1
- package/dist/patch.d.ts +25 -0
- package/dist/patch.d.ts.map +1 -1
- package/dist/patch.js +75 -9
- package/dist/patch.js.map +1 -1
- package/package.json +1 -1
- package/src/compose.ts +139 -7
- package/src/manifest.ts +1 -1
- package/src/patch.ts +103 -10
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
|
-
|
|
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
|
|
27
|
-
| Compatibility | `PackCompat`, `COMPAT_CLAIMS
|
|
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
|
|
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
|
|
46
|
+
- **content**: declarative JSON validated against the record schemas. Safe by
|
|
47
47
|
construction: it cannot execute anything.
|
|
48
|
-
- **tiles
|
|
49
|
-
- **plugin
|
|
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)
|
|
60
|
-
- [docs/MODS.md](https://github.com/neostryder/neo-angband/blob/master/docs/MODS.md)
|
|
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
|
|
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).
|
package/dist/compose.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;
|
|
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
|
-
|
|
294
|
-
|
|
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
|
-
|
|
304
|
-
|
|
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 ?? []) {
|
package/dist/compose.js.map
CHANGED
|
@@ -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
|
|
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[];
|
package/dist/patch.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
-
/**
|
|
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
|
-
|
|
113
|
-
|
|
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
|
|
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
|
|
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":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,OAAO,UAAW,SAAQ,KAAK;CAAG;
|
|
1
|
+
{"version":3,"file":"patch.js","sourceRoot":"","sources":["../src/patch.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpgm-tools/neo-angband-mod-sdk",
|
|
3
|
-
"version": "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
|
-
|
|
455
|
-
|
|
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
|
-
|
|
465
|
-
|
|
466
|
-
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
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
|
|
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). */
|