@shaunlwm/pickle.ts 1.9.0 → 1.11.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/dist/index.d.ts CHANGED
@@ -1,7 +1,27 @@
1
- import * as socket_io_client from 'socket.io-client';
2
- import { Socket } from 'socket.io-client';
1
+ import { Socket, ManagerOptions, SocketOptions } from 'socket.io-client';
3
2
  import { EventEmitter } from 'node:events';
4
3
 
4
+ type ConnectionProfilePreset = "chrome" | "node";
5
+ type HeaderValue = string | number | boolean | null | undefined;
6
+ type HeaderBag = Record<string, HeaderValue>;
7
+ type ConnectionProfile = {
8
+ preset?: ConnectionProfilePreset;
9
+ userAgent?: string;
10
+ acceptLanguage?: string;
11
+ origin?: string;
12
+ referer?: string;
13
+ headers?: HeaderBag;
14
+ };
15
+ type ConnectionProfileInput = ConnectionProfilePreset | ConnectionProfile;
16
+ type NormalizedConnectionProfile = {
17
+ preset: ConnectionProfilePreset;
18
+ userAgent?: string;
19
+ acceptLanguage?: string;
20
+ origin?: string;
21
+ referer?: string;
22
+ headers: HeaderBag;
23
+ };
24
+
5
25
  type ServerInfo = {
6
26
  name: string;
7
27
  population: number;
@@ -29,6 +49,55 @@ type QueueUpdate = {
29
49
  queueLength: number;
30
50
  };
31
51
 
52
+ type ClientLifecyclePhase = "transport_connecting" | "queueing" | "authenticating" | "joining_session" | "awaiting_initial_state" | "ready" | "disconnecting" | "disconnected";
53
+ type ClientLifecycleUpdate = {
54
+ phase: ClientLifecyclePhase;
55
+ occurredAt: number;
56
+ queue?: QueueUpdate;
57
+ };
58
+ type ClientOperationOptions = {
59
+ signal?: AbortSignal;
60
+ timeoutMs?: number;
61
+ };
62
+ type ClientConnectionTimeouts = {
63
+ loginMs: number;
64
+ transportMs: number;
65
+ /** Maximum silence between queue updates, not total time spent queued. */
66
+ queueMs: number;
67
+ authenticationMs: number;
68
+ initialStateMs: number;
69
+ requestMs: number;
70
+ };
71
+ declare const DEFAULT_CLIENT_CONNECTION_TIMEOUTS: {
72
+ readonly loginMs: 20000;
73
+ readonly transportMs: 20000;
74
+ readonly queueMs: 300000;
75
+ readonly authenticationMs: 20000;
76
+ readonly initialStateMs: 15000;
77
+ readonly requestMs: 15000;
78
+ };
79
+ type ClientDisconnectInfo = {
80
+ intentional: boolean;
81
+ reason: string | null;
82
+ occurredAt: number;
83
+ };
84
+
85
+ type ClientOperationErrorCategory = "login_timeout" | "login_rejected" | "invalid_credentials" | "account_banned" | "queue_timeout" | "transport_error" | "auth_timeout" | "auth_failed" | "initial_state_timeout" | "operation_timeout" | "unsupported_operation" | "aborted" | "disconnected" | "kicked" | "server_error";
86
+ type ClientOperationErrorOptions = {
87
+ category: ClientOperationErrorCategory;
88
+ phase: ClientLifecyclePhase;
89
+ retryable: boolean;
90
+ message: string;
91
+ cause?: unknown;
92
+ };
93
+ declare function sanitizeClientErrorMessage(message: string): string;
94
+ declare class ClientOperationError extends Error {
95
+ readonly category: ClientOperationErrorCategory;
96
+ readonly phase: ClientLifecyclePhase;
97
+ readonly retryable: boolean;
98
+ constructor(options: ClientOperationErrorOptions);
99
+ }
100
+
32
101
  /** Core appearance slots shared by all servers (CPJourney, CPLegacy, NewCP). */
33
102
  type PlayerAppearance = {
34
103
  color: number;
@@ -81,7 +150,24 @@ type RoomUser = PlayerAppearance & {
81
150
  x: number;
82
151
  y: number;
83
152
  frame: number;
84
- /** Adapter-specific extras. See each adapter's normalizeUser for keys. */
153
+ /**
154
+ * Adapter-specific extras. See each adapter's normalizeUser for keys.
155
+ *
156
+ * **CPJourney** overlay appearance slots (number):
157
+ * `hat`, `face_mask`, `neck_scarf`, `body_shirt`, `hand_glove`
158
+ *
159
+ * **CPJourney** user state:
160
+ * `transform` (number) — costume ID, 0 = none
161
+ * `walkingPuffleType` (number | null) — puffle species
162
+ * `openSprite` (string | null) — sprite state e.g. "1_3"
163
+ * `mascotGiveaway` (number | null) — non-null = mascot, value = giveaway item ID
164
+ * `iglooOpen` (number) — 0/1
165
+ * `iglooBounds` (number) — 0/1
166
+ * `igloo_slot` (number) — active igloo slot
167
+ * `currentLayer` (number) — rendering layer
168
+ * `fireRank` (number) — fire ninja rank 0–5
169
+ * `isInvisible` (boolean) — mascot visibility flag
170
+ */
85
171
  meta: Record<string, unknown>;
86
172
  /** Original unnormalized server response */
87
173
  _raw: Record<string, unknown>;
@@ -123,7 +209,78 @@ type Postcard = {
123
209
  senderId: number;
124
210
  postcardId: number;
125
211
  extra: string | null;
126
- date: string;
212
+ /** CPJourney MessagePack decodes this as a Date; other adapters may use strings. */
213
+ date: Date | string;
214
+ };
215
+ /** A puffle summary, optionally including CPJourney's full care state. */
216
+ type Puffle = {
217
+ id: number;
218
+ type: number;
219
+ userId?: number;
220
+ name?: string;
221
+ energy?: number;
222
+ health?: number;
223
+ rest?: number;
224
+ experience?: number;
225
+ level?: number;
226
+ adoption_date?: Record<string, unknown>;
227
+ last_feed?: Record<string, unknown>;
228
+ last_slept?: Record<string, unknown>;
229
+ postcard_hungry?: boolean;
230
+ dead?: number;
231
+ ran_away?: number;
232
+ last_dig?: number;
233
+ in_backyard?: number;
234
+ backyard_supplies?: number;
235
+ walking?: boolean;
236
+ backyard?: boolean;
237
+ };
238
+ /** CPJourney puffle care values returned by get_wellbeing/update_wellbeing. */
239
+ type PuffleWellbeing = {
240
+ puffleId: number;
241
+ energy: number;
242
+ health: number;
243
+ rest: number;
244
+ name: string;
245
+ type: number;
246
+ level: number;
247
+ experience: number;
248
+ inBackyard?: number;
249
+ backyardSupplyCost?: number;
250
+ backyardSuppliesEmpty?: boolean;
251
+ backyardPuffleCount?: number;
252
+ };
253
+ /** Furniture placement sent by CPJourney's igloo editor. */
254
+ type IglooFurniturePlacement = {
255
+ furnitureId: number;
256
+ x: number;
257
+ y: number;
258
+ rotation: number;
259
+ frame: number;
260
+ depth: number;
261
+ /** Present in join_igloo snapshots but omitted by editor updates. */
262
+ slot?: number;
263
+ };
264
+ /** Common CPJourney igloo/music store item fields. */
265
+ type IglooStoreItem = {
266
+ id: string;
267
+ name: string;
268
+ cost: number;
269
+ store: number;
270
+ seasonal: number;
271
+ new: number;
272
+ active?: number;
273
+ patched?: number;
274
+ timeAdded?: number;
275
+ };
276
+ /** CPJourney furniture catalog item fields. */
277
+ type FurnitureStoreItem = IglooStoreItem & {
278
+ type: number;
279
+ sort: number;
280
+ member: number;
281
+ bait: number;
282
+ max: number;
283
+ fps?: number;
127
284
  };
128
285
  type NinjaCard = {
129
286
  id: number;
@@ -179,16 +336,46 @@ type Mascot = {
179
336
  stamp: number;
180
337
  };
181
338
 
339
+ type SocketIoConnectionOptions = Partial<ManagerOptions & SocketOptions> & {
340
+ extraHeaders?: Record<string, string>;
341
+ origin?: string;
342
+ };
343
+ type AdapterMessage = {
344
+ action: string;
345
+ args: Record<string, unknown>;
346
+ };
182
347
  type ConnectOptions = {
348
+ signal?: AbortSignal;
349
+ timeouts?: Partial<ClientConnectionTimeouts>;
183
350
  onQueueUpdate?: (update: QueueUpdate) => void;
351
+ onLifecycleUpdate?: (update: ClientLifecycleUpdate) => void;
352
+ /** @internal Normalized message delivery installed before session join. */
353
+ onMessage?: (message: AdapterMessage) => void;
354
+ /** @internal Transport disconnect delivery installed before session join. */
355
+ onDisconnect?: (reason: string | null) => void;
184
356
  };
185
357
  declare abstract class BaseAdapter {
358
+ protected readonly connectionProfile: NormalizedConnectionProfile;
186
359
  abstract readonly id: string;
187
360
  protected socket: Socket | null;
188
- abstract login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
361
+ loginMessage: string | null;
362
+ loginStatus: "active" | "banned";
363
+ constructor(connectionProfile?: NormalizedConnectionProfile);
364
+ abstract login(options: LoginOptions | TokenLoginOptions, operationOptions?: ClientOperationOptions): Promise<LoginResult>;
189
365
  abstract connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
190
366
  abstract disconnect(): void;
191
367
  abstract send(action: string, args: Record<string, unknown>): void;
368
+ protected connectionTimeouts(options?: ConnectOptions): ClientConnectionTimeouts;
369
+ protected reportLifecycle(options: ConnectOptions | undefined, phase: ClientLifecyclePhase, queue?: QueueUpdate): void;
370
+ protected resetLoginState(): void;
371
+ protected unsupportedOperation(operation: string): ClientOperationError;
372
+ protected socketIoOptions(defaultUrlOrOrigin: string): SocketIoConnectionOptions;
373
+ protected webSocketOptions(defaultUrlOrOrigin: string): {
374
+ headers?: Record<string, string>;
375
+ origin?: string;
376
+ };
377
+ protected connectionHeaders(defaultUrlOrOrigin: string, headers?: HeaderBag): Record<string, string>;
378
+ protected connectionOrigin(defaultUrlOrOrigin: string): string | undefined;
192
379
  normalizeUser(_raw: Record<string, unknown>): RoomUser;
193
380
  normalizePlayer(_raw: Record<string, unknown>): PlayerData;
194
381
  protected extractAppearance(raw: Record<string, unknown>): PlayerAppearance;
@@ -214,6 +401,7 @@ declare abstract class BaseAdapter {
214
401
  buddyReject(_id: number): void;
215
402
  buddyRequestSeen(_id: number): void;
216
403
  getBuddy(_id: number, _type: "buddies" | "buddyRequests"): void;
404
+ findBuddy(_id: number): void;
217
405
  removeBuddy(_id: number): void;
218
406
  addIgnore(_id: number): void;
219
407
  removeIgnore(_id: number): void;
@@ -225,11 +413,48 @@ declare abstract class BaseAdapter {
225
413
  getPostcards(): void;
226
414
  getIglooOpen(_igloo: number): void;
227
415
  getIgloos(): void;
228
- getPuffles(_userId: number): void;
416
+ getPuffles(_userId: number, _isBackyard?: boolean): void;
417
+ getAllPuffles(): void;
418
+ getPuffleWellbeing(_puffle: number): void;
419
+ playPuffle(_puffle: number): void;
420
+ restPuffle(_puffle: number): void;
421
+ buyPuffleItem(_puffleId: number, _item: number): void;
422
+ walkPuffle(_puffle: number): void;
423
+ initializePuffleTower(): void;
424
+ getBackyardSupplies(): void;
229
425
  adoptPuffle(_type: number, _name: string): void;
230
426
  getIglooLikes(): void;
231
427
  checkPuffleSprite(_puffleSprite: boolean): void;
232
428
  joinIgloo(_igloo: number, _x?: number, _y?: number): void;
429
+ getStoreMusic(): void;
430
+ buyMusic(_music: string): void;
431
+ getIglooStoreItems(): void;
432
+ buyFurniture(_furniture: string, _amount: number): void;
433
+ updateIglooMusic(_music: string): void;
434
+ updateIglooFurniture(_furniture: Array<{
435
+ furnitureId: number;
436
+ x: number;
437
+ y: number;
438
+ rotation: number;
439
+ frame: number;
440
+ depth: number;
441
+ slot?: number;
442
+ }>): void;
443
+ autoUpdateIglooFurniture(_furniture: Array<{
444
+ furnitureId: number;
445
+ x: number;
446
+ y: number;
447
+ rotation: number;
448
+ frame: number;
449
+ depth: number;
450
+ slot?: number;
451
+ }>): void;
452
+ updateIglooType(_type: number): void;
453
+ openIgloo(): void;
454
+ closeIglooBounds(): void;
455
+ likeIgloo(): void;
456
+ openIglooEditor(): void;
457
+ closeIglooEditor(): void;
233
458
  gameOver(_coins: number): void;
234
459
  collectStamp(_stamp: number): void;
235
460
  /** Fetch ninja rank, progress, and card deck. Listen for `get_ninja` event. */
@@ -252,7 +477,8 @@ declare abstract class BaseAdapter {
252
477
 
253
478
  declare class CpjourneyAdapter extends BaseAdapter {
254
479
  readonly id = "CPJourney";
255
- login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
480
+ private gameToken;
481
+ login(options: LoginOptions | TokenLoginOptions, operationOptions?: ClientOperationOptions): Promise<LoginResult>;
256
482
  connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
257
483
  private queueForServer;
258
484
  send(action: string, args: Record<string, unknown>): void;
@@ -281,6 +507,7 @@ declare class CpjourneyAdapter extends BaseAdapter {
281
507
  buddyReject(id: number): void;
282
508
  buddyRequestSeen(id: number): void;
283
509
  getBuddy(id: number, type: "buddies" | "buddyRequests"): void;
510
+ findBuddy(id: number): void;
284
511
  removeBuddy(id: number): void;
285
512
  addIgnore(id: number): void;
286
513
  removeIgnore(id: number): void;
@@ -292,11 +519,48 @@ declare class CpjourneyAdapter extends BaseAdapter {
292
519
  getPostcards(): void;
293
520
  getIglooOpen(igloo: number): void;
294
521
  getIgloos(): void;
295
- getPuffles(userId: number): void;
522
+ getPuffles(userId: number, isBackyard?: boolean): void;
523
+ getAllPuffles(): void;
524
+ getPuffleWellbeing(puffle: number): void;
525
+ playPuffle(puffle: number): void;
526
+ restPuffle(puffle: number): void;
527
+ buyPuffleItem(puffleId: number, item: number): void;
528
+ walkPuffle(puffle: number): void;
529
+ initializePuffleTower(): void;
530
+ getBackyardSupplies(): void;
296
531
  adoptPuffle(type: number, name: string): void;
297
532
  getIglooLikes(): void;
298
533
  checkPuffleSprite(puffleSprite: boolean): void;
299
534
  joinIgloo(igloo: number, x?: number, y?: number): void;
535
+ getStoreMusic(): void;
536
+ buyMusic(music: string): void;
537
+ getIglooStoreItems(): void;
538
+ buyFurniture(furniture: string, amount: number): void;
539
+ updateIglooMusic(music: string): void;
540
+ updateIglooFurniture(furniture: Array<{
541
+ furnitureId: number;
542
+ x: number;
543
+ y: number;
544
+ rotation: number;
545
+ frame: number;
546
+ depth: number;
547
+ slot?: number;
548
+ }>): void;
549
+ autoUpdateIglooFurniture(furniture: Array<{
550
+ furnitureId: number;
551
+ x: number;
552
+ y: number;
553
+ rotation: number;
554
+ frame: number;
555
+ depth: number;
556
+ slot?: number;
557
+ }>): void;
558
+ updateIglooType(type: number): void;
559
+ openIgloo(): void;
560
+ closeIglooBounds(): void;
561
+ likeIgloo(): void;
562
+ openIglooEditor(): void;
563
+ closeIglooEditor(): void;
300
564
  gameOver(coins: number): void;
301
565
  collectStamp(stamp: number): void;
302
566
  getNinja(): void;
@@ -307,13 +571,13 @@ declare class CpjourneyAdapter extends BaseAdapter {
307
571
  selectCard(slot: number): void;
308
572
  loadAnimation(animation: string): void;
309
573
  joinMat(waddle: number): void;
310
- private createSocket;
574
+ protected createSocket(path: string): Socket;
311
575
  }
312
576
 
313
577
  declare class CplegacyAdapter extends BaseAdapter {
314
578
  readonly id = "CPLegacy";
315
579
  private version;
316
- login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
580
+ login(options: LoginOptions | TokenLoginOptions, operationOptions?: ClientOperationOptions): Promise<LoginResult>;
317
581
  connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
318
582
  send(action: string, args: Record<string, unknown>): void;
319
583
  disconnect(): void;
@@ -349,48 +613,14 @@ declare class CplegacyAdapter extends BaseAdapter {
349
613
  gameOver(coins: number): void;
350
614
  collectStamp(stamp: number): void;
351
615
  private postLogin;
352
- }
353
-
354
- declare class CpzeroAdapter extends BaseAdapter {
355
- readonly id = "CPZero";
356
- private sfs;
357
- login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
358
- connect(_serverName: string, loginResult: LoginResult, _options?: ConnectOptions): Promise<socket_io_client.Socket>;
359
- send(action: string, args: Record<string, unknown>): void;
360
- disconnect(): void;
361
- normalizeUser(raw: Record<string, unknown>): RoomUser;
362
- normalizePlayer(raw: Record<string, unknown>): PlayerData;
363
- sendMessage(message: string): void;
364
- sendEmote(emote: number): void;
365
- sendSafe(safe: number): void;
366
- walk(x: number, y: number): void;
367
- sendFrame(frame: number): void;
368
- snowball(x: number, y: number): void;
369
- joinRoom(room: number, x?: number, y?: number): void;
370
- addItem(item: number): void;
371
- equipColor(item: number): void;
372
- equipHead(item: number): void;
373
- equipFace(item: number): void;
374
- equipNeck(item: number): void;
375
- equipBody(item: number): void;
376
- equipHand(item: number): void;
377
- equipFeet(item: number): void;
378
- equipFlag(item: number): void;
379
- equipPhoto(item: number): void;
380
- getPlayer(id: number): void;
381
- joinIgloo(igloo: number, _x?: number, _y?: number): void;
382
- /**
383
- * Process a batch of `%xt%` messages that may be concatenated in a single
384
- * WebSocket frame (separated by \0 already split, but multiple %xt% in one string).
385
- */
386
- private processXtBatch;
616
+ protected createSocket(serverName: string): Socket;
387
617
  }
388
618
 
389
619
  declare class NewcpAdapter extends BaseAdapter {
390
620
  readonly id = "NewCP";
391
621
  private encryptor;
392
622
  private worlds;
393
- login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
623
+ login(options: LoginOptions | TokenLoginOptions, operationOptions?: ClientOperationOptions): Promise<LoginResult>;
394
624
  connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
395
625
  send(action: string, args: Record<string, unknown>): void;
396
626
  disconnect(): void;
@@ -421,13 +651,13 @@ declare class NewcpAdapter extends BaseAdapter {
421
651
  removeIgnore(id: number): void;
422
652
  getPlayer(id: number): void;
423
653
  joinIgloo(igloo: number, x?: number, y?: number): void;
424
- private createSocket;
654
+ protected createSocket(host: string, path: string): Socket;
425
655
  private loadWorlds;
426
656
  }
427
657
 
428
658
  declare class PenguinoriginsAdapter extends BaseAdapter {
429
659
  readonly id = "PenguinOrigins";
430
- login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
660
+ login(options: LoginOptions | TokenLoginOptions, operationOptions?: ClientOperationOptions): Promise<LoginResult>;
431
661
  connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
432
662
  send(action: string, args: Record<string, unknown>): void;
433
663
  disconnect(): void;
@@ -457,13 +687,12 @@ declare class PenguinoriginsAdapter extends BaseAdapter {
457
687
  getIglooOpen(igloo: number): void;
458
688
  joinIgloo(igloo: number, x?: number, y?: number): void;
459
689
  gameOver(coins: number): void;
460
- private createSocket;
690
+ protected createSocket(path: string): Socket;
461
691
  }
462
692
 
463
693
  declare const ADAPTERS: {
464
694
  readonly CPJourney: typeof CpjourneyAdapter;
465
695
  readonly CPLegacy: typeof CplegacyAdapter;
466
- readonly CPZero: typeof CpzeroAdapter;
467
696
  readonly NewCP: typeof NewcpAdapter;
468
697
  readonly PenguinOrigins: typeof PenguinoriginsAdapter;
469
698
  };
@@ -541,6 +770,7 @@ type ClientMessages = {
541
770
  get_igloos: Record<string, never>;
542
771
  get_puffles: {
543
772
  userId: number;
773
+ isBackyard?: boolean;
544
774
  };
545
775
  get_igloo_likes: Record<string, never>;
546
776
  join_igloo: {
@@ -592,6 +822,54 @@ type ClientMessages = {
592
822
  check_puffle_sprite: {
593
823
  puffleSprite: unknown;
594
824
  };
825
+ get_all_puffles: Record<string, never>;
826
+ get_wellbeing: {
827
+ puffle: number;
828
+ };
829
+ puffle_play: {
830
+ puffle: number;
831
+ };
832
+ update_puffle_rest: {
833
+ puffle: number;
834
+ };
835
+ puffle_buy_item: {
836
+ puffleId: number;
837
+ item: number;
838
+ };
839
+ walk_puffle: {
840
+ puffle: number;
841
+ };
842
+ backyard_supplies: Record<string, never>;
843
+ buddy_find: {
844
+ id: number;
845
+ };
846
+ get_store_music: Record<string, never>;
847
+ add_music: {
848
+ music: string;
849
+ };
850
+ get_igloostore_items: Record<string, never>;
851
+ add_furniture: {
852
+ furniture: string;
853
+ amount: number;
854
+ };
855
+ update_music: {
856
+ music: string;
857
+ };
858
+ update_furniture: {
859
+ furniture: IglooFurniturePlacement[];
860
+ };
861
+ update_furniture_auto: {
862
+ furniture: IglooFurniturePlacement[];
863
+ };
864
+ update_igloo: {
865
+ type: number;
866
+ };
867
+ open_igloo: Record<string, never>;
868
+ close_igloo_bounds: Record<string, never>;
869
+ like_igloo: Record<string, never>;
870
+ igloo_editor_open: Record<string, never>;
871
+ igloo_editor_closed: Record<string, never>;
872
+ tower_init: Record<string, never>;
595
873
  queue_server_join: {
596
874
  server: string;
597
875
  };
@@ -791,11 +1069,74 @@ type ServerMessages = {
791
1069
  };
792
1070
  get_puffles: {
793
1071
  userId: number;
794
- puffles: {
795
- id: number;
796
- type: number;
797
- }[];
1072
+ puffles: Puffle[];
1073
+ };
1074
+ get_all_puffles: {
1075
+ puffles: Puffle[];
1076
+ };
1077
+ get_wellbeing: PuffleWellbeing;
1078
+ get_walking_puffle: {
1079
+ puffle: Puffle;
1080
+ };
1081
+ update_wellbeing: PuffleWellbeing;
1082
+ puffle_levelup: {
1083
+ puffleId: number;
1084
+ level: number;
1085
+ };
1086
+ puffle_popup: {
1087
+ puffleId: number;
1088
+ popupId: number;
1089
+ };
1090
+ buy_puffle_item: {
1091
+ puffleId: number;
1092
+ item: number;
1093
+ coins: number;
1094
+ puffleInventory: Record<string, unknown>;
1095
+ };
1096
+ walk_puffle: {
1097
+ user: number;
1098
+ puffle: number;
1099
+ type: number;
1100
+ };
1101
+ backyard_supplies: {
1102
+ supplyCost: number;
1103
+ puffleCount: number;
1104
+ supplyState: number;
1105
+ };
1106
+ buddy_find: {
1107
+ find: number;
1108
+ username: string;
1109
+ game: boolean;
1110
+ };
1111
+ receive_postcard: Postcard;
1112
+ get_store_music: {
1113
+ music: IglooStoreItem[];
1114
+ };
1115
+ add_music: {
1116
+ music: string;
1117
+ coins: number;
1118
+ };
1119
+ get_igloostore_items: {
1120
+ furniture: FurnitureStoreItem[];
1121
+ flooring: IglooStoreItem[];
1122
+ igloo: IglooStoreItem[];
1123
+ location: IglooStoreItem[];
1124
+ };
1125
+ add_furniture: {
1126
+ furniture: string;
1127
+ coins: number;
1128
+ amount: number;
1129
+ };
1130
+ update_music: {
1131
+ music: string;
1132
+ };
1133
+ igloo_open_status: {
1134
+ status: number;
1135
+ };
1136
+ igloo_bounds_status: {
1137
+ status: number;
798
1138
  };
1139
+ igloo_liked: Record<string, never>;
799
1140
  update_player: {
800
1141
  id: number;
801
1142
  item: number;
@@ -842,7 +1183,7 @@ type ServerMessages = {
842
1183
  transform: number;
843
1184
  };
844
1185
  adopt_puffle: {
845
- puffle: unknown;
1186
+ puffle?: unknown;
846
1187
  coins: number;
847
1188
  };
848
1189
  /** Generic server info/notification message */
@@ -853,7 +1194,7 @@ type ServerMessages = {
853
1194
  action: string;
854
1195
  args: Record<string, unknown>;
855
1196
  };
856
- disconnect: undefined;
1197
+ disconnect: ClientDisconnectInfo;
857
1198
  /** Ninja rank, progress, and full card deck */
858
1199
  get_ninja: NinjaData;
859
1200
  /** State of all Dojo mats — keys are mat IDs, values are seat arrays */
@@ -918,26 +1259,30 @@ type ServerMessages = {
918
1259
  message: string;
919
1260
  };
920
1261
  };
1262
+ /** CPJourney-only commands captured from its Socket.IO protocol. */
1263
+ type CpjourneyClientMessages = Pick<ClientMessages, "get_puffles" | "adopt_puffle" | "check_puffle_sprite" | "get_all_puffles" | "get_wellbeing" | "puffle_play" | "update_puffle_rest" | "puffle_buy_item" | "walk_puffle" | "backyard_supplies" | "buddy_find" | "get_store_music" | "add_music" | "get_igloostore_items" | "add_furniture" | "update_music" | "update_furniture" | "update_furniture_auto" | "update_igloo" | "open_igloo" | "close_igloo_bounds" | "like_igloo" | "igloo_editor_open" | "igloo_editor_closed" | "tower_init">;
1264
+ /** CPJourney-only events captured from its Socket.IO protocol. */
1265
+ type CpjourneyServerMessages = Pick<ServerMessages, "game_over" | "get_postcards" | "join_igloo" | "get_puffles" | "adopt_puffle" | "get_all_puffles" | "get_wellbeing" | "get_walking_puffle" | "update_wellbeing" | "puffle_levelup" | "puffle_popup" | "buy_puffle_item" | "walk_puffle" | "backyard_supplies" | "buddy_find" | "receive_postcard" | "get_store_music" | "add_music" | "get_igloostore_items" | "add_furniture" | "update_music" | "igloo_open_status" | "igloo_bounds_status" | "igloo_liked">;
921
1266
 
922
- type WaitForFn = <K extends keyof ServerMessages>(event: K, timeout?: number) => Promise<ServerMessages[K]>;
1267
+ type RequestFn = <K extends keyof ServerMessages>(event: K, send: () => void, options?: ClientOperationOptions, matches?: (args: ServerMessages[K]) => boolean) => Promise<ServerMessages[K]>;
923
1268
  declare class CardJitsu {
924
1269
  private adapter;
925
- private waitFor;
926
- constructor(adapter: BaseAdapter, waitFor: WaitForFn);
1270
+ private request;
1271
+ constructor(adapter: BaseAdapter, request: RequestFn);
927
1272
  /** Fetch ninja rank, progress, and card deck. Resolves with ninja data. */
928
- getNinja(): Promise<ServerMessages["get_ninja"]>;
1273
+ getNinja(options?: ClientOperationOptions): Promise<ServerMessages["get_ninja"]>;
929
1274
  /** Fetch state of all Dojo mats. Resolves with mat state. */
930
- getMats(): Promise<ServerMessages["get_waddles"]>;
1275
+ getMats(options?: ClientOperationOptions): Promise<ServerMessages["get_waddles"]>;
931
1276
  /** Sit on a Dojo mat to wait for an opponent. Listen for `update_waddle` events. */
932
1277
  joinMat(waddle: number): void;
933
1278
  /** Join Sensei matchmaking queue. Resolves when server acknowledges. */
934
- joinMatchmaking(): Promise<ServerMessages["join_matchmaking"]>;
1279
+ joinMatchmaking(options?: ClientOperationOptions): Promise<ServerMessages["join_matchmaking"]>;
935
1280
  /** Leave Sensei matchmaking queue. */
936
1281
  leaveMatchmaking(): void;
937
1282
  /** Start a Card-Jitsu match after entering a game room. Resolves with player info. */
938
- startGame(): Promise<ServerMessages["start_game"]>;
1283
+ startGame(options?: ClientOperationOptions): Promise<ServerMessages["start_game"]>;
939
1284
  /** Play a card from your hand by slot index. Resolves when server acknowledges. */
940
- selectCard(slot: number): Promise<ServerMessages["move_my_card"]>;
1285
+ selectCard(slot: number, options?: ClientOperationOptions): Promise<ServerMessages["move_my_card"]>;
941
1286
  /** Preload a power card animation asset. */
942
1287
  loadAnimation(animation: string): void;
943
1288
  }
@@ -946,6 +1291,7 @@ type ServerMessageHandler<K extends keyof ServerMessages> = (args: ServerMessage
946
1291
  type LogFn = (message: string, ...args: unknown[]) => void;
947
1292
  type ClientOptions = {
948
1293
  debug?: boolean | LogFn;
1294
+ connectionProfile?: ConnectionProfileInput;
949
1295
  };
950
1296
  declare class Client extends EventEmitter {
951
1297
  player: PlayerData | null;
@@ -956,10 +1302,20 @@ declare class Client extends EventEmitter {
956
1302
  private loginResult;
957
1303
  private log;
958
1304
  private _cardJitsu;
1305
+ private intentionalDisconnect;
1306
+ private disconnectNotified;
1307
+ private connectionFailure;
1308
+ private lifecycleReporter;
1309
+ private requestTails;
1310
+ private disconnectEpoch;
1311
+ private lastDisconnectInfo;
1312
+ get loginMessage(): string | null;
1313
+ get loginStatus(): "active" | "banned";
959
1314
  get cardJitsu(): CardJitsu;
960
1315
  constructor(server: AdapterName, options?: ClientOptions);
961
- login(options: LoginOptions | TokenLoginOptions): Promise<ServerInfo[]>;
1316
+ login(options: LoginOptions | TokenLoginOptions, operationOptions?: ClientOperationOptions): Promise<ServerInfo[]>;
962
1317
  connect(serverName: string, options?: ConnectOptions): Promise<void>;
1318
+ private waitForInitialState;
963
1319
  on<K extends keyof ServerMessages>(event: K, listener: ServerMessageHandler<K>): this;
964
1320
  on(event: string, listener: (...args: unknown[]) => void): this;
965
1321
  off<K extends keyof ServerMessages>(event: K, listener: ServerMessageHandler<K>): this;
@@ -968,16 +1324,20 @@ declare class Client extends EventEmitter {
968
1324
  once(event: string, listener: (...args: unknown[]) => void): this;
969
1325
  emit<K extends keyof ServerMessages>(event: K, args: ServerMessages[K]): boolean;
970
1326
  emit(event: string, ...args: unknown[]): boolean;
971
- /** Wait for a server event. Resolves with the event payload. Optional timeout in ms. Rejects on disconnect. */
1327
+ /** Wait for a server event. Resolves with the event payload and rejects on timeout, abort, or disconnect. */
972
1328
  waitFor<K extends keyof ServerMessages>(event: K, timeout?: number): Promise<ServerMessages[K]>;
1329
+ waitFor<K extends keyof ServerMessages>(event: K, options?: ClientOperationOptions): Promise<ServerMessages[K]>;
1330
+ private waitForEvent;
1331
+ private request;
1332
+ private waitForRequestTurn;
973
1333
  sendMessage(message: string): void;
974
1334
  sendEmote(emote: number): void;
975
1335
  sendSafe(safe: number): void;
976
1336
  walk(x: number, y: number): void;
977
1337
  sendFrame(frame: number, set?: boolean): void;
978
1338
  snowball(x: number, y: number): void;
979
- joinRoom(room: number, x?: number, y?: number): Promise<ServerMessages["join_room"]>;
980
- addItem(item: number): Promise<ServerMessages["add_item"]>;
1339
+ joinRoom(room: number, x?: number, y?: number, options?: ClientOperationOptions): Promise<ServerMessages["join_room"]>;
1340
+ addItem(item: number, options?: ClientOperationOptions): Promise<ServerMessages["add_item"]>;
981
1341
  equipColor(item: number): void;
982
1342
  equipHead(item: number): void;
983
1343
  equipFace(item: number): void;
@@ -988,32 +1348,59 @@ declare class Client extends EventEmitter {
988
1348
  equipFlag(item: number): void;
989
1349
  equipPhoto(item: number): void;
990
1350
  buddyRequest(id: number): void;
991
- buddyAccept(id: number): Promise<ServerMessages["buddy_accept"]>;
992
- buddyReject(id: number): Promise<ServerMessages["buddy_reject"]>;
993
- buddyRequestSeen(id: number): Promise<ServerMessages["buddy_request_seen"]>;
994
- getBuddy(id: number, type: "buddies" | "buddyRequests"): Promise<ServerMessages["get_buddy"]>;
1351
+ buddyAccept(id: number, options?: ClientOperationOptions): Promise<ServerMessages["buddy_accept"]>;
1352
+ buddyReject(id: number, options?: ClientOperationOptions): Promise<ServerMessages["buddy_reject"]>;
1353
+ buddyRequestSeen(id: number, options?: ClientOperationOptions): Promise<ServerMessages["buddy_request_seen"]>;
1354
+ getBuddy(id: number, type: "buddies" | "buddyRequests", options?: ClientOperationOptions): Promise<ServerMessages["get_buddy"]>;
1355
+ findBuddy(id: number, options?: ClientOperationOptions): Promise<ServerMessages["buddy_find"]>;
995
1356
  removeBuddy(id: number): void;
996
- addIgnore(id: number): Promise<ServerMessages["ignore_add"]>;
997
- removeIgnore(id: number): Promise<ServerMessages["ignore_remove"]>;
998
- getPlayer(id: number): Promise<ServerMessages["get_player"]>;
999
- getAllSlots(): Promise<ServerMessages["slot"]>;
1000
- getMascots(): Promise<ServerMessages["get_mascots"]>;
1001
- sendPostcard(userId: number, cardId: string): Promise<ServerMessages["send_postcard"]>;
1002
- getStamps(userId: number): Promise<ServerMessages["stamps_result"]>;
1003
- getPostcards(): Promise<ServerMessages["get_postcards"]>;
1004
- getIglooOpen(igloo: number): Promise<ServerMessages["get_igloo_open"]>;
1005
- getIgloos(): Promise<ServerMessages["get_igloos"]>;
1006
- getPuffles(userId: number): Promise<ServerMessages["get_puffles"]>;
1007
- adoptPuffle(type: number, name: string): Promise<ServerMessages["adopt_puffle"]>;
1008
- getIglooLikes(): Promise<ServerMessages["get_igloo_likes"]>;
1357
+ addIgnore(id: number, options?: ClientOperationOptions): Promise<ServerMessages["ignore_add"]>;
1358
+ removeIgnore(id: number, options?: ClientOperationOptions): Promise<ServerMessages["ignore_remove"]>;
1359
+ getPlayer(id: number, options?: ClientOperationOptions): Promise<ServerMessages["get_player"]>;
1360
+ getAllSlots(options?: ClientOperationOptions): Promise<ServerMessages["slot"]>;
1361
+ getMascots(options?: ClientOperationOptions): Promise<ServerMessages["get_mascots"]>;
1362
+ sendPostcard(userId: number, cardId: string, options?: ClientOperationOptions): Promise<ServerMessages["send_postcard"]>;
1363
+ getStamps(userId: number, options?: ClientOperationOptions): Promise<ServerMessages["stamps_result"]>;
1364
+ getPostcards(options?: ClientOperationOptions): Promise<ServerMessages["get_postcards"]>;
1365
+ getIglooOpen(igloo: number, options?: ClientOperationOptions): Promise<ServerMessages["get_igloo_open"]>;
1366
+ getIgloos(options?: ClientOperationOptions): Promise<ServerMessages["get_igloos"]>;
1367
+ getPuffles(userId: number, options?: ClientOperationOptions & {
1368
+ isBackyard?: boolean;
1369
+ }): Promise<ServerMessages["get_puffles"]>;
1370
+ getAllPuffles(options?: ClientOperationOptions): Promise<ServerMessages["get_all_puffles"]>;
1371
+ getPuffleWellbeing(puffle: number, options?: ClientOperationOptions): Promise<ServerMessages["get_wellbeing"]>;
1372
+ playPuffle(puffle: number): void;
1373
+ restPuffle(puffle: number): void;
1374
+ buyPuffleItem(puffleId: number, item: number, options?: ClientOperationOptions): Promise<ServerMessages["buy_puffle_item"]>;
1375
+ walkPuffle(puffle: number, options?: ClientOperationOptions): Promise<ServerMessages["get_walking_puffle"]>;
1376
+ /** CPJourney sends tower_init after its walking-puffle acknowledgement. */
1377
+ initializePuffleTower(): void;
1378
+ getBackyardSupplies(options?: ClientOperationOptions): Promise<ServerMessages["backyard_supplies"]>;
1379
+ adoptPuffle(type: number, name: string, options?: ClientOperationOptions): Promise<ServerMessages["adopt_puffle"]>;
1380
+ getIglooLikes(options?: ClientOperationOptions): Promise<ServerMessages["get_igloo_likes"]>;
1009
1381
  checkPuffleSprite(puffleSprite: boolean): void;
1010
- joinIgloo(igloo: number, x?: number, y?: number): Promise<ServerMessages["join_igloo"]>;
1011
- gameOver(coins: number): Promise<ServerMessages["game_over"]>;
1012
- collectStamp(stamp: number): Promise<ServerMessages["stamp_earned"]>;
1382
+ joinIgloo(igloo: number, x?: number, y?: number, options?: ClientOperationOptions): Promise<ServerMessages["join_igloo"]>;
1383
+ getStoreMusic(options?: ClientOperationOptions): Promise<ServerMessages["get_store_music"]>;
1384
+ buyMusic(music: string, options?: ClientOperationOptions): Promise<ServerMessages["add_music"]>;
1385
+ getIglooStoreItems(options?: ClientOperationOptions): Promise<ServerMessages["get_igloostore_items"]>;
1386
+ buyFurniture(furniture: string, amount?: number, options?: ClientOperationOptions): Promise<ServerMessages["add_furniture"]>;
1387
+ updateIglooMusic(music: string, options?: ClientOperationOptions): Promise<ServerMessages["update_music"]>;
1388
+ updateIglooFurniture(furniture: ClientMessages["update_furniture"]["furniture"]): void;
1389
+ autoUpdateIglooFurniture(furniture: ClientMessages["update_furniture_auto"]["furniture"]): void;
1390
+ updateIglooType(type: number): void;
1391
+ openIgloo(options?: ClientOperationOptions): Promise<ServerMessages["igloo_open_status"]>;
1392
+ closeIglooBounds(options?: ClientOperationOptions): Promise<ServerMessages["igloo_bounds_status"]>;
1393
+ likeIgloo(options?: ClientOperationOptions): Promise<ServerMessages["igloo_liked"]>;
1394
+ openIglooEditor(): void;
1395
+ closeIglooEditor(): void;
1396
+ gameOver(coins: number, options?: ClientOperationOptions): Promise<ServerMessages["game_over"]>;
1397
+ collectStamp(stamp: number, options?: ClientOperationOptions): Promise<ServerMessages["stamp_earned"]>;
1013
1398
  sleep(ms: number): Promise<void>;
1014
1399
  disconnect(): void;
1400
+ private reportLifecycle;
1401
+ private handleAdapterDisconnect;
1015
1402
  private cleanup;
1016
1403
  private handleMessage;
1017
1404
  }
1018
1405
 
1019
- export { type AdapterName, BaseAdapter, type Buddy, CardJitsu, Client, type ClientMessages, type ClientOptions, type ConnectOptions, type GameCard, type GamePlayer, type LogFn, type LoginOptions, type LoginResult, type Mascot, type MatState, type NinjaCard, type NinjaData, type NinjaProgress, type PlayerAppearance, type PlayerData, type PlayerSettings, type Postcard, type QueueUpdate, type RevealedCard, type RoomUser, type RoundResult, type ServerInfo, type ServerMessages, type TokenLoginOptions };
1406
+ export { type AdapterName, BaseAdapter, type Buddy, CardJitsu, Client, type ClientConnectionTimeouts, type ClientDisconnectInfo, type ClientLifecyclePhase, type ClientLifecycleUpdate, type ClientMessages, ClientOperationError, type ClientOperationErrorCategory, type ClientOperationErrorOptions, type ClientOperationOptions, type ClientOptions, type ConnectOptions, type ConnectionProfile, type ConnectionProfileInput, type ConnectionProfilePreset, type CpjourneyClientMessages, type CpjourneyServerMessages, DEFAULT_CLIENT_CONNECTION_TIMEOUTS, type FurnitureStoreItem, type GameCard, type GamePlayer, type IglooFurniturePlacement, type IglooStoreItem, type LogFn, type LoginOptions, type LoginResult, type Mascot, type MatState, type NinjaCard, type NinjaData, type NinjaProgress, type PlayerAppearance, type PlayerData, type PlayerSettings, type Postcard, type Puffle, type PuffleWellbeing, type QueueUpdate, type RevealedCard, type RoomUser, type RoundResult, type ServerInfo, type ServerMessages, type TokenLoginOptions, sanitizeClientErrorMessage };