296 lines
7.6 KiB
JavaScript
296 lines
7.6 KiB
JavaScript
const path = require("node:path");
|
|
const fs = require("node:fs");
|
|
const https = require("node:https");
|
|
const process = require("node:process");
|
|
const os = require("node:os");
|
|
const child_process = require("node:child_process");
|
|
const electron = require("electron");
|
|
|
|
const update = require(path.join(__dirname, "update.js"));
|
|
|
|
let configFilePath;
|
|
let plutoniumInstallDirectory;
|
|
switch (os.platform()) {
|
|
case "win32":
|
|
configFilePath = path.join(process.env["LOCALAPPDATA"], "Plutonium", "open-plutonium-launcher.json");
|
|
plutoniumInstallDirectory = path.join(process.env["LOCALAPPDATA"], "Plutonium");
|
|
break;
|
|
case "linux":
|
|
configFilePath = path.join(os.userInfo().homedir, ".config", "open-plutonium-launcher.json");
|
|
plutoniumInstallDirectory = path.join(os.userInfo().homedir, ".local", "share", "Plutonium");
|
|
break;
|
|
case "darwin":
|
|
configFilePath = path.join(os.userInfo().homedir, "Library", "Application Support", "open-plutonium-launcher.json");
|
|
plutoniumInstallDirectory = path.join(os.userInfo().homedir, "Library", "Application Support", "Plutonium");
|
|
break;
|
|
default:
|
|
electron.dialog.showErrorBox("Incompatible system", "Sorry, your operating system doesn't seem to be supported...");
|
|
process.exit(1);
|
|
}
|
|
|
|
let mainWindow;
|
|
let plutoniumManifest = {
|
|
"product": "plutonium-core-prod",
|
|
"revision": -1,
|
|
"baseUrl": "https://cdn.plutonium.pw/updater/prod/files/",
|
|
"files": []
|
|
};
|
|
let userInfo = {
|
|
"token": "V3ryS3cr3t4uth3nt1c4t10nT0k3n",
|
|
"userId": -1,
|
|
"username": "AnonGuest",
|
|
"email": "guest@neverla.nd",
|
|
"emailVerified": false,
|
|
"avatar": "https://forum.plutonium.pw/assets/uploads/system/avatar-default.png"
|
|
};
|
|
|
|
function createMainWindow() {
|
|
mainWindow = new electron.BrowserWindow({
|
|
"minWidth": 640,
|
|
"minHeight": 480,
|
|
"width": 800,
|
|
"height": 600,
|
|
"fullscreenable": false,
|
|
"show": false,
|
|
"webPreferences": {
|
|
"preload": path.join(__dirname, "preload.js"),
|
|
"contextIsolation": true
|
|
}
|
|
});
|
|
|
|
mainWindow.loadFile(path.join(__dirname, "views", "login.html"));
|
|
|
|
mainWindow.once("ready-to-show", function () {
|
|
mainWindow.show();
|
|
});
|
|
}
|
|
|
|
function fetchPlutoniumManifest() {
|
|
return new Promise(function (resolve, reject) {
|
|
let request = https.request("https://cdn.plutonium.pw/updater/prod/info.json", {
|
|
"method": "GET"
|
|
}, function (response) {
|
|
if (response.statusCode !== 200) {
|
|
return reject(new Error("Failed to fetch the Plutonium launcher manifest."));
|
|
}
|
|
|
|
response.setEncoding("utf-8");
|
|
|
|
let body = "";
|
|
response.on("data", function (chunk) {
|
|
body += chunk;
|
|
});
|
|
response.on("end", function () {
|
|
try {
|
|
let data = JSON.parse(body);
|
|
|
|
resolve(data);
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
});
|
|
});
|
|
|
|
request.on("error", function (error) {
|
|
reject(error);
|
|
});
|
|
|
|
request.end();
|
|
});
|
|
}
|
|
|
|
function getPlutoniumSession(game, token) {
|
|
return new Promise(function (resolve, reject) {
|
|
let payload = JSON.stringify({
|
|
"game": game
|
|
});
|
|
|
|
let request = https.request("https://nix.plutonium.pw/api/auth/session", {
|
|
"method": "POST",
|
|
"headers": {
|
|
"Content-Type": "application/json",
|
|
"Content-Length": payload.length,
|
|
"Authorization": "UserToken " + token,
|
|
"X-Plutonium-Revision": String(plutoniumManifest.revision),
|
|
"User-Agent": "Nix/3.0"
|
|
}
|
|
}, function (response) {
|
|
if (response.statusCode !== 200) {
|
|
return resolve({
|
|
"status": "unauthenticated",
|
|
"successful": false
|
|
});
|
|
}
|
|
|
|
response.setEncoding("utf-8");
|
|
|
|
let body = "";
|
|
response.on("data", function (chunk) {
|
|
body += chunk;
|
|
});
|
|
response.on("end", function () {
|
|
try {
|
|
let data = JSON.parse(body);
|
|
|
|
if (!("token" in data)) {
|
|
reject(new Error("Authentication seems to be successful but no token was returned."));
|
|
}
|
|
|
|
resolve({
|
|
"status": "authenticated",
|
|
"successful": true,
|
|
...data
|
|
});
|
|
|
|
userInfo = data;
|
|
|
|
mainWindow.loadFile(path.join(__dirname, "src", "views", "games.html"));
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
});
|
|
});
|
|
|
|
request.on("error", function (error) {
|
|
reject(error);
|
|
});
|
|
|
|
request.write(payload);
|
|
request.end();
|
|
});
|
|
}
|
|
|
|
function launch(plutoniumInstallDirectory, game, gameInstallDirectory, online) {
|
|
return new Promise(function (resolve, reject) {
|
|
getPlutoniumSession(game, userInfo.token).then(function (data) {
|
|
if (!data.successful) {
|
|
return reject(new Error("Authentication has failed."));
|
|
}
|
|
|
|
let bootstrapperBinary = path.join(plutoniumInstallDirectory, "bin", "plutonium-bootstrapper-win32.exe");
|
|
let bootstrapperArguments = [game, gameInstallDirectory];
|
|
|
|
if (online) {
|
|
bootstrapperArguments.push("-token");
|
|
bootstrapperArguments.push(data.token);
|
|
} else {
|
|
bootstrapperArguments.push("+name");
|
|
bootstrapperArguments.push(userInfo.username);
|
|
bootstrapperArguments.push("-lan");
|
|
}
|
|
|
|
let gameProcess = child_process.spawn(bootstrapperBinary, bootstrapperArguments, {
|
|
"detached": true,
|
|
"stdio": "ignore"
|
|
});
|
|
|
|
gameProcess.on("spawn", function () {
|
|
resolve(true);
|
|
});
|
|
gameProcess.on("error", function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
electron.app.once("ready", function () {
|
|
createMainWindow();
|
|
fetchPlutoniumManifest().then(function (manifest) {
|
|
plutoniumManifest = manifest;
|
|
}).catch(function (error) {
|
|
electron.dialog.showErrorBox("Error", "The Plutonium launcher manifest could not be fetched, auto-updating might not be possible.\n" + error.message);
|
|
});
|
|
});
|
|
|
|
electron.app.on("window-all-closed", function () {
|
|
electron.app.quit();
|
|
});
|
|
|
|
electron.ipcMain.handle("login", function (event, username, password) {
|
|
return new Promise(function (resolve, reject) {
|
|
let payload = JSON.stringify({
|
|
"username": username,
|
|
"password": password
|
|
});
|
|
|
|
let request = https.request("https://nix.plutonium.pw/api/auth/login", {
|
|
"method": "POST",
|
|
"headers": {
|
|
"Content-Type": "application/json",
|
|
"Content-Length": payload.length,
|
|
"Authorization": "UserToken",
|
|
"X-Plutonium-Revision": String(plutoniumManifest.revision),
|
|
"User-Agent": "Nix/3.0"
|
|
}
|
|
}, function (response) {
|
|
if (response.statusCode !== 200) {
|
|
return resolve({
|
|
"status": "unauthenticated",
|
|
"successful": false
|
|
});
|
|
}
|
|
|
|
response.setEncoding("utf-8");
|
|
|
|
let body = "";
|
|
response.on("data", function (chunk) {
|
|
body += chunk;
|
|
});
|
|
response.on("end", function () {
|
|
try {
|
|
let data = JSON.parse(body);
|
|
|
|
if (!("token" in data)) {
|
|
reject(new Error("Login seems to be successful but no token was returned."));
|
|
}
|
|
|
|
resolve({
|
|
"status": "authenticated",
|
|
"successful": true,
|
|
...data
|
|
});
|
|
|
|
userInfo = data;
|
|
|
|
mainWindow.loadFile(path.join(__dirname, "src", "views", "games.html"));
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
});
|
|
});
|
|
|
|
request.on("error", function (error) {
|
|
reject(error);
|
|
});
|
|
|
|
request.write(payload);
|
|
request.end();
|
|
});
|
|
});
|
|
|
|
electron.ipcMain.handle("launch", function (event, game, online = true) {
|
|
return new Promise(function (resolve, reject) {
|
|
if (!(game in config.gameDirectories)) {
|
|
return resolve(false);
|
|
}
|
|
let gameInstallDirectory = config.gameDirectories[game];
|
|
|
|
update.checkFiles(plutoniumManifest, plutoniumInstallDirectory).then(function (fileList) {
|
|
let filesToUpdate = fileList.filter(function (file) {
|
|
return !file.ok;
|
|
});
|
|
|
|
update.downloadFiles(plutoniumInstallDirectory, plutoniumManifest.baseUrl, filesToUpdate).then(function () {
|
|
launch(plutoniumInstallDirectory, game, gameInstallDirectory, online).then(function (result) {
|
|
resolve(result);
|
|
});
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
});
|