@maka/maka-cli 5.112.0 → 5.114.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.
Files changed (42) hide show
  1. package/bundle/typescript/package.json +1 -1
  2. package/bundle/typescript/src/commands/game/sideQuest/commands/deck.js +3 -0
  3. package/bundle/typescript/src/commands/game/sideQuest/commands/deck.js.map +1 -1
  4. package/bundle/typescript/src/commands/game/sideQuest/commands/message.d.ts +44 -0
  5. package/bundle/typescript/src/commands/game/sideQuest/commands/message.js +125 -0
  6. package/bundle/typescript/src/commands/game/sideQuest/commands/message.js.map +1 -0
  7. package/bundle/typescript/src/commands/game/sideQuest/commands/move.js +13 -1
  8. package/bundle/typescript/src/commands/game/sideQuest/commands/move.js.map +1 -1
  9. package/bundle/typescript/src/commands/game/sideQuest/commands/say.js +33 -0
  10. package/bundle/typescript/src/commands/game/sideQuest/commands/say.js.map +1 -1
  11. package/bundle/typescript/src/commands/game/sideQuest/factories/chargen-factory.js +9 -1
  12. package/bundle/typescript/src/commands/game/sideQuest/factories/chargen-factory.js.map +1 -1
  13. package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +15 -0
  14. package/bundle/typescript/src/commands/game/sideQuest/game.js +65 -4
  15. package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
  16. package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +8 -0
  17. package/bundle/typescript/src/commands/game/sideQuest/models/player.js +9 -0
  18. package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
  19. package/bundle/typescript/src/commands/game/sideQuest/models/room.js +15 -1
  20. package/bundle/typescript/src/commands/game/sideQuest/models/room.js.map +1 -1
  21. package/bundle/typescript/src/commands/game/sideQuest/qualities.d.ts +7 -0
  22. package/bundle/typescript/src/commands/game/sideQuest/qualities.js +96 -0
  23. package/bundle/typescript/src/commands/game/sideQuest/qualities.js.map +1 -1
  24. package/bundle/typescript/src/commands/game/sideQuest/types/save-file.d.ts +14 -1
  25. package/bundle/typescript/src/commands/game/sideQuest/utilities/brand-mark.d.ts +26 -0
  26. package/bundle/typescript/src/commands/game/sideQuest/utilities/brand-mark.js +59 -0
  27. package/bundle/typescript/src/commands/game/sideQuest/utilities/brand-mark.js.map +1 -0
  28. package/bundle/typescript/src/commands/game/sideQuest/utilities/condition-report.js +5 -0
  29. package/bundle/typescript/src/commands/game/sideQuest/utilities/condition-report.js.map +1 -1
  30. package/bundle/typescript/src/commands/game/sideQuest/utilities/line-editor.d.ts +2 -0
  31. package/bundle/typescript/src/commands/game/sideQuest/utilities/line-editor.js +12 -0
  32. package/bundle/typescript/src/commands/game/sideQuest/utilities/line-editor.js.map +1 -1
  33. package/bundle/typescript/src/commands/game/sideQuest/utilities/logo-mark.d.ts +39 -0
  34. package/bundle/typescript/src/commands/game/sideQuest/utilities/logo-mark.js +64 -0
  35. package/bundle/typescript/src/commands/game/sideQuest/utilities/logo-mark.js.map +1 -0
  36. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js +30 -1
  37. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js.map +1 -1
  38. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js +10 -2
  39. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js.map +1 -1
  40. package/bundle/typescript/src/commands/logout.js +20 -2
  41. package/bundle/typescript/src/commands/logout.js.map +1 -1
  42. package/package.json +1 -1
