packet-events-js 1.0.0

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 (40) hide show
  1. package/README.md +398 -0
  2. package/package.json +31 -0
  3. package/src/auth/AuthHandler.js +138 -0
  4. package/src/auth/MojangAPI.js +186 -0
  5. package/src/client/MinecraftClient.js +336 -0
  6. package/src/crypto/Encryption.js +125 -0
  7. package/src/events/EventEmitter.js +267 -0
  8. package/src/events/PacketEvent.js +78 -0
  9. package/src/index.js +18 -0
  10. package/src/manager/PacketManager.js +258 -0
  11. package/src/protocol/ConnectionState.js +37 -0
  12. package/src/protocol/PacketDirection.js +8 -0
  13. package/src/protocol/ProtocolVersion.js +141 -0
  14. package/src/protocol/packets/Packet.js +119 -0
  15. package/src/protocol/packets/PacketRegistry.js +145 -0
  16. package/src/protocol/packets/handshake/HandshakePacket.js +44 -0
  17. package/src/protocol/packets/index.js +265 -0
  18. package/src/protocol/packets/login/DisconnectPacket.js +71 -0
  19. package/src/protocol/packets/login/EncryptionRequestPacket.js +47 -0
  20. package/src/protocol/packets/login/EncryptionResponsePacket.js +34 -0
  21. package/src/protocol/packets/login/LoginStartPacket.js +35 -0
  22. package/src/protocol/packets/login/LoginSuccessPacket.js +61 -0
  23. package/src/protocol/packets/login/SetCompressionPacket.js +29 -0
  24. package/src/protocol/packets/play/ChatPacket.js +238 -0
  25. package/src/protocol/packets/play/ChunkPacket.js +122 -0
  26. package/src/protocol/packets/play/EntityPacket.js +302 -0
  27. package/src/protocol/packets/play/KeepAlivePacket.js +55 -0
  28. package/src/protocol/packets/play/PlayerPositionPacket.js +266 -0
  29. package/src/protocol/packets/status/PingPacket.js +29 -0
  30. package/src/protocol/packets/status/PongPacket.js +29 -0
  31. package/src/protocol/packets/status/StatusRequestPacket.js +20 -0
  32. package/src/protocol/packets/status/StatusResponsePacket.js +58 -0
  33. package/src/protocol/types/NBT.js +594 -0
  34. package/src/protocol/types/Position.js +125 -0
  35. package/src/protocol/types/TextComponent.js +355 -0
  36. package/src/protocol/types/UUID.js +105 -0
  37. package/src/protocol/types/VarInt.js +144 -0
  38. package/src/protocol/types/index.js +5 -0
  39. package/src/utils/Logger.js +207 -0
  40. package/src/utils/PacketBuffer.js +389 -0
