baltica 2.0.10 → 2.0.11

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.
@@ -9,5 +9,7 @@ export declare class Bridge extends Emitter<BridgeEvents> {
9
9
  private clients;
10
10
  constructor(options: Partial<BridgeOptions>);
11
11
  start(): Promise<void>;
12
+ private pollBackendMotd;
13
+ private fetchBackendMotd;
12
14
  disconnect(player: BridgePlayer): void;
13
15
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Bridge = void 0;
4
+ const node_dgram_1 = require("node:dgram");
4
5
  const utils_1 = require("@baltica/utils");
5
6
  const protocol_1 = require("@serenityjs/protocol");
6
7
  const server_1 = require("../server");
@@ -18,6 +19,7 @@ class Bridge extends utils_1.Emitter {
18
19
  }
19
20
  async start() {
20
21
  await this.server.start();
22
+ this.pollBackendMotd();
21
23
  this.server.on("playerConnect", (player) => {
22
24
  const bridgePlayer = new bridge_player_1.BridgePlayer(player, this);
23
25
  const key = player.connection.identifier;
@@ -26,6 +28,69 @@ class Bridge extends utils_1.Emitter {
26
28
  this.emit("connect", bridgePlayer);
27
29
  });
28
30
  }
31
+ pollBackendMotd() {
32
+ this.fetchBackendMotd().then((motd) => {
33
+ if (motd)
34
+ this.server.raknet.message = motd;
35
+ }).finally(() => {
36
+ setTimeout(() => this.pollBackendMotd(), 5000);
37
+ });
38
+ }
39
+ fetchBackendMotd() {
40
+ return new Promise((resolve) => {
41
+ const socket = (0, node_dgram_1.createSocket)("udp4");
42
+ const timeout = setTimeout(() => {
43
+ try {
44
+ socket.close();
45
+ }
46
+ catch { }
47
+ resolve(null);
48
+ }, 2000);
49
+ socket.on("error", () => {
50
+ clearTimeout(timeout);
51
+ try {
52
+ socket.close();
53
+ }
54
+ catch { }
55
+ resolve(null);
56
+ });
57
+ socket.on("message", (buffer) => {
58
+ clearTimeout(timeout);
59
+ try {
60
+ socket.close();
61
+ }
62
+ catch { }
63
+ try {
64
+ if (buffer[0] === 0x1c) {
65
+ const pong = new raknet_1.UnconnectedPong(buffer.subarray(1)).deserialize();
66
+ resolve(pong.message);
67
+ }
68
+ else {
69
+ resolve(null);
70
+ }
71
+ }
72
+ catch {
73
+ resolve(null);
74
+ }
75
+ });
76
+ socket.bind(0, () => {
77
+ try {
78
+ const ping = new raknet_1.UnconnectedPing();
79
+ ping.timestamp = BigInt(Date.now());
80
+ ping.guid = BigInt(Math.floor(Math.random() * 0xffffffff));
81
+ socket.send(ping.serialize(), this.options.destination.port, this.options.destination.address);
82
+ }
83
+ catch {
84
+ clearTimeout(timeout);
85
+ try {
86
+ socket.close();
87
+ }
88
+ catch { }
89
+ resolve(null);
90
+ }
91
+ });
92
+ });
93
+ }
29
94
  disconnect(player) {
30
95
  utils_1.Logger.info(`Disconnecting player ${player.player.username}`);
31
96
  try {
@@ -38,12 +38,11 @@ class Client extends utils_1.Emitter {
38
38
  await this.raknet.connect();
39
39
  this.requestNetworkSettings();
40
40
  return new Promise((resolve, reject) => {
41
- this.on("SetLocalPlayerAsInitializedPacket", () => {
41
+ this.once("SetLocalPlayerAsInitializedPacket", () => {
42
42
  resolve();
43
- this.emit("spawn");
44
43
  this.emit("connect");
45
44
  });
46
- this.on("disconnect", (reason) => {
45
+ this.once("disconnect", (reason) => {
47
46
  reject(new Error(`Disconnected during login: ${reason}`));
48
47
  });
49
48
  });
@@ -110,10 +109,15 @@ class Client extends utils_1.Emitter {
110
109
  radius.radius = this.options.viewDistance;
111
110
  radius.maxRadius = this.options.viewDistance;
112
111
  this.send(radius.serialize());
112
+ const loadingScreen = new protocol_1.ServerboundLoadingScreenPacketPacket();
113
+ loadingScreen.type = protocol_1.ServerboundLoadingScreenType.StartLoadingScreen;
114
+ loadingScreen.hasScreenId = false;
115
+ this.send(loadingScreen.serialize());
113
116
  }
114
117
  onPlayStatus(packet) {
115
118
  if (packet.status !== protocol_1.PlayStatus.PlayerSpawn)
116
119
  return;
120
+ this.emit("spawn"); // Spawn is just spawning. not fully connected yet
117
121
  const init = new protocol_1.SetLocalPlayerAsInitializedPacket();
118
122
  init.runtimeEntityId = this.startGameData.runtimeEntityId;
119
123
  const loadingScreen = new protocol_1.ServerboundLoadingScreenPacketPacket();
@@ -243,7 +247,12 @@ class Client extends utils_1.Emitter {
243
247
  try {
244
248
  const decompressed = this.packetCompressor.decompress(packet);
245
249
  for (const packet of decompressed) {
246
- this.handlePacket(packet);
250
+ try {
251
+ this.handlePacket(packet);
252
+ }
253
+ catch (err) {
254
+ utils_2.Logger.error("Failed to handle packet", err);
255
+ }
247
256
  }
248
257
  }
249
258
  catch (err) {
@@ -262,7 +271,12 @@ class Client extends utils_1.Emitter {
262
271
  return;
263
272
  if (this.listenerCount(PacketClass.name) > 0) {
264
273
  const deserialized = new PacketClass(buffer).deserialize();
265
- this.emit(PacketClass.name, deserialized);
274
+ try {
275
+ this.emit(PacketClass.name, deserialized);
276
+ }
277
+ catch (err) {
278
+ utils_2.Logger.error(`Error in packet handler for ${PacketClass.name}:`, err);
279
+ }
266
280
  }
267
281
  }
268
282
  sendUncompressed(packet, priority = raknet_1.Priority.Medium) {
@@ -156,6 +156,7 @@ class LoginData {
156
156
  displayName: profile.name,
157
157
  identity: profile.uuid,
158
158
  titleId: "89692877",
159
+ sandboxId: "",
159
160
  XUID: "",
160
161
  },
161
162
  certificateAuthority: true,
@@ -115,6 +115,23 @@ class Player extends utils_1.Emitter {
115
115
  }
116
116
  catch { }
117
117
  }
118
+ // New client versions use Token instead of Certificate chain.
119
+ // The Token JWT payload contains cpk (client public key), xname, and xid.
120
+ if (!identityPublicKey) {
121
+ const token = identity.Token ?? identity.token;
122
+ if (token) {
123
+ try {
124
+ const payload = JSON.parse(Buffer.from(token.split(".")[1], "base64").toString());
125
+ if (payload?.cpk)
126
+ identityPublicKey = payload.cpk;
127
+ if (payload?.xname && !displayName)
128
+ displayName = payload.xname;
129
+ if (payload?.xid && !xuid)
130
+ xuid = payload.xid;
131
+ }
132
+ catch { }
133
+ }
134
+ }
118
135
  this.username = displayName;
119
136
  this.xuid = xuid;
120
137
  if (!identityPublicKey) {
@@ -3,7 +3,8 @@ export type PacketNames = {
3
3
  [K in keyof typeof Protocol]: K extends `${string}Packet` ? K extends "Packet" | "DataPacket" ? never : K : never;
4
4
  }[keyof typeof Protocol];
5
5
  export declare enum ProtocolList {
6
- "1.26.1" = 924
6
+ "1.26.1" = 924,
7
+ "1.26.10" = 944
7
8
  }
8
- export type CurrentVersion = "1.26.1";
9
+ export type CurrentVersion = "1.26.10";
9
10
  export declare const CurrentVersionConst: CurrentVersion;
@@ -4,5 +4,6 @@ exports.CurrentVersionConst = exports.ProtocolList = void 0;
4
4
  var ProtocolList;
5
5
  (function (ProtocolList) {
6
6
  ProtocolList[ProtocolList["1.26.1"] = 924] = "1.26.1";
7
+ ProtocolList[ProtocolList["1.26.10"] = 944] = "1.26.10";
7
8
  })(ProtocolList || (exports.ProtocolList = ProtocolList = {}));
8
- exports.CurrentVersionConst = "1.26.1";
9
+ exports.CurrentVersionConst = "1.26.10";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baltica",
3
- "version": "2.0.10",
3
+ "version": "2.0.11",
4
4
  "description": "Core baltica package",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -13,7 +13,7 @@
13
13
  "@baltica/auth": "*",
14
14
  "@baltica/raknet": "*",
15
15
  "@baltica/utils": "*",
16
- "@serenityjs/protocol": "^0.8.18",
16
+ "@serenityjs/protocol": "^0.8.19",
17
17
  "jose": "^6.1.3"
18
18
  },
19
19
  "files": [