baltica 2.0.9 → 2.0.10

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.
@@ -13,6 +13,7 @@ export declare class Client extends Emitter<ClientEvents> {
13
13
  loginData: LoginData;
14
14
  stopPastLogin: boolean;
15
15
  startGameData: StartGamePacket;
16
+ private isDisconnected;
16
17
  constructor(options: Partial<ClientOptions>);
17
18
  connect(): Promise<void>;
18
19
  private registerHandshakeHandlers;
@@ -20,6 +20,7 @@ class Client extends utils_1.Emitter {
20
20
  loginData;
21
21
  stopPastLogin = false;
22
22
  startGameData;
23
+ isDisconnected = false;
23
24
  constructor(options) {
24
25
  super();
25
26
  this.options = { ...types_1.defaultClientOptions, ...options };
@@ -145,6 +146,9 @@ class Client extends utils_1.Emitter {
145
146
  this.removeAllListeners();
146
147
  }
147
148
  disconnect(reason = "client disconnect") {
149
+ if (this.isDisconnected)
150
+ return;
151
+ this.isDisconnected = true;
148
152
  this.emit("disconnect", reason);
149
153
  setTimeout(() => {
150
154
  if (this.raknet && typeof this.raknet.disconnect === "function") {
@@ -225,6 +229,8 @@ class Client extends utils_1.Emitter {
225
229
  this.sendUncompressed(request.serialize(), raknet_1.Priority.High);
226
230
  }
227
231
  send(packet, priority = raknet_1.Priority.Medium, compressionMethod) {
232
+ if (this.isDisconnected)
233
+ return;
228
234
  try {
229
235
  const compressed = this.packetCompressor.compress(packet, compressionMethod);
230
236
  this.raknet.sendReliable(compressed, priority);
@@ -11,6 +11,7 @@ export declare class Player extends Emitter<PlayerEvents> {
11
11
  connection: Connection;
12
12
  username: string;
13
13
  xuid: string;
14
+ private isDisconnected;
14
15
  private privateKey;
15
16
  private publicKeyDER;
16
17
  private clientX509;
@@ -51,6 +51,7 @@ class Player extends utils_1.Emitter {
51
51
  connection;
52
52
  username = "";
53
53
  xuid = "";
54
+ isDisconnected = false;
54
55
  privateKey;
55
56
  publicKeyDER;
56
57
  clientX509;
@@ -184,6 +185,8 @@ class Player extends utils_1.Emitter {
184
185
  }
185
186
  }
186
187
  send(packet, priority = raknet_1.Priority.High, compressionMethod) {
188
+ if (this.isDisconnected)
189
+ return;
187
190
  try {
188
191
  const compressed = this.packetCompressor.compress(packet, compressionMethod);
189
192
  this.connection.send(compressed, priority);
@@ -203,6 +206,9 @@ class Player extends utils_1.Emitter {
203
206
  this.connection.send(buf, priority);
204
207
  }
205
208
  disconnect(reason = "disconnected") {
209
+ if (this.isDisconnected)
210
+ return;
211
+ this.isDisconnected = true;
206
212
  utils_1.Logger.info(`Disconnecting ${this.username || "player"}: ${reason}`);
207
213
  this.connection.disconnect();
208
214
  this.emit("disconnect");
@@ -67,26 +67,45 @@ class PacketEncryptor {
67
67
  return Buffer.from(new Uint8Array(hash.subarray(0, 8)));
68
68
  }
69
69
  encryptPacket(payload) {
70
- if (!this.cipher)
71
- throw new Error("Cipher not initialized");
72
- const checksum = this.computeCheckSum(payload, this.sendCounter);
73
- const toEncrypt = Buffer.concat([payload, checksum]);
74
- const encrypted = this.cipher.update(toEncrypt);
75
- this.sendCounter++;
76
- return Buffer.concat([Buffer.from([0xfe]), encrypted]);
70
+ if (!this.cipher) {
71
+ // Cipher destroyed - return unencrypted
72
+ return Buffer.concat([Buffer.from([0xfe]), payload]);
73
+ }
74
+ try {
75
+ const checksum = this.computeCheckSum(payload, this.sendCounter);
76
+ const toEncrypt = Buffer.concat([payload, checksum]);
77
+ const encrypted = this.cipher.update(toEncrypt);
78
+ this.sendCounter++;
79
+ return Buffer.concat([Buffer.from([0xfe]), encrypted]);
80
+ }
81
+ catch {
82
+ // Cipher in invalid state - return unencrypted
83
+ return Buffer.concat([Buffer.from([0xfe]), payload]);
84
+ }
77
85
  }
78
86
  decryptPacket(encryptedPayload) {
79
- if (!this.decipher)
80
- throw new Error("Decipher not initialized");
81
- const decrypted = this.decipher.update(encryptedPayload);
82
- const packet = decrypted.subarray(0, decrypted.length - 8);
83
- const receivedChecksum = decrypted.subarray(decrypted.length - 8);
84
- const computedChecksum = this.computeCheckSum(packet, this.receiveCounter);
85
- this.receiveCounter++;
86
- if (!receivedChecksum.equals(computedChecksum)) {
87
- throw new Error("Checksum mismatch");
87
+ if (!this.decipher) {
88
+ // Decipher destroyed - return as-is
89
+ return encryptedPayload;
90
+ }
91
+ try {
92
+ const decrypted = this.decipher.update(encryptedPayload);
93
+ const packet = decrypted.subarray(0, decrypted.length - 8);
94
+ const receivedChecksum = decrypted.subarray(decrypted.length - 8);
95
+ const computedChecksum = this.computeCheckSum(packet, this.receiveCounter);
96
+ this.receiveCounter++;
97
+ if (!receivedChecksum.equals(computedChecksum)) {
98
+ throw new Error("Checksum mismatch");
99
+ }
100
+ return packet;
101
+ }
102
+ catch (err) {
103
+ // Re-throw checksum errors, ignore cipher state errors
104
+ if (err instanceof Error && err.message === "Checksum mismatch") {
105
+ throw err;
106
+ }
107
+ return encryptedPayload;
88
108
  }
89
- return packet;
90
109
  }
91
110
  }
92
111
  exports.PacketEncryptor = PacketEncryptor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baltica",
3
- "version": "2.0.9",
3
+ "version": "2.0.10",
4
4
  "description": "Core baltica package",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",