@maka/maka-cli 5.223.0 → 5.225.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maka/maka-cli",
3
- "version": "5.223.0",
3
+ "version": "5.225.0",
4
4
  "type": "module",
5
5
  "summary": "A command line tool for scaffolding Meteor 3.x applications using either React.",
6
6
  "description": "A command line tool for scaffolding Meteor 3.x applications using React.",
@@ -1,5 +1,7 @@
1
1
  import { Direction } from '../types/shared/direction-enum.js';
2
2
  import { ARCHETYPES, getArchetype } from '../archetypes.js';
3
+ import { catalogGearDef } from '../utilities/catalog.js';
4
+ import { Category, Size, Rating } from '../types/shared/item-enum.js';
3
5
  /**
4
6
  * BUILDING THE BENCH A REVIEW ITEM SHIPS WITH.
5
7
  *
@@ -97,6 +99,43 @@ const ARMED_NPC_KIT = [
97
99
  { name: 'Ares Predator V', description: 'A heavy pistol, smartlinked and chattering to its owner over the wireless.', size: 'Small', category: 'RangedWeapon', shape: 'Pistol', color: 'Black', texture: 'Matte', rating: 'Standard', weight: 2 },
98
100
  { name: 'Meta Link', description: 'A cheap commlink. It is what puts everything else on the grid.', size: 'Tiny', category: 'Commlink', shape: 'Rectangle', color: 'Gray', texture: 'Plastic', rating: 'Common', weight: 0.1 },
99
101
  ];
102
+ /**
103
+ * THE SEED ROW FOR A REAL PIECE OF GEAR (items[].gear).
104
+ *
105
+ * catalogGearDef answers in enum VALUES ('cyberdeck'); a seed carries
106
+ * enum KEYS, because ItemFactory does `Category[json.category]`. So the
107
+ * values are mapped back to their keys here rather than anywhere that
108
+ * would have to know both shapes.
109
+ *
110
+ * A NAME THAT RESOLVES TO NOTHING THROWS. It would be easy to fall back
111
+ * to a Document and let the bench build -- and that is exactly the bug
112
+ * pFNBSzb95JHCHSJjE was: a key item whose name had drifted one word
113
+ * failed silently and left a door nobody could open. A fixture that
114
+ * quietly ships the wrong object is worse than one that refuses.
115
+ */
116
+ function catalogSeedFor(name) {
117
+ const def = catalogGearDef(name);
118
+ if (!def) {
119
+ throw new ReproFixtureError(`items[].gear is set for "${name}", but the catalog has no such row. `
120
+ + `Spell it the way the catalog does, or drop "gear" to make it an ordinary prop.`);
121
+ }
122
+ const keyOf = (e, v) => Object.keys(e).find(k => e[k] === v) ?? 'Document';
123
+ return {
124
+ category: keyOf(Category, def.category),
125
+ size: keyOf(Size, def.size),
126
+ rating: keyOf(Rating, def.rating),
127
+ shape: def.shape,
128
+ color: def.color,
129
+ texture: def.texture,
130
+ weight: def.weight,
131
+ // A DECK WITH NO CONFIG IS A DECK WITH A ZEROED ARRAY, which reads
132
+ // as a bricked one at every roll site. The book lets the owner order
133
+ // the four attributes (p.227); a bench has nobody to ask, so it gets
134
+ // the identity order and says so here rather than leaving a fixture
135
+ // author to discover it from a mechanics line.
136
+ ...(def.category === Category.Cyberdeck ? { deckOrder: [0, 1, 2, 3] } : {}),
137
+ };
138
+ }
100
139
  /** A fixture that cannot be built into an honest bench. Thrown, never
101
140
  * swallowed -- the caller turns it into a sentence for whoever wrote
102
141
  * the spec. */
