5 Commits

Author SHA1 Message Date
cd627b03ae sync 2025-05-11 08:01:49 +02:00
1106ced049 sync 2025-05-11 07:58:45 +02:00
0c01e826d9 sync 2025-05-11 07:30:13 +02:00
48c5fd4ead Update main.js 2025-05-10 18:52:18 +02:00
d6fa5b69ce sync 2025-05-10 18:37:31 +02:00
10 changed files with 411 additions and 208 deletions

View File

@@ -11,6 +11,14 @@ body {
background-color: #262626;
}
main {
app-region: drag;
}
main > * {
app-region: no-drag;
}
main > article > section > img {
width: 150px;
}
@@ -33,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;
}

View File

@@ -4,6 +4,8 @@
* {
margin: 0px;
padding: 0px;
outline: none;
user-select: none;
box-sizing: border-box;
font-family: "Roboto", sans-serif;
}
@@ -16,6 +18,11 @@ body {
background-attachment: fixed;
}
img {
app-region: drag;
pointer-events: none;
}
main {
position: absolute;
top: 0px;
@@ -24,6 +31,11 @@ main {
bottom: 0px;
width: 100%;
height: 100%;
app-region: drag;
}
main > * {
app-region: no-drag;
}
main > nav {
@@ -372,25 +384,43 @@ div.checkboxes > input[type="checkbox"] {
font-size: small;
}
button.load {
content: "";
transition: background-color 0.3s;
div.loader {
overflow: hidden;
position: absolute;
left: 0px;
right: 0px;
bottom: 0px;
width: 100%;
height: 10px;
}
div.loader > div.full {
height: 10px;
width: 100%;
background-color: #3e3e3ee6;
}
div.loader > div.full > div.progress,
div.loader > div.full > div.loading {
height: 10px;
width: 50%;
transition: 1s width;
background-color: #39aa6d;
}
div.loader > div.full > div.loading {
animation: animateLoadingEffect 1s linear infinite;
}
[hidden] {
display: none;
visibility: hidden;
}
@keyframes backgroundAnimation {
@keyframes animateLoadingEffect {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
transform: translateX(-100%);
}
100% {
background-position: 0% 50%;
transform: translateX(200%);
}
}

View File

@@ -58,18 +58,32 @@ function toggleAudio(element) {
function toggleMusic(element) {
if (element.getAttribute("state") == 0) {
system.call("audio::mute")
audio.pause()
element.setAttribute("state", 1)
element.children[0].classList.replace("fa-pause", "fa-play")
element.children[1].innerText = "Reprendre"
} else {
system.call("audio::unmute")
audio.play()
element.setAttribute("state", 0)
element.children[0].classList.replace("fa-play", "fa-pause")
element.children[1].innerText = "Pause"
}
}
function toggleMusicVolume(element) {
if (element.getAttribute("state") == 0) {
system.call("audio::mute")
element.setAttribute("state", 1)
element.children[0].classList.replace("fa-volume", "fa-volume-slash")
element.children[1].innerText = "Activer le son"
} else {
system.call("audio::unmute")
element.setAttribute("state", 0)
element.children[0].classList.replace("fa-volume-slash", "fa-volume")
element.children[1].innerText = "Couper le son"
}
}
function updateVolume(value) {
audio.volume = value / 100
audioPourcentageLabel.innerText = `${value}%`
@@ -86,7 +100,7 @@ system.result("server::ping", pong => {
function handleOptionsChanges(key, value) {
system.call("game::optionSet", { key, value })
const span = document.querySelector(`span#${key}`)
const span = document.querySelector(`span#current${key.replace(/./, c => c.toUpperCase())}`)
if (span) {
span.innerText = Math.floor(value)
}
@@ -100,16 +114,66 @@ function handleSettingsChanges(key, value) {
}
}
function setLoadingType(type) {
const loader = document.querySelector(".loader")
switch (type) {
case "continuous":
loader.children[0].children[0].classList.remove("progress")
loader.children[0].children[0].classList.add("loading")
break
case "progress":
loader.children[0].children[0].classList.remove("loading")
loader.children[0].children[0].classList.add("progress")
break
default:
break
}
}
function setLoadingProgress(pourcentage) {
const loader = document.querySelector(".loader")
const progress = loader.querySelector(".progress")
if (progress) {
progress.setAttribute("style", `width: ${pourcentage}%`)
}
}
function toggleLoadingBar() {
const loader = document.querySelector(".loader")
if (loader.hasAttribute("hidden")) {
loader.removeAttribute("hidden")
} else {
loader.setAttribute("hidden", "")
}
}
function showLoadingBar() {
const loader = document.querySelector(".loader")
if (loader.hasAttribute("hidden")) {
loader.removeAttribute("hidden")
}
}
function hideLoadingBar() {
const loader = document.querySelector(".loader")
if (!loader.hasAttribute("hidden")) {
loader.setAttribute("hidden", "")
}
}
system.result("game::parseOptions", options => {
gamma.checked = options.gamma == 1 ? true : false
renderClouds.checked = options.renderrenderClouds == false ? false : true
guiScale.value = options.guiScale
currentGuiScale.innerText = options.guiScale
graphicsMode.checked = options.graphicsMode == 0 ? true : false
renderDistance.value = options.renderDistance
currentRenderDistance.innerText = options.renderDistance
})
system.result("settings::read", settings => {
ram.value = settings.ram.max
currentRam.innerText = `${Math.floor(settings.ram.max / 1024)} G`
})
system.result("hardware::ramInformation", $ram => {
@@ -120,11 +184,17 @@ system.result("hardware::ramInformation", $ram => {
system.result("game::launch", info => {
if (info.disablePlayButton) {
playButton.removeAttribute("hidden")
hideLoadingBar()
} else {
playButton.setAttribute("hidden", "")
}
})
system.result("game::launched", info => {
muteAudio()
hideLoadingBar()
})
system.result("player::profile", playerProfile => {
console.log(playerProfile)
})
@@ -133,6 +203,26 @@ system.result("oculus::getdefaultshaderset", boolean => {
sildurs_shader.checked = boolean
})
system.result("progress::update", info => {
showLoadingBar()
setLoadingType(info.type)
if (info.type == "progress" && typeof info.pourcentage == "number") {
setLoadingProgress(info.pourcentage)
}
})
system.result("progress::hide", () => {
hideLoadingBar()
})
system.result("izitoast::error", info => {
iziToast.error(info)
})
system.result("progress::info", info => {
iziToast.error(info)
})
window.onload = () => {
system.call("hardware::ramInformation")
system.call("game::parseOptions")
@@ -140,5 +230,6 @@ window.onload = () => {
system.call("player::profile")
system.call("settings::read")
system.call("oculus::getdefaultshaderset")
hideLoadingBar()
startAudio()
}

28
app/loading.html Normal file
View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./assets/css/banned.css">
<title>Launcher banni</title>
</head>
<body>
<main>
<button class="close" onclick="system.call('window::close')">
<i class="fas fa-times"></i>
</button>
<article>
<section class="logo">
<img src="./assets/img/icon.png" alt="">
<h2>
Veuillez patienter
</h2>
</section>
</article>
</main>
<script src="./assets/js/banned.js"></script>
</body>
</html>

View File

@@ -3,6 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/izitoast/1.4.0/css/iziToast.css">
<link rel="stylesheet" href="./assets/css/index.css">
<title>NyanLauncher</title>
</head>
@@ -11,6 +12,9 @@
<button class="close" onclick="system.call('window::close')">
<i class="fas fa-times"></i>
</button>
<button class="close" onclick="system.call('window::reduce')">
<i class="fas fa-minus"></i>
</button>
<nav hidden>
<button class="close" onclick="hideNavBar()">
<i class="fas fa-times"></i>
@@ -59,7 +63,7 @@
Distance de rendu
</label>
<div class="ranges">
<span id="renderDistance">
<span id="currentRenderDistance">
4
</span>
<input type="range" name="renderDistance" min="4" max="32" id="renderDistance" onchange="handleOptionsChanges(this.name, this.value)">
@@ -72,7 +76,7 @@
Taille de l'interface
</label>
<div class="ranges">
<span id="guiScale">
<span id="currentGuiScale">
1
</span>
<input type="range" name="guiScale" min="1" max="4" id="guiScale" onchange="handleOptionsChanges(this.name, this.value)">
@@ -125,6 +129,12 @@
100%
</label>
</div>
<button class="classic" onclick="toggleMusicVolume(this)" state="0">
<i class="fas fa-volume"></i>
<span>
Couper le son
</span>
</button>
<button class="classic" onclick="toggleMusic(this)" state="0">
<i class="fas fa-pause"></i>
<span>
@@ -213,8 +223,15 @@
<img class="mascot" src="./assets/img/sulli.png" alt="">
</section>
</footer>
<div class="loader">
<div class="full">
<div class="loading">
</div>
</div>
</div>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/izitoast/1.4.0/js/iziToast.min.js"></script>
<script src="./assets/js/index.js"></script>
</body>

View File

@@ -12,6 +12,9 @@
<button class="close" onclick="system.call('window::close')">
<i class="fas fa-times"></i>
</button>
<button class="close" onclick="system.call('window::reduce')">
<i class="fas fa-minus"></i>
</button>
<article class="loginchoice">
<div frame="select">
<h2>

View File

@@ -6,7 +6,8 @@
"checkBanStatus": "/api/v1/ban/iam",
"telemetry": "/api/v1/telemetry",
"gameFiles": "/api/v1/file/game",
"downloadFile": "/api/v1/file/game/download"
"downloadFile": "/api/v1/file/game/download",
"countdown": "/api/v1/countdown"
},
"websockets": {
"base": {

120
main.js
View File

@@ -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 {
@@ -133,10 +191,21 @@ async function checkIfIAmBanned() {
}
}
async function checkCoutdown(uuid) {
try {
const response = await fetch(`${config.api.base}${config.api.endpoints.countdown}/${uuid}`)
const json = await response.json()
console.log(json)
return json.success
} catch (error) {
return false
}
}
app.whenReady().then(() => {
createLauncherWindow()
createDefaultWindow()
app.on("activate", async () => {
if (BrowserWindow.getAllWindows().length === 0) await createLauncherWindow()
if (BrowserWindow.getAllWindows().length === 0) await createDefaultWindow()
})
})
@@ -160,6 +229,9 @@ ipcMain.on("call", async (event, data) => {
launcherWindow.close()
app.quit()
break
case "window::reduce":
launcherWindow.minimize()
break
case "skin::set":
const file = await dialog.showOpenDialog(launcherWindow, {
filters: [
@@ -186,8 +258,18 @@ ipcMain.on("call", async (event, data) => {
if (data.args.trim() != "") {
auth = Authenticator.getAuth(data.args.username, data.args.password)
launcherSettings.set("auth", { token: (await auth).access_token, type: "mojang", clientToken: (await auth).client_token })
await fetch(`${config.api.base}${config.api.endpoints.telemetry}/${hwid.getHWID()}/${(await auth).uuid}`)
if (await checkCoutdown((await auth).uuid)) {
await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html"))
await fetch(`${config.api.base}${config.api.endpoints.telemetry}/${hwid.getHWID()}/${(await auth).uuid}`)
} else {
await launcherWindow.loadURL("https://nyancraft.catboat.fr")
await launcherWindow.webContents.insertCSS("a.download-button { display: none; } #return-button { app-region: no-drag } ")
await launcherWindow.webContents.executeJavaScript(`
const returnButton = document.querySelector(\"#return-button\")
returnButton.innerText = "Fermer le launcher"
returnButton.onclick = () => system.call("window::close")
`)
}
} else {
dialog.showErrorBox("Erreur", "Le mot de passe n'est pas défini. Les comptes crackés ne sont pas supporté par le launcher.")
}
@@ -200,8 +282,18 @@ ipcMain.on("call", async (event, data) => {
auth = token.mclc()
console.log(auth.meta)
launcherSettings.set("auth", { token: auth.meta, type: "msa", clientToken: auth.client_token })
if (await checkCoutdown(auth.uuid)) {
launcherWindow.loadFile(path.join(__dirname, "app", "logged.html"))
fetch(`${config.api.base}${config.api.endpoints.telemetry}/${hwid.getHWID()}/${auth.uuid}`)
} else {
await launcherWindow.loadURL("https://nyancraft.catboat.fr")
await launcherWindow.webContents.insertCSS("a.download-button { display: none; } #return-button { app-region: no-drag } ")
await launcherWindow.webContents.executeJavaScript(`
const returnButton = document.querySelector(\"#return-button\")
returnButton.innerText = "Fermer le launcher"
returnButton.onclick = () => system.call("window::close")
`)
}
} catch (error) {
console.error(error)
if (error == "error.gui.closed") {
@@ -263,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", "")
}
@@ -271,13 +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<oculus::getdefaultshaderset>", properties.getProperty($oculusProperties, "shaderPack") == "Sildur%27s+Vibrant+Shaders+v1.50+Medium.zip" ? true : false)
launcherWindow.webContents.send("Response<oculus::getdefaultshaderset>", properties.getProperty($oculusProperties, "shaderPack") == "Sildurs_Vibrant_Shaders_v1.50_Medium.zip" ? true : false)
break
}
})
async function launchGame(restartGame) {
let sendToRenderer = false
if (launcherWindow instanceof BrowserWindow) {
sendToRenderer = true
launcherWindow.webContents.send("Response<game::launch>", { disablePlayButton: false })
}
const downloadQueue = []
const remoteFiles = await fileManager.getRemoteFiles()
const localFiles = fs.readdirSync(path.join(app.getPath("appData"), ".catboat"), { recursive: true })
@@ -313,11 +409,13 @@ async function launchGame(restartGame) {
try {
await download(url, path.join(app.getPath("appData"), ".catboat", path.dirname(item)))
if (launcherWindow instanceof BrowserWindow) {
launcherWindow.webContents.send("Response<progress::update>", { type: "landing" })
launcherWindow.webContents.send("Response<izitoast::info>", { title: "Lancement du jeu", message: "Ce processus peut être plus ou moins long selon votre configuration." })
launcherWindow.webContents.send("Response<progress::update>", { type: "continuous" })
}
} catch (error) {
if (launcherWindow instanceof BrowserWindow) {
launcherWindow.webContents.send("Response<progress::error>", { type: "landing" })
launcherWindow.webContents.send("Response<progress::hide>")
launcherWindow.webContents.send("Response<izitoast::error>", { title: "Erreur", message: new String(error) })
}
dialog.showErrorBox("Erreur lors du téléchargement des fichiers", error.toString())
continue
@@ -332,6 +430,10 @@ async function launchGame(restartGame) {
console.log(log)
})
launcher.on("data", (log) => {
if (sendToRenderer) {
launcherWindow.webContents.send("Response<game::launched>")
sendToRenderer = false
}
console.log(log)
})
launcher.on("data", (log) => {
@@ -346,7 +448,7 @@ async function launchGame(restartGame) {
type: "release"
},
forge: path.join(app.getPath("appData"), ".catboat", "forge-1.16.5.jar"),
javaPath: "C:\\Program Files\\Java\\jdk-17\\bin\\java.exe",
javaPath: await java.getPath(path.join(app.getPath("appData"), ".catboat", "jre")),
memory: {
min: 512,
max: launcherSettings.get("ram").max

View File

@@ -1,182 +1,94 @@
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 = /(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)\_(?<update>\d+)/
} else {
matchRegEx = /(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\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
function checkJavaVersion(requiredVersion = "17") {
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"))
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 {
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)
}
})
} 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"))
}
})
}
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()
console.log("Java is installed but version could not be determined.")
return false
}
} 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",
console.log("Java is not installed.")
return false
}
]
})
if (javaBinPathSelect.canceled) {
showJavaErrorBox()
} else {
resolve(javaBinPathSelect.filePaths[0])
}
break
}
}
})
}
module.exports.java = main
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)
}
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.")
}
}
async function getPath(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 main(customExtractPath)
} else {
return path.join(customExtractPath, "jdk-17.0.12", "bin", os.platform() == "win32" ? "java.exe" : "java")
}
} else {
console.log("No further action is required.")
}
}
module.exports = {
main
}

View File

@@ -3,19 +3,22 @@ const RPC = require("discord-rpc")
class DiscordRPC {
constructor() {
readonly: this.activity = {
details: "Actif dans le launcher",
details: "Officiel | Solva x Alcaz",
timestamps : { start: Date.now() },
assets: {
large_image: "logo",
large_text: "CatBoat Minecraft Launcher"
large_image: "rpc_catboat_large",
large_text: "CatBoat Launcher",
small_image : "alflamme_comm_legoshi",
small_text: "by TheAlfiTeam",
},
buttons: [
{
label: "Discord",
url: "https://discord.com/invite/catboat"
"label": "Discord",
"url": "https://discord.gg/catboat"
},
{
label: "CatBoat",
url: "https://catboat.fr/"
"label": "Download Launcher",
"url": "https://catboat.thealfigame.fr"
}
],
instance: true
@@ -30,12 +33,12 @@ class DiscordRPC {
this.client.request("SET_ACTIVITY", { pid: process.pid, activity: this.activity })
console.log("The Discord Rich Presence has been set successfully.")
})
this.client.login({ clientId: "1365563093157154868" }).catch(e => {
console.log(e)
this.client.login({ clientId: "1259291027148115988" }).catch(e => {
console.log("Silent client detected: the activity status has been disabled.")
console.log(e)
this.isEnabled = false
}).then(r => this.isEnabled = true)
.catch(err => console.log)
.catch(err => console.log(err))
}
}