nostr-arena 0.1.1

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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +188 -0
  3. package/dist/__tests__/callbacks.test.d.ts +28 -0
  4. package/dist/__tests__/callbacks.test.d.ts.map +1 -0
  5. package/dist/__tests__/callbacks.test.js +140 -0
  6. package/dist/__tests__/callbacks.test.js.map +1 -0
  7. package/dist/__tests__/config.test.d.ts +18 -0
  8. package/dist/__tests__/config.test.d.ts.map +1 -0
  9. package/dist/__tests__/config.test.js +43 -0
  10. package/dist/__tests__/config.test.js.map +1 -0
  11. package/dist/__tests__/error-handling.test.d.ts +14 -0
  12. package/dist/__tests__/error-handling.test.d.ts.map +1 -0
  13. package/dist/__tests__/error-handling.test.js +199 -0
  14. package/dist/__tests__/error-handling.test.js.map +1 -0
  15. package/dist/__tests__/protocol.test.d.ts +7 -0
  16. package/dist/__tests__/protocol.test.d.ts.map +1 -0
  17. package/dist/__tests__/protocol.test.js +257 -0
  18. package/dist/__tests__/protocol.test.js.map +1 -0
  19. package/dist/__tests__/state-flow.test.d.ts +37 -0
  20. package/dist/__tests__/state-flow.test.d.ts.map +1 -0
  21. package/dist/__tests__/state-flow.test.js +160 -0
  22. package/dist/__tests__/state-flow.test.js.map +1 -0
  23. package/dist/__tests__/timing.test.d.ts +20 -0
  24. package/dist/__tests__/timing.test.d.ts.map +1 -0
  25. package/dist/__tests__/timing.test.js +73 -0
  26. package/dist/__tests__/timing.test.js.map +1 -0
  27. package/dist/core/Arena.d.ts +164 -0
  28. package/dist/core/Arena.d.ts.map +1 -0
  29. package/dist/core/Arena.js +634 -0
  30. package/dist/core/Arena.js.map +1 -0
  31. package/dist/core/NostrClient.d.ts +108 -0
  32. package/dist/core/NostrClient.d.ts.map +1 -0
  33. package/dist/core/NostrClient.js +225 -0
  34. package/dist/core/NostrClient.js.map +1 -0
  35. package/dist/core/index.d.ts +8 -0
  36. package/dist/core/index.d.ts.map +1 -0
  37. package/dist/core/index.js +7 -0
  38. package/dist/core/index.js.map +1 -0
  39. package/dist/index.d.ts +35 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +37 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/proxy.d.ts +36 -0
  44. package/dist/proxy.d.ts.map +1 -0
  45. package/dist/proxy.js +98 -0
  46. package/dist/proxy.js.map +1 -0
  47. package/dist/react/index.d.ts +7 -0
  48. package/dist/react/index.d.ts.map +1 -0
  49. package/dist/react/index.js +6 -0
  50. package/dist/react/index.js.map +1 -0
  51. package/dist/react/useArena.d.ts +74 -0
  52. package/dist/react/useArena.d.ts.map +1 -0
  53. package/dist/react/useArena.js +224 -0
  54. package/dist/react/useArena.js.map +1 -0
  55. package/dist/retry.d.ts +54 -0
  56. package/dist/retry.d.ts.map +1 -0
  57. package/dist/retry.js +82 -0
  58. package/dist/retry.js.map +1 -0
  59. package/dist/testing/MockArena.d.ts +84 -0
  60. package/dist/testing/MockArena.d.ts.map +1 -0
  61. package/dist/testing/MockArena.js +156 -0
  62. package/dist/testing/MockArena.js.map +1 -0
  63. package/dist/testing/index.d.ts +6 -0
  64. package/dist/testing/index.d.ts.map +1 -0
  65. package/dist/testing/index.js +6 -0
  66. package/dist/testing/index.js.map +1 -0
  67. package/dist/types.d.ts +183 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +55 -0
  70. package/dist/types.js.map +1 -0
  71. package/package.json +84 -0