@@ -876,6 +876,8 @@ export default class Game {
876
876
  */
877
877
  private warmNpcAppearancesInBackground;
878
878
  private _homeRoom;
879
+ /** The hub room a resume seated the player in, when it was not home. */
880
+ private _resumedAt?;
879
881
  private _homeRoomExitDirection?;
880
882
  private static readonly HOME_DIRECTION_PRIORITY;
881
883
  constructor(player: Player, sceneSeed: ISceneSeedJson);
@@ -940,6 +942,19 @@ export default class Game {
940
942
  /** The engine half of startup: scene synthesis, command registration,
941
943
  * hub seeding, resume overlay -- no widget contact. */
942
944
  initEngine(options: IMainGameConfig): Promise<string>;
945
+ /**
946
+ * WHERE YOU LOGGED OUT IS WHERE YOU LOG IN (player request 2026-09-02:
947
+ * "a player that logs in, logs back in at the server location"). The
948
+ * save carries the hub room and named spot (types/save-file.ts
949
+ * ISavedLocation); every hub room change writes a "move" beat, and
950
+ * quit writes the exact spot. On resume the player is seated there
951
+ * when the room still exists in the synthesized hub -- a save from a
952
+ * hub whose seed dropped the room wakes at home, logged, as before.
953
+ * The cell is not carried: a reload seats you on the spot's own seat.
954
+ */
955
+ private restoreHubLocation;
956
+ /** The location a save carries: the current hub room and spot. */
957
+ private hubLocationSnapshot;
943
958
  /**
944
959
  * Everything a save restores beyond the seed synthesis: the player,
945
960
  * the hub world overlay, and the Game-level ledgers. Ordering inside
@@ -13,6 +13,8 @@ import { presenceBeatAllowed } from './utilities/presence-gate.js';
13
13
  import { pushSave, burnCloudSaveFor, enqueueBoundPush, flushPushQueue, writeSpill, clearSpill, hasPendingPush, } from './utilities/cloud-saves.js';
14
14
  import { DOCWAGON_TIERS, RESUSC_FEE, DEATH_COMP } from './utilities/docwagon.js';
15
15
  import { isFence, LIFESTYLE_TIERS, canonicalLifestyleTier } from './utilities/commerce.js';
16
+ import { attachBrandMark, attachBrandMarkBottomRight } from './utilities/brand-mark.js';
17
+ import { attachLogoMark } from './utilities/logo-mark.js';
16
18
  import { bestFakeSin, wandRead, processArrest } from './utilities/sin.js';
17
19
  import { tickEphemerals } from './utilities/ephemeral.js';
18
20
  import { requestAlarmBeat, newAlarmBeatLatch, ALARM_STIMULUS } from './utilities/alarmed-staff.js';
@@ -30,6 +32,7 @@ import { currentSession } from './utilities/session-context.js';
30
32
  import { PlayersCommand } from './commands/players.js';
31
33
  import { LookCommand } from './commands/look.js';
32
34
  import { TakeCommand } from './commands/take.js';
35
+ import { MessageCommand } from './commands/message.js';
33
36
  import { DownloadCommand } from './commands/download.js';
34
37
  import { LootCommand } from './commands/loot.js';
35
38
  import { NoteCommand } from './commands/note.js';
@@ -162,7 +165,7 @@ import { SceneSeedGenerator, FIXER_NAME, isFixerName } from './factories/scene-s
162
165
  import { CALL_ICON, CALL_COLOR, END_CALL_SENTINEL } from './utilities/comm-style.js';
163
166
  import { AI } from '../../../tools/ai/ai.class.js';
164
167
  import { BULLET } from './utilities/log-style.js';
165
- import { spotOf } from './utilities/spots.js';
168
+ import { spotOf, resolveSpot } from './utilities/spots.js';
166
169
  export default class Game {
167
170
  initialized;
168
171
  static instance;
@@ -2172,6 +2175,8 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2172
2175
  // transitions -- the player's own place, unlike every job's generated
2173
2176
  // rooms which get discarded wholesale when the next job replaces them.
2174
2177
  _homeRoom;
2178
+ /** The hub room a resume seated the player in, when it was not home. */
2179
+ _resumedAt;
2175
2180
  _homeRoomExitDirection;
2176
2181
  static HOME_DIRECTION_PRIORITY = [
2177
2182
  Direction.DOWN, Direction.UP, Direction.SOUTH, Direction.NORTH, Direction.EAST, Direction.WEST,
@@ -2198,6 +2203,12 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2198
2203
  .then(m => m.reportConditionSoon(this.player))
2199
2204
  .catch(() => undefined);
2200
2205
  };
2206
+ // A ROOM CHANGE IS A SAVE BEAT (player request 2026-09-02): where you
2207
+ // stand in the hub is what a resume restores, so it has to reach the
2208
+ // save -- and the server -- as you walk, not only at quit. requestSave
2209
+ // carries its own guards (hub only, initialised, not down), so a
2210
+ // room change mid-run or mid-boot is a silent no-op.
2211
+ this.player.onRoomChanged = () => this.requestSave('move');
2201
2212
  }
2202
2213
  registerCommands() {
2203
2214
  CommandFactory.registerCommand('look', LookCommand);
@@ -2207,6 +2218,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2207
2218
  CommandFactory.registerCommand('follow', FollowCommand);
2208
2219
  CommandFactory.registerCommand('unfollow', UnfollowCommand);
2209
2220
  CommandFactory.registerCommand('take', TakeCommand);
2221
+ CommandFactory.registerCommand('message', MessageCommand);
2210
2222
  CommandFactory.registerCommand('download', DownloadCommand);
2211
2223
  CommandFactory.registerCommand('loot', LootCommand);
2212
2224
  CommandFactory.registerCommand('note', NoteCommand);
@@ -2790,7 +2802,10 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2790
2802
  const pendingNote = this._pendingRunSeed
2791
2803
  ? hint(`\n\n${FIXER_NAME}'s job is still on offer: "${this._pendingRunSeed.name}". "call taxi" when you're ready, or "call ${FIXER_NAME}" to hear it again.`)
2792
2804
  : '';
2793
- return `Welcome back, ${this.player.name}. The cot remembers your shape.\n ${this.scene.story}${pendingNote}`;
2805
+ const where = this._resumedAt && this._resumedAt !== this._homeRoom
2806
+ ? `You're back at the ${this._resumedAt.name}${this.player.atSpot ? `, by the ${this.player.atSpot}` : ''} -- right where you left off.`
2807
+ : 'The cot remembers your shape.';
2808
+ return `Welcome back, ${this.player.name}. ${where}\n ${this.scene.story}${pendingNote}`;
2794
2809
  }
2795
2810
  // Nudge the player toward "call" up front -- the fixer convention means
2796
2811
  // the story deliberately doesn't narrate a completed briefing, so
@@ -2802,6 +2817,40 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2802
2817
  : '';
2803
2818
  return `Welcome, ${this.player.name}\n ${this.scene.story}${callHint}`;
2804
2819
  }
