Skip to content

Commit 2a1727e

Browse files
committed
Fully asynchronus download
1 parent 436defc commit 2a1727e

File tree

10 files changed

+301
-162
lines changed

10 files changed

+301
-162
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.3.10",
3+
"version": "0.3.11",
44
"description": "Launcher for SimpleClient",
55
"main": "src/main.js",
66
"scripts": {

src/auth.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const { BrowserWindow } = require("electron")
2-
const { readFileSync, existsSync, writeFileSync } = require("original-fs")
2+
const { readFileSync, existsSync, writeFileSync } = require("fs")
33
const { getDirectory } = require("./util")
44
const { join } = require("path")
55

src/download/assetdownloader.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
const { join } = require("path")
2-
const { downloadFiles } = require("./downloader")
2+
const { downloadFilesAsync } = require("./downloader")
33
const { getMinecraftDir } = require("../util")
44
const { readFileSync } = require("fs")
55

66
const resourceUrl = 'https://resources.download.minecraft.net'
77

88
const log = (...data) => console.log('[Assets Download] ' + data)
99

10-
const downloadAssets = async meta => {
10+
const downloadAssets = (meta, callback) => {
1111
const dir = join(getMinecraftDir(), 'assets')
1212
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)]
13+
downloadFilesAsync([[meta.assetIndex.url, indexFile]], undefined, log, success => {
14+
if (success) {
15+
const index = JSON.parse(readFileSync(indexFile))
16+
const objects = Object.values(index.objects).map(object => {
17+
const hash = object.hash
18+
const subhash = hash.substring(0, 2)
19+
return [`${resourceUrl}/${subhash}/${hash}`, join(dir, 'objects', subhash, hash)]
20+
})
21+
downloadFilesAsync(objects, undefined, log, callback)
22+
} else callback(false)
1923
})
20-
return await downloadFiles(objects, undefined, log)
2124
}
2225

2326
module.exports = {downloadAssets}

src/download/downloader.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { spawnSync } = require("child_process")
1+
const { spawnSync, spawn } = require("child_process")
22
const { mkdirSync, existsSync } = require("fs")
33
const { dirname } = require("path")
44

@@ -28,4 +28,31 @@ const downloadFiles = async (downloads, filecount, logger) => {
2828
}
2929
}
3030

31-
module.exports = {downloadFiles}
31+
const downloadFilesAsync = (downloads, filecount, logger, callback) => {
32+
if (downloads.length == 0) callback(true)
33+
else if (filecount === undefined) {
34+
downloads = downloads.filter(download => !existsSync(download[1]))
35+
downloadFilesAsync(downloads, downloads.length, logger, callback)
36+
} else {
37+
const url = downloads[0][0]
38+
const file = downloads[0][1]
39+
const filename = url.split('/').pop()
40+
if (!existsSync(dirname(file))) {
41+
mkdirSync(dirname(file), {recursive: true})
42+
logger(`Successfully created directory ${dirname(file)} (${downloads.length}/${filecount} remaining)`)
43+
}
44+
logger(`Downloading ${url.split('/').pop()}...`)
45+
spawn('curl', ['--fail-with-body', '-L', url, '-o', file]).on('exit', (status, signal) => {
46+
if (status == 0) {
47+
downloads.shift()
48+
logger(`Successfully downloaded ${filename} (${downloads.length}/${filecount} remaining)`)
49+
downloadFilesAsync(downloads, filecount, logger, callback)
50+
} else {
51+
logger(`Couldn't download ${filename}; Trying again in 5 seconds... (${downloads.length}/${filecount} remaining)`)
52+
setTimeout(() => downloadFilesAsync(downloads, filecount, logger, callback), 5000)
53+
}
54+
})
55+
}
56+
}
57+
58+
module.exports = {downloadFiles, downloadFilesAsync}

src/download/fabricdownloader.js

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,47 @@
11
const { join } = require("path")
22
const { existsSync, statSync, rmSync } = require("fs")
3-
const { downloadFiles } = require("./downloader")
4-
const { spawnSync } = require("child_process")
3+
const { downloadFilesAsync } = require("./downloader")
4+
const { spawn } = require("child_process")
55
const { getDirectory, getMinecraftDir } = require("../util")
66
const { getJavaPath } = require("./javadownloader")
7-
const { env } = require("process")
87

98
const log = (...data) => console.log('[Fabric Download] ' + data)
109

