baltica 0.0.1 → 0.0.3

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 (76) hide show
  1. package/.github/workflows/publish.yml +88 -0
  2. package/dist/bridge/bridge-options.d.ts +9 -3
  3. package/dist/bridge/bridge-options.js +1 -0
  4. package/dist/bridge/bridge-player.d.ts +3 -0
  5. package/dist/bridge/bridge-player.js +14 -0
  6. package/dist/bridge/bridge.d.ts +1 -0
  7. package/dist/bridge/bridge.js +99 -41
  8. package/dist/client/client-data.js +26 -6
  9. package/dist/client/client-options.d.ts +5 -0
  10. package/dist/client/client-options.js +1 -0
  11. package/dist/client/client.d.ts +4 -3
  12. package/dist/client/client.js +48 -9
  13. package/dist/client/types/payload.d.ts +2 -2
  14. package/dist/client/types/payload.js +2 -1
  15. package/dist/client/worker/WorkerClient.d.ts +1 -0
  16. package/dist/client/worker/WorkerClient.js +5 -0
  17. package/dist/client/worker/worker.js +3 -6
  18. package/dist/network/auth.d.ts +1 -1
  19. package/dist/network/auth.js +80 -21
  20. package/dist/network/beta/auth.d.ts +51 -0
  21. package/dist/network/beta/auth.js +699 -0
  22. package/dist/network/level-chunk-packet.js +2 -2
  23. package/dist/network/packets/add-painting.d.ts +9 -0
  24. package/dist/network/packets/add-painting.js +41 -0
  25. package/dist/network/packets/index.d.ts +1 -0
  26. package/dist/network/packets/index.js +17 -0
  27. package/dist/server/player.d.ts +5 -2
  28. package/dist/server/player.js +40 -26
  29. package/dist/server/server-options.js +2 -2
  30. package/dist/server/server.d.ts +2 -1
  31. package/dist/server/server.js +14 -9
  32. package/dist/tools/bridge.js +36 -3
  33. package/dist/tools/bridge2.d.ts +1 -0
  34. package/dist/tools/bridge2.js +105 -0
  35. package/dist/tools/client.js +52 -26
  36. package/dist/tools/test.d.ts +1 -0
  37. package/dist/tools/test.js +8 -0
  38. package/package.json +8 -4
  39. package/src/bridge/bridge-options.ts +41 -0
  40. package/src/bridge/bridge-player.ts +56 -0
  41. package/src/bridge/bridge.ts +262 -0
  42. package/src/client/client-data.ts +219 -0
  43. package/src/client/client-options.ts +100 -0
  44. package/src/client/client.ts +364 -0
  45. package/src/client/index.ts +5 -0
  46. package/src/client/types/index.ts +3 -0
  47. package/src/client/types/login-data.ts +41 -0
  48. package/src/client/types/payload.ts +112 -0
  49. package/src/client/types/skin/Skin.d.ts +23 -0
  50. package/src/client/types/skin/Skin.json +112 -0
  51. package/src/client/types/skin/index.ts +1 -0
  52. package/src/client/worker/WorkerClient.ts +134 -0
  53. package/src/client/worker/index.ts +2 -0
  54. package/src/client/worker/worker.ts +132 -0
  55. package/src/index.ts +4 -0
  56. package/src/libs/emitter.ts +111 -0
  57. package/src/libs/index.ts +1 -0
  58. package/src/network/auth.ts +275 -0
  59. package/src/network/beta/auth.ts +927 -0
  60. package/src/network/client-cache-status.ts +28 -0
  61. package/src/network/index.ts +3 -0
  62. package/src/network/level-chunk-packet.ts +90 -0
  63. package/src/network/packet-compressor.ts +101 -0
  64. package/src/network/packet-encryptor.ts +109 -0
  65. package/src/network/packets/add-painting.ts +14 -0
  66. package/src/network/packets/index.ts +1 -0
  67. package/src/server/index.ts +3 -0
  68. package/src/server/player.ts +262 -0
  69. package/src/server/server-options.ts +41 -0
  70. package/src/server/server.ts +72 -0
  71. package/src/tools/bridge.ts +96 -0
  72. package/src/tools/bridge2.ts +151 -0
  73. package/src/tools/client.ts +98 -0
  74. package/src/tools/server.ts +8 -0
  75. package/src/tools/test.ts +8 -0
  76. package/tsconfig.json +20 -0
