mirror of
https://github.com/Grasscutters/GrassClipper.git
synced 2024-11-26 01:41:02 +00:00
Merge pull request #7 from Grasscutters/server_launcher
Server Launcher
This commit is contained in:
commit
4e4bc14f53
@ -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"
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"applicationId": "js.grassclipper.app",
|
||||
"version": "0.4.6",
|
||||
"version": "0.5.0",
|
||||
"defaultMode": "window",
|
||||
"port": 0,
|
||||
"documentRoot": "/resources/",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "GrassClipper",
|
||||
"version": "0.4.5",
|
||||
"version": "0.5.0",
|
||||
"repository": "https://github.com/Grasscutters/GrassClipper.git",
|
||||
"author": "SpikeHD <spikegdofficial@gmail.com>",
|
||||
"license": "Apache-2.0",
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
BIN
resources/bg/server/1.png
Normal file
BIN
resources/bg/server/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 221 KiB |
@ -56,6 +56,15 @@
|
||||
Auto updating is temporarily disabled. Check GitHub for the newest release.
|
||||
</span>
|
||||
</div>
|
||||
<div class="settingsRow">
|
||||
<div class="settingSection">
|
||||
<span class="settingLabel">Enable Server Launcher</span>
|
||||
<input type="checkbox" id="serverLaunchOption" onchange="toggleServerLaunchSection()" />
|
||||
</div>
|
||||
<span class="settingSubtitle" id="serverSubtitle">
|
||||
Enable to server launcher tile for launcher a local Grasscutter instance.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="controlBar">
|
||||
@ -73,11 +82,11 @@
|
||||
<img src="icons/close.svg" />
|
||||
</div>
|
||||
</div>
|
||||
<div id="halvesContainer">
|
||||
<div id="firstHalf">
|
||||
<div id="panelContainer">
|
||||
<div id="firstPanel">
|
||||
<button class="playBtn" id="playOfficial" onclick="launchOfficial()">Play Official</button>
|
||||
</div>
|
||||
<div id="secondHalf">
|
||||
<div id="secondPanel">
|
||||
<div id="ipList" style="display: none;"></div>
|
||||
<div id="secondControlContainer">
|
||||
<div id="serverInput">
|
||||
@ -88,12 +97,21 @@
|
||||
<button class="playBtn" id="playPrivate" onclick="launchPrivate()">Play Private</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="thirdPanel" style="display: none;">
|
||||
<button class="playBtn" id="serverLaunch" onclick="launchLocalServer()">Launch Local Server</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="bottomBar">
|
||||
<div class="bottomSection">
|
||||
<button class="smolBtn" onclick="setGenshinImpactFolder()">Set "Genshin Impact Game" folder</button>
|
||||
<span id="genshinPath" style="margin-top: 4px;"></span>
|
||||
<div>
|
||||
<button class="smolBtn" onclick="setGenshinImpactFolder()">Set "Genshin Impact Game" folder</button>
|
||||
<span id="genshinPath" style="margin-top: 4px;"></span>
|
||||
</div>
|
||||
<div style="display: none;">
|
||||
<button class="smolBtn" onclick="setGrassCutterFolder()">Set "GrassCutter" .jar file</button>
|
||||
<span id="serverPath" style="margin-top: 4px;"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -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')
|
||||
})
|
||||
})
|
@ -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
|
||||
*/
|
||||
|
@ -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{
|
||||
|
14
scripts/local_server_launch.cmd
Normal file
14
scripts/local_server_launch.cmd
Normal file
@ -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%
|
Loading…
Reference in New Issue
Block a user