diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app/browser.js | 235 | ||||
-rw-r--r-- | src/app/icons/no-image.png | bin | 0 -> 1959 bytes | |||
-rw-r--r-- | src/app/index.html | 15 | ||||
-rw-r--r-- | src/app/main.css | 244 | ||||
-rw-r--r-- | src/app/main.js | 18 | ||||
-rw-r--r-- | src/index.js | 4 | ||||
-rw-r--r-- | src/lang/en.json | 10 | ||||
-rw-r--r-- | src/lang/es.json | 214 | ||||
-rw-r--r-- | src/lang/fr.json | 10 | ||||
-rw-r--r-- | src/utils.js | 130 |
10 files changed, 730 insertions, 150 deletions
diff --git a/src/app/browser.js b/src/app/browser.js new file mode 100644 index 0000000..5062d86 --- /dev/null +++ b/src/app/browser.js @@ -0,0 +1,235 @@ +const Fuse = require("fuse.js"); +var fuse; +var packages = []; + +var Browser = { + maxentries: 50, + toggle: (state) => { + if (state) { + browser.scrollTo(0, 0); + overlay.classList.add("shown") + browser.classList.add("shown") + return + } else if (! state) { + if (state != undefined) { + overlay.classList.remove("shown") + browser.classList.remove("shown") + return + } + } + + browser.scrollTo(0, 0); + overlay.classList.toggle("shown") + browser.classList.toggle("shown") + }, + loadfront: async () => { + Browser.loading(); + + if (packages.length < 1) { + packages = await (await fetch("https://northstar.thunderstore.io/api/v1/package/")).json(); + + fuse = new Fuse(packages, { + keys: ["full_name"] + }) + } + + for (let i in packages) { + if (i == Browser.maxentries) {Browser.endoflist();break} + new BrowserElFromObj(packages[i]); + } + }, + loading: (string) => { + if (string) { + browserEntries.innerHTML = `<div class="loading">${string}</div>`; + } + + if (! browserEntries.querySelector(".loading")) { + browserEntries.innerHTML = `<div class="loading">${lang('gui.browser.loading')}</div>`; + } + }, + endoflist: () => { + browserEntries.innerHTML += `<div class="message">${lang('gui.browser.endoflist')}</div>` + }, + search: (string) => { + Browser.loading(); + let res = fuse.search(string); + + if (res.length < 1) { + Browser.loading("No results...") + return + } + + for (let i = 0; i < res.length; i++) { + if (i == Browser.maxentries) {Browser.endoflist();break} + new BrowserElFromObj(res[i].item); + } + }, + setbutton: (mod, string) => { + mod = normalize(mod); + if (document.getElementById(mod)) { + let elems = document.querySelectorAll(`#${mod}`); + + for (let i = 0; i < elems.length; i++) { + elems[i].querySelector(".text button").innerHTML = string; + } + } else { + let make = (str) => { + if (document.getElementById(str)) { + return Browser.setbutton(str, string); + } else { + return false; + } + } + + setTimeout(() => { + for (let i = 0; i < modsobj.all.length; i++) { + let modname = normalize(modsobj.all[i].Name); + let modfolder = normalize(modsobj.all[i].FolderName); + + if (mod.includes(modname)) { + if (! make(modname)) { + if (modsobj.all[i].ManifestName) { + make(normalize(modsobj.all[i].ManifestName)); + } + } + } + else if (mod.includes(modfolder)) {make(modfolder);break} + } + }, 1501) + } + } +}; Browser.loadfront() + +document.body.addEventListener("keyup", (e) => { + if (e.key == "Escape") {Browser.toggle(false)} +}) + +function BrowserElFromObj(obj) { + let pkg = {...obj, ...obj.versions[0]}; + + new BrowserEl({ + title: pkg.name, + image: pkg.icon, + author: pkg.owner, + url: pkg.package_url, + download: pkg.download_url, + version: pkg.version_number, + description: pkg.description + }) +} + +function BrowserEl(properties) { + properties = { + title: "No name", + version: "1.0.0", + image: "icons/no-image.png", + author: "Unnamed Pilot", + description: "No description", + ...properties + } + + if (properties.version[0] != "v") { + properties.version = "v" + properties.version; + } + + if (browserEntries.querySelector(".loading")) { + browserEntries.innerHTML = ""; + } + + let installstr = lang("gui.browser.install"); + + if (normalize(modsdiv.innerText.split("\n")).includes(normalize(properties.title))) { + installstr = lang("gui.browser.reinstall"); + + for (let i = 0; i < modsobj.all.length; i++) { + if (normalize(modsobj.all[i].Name) == normalize(properties.title) + && "v" + modsobj.all[i].Version != properties.version) { + + installstr = lang("gui.browser.update"); + } + } + } else { + for (let i = 0; i < modsobj.all.length; i++) { + let title = normalize(properties.title); + let folder = normalize(modsobj.all[i].FolderName); + let manifestname = null; + if (modsobj.all[i].ManifestName) { + manifestname = normalize(modsobj.all[i].ManifestName); + } + + if (title.includes(folder) || title.includes(manifestname)) { + installstr = lang("gui.browser.reinstall"); + + if (folder == title + && "v" + modsobj.all[i].Version != properties.version) { + + installstr = lang("gui.browser.update"); + } + } + } + } + + browserEntries.innerHTML += ` + <div class="el" id="${normalize(properties.title)}"> + <div class="image"> + <img src="${properties.image}"> + </div> + <div class="text"> + <div class="title">${properties.title}</div> + <div class="description">${properties.description}</div> + <button onclick="installFromURL('${properties.download}')">${installstr}</button> + <button onclick="require('electron').shell.openExternal('${properties.url}')">${lang('gui.browser.info')}</button> + <button class="visual">${properties.version}</button> + <button class="visual">${lang("gui.browser.madeby")} ${properties.author}</button> + </div> + </div> + ` +} + +ipcRenderer.on("removedmod", (event, mod) => { + setButtons(true); + Browser.setbutton(mod.name, lang("gui.browser.install")); + if (mod.manifestname) { + Browser.setbutton(mod.manifestname, lang("gui.browser.install")); + } +}) + +ipcRenderer.on("installedmod", (event, modname) => { + setButtons(true); + Browser.setbutton(modname, lang("gui.browser.reinstall")); +}) + +function normalize(items) { + let main = (string) => { + return string.replaceAll(" ", "").replaceAll(".", "").replaceAll("-", "").replaceAll("_", "").toLowerCase() + } + if (typeof items == "string") { + return main(items) + } else { + let newArray = []; + for (let i = 0; i < items.length; i++) { + newArray.push(main(items[i])); + } + + return newArray; + } +} + +let searchtimeout; +let searchstr = ""; +search.addEventListener("keyup", () => { + clearTimeout(searchtimeout); + + if (searchstr != search.value) { + if (search.value.replaceAll(" ", "") == "") { + searchstr = ""; + Browser.loadfront(); + return + } + + searchtimeout = setTimeout(() => { + Browser.search(search.value); + searchstr = search.value; + }, 500) + } +}) diff --git a/src/app/icons/no-image.png b/src/app/icons/no-image.png Binary files differnew file mode 100644 index 0000000..43265d1 --- /dev/null +++ b/src/app/icons/no-image.png diff --git a/src/app/index.html b/src/app/index.html index fe383a0..b861736 100644 --- a/src/app/index.html +++ b/src/app/index.html @@ -12,6 +12,19 @@ <div id="minimize" onclick="ipcRenderer.send('minimize')"></div> <div id="close" onclick="ipcRenderer.send('exit')"></div> </div> + + <div id="overlay" onclick="Browser.toggle(false)"></div> + <div id="browser"> + <div id="misc"> + <input id="search" placeholder="%%gui.browser.search%%"> + <button id="close" onclick="Browser.toggle(false)"> + <img src="icons/close.png"> + </button> + </div> + <div id="browserEntries"> + <div class="loading">%%gui.browser.loading%%</div> + </div> + </div> <nav class="gamesContainer"> <button id="vpBtn" onclick="page(0)"></button> @@ -79,6 +92,7 @@ <button id="togglemod" onclick="selected().toggle()">%%gui.mods.toggle%%</button> <button id="toggleall" onclick="selected(true).toggle(true)">%%gui.mods.toggleall%%</button> <button id="installmod" onclick="installmod()">%%gui.mods.install%%</button> + <button id="installmod" onclick="Browser.toggle(true)">%%gui.mods.find%%</button> </div> </div> </div> @@ -102,6 +116,7 @@ <script src="lang.js"></script> <script src="main.js"></script> + <script src="browser.js"></script> <script src="launcher.js"></script> </body> </html> diff --git a/src/app/main.css b/src/app/main.css index de0db46..94ef767 100644 --- a/src/app/main.css +++ b/src/app/main.css @@ -9,7 +9,11 @@ --selbg: rgba(80, 80, 80, 0.5); --redbg: linear-gradient(45deg, var(--red), #FA4343); --bluebg: linear-gradient(45deg, var(--blue), #7380ED); +} +#browser, #modsdiv { + outline: 1px solid #444444; + border: 3px solid var(--bg); } ::-webkit-scrollbar { @@ -26,12 +30,191 @@ background: var(--red); } +::selection { + color: black; + background: var(--red); +} + +body { + margin: 0; + overflow: hidden; + user-select: none; +} + +body, button, input {font-family: "Roboto", sans-serif} + +button {outline: none} +b, strong {font-weight: 700} +body, input, button {font-weight: 500} + +button { + border: none; + color: white; + outline: none; + cursor: pointer; + font-weight: 700; + padding: 5px 10px; + border-radius: 5px; + transition: 0.2s ease-in-out; +} + .playBtn, .gamesContainer button, #winbtns div { cursor: pointer; } -#winbtns { +#browser { + --spacing: var(--padding); + + z-index: 2; + opacity: 0.0; + position: fixed; + overflow-y: scroll; + top: var(--spacing); + pointer-events: none; + left: var(--spacing); + background: var(--bg); + right: var(--spacing); + bottom: var(--spacing); + transform: scale(0.98); + backdrop-filter: blur(15px); + border-radius: calc(var(--padding) / 3); + transition: opacity 0.15s ease-in-out, transform 0.15s ease-in-out; +} + +#browser.shown { + opacity: 1.0; + pointer-events: all; + transform: scale(1.0); +} + +#overlay { + top: 0; + left: 0; + right: 0; + bottom: 0; z-index: 1; + opacity: 0.0; + position: fixed; + background: var(--bg); + pointer-events: none; + transition: opacity 0.15s ease-in-out; +} + +#overlay.shown { + opacity: 0.8; + pointer-events: all; +} + +@keyframes fadein { + 0% {opacity: 0.0} + 100% {opacity: 1.0} +} + +#browser .el, #browser #misc, #browser .loading { + --spacing: calc(var(--padding) / 2); + --height: calc(var(--padding) * 3); + --mischeight: calc(var(--padding) * 1.5); + + animation-duration: 0.15s; + animation-iteration-count: 1; + animation-name: fadein; + animation-fill-mode: forwards; + animation-timing-function: ease-in-out; + + opacity: 0.0; + transition: 0.15s ease-in-out; +} + +#browser .el, #browser #search, #browser #close { + color: white; + display: flex; + align-items: center; + height: var(--height); + margin: var(--spacing); + padding: var(--spacing); + background: var(--selbg); + border-radius: var(--spacing); + width: calc(100% - var(--spacing) * 4); +} + +#browser #misc, #browser #search { + --height: var(--mischeight); +} + +#browser #misc { + display: flex; +} + +#browser #search { + border: none; + outline: none; + transition: filter 0.15s ease-in-out; + width: calc(100% - var(--spacing) * 2); +} + +#browser #search:focus { + filter: brightness(1.5); +} + +#browser #close { + --height: calc(var(--padding) * 1.5); + + padding: 0px; + margin-left: 0px; + width: var(--height); +} + +#browser #close img { + opacity: 0.6; + width: var(--height); + height: var(--height); + transform: scale(0.6); +} + +#browser .loading { + width: 100%; + color: white; + display: flex; + text-align: center; + align-items: center; + justify-content: center; + height: calc(100% - var(--mischeight) - var(--height)); +} + +#browser .message { + color: white; + text-align: center; + margin: var(--padding); + width: calc(100% - var(--padding)); +} + +#browser .el .image, #browser .el .image img { + width: var(--height); + height: var(--height); + margin-right: var(--spacing); + border-radius: var(--spacing); +} + +#browser .el .text { + overflow: hidden; +} + +#browser .el .title, #browser .el .description { + height: 1.2em; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +#browser .el .title {font-size: 1.2em} +#browser .el .description {font-size: 0.8em} +#browser .el button { + background: var(--blue); + margin-top: var(--spacing); +} + +#winbtns { + z-index: 2; display: flex; position: fixed; top: var(--padding); @@ -54,40 +237,18 @@ #winbtns div:hover {opacity: 1.0} #winbtns div:active {transform: scale(0.98)} -body { - margin: 0; - overflow: hidden; - user-select: none; - font-family: "Roboto", sans-serif; -} - -button {outline: none} -b, strong {font-weight: 700} -body, input, button {font-weight: 500} - -button { - border: none; - color: white; - outline: none; - font-weight: 700; - padding: 5px 10px; - border-radius: 5px; - transition: 0.2s ease-in-out; -} - button:hover {filter: brightness(110%)} button:active {filter: brightness(90%)} img {pointer-events: none} #bgHolder { - top: 0; - left: 0; - right: 0; - bottom: 0; - pointer-events: none; - position: fixed; - transform: scale(1.1); + top: -5px; + left: -5px; + right: -5px; + bottom: -5px; + z-index: -1; + position: absolute; background-size: cover; background-position: center; background-repeat: no-repeat; @@ -162,7 +323,7 @@ img {pointer-events: none} } .contentContainer { - width: 90%; + width: 85%; color: white; flex-grow: 1; opacity: 1.0; @@ -346,6 +507,12 @@ button:disabled { pointer-events: none; } +button.visual { + opacity: 1.0; + pointer-events: none; + background: transparent !important; +} + code { font-size: 16px; padding: 2px 5px; @@ -385,16 +552,27 @@ code { } .modbtns button { - margin-left: calc(var(--padding) / 3); + margin-left: var(--spacing); + --spacing: calc(var(--padding) / 3); + margin-top: calc(var(--spacing) / 2); + margin-bottom: calc(var(--spacing) / 2); } /* drag control */ -#bgHolder { +#bgHolder, +.contentContainer, +.gamesContainer { user-select: none; -webkit-app-region: drag; } -a, button, .contentMenu, #close, #nsRelease, #vpReleaseNotes, .mod { +#overlay.shown ~ #bgHolder, +#overlay.shown ~ .contentContainer, +#overlay.shown ~ .gamesContainer { + -webkit-app-region: no-drag; +} + +a, button, #close, #nsRelease, #vpReleaseNotes, .mod, #overlay, #modsdiv, #winbtns, .contentMenu { -webkit-app-region: no-drag; } diff --git a/src/app/main.js b/src/app/main.js index 19f6c9e..169f86f 100644 --- a/src/app/main.js +++ b/src/app/main.js @@ -3,6 +3,7 @@ const path = require("path"); const { ipcRenderer, shell } = require("electron"); const lang = require("../lang"); +var modsobj = {}; let shouldInstallNorthstar = false; // Base settings @@ -66,6 +67,15 @@ function log(msg) { // updating/installing Northstar. function setButtons(state) { playNsBtn.disabled = !state; + + let disablearray = (array) => { + for (let i = 0; i < array.length; i++) { + array[i].disabled = !state; + } + } + + disablearray(document.querySelectorAll("#nsMods .buttons.modbtns button")) + disablearray(document.querySelectorAll("#browser #browserEntries .text button")) } // Frontend part of updating Northstar @@ -148,9 +158,16 @@ function selected(all) { // Tells the main process to install a mod function installmod() { + setButtons(false); ipcRenderer.send("installmod") } +// Tells the main process to install a mod from a URL +function installFromURL(url) { + setButtons(false); + ipcRenderer.send("installfromurl", url) +} + // Frontend part of settings a new game path ipcRenderer.on("newpath", (event, newpath) => { settings.gamepath = newpath; @@ -163,6 +180,7 @@ ipcRenderer.on("alert", (event, msg) => {alert(msg)}) // Updates the installed mods ipcRenderer.on("mods", (event, mods) => { + modsobj = mods; if (! mods) {return} modcount.innerHTML = `${lang("gui.mods.count")} ${mods.all.length}`; diff --git a/src/index.js b/src/index.js index c8bfc53..a06cf69 100644 --- a/src/index.js +++ b/src/index.js @@ -43,9 +43,13 @@ function start() { ipcMain.on("exit", () => {process.exit(0)}) ipcMain.on("minimize", () => {win.minimize()}) + ipcMain.on("installfromurl", (event, url) => {utils.mods.installFromURL(url)}) ipcMain.on("winLog", (event, ...args) => {win.webContents.send("log", ...args)}); ipcMain.on("winAlert", (event, ...args) => {win.webContents.send("alert", ...args)}); ipcMain.on("ns-update-event", (event) => win.webContents.send("ns-update-event", event)); + ipcMain.on("failedmod", (event, modname) => {win.webContents.send("failedmod", modname)}); + ipcMain.on("removedmod", (event, modname) => {win.webContents.send("removedmod", modname)}); + ipcMain.on("installedmod", (event, modname) => {win.webContents.send("installedmod", modname)}); ipcMain.on("guigetmods", (event, ...args) => {win.webContents.send("mods", utils.mods.list())}); win.webContents.on("dom-ready", () => { diff --git a/src/lang/en.json b/src/lang/en.json index fe9b0b0..a9eb47f 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -49,6 +49,7 @@ "gui.mods.count": "Mods Installed:", "gui.mods.disabledtag": "Disabled", "gui.mods.install": "Install Mod", + "gui.mods.find": "Find Mods", "gui.mods.toggle": "Toggle Mod", "gui.mods.toggleall": "Toggle All", "gui.mods.remove": "Remove Mod", @@ -62,6 +63,15 @@ "gui.mods.installing": "Installing mod...", "gui.mods.installedmod": "Installed mod!", + "gui.browser.info": "Info", + "gui.browser.madeby": "by", + "gui.browser.search": "Search...", + "gui.browser.update": "Update", + "gui.browser.install": "Install", + "gui.browser.reinstall": "Re-Install", + "gui.browser.loading": "Loading mods...", + "gui.browser.endoflist": "Maximum packages has been loaded.<br>Use the search for finding other packages!", + "gui.update.downloading": "Downloading...", "gui.update.extracting": "Extracting update...", "gui.update.finished": "Done! Ready to play!", diff --git a/src/lang/es.json b/src/lang/es.json index c6e282d..9eac2b0 100644 --- a/src/lang/es.json +++ b/src/lang/es.json @@ -1,102 +1,112 @@ -{
- "cli.help.help": "muestra este mensaje de ayuda",
- "cli.help.debug": "habre las herramientas de desarrollador/depuración ",
- "cli.help.version": "muestra la información de la versión",
- "cli.help.cli": "obliga la linea de comandos a habilitarse",
- "cli.help.update": "actualiza Northstar desde la ruta de juego establecida",
- "cli.help.setpath": "establece la ruta del juego",
- "cli.help.updatevp": "actualiza Viper si es soportado",
- "cli.help.installmod": "instala una modificación, desde una carpeta o zip",
- "cli.help.removemod": "remueve una modificación",
- "cli.help.togglemod": "alterna el estado de la modificación",
-
- "cli.setpath.noarg": "No se ha proporcionado ningún argumento para --setpath",
-
- "cli.update.current": "Versión actual:",
- "cli.update.downloading": "Descargando...",
- "cli.update.checking": "Buscando actualizaciones...",
- "cli.update.downloaddone": "¡Descarga completa! Extrayendo...",
- "cli.update.finished": "Instalación/Actualización completada!",
- "cli.update.uptodate": "La ultima versión (%s) ya está instalada, omitiendo actualización.",
- "cli.update.uptodate.short": "Está actualizado",
-
- "cli.autoupdates.checking": "Buscando actualizaciones de Northstar...",
- "cli.autoupdates.available": "¡Actualización de Northsar disponible!",
- "cli.autoupdates.gamerunning": "El juego se está ejecutando, no se puede actualizar Northstar",
- "cli.autoupdates.updatingns": "Lanzando proceso de actualización...",
- "cli.autoupdates.noupdate": "No hay actualizaciones de Northstar disponibles.",
-
- "cli.launch.linuxerror": "La ejecución del juego en Linux aun no está implementada",
-
- "cli.mods.failed": "¡Fallo al instalar el mod!",
- "cli.mods.removed": "¡Modificación removida exitosamente!",
- "cli.mods.toggled": "¡El estado de la modificación ha cambiado exitosamente!",
- "cli.mods.installed": "¡Modificiación instalada exitosamente!",
- "cli.mods.cantfind": "¡No se encuentra una modificación con ese nombre!",
- "cli.mods.notamod": "La carpeta o el archivo seleccionado no es una modificación",
- "cli.mods.toggledall": "¡Estado de todas las modiciaciones ha sido cambiado exitosamente!",
- "cli.mods.improperjson": "%s's mod.json tiene errores de formato",
-
- "gui.welcome": "Bienvenido a Viper!",
- "gui.versions.viper": "Versión de Viper",
- "gui.versions.northstar": "Versión de Northstar",
- "gui.exit": "Salir",
- "gui.update": "Actualizar",
- "gui.setpath": "Cambiar la ruta del juego",
-
- "gui.update.check": "Buscar actualizaciones",
- "gui.mods": "Modificaciones (Mods)",
- "gui.mods.count": "Modificaciones instaladas:",
- "gui.mods.disabledtag": "Deshabilitado",
- "gui.mods.install": "Instalar modificación",
- "gui.mods.toggle": "Alternar modificación",
- "gui.mods.toggleall": "Alternar todo",
- "gui.mods.remove": "Remover modificación",
- "gui.mods.removeall": "Remover todo",
- "gui.mods.nothingselected": "No has seleccionado una modificación.",
- "gui.mods.toggleall.confirm": "Alternar todo podría deshabilitar las modificaciones requeridas para que Northstar funcione. ¿Está seguro?",
- "gui.mods.removeall.confirm": "Eliminar todas las modificaciones generalmente requerirá que reinstales Northstar. ¿Está seguro?",
- "gui.mods.required.confirm": "Ha seleccionado un mod esencial, es posible que Northstar no funcione sin él. ¿Está seguro?",
- "gui.mods.notamod": "¡No es una modificación!",
- "gui.mods.extracting": "Extrayendo modificación...",
- "gui.mods.installing": "Instalando modificación...",
- "gui.mods.installedmod": "¡Modificación instalada!",
-
- "gui.update.downloading": "Descargando...",
- "gui.update.extracting": "Extrayendo actualización...",
- "gui.update.finished": "¡Hecho! ¡Está listo para jugar!",
- "gui.update.uptodate": "¡Ya está actualizado!",
- "gui.update.available": "Hay una actualización disponible para Viper, ¿desea reiniciar y aplicarla?",
-
- "gui.nsupdate.gaming.title": "¡Actualización de Northstar disponible!",
- "gui.nsupdate.gaming.body": "Una actualización de northstar está disponible.\nPuedes forzar su instalación despues de cerrar el juego.",
-
- "gui.launch": "Ejecutar",
- "gui.launchvanilla": "Vanilla",
- "gui.launchnorthstar": "Northstar",
- "gui.installnorthstar": "Instalar",
-
- "gui.selectpath": "Por favor, ¡elija la ruta del juego!",
- "gui.gamepath.must": "La ruta del juego debe establecerse para ejecutar Viper.",
- "gui.gamepath.wrong": "Esta carpeta no es una ruta válida para el juego.",
-
- "viper.menu.main": "Viper",
- "viper.menu.release": "Notas de la versión",
- "viper.menu.info": "Extras",
- "viper.menu.info.links": "Links",
- "viper.menu.info.credits": "Creditos",
-
- "viper.info.discord": "Unete al Discord:",
- "viper.info.issues": "Reporta problemas de Viper:",
-
- "ns.menu.main": "Northstar Launcher",
- "ns.menu.mods": "Modificiaciones",
- "ns.menu.release": "Notas de actualización",
-
- "general.mods.enabled": "Modificaciones habilitadas:",
- "general.mods.disabled": "Modificaciones deshabilitadas:",
- "general.mods.installed": "Modificiaciones intaladas:",
- "general.missingpath": "¡La ruta del jueno no se ha podido encontrar automaticamente! ¡Por favor, elige la ruta manualmente!",
- "general.notinstalled": "¡Northstar no se ha instalado!",
- "general.launching": "Ejecutando"
-}
+{ + "cli.help.help": "muestra este mensaje de ayuda", + "cli.help.debug": "habre las herramientas de desarrollador/depuración ", + "cli.help.version": "muestra la información de la versión", + "cli.help.cli": "obliga la linea de comandos a habilitarse", + "cli.help.update": "actualiza Northstar desde la ruta de juego establecida", + "cli.help.setpath": "establece la ruta del juego", + "cli.help.updatevp": "actualiza Viper si es soportado", + "cli.help.installmod": "instala una modificación, desde una carpeta o zip", + "cli.help.removemod": "remueve una modificación", + "cli.help.togglemod": "alterna el estado de la modificación", + + "cli.setpath.noarg": "No se ha proporcionado ningún argumento para --setpath", + + "cli.update.current": "Versión actual:", + "cli.update.downloading": "Descargando...", + "cli.update.checking": "Buscando actualizaciones...", + "cli.update.downloaddone": "¡Descarga completa! Extrayendo...", + "cli.update.finished": "Instalación/Actualización completada!", + "cli.update.uptodate": "La ultima versión (%s) ya está instalada, omitiendo actualización.", + "cli.update.uptodate.short": "Está actualizado", + + "cli.autoupdates.checking": "Buscando actualizaciones de Northstar...", + "cli.autoupdates.available": "¡Actualización de Northsar disponible!", + "cli.autoupdates.gamerunning": "El juego se está ejecutando, no se puede actualizar Northstar", + "cli.autoupdates.updatingns": "Lanzando proceso de actualización...", + "cli.autoupdates.noupdate": "No hay actualizaciones de Northstar disponibles.", + + "cli.launch.linuxerror": "La ejecución del juego en Linux aun no está implementada", + + "cli.mods.failed": "¡Fallo al instalar el mod!", + "cli.mods.removed": "¡Modificación removida exitosamente!", + "cli.mods.toggled": "¡El estado de la modificación ha cambiado exitosamente!", + "cli.mods.installed": "¡Modificiación instalada exitosamente!", + "cli.mods.cantfind": "¡No se encuentra una modificación con ese nombre!", + "cli.mods.notamod": "La carpeta o el archivo seleccionado no es una modificación", + "cli.mods.toggledall": "¡Estado de todas las modiciaciones ha sido cambiado exitosamente!", + "cli.mods.improperjson": "%s's mod.json tiene errores de formato", + + "gui.welcome": "Bienvenido a Viper!", + "gui.versions.viper": "Versión de Viper", + "gui.versions.northstar": "Versión de Northstar", + "gui.exit": "Salir", + "gui.update": "Actualizar", + "gui.setpath": "Cambiar la ruta del juego", + + "gui.update.check": "Buscar actualizaciones", + "gui.mods": "Modificaciones (Mods)", + "gui.mods.count": "Modificaciones instaladas:", + "gui.mods.disabledtag": "Deshabilitado", + "gui.mods.install": "Instalar modificación", + "gui.mods.find": "Encontrar modificaciones", + "gui.mods.toggle": "Alternar modificación", + "gui.mods.toggleall": "Alternar todo", + "gui.mods.remove": "Remover modificación", + "gui.mods.removeall": "Remover todo", + "gui.mods.nothingselected": "No has seleccionado una modificación.", + "gui.mods.toggleall.confirm": "Alternar todo podría deshabilitar las modificaciones requeridas para que Northstar funcione. ¿Está seguro?", + "gui.mods.removeall.confirm": "Eliminar todas las modificaciones generalmente requerirá que reinstales Northstar. ¿Está seguro?", + "gui.mods.required.confirm": "Ha seleccionado un mod esencial, es posible que Northstar no funcione sin él. ¿Está seguro?", + "gui.mods.notamod": "¡No es una modificación!", + "gui.mods.extracting": "Extrayendo modificación...", + "gui.mods.installing": "Instalando modificación...", + "gui.mods.installedmod": "¡Modificación instalada!", + + "gui.browser.info": "Información", + "gui.browser.madeby": "por", + "gui.browser.search": "Buscar...", + "gui.browser.update": "Actualizar", + "gui.browser.install": "Instalar", + "gui.browser.reinstall": "Re-Instalar", + "gui.browser.loading": "Cargando modificaciones...", + "gui.browser.endoflist": "Se ha cargado el máximo de paquetes.<br>¡Usa la búsqueda para encontrar otros paquetes!", + + "gui.update.downloading": "Descargando...", + "gui.update.extracting": "Extrayendo actualización...", + "gui.update.finished": "¡Hecho! ¡Está listo para jugar!", + "gui.update.uptodate": "¡Ya está actualizado!", + "gui.update.available": "Hay una actualización disponible para Viper, ¿desea reiniciar y aplicarla?", + + "gui.nsupdate.gaming.title": "¡Actualización de Northstar disponible!", + "gui.nsupdate.gaming.body": "Una actualización de northstar está disponible.\nPuedes forzar su instalación despues de cerrar el juego.", + + "gui.launch": "Ejecutar", + "gui.launchvanilla": "Vainilla", + "gui.launchnorthstar": "Northstar", + "gui.installnorthstar": "Instalar", + + "gui.selectpath": "Por favor, ¡elija la ruta del juego!", + "gui.gamepath.must": "La ruta del juego debe establecerse para ejecutar Viper.", + "gui.gamepath.wrong": "Esta carpeta no es una ruta válida para el juego.", + + "viper.menu.main": "Viper", + "viper.menu.release": "Notas de la versión", + "viper.menu.info": "Extras", + "viper.menu.info.links": "Links", + "viper.menu.info.credits": "Creditos", + + "viper.info.discord": "Unete al Discord:", + "viper.info.issues": "Reporta problemas de Viper:", + + "ns.menu.main": "Northstar Launcher", + "ns.menu.mods": "Modificiaciones", + "ns.menu.release": "Notas de actualización", + + "general.mods.enabled": "Modificaciones habilitadas:", + "general.mods.disabled": "Modificaciones deshabilitadas:", + "general.mods.installed": "Modificiaciones intaladas:", + "general.missingpath": "¡La ruta del jueno no se ha podido encontrar automaticamente! ¡Por favor, elige la ruta manualmente!", + "general.notinstalled": "¡Northstar no se ha instalado!", + "general.launching": "Ejecutando" +}
\ No newline at end of file diff --git a/src/lang/fr.json b/src/lang/fr.json index 2fbc89a..4e6103a 100644 --- a/src/lang/fr.json +++ b/src/lang/fr.json @@ -49,6 +49,7 @@ "gui.mods.count": "Mods installés :", "gui.mods.disabledtag": "Désactivé", "gui.mods.install": "Installer le mod", + "gui.mods.find": "Chercher des mods", "gui.mods.toggle": "Activer/désactiver le mod", "gui.mods.toggleall": "Activer/désactiver tous les mods", "gui.mods.remove": "Supprimer le mod", @@ -62,6 +63,15 @@ "gui.mods.installing": "Installation du mod...", "gui.mods.installedmod": "Mod installé !", + "gui.browser.info": "Info", + "gui.browser.madeby": "par", + "gui.browser.search": "Rechercher", + "gui.browser.update": "Mise à jour", + "gui.browser.install": "Installer", + "gui.browser.reinstall": "Réinstaller", + "gui.browser.loading": "Chargement des mods...", + "gui.browser.endoflist": "Fin de la liste de mods.<br>Utilisez la barre de recherche pour en trouver davantage !", + "gui.update.downloading": "Téléchargement de la mise à jour...", "gui.update.extracting": "Extraction des fichiers...", "gui.update.finished": "Terminé, vous pouvez jouer !", diff --git a/src/utils.js b/src/utils.js index 0507921..1887dd1 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,6 +1,6 @@ const path = require("path"); const fs = require("fs-extra"); -const copy = require("copy-dir"); +const copy = require("recursive-copy"); const { app, dialog, ipcMain, Notification } = require("electron"); const Emitter = require("events"); @@ -374,9 +374,14 @@ const mods = { try { mods.push({...require(path.join(modpath, file, "mod.json")), FolderName: file, Disabled: false}) }catch(err) { - console.log("error: " + lang("cli.mods.improperjson"), file) + if (cli.hasArgs()) {console.log("error: " + lang("cli.mods.improperjson"), file)} mods.push({Name: file, FolderName: file, Version: "unknown", Disabled: false}) } + + let manifest = path.join(modpath, file, "manifest.json"); + if (fs.existsSync(manifest)) { + mods[mods.length - 1].ManifestName = require(manifest).name; + } } } }) @@ -393,10 +398,15 @@ const mods = { try { disabled.push({...require(path.join(disabledPath, file, "mod.json")), FolderName: file, Disabled: true}) }catch(err) { - console.log("error: " + lang("cli.mods.improperjson"), file) + if (cli.hasArgs()) {console.log("error: " + lang("cli.mods.improperjson"), file)} disabled.push({Name: file, FolderName: file, Version: "unknown", Disabled: true}) } } + + let manifest = path.join(modpath, file, "manifest.json"); + if (fs.existsSync(manifest)) { + mods[mods.length - 1].ManifestName = require(manifest).name; + } } }) @@ -439,8 +449,8 @@ const mods = { // Either a zip or folder is supported, we'll also try to search // inside the zip or folder to see if buried in another folder or // not, as sometimes that's the case. - install: (mod) => { - let modpath = path.join(settings.gamepath, "R2Northstar/mods"); + install: (mod, destname, manifestfile) => { + let modname = mod.replace(/^.*(\\|\/|\:)/, ""); if (getNSVersion() == "unknown") { winLog(lang("general.notinstalled")) @@ -461,6 +471,16 @@ const mods = { cli.exit(); winLog(lang("gui.mods.installedmod")) + + if (modname == "mods") { + let manifest = path.join(app.getPath("userData"), "Archives/manifest.json") + + if (fs.existsSync(manifest)) { + modname = require(manifest).name; + } + } + + ipcMain.emit("installedmod", "", modname); ipcMain.emit("guigetmods"); return true; } @@ -469,14 +489,17 @@ const mods = { if (fs.statSync(mod).isDirectory()) { winLog(lang("gui.mods.installing")) + files = fs.readdirSync(mod); if (fs.existsSync(path.join(mod, "mod.json")) && fs.statSync(path.join(mod, "mod.json")).isFile()) { - copy.sync(mod, path.join(modpath, mod.replace(/^.*(\\|\/|\:)/, "")), { - mode: true, - cover: true, - utimes: true, - }); + if (fs.existsSync(path.join(modpath, modname))) { + fs.rmSync(path.join(modpath, modname), {recursive: true}); + } + let copydest = path.join(modpath, modname); + if (typeof destname == "string") {copydest = path.join(modpath, destname)} + copy(mod, copydest) + copy(manifestfile, path.join(copydest, "manifest.json")) return installed(); } else { @@ -487,6 +510,7 @@ const mods = { if (fs.existsSync(path.join(mod, files[i], "mod.json")) && fs.statSync(path.join(mod, files[i], "mod.json")).isFile()) { + console.log(mods.install(path.join(mod, files[i]))) if (mods.install(path.join(mod, files[i]))) {return true}; } } @@ -500,21 +524,84 @@ const mods = { let cache = path.join(app.getPath("userData"), "Archives"); if (fs.existsSync(cache)) { fs.rmSync(cache, {recursive: true}); - fs.mkdirSync(cache); + fs.mkdirSync(path.join(cache, "mods"), {recursive: true}); } else { - fs.mkdirSync(cache); + fs.mkdirSync(path.join(cache, "mods"), {recursive: true}); } try { fs.createReadStream(mod).pipe(unzip.Extract({path: cache})) .on("finish", () => { - if (mods.install(cache)) { - installed(); - } else {return notamod()} + setTimeout(() => { + let manifest = path.join(cache, "manifest.json"); + if (fs.existsSync(manifest)) { + files = fs.readdirSync(path.join(cache, "mods")); + + if (fs.existsSync(path.join(cache, "mods/mod.json"))) { + if (mods.install(path.join(cache, "mods"), require(manifest).name, manifest)) { + return true; + } + } else { + for (let i = 0; i < files.length; i++) { + let mod = path.join(cache, "mods", files[i]); + if (fs.statSync(mod).isDirectory()) { + setTimeout(() => { + if (mods.install(mod, false, manifest)) {return true}; + }, 1000) + } + } + } + + return notamod(); + } + + if (mods.install(cache)) { + installed(); + } else {return notamod()} + }, 1000) }); }catch(err) {return notamod()} } }, + + // Installs mods from URL's + // + // This'll simply download the file that the URL points to and then + // install it with mods.install() + installFromURL: (url) => { + https.get(url, (res) => { + let tmp = path.join(app.getPath("cache"), "vipertmp"); + let modlocation = path.join(tmp, "/mod.zip"); + + if (fs.existsSync(tmp)) { + if (! fs.statSync(tmp).isDirectory()) { + fs.rmSync(tmp) + } + } else { + fs.mkdirSync(tmp) + if (fs.existsSync(modlocation)) { + fs.rmSync(modlocation) + } + } + + let stream = fs.createWriteStream(modlocation); + res.pipe(stream); + + // let received = 0; + // // Progress messages, we should probably switch this to + // // percentage instead of how much is downloaded. + // res.on("data", (chunk) => { + // received += chunk.length; + // ipcMain.emit("ns-update-event", lang("gui.update.downloading") + " " + (received / 1024 / 1024).toFixed(1) + "mb"); + // }) + + stream.on("finish", () => { + stream.close(); + mods.install(modlocation) + }) + }) + }, + // Removes mods // // Takes in the names of the mod then removes it, no confirmation, @@ -556,10 +643,19 @@ const mods = { } if (fs.statSync(modPath).isDirectory()) { + let manifestname = null; + if (fs.existsSync(path.join(modPath, "manifest.json"))) { + manifestname = require(path.join(modPath, "manifest.json")).name; + } + fs.rmSync(modPath, {recursive: true}); console.log(lang("cli.mods.removed")); cli.exit(); ipcMain.emit("guigetmods"); + ipcMain.emit("removedmod", "", { + name: mod.replace(/^.*(\\|\/|\:)/, ""), + manifestname: manifestname + }); } else { cli.exit(1); } @@ -621,6 +717,10 @@ const mods = { } }; +setInterval(() => { + ipcMain.emit("guigetmods"); +}, 1500) + module.exports = { mods, lang, |