@@ -0,0 +1,88 @@
1
+ name: Publish and Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ jobs:
9
+ lint:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - name: Set up Node.js
14
+ uses: actions/setup-node@v4
15
+ with:
16
+ node-version: '20.x'
17
+ - name: Install dependencies
18
+ run: npm install
19
+ - name: Run lint
20
+ run: npm run lint
21
+
22
+ build:
23
+ needs: [lint]
24
+ permissions:
25
+ id-token: write
26
+ contents: read
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v4
31
+ - name: Set up Node.js
32
+ uses: actions/setup-node@v4
33
+ with:
34
+ node-version: '20.x'
35
+ - name: Install dependencies
36
+ run: npm install
37
+ - name: Build
38
+ run: npm run build
39
+ - name: Upload build artifacts
40
+ uses: actions/upload-artifact@v4
41
+ with:
42
+ name: dist
43
+ path: |
44
+ dist/
45
+ package.json
46
+ package-lock.json
47
+
48
+ publish-and-release:
49
+ needs: [build]
50
+ permissions:
51
+ id-token: write
52
+ contents: write
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - name: Checkout repository
56
+ uses: actions/checkout@v4
57
+ - name: Download build artifacts
58
+ uses: actions/download-artifact@v4
59
+ with:
60
+ name: dist
61
+ - name: Set up Node.js
62
+ uses: actions/setup-node@v4
63
+ with:
64
+ node-version: '20.x'
65
+ registry-url: 'https://registry.npmjs.org'
66
+ - name: Check if package can be published
67
+ run: npm publish --dry-run --verbose
68
+ - name: Publish package
69
+ id: npm-publish
70
+ run: npm publish --access=public
71
+ env:
72
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
73
+ - name: Get version and Minecraft info
74
+ if: success()
75
+ id: package-info
76
+ run: |
77
+ echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
78
+ echo "minecraft=$(node -p "require('./package.json').minecraft")" >> $GITHUB_OUTPUT
79
+ - name: Create Release
80
+ if: success()
81
+ env:
82
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
83
+ run: |
84
+ gh release create v${{ steps.package-info.outputs.version }} \
85
+ --title "Release v${{ steps.package-info.outputs.version }} for Minecraft ${{ steps.package-info.outputs.minecraft }}" \
86
+ --notes "Release for Baltica v${{ steps.package-info.outputs.version }}
87
+ Compatible with Minecraft ${{ steps.package-info.outputs.minecraft }}" \
88
+ --target ${{ github.sha }}
@@ -4,19 +4,25 @@ import type { ClientCacheStatusPacket } from "../network/client-cache-status";
4
4
  import { type ServerOptions } from "../server/server-options";
5
5
  export type BridgePlayerEvents = {
6
6
  [K in PacketNames as `clientbound-${K}`]: [
7
- packet: InstanceType<(typeof Protocol)[K]>
7
+ packet: InstanceType<(typeof Protocol)[K]>,
8
+ cancelled: boolean
8
9
  ];
9
10
  } & {
10
11
  [K in PacketNames as `serverbound-${K}`]: [
11
- packet: InstanceType<(typeof Protocol)[K]>
12
+ packet: InstanceType<(typeof Protocol)[K]>,
13
+ cancelled: boolean
12
14
  ];
13
15
  } & {
14
- "serverbound-ClientCacheStatusPacket": [packet: ClientCacheStatusPacket];
16
+ "serverbound-ClientCacheStatusPacket": [
17
+ packet: ClientCacheStatusPacket,
18
+ cancelled: boolean
19
+ ];
15
20
  };
16
21
  export type BridgeOptions = ServerOptions & {
17
22
  destination: {
18
23
  host: string;
19
24
  port: number;
20
25
  };
26
+ offline: boolean;
21
27
  };
22
28
  export declare const defaultBridgeOptions: BridgeOptions;
@@ -8,4 +8,5 @@ exports.defaultBridgeOptions = {
8
8
  host: "127.0.0.1",
9
9
  port: 19132,
10
10
  },
11
+ offline: false,
11
12
  };
@@ -1,3 +1,4 @@
1
+ import type { LevelChunkPacket } from "../network/level-chunk-packet";
1
2
  import type { Client } from "../client";
