@@ -15,6 +15,7 @@ import {
15
15
makeBaseCompressedPacket ,
16
16
makeBasePacket ,
17
17
Packet ,
18
+ PacketDataTypes ,
18
19
parseCompressedPacket ,
19
20
parsePacket
20
21
} from './packet'
@@ -24,9 +25,9 @@ import {
24
25
resolveHostname ,
25
26
generateSharedSecret ,
26
27
mcHexDigest ,
27
- authUrl ,
28
28
protocolMap
29
29
} from './utils'
30
+ import { Certificate , joinMinecraftSession } from './api/mojang'
30
31
31
32
export interface ConnectionOptions {
32
33
host : string
@@ -35,6 +36,7 @@ export interface ConnectionOptions {
35
36
protocolVersion : number
36
37
selectedProfile ?: string
37
38
accessToken ?: string
39
+ certificate ?: Certificate
38
40
}
39
41
40
42
export declare interface ServerConnection {
@@ -92,6 +94,33 @@ export class ServerConnection extends events.EventEmitter {
92
94
}
93
95
}
94
96
97
+ const getLoginPacket = ( opts : ConnectionOptions ) => {
98
+ const data : PacketDataTypes [ ] = [ opts . username ]
99
+ if ( opts . protocolVersion >= protocolMap [ 1.19 ] ) {
100
+ data . push ( ! ! opts . certificate )
101
+ // TODO-1.19: Test if chat signing keys work.
102
+ if ( opts . certificate ) {
103
+ let buf = Buffer . alloc ( 8 )
104
+ buf . writeBigInt64BE (
105
+ BigInt ( new Date ( opts . certificate . expiresAt ) . getTime ( ) )
106
+ )
107
+ data . push ( buf )
108
+ const pkData = opts . certificate . keyPair . publicKey
109
+ . split ( '\n' )
110
+ . filter ( line => ! line . startsWith ( '-----' ) )
111
+ . join ( '' )
112
+ . trim ( )
113
+ buf = Buffer . from ( pkData , 'base64' )
114
+ data . push ( writeVarInt ( buf . byteLength ) )
115
+ data . push ( buf )
116
+ buf = Buffer . from ( opts . certificate . publicKeySignature , 'base64' )
117
+ data . push ( writeVarInt ( buf . byteLength ) )
118
+ data . push ( buf )
119
+ }
120
+ }
121
+ return concatPacketData ( data )
122
+ }
123
+
95
124
const initiateConnection = async ( opts : ConnectionOptions ) => {
96
125
const [ host , port ] = await resolveHostname ( opts . host , opts . port )
97
126
return await new Promise < ServerConnection > ( ( resolve , reject ) => {
@@ -112,20 +141,10 @@ const initiateConnection = async (opts: ConnectionOptions) => {
112
141
// Initialise Handshake with server.
113
142
socket . write ( makeBasePacket ( 0x00 , concatPacketData ( handshakeData ) ) , ( ) =>
114
143
// Send Login Start packet.
115
- socket . write (
116
- makeBasePacket (
117
- 0x00 ,
118
- concatPacketData (
119
- opts . protocolVersion < protocolMap [ 1.19 ]
120
- ? [ opts . username ]
121
- : [ opts . username , false ] // TODO-1.19: Support chat signing keys.
122
- )
123
- ) ,
124
- ( ) => {
125
- resolved = true
126
- resolve ( conn )
127
- }
128
- )
144
+ socket . write ( makeBasePacket ( 0x00 , getLoginPacket ( opts ) ) , ( ) => {
145
+ resolved = true
146
+ resolve ( conn )
147
+ } )
129
148
)
130
149
} )
131
150
socket . on ( 'close' , ( ) => {
@@ -197,16 +216,11 @@ const initiateConnection = async (opts: ConnectionOptions) => {
197
216
sha1 . update ( publicKey ) // Server's encoded public key from Encryption Request
198
217
const hash = mcHexDigest ( sha1 . digest ( ) )
199
218
// Send hash to Mojang servers.
200
- const body = JSON . stringify ( {
201
- accessToken,
202
- selectedProfile,
203
- serverId : hash
204
- } )
205
- const req = await fetch ( authUrl , {
206
- headers : { 'content-type' : 'application/json' } ,
207
- method : 'POST' ,
208
- body
209
- } )
219
+ const req = await joinMinecraftSession (
220
+ accessToken as string ,
221
+ selectedProfile as string ,
222
+ hash
223
+ )
210
224
if ( ! req . ok ) {
211
225
throw new Error ( 'Mojang online mode network request failed' )
212
226
}
0 commit comments