-
-
-
-
+
+
Graphisme bas
-
-
+
+
Luminsoité max
-
+
diff --git a/main.js b/main.js
index 3d7d1ae..31478d9 100644
--- a/main.js
+++ b/main.js
@@ -4,82 +4,90 @@ const os = require("os")
const hwid = require("./modules/hwid")
const path = require("node:path")
const serverPing = require("./modules/serverPing")
+const gameOptions = require("./modules/gameOptions")
+const launcherSettings = require("./modules/launcherSettings")
const config = require("./config.json")
const { Authenticator } = require("minecraft-launcher-core")
-let launcherWindow, auth, skinPath
+let launcherWindow, auth
async function createLauncherWindow() {
+ gameOptions.initOptions(path.join(app.getPath("appData"), ".catboat", "options.txt"))
+ launcherSettings.initSettings(path.join(app.getPath("appData"), ".catboat"))
if (net.isOnline()) {
let win_width = 1550
let win_height = parseInt(win_width / (16/9))
const isLauncherNotBanned = await checkIfIAmBanned()
- launcherWindow = new BrowserWindow({
- frame: false,
- width: win_width,
- height: win_height,
- minWidth: win_width,
- minHeight: win_height,
- titleBarStyle: "hidden",
- autoHideMenuBar: true,
- roundedCorners: false,
- resizable: false,
- webPreferences: {
- nodeIntegration: false,
- contextIsolation: true,
- preload: path.join(__dirname, "modules", "preload.js"),
- webviewTag: true
- }
- })
- if (os.platform() == "darwin") {
- app.dock.setIcon(nativeImage.createFromPath(path.join(__dirname, "app", "assets", "img", "icon.png")))
- }
- launcherWindow.setIcon(path.join(__dirname, "app", "assets", "img", "icon.png"))
- if (isLauncherNotBanned.success) {
- launcherWindow.loadFile(path.join(__dirname, "app", "login.html"))
- session.defaultSession.webRequest.onBeforeRequest({
- urls: [
- "https://embed.twitch.tv/*channel=*"
- ]
- }, (details, callback) => {
- const url = details.url
- const urlParams = new URLSearchParams(url.replace("https://embed.twitch.tv/", ""))
- if (urlParams.get("parent")) {
- callback({})
- return
+ try {
+ launcherWindow = new BrowserWindow({
+ frame: false,
+ width: win_width,
+ height: win_height,
+ minWidth: win_width,
+ minHeight: win_height,
+ titleBarStyle: "hidden",
+ autoHideMenuBar: true,
+ roundedCorners: false,
+ resizable: false,
+ webPreferences: {
+ nodeIntegration: false,
+ contextIsolation: true,
+ preload: path.join(__dirname, "modules", "preload.js"),
+ webviewTag: true
}
-
- urlParams.set("parent", "localhost")
- urlParams.set("referrer", "https://localhost/")
-
- const redirectUrl = `https://embed.twitch.tv/?${urlParams.toString()}`
- callback({
- cancel: false,
- redirectURL: redirectUrl
- })
})
-
- session.defaultSession.webRequest.onHeadersReceived({
- urls: [
- "https://www.twitch.tv/*",
- "https://player.twitch.tv/*",
- "https://embed.twitch.tv/*"
- ]
- }, (details, callback) => {
- const responseHeaders = details.responseHeaders
- delete responseHeaders["Content-Security-Policy"]
- callback({
- cancel: false,
- responseHeaders
+ if (os.platform() == "darwin") {
+ app.dock.setIcon(nativeImage.createFromPath(path.join(__dirname, "app", "assets", "img", "icon.png")))
+ }
+ launcherWindow.setIcon(path.join(__dirname, "app", "assets", "img", "icon.png"))
+ if (isLauncherNotBanned.success) {
+ launcherWindow.loadFile(path.join(__dirname, "app", "login.html"))
+ session.defaultSession.webRequest.onBeforeRequest({
+ urls: [
+ "https://embed.twitch.tv/*channel=*"
+ ]
+ }, (details, callback) => {
+ const url = details.url
+ const urlParams = new URLSearchParams(url.replace("https://embed.twitch.tv/", ""))
+ if (urlParams.get("parent")) {
+ callback({})
+ return
+ }
+
+ urlParams.set("parent", "localhost")
+ urlParams.set("referrer", "https://localhost/")
+
+ const redirectUrl = `https://embed.twitch.tv/?${urlParams.toString()}`
+ callback({
+ cancel: false,
+ redirectURL: redirectUrl
+ })
})
- })
- launcherWindow.webContents.openDevTools()
- } else {
- launcherWindow.loadFile(path.join(__dirname, "app", "banned.html"))
- launcherWindow.webContents.executeJavaScript(`
- setBannedBy("${isLauncherNotBanned.banned_by}")
- setBannedAt("${isLauncherNotBanned.banned_at}")
- setBannedBecause("${isLauncherNotBanned.reason}")
- `)
+
+ session.defaultSession.webRequest.onHeadersReceived({
+ urls: [
+ "https://www.twitch.tv/*",
+ "https://player.twitch.tv/*",
+ "https://embed.twitch.tv/*"
+ ]
+ }, (details, callback) => {
+ const responseHeaders = details.responseHeaders
+ delete responseHeaders["Content-Security-Policy"]
+ callback({
+ cancel: false,
+ responseHeaders
+ })
+ })
+ launcherWindow.webContents.openDevTools()
+ } else {
+ launcherWindow.loadFile(path.join(__dirname, "app", "banned.html"))
+ launcherWindow.webContents.executeJavaScript(`
+ setBannedBy("${isLauncherNotBanned.banned_by}")
+ setBannedAt("${isLauncherNotBanned.banned_at}")
+ setBannedBecause("${isLauncherNotBanned.reason}")
+ `)
+ }
+ } catch (error) {
+ dialog.showErrorBox("Erreur", error)
}
} else {
dialog.showErrorBox("Connexion internet", "Le launcher requiert une connexion internet.")
@@ -87,26 +95,23 @@ async function createLauncherWindow() {
}
async function checkIfIAmBanned() {
- // if (net.isOnline()) {
- // try {
- // const reponse = await fetch(`${config.api.base}${config.api.endpoints.checkBanStatus}`, {
- // method: "post",
- // body: JSON.stringify({
- // hwid: hwid.getHWID()
- // })
- // })
- // const json = await reponse.json()
- // return json
- // } catch (error) {
- // dialog.showErrorBox("Connexion à l'API", "Impossible de contacter l'API, fermeture du launcher.")
- // console.error(error)
- // app.exit()
- // }
- // } else {
- // dialog.showErrorBox("Connexion internet", "Le launcher requiert une connexion internet.")
- // }
- return {
- success: true
+ if (net.isOnline()) {
+ try {
+ const reponse = await fetch(`${config.api.base}${config.api.endpoints.checkBanStatus}`, {
+ method: "post",
+ body: JSON.stringify({
+ hwid: hwid.getHWID()
+ })
+ })
+ const json = await reponse.json()
+ return json
+ } catch (error) {
+ dialog.showErrorBox("Connexion à l'API", "Impossible de contacter l'API, fermeture du launcher.")
+ console.error(error)
+ app.exit()
+ }
+ } else {
+ dialog.showErrorBox("Connexion internet", "Le launcher requiert une connexion internet.")
}
}
@@ -124,7 +129,7 @@ app.on("window-all-closed", () => {
ipcMain.on("call", async (event, data) => {
switch (data.method) {
case "hardware::ramInformation":
- launcherWindow.webContents.send("hardware::ramInformation", {
+ launcherWindow.webContents.send("Response
", {
totalRam: Math.round(os.totalmem() / 1024 / 1024 * 100) / 100,
avaibleRam: Math.round(os.freemem() / 1024 / 1024 * 100) / 100,
})
@@ -219,5 +224,32 @@ ipcMain.on("call", async (event, data) => {
case "player::profile":
await launcherWindow.webContents.send("Response", auth)
break
+ case "game::parseOptions":
+ const $gameOptions = gameOptions.parseOptions()
+ const allowedKeys = ["renderDistance", "renderClouds", "graphicsMode", "gamma", "graphicsMode", "guiScale"]
+ const filteredOptions = Object.fromEntries(
+ Object.entries($gameOptions).filter(([key]) => allowedKeys.includes(key))
+ )
+ launcherWindow.webContents.send("Response", filteredOptions)
+ break
+ case "game::optionSet":
+ const options = gameOptions.parseOptions()
+ switch (data.args.key) {
+ case "graphicsMode":
+ options.graphicsMode = data.args.key == true ? 0 : 1
+ break
+ case "gamma":
+ options.gamma = data.args.key == false ? 0.50 : 1.0
+ break
+ default:
+ options[data.args.key] = data.args.value
+ break
+ }
+ gameOptions.saveOptions(gameOptions.stringfyOptions(options))
+ break
+ case "settings::read":
+ const $launcherSettings = launcherSettings.readSettings()
+ launcherWindow.webContents.send("Response", $launcherSettings)
+ break
}
})
\ No newline at end of file
diff --git a/modules/gameOptions.js b/modules/gameOptions.js
new file mode 100644
index 0000000..2aa13a5
--- /dev/null
+++ b/modules/gameOptions.js
@@ -0,0 +1,68 @@
+const fs = require("node:fs")
+const path = require("node:path")
+let optionsFile
+
+function initOptions($optionFile) {
+ optionsFile = $optionFile
+ const gameDir = path.parse($optionFile).dir
+ if (!fs.existsSync(gameDir)) {
+ try {
+ fs.mkdirSync(gameDir)
+ } catch (error) {
+ throw error
+ }
+ }
+ if (!fs.existsSync($optionFile)) {
+ try {
+ fs.copyFileSync(path.join(__dirname, "..", "options.txt"), $optionFile)
+ } catch (error) {
+ throw error
+ }
+ }
+}
+
+function parseOptions() {
+ const options = fs.readFileSync(optionsFile, "utf-8").toString().split("\n").filter(line => line.trim() !== "")
+ const parsedOptions = {}
+ for (let i = 0; i < options.length; i++) {
+ const line = options[i].trim()
+ const [key, value] = line.split(":")
+ if (key && value) {
+ const trimmedValue = value.trim().toLowerCase()
+ if (trimmedValue === "true" || trimmedValue === "false") {
+ parsedOptions[key.trim()] = trimmedValue === "true"
+ } else {
+ parsedOptions[key.trim()] = isNaN(value) ? value.trim() : parseInt(value, 10)
+ }
+ }
+ }
+ return parsedOptions
+}
+
+function stringfyOptions(optionsObject) {
+ const optionsArray = []
+ if (typeof optionsObject !== "object" || optionsObject === null) {
+ throw new Error("Invalid options object")
+ }
+ for (const settingKey in optionsObject) {
+ if (Object.prototype.hasOwnProperty.call(optionsObject, settingKey)) {
+ const settingValue = optionsObject[settingKey]
+ if (typeof settingValue === "object" || typeof settingValue === "function" || typeof settingValue === "symbol") {
+ throw new Error(`Invalid value for setting "${settingKey}": ${settingValue}`)
+ }
+ optionsArray.push(`${settingKey}:${settingValue}`)
+ }
+ }
+ return optionsArray.join("\n")
+}
+
+function saveOptions(options) {
+ fs.writeFileSync(optionsFile, options, "utf8")
+}
+
+module.exports = {
+ initOptions,
+ saveOptions,
+ parseOptions,
+ stringfyOptions
+}
\ No newline at end of file
diff --git a/modules/gameSettings.js b/modules/gameSettings.js
deleted file mode 100644
index 8ed46f5..0000000
--- a/modules/gameSettings.js
+++ /dev/null
@@ -1,43 +0,0 @@
-const fs = require("node:fs")
-const path = require("node:path")
-
-function parseSettings(settingsFile) {
- const settings = fs.readFileSync(settingsFile, "utf-8").toString().split("\n").filter(line => line.trim() !== "")
- const parseSettings = {}
- for (let i = 0; i < settings.length; i++) {
- const line = settings[i].trim()
- const [key, value] = line.split(":")
- if (key && value) {
- const trimmedValue = value.trim().toLowerCase()
- if (trimmedValue === "true" || trimmedValue === "false") {
- parseSettings[key.trim()] = trimmedValue === "true"
- } else {
- parseSettings[key.trim()] = isNaN(value) ? value.trim() : parseInt(value, 10)
- }
- }
- }
- return parseSettings
-}
-
-function stringfySettings(settingsFile) {
- const settingsObject = JSON.parse(fs.readFileSync(settingsFile, "utf-8").toString())
- const settingsArray = []
- if (typeof settingsObject !== "object" || settingsObject === null) {
- throw new Error("Invalid settings object")
- }
- for (const settingKey in settingsObject) {
- if (Object.prototype.hasOwnProperty.call(settingsObject, settingKey)) {
- const settingValue = settingsObject[settingKey]
- if (typeof settingValue === "object" || typeof settingValue === "function" || typeof settingValue === "symbol") {
- throw new Error(`Invalid value for setting "${settingKey}": ${settingValue}`)
- }
- settingsArray.push(`${settingKey}:${settingValue}`)
- }
- }
- return settingsArray.join("\n")
-}
-
-module.exports = {
- parseSettings,
- stringfySettings
-}
\ No newline at end of file
diff --git a/modules/launcherSettings.js b/modules/launcherSettings.js
new file mode 100644
index 0000000..9d73dc5
--- /dev/null
+++ b/modules/launcherSettings.js
@@ -0,0 +1,116 @@
+const fs = require("node:fs")
+const path = require("node:path")
+
+let launcherDataPath = path.join(__dirname, ".catboat")
+
+const baseSettings = {
+ ram: {
+ max: 1024
+ }
+}
+
+function initSettings($launcherDataPath) {
+ launcherDataPath = $launcherDataPath
+ const gameDir = path.parse($launcherDataPath).dir
+ if (!fs.existsSync(gameDir)) {
+ try {
+ fs.mkdirSync(gameDir)
+ } catch (error) {
+ throw error
+ }
+ }
+ if (!fs.existsSync($launcherDataPath)) {
+ try {
+ fs.writeFileSync($launcherDataPath, JSON.stringify(baseSettings, null, 4))
+ } catch (error) {
+ throw error
+ }
+ }
+}
+
+function getLauncherDataPath() {
+ return launcherDataPath
+}
+
+function writeSettings(settings) {
+ try {
+ fs.writeFileSync(path.join(launcherDataPath, "launcher_settings.json"), JSON.stringify(settings, null, 4))
+ return
+ } catch (error) {
+ throw error
+ }
+}
+
+function get(key) {
+ try {
+ const settings = JSON.parse(fs.readFileSync(path.join(launcherDataPath, "launcher_settings.json")))
+
+ const keys = key.split(".")
+ let value = settings
+
+ for (const k of keys) {
+ if (value[k] !== undefined) {
+ value = value[k]
+ } else {
+ throw new Error(`La clé '${key}' n'existe pas.`)
+ }
+ }
+
+ return value
+ } catch (error) {
+ console.error("Erreur lors de l'accès aux paramètres :", error.message)
+ throw error
+ }
+}
+
+function set(key, newValue) {
+ try {
+ const filePath = path.join(launcherDataPath, "launcher_settings.json")
+ const settings = JSON.parse(fs.readFileSync(filePath))
+
+ const keys = key.split(".")
+ let obj = settings
+
+ for (let i = 0; i < keys.length - 1; i++) {
+ const k = keys[i]
+ if (!obj[k]) {
+ obj[k] = {}
+ }
+ obj = obj[k]
+ }
+
+ obj[keys[keys.length - 1]] = newValue
+
+ fs.writeFileSync(filePath, JSON.stringify(settings, null, 2))
+ } catch (error) {
+ console.error("Erreur lors de la mise à jour des paramètres :", error.message)
+ throw error
+ }
+}
+
+function clean() {
+ try {
+ fs.writeFileSync(path.join(launcherDataPath, "launcher_settings.json"), JSON.stringify(baseSettings, null, 4))
+ return
+ } catch (error) {
+ throw error
+ }
+}
+
+function readSettings() {
+ try {
+ return JSON.parse(fs.readFileSync(path.join(launcherDataPath, "launcher_settings.json")))
+ } catch (error) {
+ throw error
+ }
+}
+
+module.exports = {
+ getLauncherDataPath,
+ writeSettings,
+ readSettings,
+ initSettings,
+ clean,
+ get,
+ set,
+}
\ No newline at end of file