@maka/maka-cli 5.380.1 → 5.380.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maka/maka-cli",
3
- "version": "5.380.1",
3
+ "version": "5.380.3",
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.",
@@ -20,6 +20,14 @@ export class DropCommand extends Command {
20
20
  if (bill)
21
21
  return bill;
22
22
  const itemName = args.join(' ').toLowerCase(); // Assuming the item name may contain spaces
23
+ // HELD COUNTS AS CARRIED (user ruling 2026-10-04): the thing in your
24
+ // hand or on your back drops too -- back to the bag first, which is
25
+ // what the path below reads.
26
+ if (!this.actor.inventory.hasItem(itemName)) {
27
+ const worn = this.actor.findEquipped(itemName);
28
+ if (worn)
29
+ this.actor.bagEquipped(worn.name);
30
+ }
23
31
  // Check if the item exists in the player's inventory
24
32
  if (!this.actor.inventory.hasItem(itemName)) {
25
33
  this.logger.write(`Item "${itemName}" not found in ${this.actor.name}'s inventory during 'Drop' command.`);
@@ -76,6 +76,17 @@ export class GiveCommand extends Command {
76
76
  }
77
77
  // === Try to give an item ===
78
78
  let item = this.actor.inventory.getItem(itemOrAmount);
79
+ // HELD COUNTS AS CARRIED (user ruling 2026-10-04; qW2HZD5HQCX42FN29: a
80
+ // Johnson with the cargo case in his hand could not give it). Bagged at
81
+ // the handover below, not here, so a refused give leaves it held.
82
+ let fromSlot = false;
83
+ if (!item) {
84
+ const worn = this.actor.findEquipped(itemOrAmount);
85
+ if (worn) {
86
+ item = worn;
87
+ fromSlot = true;
88
+ }
89
+ }
79
90
  // DATA ON A DEVICE IS IN YOUR HANDS TOO (digital inventory, user ruling
80
91
  // 2026-10-04): a file in your commlink's library is beamed across the
81
92
  // table, no chip required. Pack first -- a chip by that name wins --
@@ -225,7 +236,8 @@ export class GiveCommand extends Command {
225
236
  receiveData(recipient, item);
226
237
  }
227
238
  else {
228
- didTransfer = this.actor.inventory.transferItemTo(item.name, recipient.inventory);
239
+ didTransfer = (!fromSlot || this.actor.bagEquipped(item.name))
240
+ && this.actor.inventory.transferItemTo(item.name, recipient.inventory);
229
241
  }
230
242
  if (!didTransfer) {
231
243
  this.logger.write(`Item "${item.name}" is not transferable.`);
@@ -60,7 +60,7 @@ export class LockCommand extends Command {
60
60
  return `${crossNote}The door leading to "${door.getOtherSideToName(room)}" is already locked.`;
61
61
  }
62
62
  const requiredKeyOrSolution = door.unlockItemOrSolution?.toLowerCase();
63
- if (requiredKeyOrSolution && this.actor.inventory.hasItem(requiredKeyOrSolution)) {
63
+ if (requiredKeyOrSolution && this.actor.carries(requiredKeyOrSolution) && this.actor.bagEquipped(requiredKeyOrSolution)) {
64
64
  const key = this.actor.inventory.getItem(requiredKeyOrSolution);
65
65
  if (key) {
66
66
  door.isLocked = true;
@@ -78,7 +78,7 @@ export class LockCommand extends Command {
78
78
  return `The door "${label}" is already locked.`;
79
79
  }
80
80
  const requiredKeyOrSolution = door.unlockItemOrSolution?.toLowerCase();
81
- if (requiredKeyOrSolution && this.actor.inventory.hasItem(requiredKeyOrSolution)) {
81
+ if (requiredKeyOrSolution && this.actor.carries(requiredKeyOrSolution) && this.actor.bagEquipped(requiredKeyOrSolution)) {
82
82
  door.isLocked = true;
83
83
  this.logger.write(`LockCommand: ${this.actor.name} locked the door: ${label}`);
84
84
  this.actor.performAction('lock', label);
@@ -153,8 +153,10 @@ export class MoveCommand extends Command {
153
153
  // was buyable and inert, the same shape as the hostility flag:
154
154
  // wired at one end only.
155
155
  //
156
- // Carried, not worn: a kit in the pack is a kit you can rig.
157
- const assisted = actor.inventory.getAllItems().some(i => /climbing gear|climbing kit|\brope\b|harness|carabiner|crampon|grapple gun/i.test(`${i.name} ${i.description ?? ''}`));
156
+ // Carried OR worn (user ruling 2026-10-04: an equipped item is a
157
+ // carried item): a kit in the pack is a kit you can rig, and a
158
+ // harness already on you more so.
159
+ const assisted = [...actor.inventory.getAllItems(), ...actor.equippedItems()].some(i => /climbing gear|climbing kit|\brope\b|harness|carabiner|crampon|grapple gun/i.test(`${i.name} ${i.description ?? ''}`));
158
160
  // SURFACE AND CONDITION (p.134), read off the room's own prose and
159
161
  // the level's name -- see climbSurfaceModifier. Zero unless the
160
162
  // fiction says otherwise, which is why adding this could not
@@ -44,7 +44,7 @@ export class SellCommand extends Command {
44
44
  const pending = this.game?.pendingSale;
45
45
  // Bare "sell": close the standing quote, or show what's fenceable.
46
46
  if (!wanted) {
47
- if (pending && pending.fence === fence.name && (pending.lot || actor.inventory.hasItem(pending.itemName))) {
47
+ if (pending && pending.fence === fence.name && (pending.lot || (actor.carries(pending.itemName) && actor.bagEquipped(pending.itemName)))) {
48
48
  return pending.lot ? this.closeLot(fence) : this.close(fence);
49
49
  }
50
50
  return this.listSellables(fence);
@@ -10,6 +10,13 @@ export class StoreCommand extends Command {
10
10
  }
11
11
  store(args) {
12
12
  const itemName = args.join(' ').toLowerCase(); // Handle multi-word item names
13
+ // HELD COUNTS AS CARRIED (user ruling 2026-10-04): what you hold or
14
+ // wear stores too -- back to the bag first, which the path below reads.
15
+ if (!this.actor.inventory.hasItem(itemName)) {
16
+ const worn = this.actor.findEquipped(itemName);
17
+ if (worn)
18
+ this.actor.bagEquipped(worn.name);
19
+ }
13
20
  // Check if the item exists in the player's inventory
14
21
  if (!this.actor.inventory.hasItem(itemName)) {
15
22
  this.logger.write(`Item "${itemName}" not found in ${this.actor.name}'s inventory during 'Store' command.`);
@@ -69,7 +69,7 @@ export class UnlockCommand extends Command {
69
69
  return reach.refusal;
70
70
  const crossNote = reach.line ? `${reach.line}\n` : '';
71
71
  if (holder) {
72
- if (holder.keyItem && this.actor.inventory.hasItem(holder.keyItem.name)) {
72
+ if (holder.keyItem && this.actor.carries(holder.keyItem.name) && this.actor.bagEquipped(holder.keyItem.name)) {
73
73
  const result = holder.offer('', this.actor.inventory);
74
74
  this.logger.write(`UnlockCommand: ${this.actor.name} turned ${holder.keyItem.name} in ${holder.name}: ${result.success}`);
75
75
  this.actor.performAction('unlocked', result.message);
@@ -86,7 +86,7 @@ export class UnlockCommand extends Command {
86
86
  return crossNote + `${holder.name} holds it. ${takes} Or force it: ${ways}.`;
87
87
  }
88
88
  const requiredKeyOrSolution = door.unlockItemOrSolution?.toLowerCase();
89
- if (requiredKeyOrSolution && this.actor.inventory.hasItem(requiredKeyOrSolution)) {
89
+ if (requiredKeyOrSolution && this.actor.carries(requiredKeyOrSolution) && this.actor.bagEquipped(requiredKeyOrSolution)) {
90
90
  const key = this.actor.inventory.getItem(requiredKeyOrSolution);
91
91
  if (key) {
92
92
  const unlockMessage = room.attemptUnlockExit(direction, key.name);
@@ -249,7 +249,7 @@ export class UseCommand extends Command {
249
249
  // NOTHING TYPED AFTER THE NAME. Say what this particular thing
250
250
  // wants, which depends on what it IS.
251
251
  if (!rest) {
252
- if (device.keyItem && this.actor.inventory.hasItem(device.keyItem.name)) {
252
+ if (device.keyItem && this.actor.carries(device.keyItem.name) && this.actor.bagEquipped(device.keyItem.name)) {
253
253
  // They are carrying what opens it -- that IS the offer.
254
254
  return crossNote + this.openWith(device, '', 'use');
255
255
  }
@@ -24,7 +24,7 @@ export class WorkCommand extends Command {
24
24
  }
25
25
  const gig = this.game.activeGig;
26
26
  if (gig) {
27
- return actor.inventory.hasItem(gig.itemName)
27
+ return actor.carries(gig.itemName)
28
28
  ? `You've got work: get the ${gig.itemName} to ${gig.to}. ${gig.pay} nuyen on delivery.`
29
29
  : `You took ${gig.from}'s gig but the ${gig.itemName} isn't on you anymore -- find it, or that bridge stays burned this cycle.`;
30
30
  }
@@ -3276,5 +3276,19 @@
3276
3276
  // ("IN PROGRESS") instead of "Nothing on offer" and the size menu.
3277
3277
  // - A standing draft ("jobs take") and a crew change no longer swap an
3278
3278
  // accepted job aside; a ride that never shows keeps the job.
3279
- export const ENGINE_VERSION = '1.192.1';
3279
+ // 1.192.2 (2026-10-04): A GUARD WHO STEPS OFF THE POST IS DRAWN WHERE HE
3280
+ // STANDS (dfFCcY3oDfsvd8gmi). seatingIn pinned every `guarding` NPC to
3281
+ // the post before reading exact cells, so a picket the combat brain
3282
+ // walked toward a runner was narrated stepping while the map, melee
3283
+ // reach and ranges all read the post. A picket with an exact cell is
3284
+ // now seated from it.
3285
+ // 1.192.3 (2026-10-04): AN EQUIPPED ITEM IS A CARRIED ITEM, for every
3286
+ // actor (user ruling; qW2HZD5HQCX42FN29). Scene build slotted Mr.
3287
+ // Vellum's delivery case, the meet asked his bag for it, and the cargo
3288
+ // never changed hands -- his prompt never named it the runner's, and his
3289
+ // own "give" could not move it either. Player.carries()/bagEquipped():
3290
+ // the meet (give and upload cargo), the job-item prompt line, give,
3291
+ // drop, store, sell, keys (lock/unlock/use), the gig check and climbing
3292
+ // gear now see what is held or worn.
3293
+ export const ENGINE_VERSION = '1.192.3';
3280
3294
  //# sourceMappingURL=engine-version.js.map
@@ -4517,7 +4517,10 @@ export default class Game {
4517
4517
  // exactly the job it is for.
4518
4518
  const wc = this.scene.getWinCondition();
4519
4519
  const johnson = this.scene.getActor(client.name);
4520
- if (wc?.type === 'give' && wc.item && johnson && johnson.inventory.hasItem(wc.item)) {
4520
+ // HELD COUNTS (qW2HZD5HQCX42FN29): scene build may have put the
4521
+ // cargo in the client's hand -- carries() asks the slots too, and
4522
+ // bagEquipped() brings it back to the bag the transfer reads.
4523
+ if (wc?.type === 'give' && wc.item && johnson && johnson.carries(wc.item) && johnson.bagEquipped(wc.item)) {
4521
4524
  const handed = johnson.inventory.transferItemTo(wc.item, this.player.inventory);
4522
4525
  if (handed) {
4523
4526
  this.scene.updateInventory(this.player.inventory);
@@ -4540,7 +4543,7 @@ export default class Game {
4540
4543
  // device (data-library receiveData; a chip only for a runner who
4541
4544
  // carries no device at all). The drop is a HOST, and the meet says
4542
4545
  // which, on its own line for the same terse() reason as above.
4543
- if (wc?.type === 'upload' && wc.item && johnson && johnson.inventory.hasItem(wc.item)) {
4546
+ if (wc?.type === 'upload' && wc.item && johnson && johnson.carries(wc.item) && johnson.bagEquipped(wc.item)) {
4544
4547
  const cargo = johnson.inventory.getItem(wc.item);
4545
4548
  johnson.inventory.removeItem(cargo.name);
4546
4549
  const { device } = receiveData(this.player, cargo);
@@ -2116,7 +2116,9 @@ ${worldEventsSummary}
2116
2116
  // delivery the thing in its pocket actually was, so "carry it to
2117
2117
  // the Stitch yourself" came out as a refusal instead of a handover.
2118
2118
  const wc = this._scene?.getWinCondition?.();
2119
- const carriesPrize = !!wc?.item && this.inventory.getAllItems().some(i => i.name === wc.item);
2119
+ // Held or worn counts as carried (qW2HZD5HQCX42FN29: Vellum's case was
2120
+ // in his hand, so this line never told him it was the runner's cargo).
2121
+ const carriesPrize = !!wc?.item && this.carries(wc.item);
2120
2122
  // THE EXTRACTION, FROM THE INSIDE (commands/bring.ts, p.336-337):
2121
2123
  // the person the job is about is told which of the book's two shapes
2122
2124
  // they are, and their security is told whose security it is.
@@ -670,6 +670,42 @@ export class Player extends AbstractPlayer {
670
670
  }
671
671
  return out;
672
672
  }
673
+ /**
674
+ * AN EQUIPPED ITEM IS A CARRIED ITEM (user ruling 2026-10-04). Equipping
675
+ * moves an item out of the bag into a slot, so `inventory.hasItem` alone
676
+ * says a hand holding the thing is empty. The reported session
677
+ * (qW2HZD5HQCX42FN29): scene build auto-equipped Mr. Vellum's Hardshell
678
+ * Heirloom Case, the meet asked his BAG for the cargo, found nothing,
679
+ * and never handed it over -- while the runner was data-spiking the
680
+ * very case "smoking in his hand". Exact name, any case.
681
+ */
682
+ carries(name) {
683
+ if (this._inventory.hasItem(name))
684
+ return true;
685
+ const wanted = name.toLowerCase();
686
+ return this.equippedItems().some(i => i.name.toLowerCase() === wanted);
687
+ }
688
+ /**
689
+ * Put a held or worn item (exact name) back in the bag, so the bag's
690
+ * transfer can move it to someone else. True when it is in the bag
691
+ * afterwards -- already there counts. A housed device never comes out.
692
+ */
693
+ bagEquipped(name) {
694
+ if (this._inventory.hasItem(name))
695
+ return true;
696
+ const wanted = name.toLowerCase();
697
+ for (const [groupName, group] of Object.entries(this._equipment)) {
698
+ if (!group)
699
+ continue;
700
+ for (const [slotName, item] of Object.entries(group)) {
701
+ if (item?.name.toLowerCase() !== wanted)
702
+ continue;
703
+ this.unequipBySlot(groupName, slotName);
704
+ return this._inventory.hasItem(item.name);
705
+ }
706
+ }
707
+ return false;
708
+ }
673
709
  /**
674
710
  * THE WORN OR HELD ITEM A PLAYER MEANS (user ask 2026-09-24: "I'd like
675
711
  * to be able to look my equipped gear"). Equipping moves an item out of
@@ -641,11 +641,22 @@ export function seatingIn(room) {
641
641
  // -- every press on that door flipped the dot between two cells. The
642
642
  // fallen hold no ground (standingOccupants); they are seated with
643
643
  // everyone else below.
644
+ //
645
+ // ...AND ONLY WHILE SHE IS STILL ON IT (dfFCcY3oDfsvd8gmi, player
646
+ // 2026-10-04: "I see Grit moved, but I don't see it happened on the
647
+ // map"). A picket is positioned by spot and holds no exact cell; one
648
+ // that HAS one stepped there -- the combat brain closing on a runner,
649
+ // a walk, a shove. Pinning her to the post anyway drew the post while
650
+ // her steps were narrated, and inMeleeReach measured from the post too,
651
+ // so she paced every phase and "couldn't get any closer". She is
652
+ // seated from her cell in the pass below, like anyone who stepped.
644
653
  for (const a of seated) {
645
654
  if (!a.guarding)
646
655
  continue;
647
656
  if (a.isIncapacitated())
648
657
  continue;
658
+ if (a.atCell)
659
+ continue;
649
660
  const spot = spotOf(a);
650
661
  const anchor = seatAnchorFor(room, spot);
651
662
  if (!anchor)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maka/maka-cli",
3
- "version": "5.380.1",
3
+ "version": "5.380.3",
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.",