diff --git a/manifest.json b/manifest.json index 51786c6..786e54e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,5 @@ { "applicationId": "js.grassclipper.app", - "version": "0.4.6", + "version": "0.5.0", "resourcesURL": "https://github.com/Grasscutters/GrassClipper/releases/latest/download/resources.neu" } \ No newline at end of file diff --git a/neutralino.config.json b/neutralino.config.json index 01f7ae9..b927513 100644 --- a/neutralino.config.json +++ b/neutralino.config.json @@ -1,6 +1,6 @@ { "applicationId": "js.grassclipper.app", - "version": "0.4.6", + "version": "0.5.0", "defaultMode": "window", "port": 0, "documentRoot": "/resources/", diff --git a/package.json b/package.json index 05d9e01..b69abf2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "GrassClipper", - "version": "0.4.5", + "version": "0.5.0", "repository": "https://github.com/Grasscutters/GrassClipper.git", "author": "SpikeHD ", "license": "Apache-2.0", diff --git a/resources/bg/private/1.png b/resources/bg/private/1.png index eabb74f..6140560 100644 Binary files a/resources/bg/private/1.png and b/resources/bg/private/1.png differ diff --git a/resources/bg/server/1.png b/resources/bg/server/1.png new file mode 100644 index 0000000..33805af Binary files /dev/null and b/resources/bg/server/1.png differ diff --git a/resources/index.html b/resources/index.html index 1984178..e9637a5 100644 --- a/resources/index.html +++ b/resources/index.html @@ -56,6 +56,15 @@ Auto updating is temporarily disabled. Check GitHub for the newest release. +
+
+ Enable Server Launcher + +
+ + Enable to server launcher tile for launcher a local Grasscutter instance. + +
@@ -73,11 +82,11 @@
-
-
+
+
-
+
@@ -88,12 +97,21 @@
+
- - +
+ + +
+
+ + +
diff --git a/resources/js/hoverEvt.js b/resources/js/hoverEvt.js index 169fc5f..47adb2c 100644 --- a/resources/js/hoverEvt.js +++ b/resources/js/hoverEvt.js @@ -1,21 +1,36 @@ document.addEventListener('DOMContentLoaded', async () => { - const firstHalf = document.querySelector('#firstHalf') - const secondHalf = document.querySelector('#secondHalf') + const firstPanel = document.querySelector('#firstPanel') + const secondPanel = document.querySelector('#secondPanel') + const thirdPanel = document.querySelector('#thirdPanel') // Listen to hovers - firstHalf.addEventListener('mouseover', () => { - secondHalf.classList.add('darken') + firstPanel.addEventListener('mouseover', () => { + secondPanel.classList.add('darken') + thirdPanel.classList.add('darken') }) - firstHalf.addEventListener('mouseout', () => { - secondHalf.classList.remove('darken') + firstPanel.addEventListener('mouseout', () => { + secondPanel.classList.remove('darken') + thirdPanel.classList.remove('darken') }) - secondHalf.addEventListener('mouseover', () => { - firstHalf.classList.add('darken') + secondPanel.addEventListener('mouseover', () => { + firstPanel.classList.add('darken') + thirdPanel.classList.add('darken') }) - secondHalf.addEventListener('mouseout', () => { - firstHalf.classList.remove('darken') + secondPanel.addEventListener('mouseout', () => { + firstPanel.classList.remove('darken') + thirdPanel.classList.remove('darken') + }) + + thirdPanel.addEventListener('mouseover', () => { + firstPanel.classList.add('darken') + secondPanel.classList.add('darken') + }) + + thirdPanel.addEventListener('mouseout', () => { + firstPanel.classList.remove('darken') + secondPanel.classList.remove('darken') }) }) \ No newline at end of file diff --git a/resources/js/index.js b/resources/js/index.js index 2f818c9..20f925b 100644 --- a/resources/js/index.js +++ b/resources/js/index.js @@ -9,6 +9,7 @@ const filesystem = Neutralino.filesystem document.addEventListener('DOMContentLoaded', async () => { setBackgroundImage(); displayGenshinFolder(); + displayServerFolder(); // Set title version document.querySelector('#version').innerHTML = NL_APPVERSION @@ -20,6 +21,14 @@ document.addEventListener('DOMContentLoaded', async () => { handleGenshinFolderNotSet() } + if (!config.serverFolder) { + handleServerNotSet() + } + + if (config.serverLaunchPanel) { + displayServerLaunchSection() + } + // Set last connect document.querySelector('#ip').value = config.lastConnect @@ -92,8 +101,10 @@ async function getFavIps() { async function getCfg() { const defaultConf = { genshinImpactFolder: '', + serverFolder: '', lastConnect: '', - enableKillswitch: false + enableKillswitch: false, + serverLaunchPanel: false } const cfgStr = await Neutralino.storage.getData('config').catch(e => { // The data isn't set, so this is our first time opening @@ -125,6 +136,16 @@ async function enableButtons() { } } +/** + * Enable server launch button + */ + async function enableServerButton() { + const serverBtn = document.querySelector('#serverLaunch') + + serverBtn.classList.remove('disabled') + serverBtn.disabled = false +} + /** * Disable buttons when the game folder is not set */ @@ -133,7 +154,7 @@ async function handleGenshinFolderNotSet() { document.querySelector('#genshinPath').innerHTML = 'Not set' // Set official server background to default - document.querySelector('#firstHalf').style.backgroundImage = `url("../bg/private/default.png")` + document.querySelector('#firstPanel').style.backgroundImage = `url("../bg/private/default.png")` const offBtn = document.querySelector('#playOfficial') const privBtn = document.querySelector('#playPrivate') @@ -147,6 +168,19 @@ async function handleGenshinFolderNotSet() { // TODO show a dialog of sorts } +async function handleServerNotSet() { + // Set buttons to greyed out and disable + document.querySelector('#serverPath').innerHTML = 'Not set' + + // Set official server background to default + // document.querySelector('#firstPanel').style.backgroundImage = `url("../bg/private/default.png")` + + const privBtn = document.querySelector('#serverLaunch') + + privBtn.classList.add('disabled') + privBtn.disabled = true +} + async function proxyIsInstalled() { // Check if the proxy server is installed const curDirList = await filesystem.readDirectory(NL_CWD) @@ -172,6 +206,16 @@ async function displayGenshinFolder() { elm.innerHTML = config.genshinImpactFolder } +/** + * Show the server folder under the select button + */ + async function displayServerFolder() { + const elm = document.querySelector('#serverPath') + const config = await getCfg() + + elm.innerHTML = config.serverFolder +} + /** * Set the background images of both the private and public sections */ @@ -180,12 +224,18 @@ async function setBackgroundImage() { const privImages = (await filesystem.readDirectory(NL_CWD + '/resources/bg/private')).filter(file => file.type === 'FILE' && !file.entry.includes('default')) const privImage = privImages[Math.floor(Math.random() * privImages.length)].entry + + const servImages = (await filesystem.readDirectory(NL_CWD + '/resources/bg/server')).filter(file => file.type === 'FILE' && !file.entry.includes('default')) + const servImage = servImages[Math.floor(Math.random() * servImages.length)].entry // Set default image, it will change if the bg folder exists - document.querySelector('#firstHalf').style.backgroundImage = `url("https://webstatic.hoyoverse.com/upload/event/2020/11/04/7fd661b5184e1734f91f628b6f89a31f_7367318474207189623.png")` + document.querySelector('#firstPanel').style.backgroundImage = `url("https://webstatic.hoyoverse.com/upload/event/2020/11/04/7fd661b5184e1734f91f628b6f89a31f_7367318474207189623.png")` // Set the private background image - document.querySelector('#secondHalf').style.backgroundImage = `url("../bg/private/${privImage}")` + document.querySelector('#secondPanel').style.backgroundImage = `url("../bg/private/${privImage}")` + + // Set the server background image + document.querySelector('#thirdPanel').style.backgroundImage = `url("../bg/server/${servImage}")` return @@ -234,7 +284,7 @@ async function setBackgroundImage() { const image = localImg[Math.floor(Math.random() * localImg.length)].entry // Set background image - document.querySelector('#firstHalf').style.backgroundImage = `url("../bg/official/${image}")` + document.querySelector('#firstPanel').style.backgroundImage = `url("../bg/official/${image}")` } } } @@ -350,8 +400,10 @@ async function openSettings() { // Fill setting options with what is currently set in config const killSwitch = document.querySelector('#killswitchOption') + const serverLaunch = document.querySelector('#serverLaunchOption') killSwitch.checked = config.enableKillswitch + serverLaunch.checked = config.serverLaunchPanel // Check for updates //checkForUpdatesAndShow() @@ -359,11 +411,12 @@ async function openSettings() { async function closeSettings() { const settings = document.querySelector('#settingsPanel') + const config = await getCfg() settings.style.display = 'none' // In case we installed the proxy server - if (await proxyIsInstalled()) { + if (await proxyIsInstalled() && config.genshinImpactFolder) { const playPriv = document.querySelector('#playPrivate') playPriv.classList.remove('disabled') @@ -411,6 +464,29 @@ async function checkForUpdatesAndShow() { } } +async function displayServerLaunchSection() { + const serverPanel = document.querySelector('#thirdPanel') + const bottomBtnSection = document.querySelector('#serverPath').parentElement + + if (serverPanel.style.display === 'none') { + serverPanel.style.removeProperty('display') + bottomBtnSection.style.removeProperty('display') + } else { + serverPanel.style.display = 'none' + bottomBtnSection.style.display = 'none' + } +} + +async function toggleServerLaunchSection() { + const config = await getCfg() + + displayServerLaunchSection() + + // Save setting + config.serverLaunchPanel = !config.serverLaunchPanel + Neutralino.storage.setData('config', JSON.stringify(config)) +} + /** * Set the game folder by opening a folder picker */ @@ -439,6 +515,23 @@ async function setGenshinImpactFolder() { enableButtons() } +async function setGrassCutterFolder() { + const folder = await Neutralino.os.showOpenDialog('Select GrassCutter server jar', { + filters: [ + { name: 'Jar files', extensions: ['jar'] } + ] + }) + + // Set the folder in our configuration + const config = await getCfg() + + config.serverFolder = folder + Neutralino.storage.setData('config', JSON.stringify(config)) + + displayServerFolder() + enableServerButton() +} + /** * Get the name of the game executable * @@ -482,6 +575,12 @@ async function launchPrivate() { Neutralino.os.execCommand(`${NL_CWD}/scripts/private_server_launch.cmd ${ip} "${config.genshinImpactFolder}/${await getGenshinExecName()}" "${NL_CWD}" ${config.enableKillswitch}`).catch(e => console.log(e)) } +async function launchLocalServer() { + const config = await getCfg() + + Neutralino.os.execCommand(`${NL_CWD}/scripts/local_server_launch.cmd "${config.serverFolder}"`).catch(e => console.log(e)) +} + /** * Minimize the window */ diff --git a/resources/style/index.css b/resources/style/index.css index 6da82e6..bb8ab8d 100644 --- a/resources/style/index.css +++ b/resources/style/index.css @@ -50,7 +50,7 @@ body { } #settingsPanel { - width: 30%; + width: 35%; height: 60%; } @@ -65,7 +65,7 @@ body { flex-direction: column; align-items: center; justify-content: center; - padding: 10px 20%; + padding: 10px 10%; } .settingsRow { @@ -104,7 +104,7 @@ body { #settingsClose { display: inline-block; - margin-left: 65%; + margin-left: 70%; transition: filter 0.1s ease-in-out; } @@ -281,17 +281,29 @@ body { .bottomSection { display: flex; - flex-direction: column; + flex-direction: row; height: 100%; + width: 100%; background: #141414; + justify-content: space-evenly; } -#genshinPath { +.bottomSection div { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: #141414; + margin: 4px; + height: 10%; +} + +#genshinPath, #serverPath { color: white; font-size: 14px; } -#halvesContainer { +#panelContainer { width: 100%; height: 100%; position: relative; @@ -299,7 +311,7 @@ body { display: flex; } -#firstHalf, #secondHalf { +#firstPanel, #secondPanel, #thirdPanel { display: flex; justify-content: center; width: 100%; @@ -309,19 +321,22 @@ body { transition: width 0.2s ease-in-out, filter 0.2s ease-in-out; } -#firstHalf:hover, #secondHalf:hover { +#firstPanel:hover, #secondPanel:hover, #thirdPanel:hover { width: calc(100% + 150px); } -#firstHalf { +#firstPanel, #secondPanel { border-right: 6px solid #141414; +} + +#firstPanel { background-position: -340px; } /* Move the first official button to the position on the png */ -#firstHalf button { - position: relative; - transform: translate(140px, 500px); +#firstPanel button, #secondPanel button, #thirdPanel button { + display: block; + /* transform: translate(140px, 500px); */ width: 300px; height: 60px; } @@ -330,13 +345,7 @@ body { display: block; } -#secondHalf button { - display: block; - width: 300px; - height: 60px; -} - -#secondHalf input { +#secondPanel input { margin-bottom: 4px; height: 20px; background: white; @@ -348,7 +357,7 @@ body { transition: border-bottom 0.1s ease-in-out; } -#secondHalf input:focus { +#secondPanel input:focus { outline: none; border-bottom: 2px solid #ffc61e; } @@ -356,9 +365,14 @@ body { /* Move the second private button the near-bottom */ #secondControlContainer { position: relative; - transform: translate(115px, 456px); + /* transform: translate(115px, 456px); */ width: 300px; height: 60px; + margin-top: calc(68vh - 40px) !important; +} + +#secondControlContainer, #firstPanel button, #thirdPanel button { + margin-top: 68vh; } #serverInput input, #serverInput img{ diff --git a/scripts/local_server_launch.cmd b/scripts/local_server_launch.cmd new file mode 100644 index 0000000..d411daa --- /dev/null +++ b/scripts/local_server_launch.cmd @@ -0,0 +1,14 @@ +@echo off + +set GRASSCUTTER_JAR=%1 +set GRASSCUTTER_JAR=%GRASSCUTTER_JAR:"=% + +:: Ensure admin +>nul 2>&1 reg query "HKU\S-1-5-19" || ( + set params = %*:"="""% + cd /d "%~dp0" && ( if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs" ) && fsutil dirty query %systemdrive% 1>nul 2>nul || ( echo Set UAC = CreateObject^("Shell.Application"^) : UAC.ShellExecute "cmd.exe", "/k cd ""%~sdp0"" && %~s0 "%1"", "", "runas", 1 >> "%temp%\getadmin.vbs" && "%temp%\getadmin.vbs" && exit /B ) +) + +echo Starting local Grasscutter server... + +start /b java -jar %GRASSCUTTER_JAR% \ No newline at end of file