Skip to content

Commit 9ccf800

Browse files
committed
Force Downloading
1 parent 9ab7453 commit 9ccf800

File tree

15 files changed

+268
-299
lines changed

15 files changed

+268
-299
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "simplelauncher",
3-
"version": "0.2.0",
3+
"version": "0.3.0",
44
"description": "Launcher for SimpleClient",
55
"main": "src/main.js",
66
"scripts": {

src/auth.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,14 @@ const getMicrosoftData = async authorizationCode => {
137137
}
138138

139139
const getMicrosoftDataByRefreshToken = async refreshToken => {
140-
const response = await fetch('https://login.microsoftonline.com/consumers/oauth2/v2.0/token?', {
140+
const response = await fetch('https://login.microsoftonline.com/consumers/oauth2/v2.0/token', {
141141
method: 'POST',
142142
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
143143
body: new URLSearchParams({
144144
client_id: azureClientId,
145145
scope: scope,
146146
refresh_token: refreshToken,
147-
redirect_uri: redirectUrl,
148-
grant_type: 'authorization_code'
147+
grant_type: 'refresh_token'
149148
})
150149
})
151150
if (response && response.ok) return await response.json()
@@ -225,9 +224,9 @@ const refreshTokens = async account => {
225224
var time = new Date().getTime()
226225
if (account.minecraft_access_tokens.find(token => token.expiration > time)) return true
227226
var xstsAccessToken = account.xsts_access_tokens.find(token => token.expiration > time)
228-
var userhash = account.xbox_access_tokens.find(token => token.expiration > time).userhash
227+
var userhash
229228
if (!xstsAccessToken) {
230-
var xboxLiveAccessToken = account.xbox_access_tokens.find(token => token.expiration > time).token
229+
var xboxLiveAccessToken = account.xbox_access_tokens.find(token => token.expiration > time)?.token
231230
if (!xboxLiveAccessToken) {
232231
var microsoftAccessToken = account.microsoft_access_tokens.find(token => token.expiration > time)
233232
if (!microsoftAccessToken) {
@@ -258,6 +257,7 @@ const refreshTokens = async account => {
258257
expiration: new Date(xstsData.NotAfter).getTime()
259258
}]
260259
}
260+
if (!userhash) userhash = account.xbox_access_tokens.find(token => token.expiration > time).userhash
261261
var minecraftData = await getMinecraftData(userhash, xstsAccessToken)
262262
if (!minecraftData) return false
263263
var minecraftAccessToken = minecraftData.access_token

src/download/assetdownloader.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const { join } = require("path")
2+
const { downloadFiles } = require("./downloader")
3+
const { getMinecraftDir } = require("../util")
4+
const { readFileSync } = require("fs")
5+
6+
const resourceUrl = 'https://resources.download.minecraft.net'
7+
8+
const log = (...data) => console.log('[Assets Download] ' + data)
9+
10+
const downloadAssets = async meta => {
11+
const dir = join(getMinecraftDir(), 'assets')
12+
const indexFile = join(dir, 'indexes', `${meta.assetIndex.id}.json`)
13+
if (!downloadFiles([[meta.assetIndex.url, indexFile]], undefined, log)) return false
14+
const index = JSON.parse(readFileSync(indexFile))
15+
const objects = Object.values(index.objects).map(object => {
16+
const hash = object.hash
17+
const subhash = hash.substring(0, 2)
18+
return [`${resourceUrl}/${subhash}/${hash}`, join(dir, 'objects', subhash, hash)]
19+
})
20+
return await downloadFiles(objects, undefined, log)
21+
}
22+
23+
module.exports = {downloadAssets}

src/download/downloader.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const { spawnSync } = require("child_process")
2+
const { mkdirSync, existsSync } = require("fs")
3+
const { dirname } = require("path")
4+
5+
const downloadFiles = async (downloads, filecount, logger) => {
6+
if (downloads.length == 0) return true
7+
else if (filecount === undefined) {
8+
downloads = downloads.filter(download => !existsSync(download[1]))
9+
return await downloadFiles(downloads, downloads.length, logger)
10+
} else {
11+
const url = downloads[0][0]
12+
const file = downloads[0][1]
13+
const filename = url.split('/').pop()
14+
if (!existsSync(dirname(file))) {
15+
mkdirSync(dirname(file), {recursive: true})
16+
logger(`Successfully created directory ${dirname(file)} (${downloads.length}/${filecount} remaining)`)
17+
}
18+
logger(`Downloading ${url.split('/').pop()}...`)
19+
if (spawnSync('curl', ['--fail-with-body', '-L', url, '-o', file]).status == 0) {
20+
downloads.shift()
21+
logger(`Successfully downloaded ${filename} (${downloads.length}/${filecount} remaining)`)
22+
return await downloadFiles(downloads, filecount, logger)
23+
} else {
24+
logger(`Couldn't download ${filename}; Trying again in 5 seconds... (${downloads.length}/${filecount} remaining)`)
25+
await new Promise(resolve => setTimeout(resolve, 5000))
26+
return await downloadFiles(downloads, filecount, logger)
27+
}
28+
}
29+
}
30+
31+
module.exports = {downloadFiles}

src/download/fabricdownloader.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const { join } = require("path")
2+
const { existsSync, statSync } = require("fs")
3+
const { downloadFiles } = require("./downloader")
4+
const { spawnSync } = require("child_process")
5+
const { getDirectory, getMinecraftDir } = require("../util")
6+
const { getJavaPath } = require("./javadownloader")
7+
8+
const log = (...data) => console.log('[Fabric Download] ' + data)
9+
10+
const downloadFabric = async (version, meta) => {
11+
const fabric = `fabric-loader-${version.fabric_version}-${version.minecraft_version}`
12+
const fabricDir = join(getMinecraftDir(), 'versions', fabric)
13+
if (!existsSync(join(fabricDir, `${fabric}.json`))) {
14+
const fabricInstallerResponse = await fetch('https://meta.fabricmc.net/v2/versions/installer')
15+
if (!fabricInstallerResponse) return false
16+
const fabricInstallerJson = await fabricInstallerResponse.json()
17+
const fabricInstallerFile = join(dir, `fabric-installer-${fabricInstallerJson[0].version}.jar`)
18+
if (!downloadFiles([[fabricInstallerJson[0].url, fabricInstallerFile]], undefined, log)) return false
19+
log('Executing Fabric installer...')
20+
const args = ['-jar', fabricInstallerFile, 'client', '-dir', getMinecraftDir(), '-mcversion', version.minecraft_version, '-loader', version.fabric_version, '-noprofile']
21+
if (spawnSync('javaw', args, {
22+
cwd: getDirectory(),
23+
env: {PATH: getJavaPath(meta.javaVersion.component)}
24+
}).signal != 0) return false
25+
log('Successfully installed Fabric Loader')
26+
}
27+
if (!existsSync(join(fabricDir, `${fabric}.jar`)) || statSync(join(fabricDir, `${fabric}.jar`)).size == 0) {
28+
return await downloadFiles([[meta.downloads.client.url, join(fabricDir, `${fabric}.jar`)]], undefined, log)
29+
} else return true
30+
}
31+
32+
module.exports = {downloadFabric}

src/download/javadownloader.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const { platform } = require("os")
2+
const { getDirectory } = require("../util")
3+
const { join } = require("path")
4+
const { downloadFiles } = require("./downloader")
5+
6+
const javaUrl = 'https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json'
7+
8+
const log = (...data) => console.log('[Java Download] ' + data)
9+
10+
const getJavaPath = (version = 'java-runtime-gamma') => {
11+
return join(getDirectory(), 'java', version)
12+
}
13+
14+
async function getJavaDownloadsUrl(version) {
15+
try {
16+
const response = await fetch(javaUrl, {timeout: 5000})
17+
if (response && response.ok) {
18+
const json = await response.json()
19+
if (platform() == 'win32') return json['windows-x64'][version][0].manifest.url
20+
else if (platform() == 'linux') return json['linux'][version][0].manifest.url
21+
else return undefined
22+
} else return undefined
23+
} catch(error) {
24+
log('Couldn\'t fetch Java download URL. Trying again in 5 seconds...')
25+
return await getJavaDownloadsUrl(version)
26+
}
27+
}
28+
29+
async function getJavaDownloads(url) {
30+
try {
31+
const response = await fetch(url, {timeout: 5000})
32+
if (response && response.ok) {
33+
const json = await response.json()
34+
return Object.entries(json.files).filter(download => download[1].type == 'file')
35+
} else return undefined
36+
} catch (error) {
37+
log('Couldn\'t fetch Java files. Trying again in 5 seconds...\n' + error)
38+
return await getJavaDownloads(url)
39+
}
40+
}
41+
42+
const downloadJava = async (version = 'java-runtime-gamma') => {
43+
const dir = join(getDirectory(), 'java', version)
44+
const url = await getJavaDownloadsUrl(version)
45+
if (url) {
46+
var downloads = await getJavaDownloads(url)
47+
downloads = downloads.map(download => [download[1].downloads.raw.url, join(dir, download[0])])
48+
if (downloads) return await downloadFiles(downloads, undefined, log)
49+
else return false
50+
} else return false
51+
}
52+
53+
module.exports = {getJavaPath, downloadJava}

src/download/librarydownloader.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const { join } = require("path")
2+
const { downloadFiles } = require("./downloader")
3+
const { getMinecraftDir } = require("../util")
4+
5+
const log = (...data) => console.log('[Library Download] ' + data)
6+
7+
const downloadLibraries = async meta => {
8+
const dir = join(getMinecraftDir(), 'libraries')
9+
const libraries = meta.libraries.map(library => [library.downloads.artifact.url, join(dir, library.downloads.artifact.path)])
10+
return await downloadFiles(libraries, undefined, log)
11+
}
12+
13+
module.exports = {downloadLibraries}

src/download/metadownloader.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const { join } = require("path")
2+
const { downloadFiles } = require("./downloader")
3+
const { getMinecraftDir } = require("../util")
4+
5+
const metaUrl = 'https://launchermeta.mojang.com/mc/game/version_manifest.json'
6+
7+
const log = (...data) => console.log('[Meta Download] ' + data)
8+
9+
const downloadMeta = async version => {
10+
const metaManifestResponse = await fetch(metaUrl)
11+
if (!metaManifestResponse || !metaManifestResponse.ok) return false
12+
const metaManifest = (await metaManifestResponse.json()).versions.find(ver => ver.id == version.minecraft_version)
13+
return await downloadFiles([[metaManifest.url, join(getMinecraftDir(), 'versions', version.minecraft_version, `${version.minecraft_version}.json`)]], undefined, log)
14+
}
15+
16+
module.exports = {downloadMeta}

src/download/moddownloader.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const { join } = require("path")
2+
const { downloadFiles } = require("./downloader")
3+
const { getDirectory } = require("../util")
4+
5+
const log = (...data) => console.log('[Mods Download] ' + data)
6+
7+
const downloadMods = async version => {
8+
const dir = join(getDirectory(), 'versions', version.id, 'mods')
9+
const mods = version.mods.map(mod => [mod, join(dir, mod.split('/')[mod.split('/').length - 1])])
10+
return await downloadFiles(mods, undefined, log)
11+
}
12+
13+
module.exports = {downloadMods}

src/gui/index.html

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,33 +25,30 @@
2525
if (status == 'starting') {
2626
document.getElementById('launch').disabled = true
2727
document.getElementById('launch').innerText = 'Launching'
28-
} else if (status == 'download_starting') {
28+
} else if (status == 'downloading') {
2929
document.getElementById('launch').innerText = 'Downloading'
30-
} else if (status == 'downloading_java_starting') {
30+
} else if (status == 'downloading_meta') {
31+
document.getElementById('launch').innerText = 'Downloading Metadata'
32+
} else if (status == 'downloading_java') {
3133
document.getElementById('launch').innerText = 'Downloading Java'
32-
} else if (status == 'downloading_java_done') {
33-
document.getElementById('launch').innerText = 'Downloading'
34-
} else if (status == 'downloading_libraries_starting') {
34+
} else if (status == 'downloading_fabric') {
35+
document.getElementById('launch').innerText = 'Downloading Fabric Loader'
36+
} else if (status == 'downloading_libraries') {
3537
document.getElementById('launch').innerText = 'Downloading Libraries'
36-
} else if (status == 'downloading_libraries_done') {
37-
document.getElementById('launch').innerText = 'Downloading'
38-
} else if (status == 'downloading_assets_starting') {
38+
} else if (status == 'downloading_assets') {
3939
document.getElementById('launch').innerText = 'Downloading Assets'
40-
} else if (status == 'downloading_assets_done') {
41-
document.getElementById('launch').innerText = 'Downloading'
42-
} else if (status == 'downloading_mods_starting') {
40+
} else if (status == 'downloading_mods') {
4341
document.getElementById('launch').innerText = 'Downloading Mods'
44-
} else if (status == 'downloading_mods_done') {
45-
document.getElementById('launch').innerText = 'Downloading'
46-
} else if (status == 'download_done') {
47-
document.getElementById('launch').innerText = 'Launching'
4842
} else if (status == 'authenticating') {
4943
document.getElementById('launch').innerText = 'Authenticating'
5044
} else if (status == 'launching') {
5145
document.getElementById('launch').innerText = 'Launching'
52-
} else if (status == 'done' || status == 'error') {
46+
} else if (status == 'done') {
5347
document.getElementById('launch').disabled = false
5448
document.getElementById('launch').innerText = `LAUNCH ${document.getElementById('versions-button').innerText}`
49+
} else if (status == 'error') {
50+
document.getElementById('launch').disabled = false
51+
document.getElementById('launch').innerText = 'An error ocurred'
5552
}
5653
})
5754
</script>

0 commit comments

Comments
 (0)