package/README.md ADDED
@@ -0,0 +1,398 @@
1
+ # PacketEvents-JS
2
+
3
+ A robust protocol library for **Minecraft Java Edition** written entirely in **pure JavaScript**. Inspired by [PacketEvents](https://github.com/retrooper/packetevents), designed to facilitate the processing and transmission of Minecraft protocol packets with full online mode support.
4
+
5
+ ## Features
6
+
7
+ - **Pure JavaScript** - No external dependencies, only native Node.js
8
+ - **TCP Connection** - Complete TCP client for Minecraft
9
+ - **Packet System** - Read/write all protocol data types
10
+ - **Event System** - Priority-based events with cancellation and async/await
11
+ - **Compression** - Full zlib compression support
12
+ - **Encryption** - Complete AES-128-CFB8 encryption support for online mode
13
+ - **Online Mode** - Full Mojang/Microsoft authentication support
14
+ - **Offline Mode** - Offline player UUID generation (version 3)
15
+ - **Complete NBT** - Named Binary Tag read/write
16
+ - **Chat Components** - JSON Text Component with colors, formatting, and events
17
+ - **Multi-version** - Support for Minecraft 1.7.2 to 1.21.11 (66 versions)
18
+
19
+ ## Requirements
20
+
21
+ - Node.js 18.0.0 or higher
22
+ - ES Modules enabled
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ npm install packet-events-js
28
+ ```
29
+
30
+ Or clone the repository:
31
+
32
+ ```bash
33
+ git clone https://github.com/FrannnnDev/PacketEvents-JS.git
34
+ cd PacketEvents-JS
35
+ ```
36
+
37
+ ## Basic Usage
38
+
39
+ ### Server List Ping
40
+
41
+ ```javascript
42
+ import { MinecraftClient, ProtocolVersion } from 'packet-events-js';
43
+
44
+ const client = new MinecraftClient({
45
+ host: 'mc.hypixel.net',
46
+ port: 25565,
47
+ version: ProtocolVersion.V1_21_11
48
+ });
49
+
50
+ const status = await client.ping();
51
+ console.log(`Players: ${status.players.online}/${status.players.max}`);
52
+ console.log(`Latency: ${status.latency}ms`);
53
+ ```
54
+
55
+ ### Connect to Server (Offline Mode)
56
+
57
+ ```javascript
58
+ import { MinecraftClient, ProtocolVersion, Logger, LogLevel } from 'packet-events-js';
59
+ import { KeepAliveClientboundPacket, KeepAliveServerboundPacket } from 'packet-events-js/protocol/packets';
60
+
61
+ Logger.setGlobalLevel(LogLevel.DEBUG);
62
+
63
+ const client = new MinecraftClient({
64
+ host: 'localhost',
65
+ port: 25565,
66
+ version: ProtocolVersion.V1_21_11,
67
+ username: 'MyBot',
68
+ offline: true
69
+ });
70
+
71
+ client.onPacket(KeepAliveClientboundPacket, async (event) => {
72
+ const response = new KeepAliveServerboundPacket();
73
+ response.keepAliveId = event.packet.keepAliveId;
74
+ await client.sendPacket(response);
75
+ });
76
+
77
+ await client.login();
78
+ console.log(`Connected as ${client.playerName}`);
79
+ ```
80
+
81
+ ### Encryption API
82
+
83
+ ```javascript
84
+ import { MinecraftEncryption, EncryptedConnection } from 'packet-events-js/crypto/Encryption';
85
+
86
+ const keyPair = MinecraftEncryption.generateKeyPair();
87
+ console.log('Public Key:', keyPair.publicKey);
88
+ console.log('Private Key:', keyPair.privateKey);
89
+
90
+ const verifyToken = MinecraftEncryption.generateVerifyToken();
91
+ const sharedSecret = MinecraftEncryption.generateSharedSecret();
92
+
93
+ const encrypted = MinecraftEncryption.encryptRSA(keyPair.publicKey, sharedSecret);
94
+ const decrypted = MinecraftEncryption.decryptRSA(keyPair.privateKey, encrypted);
95
+
96
+ const aesEncrypted = MinecraftEncryption.encryptAES(sharedSecret, Buffer.from('Hello'));
97
+ const aesDecrypted = MinecraftEncryption.decryptAES(sharedSecret, aesEncrypted);
98
+
99
+ const serverHash = MinecraftEncryption.computeServerIdHash('', sharedSecret, keyPair.publicKey);
100
+ ```
101
+
102
+ ### Auth Handler
103
+
104
+ ```javascript
105
+ import { AuthHandler, ClientAuthHandler, AuthMode } from 'packet-events-js/auth/AuthHandler';
106
+
107
+ const serverAuth = new AuthHandler({ mode: AuthMode.ONLINE });
108
+ serverAuth.initialize();
109
+
110
+ const publicKey = serverAuth.getPublicKey();
111
+ const verifyToken = serverAuth.generateVerifyToken();
112
+
113
+ const offlineUUID = serverAuth.generateOfflineUUID('PlayerName');
114
+
115
+ const clientAuth = new ClientAuthHandler({
116
+ accessToken: 'token',
117
+ selectedProfile: { id: 'uuid', name: 'Name' }
118
+ });
119
+ ```
120
+
121
+ ### Intercept Packets
122
+
123
+ ```javascript
124
+ import { EventPriority } from 'packet-events-js/events/EventEmitter';
125
+
126
+ client.packetManager.on('packetSend', (event) => {
127
+ if (event.packet.packetName === 'SetPlayerPosition') {
128
+ console.log(`Moving to: ${event.packet.x}, ${event.packet.y}, ${event.packet.z}`);
129
+
130
+ if (event.packet.y < 0) {
131
+ event.cancel();
132
+ }
133
+ }
134
+ }, { priority: EventPriority.HIGH });
135
+ ```
136
+
137
+ ### Create Custom Packets
138
+
139
+ ```javascript
140
+ import { Packet } from 'packet-events-js/protocol/packets/Packet';
141
+ import { defaultRegistry } from 'packet-events-js/protocol/packets/PacketRegistry';
142
+ import { ConnectionState } from 'packet-events-js/protocol/ConnectionState';
143
+ import { PacketDirection } from 'packet-events-js/protocol/PacketDirection';
144
+
145
+ class MyCustomPacket extends Packet {
146
+ static get packetId() { return 0x50; }
147
+ static get packetName() { return 'MyPacket'; }
148
+
149
+ constructor() {
150
+ super();
151
+ this.myField = 0;
152
+ }
153
+
154
+ read(buffer, context) {
155
+ this.myField = buffer.readVarInt();
156
+ }
157
+
158
+ write(buffer, context) {
159
+ buffer.writeVarInt(this.myField);
160
+ }
161
+ }
162
+
163
+ defaultRegistry.register({
164
+ packetClass: MyCustomPacket,
165
+ state: ConnectionState.PLAY,
166
+ direction: PacketDirection.CLIENTBOUND,
167
+ packetId: 0x50
168
+ });
169
+ ```
170
+
171
+ ## Project Structure
172
+
173
+ ```
174
+ PacketEvents-JS/
175
+ ├── src/
176
+ │ ├── index.js
177
+ │ ├── auth/
178
+ │ │ ├── AuthHandler.js
179
+ │ │ └── MojangAPI.js
180
+ │ ├── client/
181
+ │ │ └── MinecraftClient.js
182
+ │ ├── crypto/
183
+ │ │ └── Encryption.js
184
+ │ ├── events/
185
+ │ │ ├── EventEmitter.js
186
+ │ │ └── PacketEvent.js
187
+ │ ├── manager/
188
+ │ │ └── PacketManager.js
189
+ │ ├── protocol/
190
+ │ │ ├── ConnectionState.js
191
+ │ │ ├── PacketDirection.js
192
+ │ │ ├── ProtocolVersion.js
193
+ │ │ ├── types/
194
+ │ │ │ ├── VarInt.js
195
+ │ │ │ ├── UUID.js
196
+ │ │ │ ├── Position.js
197
+ │ │ │ ├── NBT.js
198
+ │ │ │ └── TextComponent.js
199
+ │ │ └── packets/
200
+ │ │ ├── Packet.js
201
+ │ │ ├── PacketRegistry.js
202
+ │ │ ├── handshake/
203
+ │ │ ├── status/
204
+ │ │ ├── login/
205
+ │ │ └── play/
206
+ │ └── utils/
207
+ │ ├── PacketBuffer.js
208
+ │ └── Logger.js
209
+ └── examples/
210
+ ```
211
+
212
+ ## Main API
213
+
214
+ ### MinecraftClient
215
+
216
+ ```javascript
217
+ const client = new MinecraftClient({
218
+ host: string,
219
+ port: number,
220
+ version: ProtocolVersion,
221
+ username: string,
222
+ offline: boolean,
223
+ accessToken: string,
224
+ selectedProfile: object,
225
+ registry: PacketRegistry
226
+ });
227
+
228
+ await client.connect();
229
+ await client.ping();
230
+ await client.login();
231
+ await client.sendPacket(packet);
232
+ await client.disconnect();
233
+
234
+ client.isConnected;
235
+ client.isReady;
236
+ client.uuid;
237
+ client.playerName;
238
+ ```
239
+
240
+ ### PacketBuffer
241
+
242
+ ```javascript
243
+ import { PacketBuffer } from 'packet-events-js/utils/PacketBuffer';
244
+
245
+ const buffer = PacketBuffer.writer();
246
+
247
+ buffer.writeBoolean(true);
248
+ buffer.writeByte(42);
249
+ buffer.writeShort(1000);
250
+ buffer.writeInt(100000);
251
+ buffer.writeLong(9999999999n);
252
+ buffer.writeFloat(3.14);
253
+ buffer.writeDouble(3.14159265);
254
+ buffer.writeVarInt(12345);
255
+ buffer.writeString("Hello Minecraft");
256
+ buffer.writeUUID(uuid);
257
+ buffer.writePosition(position);
258
+ buffer.writeNBT(nbtCompound);
259
+
260
+ const data = buffer.getBuffer();
261
+
262
+ const reader = PacketBuffer.reader(data);
263
+ const bool = reader.readBoolean();
264
+ const num = reader.readVarInt();
265
+ const str = reader.readString();
266
+ ```
267
+
268
+ ### MinecraftEncryption
269
+
270
+ ```javascript
271
+ import { MinecraftEncryption, EncryptedConnection } from 'packet-events-js/crypto/Encryption';
272
+
273
+ const keyPair = MinecraftEncryption.generateKeyPair();
274
+
275
+ const verifyToken = MinecraftEncryption.generateVerifyToken();
276
+ const sharedSecret = MinecraftEncryption.generateSharedSecret();
277
+
278
+ MinecraftEncryption.encryptRSA(publicKey, data);
279
+ MinecraftEncryption.decryptRSA(privateKey, data);
280
+
281
+ MinecraftEncryption.encryptAES(secret, data);
282
+ MinecraftEncryption.decryptAES(secret, data);
283
+
284
+ MinecraftEncryption.computeServerIdHash(serverId, sharedSecret, publicKey);
285
+
286
+ const conn = new EncryptedConnection(sharedSecret);
287
+ conn.enable();
288
+ const encrypted = conn.encrypt(data);
289
+ const decrypted = conn.decrypt(data);
290
+ ```
291
+
292
+ ### AuthHandler
293
+
294
+ ```javascript
295
+ import { AuthHandler, ClientAuthHandler, AuthMode } from 'packet-events-js/auth/AuthHandler';
296
+
297
+ AuthMode.ONLINE;
298
+ AuthMode.OFFLINE;
299
+ AuthMode.BUNGEECORD;
300
+ AuthMode.VELOCITY;
301
+
302
+ const handler = new AuthHandler({ mode: AuthMode.ONLINE });
303
+ handler.initialize();
304
+ handler.getPublicKey();
305
+ handler.generateVerifyToken();
306
+ handler.generateOfflineUUID(username);
307
+ ```
308
+
309
+ ### EventEmitter
310
+
311
+ ```javascript
312
+ import { EventPriority } from 'packet-events-js/events/EventEmitter';
313
+
314
+ EventPriority.LOWEST;
315
+ EventPriority.LOW;
316
+ EventPriority.NORMAL;
317
+ EventPriority.HIGH;
318
+ EventPriority.HIGHEST;
319
+ EventPriority.MONITOR;
320
+
321
+ emitter.on('event', callback, { priority: EventPriority.HIGH });
322
+
323
+ emitter.on('packet', (event) => {
324
+ event.cancel();
325
+ });
326
+
327
+ await emitter.emitAsync('event', data);
328
+ ```
329
+
330
+ ### TextComponent
331
+
332
+ ```javascript
333
+ import { TextComponent, ChatColor } from 'packet-events-js/protocol/types/TextComponent';
334
+
335
+ const message = TextComponent.text('Hello!')
336
+ .color(ChatColor.GREEN)
337
+ .bold()
338
+ .append(
339
+ TextComponent.text(' World')
340
+ .color(ChatColor.YELLOW)
341
+ .italic()
342
+ )
343
+ .clickEvent('run_command', '/help')
344
+ .showText(TextComponent.text('Click for help'));
345
+
346
+ const json = message.toString();
347
+ ```
348
+
349
+ ## Supported Versions
350
+
351
+ 66 versions supported from **1.7.2** to **1.21.11**:
352
+
353
+ | Range | Versions |
354
+ |-------|----------|
355
+ | 1.21.x | 1.21.11, 1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6, 1.21.5, 1.21.4, 1.21.3, 1.21.2, 1.21.1, 1.21 |
356
+ | 1.20.x | 1.20.6, 1.20.5, 1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20 |
357
+ | 1.19.x | 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19 |
358
+ | 1.18.x | 1.18.2, 1.18.1, 1.18 |
359
+ | 1.17.x | 1.17.1, 1.17 |
360
+ | 1.16.x | 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16 |
361
+ | 1.15.x | 1.15.2, 1.15.1, 1.15 |
362
+ | 1.14.x | 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14 |
363
+ | 1.13.x | 1.13.2, 1.13.1, 1.13 |
364
+ | 1.12.x | 1.12.2, 1.12.1, 1.12 |
365
+ | 1.11.x | 1.11.2, 1.11.1, 1.11 |
366
+ | 1.10.x | 1.10.2, 1.10.1, 1.10 |
367
+ | 1.9.x | 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9 |
368
+ | 1.8.x | 1.8.9, 1.8.8, 1.8.7, 1.8.6, 1.8.5, 1.8.4, 1.8.3, 1.8.2, 1.8.1, 1.8 |
369
+ | 1.7.x | 1.7.10, 1.7.9, 1.7.6, 1.7.5, 1.7.4, 1.7.2 |
370
+
371
+ ## Examples
372
+
373
+ See the [examples](./examples) folder for complete usage examples:
374
+
375
+ - `basic-client.js` - Basic client connection
376
+ - `server-ping.js` - Server list ping
377
+ - `packet-types.js` - All packet types demonstration
378
+ - `encryption.js` - Encryption usage
379
+ - `authentication.js` - Authentication modes
380
+ - `event-system.js` - Event system usage
381
+ - `packet-buffer.js` - PacketBuffer operations
382
+ - `data-types.js` - Protocol data types
383
+ - `protocol-versions.js` - Protocol version utilities
384
+ - `connection-flows.js` - Connection flow examples
385
+ - `custom-packets.js` - Custom packet creation
386
+ - `packet-interception.js` - Packet interception
387
+
388
+ ## References
389
+
390
+ This project is inspired by:
391
+
392
+ - [PacketEvents](https://github.com/retrooper/packetevents) - Original Java library
393
+ - [wiki.vg Protocol](https://wiki.vg/Protocol) - Protocol documentation
394
+ - [MCProtocolLib](https://github.com/GeyserMC/MCProtocolLib) - Reference implementation
395
+
396
+ ## License
397
+
398
+ MIT License
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "packet-events-js",
3
+ "version": "1.0.0",
4
+ "description": "A protocol library for Minecraft Java Edition in pure JavaScript",
5
+ "main": "src/index.js",
6
+ "type": "module",
7
+ "files": [
8
+ "src"
9
+ ],
10
+ "scripts": {
11
+ "start": "node src/index.js",
12
+ "example": "node examples/basic-client.js",
13
+ "test": "node examples/packet-types.js && node examples/data-types.js && node examples/encryption.js"
14
+ },
15
+ "keywords": [
16
+ "minecraft",
17
+ "protocol",
18
+ "packets",
19
+ "java-edition",
20
+ "networking"
21
+ ],
22
+ "author": "",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/FrannnnDev/PacketEvents-JS.git"
27
+ },
28
+ "engines": {
29
+ "node": ">=18.0.0"
30
+ }
31
+ }
@@ -0,0 +1,138 @@
1
+ import { MinecraftEncryption, EncryptedConnection } from '../crypto/Encryption.js';
2
+ import { MojangAPI } from './MojangAPI.js';
3
+ import { UUID } from '../protocol/types/UUID.js';
4
+
5
+ export const AuthMode = Object.freeze({
6
+ ONLINE: 'online',
7
+ OFFLINE: 'offline',
8
+ BUNGEECORD: 'bungeecord',
9
+ VELOCITY: 'velocity'
10
+ });
11
+
12
+ export class AuthHandler {
13
+ constructor(options = {}) {
14
+ this.mode = options.mode || AuthMode.OFFLINE;
15
+ this.preventProxyConnections = options.preventProxyConnections || false;
16
+ this.velocitySecret = options.velocitySecret || null;
17
+ this.keyPair = null;
18
+ }
19
+
20
+ initialize() {
21
+ if (this.mode === AuthMode.ONLINE) {
22
+ this.keyPair = MinecraftEncryption.generateKeyPair();
23
+ }
24
+ }
25
+
26
+ getPublicKey() {
27
+ if (!this.keyPair) return null;
28
+ return this.keyPair.publicKey;
29
+ }
30
+
31
+ generateVerifyToken() {
32
+ return MinecraftEncryption.generateVerifyToken();
33
+ }
34
+
35
+ decryptVerifyToken(encryptedToken) {
36
+ if (!this.keyPair) throw new Error('No key pair available');
37
+ return MinecraftEncryption.decryptRSA(this.keyPair.privateKey, encryptedToken);
38
+ }
39
+
40
+ decryptSharedSecret(encryptedSecret) {
41
+ if (!this.keyPair) throw new Error('No key pair available');
42
+ return MinecraftEncryption.decryptRSA(this.keyPair.privateKey, encryptedSecret);
43
+ }
44
+
45
+ computeServerHash(sharedSecret) {
46
+ if (!this.keyPair) throw new Error('No key pair available');
47
+ return MinecraftEncryption.computeServerIdHash('', sharedSecret, this.keyPair.publicKey);
48
+ }
49
+
50
+ createEncryptedConnection(sharedSecret) {
51
+ return new EncryptedConnection(sharedSecret);
52
+ }
53
+
54
+ async verifyPlayer(username, serverHash, clientIP = null) {
55
+ if (this.mode !== AuthMode.ONLINE) {
56
+ return {
57
+ success: true,
58
+ uuid: UUID.offlinePlayerUUID(username).toString(false),
59
+ name: username,
60
+ properties: []
61
+ };
62
+ }
63
+
64
+ const ip = this.preventProxyConnections ? clientIP : null;
65
+ return await MojangAPI.hasJoinedServer(username, serverHash, ip);
66
+ }
67
+
68
+ generateOfflineUUID(username) {
69
+ return UUID.offlinePlayerUUID(username);
70
+ }
71
+
72
+ async authenticate(username, encryptedSharedSecret, encryptedVerifyToken, originalVerifyToken, clientIP = null) {
73
+ const verifyToken = this.decryptVerifyToken(encryptedVerifyToken);
74
+
75
+ if (!verifyToken.equals(originalVerifyToken)) {
76
+ return { success: false, reason: 'INVALID_VERIFY_TOKEN' };
77
+ }
78
+
79
+ const sharedSecret = this.decryptSharedSecret(encryptedSharedSecret);
80
+
81
+ if (sharedSecret.length !== 16) {
82
+ return { success: false, reason: 'INVALID_SHARED_SECRET' };
83
+ }
84
+
85
+ const serverHash = this.computeServerHash(sharedSecret);
86
+ const verification = await this.verifyPlayer(username, serverHash, clientIP);
87
+
88
+ if (!verification.success) {
89
+ return { success: false, reason: verification.reason || 'AUTHENTICATION_FAILED' };
90
+ }
91
+
92
+ const encryptedConnection = this.createEncryptedConnection(sharedSecret);
93
+
94
+ return {
95
+ success: true,
96
+ uuid: verification.uuid,
97
+ name: verification.name,
98
+ properties: verification.properties || [],
99
+ encryption: encryptedConnection,
100
+ sharedSecret
101
+ };
102
+ }
103
+ }
104
+
105
+ export class ClientAuthHandler {
106
+ constructor(options = {}) {
107
+ this.accessToken = options.accessToken || null;
108
+ this.profileId = options.profileId || null;
109
+ }
110
+
111
+ async authenticateWithServer(serverPublicKey, verifyToken, serverId = '') {
112
+ const sharedSecret = MinecraftEncryption.generateSharedSecret();
113
+
114
+ const encryptedSharedSecret = MinecraftEncryption.encryptRSA(serverPublicKey, sharedSecret);
115
+ const encryptedVerifyToken = MinecraftEncryption.encryptRSA(serverPublicKey, verifyToken);
116
+
117
+ const serverHash = MinecraftEncryption.computeServerIdHash(serverId, sharedSecret, serverPublicKey);
118
+
119
+ if (this.accessToken && this.profileId) {
120
+ const result = await MojangAPI.joinServer(this.accessToken, this.profileId, serverHash);
121
+ if (!result.success) {
122
+ return { success: false, reason: result.error || 'JOIN_FAILED' };
123
+ }
124
+ }
125
+
126
+ const encryptedConnection = new EncryptedConnection(sharedSecret);
127
+
128
+ return {
129
+ success: true,
130
+ encryptedSharedSecret,
131
+ encryptedVerifyToken,
132
+ encryption: encryptedConnection,
133
+ sharedSecret
134
+ };
135
+ }
136
+ }
137
+
138
+ export default AuthHandler;