diff --git a/app/assets/css/banned.css b/app/assets/css/banned.css index 3a45fa9..5377c5b 100644 --- a/app/assets/css/banned.css +++ b/app/assets/css/banned.css @@ -41,6 +41,14 @@ main > article > section.informations { font-family: "Roboto", sans-serif; } +main > article > section.logo > h2 { + color: #ffffff; + padding: 13px 13px 13px 13px; + font-weight: bolder; + text-align: center; + font-family: "Roboto", sans-serif; +} + main > article > section.informations > h2 { margin-bottom: 10px; } diff --git a/app/loading.html b/app/loading.html new file mode 100644 index 0000000..51304b1 --- /dev/null +++ b/app/loading.html @@ -0,0 +1,28 @@ + + + + + + + Launcher banni + + + +
+ +
+ +
+
+ + + + + \ No newline at end of file diff --git a/main.js b/main.js index 5ebc0f9..988880a 100644 --- a/main.js +++ b/main.js @@ -15,12 +15,13 @@ const launcher = new Client() const { io } = require("socket.io-client") const download = require("download") const rpc = require("./modules/rpc") +const java = require("./modules/java") const socket = io({ host: config.api.websockets.base.host, port: config.api.websockets.base.port }) -let launcherWindow, auth, gamePlayable = false, launchProcess +let launcherWindow, defaultWindow, auth, gamePlayable = false, launchProcess rpc.startRichPresence() @@ -108,6 +109,63 @@ async function createLauncherWindow() { } } +async function createDefaultWindow() { + gameOptions.initOptions(path.join(app.getPath("appData"), ".catboat", "options.txt")) + launcherSettings.initSettings(path.join(app.getPath("appData"), ".catboat")) + if (net.isOnline()) { + const isLauncherNotBanned = await checkIfIAmBanned() + try { + defaultWindow = new BrowserWindow({ + frame: false, + width: 300, + height: 400, + minWidth: 300, + minHeight: 400, + titleBarStyle: "hidden", + autoHideMenuBar: true, + roundedCorners: false, + resizable: false, + webPreferences: { + nodeIntegration: false, + contextIsolation: true, + preload: path.join(__dirname, "modules", "preload.js"), + webviewTag: true, + devTools: false + } + }) + if (os.platform() == "darwin") { + app.dock.setIcon(nativeImage.createFromPath(path.join(__dirname, "app", "assets", "img", "icon.png"))) + } + defaultWindow.setIcon(path.join(__dirname, "app", "assets", "img", "icon.png")) + if (isLauncherNotBanned.success) { + defaultWindow.loadFile(path.join(__dirname, "app", "loading.html")) + defaultWindow.webContents.openDevTools() + try { + await java.main(path.join(app.getPath("appData"), ".catboat", "jre")) + await launchGame(false) + defaultWindow.hide() + createLauncherWindow() + } catch (error) { + console.log(error) + defaultWindow.hide() + createLauncherWindow() + } + } else { + launcherWindow.loadFile(path.join(__dirname, "app", "banned.html")) + defaultWindow.webContents.executeJavaScript(` + setBannedBy("${isLauncherNotBanned.banned_by}") + setBannedAt("${isLauncherNotBanned.banned_at}") + setBannedBecause("${isLauncherNotBanned.reason}") + `) + } + } catch (error) { + dialog.showErrorBox("Erreur", error.toString()) + } + } else { + dialog.showErrorBox("Connexion internet", "Le launcher requiert une connexion internet.") + } +} + async function checkIfIAmBanned() { if (net.isOnline()) { try { @@ -145,9 +203,9 @@ async function checkCoutdown(uuid) { } app.whenReady().then(() => { - createLauncherWindow() + createDefaultWindow() app.on("activate", async () => { - if (BrowserWindow.getAllWindows().length === 0) await createLauncherWindow() + if (BrowserWindow.getAllWindows().length === 0) await createDefaultWindow() }) }) @@ -297,7 +355,7 @@ ipcMain.on("call", async (event, data) => { case "oculus::defaultshaderset": const oculusProperties = properties.parse(fs.readFileSync(path.join(app.getPath("appData"), ".catboat", "config", "oculus.properties")).toString()) if (data.args.boolean) { - properties.setProperty(oculusProperties, "shaderPack", "Sildur%27s+Vibrant+Shaders+v1.50+Medium.zip") + properties.setProperty(oculusProperties, "shaderPack", "Sildurs_Vibrant_Shaders_v1.50_Medium.zip") } else { properties.setProperty(oculusProperties, "shaderPack", "") } @@ -305,14 +363,17 @@ ipcMain.on("call", async (event, data) => { break case "oculus::getdefaultshaderset": const $oculusProperties = properties.parse(fs.readFileSync(path.join(app.getPath("appData"), ".catboat", "config", "oculus.properties")).toString()) - launcherWindow.webContents.send("Response", properties.getProperty($oculusProperties, "shaderPack") == "Sildur%27s+Vibrant+Shaders+v1.50+Medium.zip" ? true : false) + launcherWindow.webContents.send("Response", properties.getProperty($oculusProperties, "shaderPack") == "Sildurs_Vibrant_Shaders_v1.50_Medium.zip" ? true : false) break } }) async function launchGame(restartGame) { - let sendToRenderer = true - launcherWindow.webContents.send("Response", { disablePlayButton: false }) + let sendToRenderer = false + if (launcherWindow instanceof BrowserWindow) { + sendToRenderer = true + launcherWindow.webContents.send("Response", { disablePlayButton: false }) + } const downloadQueue = [] const remoteFiles = await fileManager.getRemoteFiles() const localFiles = fs.readdirSync(path.join(app.getPath("appData"), ".catboat"), { recursive: true }) diff --git a/modules/java.js b/modules/java.js index 8780d77..f705acd 100644 --- a/modules/java.js +++ b/modules/java.js @@ -1,182 +1,79 @@ -const os = require("os") +const { execSync } = require("child_process") +const fs = require("fs") const path = require("path") -const osmeta = require("./osmeta") -const { exec } = require("child_process") -const files = require("./files") -const config = require("../config.json") -const settings = require("./settings") -const { dialog, BrowserWindow, shell } = require("electron") +const os = require("os") +const download = require("download") const AdmZip = require("adm-zip") -function isJavaInstalled() { - return new Promise((resolve, reject) => { - try { - exec(`"${settings.get("javaPath") == "" ? "java" : settings.get("javaPath")}" -version`, (error, stdout, stderr) => { - if (error) { - reject({ - java: false - }) - } - const output = `${stdout}\n${stderr}` - const lines = output.split("\n") - const version = lines.filter(line => line.includes("version \""))[0] - try { - let matchRegEx - if (version.includes("_")) { - matchRegEx = /(?\d+)\.(?\d+)\.(?\d+)\_(?\d+)/ - } else { - matchRegEx = /(?\d+)\.(?\d+)\.(?\d+)/ - } - const versionMatch = version.match(matchRegEx) - const { major, minor, patch, update } = versionMatch.groups - resolve({ - java: true, - version: { - major: parseInt(major), - minor: parseInt(minor), - patch: parseInt(patch), - update: update ? parseInt(update) : null - } - }) - } catch (error) { - reject({ - java: false, - error - }) - } - }) - } catch (error) { - reject({ - java: false, - error - }) - } - }) +const JAVA_DOWNLOAD_URL = { + win32: "https://download.oracle.com/java/17/archive/jdk-17.0.12_windows-x64_bin.zip", + darwin: "https://download.oracle.com/java/17/archive/jdk-17.0.12_macos-x64_bin.tar.gz", + linux: "https://download.oracle.com/java/17/archive/jdk-17.0.12_linux-aarch64_bin.tar.gz", } -async function showJavaErrorBox() { - const javaErrorBox = await dialog.showMessageBox(BrowserWindow.getFocusedWindow(), { - title: "Mauvaise version de Java", - message: "Mauvaise version de Java", - detail: "La version de java installé sur votre ordinateur n'est pas compatible avec la version de minecraft utilisé", - icon: path.join(__dirname, "code/app/assets/img/java.png"), - buttons: [ - "Fermer", - "Installer automatiquement java", - "Installer manuellement java", - "Utilise un chemin d'accès personnalié", - ], - cancelId: 0, - defaultId: 1 - }) - return javaErrorBox -} -function installJava(dest) { - return new Promise(async (resolve, reject) => { - const response = await fetch(`${config.apiServicesURL}/api/java`) - const java = await response.json() - const arch = osmeta.arch() == "unknow" ? "x64" : osmeta.arch() - if (java.downloads[os.platform()]) { - if (java.downloads[os.platform()][arch]) { - files.downloadFile(config.apiServicesURL + java.downloads[os.platform()][arch].url, path.join(dest, "java.zip"), (error, file) => { - if (error) throw error - try { - const zip = new AdmZip(path.join(dest, "java.zip")) - zip.extractAllTo(path.join(dest, "java"), true) - files.removeFile(path.join(dest, "java.zip")) - if (os.platform() == "darwin") { - exec(`chmod +x "${path.join(dest, "java", "jre-1.8.0_411.jre", "Contents", "Home", "bin", "java")}"`, (error) => { - if (error) reject(error) - resolve(path.join(dest, "java", "jre-1.8.0_411.jre", "Contents", "Home", "bin", "java")) - }) - } else { - exec(`chmod +x "${path.join(dest, "java", "bin", "java")}"`, (error) => { - if (error) reject(error) - resolve(path.join(dest, "java", "bin", "java")) - }) - } - } catch (err) { - reject(err) - } - }) +function checkJavaVersion(requiredVersion = "17") { + try { + const javaVersionOutput = execSync("java -version", { + encoding: "utf8", + stdio: "pipe" + }) + const versionMatch = javaVersionOutput.match(/"(\d+\.\d+)(\.\d+)?_\d+"/) + if (versionMatch) { + const installedVersion = versionMatch[1] + console.log(`Java is installed. Version: ${installedVersion}`) + if (parseFloat(installedVersion) >= parseFloat(requiredVersion)) { + console.log("Required Java version is already installed.") + return true } else { - reject(new Error("Java are not supported for your OS arch")) + console.log(`Installed Java version (${installedVersion}) is less than required version (${requiredVersion}).`) + return false } } else { - reject(new Error("Java are not supported for your OS")) + console.log("Java is installed but version could not be determined.") + return false } - }) + } catch (error) { + console.log("Java is not installed.") + return false + } } -async function main(requiredJavaVersionMinor, dest) { - return new Promise(async (resolve, reject) => { - try { - const java = await isJavaInstalled() - if (java.version.minor < parseInt(requiredJavaVersionMinor)) { - const javaErrorBox = await showJavaErrorBox() - switch (javaErrorBox.response) { - case 0: - resolve() - break - case 1: - installJava(dest).then(javaPath => { - resolve(javaPath) - }) - break - case 2: - shell.openExternal(`https://www.java.com/fr/download/manual.jsp`) - resolve() - break - case 3: - const javaBinPathSelect = await dialog.showOpenDialog(BrowserWindow.getFocusedWindow(), { - filters: [ - { - name: "java", - } - ] - }) - if (javaBinPathSelect.canceled) { - showJavaErrorBox() - } else { - resolve(javaBinPathSelect.filePaths[0]) - } - break - } - } else { - resolve() - } - } catch (error) { - const javaErrorBox = await showJavaErrorBox() - switch (javaErrorBox.response) { - case 0: - resolve() - break - case 1: - installJava(dest).then(javaPath => { - resolve(javaPath) - }) - break - case 2: - shell.openExternal(`https://www.java.com/fr/download/manual.jsp`) - resolve() - break - case 3: - const javaBinPathSelect = await dialog.showOpenDialog(BrowserWindow.getFocusedWindow(), { - filters: [ - { - name: "java", - } - ] - }) - if (javaBinPathSelect.canceled) { - showJavaErrorBox() - } else { - resolve(javaBinPathSelect.filePaths[0]) - } - break - } - } +async function downloadAndInstallJava(extractPath = null) { + const platform = os.platform() + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "java-installer-")) + + const downloadUrl = JAVA_DOWNLOAD_URL[platform] + if (!downloadUrl) { + console.error("Unsupported platform for Java installation.") + return + } + + const zipPath = path.join(tempDir, "java-package.zip") + await download(downloadUrl, tempDir, { + filename: "java-package.zip" }) + + const extractionDir = extractPath || tempDir + const zip = new AdmZip(zipPath) + zip.extractAllTo(extractionDir, true) + + fs.unlinkSync(zipPath) } -module.exports.java = main \ No newline at end of file +async function main(customExtractPath) { + const requiredVersion = "17" + const isJavaInstalled = checkJavaVersion(requiredVersion) + + if (!isJavaInstalled) { + + if (!fs.existsSync(path.join(customExtractPath, "jdk-17.0.12", "bin", os.platform() == "win32" ? "java.exe" : "java"))) { + await downloadAndInstallJava(customExtractPath || path.join(__dirname, "..", "..", "java")) + } + } else { + console.log("No further action is required.") + } +} + +module.exports = { + main +} \ No newline at end of file