2
3
  import { Emitter } from "../libs";
3
4
  import type { Player } from "../server";
@@ -8,6 +9,8 @@ export declare class BridgePlayer extends Emitter<BridgePlayerEvents> {
8
9
  bridge: Bridge;
9
10
  client: Client;
10
11
  cacheStatus: boolean;
12
+ postStartGame: boolean;
13
+ levelChunkQueue: LevelChunkPacket[];
11
14
  constructor(bridge: Bridge, player: Player);
12
15
  prepare(): void;
13
16
  getClient(): Client;
@@ -8,6 +8,20 @@ class BridgePlayer extends libs_1.Emitter {
8
8
  super();
9
9
  this.bridge = bridge;
10
10
  this.player = player;
11
+ this.postStartGame = false;
12
+ this.levelChunkQueue = [];
13
+ this.once("clientbound-StartGamePacket", (packet) => {
14
+ this.postStartGame = true;
15
+ for (const chunk of this.levelChunkQueue) {
16
+ const eventName = "clientbound-LevelChunkPacket";
17
+ this.emit(eventName, chunk, false);
18
+ if ("binary" in packet) {
19
+ packet.binary = [];
20
+ }
21
+ const newBuffer = chunk.serialize();
22
+ this.player.send(newBuffer);
23
+ }
24
+ });
11
25
  }
12
26
  prepare() {
13
27
  this.player.connection.on("disconnect", () => {
@@ -10,6 +10,7 @@ export declare class Bridge extends Server {
10
10
  options: BridgeOptions;
11
11
  private clients;
12
12
  private packetClassCache;
13
+ private packetSerializationCache;
13
14
  private readonly debugLog;
14
15
  constructor(options?: Partial<BridgeOptions>);
15
16
  private initializePacketCache;
@@ -1,19 +1,58 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
2
38
  Object.defineProperty(exports, "__esModule", { value: true });
3
39
  exports.Bridge = void 0;
4
40
  const raknet_1 = require("@sanctumterra/raknet");
5
41
  const protocol_1 = require("@serenityjs/protocol");
42
+ const Protocol = __importStar(require("@serenityjs/protocol"));
6
43
  const client_1 = require("../client");
7
44
  const client_cache_status_1 = require("../network/client-cache-status");
8
45
  const level_chunk_packet_1 = require("../network/level-chunk-packet");
9
46
  const server_1 = require("../server");
10
47
  const bridge_options_1 = require("./bridge-options");
11
48
  const bridge_player_1 = require("./bridge-player");
49
+ const disconnect_1 = __importDefault(require("@sanctumterra/raknet/dist/proto/packets/disconnect"));
12
50
  class Bridge extends server_1.Server {
13
51
  constructor(options = {}) {
14
52
  super(options);
15
53
  this.clients = new Map();
16
54
  this.packetClassCache = new Map();
55
+ this.packetSerializationCache = new Map();
17
56
  this.debugLog = false;
18
57
  this.options = { ...bridge_options_1.defaultBridgeOptions, ...options };
19
58
  this.prepare();
@@ -22,39 +61,32 @@ class Bridge extends server_1.Server {
22
61
  initializePacketCache() {
23
62
  const CLIENT_CACHE_STATUS_ID = 129;
24
63
  this.packetClassCache.set(CLIENT_CACHE_STATUS_ID, client_cache_status_1.ClientCacheStatusPacket);
25
- if ("id" in level_chunk_packet_1.LevelChunkPacket) {
26
- const levelChunkId = level_chunk_packet_1.LevelChunkPacket.id;
64
+ const levelChunkId = level_chunk_packet_1.LevelChunkPacket.id;
65
+ if (levelChunkId !== undefined) {
27
66
  this.packetClassCache.set(levelChunkId, level_chunk_packet_1.LevelChunkPacket);
28
67
  }
29
68
  }
30
69
  getPacketClass(id, PacketClass) {
31
- const CLIENT_CACHE_STATUS_ID = 129;
32
- let CachedPacketClass = this.packetClassCache.get(id);
33
- if (!CachedPacketClass) {
34
- if (id === CLIENT_CACHE_STATUS_ID) {
35
- CachedPacketClass =
36
- client_cache_status_1.ClientCacheStatusPacket;
37
- }
38
- else if (PacketClass && typeof PacketClass === "function") {
39
- CachedPacketClass = PacketClass;
40
- }
41
- if (CachedPacketClass) {
42
- this.packetClassCache.set(id, CachedPacketClass);
43
- }
70
+ if (!this.packetClassCache.has(id) &&
71
+ PacketClass &&
72
+ typeof PacketClass === "function") {
73
+ this.packetClassCache.set(id, PacketClass);
44
74
  }
45
- return CachedPacketClass;
75
+ return this.packetClassCache.get(id);
46
76
  }
47
77
  processPacketCommon(buffer, player, isClientbound, sender) {
48
- const CLIENT_CACHE_STATUS_ID = 129;
49
78
  const id = (0, protocol_1.getPacketId)(buffer);
50
79
  const PacketClass = protocol_1.Packets[id];
51
- // @ts-ignore
52
- if (!PacketClass && id !== CLIENT_CACHE_STATUS_ID) {
80
+ const packetName = PacketClass?.name ?? "ClientCacheStatusPacket";
81
+ const eventName = `${isClientbound ? "clientbound" : "serverbound"}-${packetName}`;
82
+ if (!PacketClass && id !== 129) {
53
83
  sender.send(buffer);
54
84
  return;
55
85
  }
56
- const packetName = PacketClass?.name ?? "ClientCacheStatusPacket";
57
- const eventName = `${isClientbound ? "clientbound" : "serverbound"}-${packetName}`;
86
+ if (packetName === "LevelChunkPacket" && !player.postStartGame) {
87
+ player.levelChunkQueue.push(new level_chunk_packet_1.LevelChunkPacket(buffer).deserialize());
88
+ return;
89
+ }
58
90
  if (!player.hasListeners(eventName) &&
59
91
  packetName !== "ClientCacheStatusPacket") {
60
92
  sender.send(buffer);
@@ -69,41 +101,66 @@ class Bridge extends server_1.Server {
69
101
  if (this.debugLog) {
70
102
  raknet_1.Logger.info(`${isClientbound ? "Client -> BridgePlayer" : "BridgePlayer -> Client"} : ${packetName}`);
71
103
  }
72
- const packet = new CachedPacketClass(buffer).deserialize();
73
- if (packet instanceof client_cache_status_1.ClientCacheStatusPacket) {
74
- packet.supported = false;
75
- raknet_1.Logger.warn("Ignoring ClientCacheStatusPacket");
76
- return;
77
- }
78
- player.emit(eventName, packet);
79
- if ("binary" in packet) {
80
- packet.binary = [];
104
+ const cacheKey = `${id}-${buffer.toString("hex")}`;
105
+ let newBuffer = this.packetSerializationCache.get(cacheKey);
106
+ if (!newBuffer) {
107
+ const packet = new CachedPacketClass(buffer).deserialize();
108
+ if (packet instanceof client_cache_status_1.ClientCacheStatusPacket) {
109
+ packet.supported = false;
110
+ raknet_1.Logger.warn("Ignoring ClientCacheStatusPacket");
111
+ return;
112
+ }
113
+ const cancelled = false;
114
+ player.emit(eventName, packet, cancelled);
115
+ if (cancelled)
116
+ return;
117
+ if ("binary" in packet) {
118
+ packet.binary = [];
119
+ }
120
+ newBuffer = packet.serialize();
121
+ this.packetSerializationCache.set(cacheKey, newBuffer);
81
122
  }
82
- const newBuffer = packet.serialize();
83
- sender.send(buffer.equals(newBuffer) ? buffer : newBuffer);
123
+ sender.send(newBuffer);
84
124
  }
85
125
  catch (e) {
86
- console.error(`Failed to process ${packetName}`, e);
126
+ raknet_1.Logger.error(`Failed to process ${packetName}`, e);
87
127
  sender.send(buffer);
88
128
  }
89
129
  }
90
130
  prepare() {
91
131
  this.on("playerConnect", this.onConnect.bind(this));
92
132
  this.raknet.options.maxPacketsPerSecond = 20000;
133
+ this.on("disconnect", (data, _player) => {
134
+ const disconnect = new Protocol.DisconnectPacket();
135
+ disconnect.hideDisconnectScreen = true;
136
+ disconnect.message = new Protocol.DisconnectMessage("Disconnected");
137
+ disconnect.reason = Protocol.DisconnectReason.Disconnected;
138
+ const address = _player.connection.getAddress();
139
+ const playerKey = `${address.address}:${address.port}`;
140
+ const player = this.clients.get(playerKey);
141
+ if (player) {
142
+ const rakDisconnect = new disconnect_1.default();
143
+ const frame = new raknet_1.Frame();
144
+ frame.orderChannel = 0;
145
+ frame.payload = rakDisconnect.serialize();
146
+ player.client.raknet.sendFrame(frame, raknet_1.Priority.Immediate);
147
+ player.client.send(disconnect);
148
+ }
149
+ });
93
150
  }
94
151
  onConnect(player) {
95
152
  if (!(player.connection instanceof raknet_1.Connection))
96
153
  return;
97
154
  const bridgePlayer = new bridge_player_1.BridgePlayer(this, player);
98
- this.clients.set(`${player.connection.getAddress().address}:${player.connection.getAddress().port}`, bridgePlayer);
155
+ const address = player.connection.getAddress();
156
+ const playerKey = `${address.address}:${address.port}`;
157
+ this.clients.set(playerKey, bridgePlayer);
99
158
  this.emit("connect", bridgePlayer);
100
159
  bridgePlayer.player.once("ClientCacheStatusPacket", (packet) => {
101
160
  bridgePlayer.cacheStatus = packet.supported;
102
161
  });
103
- bridgePlayer.player.on("ClientToServerHandshakePacket", (packet) => {
104
- console.log("ClientToServerHandshakePacket");
162
+ bridgePlayer.player.on("ClientToServerHandshakePacket", () => {
105
163
  this.onLogin(bridgePlayer);
106
- return;
107
164
  });
108
165
  }
109
166
  onLogin(player) {
@@ -111,25 +168,26 @@ class Bridge extends server_1.Server {
111
168
  host: this.options.destination.host,
112
169
  port: this.options.destination.port,
113
170
  version: "1.21.50",
114
- offline: false,
115
171
  tokensFolder: "tokens",
116
172
  viewDistance: 2,
117
173
  worker: true,
174
+ offline: this.options.offline,
118
175
  });
119
176
  player.client = client;
120
177
  client.cancelPastLogin = true;
121
178
  client.removeAllListeners("ResourcePackStackPacket");
122
179
  client.removeAllListeners("ResourcePacksInfoPacket");
123
180
  client.removeAllListeners("PlayStatusPacket");
124
- client.once("ResourcePacksInfoPacket", (packet) => {
181
+ client.once("ResourcePacksInfoPacket", () => {
125
182
  client.send(client_cache_status_1.ClientCacheStatusPacket.create(false));
126
183
  });
127
- player.once("serverbound-ResourcePackClientResponsePacket", (packet) => {
184
+ player.once("serverbound-ResourcePackClientResponsePacket", () => {
128
185
  player.player.send(client_cache_status_1.ClientCacheStatusPacket.create(false));
129
186
  });
130
187
  client.once("PlayStatusPacket", (packet) => {
131
- if (packet.status !== protocol_1.PlayStatus.LoginSuccess)
188
+ if (packet.status !== protocol_1.PlayStatus.LoginSuccess) {
132
189
  throw new Error("Login failed");
190
+ }
133
191
  client.processPacket = (buffer) => {
134
192
  this.processPacketCommon(buffer, player, true, player.player);
135
193
  };
@@ -2,10 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ClientData = void 0;
4
4
  const node_crypto_1 = require("node:crypto");
5
- const node_util_1 = require("node:util");
6
5
  const raknet_1 = require("@sanctumterra/raknet");
7
6
  const protocol_1 = require("@serenityjs/protocol");
8
- const jsonwebtoken_1 = require("jsonwebtoken");
7
+ const fast_jwt_1 = require("fast-jwt");
9
8
  const uuid_1345_1 = require("uuid-1345");
10
9
  const login_data_1 = require("./types/login-data");
11
10
  const payload_1 = require("./types/payload");
@@ -14,7 +13,6 @@ const algorithm = "ES384";
14
13
  const curve = "secp384r1";
15
14
  const pem = { format: "pem", type: "sec1" };
16
15
  const der = { format: "der", type: "spki" };
17
- const signAsync = (0, node_util_1.promisify)(jsonwebtoken_1.sign);
18
16
  class ClientData {
19
17
  constructor(client) {
20
18
  this.client = client;
@@ -66,7 +64,15 @@ class ClientData {
66
64
  header: { alg: algorithm, x5u: clientX509, typ: undefined },
67
65
  };
68
66
  }
69
- return signAsync(payload, ecdhKeyPair.privateKey.export({ format: "pem", type: "pkcs8" }), signOptions);
67
+ const privateKeyPem = ecdhKeyPair.privateKey.export({
68
+ format: "pem",
69
+ type: "pkcs8",
70
+ });
71
+ const signer = (0, fast_jwt_1.createSigner)({
72
+ ...signOptions,
73
+ key: privateKeyPem,
74
+ });
75
+ return signer(payload);
70
76
  }
71
77
  async createClientUserChain(privateKey) {
72
78
  const { clientX509 } = this.loginData;
@@ -80,11 +86,24 @@ class ClientData {
80
86
  PlayFabId: ClientData.nextUUID().replace(/-/g, "").slice(0, 16),
81
87
  SelfSignedId: ClientData.nextUUID(),
82
88
  };
83
- return signAsync(payload, privateKey.export({ format: "pem", type: "pkcs8" }), {
89
+ if (privateKey.asymmetricKeyDetails?.namedCurve === "p384")
90
+ privateKey.asymmetricKeyDetails.namedCurve = "secp384r1";
91
+ // Deno sucks.
92
+ // Logger.info('Private Key details:', {
93
+ // type: privateKey.type,
94
+ // curve: privateKey.asymmetricKeyDetails?.namedCurve
95
+ // });
96
+ const privateKeyPem = privateKey.export({
97
+ format: "pem",
98
+ type: "pkcs8",
99
+ });
100
+ const signer = (0, fast_jwt_1.createSigner)({
84
101
  algorithm,
85
102
  header: { alg: algorithm, x5u: clientX509, typ: undefined },
86
103
  noTimestamp: true,
104
+ key: privateKeyPem,
87
105
  });
106
+ return signer(payload);
88
107
  }
89
108
  createSharedSecret(privateKey, publicKey) {
90
109
  this.validateKeys(privateKey, publicKey);
@@ -93,7 +112,8 @@ class ClientData {
93
112
  throw new Error("Invalid private key format. Named curve is missing.");
94
113
  }
95
114
  try {
96
- const ecdh = (0, node_crypto_1.createECDH)(curve);
115
+ const normalizedCurve = curve === "p384" ? "secp384r1" : curve;
116
+ const ecdh = (0, node_crypto_1.createECDH)(normalizedCurve);
97
117
  const privateKeyJwk = privateKey.export({ format: "jwk" });
98
118
  const publicKeyJwk = publicKey.export({ format: "jwk" });
99
119
  if (!privateKeyJwk.d || !publicKeyJwk.x || !publicKeyJwk.y) {
@@ -1,6 +1,8 @@
1
1
  import { CompressionMethod, InputMode } from "@serenityjs/protocol";
2
2
  import type * as Protocol from "@serenityjs/protocol";
3
3
  import type { ClientCacheStatusPacket } from "../network/client-cache-status";
4
+ import type { Advertisement } from "@sanctumterra/raknet";
5
+ import type { AddPaintingPacket } from "../network/packets";
4
6
  export declare enum ProtocolList {
5
7
  "1.21.50" = 766
6
8
  }
@@ -42,6 +44,7 @@ type ClientOptions = {
42
44
  offline: boolean;
43
45
  worker: boolean;
44
46
  loginOptions: LoginPacketOptions;
47
+ betaAuth: boolean;
45
48
  };
46
49
  declare const defaultClientOptions: ClientOptions;
47
50
  type PacketNames = {
@@ -52,7 +55,9 @@ type ClientEvents = {
52
55
  } & {
53
56
  session: [];
54
57
  ClientCacheStatus: [packet: ClientCacheStatusPacket];
58
+ AddPaintingPacket: [packet: AddPaintingPacket];
55
59
  } & {
56
60
  packet: [packet: InstanceType<(typeof Protocol)[PacketNames]>];
61
+ connect: [packet: Advertisement];
57
62
  };
58
63
  export { type ClientOptions, defaultClientOptions, type ClientEvents, type PacketNames, };
@@ -44,5 +44,6 @@ const defaultClientOptions = {
44
44
  CurrentInputMode: protocol_1.InputMode.GamePad,
45
45
  DefaultInputMode: protocol_1.InputMode.GamePad,
46
46
  },
47
+ betaAuth: false,
47
48
  };
48
49
  exports.defaultClientOptions = defaultClientOptions;
@@ -1,5 +1,5 @@
1
- import { Client as RaknetClient } from "@sanctumterra/raknet";
2
- import { DataPacket } from "@serenityjs/protocol";
1
+ import { type Advertisement, Client as RaknetClient } from "@sanctumterra/raknet";
2
+ import { DataPacket, type StartGamePacket } from "@serenityjs/protocol";
3
3
  import { Emitter } from "../libs/emitter";
4
4
  import { type Profile } from "../network";
5
5
  import { PacketEncryptor } from "../network/packet-encryptor";
@@ -25,7 +25,7 @@ declare class Client extends Emitter<ClientEvents> {
25
25
  runtimeEntityId: bigint;
26
26
  cancelPastLogin: boolean;
27
27
  constructor(options: Partial<ClientOptions>);
28
- connect(): Promise<unknown>;
28
+ connect(): Promise<[Advertisement, StartGamePacket]>;
29
29
  private handleStartGamePacket;
30
30
  private handleSetLocalPlayerAsInitializedPacket;
31
31
  private handleEncapsulated;
@@ -39,6 +39,7 @@ declare class Client extends Emitter<ClientEvents> {
39
39
  private handlePlayStatusPacket;
40
40
  private handleResourcePacksInfoPacket;
41
41
  startEncryption(iv: Buffer): void;
42
+ disconnect(): void;
42
43
  sendMessage(text: string): void;
43
44
  }
44
45
  export { Client };
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Client = void 0;
4
7
  const node_crypto_1 = require("node:crypto");
@@ -13,6 +16,8 @@ const packet_encryptor_1 = require("../network/packet-encryptor");
13
16
  const client_data_1 = require("./client-data");
14
17
  const client_options_1 = require("./client-options");
15
18
  const worker_1 = require("./worker");
19
+ const packets_1 = require("../network/packets");
20
+ const disconnect_1 = __importDefault(require("@sanctumterra/raknet/dist/proto/packets/disconnect"));
16
21
  class Client extends emitter_1.Emitter {
17
22
  constructor(options) {
18
23
  super();
@@ -37,6 +42,10 @@ class Client extends emitter_1.Emitter {
37
42
  this.options.offline ? (0, network_1.createOfflineSession)(this) : (0, network_1.authenticate)(this);
38
43
  }
39
44
  async connect() {
45
+ while (!this.sessionReady) {
46
+ await new Promise((resolve) => setTimeout(resolve, 10));
47
+ }
48
+ this.status = raknet_1.Status.Connecting;
40
49
  this.packetCompressor = new network_1.PacketCompressor(this);
41
50
  this.listen();
42
51
  const advertisement = await this.raknet.connect();
@@ -50,6 +59,7 @@ class Client extends emitter_1.Emitter {
50
59
  this.startGamePacket &&
51
60
  this.sessionReady) {
52
61
  clearInterval(interval);
62
+ this.emit("connect", advertisement);
53
63
  resolve([advertisement, this.startGamePacket]);
54
64
  }
55
65
  }, 50);
@@ -63,7 +73,7 @@ class Client extends emitter_1.Emitter {
63
73
  const radius = new protocol_1.RequestChunkRadiusPacket();
64
74
  radius.radius = this.options.viewDistance;
65
75
  radius.maxRadius = this.options.viewDistance;
66
- this.queue(radius);
76
+ this.send(radius);
67
77
  }
68
78
  handleSetLocalPlayerAsInitializedPacket(packet) {
69
79
  this.status = raknet_1.Status.Connected;
@@ -81,6 +91,8 @@ class Client extends emitter_1.Emitter {
81
91
  }
82
92
  sendPacket(packet, priority = raknet_1.Priority.Normal) {
83
93
  try {
94
+ if (this.status === raknet_1.Status.Disconnected)
95
+ return;
84
96
  const serialized = packet instanceof protocol_1.DataPacket ? packet.serialize() : packet;
85
97
  const compressed = this.packetCompressor.compress(serialized, this.options.compressionMethod);
86
98
  const frame = new raknet_1.Frame();
@@ -102,20 +114,28 @@ class Client extends emitter_1.Emitter {
102
114
  /** Already decompressed packets */
103
115
  processPacket(buffer) {
104
116
  const id = (0, protocol_1.getPacketId)(buffer);
105
- if (!protocol_1.Packets[id])
106
- return raknet_1.Logger.warn(`Unknown Game packet ${id}`);
107
117
  let PacketClass = protocol_1.Packets[id];
108
118
  try {
109
119
  if (id === protocol_1.Packet.LevelChunk) {
110
120
  PacketClass = level_chunk_packet_1.LevelChunkPacket;
111
121
  }
112
- if (this.hasListeners(PacketClass.name)) {
113
- const packet = new PacketClass(buffer).deserialize();
114
- this.emit(PacketClass.name, packet);
122
+ if (id === 22) {
123
+ PacketClass = packets_1.AddPaintingPacket;
115
124
  }
116
- if (this.hasListeners("packet")) {
117
- const packet = new PacketClass(buffer).deserialize();
118
- this.emit("packet", packet);
125
+ if (!protocol_1.Packets && !protocol_1.Packets[id])
126
+ return raknet_1.Logger.warn(`Unknown Game packet ${id}`);
127
+ // console.log('X - ', PacketClass.name, readPacket(this.options.version, buffer));
128
+ let deserializedPacket;
129
+ const hasSpecificListener = this.hasListeners(PacketClass.name);
130
+ const hasGenericListener = this.hasListeners("packet");
131
+ if (hasSpecificListener || hasGenericListener) {
132
+ deserializedPacket = new PacketClass(buffer).deserialize();
133
+ if (hasSpecificListener) {
134
+ this.emit(PacketClass.name, deserializedPacket);
135
+ }
136
+ if (hasGenericListener) {
137
+ this.emit("packet", deserializedPacket);
138
+ }
119
139
  }
120
140
  }
121
141
  catch (error) {
@@ -200,6 +220,25 @@ class Client extends emitter_1.Emitter {
200
220
  this.packetEncryptor = new packet_encryptor_1.PacketEncryptor(this, iv);
201
221
  this._encryptionEnabled = true;
202
222
  }
223
+ disconnect() {
224
+ const rakDisconnect = new disconnect_1.default();
225
+ const frame = new raknet_1.Frame();
226
+ frame.orderChannel = 0;
227
+ frame.payload = rakDisconnect.serialize();
228
+ this.raknet.sendFrame(frame, raknet_1.Priority.Immediate);
229
+ this.status = raknet_1.Status.Disconnected;
230
+ this.removeAllListeners();
231
+ this.raknet.cleanup();
232
+ if (this.raknet instanceof raknet_1.Client) {
233
+ this.raknet.removeAll();
234
+ this.raknet.removeAllAfter();
235
+ this.raknet.removeAllBefore();
236
+ }
237
+ else {
238
+ this.raknet.dispose();
239
+ }
240
+ return;
241
+ }
203
242
  sendMessage(text) {
204
243
  const textPacket = new protocol_1.TextPacket();
205
244
  textPacket.filtered = "";
@@ -1,6 +1,6 @@
1
- import type { Player } from "src/server/player";
1
+ import type { Player } from "../../server/player";
2
2
  import type { Client } from "../client";
3
- import type { AnimatedImageData, PersonaPieces, PieceTintColors } from "./skin";
3
+ import type { AnimatedImageData, PersonaPieces, PieceTintColors } from "./skin/Skin.d";
4
4
  export type Payload = {
5
5
  AnimatedImageData: AnimatedImageData[];
6
6
  ArmSize: string;
@@ -87,5 +87,6 @@ const createDefaultPayload = (client) => {
87
87
  };
88
88
  exports.createDefaultPayload = createDefaultPayload;
89
89
  const getRandomId = () => {
90
- return Math.floor(Math.random() * Date.now() * Math.random() * 1000000) ^ Date.now();
90
+ return (Math.floor(Math.random() * Date.now() * Math.random() * 1000000) ^
91
+ Date.now());
91
92
  };