@@ -465,13 +504,23 @@ export function buildReproScene(fixture) {
465
504
  name: it.name,
466
505
  description: it.description,
467
506
  details: it.details,
468
- size: 'Tiny',
469
- category: 'Document',
470
- shape: 'Rectangle',
471
- color: 'Gray',
472
- texture: 'Plain',
473
- rating: 'Common',
474
- weight: 0.1,
507
+ // REAL GEAR WHEN THE FIXTURE ASKS FOR IT (items[].gear). Everything
508
+ // here used to be a Document whatever it was called, which works for
509
+ // the props a fixture is mostly made of and breaks the moment the
510
+ // engine recognises something by CATEGORY rather than by name -- a
511
+ // "Fairlight Excalibur" that isCyberdeck() called a sheet of paper.
512
+ // The catalog is the engine's own answer for what a named piece of
513
+ // gear IS (chargen builds every runner's kit from these rows), so
514
+ // this asks it rather than inventing a second source.
515
+ ...(it.gear ? catalogSeedFor(it.name) : {
516
+ size: 'Tiny',
517
+ category: 'Document',
518
+ shape: 'Rectangle',
519
+ color: 'Gray',
520
+ texture: 'Plain',
521
+ rating: 'Common',
522
+ weight: 0.1,
523
+ }),
475
524
  // A FILE rides the host's room on the matrix plane and takes no
476
525
  // spot -- a spot is a meat position (see the ice rule above).
477
526
  ...(it.file
@@ -24,10 +24,18 @@
24
24
  * 2.4.0 adds IReproNpc.astral -- purely additive, older drafts still
25
25
  * valid.
26
26
  *
27
+ * 2.8.0 adds IReproItem.gear -- resolve the name against the CATALOG
28
+ * and build the real thing. Purely additive: an item without it is
29
+ * the same Document prop it always was, so every existing draft
30
+ * stays valid. It exists because a fixture could not express a
31
+ * CYBERDECK at all (isCyberdeck reads the category, which was
32
+ * hard-coded to Document), which made a whole class of bench
33
+ * unbuildable -- see factories/repro-gear.test.ts.
34
+ *
27
35
  * 2.5.0 adds IReproHost.purpose / .sculpt and IReproItem.file (engine
28
36
  * 1.50.0, hosts with a purpose) -- additive.
29
37
  */
30
- export const REPRO_SCHEMA_VERSION = '2.7.0';
38
+ export const REPRO_SCHEMA_VERSION = '2.8.0';
31
39
  /** THE LIVE REASON, from the field or the card's own words.
32
40
  *
33
41
  * `repro.live` is authoritative -- but the server's validator must
@@ -110,17 +110,25 @@ export function enterMatrix(scene, actor, mode) {
110
110
  actor.performAction('jacks in', `slumping where they stand, eyes flickering (${mode}-sim)`, { quiet: scene.isHumanControlled?.(actor) ?? false });
111
111
  scene.addWorldEvent(`${actor.name} jacked into the Matrix in ${actor.bodyRoom.name}.`);
112
112
  Logger.getInstance().write(`${actor.name} entered the Matrix (${mode}-sim, ${actor.activeDeck?.name ?? (actor.isTechnomancer() ? 'living persona' : 'no deck?!')}) from ${actor.bodyRoom.name}.`);
113
+ // WHAT YOU ARE ACTUALLY RIDING (9d9kJJW3WANoA2MvA). A commlink is a
114
+ // way onto the Matrix (p.222) and activeDeck is only ever a CYBERDECK,
115
+ // so for the ordinary runner who just jacked in on their Meta Link
116
+ // both lines below used to say "deck" about a thing that is not one.
117
+ // Naming the rig is the whole of the fix: nothing else here changes,
118
+ // and a runner with a real deck reads exactly what they read before.
119
+ const rig = actor.activeDeck ?? actor.getPanMaster();
120
+ const rigName = rig?.name ?? 'deck';
113
121
  const hotWarning = mode === 'hot'
114
122
  ? ` Hot-sim: everything is faster and hits harder -- including what hits YOU. Ice biofeedback bleeds into your real stun track.`
115
123
  : actor.isTechnomancer()
116
124
  ? ` There is no deck between you and the ice -- every hit out here is YOUR mind taking it.`
117
- : ` Cold-sim: the ice can only chew on your deck, not your brain.`;
125
+ : ` Cold-sim: the ice can only chew on your ${rigName}, not your brain.`;
118
126
  const deckNote = actor.activeDeck && actor.activeDeck.deckDamage > 0
119
127
  ? ` Your ${actor.activeDeck.name} is already scarred: ${actor.activeDeck.deckSummary()}.`
120
128
  : '';
121
129
  const entry = actor.isTechnomancer()
122
130
  ? `You close your eyes and the Matrix is simply THERE -- no deck, no interface, just the resonance singing. Your body slumps where you stood in ${actor.bodyRoom.name}, empty.`
123
- : `Your ${actor.activeDeck?.name ?? 'deck'} spins up and the room dissolves into geometry -- you're in. Your body slumps where you stood in ${actor.bodyRoom.name}, empty.`;
131
+ : `Your ${rigName} spins up and the room dissolves into geometry -- you're in. Your body slumps where you stood in ${actor.bodyRoom.name}, empty.`;
124
132
  return [
125
133
  `${entry}${hotWarning}${deckNote} You come up on ${actor.currentGrid?.name ?? 'the grid'}.${actor.currentGrid?.userPenalty ? ' Public grid: -2 on everything you do out here.' : ''}`,
126
134
  hint(`No streets out here: "map" lights the hosts overhead and names them, "hack <host>" slips a mark in quiet (p.240) and "force <host>" smashes one in (p.238), one mark lets "enter <host>" walk you inside from anywhere, "mark" shows who holds what, "jack out" to return.`),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maka/maka-cli",
3
- "version": "5.223.0",
3
+ "version": "5.225.0",
4
4
  "type": "module",
5
5
  "summary": "A command line tool for scaffolding Meteor 3.x applications using either React.",
6
6
  "description": "A command line tool for scaffolding Meteor 3.x applications using React.",