2820
+ /**
2821
+ * WHERE YOU LOGGED OUT IS WHERE YOU LOG IN (player request 2026-09-02:
2822
+ * "a player that logs in, logs back in at the server location"). The
2823
+ * save carries the hub room and named spot (types/save-file.ts
2824
+ * ISavedLocation); every hub room change writes a "move" beat, and
2825
+ * quit writes the exact spot. On resume the player is seated there
2826
+ * when the room still exists in the synthesized hub -- a save from a
2827
+ * hub whose seed dropped the room wakes at home, logged, as before.
2828
+ * The cell is not carried: a reload seats you on the spot's own seat.
2829
+ */
2830
+ restoreHubLocation(loc) {
2831
+ if (!loc || !this._hubScene)
2832
+ return;
2833
+ // Not getRoom(): that one throws and logs an error for a miss, and a
2834
+ // dropped room is an expected, quiet fall-through here.
2835
+ const room = loc.room === this._homeRoom?.name
2836
+ ? this._homeRoom
2837
+ : Object.values(this._hubScene.getRooms()).find(r => r.name === loc.room);
2838
+ if (!room) {
2839
+ Logger.getInstance().write(`resume: saved room "${loc.room}" is not in this hub -- waking at home.`);
2840
+ return;
2841
+ }
2842
+ this.player.currentLocation = room;
2843
+ if (loc.spot && resolveSpot(room, loc.spot))
2844
+ this.player.atSpot = loc.spot;
2845
+ this._resumedAt = room;
2846
+ }
2847
+ /** The location a save carries: the current hub room and spot. */
2848
+ hubLocationSnapshot() {
2849
+ const room = this.player.currentLocation;
2850
+ if (!room)
2851
+ return undefined;
2852
+ return { room: room.name, ...(this.player.atSpot ? { spot: this.player.atSpot } : {}) };
2853
+ }
2805
2854
  /**
2806
2855
  * Everything a save restores beyond the seed synthesis: the player,
2807
2856
  * the hub world overlay, and the Game-level ledgers. Ordering inside
@@ -2939,6 +2988,8 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2939
2988
  this.pendingRunAccepted = save.game.pendingRun.accepted ?? false;
2940
2989
  }
2941
2990
  this.player.currentLocation = this._homeRoom;
2991
+ // ...unless the save says where you actually were (see restoreHubLocation).
2992
+ this.restoreHubLocation(save.game.location);
2942
2993
  this.repaintForScene();
2943
2994
  this.refreshLogLabel();
2944
2995
  Logger.getInstance().write(`Resumed save for ${save.playerName} (saved ${save.savedAt}, reason ${save.reason}).`);
@@ -2984,7 +3035,9 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2984
3035
  * from it.
2985
3036
  */
