@sanctumterra/raknet 1.4.12 → 1.4.14

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 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,YAAY,EAWZ,QAAQ,EAIR,KAAK,KAAK,EAKV,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EACN,KAAK,aAAa,EAElB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAgB,KAAK,UAAU,EAAe,MAAM,YAAY,CAAC;AAKxE,qBAAa,MAAO,SAAQ,YAAY,CAAC,YAAY,CAAC;IACrD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAiC;IACnE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAO;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAO;IAE3C,OAAO,EAAE,aAAa,CAAC;IAC9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,MAAM,CAAmB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,gBAAgB,CAAsB;IAC9C,OAAO,CAAC,cAAc,CAAS;gBAEnB,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM;YAmBlC,UAAU;IAoGxB,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,iBAAiB;IAuBzB,OAAO,CAAC,qBAAqB;IA4B7B,OAAO,CAAC,oBAAoB;IA2Bf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiD9B,MAAM,IAAI,IAAI;IA6BrB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,OAAO;IAgBR,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IAmEhD,YAAY,CAAC,IAAI,EAAE,MAAM;IAkDzB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,GAAE,QAA0B;IAI5D,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,QAA0B;IAI/D,IAAI,IAAI,IAAI;IAOZ,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAWxB,UAAU,IAAI,IAAI;CAWzB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,YAAY,EAWZ,QAAQ,EAIR,KAAK,KAAK,EAKV,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EACN,KAAK,aAAa,EAElB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAgB,KAAK,UAAU,EAAe,MAAM,YAAY,CAAC;AAKxE,qBAAa,MAAO,SAAQ,YAAY,CAAC,YAAY,CAAC;IACrD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAiC;IACnE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAO;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAO;IAE3C,OAAO,EAAE,aAAa,CAAC;IAC9B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,MAAM,CAAmB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,gBAAgB,CAAsB;IAC9C,OAAO,CAAC,cAAc,CAAS;gBAEnB,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM;YAmBlC,UAAU;IAoGxB,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,iBAAiB;IAuBzB,OAAO,CAAC,qBAAqB;IA4B7B,OAAO,CAAC,oBAAoB;IA2Bf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA6D9B,MAAM,IAAI,IAAI;IA6BrB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,OAAO;IAgBR,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IAoEhD,YAAY,CAAC,IAAI,EAAE,MAAM;IAiDzB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,GAAE,QAA0B;IAI5D,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,QAA0B;IAI/D,IAAI,IAAI,IAAI;IAOZ,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAWxB,UAAU,IAAI,IAAI;CAWzB"}
@@ -36,7 +36,7 @@ class Client extends shared_1.EventEmitter {
36
36
  this.socket.bind();
37
37
  this.interval = setInterval(this.onTick.bind(this), 1000 / this.options.tickRate);
38
38
  this.socket.on("message", this.onMessage.bind(this));
39
- this.session = new shared_1.NetworkSession(this.options.mtu);
39
+ this.session = new shared_1.NetworkSession(this.options.mtu, this.options.debug);
40
40
  this.session.send = this.send.bind(this);
41
41
  this.session.handle = (data) => {
42
42
  this.handleOnline(data);
@@ -207,15 +207,25 @@ class Client extends shared_1.EventEmitter {
207
207
  }
208
208
  this.status = shared_1.ConnectionStatus.Connecting;
209
209
  this.gotReply1 = false;
210
+ // Reset session state for fresh connection
211
+ this.session = new shared_1.NetworkSession(this.options.mtu, this.options.debug);
212
+ this.session.send = this.send.bind(this);
213
+ this.session.handle = (data) => {
214
+ this.handleOnline(data);
215
+ };
210
216
  return new Promise((resolve, reject) => {
211
217
  let mtuIndex = 0;
212
218
  let retryTimeout = null;
219
+ // Use configured MTU or fall back to default values
220
+ const mtuValues = this.options.mtu
221
+ ? [this.options.mtu]
222
+ : Client.MTU_VALUES;
213
223
  const sendRequest = () => {
214
- if (mtuIndex >= Client.MTU_VALUES.length) {
224
+ if (mtuIndex >= mtuValues.length) {
215
225
  reject(new Error("Connection timed out, all MTU values exhausted"));
216
226
  return;
217
227
  }
218
- const mtu = Client.MTU_VALUES[mtuIndex];
228
+ const mtu = mtuValues[mtuIndex];
219
229
  if (!mtu)
220
230
  throw new Error("MTU value is undefined");
221
231
  const request = new shared_1.OpenConnectionRequestOne();
@@ -330,6 +340,7 @@ class Client extends shared_1.EventEmitter {
330
340
  case shared_1.Packets.OpenConnectionReply2: {
331
341
  const reply2 = new shared_1.OpenConnectionReplyTwo(actualData).deserialize();
332
342
  // Update session MTU with the negotiated value from server
343
+ shared_2.Logger.info(`MTU negotiated: ${reply2.mtu} (was ${this.session.mtu})`);
333
344
  this.session.mtu = reply2.mtu;
334
345
  const request = new shared_1.ConnectionRequest();
335
346
  request.guid = this.options.guid;
@@ -396,7 +407,6 @@ class Client extends shared_1.EventEmitter {
396
407
  this.lastPongTime = Date.now(); // Reset stale timer on connect
397
408
  this.lastActivityTime = Date.now();
398
409
  this.emit("connect");
399
- console.log("Raknet Connected");
400
410
  break;
401
411
  }
402
412
  default: {
@@ -13,6 +13,7 @@ export type ClientOptions = {
13
13
  pingRate: number;
14
14
  timeout: number;
15
15
  proxy?: ProxyOptions;
16
+ debug: boolean;
16
17
  };
17
18
  export declare const generateGuid: () => bigint;
18
19
  export declare const createDefaultClientOptions: () => ClientOptions;
@@ -1 +1 @@
1
- {"version":3,"file":"client-options.d.ts","sourceRoot":"","sources":["../../../src/client/types/client-options.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,YAAY,QAAO,MAC0B,CAAC;AAE3D,eAAO,MAAM,0BAA0B,QAAO,aAQ5C,CAAC"}
1
+ {"version":3,"file":"client-options.d.ts","sourceRoot":"","sources":["../../../src/client/types/client-options.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,YAAY,QAAO,MAC0B,CAAC;AAE3D,eAAO,MAAM,0BAA0B,QAAO,aAS5C,CAAC"}
@@ -11,5 +11,6 @@ const createDefaultClientOptions = () => ({
11
11
  tickRate: 20,
12
12
  pingRate: 40,
13
13
  timeout: 30000,
14
+ debug: false,
14
15
  });
15
16
  exports.createDefaultClientOptions = createDefaultClientOptions;
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/server/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,GAAG,EAOR,YAAY,EACZ,KAAK,KAAK,EACV,KAAK,QAAQ,EAIb,QAAQ,EACR,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,qBAAa,UAAW,SAAQ,YAAY,CAAC,gBAAgB,CAAC;IAS5D,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,IAAI;IAXb,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAO;IAElD,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,gBAAgB,CAAsB;IAC9C,OAAO,CAAC,cAAc,CAAS;gBAGtB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM;IAQd,MAAM,CAAC,IAAI,EAAE,MAAM;IAoBnB,UAAU,CAAC,MAAM,SAAiB,GAAG,IAAI;IAYzC,OAAO,IAAI,OAAO;IAIlB,UAAU,CAAC,QAAQ,EAAE,QAAQ;IAK7B,UAAU,IAAI,UAAU;IAIxB,SAAS,CAAC,IAAI,EAAE,MAAM;IA8DtB,KAAK,CAAC,OAAO,EAAE,GAAG;IAIzB,uFAAuF;IAChF,MAAM,CAAC,OAAO,EAAE,GAAG;IAInB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,GAAE,QAAwB;IAI1D,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,QAAwB;IAIhE,IAAI,CAAC,IAAI,EAAE,MAAM;CAGxB"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/server/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,GAAG,EAOR,YAAY,EACZ,KAAK,KAAK,EACV,KAAK,QAAQ,EAIb,QAAQ,EACR,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,qBAAa,UAAW,SAAQ,YAAY,CAAC,gBAAgB,CAAC;IAS5D,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,IAAI;IAXb,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAO;IAElD,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,gBAAgB,CAAsB;IAC9C,OAAO,CAAC,cAAc,CAAS;gBAGtB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM;IAWd,MAAM,CAAC,IAAI,EAAE,MAAM;IAoBnB,UAAU,CAAC,MAAM,SAAiB,GAAG,IAAI;IAYzC,OAAO,IAAI,OAAO;IAIlB,UAAU,CAAC,QAAQ,EAAE,QAAQ;IAK7B,UAAU,IAAI,UAAU;IAIxB,SAAS,CAAC,IAAI,EAAE,MAAM;IA8DtB,KAAK,CAAC,OAAO,EAAE,GAAG;IAIzB,uFAAuF;IAChF,MAAM,CAAC,OAAO,EAAE,GAAG;IAInB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,GAAE,QAAwB;IAI1D,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,QAAwB;IAIhE,IAAI,CAAC,IAAI,EAAE,MAAM;CAGxB"}
@@ -18,7 +18,7 @@ class Connection extends shared_1.EventEmitter {
18
18
  this.rinfo = rinfo;
19
19
  this.mtu = mtu;
20
20
  this.guid = guid;
21
- this.session = new shared_1.NetworkSession(this.mtu);
21
+ this.session = new shared_1.NetworkSession(this.mtu, this.server.options.enableServerLogs);
22
22
  this.session.send = this.send.bind(this);
23
23
  this.session.handle = this.onMessage.bind(this);
24
24
  }
@@ -1,6 +1,7 @@
1
1
  import { Ack, Frame, FrameSet, Priority } from "./proto";
2
2
  export declare class NetworkSession {
3
3
  mtu: number;
4
+ debug: boolean;
4
5
  send: (data: Buffer) => void;
5
6
  handle: (data: Buffer) => void;
6
7
  outputReliableIndex: number;
@@ -27,13 +28,18 @@ export declare class NetworkSession {
27
28
  private static readonly RELIABLE_WINDOW_SIZE;
28
29
  private static readonly FRAGMENT_TIMEOUT_MS;
29
30
  private static readonly ORDER_QUEUE_MAX_SIZE;
30
- constructor(mtu: number);
31
+ private static readonly ORDER_QUEUE_SKIP_THRESHOLD;
32
+ constructor(mtu: number, debug?: boolean);
31
33
  onTick(_tick?: number): void;
32
34
  onAck(ack: Ack): void;
33
35
  onNack(nack: Ack): void;
34
36
  frameAndSend(data: Buffer, priority?: Priority): void;
35
37
  sendFrame(frame: Frame, priority?: Priority): void;
36
38
  queueFrame(frame: Frame, priority: Priority): void;
39
+ /**
40
+ * Send split frames - each in its own frameset with small delays to ensure ordering
41
+ */
42
+ sendSplitFrames(frames: Frame[], priority: Priority): void;
37
43
  sendQueue(amount: number): void;
38
44
  onFrameSet(frameSet: FrameSet): void;
39
45
  handleFrame(frame: Frame): void;
@@ -1 +1 @@
1
- {"version":3,"file":"network_session.d.ts","sourceRoot":"","sources":["../../src/shared/network_session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAW,QAAQ,EAAe,MAAM,SAAS,CAAC;AAK/E,qBAAa,cAAc;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,MAAM,EAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAGhC,mBAAmB,SAAK;IACxB,gBAAgB,SAAK;IAC5B,SAAS,CAAC,cAAc,SAAK;IACtB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,CAAa;IACrC,YAAY,uBAA8B;IAG1C,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IAChD,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IAC5C,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IACrC,iBAAiB,SAAM;IACvB,cAAc,EAAE,GAAG,CACzB,MAAM,EACN;QAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CACjD,CAAa;IACP,yBAAyB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtC,SAAS,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAa;IAE1E,OAAO,CAAC,4BAA4B,CAA0B;IAC9D,OAAO,CAAC,oBAAoB,CAAM;IAGlC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAQ;IACnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAQ;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAO;gBAEvC,GAAG,EAAE,MAAM;IAUvB,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM;IAsDrB,KAAK,CAAC,GAAG,EAAE,GAAG;IAMd,MAAM,CAAC,IAAI,EAAE,GAAG;IAeT,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,QAA0B;IAQ/D,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,GAAE,QAA0B;IA8C5D,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ;IAW3C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAiB/B,UAAU,CAAC,QAAQ,EAAE,QAAQ;IAgD7B,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAwB/B,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IA0CpC,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAenC,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;CAwCxC"}
1
+ {"version":3,"file":"network_session.d.ts","sourceRoot":"","sources":["../../src/shared/network_session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAW,QAAQ,EAAe,MAAM,SAAS,CAAC;AAK/E,qBAAa,cAAc;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,MAAM,EAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAGhC,mBAAmB,SAAK;IACxB,gBAAgB,SAAK;IAC5B,SAAS,CAAC,cAAc,SAAK;IACtB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,CAAa;IACrC,YAAY,uBAA8B;IAG1C,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IAChD,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IAC5C,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IACrC,iBAAiB,SAAM;IACvB,cAAc,EAAE,GAAG,CACzB,MAAM,EACN;QAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CACjD,CAAa;IACP,yBAAyB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtC,SAAS,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAa;IAE1E,OAAO,CAAC,4BAA4B,CAA0B;IAC9D,OAAO,CAAC,oBAAoB,CAAM;IAGlC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAQ;IACnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAQ;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAQ;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,0BAA0B,CAAO;gBAE7C,GAAG,EAAE,MAAM,EAAE,KAAK,UAAQ;IAWtC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM;IAuDrB,KAAK,CAAC,GAAG,EAAE,GAAG;IAOd,MAAM,CAAC,IAAI,EAAE,GAAG;IAkBT,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,QAA0B;IAQ/D,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,GAAE,QAA0B;IAmD5D,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ;IAclD;;OAEG;IACI,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ;IA6BnD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IA0B/B,UAAU,CAAC,QAAQ,EAAE,QAAQ;IAkD7B,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAwB/B,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IA2CpC,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAenC,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;CAwDxC"}
@@ -7,6 +7,7 @@ const logger_1 = require("./logger");
7
7
  const MTU_HEADER_SIZE = 36;
8
8
  class NetworkSession {
9
9
  mtu;
10
+ debug;
10
11
  send;
11
12
  handle;
12
13
  // Output
@@ -32,9 +33,11 @@ class NetworkSession {
32
33
  static RECEIVE_WINDOW_SIZE = 2048;
33
34
  static RELIABLE_WINDOW_SIZE = 4096;
34
35
  static FRAGMENT_TIMEOUT_MS = 30000;
35
- static ORDER_QUEUE_MAX_SIZE = 256;
36
- constructor(mtu) {
36
+ static ORDER_QUEUE_MAX_SIZE = 1024;
37
+ static ORDER_QUEUE_SKIP_THRESHOLD = 512;
38
+ constructor(mtu, debug = false) {
37
39
  this.mtu = mtu;
40
+ this.debug = debug;
38
41
  this.outputOrderIndex = new Array(32).fill(0);
39
42
  this.outputSequenceIndex = new Array(32).fill(0);
40
43
  this.inputHighestSequenceIndex = Array.from({ length: 32 }).fill(0);
@@ -64,7 +67,8 @@ class NetworkSession {
64
67
  }
65
68
  for (const [splitId, entry] of this.fragmentsQueue) {
66
69
  if (now - entry.timestamp > NetworkSession.FRAGMENT_TIMEOUT_MS) {
67
- logger_1.Logger.warn(`Fragment queue ${splitId} timed out, dropping ${entry.frames.size} fragments`);
70
+ if (this.debug)
71
+ logger_1.Logger.warn(`Fragment queue ${splitId} timed out, dropping ${entry.frames.size} fragments`);
68
72
  this.fragmentsQueue.delete(splitId);
69
73
  }
70
74
  }
@@ -89,11 +93,13 @@ class NetworkSession {
89
93
  this.sendQueue(size);
90
94
  }
91
95
  onAck(ack) {
96
+ logger_1.Logger.info(`ACK received: ${ack.sequences.join(", ")}`);
92
97
  for (let i = 0, len = ack.sequences.length; i < len; i++) {
93
98
  this.outputBackup.delete(ack.sequences[i]);
94
99
  }
95
100
  }
96
101
  onNack(nack) {
102
+ logger_1.Logger.info(`Received NACK for sequences: ${nack.sequences.join(", ")} - resending`);
97
103
  for (let i = 0, len = nack.sequences.length; i < len; i++) {
98
104
  const seq = nack.sequences[i];
99
105
  const lostFrames = this.outputBackup.get(seq);
@@ -129,6 +135,8 @@ class NetworkSession {
129
135
  if (payloadSize > maxSize) {
130
136
  const splitSize = Math.ceil(payloadSize / maxSize);
131
137
  const splitId = this.outputSplitIndex++ & 0xffff;
138
+ // Queue all split frames first
139
+ const splitFrames = [];
132
140
  for (let i = 0; i < splitSize; i++) {
133
141
  const index = i * maxSize;
134
142
  const nF = new proto_1.Frame();
@@ -143,8 +151,10 @@ class NetworkSession {
143
151
  nF.splitFrameIndex = i;
144
152
  nF.splitId = splitId;
145
153
  nF.splitSize = splitSize;
146
- this.queueFrame(nF, priority);
154
+ splitFrames.push(nF);
147
155
  }
156
+ // Send all split frames together in one batch
157
+ this.sendSplitFrames(splitFrames, priority);
148
158
  }
149
159
  else {
150
160
  if (frame.isReliable()) {
@@ -155,13 +165,39 @@ class NetworkSession {
155
165
  }
156
166
  queueFrame(frame, priority) {
157
167
  let length = 4;
158
- for (const frame of this.outputFrames)
159
- length += frame.getByteLength();
168
+ for (const f of this.outputFrames)
169
+ length += f.getByteLength();
160
170
  if (length + frame.getByteLength() > this.mtu - MTU_HEADER_SIZE)
161
171
  this.sendQueue(this.outputFrames.size);
162
172
  this.outputFrames.add(frame);
173
+ // For high priority, send all queued frames immediately (not just 1)
174
+ // This ensures split frames go out together
163
175
  if (priority === proto_1.Priority.High)
164
- this.sendQueue(1);
176
+ this.sendQueue(this.outputFrames.size);
177
+ }
178
+ /**
179
+ * Send split frames - each in its own frameset with small delays to ensure ordering
180
+ */
181
+ sendSplitFrames(frames, priority) {
182
+ logger_1.Logger.info(`Sending ${frames.length} split frames`);
183
+ // Send first frame immediately
184
+ const sendFrame = (index) => {
185
+ if (index >= frames.length)
186
+ return;
187
+ const frame = frames[index];
188
+ const frameset = new proto_1.FrameSet();
189
+ frameset.sequence = this.outputSequence++;
190
+ frameset.frames = [frame];
191
+ this.outputBackup.set(frameset.sequence, [frame]);
192
+ const buffer = frameset.serialize();
193
+ logger_1.Logger.info(`Split ${index + 1}/${frames.length} sent (seq: ${frameset.sequence}, size: ${buffer.length})`);
194
+ this.send(buffer);
195
+ // Send next frame after a small delay to ensure ordering
196
+ if (index + 1 < frames.length) {
197
+ setTimeout(() => sendFrame(index + 1), 5);
198
+ }
199
+ };
200
+ sendFrame(0);
165
201
  }
166
202
  sendQueue(amount) {
167
203
  if (this.outputFrames.size === 0)
@@ -172,6 +208,12 @@ class NetworkSession {
172
208
  this.outputBackup.set(frameset.sequence, frameset.frames);
173
209
  for (const frame of frameset.frames)
174
210
  this.outputFrames.delete(frame);
211
+ // Log what we're sending
212
+ for (const frame of frameset.frames) {
213
+ if (frame.isSplit()) {
214
+ logger_1.Logger.info(`Sending split frame ${frame.splitFrameIndex}/${frame.splitSize} (splitId: ${frame.splitId}, seq: ${frameset.sequence}, reliable: ${frame.reliableFrameIndex})`);
215
+ }
216
+ }
175
217
  const buffer = frameset.serialize();
176
218
  if (!this.send)
177
219
  throw new Error("Send method was not initialized");
@@ -180,7 +222,8 @@ class NetworkSession {
180
222
  onFrameSet(frameSet) {
181
223
  // Already received this exact sequence so ignore duplicate
182
224
  if (this.receivedFrameSequences.has(frameSet.sequence)) {
183
- logger_1.Logger.warn(`Duplicate frame set received: sequence ${frameSet.sequence}`);
225
+ if (this.debug)
226
+ logger_1.Logger.warn(`Duplicate frame set received: sequence ${frameSet.sequence}`);
184
227
  return;
185
228
  }
186
229
  // Remove from lost if we finally got it
@@ -204,7 +247,8 @@ class NetworkSession {
204
247
  }
205
248
  else {
206
249
  // zOut-of-order packet (arrived late but still valid)
207
- logger_1.Logger.warn(`Out-of-order frame set received: sequence ${frameSet.sequence} (expected > ${this.lastInputSequence})`);
250
+ if (this.debug)
251
+ logger_1.Logger.warn(`Out-of-order frame set received: sequence ${frameSet.sequence} (expected > ${this.lastInputSequence})`);
208
252
  }
209
253
  // Process all frames
210
254
  for (const frame of frameSet.frames) {
@@ -249,7 +293,8 @@ class NetworkSession {
249
293
  for (let index = 0; index < frame.splitSize; index++) {
250
294
  const sframe = entry.frames.get(index);
251
295
  if (!sframe) {
252
- logger_1.Logger.warn(`Missing fragment at index ${index} for splitId=${frame.splitId}`);
296
+ if (this.debug)
297
+ logger_1.Logger.warn(`Missing fragment at index ${index} for splitId=${frame.splitId}`);
253
298
  this.fragmentsQueue.delete(splitId);
254
299
  return;
255
300
  }
@@ -311,15 +356,28 @@ class NetworkSession {
311
356
  }
312
357
  }
313
358
  else if (frame.orderedFrameIndex > expectedOrderIndex) {
314
- // Future frame n queue it for later
359
+ const gap = frame.orderedFrameIndex - expectedOrderIndex;
360
+ // If we're way too far behind, skip ahead to avoid infinite queue buildup
361
+ if (gap > NetworkSession.ORDER_QUEUE_SKIP_THRESHOLD) {
362
+ if (this.debug)
363
+ logger_1.Logger.debug(`Order queue for channel ${channel} skipping ahead from ${expectedOrderIndex} to ${frame.orderedFrameIndex} (gap: ${gap})`);
364
+ // Clear the queue and skip to this frame
365
+ const outOfOrderQueue = this.inputOrderingQueue.get(channel);
366
+ if (outOfOrderQueue)
367
+ outOfOrderQueue.clear();
368
+ this.inputOrderIndex[channel] = frame.orderedFrameIndex + 1;
369
+ this.handle(frame.payload);
370
+ return;
371
+ }
372
+ // Future frame - queue it for later
315
373
  const outOfOrderQueue = this.inputOrderingQueue.get(channel);
316
374
  if (outOfOrderQueue) {
317
- // Prevent unbounded queue growth
318
375
  if (outOfOrderQueue.size < NetworkSession.ORDER_QUEUE_MAX_SIZE) {
319
376
  outOfOrderQueue.set(frame.orderedFrameIndex, frame);
320
377
  }
321
378
  else {
322
- logger_1.Logger.warn(`Order queue for channel ${channel} is full, dropping frame ${frame.orderedFrameIndex}`);
379
+ if (this.debug)
380
+ logger_1.Logger.debug(`Order queue for channel ${channel} is full, dropping frame ${frame.orderedFrameIndex}`);
323
381
  }
324
382
  }
325
383
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanctumterra/raknet",
3
- "version": "1.4.12",
3
+ "version": "1.4.14",
4
4
  "description": "",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=frame-reordering.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"frame-reordering.d.ts","sourceRoot":"","sources":["../../src/tests/frame-reordering.ts"],"names":[],"mappings":""}
@@ -1,48 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const shared_1 = require("../shared");
4
- // Enable debug logging to see the reordering in action
5
- shared_1.Logger.debugEnabled = true;
6
- // Create a test network session``
7
- const session = new shared_1.NetworkSession(1400);
8
- session.send = (data) => {
9
- console.log(`Would send ${data.length} bytes`);
10
- };
11
- session.handle = (data) => {
12
- console.log(`✓ Processed frame: "${data.toString()}"`);
13
- };
14
- // Create test frame sets with out-of-order sequences
15
- function createTestFrameSet(sequence, orderedIndex, message) {
16
- const frameSet = new shared_1.FrameSet();
17
- frameSet.sequence = sequence;
18
- const frame = new shared_1.Frame();
19
- frame.reliability = shared_1.Reliability.ReliableOrdered;
20
- frame.orderChannel = 0;
21
- frame.orderedFrameIndex = orderedIndex; // Set the ordered index
22
- frame.reliableFrameIndex = sequence; // Set reliable index
23
- frame.payload = Buffer.from(message);
24
- frameSet.frames = [frame];
25
- return frameSet;
26
- }
27
- console.log("Testing frame reordering system...\n");
28
- // Simulate receiving frames out of order (starting from 0)
29
- const frames = [
30
- createTestFrameSet(0, 0, "First frame"),
31
- createTestFrameSet(2, 2, "Third frame (out of order)"),
32
- createTestFrameSet(1, 1, "Second frame (fills gap)"),
33
- createTestFrameSet(4, 4, "Fifth frame (way ahead)"),
34
- createTestFrameSet(3, 3, "Fourth frame (fills another gap)"),
35
- ];
36
- // Process frames in the wrong order to test reordering
37
- console.log("Receiving frames in order: 0, 2, 1, 4, 3");
38
- console.log("Expected processing order: 0, 1, 2, 3, 4\n");
39
- for (const frame of frames) {
40
- console.log(`\n--- Receiving frame set ${frame.sequence} ---`);
41
- try {
42
- session.onFrameSet(frame);
43
- }
44
- catch (error) {
45
- console.error(`Error processing frame ${frame.sequence}:`, error);
46
- }
47
- }
48
- console.log("\nTest completed!");