mirror of
https://github.com/Grasscutters/GrassClipper.git
synced 2024-11-16 04:45:34 +00:00
Merge branch 'Grasscutters:main' into main
This commit is contained in:
commit
55fef29013
29
.eslintrc.json
Normal file
29
.eslintrc.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"commonjs": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 13
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"no-undef": 0,
|
||||||
|
"no-unused-vars": 0,
|
||||||
|
"no-case-declarations": 0,
|
||||||
|
|
||||||
|
"indent": [
|
||||||
|
"error",
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"single"
|
||||||
|
],
|
||||||
|
"semi": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@ bin/
|
|||||||
dist/
|
dist/
|
||||||
ext/
|
ext/
|
||||||
temp/
|
temp/
|
||||||
|
gc*/
|
||||||
resources/js/neutralino.js
|
resources/js/neutralino.js
|
||||||
resources/bg/official
|
resources/bg/official
|
||||||
|
|
||||||
|
@ -63,5 +63,21 @@
|
|||||||
"alertAuthNoRegister": "Authentication is disabled, no need to register!",
|
"alertAuthNoRegister": "Authentication is disabled, no need to register!",
|
||||||
"alertRegisterSuccess": "Registration successful!",
|
"alertRegisterSuccess": "Registration successful!",
|
||||||
|
|
||||||
|
"downloadTitle": "Downloads",
|
||||||
|
"grassclipperTitle": "GrassClipper",
|
||||||
|
"grasscutterTitle": "Grasscutter",
|
||||||
|
"installerTitle": "Installer",
|
||||||
|
"installerSubtitle": "Installs proxy and other tools. Required for Grasscutter servers.",
|
||||||
|
"downloadStable": "Download Grasscutter Stable Build",
|
||||||
|
"stableSubtitle": "Install Grasscutter stable branch. This build usually has less bugs, but also less features.",
|
||||||
|
"downloadDev": "Download Grasscutter Development Build",
|
||||||
|
"downloadSubtitle": "Install Grasscutter development branch. This build sometimes has bugs, and is frequently updated. Use at your own risk.",
|
||||||
|
"downloadResources": "Download Grasscutter Resources",
|
||||||
|
"devSubtitle": "Downloads Grasscutter resources into the currently set Grasscutter folder. This should be done unless you plan on getting resources externally.",
|
||||||
|
|
||||||
|
"gcScriptRunning": "Running...",
|
||||||
|
"stableInstall": "Download",
|
||||||
|
"devInstall": "Download",
|
||||||
|
|
||||||
"updateNotifText": "A new update is available! Newest version: "
|
"updateNotifText": "A new update is available! Newest version: "
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
"proxyInstallDeny": "不用了,謝謝。",
|
"proxyInstallDeny": "不用了,謝謝。",
|
||||||
|
|
||||||
"gameFolderDialog": "選擇Genshin Impact game資料夾",
|
"gameFolderDialog": "選擇Genshin Impact game資料夾",
|
||||||
"grasscutterFileDialog": "選擇Grasscutter.jar檔案"
|
"grasscutterFileDialog": "選擇Grasscutter.jar檔案",
|
||||||
|
|
||||||
"loggingInTo": "登錄至:",
|
"loggingInTo": "登錄至:",
|
||||||
"registeringFor": "註冊至:",
|
"registeringFor": "註冊至:",
|
||||||
@ -60,7 +60,7 @@
|
|||||||
"alertUserTaken": "用戶名已被占用",
|
"alertUserTaken": "用戶名已被占用",
|
||||||
"alertPassMismatch": "兩組密碼不一致",
|
"alertPassMismatch": "兩組密碼不一致",
|
||||||
"alertAuthNoRegister": "未啟用認證,無需註冊!",
|
"alertAuthNoRegister": "未啟用認證,無需註冊!",
|
||||||
"alertRegisterSuccess": "註冊成功!"
|
"alertRegisterSuccess": "註冊成功!",
|
||||||
|
|
||||||
"updateNotifText": "有新的GrassClipper更新可用! 最新版本: "
|
"updateNotifText": "有新的GrassClipper更新可用! 最新版本: "
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"applicationId": "js.grassclipper.app",
|
"applicationId": "js.grassclipper.app",
|
||||||
"version": "0.8.5",
|
"version": "0.9.0",
|
||||||
"resourcesURL": "https://github.com/Grasscutters/GrassClipper/releases/latest/download/resources.neu"
|
"resourcesURL": "https://github.com/Grasscutters/GrassClipper/releases/latest/download/resources.neu"
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"applicationId": "js.grassclipper.app",
|
"applicationId": "js.grassclipper.app",
|
||||||
"version": "0.8.5",
|
"version": "0.9.0",
|
||||||
"defaultMode": "window",
|
"defaultMode": "window",
|
||||||
"port": 0,
|
"port": 0,
|
||||||
"documentRoot": "/resources/",
|
"documentRoot": "/resources/",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "grassclipper",
|
"name": "grassclipper",
|
||||||
"version": "0.8.5",
|
"version": "0.9.0",
|
||||||
"repository": "https://github.com/Grasscutters/GrassClipper.git",
|
"repository": "https://github.com/Grasscutters/GrassClipper.git",
|
||||||
"author": "SpikeHD <spikegdofficial@gmail.com>",
|
"author": "SpikeHD <spikegdofficial@gmail.com>",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@ -9,5 +9,8 @@
|
|||||||
"build-win": ".\\build_win.cmd",
|
"build-win": ".\\build_win.cmd",
|
||||||
"build-linux": "./build.sh",
|
"build-linux": "./build.sh",
|
||||||
"build": "echo !! Run build-win or build-linux to build for your platform !!\n"
|
"build": "echo !! Run build-win or build-linux to build for your platform !!\n"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^8.14.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
resources/icons/download.svg
Normal file
11
resources/icons/download.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
|
||||||
|
<desc>Created with Fabric.js 1.7.22</desc>
|
||||||
|
<defs>
|
||||||
|
</defs>
|
||||||
|
<g transform="translate(128 128) scale(0.72 0.72)" style="">
|
||||||
|
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(-175.05 -175.05) scale(3.89 3.89)" >
|
||||||
|
<path d="M 66.848 42.103 c -2.111 -1.782 -5.266 -1.512 -7.046 0.599 L 50 54.325 V 5 c 0 -2.761 -2.238 -5 -5 -5 c -2.761 0 -5 2.239 -5 5 v 49.325 l -9.802 -11.623 c -1.78 -2.111 -4.934 -2.378 -7.046 -0.599 c -2.111 1.78 -2.379 4.935 -0.599 7.046 l 18.624 22.085 c 0.075 0.088 0.156 0.168 0.236 0.251 c 0.028 0.029 0.054 0.059 0.083 0.088 c 0.2 0.196 0.416 0.372 0.643 0.531 c 0.044 0.031 0.088 0.061 0.133 0.091 c 0.23 0.15 0.471 0.282 0.722 0.392 c 0.05 0.022 0.101 0.04 0.151 0.061 c 0.264 0.105 0.534 0.193 0.813 0.252 c 0.035 0.007 0.071 0.011 0.106 0.018 c 0.306 0.058 0.618 0.094 0.935 0.094 c 0.317 0 0.628 -0.036 0.934 -0.094 c 0.035 -0.007 0.071 -0.01 0.106 -0.018 c 0.279 -0.059 0.549 -0.147 0.812 -0.252 c 0.052 -0.021 0.103 -0.039 0.154 -0.062 c 0.25 -0.11 0.49 -0.241 0.719 -0.39 c 0.047 -0.03 0.092 -0.061 0.137 -0.093 c 0.226 -0.158 0.441 -0.333 0.64 -0.528 c 0.03 -0.029 0.057 -0.061 0.086 -0.091 c 0.079 -0.082 0.161 -0.161 0.234 -0.249 l 18.624 -22.085 C 69.227 47.037 68.958 43.883 66.848 42.103 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
|
||||||
|
<path d="M 79.692 90 H 10.307 c -2.761 0 -5 -2.239 -5 -5 l 0 -20.352 c 0 -2.611 1.909 -4.943 4.508 -5.191 c 2.982 -0.285 5.492 2.053 5.492 4.976 v 14.528 c 0 0.574 0.465 1.039 1.039 1.039 h 57.308 c 0.574 0 1.039 -0.465 1.039 -1.039 V 64.648 c 0 -2.612 1.91 -4.943 4.509 -5.191 c 2.982 -0.284 5.491 2.053 5.491 4.977 V 85 C 84.692 87.761 82.454 90 79.692 90 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
@ -8,6 +8,7 @@
|
|||||||
<script src="js/hoverEvt.js"></script>
|
<script src="js/hoverEvt.js"></script>
|
||||||
<script src="js/helpers.js"></script>
|
<script src="js/helpers.js"></script>
|
||||||
<script src="js/index.js"></script>
|
<script src="js/index.js"></script>
|
||||||
|
<script src="js/gcdownloader.js"></script>
|
||||||
<script src="js/onLoad.js"></script>
|
<script src="js/onLoad.js"></script>
|
||||||
<script src="js/options.js"></script>
|
<script src="js/options.js"></script>
|
||||||
<script src="js/login.js"></script>
|
<script src="js/login.js"></script>
|
||||||
@ -114,6 +115,59 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="downloadPanel" style="display: none;">
|
||||||
|
<div id="downloadTitleBar">
|
||||||
|
<span id="downloadTitle">Downloads</span>
|
||||||
|
<div id="downloadClose" onclick="closeDownloads()">
|
||||||
|
<img src="icons/close.svg" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="downloadPanelInner">
|
||||||
|
<div class="downloadTitle", id="grassclipperTitle">
|
||||||
|
GrassClipper
|
||||||
|
</div>
|
||||||
|
<div class="downloadRow">
|
||||||
|
<div class="downloadSection">
|
||||||
|
<span class="downloadLabel" id="installerTitle">Installer</span>
|
||||||
|
<button class="smolBtn" onclick="runInstallScript()" id="proxyInstall">Install</button>
|
||||||
|
</div>
|
||||||
|
<span class="downloadSubtitle" id="installerSubtitle">
|
||||||
|
Installs proxy and other tools. Required for Grasscutter servers.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="downloadTitle", id="grasscutterTitle">
|
||||||
|
Grasscutter
|
||||||
|
</div>
|
||||||
|
<div class="downloadRow">
|
||||||
|
<div class="downloadSection">
|
||||||
|
<span class="downloadLabel" id="downloadStable">Download Grasscutter Stable Build</span>
|
||||||
|
<button class="smolBtn" onclick="downloadGC('stable')" id="stableInstall">Download</button>
|
||||||
|
</div>
|
||||||
|
<span class="downloadSubtitle" id="stableSubtitle">
|
||||||
|
Install Grasscutter stable branch. This build usually has less bugs, but also less features.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="downloadRow">
|
||||||
|
<div class="downloadSection">
|
||||||
|
<span class="downloadLabel" id="downloadDev">Download Grasscutter Development Build</span>
|
||||||
|
<button class="smolBtn" onclick="downloadGC('development')" id="devInstall">Download</button>
|
||||||
|
</div>
|
||||||
|
<span class="downloadSubtitle" id="devSubtitle">
|
||||||
|
Install Grasscutter development branch. This build sometimes has bugs, and is frequently updated. Use at your own risk.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="downloadRow">
|
||||||
|
<div class="downloadSection">
|
||||||
|
<span class="downloadLabel" id="downloadResources">Download Grasscutter Resources</span>
|
||||||
|
<button class="smolBtn" onclick="downloadGC('development')" id="resourceInstall">Download</button>
|
||||||
|
</div>
|
||||||
|
<span class="downloadSubtitle" id="devSubtitle">
|
||||||
|
Downloads Grasscutter resources into the currently set Grasscutter folder. This should be done unless you plan on getting resources externally.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Setting panel -->
|
<!-- Setting panel -->
|
||||||
<div id="settingsPanel" style="display: none;">
|
<div id="settingsPanel" style="display: none;">
|
||||||
<div id="settingsTitleBar">
|
<div id="settingsTitleBar">
|
||||||
@ -194,6 +248,9 @@
|
|||||||
<div id="refreshBtn" onclick="window.location.reload()">
|
<div id="refreshBtn" onclick="window.location.reload()">
|
||||||
<img src="icons/refresh.svg" />
|
<img src="icons/refresh.svg" />
|
||||||
</div>
|
</div>
|
||||||
|
<div id="downloadBtn" onclick="openDownloads()">
|
||||||
|
<img src="icons/download.svg" />
|
||||||
|
</div>
|
||||||
<div id="settingsBtn" onclick="openSettings()">
|
<div id="settingsBtn" onclick="openSettings()">
|
||||||
<img src="icons/cog.svg" />
|
<img src="icons/cog.svg" />
|
||||||
</div>
|
</div>
|
||||||
@ -204,6 +261,8 @@
|
|||||||
<img src="icons/close.svg" />
|
<img src="icons/close.svg" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Main content -->
|
||||||
<div id="panelContainer">
|
<div id="panelContainer">
|
||||||
<!-- Official play btn -->
|
<!-- Official play btn -->
|
||||||
<div id="firstPanel">
|
<div id="firstPanel">
|
||||||
|
@ -9,37 +9,37 @@ async function displayRegisterAlert(message, type, cooldown = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function displayAlert(message, type, cooldown, name) {
|
function displayAlert(message, type, cooldown, name) {
|
||||||
const elm = document.getElementById(`${name}Alert`);
|
const elm = document.getElementById(`${name}Alert`)
|
||||||
const text = document.getElementById(`${name}AlertText`);
|
const text = document.getElementById(`${name}AlertText`)
|
||||||
|
|
||||||
elm.style.removeProperty('display');
|
elm.style.removeProperty('display')
|
||||||
|
|
||||||
// Remove classification classes
|
// Remove classification classes
|
||||||
elm.classList.remove('error');
|
elm.classList.remove('error')
|
||||||
elm.classList.remove('success');
|
elm.classList.remove('success')
|
||||||
elm.classList.remove('warn');
|
elm.classList.remove('warn')
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case 'error':
|
case 'error':
|
||||||
elm.classList.add('error');
|
elm.classList.add('error')
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'success':
|
case 'success':
|
||||||
elm.classList.add('success');
|
elm.classList.add('success')
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'warn':
|
case 'warn':
|
||||||
default:
|
default:
|
||||||
elm.classList.add('warn');
|
elm.classList.add('warn')
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
text.innerText = message;
|
text.innerText = message
|
||||||
|
|
||||||
clearTimeout(alertTimeout)
|
clearTimeout(alertTimeout)
|
||||||
|
|
||||||
// Disappear after cooldown
|
// Disappear after cooldown
|
||||||
alertTimeout = setTimeout(() => {
|
alertTimeout = setTimeout(() => {
|
||||||
elm.style.display = 'none';
|
elm.style.display = 'none'
|
||||||
}, cooldown || alertCooldown)
|
}, cooldown || alertCooldown)
|
||||||
}
|
}
|
102
resources/js/gcdownloader.js
Normal file
102
resources/js/gcdownloader.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
async function clearGCInstallation() {
|
||||||
|
Neutralino.os.execCommand('del /s /q "./gc"')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setDownloadButtonsToLoading() {
|
||||||
|
const stableBtn = document.querySelector('#stableInstall')
|
||||||
|
const devBtn = document.querySelector('#devInstall')
|
||||||
|
|
||||||
|
stableBtn.innerText = localeObj.gcScriptRunning || 'Running...'
|
||||||
|
|
||||||
|
devBtn.innerText = localeObj.gcScriptRunning || 'Running...'
|
||||||
|
|
||||||
|
// Set btns to disabled
|
||||||
|
stableBtn.disabled = true
|
||||||
|
stableBtn.classList.add('disabled')
|
||||||
|
|
||||||
|
devBtn.disabled = true
|
||||||
|
devBtn.classList.add('disabled')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resetDownloadButtons() {
|
||||||
|
const stableBtn = document.querySelector('#stableInstall')
|
||||||
|
const devBtn = document.querySelector('#devInstall')
|
||||||
|
|
||||||
|
stableBtn.innerText = localeObj.stableInstall || 'Download'
|
||||||
|
devBtn.innerText = localeObj.devInstall || 'Download'
|
||||||
|
|
||||||
|
// Set btns to enabled
|
||||||
|
stableBtn.disabled = false
|
||||||
|
stableBtn.classList.remove('disabled')
|
||||||
|
|
||||||
|
devBtn.disabled = false
|
||||||
|
devBtn.classList.remove('disabled')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadGC(branch) {
|
||||||
|
const config = await getCfg()
|
||||||
|
|
||||||
|
// If we are pulling from a new branch, delete the old installation
|
||||||
|
if (config.grasscutterBranch !== branch) await clearGCInstallation()
|
||||||
|
|
||||||
|
// Set current installation in config
|
||||||
|
config.grasscutterBranch = branch
|
||||||
|
|
||||||
|
// Set gc path for people with launcher enabled
|
||||||
|
config.serverFolder = `${NL_CWD}/gc-${branch}/grasscutter.jar`
|
||||||
|
|
||||||
|
// Enable server launcher
|
||||||
|
config.serverLaunchPanel = true
|
||||||
|
|
||||||
|
Neutralino.storage.setData('config', JSON.stringify(config))
|
||||||
|
|
||||||
|
setDownloadButtonsToLoading()
|
||||||
|
|
||||||
|
// Keystore for branch (since they can differ)
|
||||||
|
const keystoreUrl = `https://github.com/Grasscutters/Grasscutter/raw/${branch}/keystore.p12`
|
||||||
|
|
||||||
|
// External service that allows un-authed artifact downloading
|
||||||
|
const artiUrl = `https://nightly.link/Grasscutters/Grasscutter/workflows/build/${branch}/Grasscutter.zip`
|
||||||
|
|
||||||
|
// For data files
|
||||||
|
const dataFiles = await axios.get(`https://api.github.com/repos/Grasscutters/Grasscutter/contents/data?ref=${branch}`)
|
||||||
|
const dataList = dataFiles.data
|
||||||
|
.map(file => ({ path: file.path, filename: file.name }))
|
||||||
|
.map(o => ({ url: `https://raw.githubusercontent.com/Grasscutters/Grasscutter/${branch}/${o.path}`, filename: o.filename }))
|
||||||
|
|
||||||
|
// For key files
|
||||||
|
const keyFiles = await axios.get(`https://api.github.com/repos/Grasscutters/Grasscutter/contents/keys?ref=${branch}`)
|
||||||
|
const keyList = keyFiles.data
|
||||||
|
.map(file => ({ path: file.path, filename: file.name }))
|
||||||
|
.map(o => ({ url: `https://raw.githubusercontent.com/Grasscutters/Grasscutter/${branch}/${o.path}`, filename: o.filename }))
|
||||||
|
|
||||||
|
const serverFolderFixed = config.serverFolder.match(/.*\\|.*\//g, '')[0].replace(/\//g, '\\')
|
||||||
|
|
||||||
|
// Ensure data and key folders exist
|
||||||
|
|
||||||
|
await Neutralino.os.execCommand(`mkdir ${serverFolderFixed}\\data`)
|
||||||
|
await Neutralino.os.execCommand(`mkdir ${serverFolderFixed}\\keys`)
|
||||||
|
|
||||||
|
// Download data files
|
||||||
|
for (const o of dataList) {
|
||||||
|
const folder = 'data'
|
||||||
|
await Neutralino.os.execCommand(`powershell Invoke-WebRequest -Uri ${o.url} -OutFile "${serverFolderFixed}\\${folder}\\${o.filename}"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download key files
|
||||||
|
for (const o of keyList) {
|
||||||
|
const folder = 'keys'
|
||||||
|
await Neutralino.os.execCommand(`powershell Invoke-WebRequest -Uri ${o.url} -OutFile "${serverFolderFixed}\\${folder}\\${o.filename}"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run installer
|
||||||
|
createCmdWindow(`.\\scripts\\gc_download.cmd ${artiUrl} ${keystoreUrl} ${branch}`)
|
||||||
|
|
||||||
|
// Fix buttons
|
||||||
|
resetDownloadButtons()
|
||||||
|
|
||||||
|
// Display folder after saving config
|
||||||
|
displayServerFolder()
|
||||||
|
enableServerButton()
|
||||||
|
displayServerLaunchSection()
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
*/
|
*/
|
||||||
async function getCfg() {
|
async function getCfg() {
|
||||||
const defaultConf = {
|
const defaultConf = {
|
||||||
gameexe: '',
|
gameexe: '',
|
||||||
serverFolder: '',
|
serverFolder: '',
|
||||||
@ -12,6 +12,7 @@
|
|||||||
serverLaunchPanel: false,
|
serverLaunchPanel: false,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
useHttps: true,
|
useHttps: true,
|
||||||
|
grasscutterBranch: '',
|
||||||
}
|
}
|
||||||
const cfgStr = await Neutralino.storage.getData('config').catch(e => {
|
const cfgStr = await Neutralino.storage.getData('config').catch(e => {
|
||||||
// The data isn't set, so this is our first time opening
|
// The data isn't set, so this is our first time opening
|
||||||
@ -31,7 +32,7 @@
|
|||||||
*
|
*
|
||||||
* @returns {Promise<string[]>}
|
* @returns {Promise<string[]>}
|
||||||
*/
|
*/
|
||||||
async function getFavIps() {
|
async function getFavIps() {
|
||||||
const ipStr = await Neutralino.storage.getData('favorites').catch(e => {
|
const ipStr = await Neutralino.storage.getData('favorites').catch(e => {
|
||||||
// The data isn't set, so this is our first time opening
|
// The data isn't set, so this is our first time opening
|
||||||
Neutralino.storage.setData('favorites', JSON.stringify([]))
|
Neutralino.storage.setData('favorites', JSON.stringify([]))
|
||||||
@ -97,7 +98,7 @@ async function openGameFolder() {
|
|||||||
|
|
||||||
async function openGrasscutterFolder() {
|
async function openGrasscutterFolder() {
|
||||||
const config = await getCfg()
|
const config = await getCfg()
|
||||||
const folder = config.serverFolder.match(/.*\\/g, '')[0]
|
const folder = config.serverFolder.match(/.*\\|.*\//g, '')[0]
|
||||||
|
|
||||||
openInExplorer(folder)
|
openInExplorer(folder)
|
||||||
}
|
}
|
||||||
@ -105,7 +106,7 @@ async function openGrasscutterFolder() {
|
|||||||
/**
|
/**
|
||||||
* Minimize the window
|
* Minimize the window
|
||||||
*/
|
*/
|
||||||
function minimizeWin() {
|
function minimizeWin() {
|
||||||
console.log('min')
|
console.log('min')
|
||||||
Neutralino.window.minimize()
|
Neutralino.window.minimize()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
Neutralino.init();
|
Neutralino.init()
|
||||||
|
|
||||||
let localeObj;
|
let localeObj
|
||||||
const filesystem = Neutralino.filesystem
|
const filesystem = Neutralino.filesystem
|
||||||
const createCmdWindow = async (command) => {
|
const createCmdWindow = async (command) => {
|
||||||
Neutralino.os.execCommand(`cmd.exe /c start "" ${command}`, { background: true })
|
Neutralino.os.execCommand(`cmd.exe /c start "" ${command}`, { background: true })
|
||||||
@ -31,7 +31,7 @@ async function enableButtons() {
|
|||||||
/**
|
/**
|
||||||
* Enable server launch button
|
* Enable server launch button
|
||||||
*/
|
*/
|
||||||
async function enableServerButton() {
|
async function enableServerButton() {
|
||||||
const serverBtn = document.querySelector('#serverLaunch')
|
const serverBtn = document.querySelector('#serverLaunch')
|
||||||
|
|
||||||
serverBtn.classList.remove('disabled')
|
serverBtn.classList.remove('disabled')
|
||||||
@ -46,7 +46,7 @@ async function handleGameNotSet() {
|
|||||||
document.querySelector('#gamePath').innerHTML = localeObj.folderNotSet
|
document.querySelector('#gamePath').innerHTML = localeObj.folderNotSet
|
||||||
|
|
||||||
// Set official server background to default
|
// Set official server background to default
|
||||||
document.querySelector('#firstPanel').style.backgroundImage = `url("../bg/private/default.png")`
|
document.querySelector('#firstPanel').style.backgroundImage = 'url("../bg/private/default.png")'
|
||||||
|
|
||||||
const offBtn = document.querySelector('#playOfficial')
|
const offBtn = document.querySelector('#playOfficial')
|
||||||
const privBtn = document.querySelector('#playPrivate')
|
const privBtn = document.querySelector('#playPrivate')
|
||||||
@ -86,7 +86,7 @@ async function displayGameFolder() {
|
|||||||
/**
|
/**
|
||||||
* Show the server folder under the select button
|
* Show the server folder under the select button
|
||||||
*/
|
*/
|
||||||
async function displayServerFolder() {
|
async function displayServerFolder() {
|
||||||
const elm = document.querySelector('#serverPath')
|
const elm = document.querySelector('#serverPath')
|
||||||
const config = await getCfg()
|
const config = await getCfg()
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ async function setBackgroundImage() {
|
|||||||
const servImage = servImages[Math.floor(Math.random() * servImages.length)].entry
|
const servImage = servImages[Math.floor(Math.random() * servImages.length)].entry
|
||||||
|
|
||||||
// Set default image, it will change if the bg folder exists
|
// Set default image, it will change if the bg folder exists
|
||||||
document.querySelector('#firstPanel').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
|
// Set the private background image
|
||||||
document.querySelector('#secondPanel').style.backgroundImage = `url("../bg/private/${privImage}")`
|
document.querySelector('#secondPanel').style.backgroundImage = `url("../bg/private/${privImage}")`
|
||||||
@ -246,6 +246,30 @@ async function handleFavoriteList() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function openDownloads() {
|
||||||
|
const downloads = document.querySelector('#downloadPanel')
|
||||||
|
const config = await getCfg()
|
||||||
|
|
||||||
|
if (downloads.style.display === 'none') {
|
||||||
|
downloads.style.removeProperty('display')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable the resource download button if a serverFolder path is not set
|
||||||
|
if (!config.serverFolder) {
|
||||||
|
document.querySelector('#resourceInstall').disabled = true
|
||||||
|
document.querySelector('#resourceInstall').classList.add('disabled')
|
||||||
|
} else {
|
||||||
|
document.querySelector('#resourceInstall').disabled = false
|
||||||
|
document.querySelector('#resourceInstall').classList.remove('disabled')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function closeDownloads() {
|
||||||
|
const downloads = document.querySelector('#downloadPanel')
|
||||||
|
|
||||||
|
downloads.style.display = 'none'
|
||||||
|
}
|
||||||
|
|
||||||
async function openSettings() {
|
async function openSettings() {
|
||||||
const settings = document.querySelector('#settingsPanel')
|
const settings = document.querySelector('#settingsPanel')
|
||||||
const config = await getCfg()
|
const config = await getCfg()
|
||||||
@ -294,13 +318,13 @@ async function openLogin() {
|
|||||||
|
|
||||||
const config = await getCfg()
|
const config = await getCfg()
|
||||||
const useHttps = config.useHttps
|
const useHttps = config.useHttps
|
||||||
const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}`;
|
const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}`
|
||||||
|
|
||||||
// Check if we even need to authenticate
|
// Check if we even need to authenticate
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get(url + '/grasscutter/auth_status')
|
const { data } = await axios.get(url + '/authentication/type')
|
||||||
|
|
||||||
if (data?.message !== 'AUTH_ENABLED') {
|
if (!data.includes('GCAuthAuthenticationHandler')) {
|
||||||
launchPrivate()
|
launchPrivate()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -309,7 +333,6 @@ async function openLogin() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
loginIpDisplay.innerText = ip
|
loginIpDisplay.innerText = ip
|
||||||
registerIpDisplay.innerText = ip
|
registerIpDisplay.innerText = ip
|
||||||
|
|
||||||
@ -357,10 +380,10 @@ async function checkForUpdatesAndShow() {
|
|||||||
|
|
||||||
// Version mismatch? Update!
|
// Version mismatch? Update!
|
||||||
if (manifest?.version !== NL_APPVERSION) {
|
if (manifest?.version !== NL_APPVERSION) {
|
||||||
subtitle.innerHTML = "New update available!"
|
subtitle.innerHTML = 'New update available!'
|
||||||
updateBtn.classList.remove('disabled')
|
updateBtn.classList.remove('disabled')
|
||||||
} else {
|
} else {
|
||||||
subtitle.innerHTML = "You are on the latest version! :)"
|
subtitle.innerHTML = 'You are on the latest version! :)'
|
||||||
updateBtn.classList.add('disabled')
|
updateBtn.classList.add('disabled')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -388,6 +411,8 @@ async function setGameExe() {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!gameExe[0]) return
|
||||||
|
|
||||||
// Set the folder in our configuration
|
// Set the folder in our configuration
|
||||||
const config = await getCfg()
|
const config = await getCfg()
|
||||||
|
|
||||||
@ -409,6 +434,8 @@ async function setGrasscutterFolder() {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!folder[0]) return
|
||||||
|
|
||||||
// Set the folder in our configuration
|
// Set the folder in our configuration
|
||||||
const config = await getCfg()
|
const config = await getCfg()
|
||||||
|
|
||||||
|
@ -2,99 +2,99 @@
|
|||||||
* Toggle the login section
|
* Toggle the login section
|
||||||
*/
|
*/
|
||||||
async function setLoginSection() {
|
async function setLoginSection() {
|
||||||
const title = document.getElementById('loginSectionTitle');
|
const title = document.getElementById('loginSectionTitle')
|
||||||
const altTitle = document.getElementById('registerSectionTitle');
|
const altTitle = document.getElementById('registerSectionTitle')
|
||||||
const loginSection = document.getElementById('loginPopupContentBody');
|
const loginSection = document.getElementById('loginPopupContentBody')
|
||||||
const registerSection = document.getElementById('registerPopupContentBody');
|
const registerSection = document.getElementById('registerPopupContentBody')
|
||||||
|
|
||||||
title.classList.add('selectedTitle')
|
title.classList.add('selectedTitle')
|
||||||
altTitle.classList.remove('selectedTitle')
|
altTitle.classList.remove('selectedTitle')
|
||||||
|
|
||||||
loginSection.style.removeProperty('display');
|
loginSection.style.removeProperty('display')
|
||||||
registerSection.style.display = 'none';
|
registerSection.style.display = 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle the register section
|
* Toggle the register section
|
||||||
*/
|
*/
|
||||||
async function setRegisterSection(fromLogin = false) {
|
async function setRegisterSection(fromLogin = false) {
|
||||||
const title = document.getElementById('registerSectionTitle');
|
const title = document.getElementById('registerSectionTitle')
|
||||||
const altTitle = document.getElementById('loginSectionTitle');
|
const altTitle = document.getElementById('loginSectionTitle')
|
||||||
const loginSection = document.getElementById('loginPopupContentBody');
|
const loginSection = document.getElementById('loginPopupContentBody')
|
||||||
const registerSection = document.getElementById('registerPopupContentBody');
|
const registerSection = document.getElementById('registerPopupContentBody')
|
||||||
|
|
||||||
title.classList.add('selectedTitle')
|
title.classList.add('selectedTitle')
|
||||||
altTitle.classList.remove('selectedTitle')
|
altTitle.classList.remove('selectedTitle')
|
||||||
|
|
||||||
loginSection.style.display = 'none';
|
loginSection.style.display = 'none'
|
||||||
registerSection.style.removeProperty('display');
|
registerSection.style.removeProperty('display')
|
||||||
|
|
||||||
if (fromLogin) {
|
if (fromLogin) {
|
||||||
// Take the values from the login section and put them in the register section
|
// Take the values from the login section and put them in the register section
|
||||||
const loginUsername = document.getElementById('loginUsername').value;
|
const loginUsername = document.getElementById('loginUsername').value
|
||||||
const loginPassword = document.getElementById('loginPassword').value;
|
const loginPassword = document.getElementById('loginPassword').value
|
||||||
|
|
||||||
document.getElementById('registerUsername').value = loginUsername;
|
document.getElementById('registerUsername').value = loginUsername
|
||||||
document.getElementById('registerPassword').value = loginPassword;
|
document.getElementById('registerPassword').value = loginPassword
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseJwt(token) {
|
function parseJwt(token) {
|
||||||
const base64Url = token.split('.')[1];
|
const base64Url = token.split('.')[1]
|
||||||
const base64 = base64Url.replace('-', '+').replace('_', '/');
|
const base64 = base64Url.replace('-', '+').replace('_', '/')
|
||||||
return JSON.parse(window.atob(base64));
|
return JSON.parse(window.atob(base64))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt login and launch game
|
* Attempt login and launch game
|
||||||
*/
|
*/
|
||||||
async function login() {
|
async function login() {
|
||||||
const username = document.getElementById('loginUsername').value;
|
const username = document.getElementById('loginUsername').value
|
||||||
const password = document.getElementById('loginPassword').value;
|
const password = document.getElementById('loginPassword').value
|
||||||
const ip = document.getElementById('ip').value;
|
const ip = document.getElementById('ip').value
|
||||||
const port = document.getElementById('port').value || '443';
|
const port = document.getElementById('port').value || '443'
|
||||||
const config = await getCfg();
|
const config = await getCfg()
|
||||||
const useHttps = config.useHttps;
|
const useHttps = config.useHttps
|
||||||
const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}`;
|
const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}`
|
||||||
|
|
||||||
const reqBody = {
|
const reqBody = {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = await axios.post(url + '/grasscutter/login', reqBody)
|
const { data } = await axios.post(url + '/authentication/login', reqBody)
|
||||||
|
|
||||||
switch(data.message) {
|
switch(data.message) {
|
||||||
case 'INVALID_ACCOUNT':
|
case 'INVALID_ACCOUNT':
|
||||||
displayLoginAlert(localeObj.alertInvalid || 'Invalid username or password', 'error');
|
displayLoginAlert(localeObj.alertInvalid || 'Invalid username or password', 'error')
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'NO_PASSWORD':
|
case 'NO_PASSWORD':
|
||||||
// No account password, create one with change password
|
// No account password, create one with change password
|
||||||
displayLoginAlert(localeObj.alertNoPass || 'No password set, please change password', 'warn');
|
displayLoginAlert(localeObj.alertNoPass || 'No password set, please change password', 'warn')
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'UNKNOWN':
|
case 'UNKNOWN':
|
||||||
// Unknown error, contact server owner
|
// Unknown error, contact server owner
|
||||||
displayLoginAlert(localeObj.alertUnknown || 'Unknown error, contact server owner', 'error');
|
displayLoginAlert(localeObj.alertUnknown || 'Unknown error, contact server owner', 'error')
|
||||||
break;
|
break
|
||||||
|
|
||||||
case undefined:
|
case undefined:
|
||||||
case null:
|
case null:
|
||||||
case 'AUTH_DISABLED':
|
case 'AUTH_DISABLED':
|
||||||
// Authentication is disabled, we can just connect the user
|
// Authentication is disabled, we can just connect the user
|
||||||
displayLoginAlert(localeObj.alertAuthNoLogin || 'Authentication is disabled, no need to log in!', 'warn');
|
displayLoginAlert(localeObj.alertAuthNoLogin || 'Authentication is disabled, no need to log in!', 'warn')
|
||||||
launchPrivate();
|
launchPrivate()
|
||||||
break;
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Success! Copy the JWT token to their clipboard
|
// Success! Copy the JWT token to their clipboard
|
||||||
const tkData = parseJwt(data.jwt)
|
const tkData = parseJwt(data.jwt)
|
||||||
await Neutralino.clipboard.writeText(tkData.token)
|
await Neutralino.clipboard.writeText(tkData.token)
|
||||||
|
|
||||||
displayLoginAlert(localeObj.alertLoginSuccess || 'Login successful! Token copied to clipboard. Paste this token into the username field of the game to log in.', 'success', 8000);
|
displayLoginAlert(localeObj.alertLoginSuccess || 'Login successful! Token copied to clipboard. Paste this token into the username field of the game to log in.', 'success', 8000)
|
||||||
launchPrivate()
|
launchPrivate()
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,14 +102,14 @@ async function login() {
|
|||||||
* Attempt registration, do not launch game
|
* Attempt registration, do not launch game
|
||||||
*/
|
*/
|
||||||
async function register() {
|
async function register() {
|
||||||
const username = document.getElementById('registerUsername').value;
|
const username = document.getElementById('registerUsername').value
|
||||||
const password = document.getElementById('registerPassword').value;
|
const password = document.getElementById('registerPassword').value
|
||||||
const password_confirmation = document.getElementById('registerPasswordConfirm').value;
|
const password_confirmation = document.getElementById('registerPasswordConfirm').value
|
||||||
const ip = document.getElementById('ip').value;
|
const ip = document.getElementById('ip').value
|
||||||
const port = document.getElementById('port').value || '443';
|
const port = document.getElementById('port').value || '443'
|
||||||
const config = await getCfg();
|
const config = await getCfg()
|
||||||
const useHttps = config.useHttps;
|
const useHttps = config.useHttps
|
||||||
const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}`;
|
const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}`
|
||||||
|
|
||||||
const reqBody = {
|
const reqBody = {
|
||||||
username,
|
username,
|
||||||
@ -117,38 +117,38 @@ async function register() {
|
|||||||
password_confirmation
|
password_confirmation
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = await axios.post(url + '/grasscutter/register', reqBody)
|
const { data } = await axios.post(url + '/authentication/register', reqBody)
|
||||||
|
|
||||||
switch(data.message) {
|
switch(data.message) {
|
||||||
case 'USERNAME_TAKEN':
|
case 'USERNAME_TAKEN':
|
||||||
// Username is taken
|
// Username is taken
|
||||||
displayRegisterAlert(localeObj.alertUserTaken || 'Username is taken', 'error');
|
displayRegisterAlert(localeObj.alertUserTaken || 'Username is taken', 'error')
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'PASSWORD_MISMATCH':
|
case 'PASSWORD_MISMATCH':
|
||||||
// The password and password confirmation do not match
|
// The password and password confirmation do not match
|
||||||
displayRegisterAlert(localStorage.alertPassMismatch || 'Password and password confirmation do not match', 'error');
|
displayRegisterAlert(localStorage.alertPassMismatch || 'Password and password confirmation do not match', 'error')
|
||||||
break;
|
break
|
||||||
|
|
||||||
case 'UNKNOWN':
|
case 'UNKNOWN':
|
||||||
// Unknown error, contact server owner
|
// Unknown error, contact server owner
|
||||||
displayRegisterAlert(localeObj.alertUnknown || 'Unknown error, contact server owner', 'error');
|
displayRegisterAlert(localeObj.alertUnknown || 'Unknown error, contact server owner', 'error')
|
||||||
break;
|
break
|
||||||
|
|
||||||
case undefined:
|
case undefined:
|
||||||
case null:
|
case null:
|
||||||
case 'AUTH_DISABLED':
|
case 'AUTH_DISABLED':
|
||||||
// Authentication is disabled, we can just connect the user
|
// Authentication is disabled, we can just connect the user
|
||||||
displayRegisterAlert(localeObj.alertAuthNoRegister || 'Authentication is disabled, no need to register!', 'warn');
|
displayRegisterAlert(localeObj.alertAuthNoRegister || 'Authentication is disabled, no need to register!', 'warn')
|
||||||
break;
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Success!! Bring them to the login screen and auto-input their username
|
// Success!! Bring them to the login screen and auto-input their username
|
||||||
const loginUsername = document.getElementById('loginUsername');
|
const loginUsername = document.getElementById('loginUsername')
|
||||||
loginUsername.value = username;
|
loginUsername.value = username
|
||||||
|
|
||||||
setLoginSection();
|
setLoginSection()
|
||||||
displayLoginAlert(localeObj.alertRegisterSuccess || 'Registration successful!', 'success', 5000);
|
displayLoginAlert(localeObj.alertRegisterSuccess || 'Registration successful!', 'success', 5000)
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
* Every autofill, such as backgrounds and the game folder,
|
* Every autofill, such as backgrounds and the game folder,
|
||||||
* should be done here to ensure DOM contents are loaded.
|
* should be done here to ensure DOM contents are loaded.
|
||||||
*/
|
*/
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
displayUpdate();
|
displayUpdate()
|
||||||
setBackgroundImage();
|
setBackgroundImage()
|
||||||
displayGameFolder();
|
displayGameFolder()
|
||||||
displayServerFolder();
|
displayServerFolder()
|
||||||
|
|
||||||
// Set title version
|
// Set title version
|
||||||
document.querySelector('#version').innerHTML = NL_APPVERSION
|
document.querySelector('#version').innerHTML = NL_APPVERSION
|
||||||
@ -35,9 +35,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Exit favorites list and settings panel when clicking outside of it
|
// Exit favorites list and settings panel when clicking outside of it
|
||||||
window.addEventListener("click", function(e) {
|
window.addEventListener('click', function(e) {
|
||||||
const favList = document.querySelector('#ipList')
|
const favList = document.querySelector('#ipList')
|
||||||
const settingsPanel = document.querySelector('#settingsPanel')
|
const settingsPanel = document.querySelector('#settingsPanel')
|
||||||
|
const downloadPanel = document.querySelector('#downloadPanel')
|
||||||
|
|
||||||
// This will close the favorites list no matter what is clicked
|
// This will close the favorites list no matter what is clicked
|
||||||
if (favList.style.display !== 'none') {
|
if (favList.style.display !== 'none') {
|
||||||
@ -46,25 +47,34 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This will close the settings panel no matter what is clicked
|
// This will close the settings panel no matter what is clicked
|
||||||
let settingCheckElm = e.target
|
let checkElm = e.target
|
||||||
|
|
||||||
while(settingCheckElm.tagName !== 'BODY') {
|
while(checkElm.tagName !== 'BODY') {
|
||||||
if (settingCheckElm.id === 'settingsPanel'
|
if (checkElm.id === 'settingsPanel'
|
||||||
|| settingCheckElm.id === 'settingsBtn') {
|
|| checkElm.id === 'settingsBtn') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
settingCheckElm = settingCheckElm.parentElement
|
if (checkElm.id === 'downloadPanel' ||
|
||||||
|
checkElm.id === 'downloadBtn') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
checkElm = checkElm.parentElement
|
||||||
}
|
}
|
||||||
|
|
||||||
// We travelled through the parents, so if we are at the body, we clicked outside of the settings panel
|
// We travelled through the parents, so if we are at the body, we clicked outside of the settings panel
|
||||||
if (settingCheckElm.tagName === 'BODY') {
|
if (checkElm.tagName === 'BODY') {
|
||||||
// This will close the settings panel only when something outside of it is clicked
|
// This will close the settings panel only when something outside of it is clicked
|
||||||
if (settingsPanel.style.display !== 'none') {
|
if (settingsPanel.style.display !== 'none') {
|
||||||
settingsPanel.style.display = 'none'
|
settingsPanel.style.display = 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (downloadPanel.style.display !== 'none') {
|
||||||
|
downloadPanel.style.display = 'none'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
// Ensure we do the translation at the very end, after everything else has loaded
|
// Ensure we do the translation at the very end, after everything else has loaded
|
||||||
await doTranslation()
|
await doTranslation()
|
||||||
|
@ -72,7 +72,7 @@ async function handleLanguageChange(elm) {
|
|||||||
/**
|
/**
|
||||||
* Toggle the use of HTTPS
|
* Toggle the use of HTTPS
|
||||||
*/
|
*/
|
||||||
async function toggleHttps() {
|
async function toggleHttps() {
|
||||||
const httpsCheckbox = document.querySelector('#httpsOption')
|
const httpsCheckbox = document.querySelector('#httpsOption')
|
||||||
const config = await getCfg()
|
const config = await getCfg()
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ async function handleLanguageChange(elm) {
|
|||||||
* OR
|
* OR
|
||||||
* Remove the current value of the IP input from the favorites list
|
* Remove the current value of the IP input from the favorites list
|
||||||
*/
|
*/
|
||||||
async function setFavorite() {
|
async function setFavorite() {
|
||||||
const ip = document.querySelector('#ip').value
|
const ip = document.querySelector('#ip').value
|
||||||
const port = document.querySelector('#port').value || '443'
|
const port = document.querySelector('#port').value || '443'
|
||||||
const ipArr = await getFavIps()
|
const ipArr = await getFavIps()
|
||||||
|
@ -90,6 +90,21 @@ async function doTranslation() {
|
|||||||
set('loginPopupContentBodyBtnRegister', 'authRegisterBtn')
|
set('loginPopupContentBodyBtnRegister', 'authRegisterBtn')
|
||||||
set('noLoginBtn', 'launchWithoutAuth')
|
set('noLoginBtn', 'launchWithoutAuth')
|
||||||
|
|
||||||
|
// Downloads section
|
||||||
|
set('downloadTitle', 'downloadTitle')
|
||||||
|
set('grassclipperTitle', 'grassclipperTitle')
|
||||||
|
set('grasscutterTitle', 'grasscutterTitle')
|
||||||
|
set('installerTitle', 'installerTitle')
|
||||||
|
set('installerSubtitle', 'installerSubtitle')
|
||||||
|
set('downloadStable', 'downloadStable')
|
||||||
|
set('stableSubtitle', 'stableSubtitle')
|
||||||
|
set('downloadDev', 'downloadDev')
|
||||||
|
set('devSubtitle', 'downloadSubtitle')
|
||||||
|
set('downloadResources', 'downloadResources')
|
||||||
|
set('devSubtitle', 'devSubtitle')
|
||||||
|
set('stableInstall', 'stableInstall')
|
||||||
|
set('devInstall', 'devInstall')
|
||||||
|
|
||||||
// update notification
|
// update notification
|
||||||
set('updateNotifText', 'updateNotifText')
|
set('updateNotifText', 'updateNotifText')
|
||||||
}
|
}
|
@ -1,25 +1,25 @@
|
|||||||
// https://stackoverflow.com/questions/67971689/positioning-the-borderless-window-in-neutralino-js
|
// https://stackoverflow.com/questions/67971689/positioning-the-borderless-window-in-neutralino-js
|
||||||
// had to use this since the in-built function breaks the close and minimize buttons
|
// had to use this since the in-built function breaks the close and minimize buttons
|
||||||
let dragging = false, ratio = 1, posX, posY;
|
let dragging = false, ratio = 1, posX, posY
|
||||||
let draggable;
|
let draggable
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
draggable = document.getElementById('controlBar');
|
draggable = document.getElementById('controlBar')
|
||||||
|
|
||||||
// Listen to hovers
|
// Listen to hovers
|
||||||
draggable.onmousedown = function (e) {
|
draggable.onmousedown = function (e) {
|
||||||
ratio = window.devicePixelRatio
|
ratio = window.devicePixelRatio
|
||||||
|
|
||||||
posX = e.pageX * ratio, posY = e.pageY * ratio;
|
posX = e.pageX * ratio, posY = e.pageY * ratio
|
||||||
dragging = true;
|
dragging = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patch for monitors with scaling enabled, allows them to detach from the titlebar anywhere
|
// Patch for monitors with scaling enabled, allows them to detach from the titlebar anywhere
|
||||||
window.onmouseup = function (e) {
|
window.onmouseup = function (e) {
|
||||||
dragging = false;
|
dragging = false
|
||||||
}
|
}
|
||||||
|
|
||||||
document.onmousemove = function (e) {
|
document.onmousemove = function (e) {
|
||||||
if (dragging) Neutralino.window.move(e.screenX * ratio - posX, e.screenY * ratio - posY);
|
if (dragging) Neutralino.window.move(e.screenX * ratio - posX, e.screenY * ratio - posY)
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -11,6 +11,10 @@ a {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.darken {
|
.darken {
|
||||||
filter: brightness(0.6);
|
filter: brightness(0.6);
|
||||||
}
|
}
|
||||||
@ -157,6 +161,7 @@ a {
|
|||||||
|
|
||||||
#firstTimeNotice,
|
#firstTimeNotice,
|
||||||
#loginPanel,
|
#loginPanel,
|
||||||
|
#downloadPanel,
|
||||||
#settingsPanel {
|
#settingsPanel {
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -172,18 +177,21 @@ a {
|
|||||||
font-family: system-ui;
|
font-family: system-ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#downloadPanel,
|
||||||
#settingsPanel {
|
#settingsPanel {
|
||||||
width: 35%;
|
width: 35%;
|
||||||
height: 80%;
|
height: 80%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#downloadTitle,
|
||||||
#fullSettingsTitle {
|
#fullSettingsTitle {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#downloadPanelInner,
|
||||||
#settingsPanelInner {
|
#settingsPanelInner {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -192,16 +200,23 @@ a {
|
|||||||
padding: 10px 10%;
|
padding: 10px 10%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.downloadRow,
|
||||||
.settingsRow {
|
.settingsRow {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.downloadTitle,
|
||||||
.settingTitle {
|
.settingTitle {
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.downloadTitle {
|
||||||
|
margin: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.downloadLabel,
|
||||||
.settingLabel {
|
.settingLabel {
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
@ -209,12 +224,14 @@ a {
|
|||||||
margin: 10px 0px;
|
margin: 10px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.downloadSubtitle,
|
||||||
.settingSubtitle {
|
.settingSubtitle {
|
||||||
color: rgb(165, 165, 165);
|
color: rgb(165, 165, 165);
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.downloadSection,
|
||||||
.settingSection {
|
.settingSection {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -222,10 +239,12 @@ a {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.downloadSection .smolBtn,
|
||||||
.settingSection .smolBtn {
|
.settingSection .smolBtn {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#downloadTitleBar,
|
||||||
#settingsTitleBar {
|
#settingsTitleBar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -233,15 +252,18 @@ a {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#downloadClose,
|
||||||
#settingsClose {
|
#settingsClose {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
transition: filter 0.1s ease-in-out;
|
transition: filter 0.1s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#downloadClose img,
|
||||||
#settingsClose img {
|
#settingsClose img {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#downloadClose:hover,
|
||||||
#settingsClose:hover {
|
#settingsClose:hover {
|
||||||
filter: invert(85%) sepia(31%) saturate(560%) hue-rotate(329deg) brightness(100%) contrast(92%);
|
filter: invert(85%) sepia(31%) saturate(560%) hue-rotate(329deg) brightness(100%) contrast(92%);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
58
scripts/gc_download.cmd
Normal file
58
scripts/gc_download.cmd
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set KEYSTORE_URL=%1
|
||||||
|
set ARTIFACT_URL=%2
|
||||||
|
set BRANCH=%3
|
||||||
|
set FOLDER_NAME=".\gc-%BRANCH%"
|
||||||
|
set FOLDER_NAME=%FOLDER_NAME:"=%
|
||||||
|
|
||||||
|
title GC Download Script
|
||||||
|
|
||||||
|
if not exist "%FOLDER_NAME%" mkdir "%FOLDER_NAME%"
|
||||||
|
if not exist ".\temp" mkdir ".\temp"
|
||||||
|
|
||||||
|
echo Downloading Grasscutter prebuilt jar...
|
||||||
|
|
||||||
|
:: Download the jar
|
||||||
|
powershell Invoke-WebRequest -Uri %KEYSTORE_URL% -OutFile "./temp/gcjar.zip"
|
||||||
|
|
||||||
|
echo Extracting...
|
||||||
|
|
||||||
|
:: Delete old file if there is one there
|
||||||
|
if exist "%FOLDER_NAME%\grasscutter.jar" del "%FOLDER_NAME%\grasscutter.jar"
|
||||||
|
|
||||||
|
powershell Expand-Archive -Path "./temp/gcjar.zip" -DestinationPath "%FOLDER_NAME%" -Force
|
||||||
|
|
||||||
|
:: Find the jar file name and rename it, just in case
|
||||||
|
for %%i in (%FOLDER_NAME%/*) do (
|
||||||
|
:: If the extension is jar, rename the file
|
||||||
|
if %%~xi equ .jar rename "%FOLDER_NAME%\%%i" grasscutter.jar
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Downloading keystore.p12...
|
||||||
|
|
||||||
|
:: Download the keystore.p12 file
|
||||||
|
powershell Invoke-WebRequest -Uri %ARTIFACT_URL% -OutFile "./%FOLDER_NAME%/keystore.p12"
|
||||||
|
|
||||||
|
:: Check java version, this will automatically output some tuff
|
||||||
|
call .\scripts\javaver.cmd %BRANCH%
|
||||||
|
|
||||||
|
:: Allow resource downloading to be optional, since it takes a while
|
||||||
|
set REPLY=y
|
||||||
|
set /p "REPLY=Download server resources? (This can take a while) [y|n]:"
|
||||||
|
if /i not "%reply%" == "y" goto :finish
|
||||||
|
|
||||||
|
call .\scripts\resources_download.cmd %FOLDER_NAME%
|
||||||
|
|
||||||
|
goto :finish
|
||||||
|
|
||||||
|
:finish
|
||||||
|
:: Remove temp stuff
|
||||||
|
del /s /q "./temp"
|
||||||
|
|
||||||
|
echo Done, latest Grasscutter %BRANCH% now downloaded in %FOLDER_NAME%
|
||||||
|
|
||||||
|
pause
|
||||||
|
|
||||||
|
taskkill /f /fi "WINDOWTITLE eq GC Download Script"
|
||||||
|
|
@ -3,6 +3,8 @@
|
|||||||
set ORIGIN=%1
|
set ORIGIN=%1
|
||||||
set ORIGIN=%ORIGIN:"=%
|
set ORIGIN=%ORIGIN:"=%
|
||||||
|
|
||||||
|
title Grassclipper Installer
|
||||||
|
|
||||||
echo Downloading proxy server...
|
echo Downloading proxy server...
|
||||||
|
|
||||||
:: Make sure we are in the right directory
|
:: Make sure we are in the right directory
|
||||||
@ -35,12 +37,12 @@ taskkill /f /im mitmdump.exe
|
|||||||
echo Adding ceritifcate...
|
echo Adding ceritifcate...
|
||||||
|
|
||||||
:: Ensure we are elevated for certs
|
:: Ensure we are elevated for certs
|
||||||
>nul 2>&1 certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer || (
|
>nul 2>&1 certutil -addstore root "%USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer" || (
|
||||||
echo ============================================================================================================
|
echo ============================================================================================================
|
||||||
echo !! Certificate install failed !!
|
echo !! Certificate install failed !!
|
||||||
echo.
|
echo.
|
||||||
echo Please manually run this command as Administrator:
|
echo Please manually run this command as Administrator:
|
||||||
echo certutil -addstore root %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer
|
echo certutil -addstore root "%USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.cer"
|
||||||
echo ============================================================================================================
|
echo ============================================================================================================
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,4 +50,4 @@ echo Done! You can now open GrassClipper.exe!
|
|||||||
|
|
||||||
pause
|
pause
|
||||||
|
|
||||||
exit /b
|
taskkill /f /fi "WINDOWTITLE eq Grassclipper Installer"
|
70
scripts/javaver.cmd
Normal file
70
scripts/javaver.cmd
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set BRANCH=%1
|
||||||
|
|
||||||
|
echo Checking java version...
|
||||||
|
|
||||||
|
where java >nul 2>nul
|
||||||
|
if %errorlevel%==1 (
|
||||||
|
echo =======================================================================================
|
||||||
|
echo No version of Java was found!
|
||||||
|
|
||||||
|
if %BRANCH% EQU stable (
|
||||||
|
echo To launch the stable branch server, you must install Java 8
|
||||||
|
)
|
||||||
|
|
||||||
|
if %BRANCH% EQU development (
|
||||||
|
echo To launch the development branch server, you must install Java 17
|
||||||
|
)
|
||||||
|
|
||||||
|
echo =======================================================================================
|
||||||
|
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
:: https://stackoverflow.com/questions/5675459/how-to-get-java-version-from-batch-script
|
||||||
|
for /f "tokens=3" %%g in ('java -version 2^>^&1 ^| findstr /i "version"') do (
|
||||||
|
@echo Output: %%g
|
||||||
|
set JAVAVER=%%g
|
||||||
|
)
|
||||||
|
set JAVAVER=%JAVAVER:"=%
|
||||||
|
|
||||||
|
for /f "delims=. tokens=1-3" %%v in ("%JAVAVER%") do (
|
||||||
|
set MAJOR=%%v
|
||||||
|
set MINOR=%%w
|
||||||
|
set BUILD=%%x
|
||||||
|
)
|
||||||
|
|
||||||
|
if %BRANCH% EQU stable (
|
||||||
|
:: Ensure java 8
|
||||||
|
if %MAJOR% EQU 1 (
|
||||||
|
if %MINOR% LSS 8 (
|
||||||
|
echo =======================================================================================
|
||||||
|
echo !! Java version is less than 8 !!
|
||||||
|
echo Please download Java 8 to ensure %BRANCH% branch server launches correctly.
|
||||||
|
echo =======================================================================================
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if %MAJOR% NEQ 1 (
|
||||||
|
echo =======================================================================================
|
||||||
|
echo !! Java version is not 8 !!
|
||||||
|
echo Please download Java 8 to ensure %BRANCH% branch server launches correctly.
|
||||||
|
echo =======================================================================================
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if %BRANCH% EQU development (
|
||||||
|
:: Ensure java 17
|
||||||
|
if %MAJOR% LSS 17 (
|
||||||
|
echo =======================================================================================
|
||||||
|
echo !! Java version is less than 17 !!
|
||||||
|
echo Please download Java 17 to ensure %BRANCH% branch server launches correctly.
|
||||||
|
echo =======================================================================================
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Java version is compatible
|
@ -3,15 +3,23 @@
|
|||||||
set GRASSCUTTER_JAR=%1
|
set GRASSCUTTER_JAR=%1
|
||||||
set GRASSCUTTER_JAR=%GRASSCUTTER_JAR:"=%
|
set GRASSCUTTER_JAR=%GRASSCUTTER_JAR:"=%
|
||||||
|
|
||||||
|
title Grasscutter
|
||||||
|
|
||||||
:: Get folder the jar is in
|
:: Get folder the jar is in
|
||||||
set "X=%GRASSCUTTER_JAR%"
|
set "X=%GRASSCUTTER_JAR%"
|
||||||
:l
|
:l
|
||||||
if "%X:~-1%"=="\" goto al
|
set IS_SLASH=false
|
||||||
set "X=%X:~0,-1%"
|
|
||||||
goto l
|
if "%X:~-1%"=="\" set IS_SLASH=true
|
||||||
|
if "%X:~-1%"=="/" set IS_SLASH=true
|
||||||
|
|
||||||
|
if %IS_SLASH% equ true goto al
|
||||||
|
|
||||||
|
set "X=%X:~0,-1%"
|
||||||
|
goto l
|
||||||
:al
|
:al
|
||||||
set "X=%X:~0,-1%"
|
set "X=%X:~0,-1%"
|
||||||
set "GRASSCUTTER_ROOT=%X%"
|
set "GRASSCUTTER_ROOT=%X%"
|
||||||
|
|
||||||
echo Starting local Grasscutter server...
|
echo Starting local Grasscutter server...
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ if "%ENABLE_KILLSWITCH%" EQU "true" (
|
|||||||
:: Restart in elevated if need be
|
:: Restart in elevated if need be
|
||||||
>nul 2>&1 reg query "HKU\S-1-5-19" || (
|
>nul 2>&1 reg query "HKU\S-1-5-19" || (
|
||||||
set params = %*:"="""%
|
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 %2 %3 "%4" ""%cd%/../"" %6", "", "runas", 1 >> "%temp%\getadmin.vbs" && "%temp%\getadmin.vbs" && taskkill /f /fi "WINDOWTITLE eq PS Launcher Script" && exit /b )
|
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 %2 %3 "%4" ""%cd%"" %6", "", "runas", 1 >> "%temp%\getadmin.vbs" && "%temp%\getadmin.vbs" && taskkill /f /fi "WINDOWTITLE eq PS Launcher Script" && exit /b )
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v Pr
|
|||||||
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /d "127.0.0.1:8080" /f >nul 2>nul
|
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /d "127.0.0.1:8080" /f >nul 2>nul
|
||||||
|
|
||||||
:: Start proxy server
|
:: Start proxy server
|
||||||
start "Proxy Server" "%ORIGIN%/ext/mitmdump.exe" -s "%ORIGIN%/proxy/proxy.py" -k --allow-hosts ".*\.yuanshen\.com|.*\.mihoyo\.com|.*\.hoyoverse\.com" --ssl-insecure --set ip=%IP% --set port=%PORT% --set use_https=%USE_HTTPS%
|
start "Proxy Server" "%ORIGIN%\ext\mitmdump.exe" -s "%ORIGIN%/proxy/proxy.py" -k --allow-hosts ".*\.yuanshen\.com|.*\.mihoyo\.com|.*\.hoyoverse\.com" --ssl-insecure --set ip=%IP% --set port=%PORT% --set use_https=%USE_HTTPS%
|
||||||
|
|
||||||
echo Opening %GAME_PATH%
|
echo Opening %GAME_PATH%
|
||||||
|
|
||||||
|
29
scripts/resources_download.cmd
Normal file
29
scripts/resources_download.cmd
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set FOLDER_NAME=%1
|
||||||
|
set FOLDER_NAME=%FOLDER_NAME:"=%
|
||||||
|
|
||||||
|
if not exist ".\temp" mkdir ".\temp"
|
||||||
|
if not exist ".\resources" mkdir ".\resources"
|
||||||
|
|
||||||
|
echo Downloading resources, this can take a while...
|
||||||
|
|
||||||
|
:: Grab the giant ass resource zip
|
||||||
|
powershell Invoke-WebRequest -Uri https://github.com/Koko-boya/Grasscutter_Resources/archive/refs/heads/main.zip -OutFile "./temp/resources.zip"
|
||||||
|
|
||||||
|
echo Extracting...
|
||||||
|
|
||||||
|
:: Extract resources to the folder
|
||||||
|
powershell Expand-Archive -Path "./temp/resources.zip" -DestinationPath "%FOLDER_NAME%" -Force
|
||||||
|
|
||||||
|
:: Delete old resources folder if there is one there
|
||||||
|
del /s /q "%FOLDER_NAME%\resources">nul
|
||||||
|
|
||||||
|
echo Moving resources to folder...
|
||||||
|
|
||||||
|
robocopy "%FOLDER_NAME%\Grasscutter_Resources-main\Resources" "%FOLDER_NAME%\resources" /E /MOVE>nul
|
||||||
|
|
||||||
|
:: Delete straggling files
|
||||||
|
del /s /q "%FOLDER_NAME%\Grasscutter_Resources-main"
|
||||||
|
|
||||||
|
echo Done, resources should be properly extracted
|
Loading…
Reference in New Issue
Block a user