2986
3037
  requestSave(reason) {
2987
- const logger = Logger.getInstance();
3038
+ // GUARDS BEFORE THE LOGGER: the "move" beat fires from any room change,
3039
+ // including ones outside a logging session (harnesses, benches). A
3040
+ // no-op beat must cost nothing and touch nothing.
2988
3041
  if (!this.initialized || this._dead || !this._saveFilePath)
2989
3042
  return;
2990
3043
  if (!this.hasHub || this.scene !== this._hubScene || !this._hubSeed)
@@ -2993,6 +3046,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2993
3046
  return;
2994
3047
  if (this.scene.isPlayerExchangeActive())
2995
3048
  return;
3049
+ const logger = Logger.getInstance();
2996
3050
  try {
2997
3051
  const save = this.buildSaveFile(reason);
2998
3052
  // Carry the cloud-sync stamp FORWARD through local writes: the
@@ -3092,6 +3146,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3092
3146
  hubSeed: this._hubSeed,
3093
3147
  player: serializePlayer(this.player),
3094
3148
  game: {
3149
+ location: this.hubLocationSnapshot(),
3095
3150
  lifestyleTier: this.lifestyleTier,
3096
3151
  rentDebt: this.rentDebt,
3097
3152
  tier: this._tier,
@@ -4352,6 +4407,9 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
4352
4407
  screen.render();
4353
4408
  });
4354
4409
  screen.append(logBox);
4410
+ // まか on the border, over the log (see utilities/brand-mark.ts).
4411
+ attachBrandMark(screen);
4412
+ attachBrandMarkBottomRight(screen, logBox);
4355
4413
  }
4356
4414
  /**
4357
4415
  * The Game Log banner names WHERE you are in the campaign (player
@@ -4472,6 +4530,9 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
4472
4530
  });
4473
4531
  this._statusBox = statusBox;
4474
4532
  screen.append(statusBox);
4533
+ // The site's dotted logo fills the HUD's six rows at the far right
4534
+ // (utilities/logo-mark.ts). Not keyable (see initInputBox).
4535
+ attachLogoMark(screen, statusBox);
4475
4536
  }
4476
4537
  /**
4477
4538
  * THE MINIMAP (map-overlay wave 2026-08-24; split into a pair
@@ -5447,7 +5508,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
5447
5508
  // technomancer-gated (a sprite task, SR5 p.256) and refuses anyone
5448
5509
  // else, so the Emerged shelf is where its audience looks.
5449
5510
  { title: 'resonance', entries: [['compile'], ['decompile'], ['thread'], ['unravel'], ['register'], ['standby'], ['sustain'], ['sprites']] },
5450
- { title: 'social', entries: [['say'], ['emote', 'me'], ['talk-to'], ['call'], ['end-call', 'end', 'hangup'], ['accept'], ['decline', 'deny', 'refuse'], ['haggle', 'negotiate'], ['persuade', 'convince'], ['ask'], ['contacts']] },
5511
+ { title: 'social', entries: [['say'], ['emote', 'me'], ['talk-to'], ['call'], ['message'], ['end-call', 'end', 'hangup'], ['accept'], ['decline', 'deny', 'refuse'], ['haggle', 'negotiate'], ['persuade', 'convince'], ['ask'], ['contacts']] },
5451
5512
  { title: 'street', entries: [['abandon'], ['browse', 'buy'], ['sell'], ['catalog'], ['source', 'procure'], ['work', 'gig'], ['jobs'], ['journal'], ['perform'], ['palm'], ['docwagon'], ['treat'], ['eat'], ['drink'], ['lifestyle'], ['pay']] },
5452
5513
  { title: 'barriers', entries: [['pick'], ['breach'], ['dispel', 'dispell'], ['bluff'], ['unlock'], ['lock']] },
5453
5514
  { title: 'character', entries: [['sheet', 'stats'], ['advance'], ['qualities', 'quality'], ['sin', 'sins', 'papers'], ['initiate', 'submerge'], ['install', 'chrome']] },