@wildshard/shard-format 0.4.5 → 0.4.7

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/src/format/tar.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  // same files always give the same bytes, because a tarball's hash is its
8
8
  // identity (J60): sorted paths, no directories, no times, no owners.
9
9
 
10
+ import { archiveError } from './issue-codes.ts'
10
11
  import {
11
12
  BLOCK,
12
13
  CHECKSUM,
@@ -53,7 +54,7 @@ function text(block: Readonly<Uint8Array>, field: TarField): string {
53
54
  function octal(block: Readonly<Uint8Array>, field: TarField): number {
54
55
  const digits = text(block, field).trim()
55
56
  if (!/^[0-7]+$/u.test(digits)) {
56
- throw new Error('tar: bad octal field')
57
+ throw archiveError('tar: bad octal field')
57
58
  }
58
59
  return Number.parseInt(digits, OCTAL)
59
60
  }
@@ -78,7 +79,7 @@ function entryPath(block: Readonly<Uint8Array>): string {
78
79
  const trimmed =
79
80
  block[TYPE_AT] === DIRECTORY_CODE ? relative.replace(/\/$/u, '') : relative
80
81
  if (full.startsWith('/') || trimmed === '' || badPath(trimmed)) {
81
- throw new Error(`tar: bad path ${JSON.stringify(full)}`)
82
+ throw archiveError(`tar: bad path ${JSON.stringify(full)}`)
82
83
  }
83
84
  return trimmed
84
85
  }
@@ -91,11 +92,11 @@ interface Header {
91
92
 
92
93
  function header(block: Readonly<Uint8Array>): Header {
93
94
  if (text(block, MAGIC) !== 'ustar' || !checksumOk(block)) {
94
- throw new Error('tar: not a ustar header')
95
+ throw archiveError('tar: not a ustar header')
95
96
  }
96
97
  const type = String.fromCodePoint(block[TYPE_AT] ?? NUL)
97
98
  if (!REGULAR_TYPES.has(type) && type !== DIRECTORY_TYPE) {
98
- throw new Error(`tar: unsupported entry type ${JSON.stringify(type)}`)
99
+ throw archiveError(`tar: unsupported entry type ${JSON.stringify(type)}`)
99
100
  }
100
101
  return { path: entryPath(block), type, size: octal(block, SIZE) }
101
102
  }
@@ -104,7 +105,7 @@ function header(block: Readonly<Uint8Array>): Header {
104
105
  function assertPadding(source: TarSource, offset: number, path: string): void {
105
106
  const length = padded(offset) - offset
106
107
  if (length > START && !isZero(source.read(offset, length))) {
107
- throw new Error(`tar: non-zero padding after ${path}`)
108
+ throw archiveError(`tar: non-zero padding after ${path}`)
108
109
  }
109
110
  }
110
111
 
@@ -134,10 +135,10 @@ function readEntry(offset: number, reading: Readonly<Reading>): number {
134
135
  const entry = header(source.read(offset, BLOCK))
135
136
  const start = offset + BLOCK
136
137
  if (entry.type === DIRECTORY_TYPE && entry.size !== START) {
137
- throw new Error(`tar: directory with a size ${entry.path}`)
138
+ throw archiveError(`tar: directory with a size ${entry.path}`)
138
139
  }
139
140
  if (start + entry.size > source.length) {
140
- throw new Error(`tar: truncated entry ${entry.path}`)
141
+ throw archiveError(`tar: truncated entry ${entry.path}`)
141
142
  }
142
143
  recordEntry(entry, start, reading)
143
144
  return start + padded(entry.size)
@@ -145,11 +146,11 @@ function readEntry(offset: number, reading: Readonly<Reading>): number {
145
146
 
146
147
  function assertEnd(source: TarSource, offset: number): void {
147
148
  if (source.length - offset < END_BLOCKS * BLOCK) {
148
- throw new Error('tar: bad end-of-archive blocks')
149
+ throw archiveError('tar: bad end-of-archive blocks')
149
150
  }
150
151
  for (let at = offset; at < source.length; at += END_CHUNK) {
151
152
  if (!isZero(source.read(at, Math.min(END_CHUNK, source.length - at)))) {
152
- throw new Error('tar: bad end-of-archive blocks')
153
+ throw archiveError('tar: bad end-of-archive blocks')
153
154
  }
154
155
  }
155
156
  }
@@ -157,7 +158,7 @@ function assertEnd(source: TarSource, offset: number): void {
157
158
  function firstBlock(source: TarSource, offset: number): Readonly<Uint8Array> {
158
159
  const block = source.read(offset, BLOCK)
159
160
  if (block.length < BLOCK) {
160
- throw new Error('tar: truncated (no end-of-archive blocks)')
161
+ throw archiveError('tar: truncated (no end-of-archive blocks)')
161
162
  }
162
163
  return block
163
164
  }
@@ -176,7 +177,7 @@ function indexTar(source: TarSource): ReadonlyMap<string, TarEntry> {
176
177
  return reading.files
177
178
  }
178
179
  if (entries === MAX_ENTRIES) {
179
- throw new Error(`tar: too many entries, over ${MAX_ENTRIES}`)
180
+ throw archiveError(`tar: too many entries, over ${MAX_ENTRIES}`)
180
181
  }
181
182
  offset = readEntry(offset, reading)
182
183
  }
@@ -0,0 +1,497 @@
1
+ {
2
+ "$doc": "Engine-only facts for docs/RUNTIME-CONTRACT.md, hand-kept (SA19). sections: engine scripts/host-ruler/roots.mjs SECTION_HOSTS, each host as <side> <binding> (page = src/client, server = src/server, both = src/shared, shard-format = this package). kinds: engine src/client/game/shardfile/clientPlan.ts CLIENT_FEATURES, page = the bindings the kind loads, reads = its sections list. Copy again when engine changes either table; runtime-contract.test.ts fails when a section or kind is missing or extra.",
3
+ "engine": "8f613824",
4
+ "sections": {
5
+ "actors/creatures": {
6
+ "hosts": ["server installDeclaredBrains"]
7
+ },
8
+ "actors/crowds": {
9
+ "hosts": ["both prepareDeclaredCrowds"]
10
+ },
11
+ "actors/moves": {
12
+ "hosts": ["server ActorMoveRunner", "shard-format parseActorMoves"]
13
+ },
14
+ "actors/npcs": {
15
+ "hosts": ["server installDeclaredQuestHost"]
16
+ },
17
+ "actors/return-scripts": {
18
+ "hosts": ["both ReturnProgram", "shard-format parseDecisionScripts"]
19
+ },
20
+ "actors/spawn-scripts": {
21
+ "hosts": ["server SpawnScript", "shard-format parseSpawnScript"]
22
+ },
23
+ "actors/spawns": {
24
+ "hosts": ["server installDeclaredBrains"]
25
+ },
26
+ "actors/species": {
27
+ "hosts": ["server speciesResolver", "page clientSpeciesLooks"]
28
+ },
29
+ "actors/species-programs": {
30
+ "hosts": [],
31
+ "note": "Metadata lent to existing page/native species and hunt owners."
32
+ },
33
+ "actors/strikes": {
34
+ "hosts": [],
35
+ "note": "Consumed by the runtime's explicitly imported creature host."
36
+ },
37
+ "audio/audio": {
38
+ "hosts": ["page installDeclaredAudio"]
39
+ },
40
+ "client/plan": {
41
+ "hosts": ["page installClientPhase"]
42
+ },
43
+ "collections/displays": {
44
+ "hosts": ["page CollectionCatalogue"]
45
+ },
46
+ "combat/encounters": {
47
+ "hosts": ["server createShardfileSim"]
48
+ },
49
+ "combat/items": {
50
+ "hosts": ["both installDeclaredItems"]
51
+ },
52
+ "combat/strikes": {
53
+ "hosts": ["server createShardfileSim"]
54
+ },
55
+ "economy/ledger": {
56
+ "hosts": ["both Ledger", "both installLedgerEmitter"]
57
+ },
58
+ "economy/loot": {
59
+ "hosts": ["both declaredLootPresentation"]
60
+ },
61
+ "explore/catalogue": {
62
+ "hosts": ["page explorerRoster"]
63
+ },
64
+ "held/arms": {
65
+ "hosts": ["page HeldClaims", "page HeldView"]
66
+ },
67
+ "held/equipment": {
68
+ "hosts": ["page HeldEquipment"]
69
+ },
70
+ "held/finishes": {
71
+ "hosts": ["page HeldFinishes"]
72
+ },
73
+ "held/gear": {
74
+ "hosts": ["page heldGear"]
75
+ },
76
+ "held/loadout": {
77
+ "hosts": ["page installHeldLoadout"]
78
+ },
79
+ "look/colour-functions": {
80
+ "hosts": ["page materialColourGraph"]
81
+ },
82
+ "look/hull-book": {
83
+ "hosts": ["page productHullBook"]
84
+ },
85
+ "look/keyed-sky": {
86
+ "hosts": ["page keyedSkyBackdrop"]
87
+ },
88
+ "look/look": {
89
+ "hosts": ["page shardfileLook"]
90
+ },
91
+ "look/map": {
92
+ "hosts": ["page reserveMapImage"]
93
+ },
94
+ "look/materials": {
95
+ "hosts": ["page clientMaterials"]
96
+ },
97
+ "look/painted": {
98
+ "hosts": ["page productPaintedLook"]
99
+ },
100
+ "look/rigged-hulls": {
101
+ "hosts": ["page productRiggedHulls"]
102
+ },
103
+ "look/toon": {
104
+ "hosts": ["page toonLook"]
105
+ },
106
+ "models/island-library": {
107
+ "hosts": ["page IslandLibrary"]
108
+ },
109
+ "player/stealth": {
110
+ "hosts": ["page StealthController", "shard-format StealthRowsSchema"]
111
+ },
112
+ "quests/directors": {
113
+ "hosts": ["both DirectorStageLane"]
114
+ },
115
+ "quests/host": {
116
+ "hosts": ["server installDeclaredQuestHost"]
117
+ },
118
+ "quests/quests": {
119
+ "hosts": ["both DeclaredQuests"]
120
+ },
121
+ "sim/bodies": {
122
+ "hosts": ["server DeclaredBodyOps", "shard-format DeclaredBodyOpsSchema"]
123
+ },
124
+ "sim/client-channels": {
125
+ "hosts": ["page ClientScriptViews"]
126
+ },
127
+ "sim/client-scripts": {
128
+ "hosts": ["page createShardfileClientScripts"]
129
+ },
130
+ "sim/hooks": {
131
+ "hosts": ["server createShardfileScriptLane"]
132
+ },
133
+ "sim/plumbing": {
134
+ "hosts": ["page installDeclaredPlumbing"]
135
+ },
136
+ "sim/runtime-plan": {
137
+ "hosts": ["server prepareProductRuntimePlan"]
138
+ },
139
+ "sim/scripts": {
140
+ "hosts": ["server DecisionHost", "shard-format parseDecisionScripts"]
141
+ },
142
+ "sim/sim": {
143
+ "hosts": ["server createShardfileScriptLane"]
144
+ },
145
+ "state/migrations": {
146
+ "hosts": ["both logicalStateFromLane"]
147
+ },
148
+ "state/modes": {
149
+ "hosts": ["both playerModes"]
150
+ },
151
+ "state/state": {
152
+ "hosts": ["server numericScriptState"]
153
+ },
154
+ "ui/card": {
155
+ "hosts": [],
156
+ "note": "Discovery metadata; no per-shard executable implementation."
157
+ },
158
+ "ui/compendium": {
159
+ "hosts": ["both declaredProductCompendium"]
160
+ },
161
+ "ui/completion": {
162
+ "hosts": ["page installCompletion"]
163
+ },
164
+ "ui/level": {
165
+ "hosts": [],
166
+ "note": "Metadata read by another host."
167
+ },
168
+ "ui/strings": {
169
+ "hosts": [],
170
+ "note": "Read by an explicitly imported consumer, not executed."
171
+ },
172
+ "ui/ui": {
173
+ "hosts": ["page mountDeclaredUi", "page installDeclaredTargets"]
174
+ },
175
+ "view/modules": {
176
+ "hosts": [
177
+ "shard-format ViewModulesSchema",
178
+ "shard-format admitScriptContract"
179
+ ]
180
+ },
181
+ "world/collision": {
182
+ "hosts": ["both installShardfileColliders"]
183
+ },
184
+ "world/days": {
185
+ "hosts": ["both declaredDay"]
186
+ },
187
+ "world/edge": {
188
+ "hosts": ["both createPortalTraversal"]
189
+ },
190
+ "world/movers": {
191
+ "hosts": [
192
+ "server createComposedMoverHost",
193
+ "page installClientMoverOwners"
194
+ ]
195
+ },
196
+ "world/navigation": {
197
+ "hosts": ["page installProductNavigation"]
198
+ },
199
+ "world/physics": {
200
+ "hosts": [],
201
+ "note": "Handed to the runtime's explicitly imported native host."
202
+ },
203
+ "world/props": {
204
+ "hosts": ["both propColliderDescriptors"]
205
+ },
206
+ "world/scenes": {
207
+ "hosts": ["page installWorldScenes"]
208
+ },
209
+ "world/spawn": {
210
+ "hosts": [],
211
+ "note": "Level admission metadata."
212
+ },
213
+ "world/targets": {
214
+ "hosts": ["both WorldTargetHost"]
215
+ },
216
+ "world/terrain": {
217
+ "hosts": ["both clientGround"]
218
+ },
219
+ "world/tiles": {
220
+ "hosts": ["page clientTileViews"]
221
+ },
222
+ "world/traversal": {
223
+ "hosts": ["both createPortalTraversal"]
224
+ },
225
+ "world/trees": {
226
+ "hosts": ["page productTreeSet", "page placeForestPageModels"]
227
+ },
228
+ "world/water": {
229
+ "hosts": ["page installClientWater", "page shardfileWater"]
230
+ },
231
+ "world/weather": {
232
+ "hosts": ["both declaredWeather"]
233
+ }
234
+ },
235
+ "kinds": {
236
+ "arena-room.entry": {
237
+ "page": ["installArenaRoomEntry"],
238
+ "reads": []
239
+ },
240
+ "audio.cues": {
241
+ "page": ["installClientCues"],
242
+ "reads": ["world/scenes"]
243
+ },
244
+ "audio.scene": {
245
+ "page": ["enterClientAudioScene", "installClientAudioScene"],
246
+ "reads": []
247
+ },
248
+ "bag.finds": {
249
+ "page": ["installClientFinds"],
250
+ "reads": []
251
+ },
252
+ "boss.held": {
253
+ "page": ["installClientBossFight"],
254
+ "reads": ["sim/runtime-plan"]
255
+ },
256
+ "boss.spawned": {
257
+ "page": ["installClientBossFight"],
258
+ "reads": ["sim/runtime-plan"]
259
+ },
260
+ "boss.telegraph": {
261
+ "page": ["installClientBossTelegraph"],
262
+ "reads": ["sim/runtime-plan", "actors/strikes"]
263
+ },
264
+ "combat.targets": {
265
+ "page": ["installCombatTargets"],
266
+ "reads": []
267
+ },
268
+ "content.catalogue": {
269
+ "page": ["installClientCatalogue"],
270
+ "reads": ["held/finishes"]
271
+ },
272
+ "debug.expose": {
273
+ "page": ["SceneDressing"],
274
+ "reads": []
275
+ },
276
+ "elite.construct": {
277
+ "page": ["installClientEliteConstruction"],
278
+ "reads": []
279
+ },
280
+ "elite.entry": {
281
+ "page": ["installClientEliteEntry"],
282
+ "reads": []
283
+ },
284
+ "fx.trail": {
285
+ "page": ["installClientTrails"],
286
+ "reads": ["world/scenes"]
287
+ },
288
+ "held.claims.enter": {
289
+ "page": ["entryOwner"],
290
+ "reads": ["held/arms"]
291
+ },
292
+ "held.claims.install": {
293
+ "page": ["installHeldClaimsEntry"],
294
+ "reads": []
295
+ },
296
+ "held.claims.prepare": {
297
+ "page": ["prepareHeldClaimsEntry"],
298
+ "reads": ["held/arms"]
299
+ },
300
+ "held.cosmetics": {
301
+ "page": ["installClientCosmeticFinishes"],
302
+ "reads": ["held/finishes"]
303
+ },
304
+ "held.melee": {
305
+ "page": ["enterClientHeldMelee", "installClientHeldMelee"],
306
+ "reads": ["look/painted"]
307
+ },
308
+ "held.ranged-feel": {
309
+ "page": ["installHeldRangedFeel"],
310
+ "reads": []
311
+ },
312
+ "held.ranged-page": {
313
+ "page": ["installEntryRangedPage", "prepareRangedPage"],
314
+ "reads": ["held/finishes"]
315
+ },
316
+ "light.emitters": {
317
+ "page": ["installLightEmitters"],
318
+ "reads": ["world/scenes"]
319
+ },
320
+ "look.painterly": {
321
+ "page": ["setPainterlyLook"],
322
+ "reads": []
323
+ },
324
+ "motion.channels": {
325
+ "page": ["installSceneMotion"],
326
+ "reads": ["world/scenes"]
327
+ },
328
+ "page.life": {
329
+ "page": ["installClientPageLife"],
330
+ "reads": []
331
+ },
332
+ "player.enter": {
333
+ "page": ["enterClientPlayer", "installClientPlayerEnter"],
334
+ "reads": []
335
+ },
336
+ "population.homes": {
337
+ "page": ["installClientPopulation"],
338
+ "reads": ["sim/runtime-plan", "sim/scripts"]
339
+ },
340
+ "population.hull-book": {
341
+ "page": ["prepareDeclaredHullBookKit"],
342
+ "reads": ["actors/species-programs", "explore/catalogue"]
343
+ },
344
+ "population.product-creatures": {
345
+ "page": ["installProductCreatures"],
346
+ "reads": ["actors/species-programs"]
347
+ },
348
+ "population.wildlife": {
349
+ "page": ["clientWildlife", "installClientWildlife"],
350
+ "reads": []
351
+ },
352
+ "portal.ride": {
353
+ "page": ["installDeclaredPortalRide"],
354
+ "reads": []
355
+ },
356
+ "practice.course": {
357
+ "page": ["installPracticeCourse"],
358
+ "reads": []
359
+ },
360
+ "quest.chapter-view": {
361
+ "page": ["installEntryChapterView"],
362
+ "reads": []
363
+ },
364
+ "quest.composition": {
365
+ "page": ["installEntryQuestComposition"],
366
+ "reads": []
367
+ },
368
+ "quest.continuation": {
369
+ "page": ["installQuestContinuationFile"],
370
+ "reads": []
371
+ },
372
+ "quest.page": {
373
+ "page": ["finishClientQuestPage", "installClientQuestPage"],
374
+ "reads": ["world/scenes", "world/targets", "look/painted"]
375
+ },
376
+ "quest.reference": {
377
+ "page": ["installEntryQuestReference"],
378
+ "reads": []
379
+ },
380
+ "quest.spawns": {
381
+ "page": ["installDeclaredQuestSpawns", "publishEntryOwner"],
382
+ "reads": []
383
+ },
384
+ "quest.views": {
385
+ "page": ["installEntryQuestViews"],
386
+ "reads": ["world/scenes"]
387
+ },
388
+ "quest.world": {
389
+ "page": ["prepareQuestWorldEntry"],
390
+ "reads": []
391
+ },
392
+ "riding.session": {
393
+ "page": ["installClientRiding"],
394
+ "reads": []
395
+ },
396
+ "species.program": {
397
+ "page": ["installClientSpeciesProgram", "prepareClientSpeciesCatalogue"],
398
+ "reads": ["actors/species-programs", "sim/scripts", "sim/runtime-plan"]
399
+ },
400
+ "state.adventure": {
401
+ "page": ["installClientAdventurePersistence"],
402
+ "reads": []
403
+ },
404
+ "stealth.entry": {
405
+ "page": ["installClientStealthEntry", "prepareClientStealthEntry"],
406
+ "reads": ["player/stealth"]
407
+ },
408
+ "strings.register": {
409
+ "page": ["levelRegistrations.strings"],
410
+ "reads": ["ui/strings"]
411
+ },
412
+ "taming.entry": {
413
+ "page": ["installTamingEntry"],
414
+ "reads": []
415
+ },
416
+ "timed.encounters": {
417
+ "page": ["installClientTimedEncounters"],
418
+ "reads": []
419
+ },
420
+ "view.program": {
421
+ "page": ["installViewProgram"],
422
+ "reads": ["view/modules"]
423
+ },
424
+ "weather.fields": {
425
+ "page": ["installWeatherFields"],
426
+ "reads": []
427
+ },
428
+ "weather.forest": {
429
+ "page": ["installClientForestWeather"],
430
+ "reads": []
431
+ },
432
+ "world.ambient-life": {
433
+ "page": ["installClientAmbientLife"],
434
+ "reads": []
435
+ },
436
+ "world.assembly": {
437
+ "page": ["installClientWorldAssembly"],
438
+ "reads": ["world/scenes"]
439
+ },
440
+ "world.baked": {
441
+ "page": ["installClientBakedTiles"],
442
+ "reads": []
443
+ },
444
+ "world.bind-sets": {
445
+ "page": ["bindEnteredClientPlaceSets"],
446
+ "reads": []
447
+ },
448
+ "world.dressing": {
449
+ "page": ["SceneDressing"],
450
+ "reads": ["world/scenes"]
451
+ },
452
+ "world.forest-page": {
453
+ "page": ["enterClientForestPage", "installClientForestPage"],
454
+ "reads": []
455
+ },
456
+ "world.meadow": {
457
+ "page": ["installClientMeadow"],
458
+ "reads": []
459
+ },
460
+ "world.movers": {
461
+ "page": ["installClientMoverOwners"],
462
+ "reads": ["world/movers"]
463
+ },
464
+ "world.paths": {
465
+ "page": ["installClientPathRamps"],
466
+ "reads": []
467
+ },
468
+ "world.runtime-hooks": {
469
+ "page": ["installClientRuntimeHooks"],
470
+ "reads": []
471
+ },
472
+ "world.scenes": {
473
+ "page": [
474
+ "StreamingCamera",
475
+ "cameraCone",
476
+ "followResidentTiles",
477
+ "installWorldScenes",
478
+ "noteTileBytes",
479
+ "productTileRing",
480
+ "residentTiles"
481
+ ],
482
+ "reads": ["world/scenes"]
483
+ },
484
+ "world.sets": {
485
+ "page": ["installClientPlaceSets"],
486
+ "reads": []
487
+ },
488
+ "world.updates": {
489
+ "page": ["installWorldUpdates"],
490
+ "reads": ["look/toon"]
491
+ },
492
+ "world.water": {
493
+ "page": ["installClientWaterSurfaces"],
494
+ "reads": []
495
+ }
496
+ }
497
+ }