@@ -11,6 +11,7 @@ import {
11
11
} from 'react-native'
12
12
import { Picker } from '@react-native-picker/picker'
13
13
import Ionicons from 'react-native-vector-icons/Ionicons'
14
+ import { NativeStackScreenProps } from '@react-navigation/native-stack'
14
15
import allSettled from 'promise.allsettled'
15
16
16
17
import globalStyle from '../globalStyle'
@@ -26,50 +27,33 @@ import TextField from '../components/TextField'
26
27
import ElevatedView from '../components/ElevatedView'
27
28
import useDarkMode from '../context/useDarkMode'
28
29
import ServersContext from '../context/serversContext'
30
+ import useSessionStore from '../context/sessionStore'
29
31
import SettingsContext from '../context/settingsContext'
30
32
import AccountsContext from '../context/accountsContext'
31
33
import ConnectionContext from '../context/connectionContext'
32
- import { resolveHostname , protocolMap } from '../minecraft/utils'
33
- import initiateConnection from '../minecraft/connection'
34
- import {
35
- refreshMSAuthToken ,
36
- getXboxLiveTokenAndUserHash ,
37
- getXstsTokenAndUserHash ,
38
- authenticateWithXsts
39
- } from '../minecraft/api/microsoft'
40
- import { Certificate , getPlayerCertificates } from '../minecraft/api/mojang'
41
- import { refresh } from '../minecraft/api/yggdrasil'
34
+ import { parseIp , protocolMap } from '../minecraft/utils'
42
35
import {
43
36
ChatToJsx ,
44
37
lightColorMap ,
45
- mojangColorMap ,
46
- parseValidJson
38
+ mojangColorMap
47
39
} from '../minecraft/chatToJsx'
48
- import config from '../../config.json '
40
+ import { createConnection } from './chat/sessionBuilder '
49
41
50
- const parseIp = ( ipAddress : string ) : [ string , number ] => {
51
- const splitAddr = ipAddress . split ( ':' )
52
- const portStr = splitAddr . pop ( ) || ''
53
- let port = + portStr
54
- if ( isNaN ( + portStr ) ) {
55
- splitAddr . push ( portStr )
56
- port = 25565
57
- }
58
- return [ splitAddr . join ( ':' ) , port ]
42
+ interface RootStackParamList {
43
+ [ index : string ] : any
44
+ Home : undefined
45
+ Chat : { serverName : string ; version : number }
59
46
}
47
+ type Props = NativeStackScreenProps < RootStackParamList , 'Chat' >
60
48
61
- interface Session {
62
- certificate ?: Certificate
63
- accessToken : string
64
- }
65
-
66
- const ServerScreen = ( ) => {
49
+ const ServerScreen = ( props : Props ) => {
67
50
const darkMode = useDarkMode ( )
68
51
const { settings } = useContext ( SettingsContext )
69
52
const { servers, setServers } = useContext ( ServersContext )
70
53
const { accounts, setAccounts } = useContext ( AccountsContext )
71
54
const { connection, setConnection, setDisconnectReason } =
72
55
useContext ( ConnectionContext )
56
+ const { sessions, setSession } = useSessionStore ( )
73
57
const initiatingConnection = useRef ( false )
74
58
75
59
const [ ipAddr , setIpAddr ] = useState ( '' )
@@ -86,7 +70,6 @@ const ServerScreen = () => {
86
70
// false - no route, null - unknown err, undefined - pinging
87
71
[ ip : string ] : LegacyPing | Ping | false | null | undefined
88
72
} > ( { } )
89
- const [ sessions , setSessions ] = useState < { [ uuid : string ] : Session } > ( { } )
90
73
91
74
useEffect ( ( ) => {
92
75
if ( Object . keys ( pingResponses ) . length > 0 ) {
@@ -168,116 +151,41 @@ const ServerScreen = () => {
168
151
if ( initiatingConnection . current ) return
169
152
if ( ! connection ) {
170
153
initiatingConnection . current = true
171
- const [ hostname , portNumber ] = parseIp ( servers [ server ] . address )
172
- const [ host , port ] = await resolveHostname ( hostname , portNumber )
173
- const activeAccount = Object . keys ( accounts ) . find ( e => accounts [ e ] . active )
174
- if ( ! activeAccount ) {
175
- initiatingConnection . current = false
176
- return setDisconnectReason ( {
177
- server,
178
- reason :
179
- 'No active account selected! Open the Accounts tab and add an account.'
180
- } )
181
- }
182
- let protocolVersion = protocolMap [ servers [ server ] . version ]
183
- if ( protocolVersion === - 1 ) {
154
+ let version = protocolMap [ servers [ server ] . version ]
155
+ if ( version === - 1 ) {
184
156
const ping = pingResponses [ servers [ server ] . address ]
185
157
// Try the latest.
186
158
// TODO: Make 1.19 the default.
187
- if ( ! ping ) protocolVersion = protocolMap [ '1.18.2' ]
159
+ if ( ! ping ) version = protocolMap [ '1.18.2' ]
188
160
else if ( typeof ping . version === 'object' ) {
189
- protocolVersion = ping . version . protocol
190
- } else protocolVersion = ( ping as LegacyPing ) . protocol
161
+ version = ping . version . protocol
162
+ } else version = ( ping as LegacyPing ) . protocol
191
163
}
192
- if ( protocolVersion < 754 ) {
164
+ if ( version < 754 ) {
193
165
initiatingConnection . current = false
194
166
return setDisconnectReason ( {
195
167
server,
196
168
reason : 'EnderChat only supports 1.16.4 and newer (for now).'
197
169
} )
198
170
}
199
- const uuid = accounts [ activeAccount ] . type ? activeAccount : undefined
200
-
201
- // Create an updated "session" containing access tokens and certificates.
202
171
// LOW-TODO: Creating a session would be better with a loading screen, since Microsoft Login is slow.
203
172
// Maybe setConnection(null) to bring up ChatScreen while still being in a logged out state?
204
- let session = sessions [ activeAccount ]
205
- const is119 = protocolVersion >= protocolMap [ 1.19 ]
206
- if ( uuid && ( ! session || ( ! session . certificate && is119 ) ) ) {
207
- // LOW-TODO: Certificates and access tokens should be updated regularly.
208
- try {
209
- // Create a session with the latest access token.
210
- const account = accounts [ activeAccount ]
211
- if ( ! session && accounts [ activeAccount ] . type === 'microsoft' ) {
212
- const [ msAccessToken , msRefreshToken ] = await refreshMSAuthToken (
213
- accounts [ activeAccount ] . microsoftRefreshToken || '' ,
214
- config . clientId ,
215
- config . scope
216
- )
217
- const [ xlt , xuh ] = await getXboxLiveTokenAndUserHash ( msAccessToken )
218
- const [ xstsToken ] = await getXstsTokenAndUserHash ( xlt )
219
- const accessToken = await authenticateWithXsts ( xstsToken , xuh )
220
- session = { accessToken }
221
- setAccounts ( {
222
- [ activeAccount ] : {
223
- ...account ,
224
- accessToken,
225
- microsoftAccessToken : msAccessToken ,
226
- microsoftRefreshToken : msRefreshToken
227
- }
228
- } )
229
- } else if ( ! session && accounts [ activeAccount ] . type === 'mojang' ) {
230
- const { accessToken, clientToken } = await refresh (
231
- accounts [ activeAccount ] . accessToken || '' ,
232
- accounts [ activeAccount ] . clientToken || '' ,
233
- false
234
- )
235
- session = { accessToken }
236
- setAccounts ( {
237
- [ activeAccount ] : { ...account , accessToken, clientToken }
238
- } )
239
- }
240
- // If connecting to 1.19, get player certificates.
241
- if ( ! session . certificate && is119 ) {
242
- const token = session . accessToken
243
- session . certificate = await getPlayerCertificates ( token )
244
- }
245
- setSessions ( { [ activeAccount ] : session } )
246
- } catch ( e ) {
247
- const reason =
248
- 'Failed to create session! You may need to re-login with your Microsoft Account in the Accounts tab.'
249
- setDisconnectReason ( { server, reason } )
250
- initiatingConnection . current = false
251
- return
252
- }
253
- }
254
-
255
- // Connect to server after setting up the session.
173
+ // Or delegate this task to ChatScreen? Would make initiatingConnectionRef unnecessary.
256
174
try {
257
- const newConn = await initiateConnection ( {
258
- host,
259
- port,
260
- username : accounts [ activeAccount ] . username ,
261
- protocolVersion,
262
- selectedProfile : uuid ,
263
- accessToken : session ?. accessToken ,
264
- certificate : settings . enableChatSigning
265
- ? session ?. certificate
266
- : undefined
267
- } )
268
- const onCloseOrError = ( ) => {
269
- setConnection ( undefined )
270
- if ( newConn . disconnectReason ) {
271
- const reason = parseValidJson ( newConn . disconnectReason )
272
- setDisconnectReason ( { server, reason } )
273
- }
274
- }
275
- newConn . on ( 'close' , onCloseOrError )
276
- newConn . on ( 'error' , onCloseOrError )
277
- setConnection ( { serverName : server , connection : newConn } )
278
- } catch ( e ) {
279
- setDisconnectReason ( { server, reason : 'Failed to connect to server!' } )
280
- }
175
+ await createConnection (
176
+ server ,
177
+ version ,
178
+ servers ,
179
+ settings ,
180
+ accounts ,
181
+ sessions ,
182
+ setSession ,
183
+ setAccounts ,
184
+ setConnection ,
185
+ setDisconnectReason ,
186
+ ( ) => { }
187
+ )
188
+ } catch ( e ) { }
281
189
initiatingConnection . current = false
282
190
}
283
191
}
@@ -445,12 +353,7 @@ const ServerScreen = () => {
445
353
const styles = StyleSheet . create ( {
446
354
serverView : { marginBottom : 12 } ,
447
355
serverPressable : { padding : 8 , flexDirection : 'row' } ,
448
- serverImage : {
449
- resizeMode : 'contain' ,
450
- padding : 4 ,
451
- height : 72 ,
452
- width : 72
453
- } ,
356
+ serverImage : { resizeMode : 'contain' , padding : 4 , height : 72 , width : 72 } ,
454
357
serverLoading : {
455
358
justifyContent : 'center' ,
456
359
alignItems : 'center' ,
0 commit comments