diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..7a3993c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Main Process", + "type": "node", + "request": "launch", + "cwd": "${workspaceFolder}", + "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron", + "windows": { + "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd" + }, + "args" : ["."], + "outputCapture": "std" + } + ] +} \ No newline at end of file diff --git a/app.js b/app.js index 4563aaa..7e9296d 100644 --- a/app.js +++ b/app.js @@ -195,11 +195,19 @@ const run = () => { } else linuxWMCtrlFound = true; } else { const osuFolder = await config.get("osuPath"); + console.log(osuFolder, !osuFolder || osuFolder == ""); if (!osuFolder || osuFolder == "") { const foundFolder = await osuUtil.findOsuInstallation(); + if (foundFolder && osuUtil.isValidOsuFolder(foundFolder)) { + mainWindow.webContents.send('alert_message', foundFolder); + } console.log("osu! Installation located at: ", foundFolder); } } + }); + ipcMain.on("alert_response", async (event, path) => { + console.log("yes"); + await config.set("osuPath", path); }) app.on('activate', function () { if (BrowserWindow.getAllWindows().length === 0) mainWindow = createWindow(); @@ -208,6 +216,8 @@ const run = () => { app.quit() }) ipcMain.handle('launch', async () => { + const osuFolder = await config.get("osuPath"); + await osuUtil.updateOsuCfg(path.join(osuFolder, "osu!.cfg")); const osuConfig = await osuUtil.getLatestConfig(tempOsuPath); const username = await config.get('username'); const password = await config.get('password'); @@ -221,13 +231,17 @@ const run = () => { await osuUtil.setConfigValue(osuConfig.path, "Username", ""); await osuUtil.setConfigValue(osuConfig.path, "Password", ""); } + await osuUtil.replaceUI(osuFolder, true); rpc.updateState("Launching osu!..."); isIngame = true; if (mainWindow.isVisible()) mainWindow.hide(); const result = await osuUtil.startOsuWithDevServer(tempOsuPath, "ez-pp.farm", async () => { - isIngame = false; if (!mainWindow.isVisible()) mainWindow.show(); - await doUpdateCheck(mainWindow); + setTimeout(async () => { + isIngame = false; + await osuUtil.replaceUI(osuFolder, false); + await doUpdateCheck(mainWindow); + }, 2000); }); return result; }) @@ -344,6 +358,7 @@ async function tryLogin(window) { async function doUpdateCheck(window) { const osuPath = await config.get("osuPath"); + console.log("osuPath:", osuPath); if (!osuPath || osuPath.trim == "") { window.webContents.send('status_update', { type: "missing-folder" diff --git a/assets/launcher.css b/assets/launcher.css index 1051e8b..0e6b0a8 100644 --- a/assets/launcher.css +++ b/assets/launcher.css @@ -1,53 +1,66 @@ @import url('https://fonts.googleapis.com/css2?family=Exo+2:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); :root { - --main-accent: 335deg; - --main-bg: 230deg; + --main-accent: 335deg; + --main-bg: 230deg; } * { - font-family: 'Exo 2', 'Roboto' !important; + font-family: 'Exo 2', 'Roboto' !important; } body { - background-color: hsl(var(--main-bg), 24%, 19%); + background-color: hsl(var(--main-bg), 24%, 19%); +} + +p.text-white { + margin: .5rem 0; + color: white; +} + +.quotetext { + color: white; + background-color: #727272; + border-radius: .35rem; + font-size: .95rem; + padding: .25rem .5rem; } .sections { - display: flex; - flex-flow: column; + display: flex; + flex-flow: column; } .app-name { - font-size: 40px; - font-weight: 500; - text-shadow: 0 0 15px rgba(255, 255, 255, 0.37); + font-size: 40px; + font-weight: 500; + text-shadow: 0 0 15px rgba(255, 255, 255, 0.37); } .launcher-window { - width: 100%; + width: 100%; } .launch-button-section { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } .launch-button-section button { - margin-bottom: 10px; + margin-bottom: 10px; } .loading-section, .login-section { - margin-top: 35px; - display: flex; - flex-flow: column; - justify-content: center; - align-items: center; + margin-top: 35px; + display: flex; + flex-flow: column; + justify-content: center; + align-items: center; } .loading-section { - margin-top: 0; + margin-top: 0; } .loading-section {} @@ -55,268 +68,268 @@ body { .loading-indicator {} .loading-indicator-text { - display: flex; - flex-flow: column; - justify-content: center; - align-items: center; + display: flex; + flex-flow: column; + justify-content: center; + align-items: center; } .folder-section { - margin-top: 50px; - display: flex; - flex-flow: column; - justify-content: center; - align-items: center; - color: #aaa; - font-weight: 500; + margin-top: 50px; + display: flex; + flex-flow: column; + justify-content: center; + align-items: center; + color: #aaa; + font-weight: 500; } .folder-action { - font-style: italic; - cursor: pointer; - width: fit-content; - line-height: .9; + font-style: italic; + cursor: pointer; + width: fit-content; + line-height: .9; } .launch-section { - width: 100%; - display: flex; - flex-flow: column; - align-items: center; - justify-content: center; + width: 100%; + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; } .btn.btn-launch { - margin-top: 10px; - width: 300px; - font-size: 23px; - text-transform: none; + margin-top: 10px; + width: 300px; + font-size: 23px; + text-transform: none; } .account-section { - display: flex; - align-items: center; - gap: 20px; + display: flex; + align-items: center; + gap: 20px; } .server-logo img { - user-select: none; - pointer-events: none; + user-select: none; + pointer-events: none; } .user-info { - text-align: start; - display: flex; - flex-flow: column; - justify-content: center; - align-content: center; - overflow: hidden; - text-overflow: ellipsis; + text-align: start; + display: flex; + flex-flow: column; + justify-content: center; + align-content: center; + overflow: hidden; + text-overflow: ellipsis; } .user-info .welcome-text { - font-size: 31px; - letter-spacing: .02rem; - height: 30px; - line-height: .8; - text-shadow: 0 0 10px rgba(0, 0, 0, 0.349); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + font-size: 31px; + letter-spacing: .02rem; + height: 30px; + line-height: .8; + text-shadow: 0 0 10px rgba(0, 0, 0, 0.349); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .user-info .account-action { - font-size: 21px; - letter-spacing: .05rem; - font-weight: 500; - font-style: italic; - color: #aaa; - text-shadow: 0 0 10px rgba(0, 0, 0, 0.349); - cursor: pointer; - line-height: 1.2; - width: fit-content; + font-size: 21px; + letter-spacing: .05rem; + font-weight: 500; + font-style: italic; + color: #aaa; + text-shadow: 0 0 10px rgba(0, 0, 0, 0.349); + cursor: pointer; + line-height: 1.2; + width: fit-content; } .user-image { - border: 5px solid white; - border-radius: 0.4rem; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.349); - background-image: url(https://a.ez-pp.farm/0); - width: 100px; - height: 100px; - background-size: cover; - background-position: center; + border: 5px solid white; + border-radius: 0.4rem; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.349); + background-image: url(https://a.ez-pp.farm/0); + width: 100px; + height: 100px; + background-size: cover; + background-position: center; } .form-outline .form-control:focus~.form-notch .form-notch-leading { - border-color: hsl(var(--main-accent), 93%, 48%); - box-shadow: -1px 0 0 0 hsl(var(--main-accent), 93%, 48%), 0 1px 0 0 hsl(var(--main-accent), 93%, 48%), 0 -1px 0 0 hsl(var(--main-accent), 93%, 48%); + border-color: hsl(var(--main-accent), 93%, 48%); + box-shadow: -1px 0 0 0 hsl(var(--main-accent), 93%, 48%), 0 1px 0 0 hsl(var(--main-accent), 93%, 48%), 0 -1px 0 0 hsl(var(--main-accent), 93%, 48%); } .form-outline .form-control:focus~.form-notch .form-notch-middle { - border-color: hsl(var(--main-accent), 93%, 48%); - box-shadow: 0 1px 0 0 hsl(var(--main-accent), 93%, 48%); - border-top: 1px solid transparent; + border-color: hsl(var(--main-accent), 93%, 48%); + box-shadow: 0 1px 0 0 hsl(var(--main-accent), 93%, 48%); + border-top: 1px solid transparent; } .form-outline .form-control:focus~.form-notch .form-notch-trailing { - border-color: hsl(var(--main-accent), 93%, 48%); - box-shadow: 1px 0 0 0 hsl(var(--main-accent), 93%, 48%), 0 -1px 0 0 hsl(var(--main-accent), 93%, 48%), 0 1px 0 0 hsl(var(--main-accent), 93%, 48%); + border-color: hsl(var(--main-accent), 93%, 48%); + box-shadow: 1px 0 0 0 hsl(var(--main-accent), 93%, 48%), 0 -1px 0 0 hsl(var(--main-accent), 93%, 48%), 0 1px 0 0 hsl(var(--main-accent), 93%, 48%); } .form-outline .form-control:focus~.form-label { - color: hsl(var(--main-accent), 93%, 48%); + color: hsl(var(--main-accent), 93%, 48%); } .btn-accent, .btn-accent:active { - background: hsl(var(--main-accent), 93%, 48%); - color: #fff; + background: hsl(var(--main-accent), 93%, 48%); + color: #fff; } .btn-accent:hover { - background: hsl(var(--main-accent), 93%, 42%); - color: #fff ; + background: hsl(var(--main-accent), 93%, 42%); + color: #fff; } .btn-grey, .btn-grey:active { - background: #727272; - color: #fff; + background: #727272; + color: #fff; } .btn-grey:hover { - background: #626262; - color: #fff; + background: #626262; + color: #fff; } .btn-grouped { - display: flex; - gap: 50px; + display: flex; + gap: 50px; } .clickable { - cursor: pointer; + cursor: pointer; } .loader { - position: relative; - margin: 0px auto; - width: 200px; - height: 200px; - transform: scale(0.5); + position: relative; + margin: 0px auto; + width: 200px; + height: 200px; + transform: scale(0.5); } .loader:before { - content: ''; - display: block; - padding-top: 100%; + content: ''; + display: block; + padding-top: 100%; } .circular-loader { - -webkit-animation: rotate 2s linear infinite; - animation: rotate 2s linear infinite; - height: 100%; - -webkit-transform-origin: center center; - -ms-transform-origin: center center; - transform-origin: center center; - width: 100%; - position: absolute; - top: 0; - left: 0; - margin: auto; + -webkit-animation: rotate 2s linear infinite; + animation: rotate 2s linear infinite; + height: 100%; + -webkit-transform-origin: center center; + -ms-transform-origin: center center; + transform-origin: center center; + width: 100%; + position: absolute; + top: 0; + left: 0; + margin: auto; } .loader-path { - stroke-dasharray: 150, 200; - stroke-dashoffset: -10; - -webkit-animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite; - animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite; - stroke-linecap: round; + stroke-dasharray: 150, 200; + stroke-dashoffset: -10; + -webkit-animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite; + animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite; + stroke-linecap: round; } @-webkit-keyframes rotate { - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } } @keyframes rotate { - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } } @-webkit-keyframes dash { - 0% { - stroke-dasharray: 1, 200; - stroke-dashoffset: 0; - } + 0% { + stroke-dasharray: 1, 200; + stroke-dashoffset: 0; + } - 50% { - stroke-dasharray: 89, 200; - stroke-dashoffset: -35; - } + 50% { + stroke-dasharray: 89, 200; + stroke-dashoffset: -35; + } - 100% { - stroke-dasharray: 89, 200; - stroke-dashoffset: -124; - } + 100% { + stroke-dasharray: 89, 200; + stroke-dashoffset: -124; + } } @keyframes dash { - 0% { - stroke-dasharray: 1, 200; - stroke-dashoffset: 0; - } + 0% { + stroke-dasharray: 1, 200; + stroke-dashoffset: 0; + } - 50% { - stroke-dasharray: 89, 200; - stroke-dashoffset: -35; - } + 50% { + stroke-dasharray: 89, 200; + stroke-dashoffset: -35; + } - 100% { - stroke-dasharray: 89, 200; - stroke-dashoffset: -124; - } + 100% { + stroke-dasharray: 89, 200; + stroke-dashoffset: -124; + } } @-webkit-keyframes color { - 0% { - stroke: #fff; - } + 0% { + stroke: #fff; + } - 40% { - stroke: #fff; - } + 40% { + stroke: #fff; + } - 66% { - stroke: #fff; - } + 66% { + stroke: #fff; + } - 80%, - 90% { - stroke: #fff; - } + 80%, + 90% { + stroke: #fff; + } } @keyframes color { - 0% { - stroke: #fff; - } + 0% { + stroke: #fff; + } - 40% { - stroke: #fff; - } + 40% { + stroke: #fff; + } - 66% { - stroke: #fff; - } + 66% { + stroke: #fff; + } - 80%, - 90% { - stroke: #fff; - } + 80%, + 90% { + stroke: #fff; + } } \ No newline at end of file diff --git a/osuUtil.js b/osuUtil.js index c28f21a..f73673a 100644 --- a/osuUtil.js +++ b/osuUtil.js @@ -8,189 +8,237 @@ const { EventEmitter } = require('events'); const { DownloaderHelper } = require('node-downloader-helper'); const checkUpdateURL = "https://osu.ppy.sh/web/check-updates.php?action=check&stream="; +const customUIDLLPath = ""; +const customUIDLLName = "ezpp!ui.dll"; const ignoredOsuEntities = [ - 'osu!auth.dll' + 'osu!auth.dll', ] const osuEntities = [ - 'avcodec-51.dll', - 'avformat-52.dll', - 'avutil-49.dll', - 'bass.dll', - 'bass_fx.dll', - 'collection.db', - 'd3dcompiler_47.dll', - 'Data', - 'Downloads', - 'libEGL.dll', - 'libGLESv2.dll', - 'Logs', - 'Microsoft.Ink.dll', - 'OpenTK.dll', - 'osu!.cfg', - 'osu!.db', - 'osu!.exe', - 'osu!auth.dll', - 'osu!gameplay.dll', - 'osu!seasonal.dll', - 'osu!ui.dll', - 'presence.db', - 'pthreadGC2.dll', - 'scores.db', - 'Skins', - 'Songs' + 'avcodec-51.dll', + 'avformat-52.dll', + 'avutil-49.dll', + 'bass.dll', + 'bass_fx.dll', + 'collection.db', + 'd3dcompiler_47.dll', + 'Data', + 'Downloads', + 'libEGL.dll', + 'libGLESv2.dll', + 'Logs', + 'Microsoft.Ink.dll', + 'OpenTK.dll', + 'osu!.cfg', + 'osu!.db', + 'osu!.exe', + 'osu!auth.dll', + 'osu!gameplay.dll', + 'osu!seasonal.dll', + 'osu!ui.dll', + 'presence.db', + 'pthreadGC2.dll', + 'scores.db', + 'Skins', + 'Songs' ] async function isValidOsuFolder(path) { - const allFiles = await fs.promises.readdir(path); - let matches = 0; - for (const file of allFiles) { - if (osuEntities.includes(file)) matches = matches + 1; - } - return Math.round((matches / osuEntities.length) * 100) >= 60; + const allFiles = await fs.promises.readdir(path); + let matches = 0; + for (const file of allFiles) { + if (osuEntities.includes(file)) matches = matches + 1; + } + return Math.round((matches / osuEntities.length) * 100) >= 60; } async function getLatestConfig(osuPath) { - const configFileInfo = { - name: "", - path: "", - get: async (key) => { - if (!configFileInfo.path) - return ""; - const fileStream = await fs.promises.readFile(configFileInfo.path, "utf-8"); - const lines = fileStream.split(/\r?\n/) - for (const line of lines) { - if (line.includes(' = ')) { - const argsPair = line.split(' = ', 2); - const keyname = argsPair[0] - const value = argsPair[1]; - if (keyname == key) { - return value; - } - } - } + const configFileInfo = { + name: "", + path: "", + get: async (key) => { + if (!configFileInfo.path) + return ""; + const fileStream = await fs.promises.readFile(configFileInfo.path, "utf-8"); + const lines = fileStream.split(/\r?\n/) + for (const line of lines) { + if (line.includes(' = ')) { + const argsPair = line.split(' = ', 2); + const keyname = argsPair[0] + const value = argsPair[1]; + if (keyname == key) { + return value; + } } + } } - const userOsuConfig = path.join(osuPath, `osu!.${process.env['USERNAME']}.cfg`) - if (fs.existsSync(userOsuConfig)) { - configFileInfo.name = `osu!.${process.env['USERNAME']}.cfg`; - configFileInfo.path = userOsuConfig; - } - return configFileInfo; + } + const userOsuConfig = path.join(osuPath, `osu!.${process.env['USERNAME']}.cfg`) + if (fs.existsSync(userOsuConfig)) { + configFileInfo.name = `osu!.${process.env['USERNAME']}.cfg`; + configFileInfo.path = userOsuConfig; + } + return configFileInfo; } async function getUpdateFiles(releaseStream) { - const releaseData = await axios.get(checkUpdateURL + releaseStream, {}); - return releaseData.data; + const releaseData = await axios.get(checkUpdateURL + releaseStream, {}); + return releaseData.data; } async function filesThatNeedUpdate(osuPath, updateFiles) { - const filesToDownload = []; - for (const updatedFile of updateFiles) { - const fileName = updatedFile.filename; - const fileHash = updatedFile.file_hash; - const fileURL = updatedFile.url_full; + const filesToDownload = []; + for (const updatedFile of updateFiles) { + const fileName = updatedFile.filename; + const fileHash = updatedFile.file_hash; + const fileURL = updatedFile.url_full; - if (ignoredOsuEntities.includes(fileName)) continue; + if (ignoredOsuEntities.includes(fileName)) continue; - const fileOnDisk = path.join(osuPath, fileName); - if (await fu.existsAsync(fileOnDisk)) { - const binaryFileContents = await fs.promises.readFile(fileOnDisk); - const existingFileMD5 = crypto.createHash("md5").update(binaryFileContents).digest("hex"); - if (existingFileMD5.toLowerCase() != fileHash.toLowerCase()) { - filesToDownload.push({ - fileName, - fileURL - }) - } - } else { - filesToDownload.push({ - fileName, - fileURL - }); - } + const fileOnDisk = path.join(osuPath, fileName); + if (await fu.existsAsync(fileOnDisk)) { + const binaryFileContents = await fs.promises.readFile(fileOnDisk); + const existingFileMD5 = crypto.createHash("md5").update(binaryFileContents).digest("hex"); + if (existingFileMD5.toLowerCase() != fileHash.toLowerCase()) { + filesToDownload.push({ + fileName, + fileURL + }) + } + } else { + filesToDownload.push({ + fileName, + fileURL + }); } - return filesToDownload; + } + return filesToDownload; } async function downloadUpdateFiles(osuPath, filesToUpdate) { - const eventEmitter = new EventEmitter(); - let completedIndex = 0; - filesToUpdate.forEach(async (fileToUpdate) => { - const filePath = path.join(osuPath, fileToUpdate.fileName); - console.log(filePath); - if (await fu.existsAsync(filePath)) - await fs.promises.rm(filePath); + const eventEmitter = new EventEmitter(); + let completedIndex = 0; + filesToUpdate.forEach(async (fileToUpdate) => { + const filePath = path.join(osuPath, fileToUpdate.fileName); + console.log(filePath); + if (await fu.existsAsync(filePath)) + await fs.promises.rm(filePath); - const fileDownload = new DownloaderHelper(fileToUpdate.fileURL, osuPath, { - fileName: fileToUpdate.fileName, - override: true, - }); - fileDownload.on('end', () => { - completedIndex = completedIndex + 1; - if (completedIndex >= filesToUpdate.length) - eventEmitter.emit('completed'); - }); - fileDownload.on('error', (err) => { - console.log(err); - eventEmitter.emit('error'); - }); - - fileDownload.start().catch(err => console.error(err)); + const fileDownload = new DownloaderHelper(fileToUpdate.fileURL, osuPath, { + fileName: fileToUpdate.fileName, + override: true, + }); + fileDownload.on('end', () => { + completedIndex = completedIndex + 1; + if (completedIndex >= filesToUpdate.length) + eventEmitter.emit('completed'); + }); + fileDownload.on('error', (err) => { + console.log(err); + eventEmitter.emit('error'); }); - return eventEmitter; + fileDownload.start().catch(err => console.error(err)); + }); + + return eventEmitter; } async function startWithDevServer(osuPath, serverDomain, onExit) { - const osuExe = path.join(osuPath, "osu!.exe"); - if (!await fu.existsAsync(osuExe)) return false; - switch (process.platform) { - case "linux": - executeUtil.runFile(osuPath, 'osu-stable', ["-devserver", serverDomain], onExit); - return true; - case "win32": - executeUtil.runFile(osuPath, osuExe, ["-devserver", serverDomain], onExit); - return true; - } - return false; + const osuExe = path.join(osuPath, "osu!.exe"); + if (!await fu.existsAsync(osuExe)) return false; + switch (process.platform) { + case "linux": + executeUtil.runFile(osuPath, 'osu-stable', ["-devserver", serverDomain], onExit); + return true; + case "win32": + executeUtil.runFile(osuPath, osuExe, ["-devserver", serverDomain], onExit); + return true; + } + return false; } async function setConfigValue(configPath, key, value) { - const configLines = new Array(); - const fileStream = await fs.promises.readFile(configPath, "utf-8"); - const lines = fileStream.split(/\r?\n/) - for (const line of lines) { - if (line.includes(' = ')) { - const argsPair = line.split(' = ', 2); - const keyname = argsPair[0].trim(); - if (key == keyname) { - configLines.push(`${keyname} = ${value}`); - } else { - configLines.push(line); - } - } else { - configLines.push(line); - } + const configLines = new Array(); + const fileStream = await fs.promises.readFile(configPath, "utf-8"); + const lines = fileStream.split(/\r?\n/) + for (const line of lines) { + if (line.includes(' = ')) { + const argsPair = line.split(' = ', 2); + const keyname = argsPair[0].trim(); + if (key == keyname) { + configLines.push(`${keyname} = ${value}`); + } else { + configLines.push(line); + } + } else { + configLines.push(line); } - await fs.promises.writeFile(configPath, configLines.join("\n"), 'utf-8'); + } + await fs.promises.writeFile(configPath, configLines.join("\n"), 'utf-8'); } -async function findOsuInstallation() { - const regedit = require('qiao-regedit'); - const osuLocationFromDefaultIcon = "HKLM\\SOFTWARE\\Classes\\osu\\DefaultIcon"; - const osuStruct = await regedit.listValuesSync(osuLocationFromDefaultIcon); - for (const line of osuStruct.split("\n")) { - if (line.includes("REG_SZ")) { - let value = (line.trim().split(" ")[2]); - value = value.substring(1, value.length - 3); - return value.trim(); - } +async function updateOsuCfg(cfgPath) { + const osuFolder = path.dirname(cfgPath); + const fileStream = await fs.promises.readFile(cfgPath, "utf-8"); + const lines = fileStream.split(/\r?\n/); + const newLines = []; + for (const line of lines) { + if (line.includes(' = ')) { + const argsPair = line.split(' = ', 2); + const keyname = argsPair[0] + const value = argsPair[1]; + + if (keyname.startsWith("h_")) { + const filename = keyname.substring(2, keyname.length); + const filepath = path.join(osuFolder, filename); + if (!fs.existsSync(filepath)) continue; + const binaryFileContents = await fs.promises.readFile(filepath); + const existingFileMD5 = crypto.createHash("md5").update(binaryFileContents).digest("hex"); + if (value == existingFileMD5) newLines.push(line) + else newLines.push(`${keyname} = ${existingFileMD5}`); + } else { + newLines.push(line); + } } - return undefined; + } + await fs.promises.writeFile(cfgPath, newLines.join("\n"), 'utf-8'); +} + +async function findOsuInstallation() { + const regedit = require('qiao-regedit'); + + const osuLocationFromDefaultIcon = "HKLM\\SOFTWARE\\Classes\\osu\\DefaultIcon"; + const osuStruct = await regedit.listValuesSync(osuLocationFromDefaultIcon); + for (const line of osuStruct.split("\n")) { + if (line.includes("REG_SZ")) { + let value = (line.trim().split(" ")[2]); + value = value.substring(1, value.length - 3); + return path.dirname(value.trim()); + } + } + return undefined; +} + +async function replaceUI(folder, isStart) { + const ezppUIFile = path.join(folder, customUIDLLName); + const osuUIFile = path.join(folder, "osu!ui.dll"); + const osuUIFileBackup = path.join(folder, "osu!ui.dll.bak"); + if (isStart) { + if (fs.existsSync(osuUIFileBackup)) await fs.promises.unlink(osuUIFileBackup); + await fs.promises.rename(osuUIFile, osuUIFileBackup); + await new Promise((res) => setTimeout(res, 1000)); + await fs.promises.rename(ezppUIFile, osuUIFile); + } else { + if (!fs.existsSync(osuUIFileBackup)) return; + await fs.promises.rename(osuUIFile, ezppUIFile); + await new Promise((res) => setTimeout(res, 1000)); + await fs.promises.rename(osuUIFileBackup, osuUIFile); + } + } module.exports = { - isValidOsuFolder, getLatestConfig, getUpdateFiles, filesThatNeedUpdate, - downloadUpdateFiles, startOsuWithDevServer: startWithDevServer, setConfigValue, - findOsuInstallation + isValidOsuFolder, getLatestConfig, getUpdateFiles, filesThatNeedUpdate, + downloadUpdateFiles, startOsuWithDevServer: startWithDevServer, setConfigValue, + findOsuInstallation, replaceUI, updateOsuCfg } \ No newline at end of file diff --git a/preload/preload.js b/preload/preload.js index 337335a..f7f939d 100644 --- a/preload/preload.js +++ b/preload/preload.js @@ -188,6 +188,28 @@ window.addEventListener('DOMContentLoaded', () => { } }) + ipcRenderer.on('alert_message', async (event, path) => { + const res = await Swal.fire({ + title: 'Hey!', + html: `

Detected a osu! installation at

${path}

Is this correct?

`, + icon: 'info', + showCancelButton: true, + confirmButtonText: 'Yes', + cancelButtonText: 'No', + }); + if (res.isConfirmed) { + $('#currentOsuPath').text(path); + ipcRenderer.send('alert_response', path); + Swal.fire({ + title: 'Success!', + text: 'osu! folder set.', + icon: 'success', + confirmButtonText: 'Cool' + }) + ipcRenderer.send("do-update-check"); + } + }) + ipcRenderer.on('status_update', (event, status) => { switch (status.type) { case "up-to-date":