This commit is contained in:
Gilles Lazures 2025-05-01 14:46:56 +02:00
parent 378e4b4823
commit 96e9173ff0
6 changed files with 355 additions and 154 deletions

View File

@ -79,18 +79,46 @@ function logout() {
document.location.href = './login.html'
}
system.result("server::ping", (pong) => {
playersStatus.innerText = `${pong.players.online}/${pong.players.max}`
})
system.result("player::profile", (playerProfile) => {
if (!localStorage.getItem("user")) {
localStorage.setItem("user", JSON.stringify(playerProfile))
}
})
function handleOptionsChanges(key, value) {
system.call("game::optionSet", { key, value })
}
function handleSettingsChanges(key, value) {
system.call("settings::set", { key, value })
}
system.result("game::parseOptions", (options) => {
gamma.checked = options.gamma == 1 ? true : false
renderClouds.checked = options.renderrenderClouds == false ? false : true
guiScale.value = options.guiScale
graphicsMode.checked = options.graphicsMode == 0 ? true : false
renderDistance.value = options.renderDistance
})
system.result("settings::read", (settings) => {
ram.value = settings.ram.max
})
system.result("hardware::ramInformation", ($ram) => {
ram.setAttribute("max", $ram.avaibleRam)
maxRam.innerText = `${Math.floor($ram.avaibleRam / 1024)} G`
})
window.onload = () => {
system.call("hardware::ramInformation")
system.call("game::parseOptions")
system.call("server::ping")
system.call("player::profile")
system.call("settings::read")
startAudio()
}
system.result("server::ping", (data) => {
playersStatus.innerText = `${data.players.online}/${data.players.max}`
})
system.result("player::profile", (data) => {
if (!localStorage.getItem("user")) {
localStorage.setItem("user", JSON.stringify(data))
}
})

View File

@ -49,8 +49,8 @@
<span>
0.5GB
</span>
<input type="range" name="ram" min="0" max="2048" id="ram">
<span>
<input type="range" name="ram" min="0" max="2048" id="ram" onchange="handleSettingsChanges(this.name, this.value)">
<span id="maxRam">
MAX
</span>
</div>
@ -62,20 +62,20 @@
<span>
4
</span>
<input type="range" name="ram" min="4" max="32" id="renderDistance">
<input type="range" name="renderDistance" min="4" max="32" id="renderDistance" onchange="handleOptionsChanges(this.name, this.value)">
<span>
32
</span>
</div>
<br>
<label>
Ram alloué
Taille de l'interface
</label>
<div class="ranges">
<span>
1
</span>
<input type="range" name="ram" min="1" max="4" id="guiScale">
<input type="range" name="guiScale" min="1" max="4" id="guiScale" onchange="handleOptionsChanges(this.name, this.value)">
<span>
4
</span>
@ -83,29 +83,29 @@
<br>
<div class="checkboxes">
<div>
<input type="checkbox" name="clouds" id="clouds">
<label for="clouds">
<input type="checkbox" name="renderClouds" id="renderClouds" onchange="handleOptionsChanges(this.name, this.checked)">
<label for="renderClouds">
Nuages
</label>
</div>
<div>
<input type="checkbox" name="lowGraphism" id="lowGraphism">
<label for="lowGraphism">
<input type="checkbox" name="graphicsMode" id="graphicsMode" onchange="handleOptionsChanges(this.name, this.checked)">
<label for="graphicsMode">
Graphisme bas
</label>
</div>
<div>
<input type="checkbox" name="fullbright" id="fullbright">
<label for="fullbright">
<input type="checkbox" name="gamma" id="gamma" onchange="handleOptionsChanges(this.name, this.checked)">
<label for="gamma">
Luminsoité max
</label>
</div>
<div>
<!-- <div>
<input type="checkbox" name="sildurs_shader" id="sildurs_shader">
<label for="sildurs_shader">
Sildur's Shader
</label>
</div>
</div> -->
</div>
</article>
</details>

76
main.js
View File

@ -4,15 +4,20 @@ 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()
try {
launcherWindow = new BrowserWindow({
frame: false,
width: win_width,
@ -81,32 +86,32 @@ async function createLauncherWindow() {
setBannedBecause("${isLauncherNotBanned.reason}")
`)
}
} catch (error) {
dialog.showErrorBox("Erreur", error)
}
} else {
dialog.showErrorBox("Connexion internet", "Le launcher requiert une connexion internet.")
}
}
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<hardware::ramInformation>", {
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<player::profile>", 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<game::parseOptions>", 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<settings::read>", $launcherSettings)
break
}
})

68
modules/gameOptions.js Normal file
View File

@ -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
}

View File

@ -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
}

116
modules/launcherSettings.js Normal file
View File

@ -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,
}