@@ -0,0 +1,634 @@
1
+ /**
2
+ * nostr-battle-room - Arena
3
+ * Main class for managing multiplayer game rooms over Nostr
4
+ */
5
+ import { NostrClient } from './NostrClient';
6
+ import { DEFAULT_CONFIG, INITIAL_ROOM_STATE, NOSTR_KINDS, createRoomTag, generateSeed, generateRoomId, } from '../types';
7
+ import { withTimeout } from '../retry';
8
+ /**
9
+ * Arena - Manages a multiplayer game room over Nostr
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * interface MyGameState {
14
+ * score: number;
15
+ * position: { x: number; y: number };
16
+ * }
17
+ *
18
+ * const room = new Arena<MyGameState>({
19
+ * gameId: 'my-game',
20
+ * relays: ['wss://relay.damus.io'],
21
+ * });
22
+ *
23
+ * room.on('opponentState', (state) => {
24
+ * console.log('Opponent score:', state.score);
25
+ * });
26
+ *
27
+ * const url = await room.create();
28
+ * console.log('Share this URL:', url);
29
+ * ```
30
+ */
31
+ export class Arena {
32
+ constructor(config) {
33
+ this.callbacks = {};
34
+ this._roomState = { ...INITIAL_ROOM_STATE };
35
+ this._opponent = null;
36
+ this.unsubscribe = null;
37
+ this.heartbeatInterval = null;
38
+ this.disconnectCheckInterval = null;
39
+ this.lastStateUpdate = 0;
40
+ this.config = {
41
+ ...DEFAULT_CONFIG,
42
+ ...config,
43
+ };
44
+ this.client = new NostrClient({
45
+ relays: this.config.relays,
46
+ storageKeyPrefix: this.config.gameId,
47
+ });
48
+ // Default to localStorage, with fallback for non-browser environments
49
+ this.storage =
50
+ typeof localStorage !== 'undefined'
51
+ ? localStorage
52
+ : {
53
+ getItem: () => null,
54
+ setItem: () => { },
55
+ removeItem: () => { },
56
+ };
57
+ }
58
+ // ===========================================================================
59
+ // Public Getters
60
+ // ===========================================================================
61
+ /** Current room state */
62
+ get roomState() {
63
+ return this._roomState;
64
+ }
65
+ /** Current opponent state (null if no opponent) */
66
+ get opponent() {
67
+ return this._opponent;
68
+ }
69
+ /** Whether connected to Nostr relays */
70
+ get isConnected() {
71
+ return this.client.isConnected;
72
+ }
73
+ /** This player's public key */
74
+ get publicKey() {
75
+ return this.client.publicKey;
76
+ }
77
+ /**
78
+ * Get the connection status of each relay
79
+ */
80
+ getRelayStatus() {
81
+ return this.client.getRelayStatus();
82
+ }
83
+ /**
84
+ * Check if at least one relay is connected
85
+ */
86
+ get hasConnectedRelay() {
87
+ return this.client.hasConnectedRelay;
88
+ }
89
+ // ===========================================================================
90
+ // Event Registration
91
+ // ===========================================================================
92
+ /**
93
+ * Register event callback for opponentJoin
94
+ */
95
+ onOpponentJoin(callback) {
96
+ this.callbacks.onOpponentJoin = callback;
97
+ return this;
98
+ }
99
+ /**
100
+ * Register event callback for opponentState
101
+ */
102
+ onOpponentState(callback) {
103
+ this.callbacks.onOpponentState = callback;
104
+ return this;
105
+ }
106
+ /**
107
+ * Register event callback for opponentDisconnect
108
+ */
109
+ onOpponentDisconnect(callback) {
110
+ this.callbacks.onOpponentDisconnect = callback;
111
+ return this;
112
+ }
113
+ /**
114
+ * Register event callback for opponentGameOver
115
+ */
116
+ onOpponentGameOver(callback) {
117
+ this.callbacks.onOpponentGameOver = callback;
118
+ return this;
119
+ }
120
+ /**
121
+ * Register event callback for rematchRequested
122
+ */
123
+ onRematchRequested(callback) {
124
+ this.callbacks.onRematchRequested = callback;
125
+ return this;
126
+ }
127
+ /**
128
+ * Register event callback for rematchStart
129
+ */
130
+ onRematchStart(callback) {
131
+ this.callbacks.onRematchStart = callback;
132
+ return this;
133
+ }
134
+ /**
135
+ * Register event callback for error
136
+ */
137
+ onError(callback) {
138
+ this.callbacks.onError = callback;
139
+ return this;
140
+ }
141
+ // ===========================================================================
142
+ // Connection
143
+ // ===========================================================================
144
+ /**
145
+ * Connect to Nostr relays
146
+ */
147
+ connect() {
148
+ this.client.connect();
149
+ }
150
+ /**
151
+ * Disconnect from relays and clean up
152
+ */
153
+ disconnect() {
154
+ this.stopHeartbeat();
155
+ this.stopDisconnectCheck();
156
+ this.unsubscribe?.();
157
+ this.client.disconnect();
158
+ }
159
+ // ===========================================================================
160
+ // Room Management
161
+ // ===========================================================================
162
+ /**
163
+ * Create a new room
164
+ *
165
+ * Times out after joinTimeout (default: 30 seconds)
166
+ * @returns Room URL (e.g., "https://example.com/battle/abc123")
167
+ */
168
+ async create(baseUrl) {
169
+ const timeoutMs = this.config.joinTimeout ?? DEFAULT_CONFIG.joinTimeout;
170
+ try {
171
+ return await withTimeout(() => this.createInternal(baseUrl), timeoutMs, 'Create operation timed out');
172
+ }
173
+ catch (error) {
174
+ // Reset state on any error
175
+ this._roomState = { ...INITIAL_ROOM_STATE };
176
+ this.clearRoom();
177
+ throw error;
178
+ }
179
+ }
180
+ /**
181
+ * Internal create implementation
182
+ */
183
+ async createInternal(baseUrl) {
184
+ if (!this.client.isConnected) {
185
+ this.client.connect();
186
+ }
187
+ const roomId = generateRoomId();
188
+ const seed = generateSeed();
189
+ const createdAt = Date.now();
190
+ this._roomState = {
191
+ roomId,
192
+ status: 'creating',
193
+ isHost: true,
194
+ seed,
195
+ createdAt,
196
+ };
197
+ // Publish room creation event
198
+ await this.client.publish({
199
+ kind: NOSTR_KINDS.ROOM,
200
+ tags: [
201
+ ['d', createRoomTag(this.config.gameId, roomId)],
202
+ ['t', this.config.gameId],
203
+ ],
204
+ content: JSON.stringify({
205
+ type: 'room',
206
+ status: 'waiting',
207
+ seed,
208
+ hostPubkey: this.client.publicKey,
209
+ }),
210
+ });
211
+ // Only save and subscribe after successful publish
212
+ this._roomState = { ...this._roomState, status: 'waiting' };
213
+ this.saveRoom({ roomId, isHost: true, seed, createdAt });
214
+ this.subscribeToRoom(roomId);
215
+ const base = baseUrl ?? (typeof window !== 'undefined' ? window.location.origin : '');
216
+ return `${base}/battle/${roomId}`;
217
+ }
218
+ /**
219
+ * Join an existing room
220
+ *
221
+ * Times out after joinTimeout (default: 30 seconds)
222
+ */
223
+ async join(roomId) {
224
+ const timeoutMs = this.config.joinTimeout ?? DEFAULT_CONFIG.joinTimeout;
225
+ try {
226
+ await withTimeout(() => this.joinInternal(roomId), timeoutMs, 'Join operation timed out');
227
+ }
228
+ catch (error) {
229
+ // Reset state on any error
230
+ this._roomState = { ...INITIAL_ROOM_STATE };
231
+ throw error;
232
+ }
233
+ }
234
+ /**
235
+ * Internal join implementation
236
+ */
237
+ async joinInternal(roomId) {
238
+ if (!this.client.isConnected) {
239
+ this.client.connect();
240
+ }
241
+ this._roomState = {
242
+ ...this._roomState,
243
+ roomId,
244
+ status: 'joining',
245
+ isHost: false,
246
+ };
247
+ // Fetch room info
248
+ let roomEvents;
249
+ try {
250
+ roomEvents = await this.client.fetch({
251
+ kinds: [NOSTR_KINDS.ROOM],
252
+ '#d': [createRoomTag(this.config.gameId, roomId)],
253
+ limit: 1,
254
+ }, 5000);
255
+ }
256
+ catch (error) {
257
+ // Relay connection failed
258
+ const message = error instanceof Error ? error.message : String(error);
259
+ throw new Error(`Failed to connect to relays: ${message}`);
260
+ }
261
+ if (roomEvents.length === 0) {
262
+ throw new Error('Room not found');
263
+ }
264
+ let roomContent;
265
+ try {
266
+ roomContent = JSON.parse(roomEvents[0].content);
267
+ }
268
+ catch {
269
+ throw new Error('Invalid room data');
270
+ }
271
+ if (!roomContent.seed || !roomContent.hostPubkey) {
272
+ throw new Error('Invalid room data: missing required fields');
273
+ }
274
+ const roomCreatedAt = (roomEvents[0].created_at ?? 0) * 1000;
275
+ if (this.isExpired(roomCreatedAt)) {
276
+ throw new Error('Room has expired');
277
+ }
278
+ this._roomState = {
279
+ ...this._roomState,
280
+ seed: roomContent.seed,
281
+ status: 'ready',
282
+ createdAt: roomCreatedAt,
283
+ };
284
+ this._opponent = this.createInitialOpponent(roomContent.hostPubkey);
285
+ this.saveRoom({
286
+ roomId,
287
+ isHost: false,
288
+ seed: roomContent.seed,
289
+ createdAt: roomCreatedAt,
290
+ opponentPubkey: roomContent.hostPubkey,
291
+ });
292
+ // Send join event
293
+ await this.client.publish({
294
+ kind: NOSTR_KINDS.EPHEMERAL,
295
+ tags: [['d', createRoomTag(this.config.gameId, roomId)]],
296
+ content: JSON.stringify({
297
+ type: 'join',
298
+ playerPubkey: this.client.publicKey,
299
+ }),
300
+ });
301
+ this.subscribeToRoom(roomId);
302
+ }
303
+ /**
304
+ * Leave the current room
305
+ */
306
+ leave() {
307
+ this.unsubscribe?.();
308
+ this.unsubscribe = null;
309
+ this.stopHeartbeat();
310
+ this.stopDisconnectCheck();
311
+ this.clearRoom();
312
+ this._roomState = { ...INITIAL_ROOM_STATE };
313
+ this._opponent = null;
314
+ }
315
+ /**
316
+ * Attempt to reconnect to a previously joined room
317
+ */
318
+ async reconnect() {
319
+ const timeoutMs = this.config.joinTimeout ?? DEFAULT_CONFIG.joinTimeout;
320
+ try {
321
+ return await withTimeout(() => this.reconnectInternal(), timeoutMs, 'Reconnect operation timed out');
322
+ }
323
+ catch {
324
+ // Reset state on any error
325
+ this._roomState = { ...INITIAL_ROOM_STATE };
326
+ this._opponent = null;
327
+ this.clearRoom();
328
+ // Don't throw - return false to indicate reconnect failed
329
+ return false;
330
+ }
331
+ }
332
+ /**
333
+ * Internal reconnection logic
334
+ */
335
+ async reconnectInternal() {
336
+ const stored = this.loadRoom();
337
+ if (!stored)
338
+ return false;
339
+ if (!this.client.isConnected) {
340
+ this.client.connect();
341
+ }
342
+ this._roomState = {
343
+ roomId: stored.roomId,
344
+ status: 'joining',
345
+ isHost: stored.isHost,
346
+ seed: stored.seed,
347
+ createdAt: stored.createdAt,
348
+ };
349
+ if (stored.opponentPubkey) {
350
+ this._opponent = {
351
+ ...this.createInitialOpponent(stored.opponentPubkey),
352
+ isConnected: false,
353
+ lastHeartbeat: 0,
354
+ };
355
+ }
356
+ this.subscribeToRoom(stored.roomId);
357
+ // Announce reconnection
358
+ await this.client.publish({
359
+ kind: NOSTR_KINDS.EPHEMERAL,
360
+ tags: [['d', createRoomTag(this.config.gameId, stored.roomId)]],
361
+ content: JSON.stringify({
362
+ type: 'join',
363
+ playerPubkey: this.client.publicKey,
364
+ }),
365
+ });
366
+ // Wait briefly then set final status
367
+ await new Promise((resolve) => setTimeout(resolve, 1000));
368
+ this._roomState = {
369
+ ...this._roomState,
370
+ status: stored.opponentPubkey ? 'ready' : 'waiting',
371
+ };
372
+ return true;
373
+ }
374
+ // ===========================================================================
375
+ // Game State
376
+ // ===========================================================================
377
+ /**
378
+ * Send game state to opponent (throttled)
379
+ */
380
+ sendState(state) {
381
+ const now = Date.now();
382
+ if (now - this.lastStateUpdate < this.config.stateThrottle)
383
+ return;
384
+ this.lastStateUpdate = now;
385
+ if (this._roomState.roomId) {
386
+ this.publishToRoom({ type: 'state', gameState: state });
387
+ }
388
+ }
389
+ /**
390
+ * Send game over event
391
+ */
392
+ sendGameOver(reason, finalScore) {
393
+ if (this._roomState.roomId) {
394
+ this.publishToRoom({
395
+ type: 'gameover',
396
+ reason,
397
+ finalScore,
398
+ winner: this._opponent?.publicKey ?? '',
399
+ });
400
+ this._roomState = { ...this._roomState, status: 'finished' };
401
+ }
402
+ }
403
+ /**
404
+ * Request a rematch
405
+ */
406
+ requestRematch() {
407
+ if (!this._roomState.roomId || this._roomState.status !== 'finished')
408
+ return;
409
+ this._roomState = { ...this._roomState, rematchRequested: true };
410
+ this.publishToRoom({ type: 'rematch', action: 'request' });
411
+ // If opponent already requested, accept immediately
412
+ if (this._opponent?.rematchRequested) {
413
+ this.acceptRematch();
414
+ }
415
+ }
416
+ /**
417
+ * Accept a rematch request
418
+ */
419
+ acceptRematch() {
420
+ if (!this._roomState.roomId)
421
+ return;
422
+ const newSeed = generateSeed();
423
+ this.publishToRoom({ type: 'rematch', action: 'accept', newSeed });
424
+ this.resetForRematch(newSeed);
425
+ }
426
+ // ===========================================================================
427
+ // Private: Event Handling
428
+ // ===========================================================================
429
+ subscribeToRoom(roomId) {
430
+ this.unsubscribe?.();
431
+ if (!this.client.isConnected) {
432
+ this.callbacks.onError?.(new Error('NostrClient not connected. Call connect() first.'));
433
+ return;
434
+ }
435
+ this.unsubscribe = this.client.subscribe([{ kinds: [NOSTR_KINDS.EPHEMERAL], '#d': [createRoomTag(this.config.gameId, roomId)] }], (event) => {
436
+ try {
437
+ this.handleRoomEvent(event);
438
+ }
439
+ catch (error) {
440
+ this.callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));
441
+ }
442
+ });
443
+ this.startHeartbeat();
444
+ this.startDisconnectCheck();
445
+ }
446
+ handleRoomEvent(event) {
447
+ if (event.pubkey === this.client.publicKey)
448
+ return;
449
+ try {
450
+ const content = JSON.parse(event.content);
451
+ switch (content.type) {
452
+ case 'join':
453
+ this._opponent = this.createInitialOpponent(content.playerPubkey);
454
+ this._roomState = { ...this._roomState, status: 'ready' };
455
+ this.callbacks.onOpponentJoin?.(content.playerPubkey);
456
+ if (this._roomState.roomId) {
457
+ this.saveRoom({
458
+ roomId: this._roomState.roomId,
459
+ isHost: this._roomState.isHost,
460
+ seed: this._roomState.seed,
461
+ createdAt: this._roomState.createdAt ?? Date.now(),
462
+ opponentPubkey: content.playerPubkey,
463
+ });
464
+ }
465
+ break;
466
+ case 'state':
467
+ if (this._opponent) {
468
+ this._opponent = {
469
+ ...this._opponent,
470
+ gameState: content.gameState,
471
+ lastHeartbeat: Date.now(),
472
+ isConnected: true,
473
+ };
474
+ this.callbacks.onOpponentState?.(content.gameState);
475
+ }
476
+ break;
477
+ case 'gameover':
478
+ this._roomState = { ...this._roomState, status: 'finished', rematchRequested: false };
479
+ if (this._opponent) {
480
+ this._opponent = { ...this._opponent, rematchRequested: false };
481
+ }
482
+ this.callbacks.onOpponentGameOver?.(content.reason, content.finalScore);
483
+ break;
484
+ case 'heartbeat':
485
+ if (this._opponent) {
486
+ this._opponent = {
487
+ ...this._opponent,
488
+ lastHeartbeat: content.timestamp,
489
+ isConnected: true,
490
+ };
491
+ }
492
+ break;
493
+ case 'rematch':
494
+ if (content.action === 'request') {
495
+ if (this._opponent) {
496
+ this._opponent = { ...this._opponent, rematchRequested: true };
497
+ }
498
+ this.callbacks.onRematchRequested?.();
499
+ }
500
+ else if (content.action === 'accept' && content.newSeed) {
501
+ this.resetForRematch(content.newSeed);
502
+ }
503
+ break;
504
+ }
505
+ }
506
+ catch (e) {
507
+ console.error('Failed to parse room event:', e);
508
+ this.callbacks.onError?.(e instanceof Error ? e : new Error(String(e)));
509
+ }
510
+ }
511
+ // ===========================================================================
512
+ // Private: Heartbeat & Disconnect Detection
513
+ // ===========================================================================
514
+ startHeartbeat() {
515
+ if (this.heartbeatInterval)
516
+ return;
517
+ this.heartbeatInterval = setInterval(() => {
518
+ if (this._roomState.roomId) {
519
+ this.publishToRoom({ type: 'heartbeat', timestamp: Date.now() });
520
+ }
521
+ }, this.config.heartbeatInterval);
522
+ }
523
+ stopHeartbeat() {
524
+ if (this.heartbeatInterval) {
525
+ clearInterval(this.heartbeatInterval);
526
+ this.heartbeatInterval = null;
527
+ }
528
+ }
529
+ startDisconnectCheck() {
530
+ if (this.disconnectCheckInterval)
531
+ return;
532
+ this.disconnectCheckInterval = setInterval(() => {
533
+ if (!this._opponent?.lastHeartbeat)
534
+ return;
535
+ const timeSince = Date.now() - this._opponent.lastHeartbeat;
536
+ if (timeSince > this.config.disconnectThreshold && this._opponent.isConnected) {
537
+ this._opponent = { ...this._opponent, isConnected: false };
538
+ this.callbacks.onOpponentDisconnect?.();
539
+ }
540
+ }, 1000);
541
+ }
542
+ stopDisconnectCheck() {
543
+ if (this.disconnectCheckInterval) {
544
+ clearInterval(this.disconnectCheckInterval);
545
+ this.disconnectCheckInterval = null;
546
+ }
547
+ }
548
+ // ===========================================================================
549
+ // Private: Helpers
550
+ // ===========================================================================
551
+ publishToRoom(content) {
552
+ if (!this._roomState.roomId)
553
+ return;
554
+ this.client
555
+ .publish({
556
+ kind: NOSTR_KINDS.EPHEMERAL,
557
+ tags: [['d', createRoomTag(this.config.gameId, this._roomState.roomId)]],
558
+ content: JSON.stringify(content),
559
+ })
560
+ .catch((e) => {
561
+ console.error('Failed to publish:', e);
562
+ this.callbacks.onError?.(e instanceof Error ? e : new Error(String(e)));
563
+ });
564
+ }
565
+ createInitialOpponent(publicKey) {
566
+ return {
567
+ publicKey,
568
+ gameState: null,
569
+ isConnected: true,
570
+ lastHeartbeat: Date.now(),
571
+ rematchRequested: false,
572
+ };
573
+ }
574
+ resetForRematch(newSeed) {
575
+ this._roomState = {
576
+ ...this._roomState,
577
+ seed: newSeed,
578
+ status: 'ready',
579
+ rematchRequested: false,
580
+ };
581
+ if (this._opponent) {
582
+ this._opponent = {
583
+ ...this._opponent,
584
+ gameState: null,
585
+ rematchRequested: false,
586
+ };
587
+ }
588
+ this.callbacks.onRematchStart?.(newSeed);
589
+ }
590
+ // ===========================================================================
591
+ // Private: Storage
592
+ // ===========================================================================
593
+ get storageKey() {
594
+ return `${this.config.gameId}-room`;
595
+ }
596
+ saveRoom(data) {
597
+ try {
598
+ this.storage.setItem(this.storageKey, JSON.stringify(data));
599
+ }
600
+ catch (error) {
601
+ // Storage error (quota exceeded, etc.) - log but don't throw
602
+ console.warn('Failed to save room data:', error);
603
+ }
604
+ }
605
+ loadRoom() {
606
+ try {
607
+ const stored = this.storage.getItem(this.storageKey);
608
+ if (!stored)
609
+ return null;
610
+ const data = JSON.parse(stored);
611
+ if (this.isExpired(data.createdAt)) {
612
+ this.clearRoom();
613
+ return null;
614
+ }
615
+ return data;
616
+ }
617
+ catch {
618
+ // Storage or parse error - treat as no saved room
619
+ return null;
620
+ }
621
+ }
622
+ clearRoom() {
623
+ try {
624
+ this.storage.removeItem(this.storageKey);
625
+ }
626
+ catch {
627
+ // Ignore storage errors
628
+ }
629
+ }
630
+ isExpired(createdAt) {
631
+ return Date.now() - createdAt > this.config.roomExpiry;
632
+ }
633
+ }
634
+ //# sourceMappingURL=Arena.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Arena.js","sourceRoot":"","sources":["../../src/core/Arena.ts"],"names":[],"mappings":"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"}