diff --git a/.gitignore b/.gitignore index 48dea98..938aeb4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ node_modules/ game out/ .vscode/ -launcher.json *.code-workspace diff --git a/config.forge.js b/config.forge.js index 6685f67..a879823 100644 --- a/config.forge.js +++ b/config.forge.js @@ -1,4 +1,6 @@ const path = require('path'); +const pkg = require('./package.json') + module.exports = { packagerConfig: { packageName: "altarik-launcher", @@ -11,11 +13,11 @@ module.exports = { name: "@electron-forge/maker-squirrel", platforms: ['darwin', 'win32'], config: { - name: "altarik-launcher", + name: pkg.name, iconUrl: path.resolve(__dirname, 'icon.ico'), //loadingGif: path.resolve(__dirname, 'src/assets/loading.gif'), setupIcon: path.resolve(__dirname, 'icon.ico'), - setupExe: "altarik-launcher-win32-x64.exe" + setupExe: `${pkg.name}-${pkg.version}-win32-x64.exe` } } ] diff --git a/launcher.json b/launcher.json new file mode 100644 index 0000000..019ecdc --- /dev/null +++ b/launcher.json @@ -0,0 +1,68 @@ +{ + "chapters": [ + { + "title": "Chapitre 1", + "description": "Egypte", + "minecraftVersion": "1.16.5", + "type": "release", + "customVersion": "fabric-loader-0.11.3-1.16.5", + "modspack": { + "mods": [ + "https://www.dropbox.com/s/ww6a052nzzgojdm/modpack.zip?dl=1", + "https://www.dropbox.com/s/rn72wq0qxd5xk8a/building-blocks-1.0.0.zip?dl=1" + ], + "sha1sum": [ + "97de8fab9a1a3448fcded5dd33b0d3b879e1caa2", + "a9ff83d9e8c814d6393a8b4c9e610dda5b952195" + ] + }, + "java": { + "platform": { + "win32": { + "x64": { + "name": "jdk8u292-b10-jre", + "link": "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jre_x64_windows_hotspot_8u292b10.zip", + "sha256sum": "df79660dbc00687928d870d5f9ac91d5dfdd69be2131d5b4b2457b77fc486f54" + }, + "ia32": { + "name": "jdk8u292-b10-jre", + "link": "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jre_x86-32_windows_hotspot_8u292b10.zip", + "sha256sum": "ee1c52c109bb5b05acb3304f9a9494de01ee7e9a95f33e16627ea916e0f48a2f" + } + } + } + } + }, + { + "title": "Dev", + "description": "Dev", + "minecraftVersion": "21w19a", + "type": "snapshot", + "customVersion": "fabric-loader-0.11.3-21w19a", + "modspack": { + "mods": [ + "https://www.dropbox.com/s/dcs3euf1l6xs6er/dev.zip?dl=1" + ], + "sha1sum": [ + "5ba97cf05d43250bd94210ad085f8ff2278c55be" + ] + }, + "java": { + "platform": { + "win32": { + "x64": { + "name": "jdk-16.0.1+9-jre", + "link": "https://github.com/AdoptOpenJDK/openjdk16-binaries/releases/download/jdk-16.0.1%2B9/OpenJDK16U-jre_x64_windows_hotspot_16.0.1_9.zip", + "sha256sum": "169b7975e01bd6573062d29a5f2a1c7c4b659ada9de69c4a63328f2936d0f3f9" + }, + "ia32": { + "name": "jdk-16.0.1+9-jre", + "link" : "https://github.com/AdoptOpenJDK/openjdk16-binaries/releases/download/jdk-16.0.1%2B9/OpenJDK16U-jre_x86-32_windows_hotspot_16.0.1_9.zip", + "sha256sum" : "b58fa948e50d1822c50bf45cc34e58eaf4018e0ae41d0221746313077ac336fe" + } + } + } + } + } + ] +} diff --git a/package-lock.json b/package-lock.json index 9616b94..85590ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4090,14 +4090,6 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "sha1-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sha1-file/-/sha1-file-2.0.0.tgz", - "integrity": "sha512-ejHwMRlsshtZF/UVYfuzq0B4jSUFPxBgbBUnYr1sS4K7i9j5Ix6bz2ZxxDIXB6tqZCVv08Gjp1McFkoGIsa7Jw==", - "requires": { - "hasha": "^5.2.0" - } - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/package.json b/package.json index e431f43..2b3ad81 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,8 @@ "electron-log": "^4.3.5", "electron-squirrel-startup": "^1.0.0", "extract-zip": "^2.0.1", - "minecraft-launcher-core": "^3.16.3", - "sha1-file": "^2.0.0" + "hasha": "^5.2.2", + "minecraft-launcher-core": "^3.16.3" }, "config": { "forge": "./config.forge.js" diff --git a/src/server/main.js b/src/server/main.js index 193ce9f..a034d6b 100644 --- a/src/server/main.js +++ b/src/server/main.js @@ -64,6 +64,10 @@ ipcMain.on("login", (event, args) => { minecraft.login(event, win, showNotification, args.user, args.pass) }) +ipcMain.on("launch", (event, args) => { + minecraft.launch(event, showNotification, args) +}) + function showNotification(title, body="") { new Notification({ title: title, body: body }).show() } @@ -72,10 +76,6 @@ ipcMain.on("notification", (event, args) => { showNotification(args.title, args.body) }) -ipcMain.on("launch", (event, args) => { - minecraft.launch(event, args) -}) - ipcMain.on("disconnect", (e) => { win.loadFile('src/client/login.html') }) diff --git a/src/server/minecraft.js b/src/server/minecraft.js index f72d5e8..7261fe7 100644 --- a/src/server/minecraft.js +++ b/src/server/minecraft.js @@ -1,9 +1,9 @@ const isDev = require('electron-is-dev') const { Client, Authenticator } = require('minecraft-launcher-core') const axios = require('axios').default -const sha1File = require('sha1-file') +const hasha = require('hasha'); const fs = require('fs') -const { join } = require('path') +const { join, resolve } = require('path') const constants = require("constants") const zip = require('extract-zip') const logger = require('electron-log') @@ -15,7 +15,6 @@ class Minecraft { launcher = new Client() auth = null modsList = undefined - jre8 = "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jre_x64_windows_hotspot_8u292b10.zip" login(event, win, showNotification, username, password) { this.auth = null @@ -34,46 +33,55 @@ class Minecraft { } } - launch(event, args) { - this.extractMods(Number(args.chapter), event).then((chapter) => { - this.launcher.launch({ - authorization: this.auth, - root: this.minecraftpath, - version: { - number: chapter.minecraftVersion, - type: "release", - custom: chapter.customVersion - }, - memory: { - max: args.maxMem, - min: args.minMem - } + launch(event, showNotification, args) { + this.extractJava(Number(args.chapter), event).then((javaPath) => { + this.extractMods(Number(args.chapter), event).then((chapter) => { + this.launcher.launch({ + authorization: this.auth, + root: this.minecraftpath, + javaPath: javaPath, + version: { + number: chapter.minecraftVersion, + type: chapter.type | "release", + custom: chapter.customVersion + }, + memory: { + max: args.maxMem, + min: args.minMem + } + }) + this.launcher.on('debug', (e) => logger.info(`debug: ${e}`)); + // this.launcher.on('data', (e) => logger.info(`data: ${e}`)); + this.launcher.on('progress', (e) => { + event.sender.send("progress", e) + logger.info(`progress ${e.type} :${e.task} / ${e.total}`) + }) + this.launcher.on('arguments', (e) => { + event.sender.send("launch", e) + logger.info("launching the game") + logger.info(e) + }) + this.launcher.on('close', (e) => { + event.sender.send("close", e) + if(e !== 0) { + logger.warn("Minecraft didn't close properly") + logger.warn(e) + showNotification("Une erreur est survenue", "Minecraft ne s'est pas fermé correctement") + } + }) + }).catch((err) => { + showNotification("Impossible de lancer le jeu") + event.sender.send("close", 1) + logger.error('Unable to launch the game') + logger.error(err) }) - // this.launcher.on('debug', (e) => console.log("debug", e)); - // this.launcher.on('data', (e) => console.log("data", e)); - this.launcher.on('progress', (e) => { - event.sender.send("progress", e) - logger.info(`progress ${e.type} :${e.task} / ${e.total}`) - }) - this.launcher.on('arguments', (e) => { - event.sender.send("launch", e) - logger.info("launching the game") - logger.info(e) - }) - this.launcher.on('close', (e) => { - event.sender.send("close", e) - if(e !== 0) { - logger.warn("Minecraft didn't close properly") - logger.warn(e) - showNotification("Une erreur est survenue", "Minecraft ne s'est pas fermé correctement") - } - }) - }).catch((err) => { - showNotification("Impossible de lancer le jeu") + }).catch(err => { + showNotification("Impossible d'intaller Java pour votre configuration") event.sender.send("close", 1) - logger.error('Unable to launch the game') - logger.error(err) + logger.warn("Unable to install java") + logger.warn(err) }) + } getModsInformations(event) { @@ -123,14 +131,14 @@ class Minecraft { if(Number(i) === chapterId) { const chapter = this.modsList[i] for(let j in chapter.modspack.mods) { - event.sender.send("progress", {type: "mods", task: i, total: chapter.modspack.mods.length }) + event.sender.send("progress", {type: "mods", task: 0, total: chapter.modspack.mods.length }) let modpackFolder = join(this.minecraftpath, "modpack", chapter.title) if(!fs.existsSync(modpackFolder)) fs.mkdirSync(modpackFolder, { recursive: true }) const path = join(modpackFolder, `modpack${j}.zip`) try { fs.accessSync(path, constants.W_OK) - let sha1 = await sha1File(path) + let sha1 = await hasha.fromFile(path, {algorithm: 'sha1'}) if(sha1 === chapter.modspack.sha1sum[j]) { await this.unzipMods(path).catch(err => { reject(err) @@ -169,12 +177,13 @@ class Minecraft { responseType: "stream" }).then(res => { if(res.status === 200) { - fs.rmSync(path) + if(fs.existsSync(path)) + fs.rmSync(path) res.data.pipe(fs.createWriteStream(path)); res.data.on("end", () => { logger.log("download completed"); resolve("download completed") - }); + }) } else { reject(res.status) } @@ -184,9 +193,9 @@ class Minecraft { }) } - async unzipMods(path) { + async unzipMods(zipLocation, outLocation=this.minecraftpath) { return new Promise(async (resolve, reject) => { - zip(path, { dir: this.minecraftpath }).then(() => { + zip(zipLocation, { dir: outLocation }).then(() => { resolve() }).catch(err => { reject(err) @@ -197,7 +206,7 @@ class Minecraft { } async downloadAndExtractMods(link, path) { - return new Promise(async(resolve, reject) => { + return new Promise(async (resolve, reject) => { this.downloadMods(link, path).then(() => { this.unzipMods(path).then(() => { resolve() @@ -210,6 +219,48 @@ class Minecraft { }) } + + async extractJava(chapterId, event) { + return new Promise(async (resolve, reject) => { + const runtime = join(this.minecraftpath, "runtime") + if(this.modsList[chapterId].java.platform[process.platform][process.arch] !== undefined) { + event.sender.send("progress", {type: "java", task: 0, total: 1 }) + const infos = this.modsList[chapterId].java.platform[process.platform][process.arch] + const jre = join(runtime, infos.name) + const downloadFolder = join(runtime, "download") + const downloadFile = join(downloadFolder, `${infos.name}.zip`) + if(fs.existsSync(jre)) + fs.rmSync(jre, { recursive: true }) + if(!fs.existsSync(downloadFolder)) + fs.mkdirSync(downloadFolder, { recursive: true }) + if(fs.existsSync(downloadFile)) { + let sha1 = await hasha.fromFile(downloadFile, {algorithm: 'sha256'}) + if(sha1 === infos.sha256sum) { + await this.unzipMods(downloadFile, runtime) + resolve(join(jre, 'bin', 'java.exe')) + } else { + logger.warn(`java sha256sum ${sha1} don't correspond to ${infos.sha256sum}`) + await this.downloadAndExtractJava(infos, downloadFolder, runtime).then(() => resolve(join(jre, 'bin', 'java.exe'))).catch(err => reject(err)) + } + } else { + await this.downloadAndExtractJava(infos, downloadFolder, runtime).then(() => resolve(join(jre, 'bin', 'java.exe'))).catch(err => reject(err)) + } + event.sender.send("progress", {type: "java", task: 1, total: 1 }) + } else { + reject("There is not available version for your system") + } + }) + } + + async downloadAndExtractJava(infos, downloadFolder, runtimeFolder) { + return new Promise((resolve, reject) => { + this.downloadMods(infos.link, join(downloadFolder, `${infos.name}.zip`)).then(() => { + this.unzipMods(join(downloadFolder, `${infos.name}.zip`), runtimeFolder).then(() => resolve()).catch(err => reject(err)) + }).catch(err => { + reject(err) + }) + }) + } } module.exports = new Minecraft \ No newline at end of file diff --git a/src/server/updater.js b/src/server/updater.js index 54ed45e..ce83a0e 100644 --- a/src/server/updater.js +++ b/src/server/updater.js @@ -12,6 +12,8 @@ function initUpdater(autoUpdater) { } function configUpdater(app, autoUpdater, dialog, logger) { + logger.info(`platform: ${process.platform}`) + logger.info(`arch: ${process.arch}`) if(isDev) { logger.info(`developpement version ${app.getVersion()}`) return