modd-network 1.0.3 → 1.0.6

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.
@@ -97,7 +97,7 @@ export interface Game {
97
97
  processInput(input: any): void;
98
98
  }
99
99
  declare function createStateSync(options?: StateSyncConfig): GameInternal;
100
- export declare function connect(appId: string, room: string, options?: GameConnectOptions): Promise<Game>;
100
+ export declare function connect(room: string, options?: GameConnectOptions): Promise<Game>;
101
101
  export declare function rapierAdapter(body: any): PhysicsAdapter;
102
102
  export declare function generic2DAdapter(getBody: () => any, setBody: (state: any) => void): PhysicsAdapter;
103
103
  interface InitOptions {
@@ -489,7 +489,7 @@ function createStateSync(options = {}) {
489
489
  // ============================================
490
490
  // Main Connect Function
491
491
  // ============================================
492
- async function connect(appId, room, options = {}) {
492
+ async function connect(room, options = {}) {
493
493
  // Create the game/state sync object
494
494
  const game = createStateSync(options.stateSync);
495
495
  // Set up onTick to process inputs
@@ -506,7 +506,7 @@ async function connect(appId, room, options = {}) {
506
506
  },
507
507
  };
508
508
  // Connect to network
509
- const connection = await (0, modd_network_1.connect)(appId, room, gameOptions);
509
+ const connection = await (0, modd_network_1.connect)(room, gameOptions);
510
510
  game.setConnection(connection);
511
511
  // Return public interface (without setConnection)
512
512
  return game;
@@ -42,6 +42,7 @@ export interface Connection {
42
42
  }
43
43
  export interface ConnectOptions {
44
44
  snapshot?: any;
45
+ appId?: string;
45
46
  user?: any;
46
47
  centralServiceUrl?: string;
47
48
  nodeUrl?: string;
@@ -69,5 +70,5 @@ export interface DecodedMessage {
69
70
  }
70
71
  export declare function encodeSyncHash(roomId: string, hash: string, seq: number, frame: number): Uint8Array;
71
72
  export declare function decodeBinaryMessage(buffer: ArrayBuffer): DecodedMessage | null;
72
- export declare function connect(appId: string, roomId: string, options?: ConnectOptions): Promise<Connection>;
73
+ export declare function connect(roomId: string, options?: ConnectOptions): Promise<Connection>;
73
74
  export declare const modd: typeof connect;
@@ -253,7 +253,7 @@ async function toArrayBuffer(data) {
253
253
  return await data.arrayBuffer();
254
254
  return new Uint8Array(data).buffer;
255
255
  }
256
- async function connect(appId, roomId, options = {}) {
256
+ async function connect(roomId, options = {}) {
257
257
  const initialSnapshot = options.snapshot || {};
258
258
  const user = options.user || null;
259
259
  const onConnect = options.onConnect || (() => { });
@@ -262,6 +262,7 @@ async function connect(appId, roomId, options = {}) {
262
262
  const onMessage = options.onMessage || (() => { });
263
263
  const onTick = options.onTick || null;
264
264
  const getStateHash = options.getStateHash || null;
265
+ const appId = options.appId || 'test-app';
265
266
  const centralServiceUrl = options.centralServiceUrl || (typeof window !== 'undefined' && (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1')
266
267
  ? 'http://localhost:9001'
267
268
  : 'https://nodes.modd.io');
@@ -285,24 +286,29 @@ async function connect(appId, roomId, options = {}) {
285
286
  let lastSyncFrame = 0;
286
287
  let currentFrame = 0;
287
288
  let myClientId = null;
288
- // Process events to auto-register clientIds from join/leave events
289
+ // Process events to auto-register clientIds from join/leave/disconnect/reconnect events
289
290
  // This is CRITICAL for binary TICK decoding - the hash lookup needs clientIds registered
290
291
  function processEventsForClientIds(events) {
291
292
  for (const event of events) {
292
293
  const data = event.data || {};
293
294
  const eventType = data.type || event.type;
294
- if (eventType === 'join') {
295
+ if (eventType === 'join' || eventType === 'reconnect') {
296
+ // Register clientId for new joins and reconnections
295
297
  const clientId = data.clientId || event.clientId;
296
298
  if (clientId) {
297
299
  registerClientId(clientId);
298
300
  }
299
301
  }
300
302
  else if (eventType === 'leave') {
303
+ // Only unregister on permanent leave (not disconnect)
304
+ // Disconnected members may reconnect with a new clientId
301
305
  const clientId = data.clientId || event.clientId;
302
306
  if (clientId) {
303
307
  unregisterClientId(clientId);
304
308
  }
305
309
  }
310
+ // Note: 'disconnect' events do NOT unregister the clientId
311
+ // The member is still part of the room, just temporarily offline
306
312
  }
307
313
  }
308
314
  try {
@@ -378,11 +384,14 @@ async function connect(appId, roomId, options = {}) {
378
384
  }
379
385
  },
380
386
  leaveRoom() {
381
- if (connected && user && ws) {
382
- const msg = JSON.stringify({ type: 'SEND_INPUT', payload: { roomId, data: { type: 'leave', user } } });
387
+ if (connected && ws) {
388
+ // Send proper LEAVE_ROOM message to permanently exit the room
389
+ // This broadcasts a "leave" event to other clients
390
+ const msg = JSON.stringify({ type: 'LEAVE_ROOM', payload: { roomId } });
383
391
  bytesOut += msg.length;
384
392
  ws.send(msg);
385
393
  }
394
+ // Close the WebSocket after sending leave message
386
395
  if (ws)
387
396
  ws.close();
388
397
  },
@@ -461,7 +470,7 @@ async function connect(appId, roomId, options = {}) {
461
470
  }
462
471
  bytesIn += buffer.byteLength;
463
472
  const msg = decodeBinaryMessage(buffer);
464
- console.log("decoded msg: ", msg);
473
+ // console.log("decoded msg: ", msg);
465
474
  if (!msg)
466
475
  return;
467
476
  switch (msg.type) {
@@ -528,6 +537,9 @@ async function connect(appId, roomId, options = {}) {
528
537
  const maxSeq = Math.max(...events.map(e => e.seq || 0));
529
538
  if (maxSeq > lastSyncSeq)
530
539
  lastSyncSeq = maxSeq;
540
+ // CRITICAL: Mark all INITIAL_STATE events as delivered
541
+ // to prevent duplicate processing when same events arrive via TICK
542
+ events.forEach(e => deliveredSeqs.add(e.seq));
531
543
  }
532
544
  // Auto-register clientIds from join events in history
533
545
  if (events && events.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modd-network",
3
- "version": "1.0.3",
3
+ "version": "1.0.6",
4
4
  "description": "SDK for connecting to mesh network for multiplayer applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/README.md DELETED
@@ -1,40 +0,0 @@
1
- # MODD Network SDK
2
-
3
- The official SDK for connecting to the MODD mesh network for multiplayer applications.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install modd-network
9
- ```
10
-
11
- ## Usage
12
-
13
- ```typescript
14
- import { modd } from 'modd-network';
15
-
16
- // Connect to a room
17
- const connection = await modd('my-room-id', {
18
- appId: 'your-app-id',
19
- onConnect: (snapshot, inputs) => {
20
- console.log('Connected with snapshot:', snapshot);
21
- },
22
- onTick: (frame, inputs) => {
23
- console.log('Tick:', frame, inputs);
24
- },
25
- onDisconnect: () => {
26
- console.log('Disconnected');
27
- }
28
- });
29
-
30
- // Send input
31
- connection.send({ x: 10, y: 20 });
32
- ```
33
-
34
- ## Features
35
-
36
- - Room creation and joining
37
- - Real-time input synchronization (Binary protocol)
38
- - Snapshot state management
39
- - Game engine utilities (Physics sync, Delta compression)
40
- - Mesh network connectivity (Browser & Node.js)