From 0b85d5c84a8b1710f78fa59e419efa843fc380bd Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Thu, 13 May 2021 13:50:07 +0200 Subject: [PATCH] moved all minecraft related instructions to minecraft class + fix sha1 bug + fix old modspack files not deleted if sha1 not correct --- src/server/main.js | 209 ++------------------------------------ src/server/minecraft.js | 215 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+), 203 deletions(-) create mode 100644 src/server/minecraft.js diff --git a/src/server/main.js b/src/server/main.js index 646a502..193ce9f 100644 --- a/src/server/main.js +++ b/src/server/main.js @@ -8,23 +8,10 @@ if (require('electron-squirrel-startup')) { } require('./updater.js').configUpdater(app, autoUpdater, dialog, logger) -const axios = require('axios').default -const sha1File = require('sha1-file') -const fs = require('fs') -const constants = require("constants") -const zip = require('extract-zip') +const minecraft = require('./minecraft.js') -const { Client, Authenticator } = require('minecraft-launcher-core') -const appdata = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Preferences' : process.env.HOME + "/.local/share") - -const launcher = new Client() const iconPath = join(__dirname, "icon.ico") let win = null -let auth = null - -let Minecraftpath = join(appdata, ".altarik") -// let clientPackage = "https://www.dropbox.com/s/ww6a052nzzgojdm/modpack.zip?dl=1" -let modsList = undefined function createWindow () { win = new BrowserWindow({ @@ -45,13 +32,9 @@ function createWindow () { win.loadFile('src/client/login.html') } -const { - setWindow, - minimizeWindow, - closeWindow - } = require("./menubar.js"); +const { setWindow, minimizeWindow, closeWindow } = require("./menubar.js"); - setWindow(win) +setWindow(win) app.whenReady().then(() => { createWindow() @@ -78,19 +61,7 @@ app.on('activate', () => { }) ipcMain.on("login", (event, args) => { - auth = Authenticator.getAuth(args.user, args.pass) - auth.then(v => { - win.loadFile('src/client/index.html') - setTimeout(() => { - event.sender.send("nick", { - name: v.name - }) - }, 1000) - - }).catch((err) => { - logger.error(err) - showNotification("Erreur de connexion") - }) + minecraft.login(event, win, showNotification, args.user, args.pass) }) function showNotification(title, body="") { @@ -102,46 +73,7 @@ ipcMain.on("notification", (event, args) => { }) ipcMain.on("launch", (event, args) => { - extractMods(Number(args.chapter), event).then((chapter) => { - launcher.launch({ - // clientPackage: clientPackage, - authorization: auth, - root: Minecraftpath, - version: { - number: chapter.minecraftVersion, - type: "release", - custom: chapter.customVersion - }, - memory: { - max: args.maxMem, - min: args.minMem - } - }) - // launcher.on('debug', (e) => console.log("debug", e)); - // launcher.on('data', (e) => console.log("data", e)); - launcher.on('progress', (e) => { - event.sender.send("progress", e) - logger.info(`progress ${e.type} :${e.task} / ${e.total}`) - }) - launcher.on('arguments', (e) => { - event.sender.send("launch", e) - logger.info("launching the game") - logger.info(e) - }) - 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) - }) + minecraft.launch(event, args) }) ipcMain.on("disconnect", (e) => { @@ -150,137 +82,8 @@ ipcMain.on("disconnect", (e) => { ipcMain.on("demandModsInformations", (e) => { - getModsInformations(e) + minecraft.getModsInformations(e) }) -function getModsInformations(event) { - axios.get("https://altarik.fr/launcher.json").then(o => { - if(o.status === 200 && o.headers["content-type"] === "application/json") { - folder = join(process.env.LOCALAPPDATA, "altarik-launcher", "data") - if(!fs.existsSync(folder)) - fs.mkdirSync(folder) - fs.writeFileSync(join(folder, "launcher.json"), JSON.stringify(o.data)) - event.sender.send('modsInformations', extractModsInformations(o.data)) - } else { - event.sender.send('modsInformations', extractModsFromFileSystem()) - } - }).catch(err => { - logger.warn("Unable to connect to server") - logger.warn(err) - event.sender.send('modsInformations', extractModsFromFileSystem()) - }) -} -function extractModsFromFileSystem() { - content = fs.readFileSync(join(process.env.LOCALAPPDATA, "altarik-launcher/data/launcher.json")) - if(content !== null) { - showNotification("Impossible de récupérer certaines informations en ligne", "utilisation des dernières données récupérées") - return extractModsInformations(JSON.parse(o.data)) - } else { - showNotification("Impossible de récupérer certaines informations en ligne", "Veuillez réessayez en cliquant sur le bouton") - logger.error("Unable to get chapters informations from server or filesystem") - return null - } -} - -function extractModsInformations(json) { - modsList = json.chapters - return modsList -} - -async function extractMods(chapterId, event) { - return new Promise(async (resolve, reject) => { - modsFolder = join(Minecraftpath, "mods") - shaderFolder = join(Minecraftpath, "shaderpacks") - if(fs.existsSync(modsFolder)) - fs.rmSync(modsFolder, { recursive: true }) - if(fs.existsSync(shaderFolder)) - fs.rmSync(shaderFolder, { recursive: true }) - for(const i in modsList) { - if(Number(i) === chapterId) { - const chapter = modsList[i] - let j - for(j in chapter.modspack.mods) { - event.sender.send("progress", {type: "mods", task: i, total: chapter.modspack.mods.length }) - modpackFolder = join(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) - sha1 = await sha1File(path) - if(sha1 === chapter.modspack.sha1sum) { - await unzipMods(path) - } else { - await downloadAndExtractMods(chapter.modspack.mods[j], path).catch(err => { - reject(err) - }) - } - } catch (err) { - try { - await downloadAndExtractMods(chapter.modspack.mods[j], path) - } catch(e) { - reject({ err, e }) - return - } - } - } - event.sender.send("progress", {type: "mods", task: Number(j)+1, total: chapter.modspack.mods.length }) - resolve(chapter) - return - - } - } - reject("didn't found the correct chapter" + chapter) - return - }) -} - -function downloadMods(link, path) { - return new Promise((resolve, reject) => { - axios.get(link, { - responseType: "stream" - }).then(res => { - if(res.status === 200) { - res.data.pipe(fs.createWriteStream(path)); - res.data.on("end", () => { - logger.log("download completed"); - resolve("download completed") - }); - } else { - reject(res.status) - } - }).catch(err => { - reject(err) - }) - }) -} - -async function unzipMods(path) { - return new Promise(async (resolve, reject) => { - zip(path, { dir: Minecraftpath }).then(() => { - resolve() - }).catch(err => { - reject(err) - }) - - }) - - -} - -async function downloadAndExtractMods(link, path) { - return new Promise(async(resolve, reject) => { - downloadMods(link, path).then(() => { - unzipMods(path).then(() => { - resolve() - }).catch(err => { - reject(err) - }) - }).catch(err => { - reject(err) - }) - - }) -} diff --git a/src/server/minecraft.js b/src/server/minecraft.js new file mode 100644 index 0000000..f72d5e8 --- /dev/null +++ b/src/server/minecraft.js @@ -0,0 +1,215 @@ +const isDev = require('electron-is-dev') +const { Client, Authenticator } = require('minecraft-launcher-core') +const axios = require('axios').default +const sha1File = require('sha1-file') +const fs = require('fs') +const { join } = require('path') +const constants = require("constants") +const zip = require('extract-zip') +const logger = require('electron-log') + +class Minecraft { + + appdata = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Preferences' : process.env.HOME + "/.local/share") + minecraftpath = join(this.appdata, ".altarik") + 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 + if(isDev || password.trim() !== "") { + this.auth = Authenticator.getAuth(username, password) + this.auth.then(v => { + win.loadFile('src/client/index.html').then(() => { + event.sender.send("nick", { name: v.name }) + }) + }).catch((err) => { + logger.error(err) + showNotification("Erreur de connexion") + }) + } else { + showNotification("Veuillez renseignez un mot de passe") + } + } + + 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 + } + }) + // 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") + event.sender.send("close", 1) + logger.error('Unable to launch the game') + logger.error(err) + }) + } + + getModsInformations(event) { + axios.get("https://altarik.fr/launcher.json").then(o => { + if(o.status === 200 && o.headers["content-type"] === "application/json") { + let folder = join(process.env.LOCALAPPDATA, "altarik-launcher", "data") + if(!fs.existsSync(folder)) + fs.mkdirSync(folder) + fs.writeFileSync(join(folder, "launcher.json"), JSON.stringify(o.data)) + event.sender.send('modsInformations', this.extractModsInformations(o.data)) + } else { + event.sender.send('modsInformations', this.extractModsFromFileSystem()) + } + }).catch(err => { + logger.warn("Unable to connect to server") + logger.warn(err) + event.sender.send('modsInformations', this.extractModsFromFileSystem()) + }) + } + + extractModsFromFileSystem() { + content = fs.readFileSync(join(process.env.LOCALAPPDATA, "altarik-launcher/data/launcher.json")) + if(content !== null) { + showNotification("Impossible de récupérer certaines informations en ligne", "utilisation des dernières données récupérées") + return this.extractModsInformations(JSON.parse(content)) + } else { + showNotification("Impossible de récupérer certaines informations en ligne", "Veuillez réessayez en cliquant sur le bouton") + logger.error("Unable to get chapters informations from server or filesystem") + return null + } + } + + extractModsInformations(json) { + this.modsList = json.chapters + return this.modsList + } + + async extractMods(chapterId, event) { + return new Promise(async (resolve, reject) => { + const modsFolder = join(this.minecraftpath, "mods") + const shaderFolder = join(this.minecraftpath, "shaderpacks") + if(fs.existsSync(modsFolder)) + fs.rmSync(modsFolder, { recursive: true }) + if(fs.existsSync(shaderFolder)) + fs.rmSync(shaderFolder, { recursive: true }) + for(const i in this.modsList) { + 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 }) + 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) + if(sha1 === chapter.modspack.sha1sum[j]) { + await this.unzipMods(path).catch(err => { + reject(err) + return + }) + } else { + logger.warn(`sha1sum ${sha1} don't correspond to ${chapter.modspack.sha1sum[j]} of mods ${path}`) + await this.downloadAndExtractMods(chapter.modspack.mods[j], path).catch(err => { + reject(err) + return + }) + } + event.sender.send("progress", {type: "mods", task: Number(j)+1, total: chapter.modspack.mods.length }) + } catch (err) { + try { + await this.downloadAndExtractMods(chapter.modspack.mods[j], path) + } catch(e) { + reject({ err, e }) + return + } + } + } + resolve(chapter) + return + + } + } + reject("didn't found the correct chapter" + chapter) + return + }) + } + + downloadMods(link, path) { + return new Promise((resolve, reject) => { + axios.get(link, { + responseType: "stream" + }).then(res => { + if(res.status === 200) { + fs.rmSync(path) + res.data.pipe(fs.createWriteStream(path)); + res.data.on("end", () => { + logger.log("download completed"); + resolve("download completed") + }); + } else { + reject(res.status) + } + }).catch(err => { + reject(err) + }) + }) + } + + async unzipMods(path) { + return new Promise(async (resolve, reject) => { + zip(path, { dir: this.minecraftpath }).then(() => { + resolve() + }).catch(err => { + reject(err) + }) + + }) + + } + + async downloadAndExtractMods(link, path) { + return new Promise(async(resolve, reject) => { + this.downloadMods(link, path).then(() => { + this.unzipMods(path).then(() => { + resolve() + }).catch(err => { + reject(err) + }) + }).catch(err => { + reject(err) + }) + + }) + } +} + +module.exports = new Minecraft \ No newline at end of file