11-
const downloadFabric = async (version, meta) => {
10+
function downloadJar(version, meta, callback) {
11+
const fabric = `fabric-loader-${version.fabric_version}-${version.minecraft_version}`
12+
const jar = join(getMinecraftDir(), 'versions', fabric, `${fabric}.jar`)
13+
if (existsSync(jar) && statSync(jar).size == 0) rmSync(jar)
14+
if (!existsSync(jar)) downloadFilesAsync([[meta.downloads.client.url, jar]], undefined, log, callback)
15+
else callback(true)
16+
}
17+
18+
const downloadFabric = (version, meta, callback) => {
1219
const fabric = `fabric-loader-${version.fabric_version}-${version.minecraft_version}`
1320
const fabricDir = join(getMinecraftDir(), 'versions', fabric)
14-
if (!existsSync(join(fabricDir, `${fabric}.json`))) {
15-
const fabricInstallerResponse = await fetch('https://meta.fabricmc.net/v2/versions/installer')
16-
if (!fabricInstallerResponse) return false
17-
const fabricInstallerJson = await fabricInstallerResponse.json()
18-
const fabricInstallerFile = join(getDirectory(), 'versions', version.id, `fabric-installer-${fabricInstallerJson[0].version}.jar`)
19-
if (!downloadFiles([[fabricInstallerJson[0].url, fabricInstallerFile]], undefined, log)) return false
20-
log('Executing Fabric installer...')
21-
const args = ['-jar', fabricInstallerFile, 'client', '-dir', getMinecraftDir(), '-mcversion', version.minecraft_version, '-loader', version.fabric_version, '-noprofile']
22-
if (spawnSync(join(getJavaPath(meta.javaVersion.component), 'bin', 'javaw'), args, {
23-
cwd: getDirectory()
24-
}).signal != 0) return false
25-
log('Successfully installed Fabric Loader')
21+
if (existsSync(join(fabricDir, `${fabric}.json`))) downloadJar(version, meta, callback)
22+
else {
23+
fetch('https://meta.fabricmc.net/v2/versions/installer').then(fabricInstallerResponse => {
24+
if (fabricInstallerResponse) {
25+
fabricInstallerResponse.json().then(fabricInstallerJson => {
26+
const fabricInstallerFile = join(getDirectory(), 'versions', version.id, `fabric-installer-${fabricInstallerJson[0].version}.jar`)
27+
downloadFilesAsync([[fabricInstallerJson[0].url, fabricInstallerFile]], undefined, log, succes => {
28+
if (succes) {
29+
log('Executing Fabric installer...')
30+
const args = ['-jar', fabricInstallerFile, 'client', '-dir', getMinecraftDir(), '-mcversion', version.minecraft_version, '-loader', version.fabric_version, '-noprofile']
31+
spawn(join(getJavaPath(meta.javaVersion.component), 'bin', 'javaw'), args, {
32+
cwd: getDirectory()
33+
}).on('exit', (code, signal) => {
34+
if (code == 0) {
35+
log('Successfully installed Fabric Loader')
36+
downloadJar(version, meta, callback)
37+
} else callback(false)
38+
})
39+
} else callback(false)
40+
})
41+
})
42+
} else callback(false)
43+
})
2644
}
27-
if (statSync(join(fabricDir, `${fabric}.jar`)).size == 0) rmSync(join(fabricDir, `${fabric}.jar`))
28-
if (!existsSync(join(fabricDir, `${fabric}.jar`))) {
29-
return await downloadFiles([[meta.downloads.client.url, join(fabricDir, `${fabric}.jar`)]], undefined, log)
30-
} else return true
3145
}
3246

3347
module.exports = {downloadFabric}

src/download/javadownloader.js

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const { platform } = require("os")
22
const { getDirectory } = require("../util")
33
const { join } = require("path")
4-
const { downloadFiles } = require("./downloader")
4+
const { downloadFiles, downloadFilesAsync } = require("./downloader")
55

66
const javaUrl = 'https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json'
77

@@ -11,43 +11,43 @@ const getJavaPath = (version = 'java-runtime-gamma') => {
1111
return join(getDirectory(), 'java', version)
1212
}
1313

14-
async function getJavaDownloadsUrl(version) {
15-
try {
16-
const response = await fetch(javaUrl, {timeout: 5000})
14+
function getJavaDownloadsUrl(version, callback) {
15+
fetch(javaUrl, {timeout: 5000}).then(response => {
1716
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) {
17+
response.json().then(json => {
18+
if (platform() == 'win32') callback(json['windows-x64'][version][0].manifest.url)
19+
else if (platform() == 'linux') callback(json['linux'][version][0].manifest.url)
20+
else callback(undefined)
21+
})
22+
} else callback(undefined)
23+
}).catch(error => {
2424
log('Couldn\'t fetch Java download URL. Trying again in 5 seconds...')
25-
return await getJavaDownloadsUrl(version)
26-
}
25+
setTimeout(5000, () => getJavaDownloadsUrl(version, callback))
26+
})
2727
}
2828

29-
async function getJavaDownloads(url) {
30-
try {
31-
const response = await fetch(url, {timeout: 5000})
29+
function getJavaDownloads(url, callback) {
30+
fetch(url, {timeout: 5000}).then(response => {
3231
if (response && response.ok) {
33-
const json = await response.json()
34-
return Object.entries(json.files).filter(download => download[1].type == 'file')
32+
response.json().then(json => callback(Object.entries(json.files).filter(download => download[1].type == 'file')))
3533
} else return undefined
36-
} catch (error) {
34+
}).catch(error => {
3735
log('Couldn\'t fetch Java files. Trying again in 5 seconds...\n' + error)
38-
return await getJavaDownloads(url)
39-
}
36+
setTimeout(5000, () => getJavaDownloads(url, callback))
37+
})
4038
}
4139

42-
const downloadJava = async (version = 'java-runtime-gamma') => {
40+
const downloadJava = (version, callback) => {
4341
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
42+
getJavaDownloadsUrl(version, url => {
43+
if (url) {
44+
getJavaDownloads(url, downloads => {
45+
console.log(downloads)
46+
downloads = downloads.map(download => [download[1].downloads.raw.url, join(dir, download[0])])
47+
downloadFilesAsync(downloads, undefined, log, callback)
48+
})
49+
} else callback(false)
50+
})
5151
}
5252

5353
module.exports = {getJavaPath, downloadJava}

src/download/librarydownloader.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
const { join } = require("path")
2-
const { downloadFiles } = require("./downloader")
2+
const { downloadFilesAsync } = require("./downloader")
33
const { getMinecraftDir } = require("../util")
44

55
const log = (...data) => console.log('[Library Download] ' + data)
66

7-
const downloadLibraries = async meta => {
7+
const downloadLibraries = (meta, callback) => {
88
const dir = join(getMinecraftDir(), 'libraries')
99
const libraries = meta.libraries.map(library => [library.downloads.artifact.url, join(dir, library.downloads.artifact.path)])
10-
return await downloadFiles(libraries, undefined, log)
10+
downloadFilesAsync(libraries, undefined, log, callback)
1111
}
1212

1313
module.exports = {downloadLibraries}

src/download/moddownloader.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
const { join } = require("path")
2-
const { downloadFiles } = require("./downloader")
2+
const { downloadFilesAsync } = require("./downloader")
33
const { getDirectory } = require("../util")
44

55
const log = (...data) => console.log('[Mods Download] ' + data)
66

7-
const downloadMods = async version => {
7+
const downloadMods = (version, callback) => {
88
const dir = join(getDirectory(), 'versions', version.id, 'mods')
99
const mods = version.mods.map(mod => [mod, join(dir, mod.split('/')[mod.split('/').length - 1])])
10-
return await downloadFiles(mods, undefined, log)
10+
downloadFilesAsync(mods, undefined, log, callback)
1111
}
1212

1313
module.exports = {downloadMods}

src/launch.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
const { Worker, parentPort } = require('worker_threads')
2-
const { isMainThread, workerData } = require('worker_threads')
1+
const { Worker, parentPort, isMainThread, workerData } = require('worker_threads')
32

43
if (!isMainThread) require('./minecraft').launch(workerData.version, workerData.account, status => parentPort.postMessage(status))
54

6-
const launch = async (version, account, statusCallback) => {
7-
new Worker(__filename, {
8-
workerData: {
9-
version: version,
10-
account: account
11-
},
12-
}).on('message', statusCallback)
5+
const launch = (version, account, statusCallback) => {
6+
statusCallback('starting')
7+
statusCallback('authenticating')
8+
require('./auth').refreshTokens(account).then(success => {
9+
if (success) {
10+
new Worker(__filename, {
11+
workerData: {
12+
version: version,
13+
account: account
14+
},
15+
}).on('message', statusCallback)
16+
} else statusCallback('error')
17+
})
1318
}
1419

1520
module.exports = {launch}

0 commit comments

Comments
 (0)