mirror of
https://github.com/dscalzi/HeliosLauncher.git
synced 2024-12-22 11:42:14 -08:00
Merge branch 'master' into ms-login2.0
This commit is contained in:
commit
5fb312628a
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"env": {
|
"env": {
|
||||||
"es2017": true,
|
"es2022": true,
|
||||||
"node": true
|
"node": true
|
||||||
},
|
},
|
||||||
"extends": "eslint:recommended",
|
"extends": "eslint:recommended",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaVersion": 2019,
|
"ecmaVersion": 2022,
|
||||||
"sourceType": "module"
|
"sourceType": "module"
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
|||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<em><h5 align="center">(formerly Electron Launcher)</h5></em>
|
<em><h5 align="center">(formerly Electron Launcher)</h5></em>
|
||||||
|
|
||||||
[<p align="center"><img src="https://img.shields.io/github/workflow/status/dscalzi/HeliosLauncher/Build.svg?style=for-the-badge" alt="gh actions">](https://github.com/dscalzi/HeliosLauncher/actions) [<img src="https://img.shields.io/github/downloads/dscalzi/HeliosLauncher/total.svg?style=for-the-badge" alt="downloads">](https://github.com/dscalzi/HeliosLauncher/releases) <img src="https://forthebadge.com/images/badges/winter-is-coming.svg" height="28px" alt="winter-is-coming"></p>
|
[<p align="center"><img src="https://img.shields.io/github/actions/workflow/status/dscalzi/HeliosLauncher/build.yml?branch=master&style=for-the-badge" alt="gh actions">](https://github.com/dscalzi/HeliosLauncher/actions) [<img src="https://img.shields.io/github/downloads/dscalzi/HeliosLauncher/total.svg?style=for-the-badge" alt="downloads">](https://github.com/dscalzi/HeliosLauncher/releases) <img src="https://forthebadge.com/images/badges/winter-is-coming.svg" height="28px" alt="winter-is-coming"></p>
|
||||||
|
|
||||||
<p align="center">Join modded servers without worrying about installing Java, Forge, or other mods. We'll handle that for you.</p>
|
<p align="center">Join modded servers without worrying about installing Java, Forge, or other mods. We'll handle that for you.</p>
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ This section details the setup of a basic developmentment environment.
|
|||||||
|
|
||||||
**System Requirements**
|
**System Requirements**
|
||||||
|
|
||||||
* [Node.js][nodejs] v16
|
* [Node.js][nodejs] v18
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -1228,6 +1228,59 @@ body, button {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Selected server content container */
|
||||||
|
.settingsSelServContainer {
|
||||||
|
background: rgba(0, 0, 0, 0.25);
|
||||||
|
width: 75%;
|
||||||
|
border-radius: 3px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 15px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Div which will be populated with the selected server's information. */
|
||||||
|
.settingsSelServContent {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wrapper container for the switch server button. */
|
||||||
|
.settingsSwitchServerContainer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button to switch server configurations on the mods tab. */
|
||||||
|
.settingsSwitchServerButton {
|
||||||
|
opacity: 0;
|
||||||
|
border: 1px solid rgb(255, 255, 255);
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
background: none;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-family: 'Avenir Medium';
|
||||||
|
transition: 0.25s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.settingsSwitchServerButton:hover,
|
||||||
|
.settingsSwitchServerButton:focus {
|
||||||
|
box-shadow: 0px 0px 20px rgb(255, 255, 255);
|
||||||
|
background: rgba(255, 255, 255, 0.25);
|
||||||
|
}
|
||||||
|
.settingsSwitchServerButton:active {
|
||||||
|
box-shadow: 0px 0px 20px rgb(187, 187, 187);
|
||||||
|
background: rgba(187, 187, 187, 0.25);
|
||||||
|
border: 1px solid rgb(187, 187, 187);
|
||||||
|
color: rgb(187, 187, 187);
|
||||||
|
}
|
||||||
|
.settingsSelServContainer:hover .settingsSwitchServerButton {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove spin button from number inputs. */
|
/* Remove spin button from number inputs. */
|
||||||
#settingsContainer input[type=number]::-webkit-inner-spin-button {
|
#settingsContainer input[type=number]::-webkit-inner-spin-button {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
@ -1638,59 +1691,6 @@ input:checked + .toggleSwitchSlider:before {
|
|||||||
* Settings View (Mods Tab)
|
* Settings View (Mods Tab)
|
||||||
* * */
|
* * */
|
||||||
|
|
||||||
/* Selected server content container */
|
|
||||||
#settingsSelServContainer {
|
|
||||||
background: rgba(0, 0, 0, 0.25);
|
|
||||||
width: 75%;
|
|
||||||
border-radius: 3px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin: 15px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Div which will be populated with the selected server's information. */
|
|
||||||
#settingsSelServContent {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
padding: 5px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wrapper container for the switch server button. */
|
|
||||||
#settingsSwitchServerContainer {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Button to switch server configurations on the mods tab. */
|
|
||||||
#settingsSwitchServerButton {
|
|
||||||
opacity: 0;
|
|
||||||
border: 1px solid rgb(255, 255, 255);
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
background: none;
|
|
||||||
font-size: 12px;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-family: 'Avenir Medium';
|
|
||||||
transition: 0.25s ease;
|
|
||||||
cursor: pointer;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
#settingsSwitchServerButton:hover,
|
|
||||||
#settingsSwitchServerButton:focus {
|
|
||||||
box-shadow: 0px 0px 20px rgb(255, 255, 255);
|
|
||||||
background: rgba(255, 255, 255, 0.25);
|
|
||||||
}
|
|
||||||
#settingsSwitchServerButton:active {
|
|
||||||
box-shadow: 0px 0px 20px rgb(187, 187, 187);
|
|
||||||
background: rgba(187, 187, 187, 0.25);
|
|
||||||
border: 1px solid rgb(187, 187, 187);
|
|
||||||
color: rgb(187, 187, 187);
|
|
||||||
}
|
|
||||||
#settingsSelServContainer:hover #settingsSwitchServerButton {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main content container for the mod elements. */
|
/* Main content container for the mod elements. */
|
||||||
#settingsModsContainer {
|
#settingsModsContainer {
|
||||||
width: 75%;
|
width: 75%;
|
||||||
|
@ -6,8 +6,11 @@ if(target == null){
|
|||||||
}
|
}
|
||||||
let tracker = new target(...(process.argv.splice(3)))
|
let tracker = new target(...(process.argv.splice(3)))
|
||||||
|
|
||||||
|
const { LoggerUtil } = require('helios-core')
|
||||||
|
const logger = LoggerUtil.getLogger('AssetExec')
|
||||||
|
|
||||||
//const tracker = new AssetGuard(process.argv[2], process.argv[3])
|
//const tracker = new AssetGuard(process.argv[2], process.argv[3])
|
||||||
console.log('AssetExec Started')
|
logger.info('AssetExec Started')
|
||||||
|
|
||||||
// Temporary for debug purposes.
|
// Temporary for debug purposes.
|
||||||
process.on('unhandledRejection', r => console.log(r))
|
process.on('unhandledRejection', r => console.log(r))
|
||||||
@ -66,6 +69,6 @@ process.on('message', (msg) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
process.on('disconnect', () => {
|
process.on('disconnect', () => {
|
||||||
console.log('AssetExec Disconnected')
|
logger.info('AssetExec Disconnected')
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
})
|
})
|
@ -5,6 +5,8 @@ const child_process = require('child_process')
|
|||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
const EventEmitter = require('events')
|
const EventEmitter = require('events')
|
||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
|
const { LoggerUtil } = require('helios-core')
|
||||||
|
const nodeDiskInfo = require('node-disk-info')
|
||||||
const StreamZip = require('node-stream-zip')
|
const StreamZip = require('node-stream-zip')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const Registry = require('winreg')
|
const Registry = require('winreg')
|
||||||
@ -16,6 +18,8 @@ const ConfigManager = require('./configmanager')
|
|||||||
const DistroManager = require('./distromanager')
|
const DistroManager = require('./distromanager')
|
||||||
const isDev = require('./isdev')
|
const isDev = require('./isdev')
|
||||||
|
|
||||||
|
const isARM64 = process.arch === 'arm64'
|
||||||
|
|
||||||
// Classes
|
// Classes
|
||||||
|
|
||||||
/** Class representing a base asset. */
|
/** Class representing a base asset. */
|
||||||
@ -214,6 +218,7 @@ class JavaGuard extends EventEmitter {
|
|||||||
constructor(mcVersion){
|
constructor(mcVersion){
|
||||||
super()
|
super()
|
||||||
this.mcVersion = mcVersion
|
this.mcVersion = mcVersion
|
||||||
|
this.logger = LoggerUtil.getLogger('JavaGuard')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -299,7 +304,8 @@ class JavaGuard extends EventEmitter {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = `https://corretto.aws/downloads/latest/amazon-corretto-${major}-x64-${sanitizedOS}-jdk.${ext}`
|
const arch = isARM64 ? 'aarch64' : 'x64'
|
||||||
|
const url = `https://corretto.aws/downloads/latest/amazon-corretto-${major}-${arch}-${sanitizedOS}-jdk.${ext}`
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
request.head({url, json: true}, (err, resp) => {
|
request.head({url, json: true}, (err, resp) => {
|
||||||
@ -342,6 +348,9 @@ class JavaGuard extends EventEmitter {
|
|||||||
* @returns {boolean} True if the path points to a Java executable, otherwise false.
|
* @returns {boolean} True if the path points to a Java executable, otherwise false.
|
||||||
*/
|
*/
|
||||||
static isJavaExecPath(pth){
|
static isJavaExecPath(pth){
|
||||||
|
if(pth == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if(process.platform === 'win32'){
|
if(process.platform === 'win32'){
|
||||||
return pth.endsWith(path.join('bin', 'javaw.exe'))
|
return pth.endsWith(path.join('bin', 'javaw.exe'))
|
||||||
} else if(process.platform === 'darwin'){
|
} else if(process.platform === 'darwin'){
|
||||||
@ -447,7 +456,7 @@ class JavaGuard extends EventEmitter {
|
|||||||
if(props[i].indexOf('sun.arch.data.model') > -1){
|
if(props[i].indexOf('sun.arch.data.model') > -1){
|
||||||
let arch = props[i].split('=')[1].trim()
|
let arch = props[i].split('=')[1].trim()
|
||||||
arch = parseInt(arch)
|
arch = parseInt(arch)
|
||||||
console.log(props[i].trim())
|
this.logger.debug(props[i].trim())
|
||||||
if(arch === 64){
|
if(arch === 64){
|
||||||
meta.arch = arch
|
meta.arch = arch
|
||||||
++checksum
|
++checksum
|
||||||
@ -457,10 +466,15 @@ class JavaGuard extends EventEmitter {
|
|||||||
}
|
}
|
||||||
} else if(props[i].indexOf('java.runtime.version') > -1){
|
} else if(props[i].indexOf('java.runtime.version') > -1){
|
||||||
let verString = props[i].split('=')[1].trim()
|
let verString = props[i].split('=')[1].trim()
|
||||||
console.log(props[i].trim())
|
this.logger.debug(props[i].trim())
|
||||||
const verOb = JavaGuard.parseJavaRuntimeVersion(verString)
|
const verOb = JavaGuard.parseJavaRuntimeVersion(verString)
|
||||||
|
// TODO implement a support matrix eventually. Right now this is good enough
|
||||||
|
// 1.7-1.16 = Java 8
|
||||||
|
// 1.17+ = Java 17
|
||||||
|
// Actual support may vary, but we're going with this rule for simplicity.
|
||||||
if(verOb.major < 9){
|
if(verOb.major < 9){
|
||||||
// Java 8
|
// Java 8
|
||||||
|
if(!Util.mcVersionAtLeast('1.17', this.mcVersion)){
|
||||||
if(verOb.major === 8 && verOb.update > 52){
|
if(verOb.major === 8 && verOb.update > 52){
|
||||||
meta.version = verOb
|
meta.version = verOb
|
||||||
++checksum
|
++checksum
|
||||||
@ -468,22 +482,24 @@ class JavaGuard extends EventEmitter {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
} else if(verOb.major >= 17) {
|
||||||
// Java 9+
|
// Java 9+
|
||||||
if(Util.mcVersionAtLeast('1.13', this.mcVersion)){
|
if(Util.mcVersionAtLeast('1.17', this.mcVersion)){
|
||||||
console.log('Java 9+ not yet tested.')
|
meta.version = verOb
|
||||||
/* meta.version = verOb
|
|
||||||
++checksum
|
++checksum
|
||||||
if(checksum === goal){
|
if(checksum === goal){
|
||||||
break
|
break
|
||||||
} */
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Space included so we get only the vendor.
|
// Space included so we get only the vendor.
|
||||||
} else if(props[i].lastIndexOf('java.vendor ') > -1) {
|
} else if(props[i].lastIndexOf('java.vendor ') > -1) {
|
||||||
let vendorName = props[i].split('=')[1].trim()
|
let vendorName = props[i].split('=')[1].trim()
|
||||||
console.log(props[i].trim())
|
this.logger.debug(props[i].trim())
|
||||||
meta.vendor = vendorName
|
meta.vendor = vendorName
|
||||||
|
} else if (props[i].indexOf('os.arch') > -1) {
|
||||||
|
meta.isARM = props[i].split('=')[1].trim() === 'aarch64'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,7 +528,7 @@ class JavaGuard extends EventEmitter {
|
|||||||
resolve({valid: false})
|
resolve({valid: false})
|
||||||
} else if(fs.existsSync(binaryExecPath)){
|
} else if(fs.existsSync(binaryExecPath)){
|
||||||
// Workaround (javaw.exe no longer outputs this information.)
|
// Workaround (javaw.exe no longer outputs this information.)
|
||||||
console.log(typeof binaryExecPath)
|
this.logger.debug(typeof binaryExecPath)
|
||||||
if(binaryExecPath.indexOf('javaw.exe') > -1) {
|
if(binaryExecPath.indexOf('javaw.exe') > -1) {
|
||||||
binaryExecPath.replace('javaw.exe', 'java.exe')
|
binaryExecPath.replace('javaw.exe', 'java.exe')
|
||||||
}
|
}
|
||||||
@ -804,15 +820,22 @@ class JavaGuard extends EventEmitter {
|
|||||||
// Get possible paths from the registry.
|
// Get possible paths from the registry.
|
||||||
let pathSet1 = await JavaGuard._scanRegistry()
|
let pathSet1 = await JavaGuard._scanRegistry()
|
||||||
if(pathSet1.size === 0){
|
if(pathSet1.size === 0){
|
||||||
|
|
||||||
// Do a manual file system scan of program files.
|
// Do a manual file system scan of program files.
|
||||||
|
// Check all drives
|
||||||
|
const driveMounts = nodeDiskInfo.getDiskInfoSync().map(({ mounted }) => mounted)
|
||||||
|
for(const mount of driveMounts) {
|
||||||
pathSet1 = new Set([
|
pathSet1 = new Set([
|
||||||
...pathSet1,
|
...pathSet1,
|
||||||
...(await JavaGuard._scanFileSystem('C:\\Program Files\\Java')),
|
...(await JavaGuard._scanFileSystem(`${mount}\\Program Files\\Java`)),
|
||||||
...(await JavaGuard._scanFileSystem('C:\\Program Files\\Eclipse Foundation')),
|
...(await JavaGuard._scanFileSystem(`${mount}\\Program Files\\Eclipse Adoptium`)),
|
||||||
...(await JavaGuard._scanFileSystem('C:\\Program Files\\AdoptOpenJDK'))
|
...(await JavaGuard._scanFileSystem(`${mount}\\Program Files\\Eclipse Foundation`)),
|
||||||
|
...(await JavaGuard._scanFileSystem(`${mount}\\Program Files\\AdoptOpenJDK`))
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Get possible paths from the data directory.
|
// Get possible paths from the data directory.
|
||||||
const pathSet2 = await JavaGuard._scanFileSystem(path.join(dataDir, 'runtime', 'x64'))
|
const pathSet2 = await JavaGuard._scanFileSystem(path.join(dataDir, 'runtime', 'x64'))
|
||||||
|
|
||||||
@ -848,6 +871,9 @@ class JavaGuard extends EventEmitter {
|
|||||||
* @param {string} dataDir The base launcher directory.
|
* @param {string} dataDir The base launcher directory.
|
||||||
* @returns {Promise.<string>} A Promise which resolves to the executable path of a valid
|
* @returns {Promise.<string>} A Promise which resolves to the executable path of a valid
|
||||||
* x64 Java installation. If none are found, null is returned.
|
* x64 Java installation. If none are found, null is returned.
|
||||||
|
*
|
||||||
|
* Added: On the system with ARM architecture attempts to find aarch64 Java.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
async _darwinJavaValidate(dataDir){
|
async _darwinJavaValidate(dataDir){
|
||||||
|
|
||||||
@ -876,7 +902,16 @@ class JavaGuard extends EventEmitter {
|
|||||||
pathArr = JavaGuard._sortValidJavaArray(pathArr)
|
pathArr = JavaGuard._sortValidJavaArray(pathArr)
|
||||||
|
|
||||||
if(pathArr.length > 0){
|
if(pathArr.length > 0){
|
||||||
return pathArr[0].execPath
|
|
||||||
|
// TODO Revise this a bit, seems to work for now. Discovery logic should
|
||||||
|
// probably just filter out the invalid architectures before it even
|
||||||
|
// gets to this point.
|
||||||
|
if (isARM64) {
|
||||||
|
return pathArr.find(({ isARM }) => isARM)?.execPath ?? null
|
||||||
|
} else {
|
||||||
|
return pathArr.find(({ isARM }) => !isARM)?.execPath ?? null
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -942,6 +977,8 @@ class JavaGuard extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
class AssetGuard extends EventEmitter {
|
class AssetGuard extends EventEmitter {
|
||||||
|
|
||||||
|
static logger = LoggerUtil.getLogger('AssetGuard')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of AssetGuard.
|
* Create an instance of AssetGuard.
|
||||||
* On creation the object's properties are never-null default
|
* On creation the object's properties are never-null default
|
||||||
@ -1100,7 +1137,8 @@ class AssetGuard extends EventEmitter {
|
|||||||
* @returns {Promise.<void>} An empty promise to indicate the extraction has completed.
|
* @returns {Promise.<void>} An empty promise to indicate the extraction has completed.
|
||||||
*/
|
*/
|
||||||
static _extractPackXZ(filePaths, javaExecutable){
|
static _extractPackXZ(filePaths, javaExecutable){
|
||||||
console.log('[PackXZExtract] Starting')
|
const extractLogger = LoggerUtil.getLogger('PackXZExtract')
|
||||||
|
extractLogger.info('Starting')
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
let libPath
|
let libPath
|
||||||
@ -1117,13 +1155,13 @@ class AssetGuard extends EventEmitter {
|
|||||||
const filePath = filePaths.join(',')
|
const filePath = filePaths.join(',')
|
||||||
const child = child_process.spawn(javaExecutable, ['-jar', libPath, '-packxz', filePath])
|
const child = child_process.spawn(javaExecutable, ['-jar', libPath, '-packxz', filePath])
|
||||||
child.stdout.on('data', (data) => {
|
child.stdout.on('data', (data) => {
|
||||||
console.log('[PackXZExtract]', data.toString('utf8'))
|
extractLogger.info(data.toString('utf8'))
|
||||||
})
|
})
|
||||||
child.stderr.on('data', (data) => {
|
child.stderr.on('data', (data) => {
|
||||||
console.log('[PackXZExtract]', data.toString('utf8'))
|
extractLogger.info(data.toString('utf8'))
|
||||||
})
|
})
|
||||||
child.on('close', (code, signal) => {
|
child.on('close', (code, signal) => {
|
||||||
console.log('[PackXZExtract]', 'Exited with code', code)
|
extractLogger.info('Exited with code', code)
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1189,7 +1227,7 @@ class AssetGuard extends EventEmitter {
|
|||||||
if(!fs.existsSync(versionFile) || force){
|
if(!fs.existsSync(versionFile) || force){
|
||||||
const url = await self._getVersionDataUrl(version)
|
const url = await self._getVersionDataUrl(version)
|
||||||
//This download will never be tracked as it's essential and trivial.
|
//This download will never be tracked as it's essential and trivial.
|
||||||
console.log('Preparing download of ' + version + ' assets.')
|
AssetGuard.logger.info('Preparing download of ' + version + ' assets.')
|
||||||
fs.ensureDirSync(versionPath)
|
fs.ensureDirSync(versionPath)
|
||||||
const stream = request(url).pipe(fs.createWriteStream(versionFile))
|
const stream = request(url).pipe(fs.createWriteStream(versionFile))
|
||||||
stream.on('finish', () => {
|
stream.on('finish', () => {
|
||||||
@ -1271,7 +1309,7 @@ class AssetGuard extends EventEmitter {
|
|||||||
|
|
||||||
let data = null
|
let data = null
|
||||||
if(!fs.existsSync(assetIndexLoc) || force){
|
if(!fs.existsSync(assetIndexLoc) || force){
|
||||||
console.log('Downloading ' + versionData.id + ' asset index.')
|
AssetGuard.logger.info('Downloading ' + versionData.id + ' asset index.')
|
||||||
fs.ensureDirSync(indexPath)
|
fs.ensureDirSync(indexPath)
|
||||||
const stream = request(assetIndex.url).pipe(fs.createWriteStream(assetIndexLoc))
|
const stream = request(assetIndex.url).pipe(fs.createWriteStream(assetIndexLoc))
|
||||||
stream.on('finish', () => {
|
stream.on('finish', () => {
|
||||||
@ -1542,9 +1580,10 @@ class AssetGuard extends EventEmitter {
|
|||||||
// Java (Category=''') Validation (download) Functions
|
// Java (Category=''') Validation (download) Functions
|
||||||
// #region
|
// #region
|
||||||
|
|
||||||
_enqueueOpenJDK(dataDir){
|
_enqueueOpenJDK(dataDir, mcVersion){
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
JavaGuard._latestOpenJDK('8').then(verData => {
|
const major = Util.mcVersionAtLeast('1.17', mcVersion) ? '17' : '8'
|
||||||
|
JavaGuard._latestOpenJDK(major).then(verData => {
|
||||||
if(verData != null){
|
if(verData != null){
|
||||||
|
|
||||||
dataDir = path.join(dataDir, 'runtime', 'x64')
|
dataDir = path.join(dataDir, 'runtime', 'x64')
|
||||||
@ -1559,9 +1598,9 @@ class AssetGuard extends EventEmitter {
|
|||||||
// Tar.gz
|
// Tar.gz
|
||||||
let h = null
|
let h = null
|
||||||
fs.createReadStream(a.to)
|
fs.createReadStream(a.to)
|
||||||
.on('error', err => console.log(err))
|
.on('error', err => AssetGuard.logger.error(err))
|
||||||
.pipe(zlib.createGunzip())
|
.pipe(zlib.createGunzip())
|
||||||
.on('error', err => console.log(err))
|
.on('error', err => AssetGuard.logger.error(err))
|
||||||
.pipe(tar.extract(dataDir, {
|
.pipe(tar.extract(dataDir, {
|
||||||
map: (header) => {
|
map: (header) => {
|
||||||
if(h == null){
|
if(h == null){
|
||||||
@ -1569,11 +1608,11 @@ class AssetGuard extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.on('error', err => console.log(err))
|
.on('error', err => AssetGuard.logger.error(err))
|
||||||
.on('finish', () => {
|
.on('finish', () => {
|
||||||
fs.unlink(a.to, err => {
|
fs.unlink(a.to, err => {
|
||||||
if(err){
|
if(err){
|
||||||
console.log(err)
|
AssetGuard.logger.error(err)
|
||||||
}
|
}
|
||||||
if(h.indexOf('/') > -1){
|
if(h.indexOf('/') > -1){
|
||||||
h = h.substring(0, h.indexOf('/'))
|
h = h.substring(0, h.indexOf('/'))
|
||||||
@ -1606,14 +1645,14 @@ class AssetGuard extends EventEmitter {
|
|||||||
const entries = await zip.entries()
|
const entries = await zip.entries()
|
||||||
pos = path.join(runtimeDir, Object.keys(entries)[0])
|
pos = path.join(runtimeDir, Object.keys(entries)[0])
|
||||||
|
|
||||||
console.log('Extracting jdk..')
|
AssetGuard.logger.info('Extracting jdk..')
|
||||||
await zip.extract(null, runtimeDir)
|
await zip.extract(null, runtimeDir)
|
||||||
console.log('Cleaning up..')
|
AssetGuard.logger.info('Cleaning up..')
|
||||||
await fs.remove(zipPath)
|
await fs.remove(zipPath)
|
||||||
console.log('Jdk extraction complete.')
|
AssetGuard.logger.info('Jdk extraction complete.')
|
||||||
|
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.log(err)
|
AssetGuard.logger.error(err)
|
||||||
} finally {
|
} finally {
|
||||||
zip.close()
|
zip.close()
|
||||||
self.emit('complete', 'java', JavaGuard.javaExecFromRoot(pos))
|
self.emit('complete', 'java', JavaGuard.javaExecFromRoot(pos))
|
||||||
@ -1679,7 +1718,7 @@ class AssetGuard extends EventEmitter {
|
|||||||
const dlQueue = dlTracker.dlqueue
|
const dlQueue = dlTracker.dlqueue
|
||||||
|
|
||||||
if(dlQueue.length > 0){
|
if(dlQueue.length > 0){
|
||||||
console.log('DLQueue', dlQueue)
|
AssetGuard.logger.info('DLQueue', dlQueue)
|
||||||
|
|
||||||
async.eachLimit(dlQueue, limit, (asset, cb) => {
|
async.eachLimit(dlQueue, limit, (asset, cb) => {
|
||||||
|
|
||||||
@ -1696,7 +1735,7 @@ class AssetGuard extends EventEmitter {
|
|||||||
const contentLength = parseInt(resp.headers['content-length'])
|
const contentLength = parseInt(resp.headers['content-length'])
|
||||||
|
|
||||||
if(contentLength !== asset.size){
|
if(contentLength !== asset.size){
|
||||||
console.log(`WARN: Got ${contentLength} bytes for ${asset.id}: Expected ${asset.size}`)
|
AssetGuard.logger.warn(`WARN: Got ${contentLength} bytes for ${asset.id}: Expected ${asset.size}`)
|
||||||
doHashCheck = true
|
doHashCheck = true
|
||||||
|
|
||||||
// Adjust download
|
// Adjust download
|
||||||
@ -1713,9 +1752,9 @@ class AssetGuard extends EventEmitter {
|
|||||||
if(doHashCheck){
|
if(doHashCheck){
|
||||||
const v = AssetGuard._validateLocal(asset.to, asset.type != null ? 'md5' : 'sha1', asset.hash)
|
const v = AssetGuard._validateLocal(asset.to, asset.type != null ? 'md5' : 'sha1', asset.hash)
|
||||||
if(v){
|
if(v){
|
||||||
console.log(`Hashes match for ${asset.id}, byte mismatch is an issue in the distro index.`)
|
AssetGuard.logger.warn(`Hashes match for ${asset.id}, byte mismatch is an issue in the distro index.`)
|
||||||
} else {
|
} else {
|
||||||
console.error(`Hashes do not match, ${asset.id} may be corrupted.`)
|
AssetGuard.logger.error(`Hashes do not match, ${asset.id} may be corrupted.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1727,7 +1766,7 @@ class AssetGuard extends EventEmitter {
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
req.abort()
|
req.abort()
|
||||||
console.log(`Failed to download ${asset.id}(${typeof asset.from === 'object' ? asset.from.url : asset.from}). Response code ${resp.statusCode}`)
|
AssetGuard.logger.error(`Failed to download ${asset.id}(${typeof asset.from === 'object' ? asset.from.url : asset.from}). Response code ${resp.statusCode}`)
|
||||||
self.progress += asset.size*1
|
self.progress += asset.size*1
|
||||||
self.emit('progress', 'download', self.progress, self.totaldlsize)
|
self.emit('progress', 'download', self.progress, self.totaldlsize)
|
||||||
cb()
|
cb()
|
||||||
@ -1748,9 +1787,9 @@ class AssetGuard extends EventEmitter {
|
|||||||
}, (err) => {
|
}, (err) => {
|
||||||
|
|
||||||
if(err){
|
if(err){
|
||||||
console.log('An item in ' + identifier + ' failed to process')
|
AssetGuard.logger.warn('An item in ' + identifier + ' failed to process')
|
||||||
} else {
|
} else {
|
||||||
console.log('All ' + identifier + ' have been processed successfully')
|
AssetGuard.logger.info('All ' + identifier + ' have been processed successfully')
|
||||||
}
|
}
|
||||||
|
|
||||||
//self.totaldlsize -= dlTracker.dlsize
|
//self.totaldlsize -= dlTracker.dlsize
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
|
const { LoggerUtil } = require('helios-core')
|
||||||
const os = require('os')
|
const os = require('os')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
const logger = require('./loggerutil')('%c[ConfigManager]', 'color: #a02d2a; font-weight: bold')
|
const logger = LoggerUtil.getLogger('ConfigManager')
|
||||||
|
|
||||||
const sysRoot = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME)
|
const sysRoot = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME)
|
||||||
// TODO change
|
// TODO change
|
||||||
@ -63,6 +64,27 @@ function resolveMinRAM(){
|
|||||||
return resolveMaxRAM()
|
return resolveMaxRAM()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO Copy pasted, should be in a utility file.
|
||||||
|
*
|
||||||
|
* Returns true if the actual version is greater than
|
||||||
|
* or equal to the desired version.
|
||||||
|
*
|
||||||
|
* @param {string} desired The desired version.
|
||||||
|
* @param {string} actual The actual version.
|
||||||
|
*/
|
||||||
|
function mcVersionAtLeast(desired, actual){
|
||||||
|
const des = desired.split('.')
|
||||||
|
const act = actual.split('.')
|
||||||
|
|
||||||
|
for(let i=0; i<des.length; i++){
|
||||||
|
if(!(parseInt(act[i]) >= parseInt(des[i]))){
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Three types of values:
|
* Three types of values:
|
||||||
* Static = Explicitly declared.
|
* Static = Explicitly declared.
|
||||||
@ -71,17 +93,6 @@ function resolveMinRAM(){
|
|||||||
*/
|
*/
|
||||||
const DEFAULT_CONFIG = {
|
const DEFAULT_CONFIG = {
|
||||||
settings: {
|
settings: {
|
||||||
java: {
|
|
||||||
minRAM: resolveMinRAM(),
|
|
||||||
maxRAM: resolveMaxRAM(), // Dynamic
|
|
||||||
executable: null,
|
|
||||||
jvmOptions: [
|
|
||||||
'-XX:+UseConcMarkSweepGC',
|
|
||||||
'-XX:+CMSIncrementalMode',
|
|
||||||
'-XX:-UseAdaptiveSizePolicy',
|
|
||||||
'-Xmn128M'
|
|
||||||
],
|
|
||||||
},
|
|
||||||
game: {
|
game: {
|
||||||
resWidth: 1280,
|
resWidth: 1280,
|
||||||
resHeight: 720,
|
resHeight: 720,
|
||||||
@ -103,7 +114,8 @@ const DEFAULT_CONFIG = {
|
|||||||
selectedServer: null, // Resolved
|
selectedServer: null, // Resolved
|
||||||
selectedAccount: null,
|
selectedAccount: null,
|
||||||
authenticationDatabase: {},
|
authenticationDatabase: {},
|
||||||
modConfigurations: []
|
modConfigurations: [],
|
||||||
|
javaConfig: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let config = null
|
let config = null
|
||||||
@ -144,8 +156,8 @@ exports.load = function(){
|
|||||||
doValidate = true
|
doValidate = true
|
||||||
} catch (err){
|
} catch (err){
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
logger.log('Configuration file contains malformed JSON or is corrupt.')
|
logger.info('Configuration file contains malformed JSON or is corrupt.')
|
||||||
logger.log('Generating a new configuration file.')
|
logger.info('Generating a new configuration file.')
|
||||||
fs.ensureDirSync(path.join(configPath, '..'))
|
fs.ensureDirSync(path.join(configPath, '..'))
|
||||||
config = DEFAULT_CONFIG
|
config = DEFAULT_CONFIG
|
||||||
exports.save()
|
exports.save()
|
||||||
@ -155,7 +167,7 @@ exports.load = function(){
|
|||||||
exports.save()
|
exports.save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.log('Successfully Loaded')
|
logger.info('Successfully Loaded')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -177,7 +189,7 @@ function validateKeySet(srcObj, destObj){
|
|||||||
if(srcObj == null){
|
if(srcObj == null){
|
||||||
srcObj = {}
|
srcObj = {}
|
||||||
}
|
}
|
||||||
const validationBlacklist = ['authenticationDatabase']
|
const validationBlacklist = ['authenticationDatabase', 'javaConfig']
|
||||||
const keys = Object.keys(srcObj)
|
const keys = Object.keys(srcObj)
|
||||||
for(let i=0; i<keys.length; i++){
|
for(let i=0; i<keys.length; i++){
|
||||||
if(typeof destObj[keys[i]] === 'undefined'){
|
if(typeof destObj[keys[i]] === 'undefined'){
|
||||||
@ -511,16 +523,66 @@ exports.setModConfiguration = function(serverid, configuration){
|
|||||||
|
|
||||||
// Java Settings
|
// Java Settings
|
||||||
|
|
||||||
|
function defaultJavaConfig(mcVersion) {
|
||||||
|
if(mcVersionAtLeast('1.17', mcVersion)) {
|
||||||
|
return defaultJavaConfig117()
|
||||||
|
} else {
|
||||||
|
return defaultJavaConfigBelow117()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultJavaConfigBelow117() {
|
||||||
|
return {
|
||||||
|
minRAM: resolveMinRAM(),
|
||||||
|
maxRAM: resolveMaxRAM(), // Dynamic
|
||||||
|
executable: null,
|
||||||
|
jvmOptions: [
|
||||||
|
'-XX:+UseConcMarkSweepGC',
|
||||||
|
'-XX:+CMSIncrementalMode',
|
||||||
|
'-XX:-UseAdaptiveSizePolicy',
|
||||||
|
'-Xmn128M'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultJavaConfig117() {
|
||||||
|
return {
|
||||||
|
minRAM: resolveMinRAM(),
|
||||||
|
maxRAM: resolveMaxRAM(), // Dynamic
|
||||||
|
executable: null,
|
||||||
|
jvmOptions: [
|
||||||
|
'-XX:+UnlockExperimentalVMOptions',
|
||||||
|
'-XX:+UseG1GC',
|
||||||
|
'-XX:G1NewSizePercent=20',
|
||||||
|
'-XX:G1ReservePercent=20',
|
||||||
|
'-XX:MaxGCPauseMillis=50',
|
||||||
|
'-XX:G1HeapRegionSize=32M'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure a java config property is set for the given server.
|
||||||
|
*
|
||||||
|
* @param {string} serverid The server id.
|
||||||
|
* @param {*} mcVersion The minecraft version of the server.
|
||||||
|
*/
|
||||||
|
exports.ensureJavaConfig = function(serverid, mcVersion) {
|
||||||
|
if(!Object.prototype.hasOwnProperty.call(config.javaConfig, serverid)) {
|
||||||
|
config.javaConfig[serverid] = defaultJavaConfig(mcVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the minimum amount of memory for JVM initialization. This value
|
* Retrieve the minimum amount of memory for JVM initialization. This value
|
||||||
* contains the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
|
* contains the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
|
||||||
* 1024 MegaBytes, etc.
|
* 1024 MegaBytes, etc.
|
||||||
*
|
*
|
||||||
* @param {boolean} def Optional. If true, the default value will be returned.
|
* @param {string} serverid The server id.
|
||||||
* @returns {string} The minimum amount of memory for JVM initialization.
|
* @returns {string} The minimum amount of memory for JVM initialization.
|
||||||
*/
|
*/
|
||||||
exports.getMinRAM = function(def = false){
|
exports.getMinRAM = function(serverid){
|
||||||
return !def ? config.settings.java.minRAM : DEFAULT_CONFIG.settings.java.minRAM
|
return config.javaConfig[serverid].minRAM
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -528,10 +590,11 @@ exports.getMinRAM = function(def = false){
|
|||||||
* contain the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
|
* contain the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
|
||||||
* 1024 MegaBytes, etc.
|
* 1024 MegaBytes, etc.
|
||||||
*
|
*
|
||||||
|
* @param {string} serverid The server id.
|
||||||
* @param {string} minRAM The new minimum amount of memory for JVM initialization.
|
* @param {string} minRAM The new minimum amount of memory for JVM initialization.
|
||||||
*/
|
*/
|
||||||
exports.setMinRAM = function(minRAM){
|
exports.setMinRAM = function(serverid, minRAM){
|
||||||
config.settings.java.minRAM = minRAM
|
config.javaConfig[serverid].minRAM = minRAM
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -539,11 +602,11 @@ exports.setMinRAM = function(minRAM){
|
|||||||
* contains the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
|
* contains the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
|
||||||
* 1024 MegaBytes, etc.
|
* 1024 MegaBytes, etc.
|
||||||
*
|
*
|
||||||
* @param {boolean} def Optional. If true, the default value will be returned.
|
* @param {string} serverid The server id.
|
||||||
* @returns {string} The maximum amount of memory for JVM initialization.
|
* @returns {string} The maximum amount of memory for JVM initialization.
|
||||||
*/
|
*/
|
||||||
exports.getMaxRAM = function(def = false){
|
exports.getMaxRAM = function(serverid){
|
||||||
return !def ? config.settings.java.maxRAM : resolveMaxRAM()
|
return config.javaConfig[serverid].maxRAM
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -551,10 +614,11 @@ exports.getMaxRAM = function(def = false){
|
|||||||
* contain the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
|
* contain the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
|
||||||
* 1024 MegaBytes, etc.
|
* 1024 MegaBytes, etc.
|
||||||
*
|
*
|
||||||
|
* @param {string} serverid The server id.
|
||||||
* @param {string} maxRAM The new maximum amount of memory for JVM initialization.
|
* @param {string} maxRAM The new maximum amount of memory for JVM initialization.
|
||||||
*/
|
*/
|
||||||
exports.setMaxRAM = function(maxRAM){
|
exports.setMaxRAM = function(serverid, maxRAM){
|
||||||
config.settings.java.maxRAM = maxRAM
|
config.javaConfig[serverid].maxRAM = maxRAM
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -562,19 +626,21 @@ exports.setMaxRAM = function(maxRAM){
|
|||||||
*
|
*
|
||||||
* This is a resolved configuration value and defaults to null until externally assigned.
|
* This is a resolved configuration value and defaults to null until externally assigned.
|
||||||
*
|
*
|
||||||
|
* @param {string} serverid The server id.
|
||||||
* @returns {string} The path of the Java Executable.
|
* @returns {string} The path of the Java Executable.
|
||||||
*/
|
*/
|
||||||
exports.getJavaExecutable = function(){
|
exports.getJavaExecutable = function(serverid){
|
||||||
return config.settings.java.executable
|
return config.javaConfig[serverid].executable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the path of the Java Executable.
|
* Set the path of the Java Executable.
|
||||||
*
|
*
|
||||||
|
* @param {string} serverid The server id.
|
||||||
* @param {string} executable The new path of the Java Executable.
|
* @param {string} executable The new path of the Java Executable.
|
||||||
*/
|
*/
|
||||||
exports.setJavaExecutable = function(executable){
|
exports.setJavaExecutable = function(serverid, executable){
|
||||||
config.settings.java.executable = executable
|
config.javaConfig[serverid].executable = executable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -582,11 +648,11 @@ exports.setJavaExecutable = function(executable){
|
|||||||
* such as memory allocation, will be dynamically resolved and will not be included
|
* such as memory allocation, will be dynamically resolved and will not be included
|
||||||
* in this value.
|
* in this value.
|
||||||
*
|
*
|
||||||
* @param {boolean} def Optional. If true, the default value will be returned.
|
* @param {string} serverid The server id.
|
||||||
* @returns {Array.<string>} An array of the additional arguments for JVM initialization.
|
* @returns {Array.<string>} An array of the additional arguments for JVM initialization.
|
||||||
*/
|
*/
|
||||||
exports.getJVMOptions = function(def = false){
|
exports.getJVMOptions = function(serverid){
|
||||||
return !def ? config.settings.java.jvmOptions : DEFAULT_CONFIG.settings.java.jvmOptions
|
return config.javaConfig[serverid].jvmOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -594,11 +660,12 @@ exports.getJVMOptions = function(def = false){
|
|||||||
* such as memory allocation, will be dynamically resolved and should not be
|
* such as memory allocation, will be dynamically resolved and should not be
|
||||||
* included in this value.
|
* included in this value.
|
||||||
*
|
*
|
||||||
|
* @param {string} serverid The server id.
|
||||||
* @param {Array.<string>} jvmOptions An array of the new additional arguments for JVM
|
* @param {Array.<string>} jvmOptions An array of the new additional arguments for JVM
|
||||||
* initialization.
|
* initialization.
|
||||||
*/
|
*/
|
||||||
exports.setJVMOptions = function(jvmOptions){
|
exports.setJVMOptions = function(serverid, jvmOptions){
|
||||||
config.settings.java.jvmOptions = jvmOptions
|
config.javaConfig[serverid].jvmOptions = jvmOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// Game Settings
|
// Game Settings
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
// Work in progress
|
// Work in progress
|
||||||
const logger = require('./loggerutil')('%c[DiscordWrapper]', 'color: #7289da; font-weight: bold')
|
const { LoggerUtil } = require('helios-core')
|
||||||
|
|
||||||
const {Client} = require('discord-rpc-patch')
|
const logger = LoggerUtil.getLogger('DiscordWrapper')
|
||||||
|
|
||||||
|
const { Client } = require('discord-rpc-patch')
|
||||||
|
|
||||||
let client
|
let client
|
||||||
let activity
|
let activity
|
||||||
@ -21,15 +23,15 @@ exports.initRPC = function(genSettings, servSettings, initialDetails = 'Waiting
|
|||||||
}
|
}
|
||||||
|
|
||||||
client.on('ready', () => {
|
client.on('ready', () => {
|
||||||
logger.log('Discord RPC Connected')
|
logger.info('Discord RPC Connected')
|
||||||
client.setActivity(activity)
|
client.setActivity(activity)
|
||||||
})
|
})
|
||||||
|
|
||||||
client.login({clientId: genSettings.clientId}).catch(error => {
|
client.login({clientId: genSettings.clientId}).catch(error => {
|
||||||
if(error.message.includes('ENOENT')) {
|
if(error.message.includes('ENOENT')) {
|
||||||
logger.log('Unable to initialize Discord Rich Presence, no client detected.')
|
logger.info('Unable to initialize Discord Rich Presence, no client detected.')
|
||||||
} else {
|
} else {
|
||||||
logger.log('Unable to initialize Discord Rich Presence: ' + error.message, error)
|
logger.info('Unable to initialize Discord Rich Presence: ' + error.message, error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const request = require('request')
|
const request = require('request')
|
||||||
|
const { LoggerUtil } = require('helios-core')
|
||||||
|
|
||||||
const ConfigManager = require('./configmanager')
|
const ConfigManager = require('./configmanager')
|
||||||
const logger = require('./loggerutil')('%c[DistroManager]', 'color: #a02d2a; font-weight: bold')
|
|
||||||
|
const logger = LoggerUtil.getLogger('DistroManager')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the download information
|
* Represents the download information
|
||||||
@ -118,7 +120,7 @@ class Module {
|
|||||||
* @returns {Module} The parsed Module.
|
* @returns {Module} The parsed Module.
|
||||||
*/
|
*/
|
||||||
static fromJSON(json, serverid){
|
static fromJSON(json, serverid){
|
||||||
return new Module(json.id, json.name, json.type, json.required, json.artifact, json.subModules, serverid)
|
return new Module(json.id, json.name, json.type, json.classpath, json.required, json.artifact, json.subModules, serverid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,9 +145,10 @@ class Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(id, name, type, required, artifact, subModules, serverid) {
|
constructor(id, name, type, classpath, required, artifact, subModules, serverid) {
|
||||||
this.identifier = id
|
this.identifier = id
|
||||||
this.type = type
|
this.type = type
|
||||||
|
this.classpath = classpath
|
||||||
this._resolveMetaData()
|
this._resolveMetaData()
|
||||||
this.name = name
|
this.name = name
|
||||||
this.required = Required.fromJSON(required)
|
this.required = Required.fromJSON(required)
|
||||||
@ -306,6 +309,13 @@ class Module {
|
|||||||
return this.type
|
return this.type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean} Whether or not this library should be on the classpath.
|
||||||
|
*/
|
||||||
|
getClasspath(){
|
||||||
|
return this.classpath ?? true
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
exports.Module
|
exports.Module
|
||||||
|
|
||||||
@ -591,10 +601,10 @@ exports.pullLocal = function(){
|
|||||||
|
|
||||||
exports.setDevMode = function(value){
|
exports.setDevMode = function(value){
|
||||||
if(value){
|
if(value){
|
||||||
logger.log('Developer mode enabled.')
|
logger.info('Developer mode enabled.')
|
||||||
logger.log('If you don\'t know what that means, revert immediately.')
|
logger.info('If you don\'t know what that means, revert immediately.')
|
||||||
} else {
|
} else {
|
||||||
logger.log('Developer mode disabled.')
|
logger.info('Developer mode disabled.')
|
||||||
}
|
}
|
||||||
DEV_MODE = value
|
DEV_MODE = value
|
||||||
}
|
}
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
class LoggerUtil {
|
|
||||||
|
|
||||||
constructor(prefix, style){
|
|
||||||
this.prefix = prefix
|
|
||||||
this.style = style
|
|
||||||
}
|
|
||||||
|
|
||||||
log(){
|
|
||||||
console.log.apply(null, [this.prefix, this.style, ...arguments])
|
|
||||||
}
|
|
||||||
|
|
||||||
info(){
|
|
||||||
console.info.apply(null, [this.prefix, this.style, ...arguments])
|
|
||||||
}
|
|
||||||
|
|
||||||
warn(){
|
|
||||||
console.warn.apply(null, [this.prefix, this.style, ...arguments])
|
|
||||||
}
|
|
||||||
|
|
||||||
debug(){
|
|
||||||
console.debug.apply(null, [this.prefix, this.style, ...arguments])
|
|
||||||
}
|
|
||||||
|
|
||||||
error(){
|
|
||||||
console.error.apply(null, [this.prefix, this.style, ...arguments])
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function (prefix, style){
|
|
||||||
return new LoggerUtil(prefix, style)
|
|
||||||
}
|
|
@ -6,9 +6,11 @@ const path = require('path')
|
|||||||
const ConfigManager = require('./configmanager')
|
const ConfigManager = require('./configmanager')
|
||||||
const DistroManager = require('./distromanager')
|
const DistroManager = require('./distromanager')
|
||||||
const LangLoader = require('./langloader')
|
const LangLoader = require('./langloader')
|
||||||
const logger = require('./loggerutil')('%c[Preloader]', 'color: #a02d2a; font-weight: bold')
|
const { LoggerUtil } = require('helios-core')
|
||||||
|
|
||||||
logger.log('Loading..')
|
const logger = LoggerUtil.getLogger('Preloader')
|
||||||
|
|
||||||
|
logger.info('Loading..')
|
||||||
|
|
||||||
// Load ConfigManager
|
// Load ConfigManager
|
||||||
ConfigManager.load()
|
ConfigManager.load()
|
||||||
@ -21,7 +23,7 @@ function onDistroLoad(data){
|
|||||||
|
|
||||||
// Resolve the selected server if its value has yet to be set.
|
// Resolve the selected server if its value has yet to be set.
|
||||||
if(ConfigManager.getSelectedServer() == null || data.getServer(ConfigManager.getSelectedServer()) == null){
|
if(ConfigManager.getSelectedServer() == null || data.getServer(ConfigManager.getSelectedServer()) == null){
|
||||||
logger.log('Determining default selected server..')
|
logger.info('Determining default selected server..')
|
||||||
ConfigManager.setSelectedServer(data.getMainServer().getID())
|
ConfigManager.setSelectedServer(data.getMainServer().getID())
|
||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
}
|
}
|
||||||
@ -31,26 +33,26 @@ function onDistroLoad(data){
|
|||||||
|
|
||||||
// Ensure Distribution is downloaded and cached.
|
// Ensure Distribution is downloaded and cached.
|
||||||
DistroManager.pullRemote().then((data) => {
|
DistroManager.pullRemote().then((data) => {
|
||||||
logger.log('Loaded distribution index.')
|
logger.info('Loaded distribution index.')
|
||||||
|
|
||||||
onDistroLoad(data)
|
onDistroLoad(data)
|
||||||
|
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
logger.log('Failed to load distribution index.')
|
logger.info('Failed to load distribution index.')
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
|
|
||||||
logger.log('Attempting to load an older version of the distribution index.')
|
logger.info('Attempting to load an older version of the distribution index.')
|
||||||
// Try getting a local copy, better than nothing.
|
// Try getting a local copy, better than nothing.
|
||||||
DistroManager.pullLocal().then((data) => {
|
DistroManager.pullLocal().then((data) => {
|
||||||
logger.log('Successfully loaded an older version of the distribution index.')
|
logger.info('Successfully loaded an older version of the distribution index.')
|
||||||
|
|
||||||
onDistroLoad(data)
|
onDistroLoad(data)
|
||||||
|
|
||||||
|
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
|
|
||||||
logger.log('Failed to load an older version of the distribution index.')
|
logger.info('Failed to load an older version of the distribution index.')
|
||||||
logger.log('Application cannot run.')
|
logger.info('Application cannot run.')
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
|
|
||||||
onDistroLoad(null)
|
onDistroLoad(null)
|
||||||
@ -64,6 +66,6 @@ fs.remove(path.join(os.tmpdir(), ConfigManager.getTempNativeFolder()), (err) =>
|
|||||||
if(err){
|
if(err){
|
||||||
logger.warn('Error while cleaning natives directory', err)
|
logger.warn('Error while cleaning natives directory', err)
|
||||||
} else {
|
} else {
|
||||||
logger.log('Cleaned natives directory.')
|
logger.info('Cleaned natives directory.')
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -2,6 +2,7 @@ const AdmZip = require('adm-zip')
|
|||||||
const child_process = require('child_process')
|
const child_process = require('child_process')
|
||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
|
const { LoggerUtil } = require('helios-core')
|
||||||
const os = require('os')
|
const os = require('os')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const { URL } = require('url')
|
const { URL } = require('url')
|
||||||
@ -9,9 +10,8 @@ const { URL } = require('url')
|
|||||||
const { Util, Library } = require('./assetguard')
|
const { Util, Library } = require('./assetguard')
|
||||||
const ConfigManager = require('./configmanager')
|
const ConfigManager = require('./configmanager')
|
||||||
const DistroManager = require('./distromanager')
|
const DistroManager = require('./distromanager')
|
||||||
const LoggerUtil = require('./loggerutil')
|
|
||||||
|
|
||||||
const logger = LoggerUtil('%c[ProcessBuilder]', 'color: #003996; font-weight: bold')
|
const logger = LoggerUtil.getLogger('ProcessBuilder')
|
||||||
|
|
||||||
class ProcessBuilder {
|
class ProcessBuilder {
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ class ProcessBuilder {
|
|||||||
const tempNativePath = path.join(os.tmpdir(), ConfigManager.getTempNativeFolder(), crypto.pseudoRandomBytes(16).toString('hex'))
|
const tempNativePath = path.join(os.tmpdir(), ConfigManager.getTempNativeFolder(), crypto.pseudoRandomBytes(16).toString('hex'))
|
||||||
process.throwDeprecation = true
|
process.throwDeprecation = true
|
||||||
this.setupLiteLoader()
|
this.setupLiteLoader()
|
||||||
logger.log('Using liteloader:', this.usingLiteLoader)
|
logger.info('Using liteloader:', this.usingLiteLoader)
|
||||||
const modObj = this.resolveModConfiguration(ConfigManager.getModConfiguration(this.server.getID()).mods, this.server.getModules())
|
const modObj = this.resolveModConfiguration(ConfigManager.getModConfiguration(this.server.getID()).mods, this.server.getModules())
|
||||||
|
|
||||||
// Mod list below 1.13
|
// Mod list below 1.13
|
||||||
@ -59,9 +59,9 @@ class ProcessBuilder {
|
|||||||
args = args.concat(this.constructModList(modObj.fMods))
|
args = args.concat(this.constructModList(modObj.fMods))
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log('Launch Arguments:', args)
|
logger.info('Launch Arguments:', args)
|
||||||
|
|
||||||
const child = child_process.spawn(ConfigManager.getJavaExecutable(), args, {
|
const child = child_process.spawn(ConfigManager.getJavaExecutable(this.server.getID()), args, {
|
||||||
cwd: this.gameDir,
|
cwd: this.gameDir,
|
||||||
detached: ConfigManager.getLaunchDetached()
|
detached: ConfigManager.getLaunchDetached()
|
||||||
})
|
})
|
||||||
@ -73,22 +73,20 @@ class ProcessBuilder {
|
|||||||
child.stdout.setEncoding('utf8')
|
child.stdout.setEncoding('utf8')
|
||||||
child.stderr.setEncoding('utf8')
|
child.stderr.setEncoding('utf8')
|
||||||
|
|
||||||
const loggerMCstdout = LoggerUtil('%c[Minecraft]', 'color: #36b030; font-weight: bold')
|
|
||||||
const loggerMCstderr = LoggerUtil('%c[Minecraft]', 'color: #b03030; font-weight: bold')
|
|
||||||
|
|
||||||
child.stdout.on('data', (data) => {
|
child.stdout.on('data', (data) => {
|
||||||
loggerMCstdout.log(data)
|
data.trim().split('\n').forEach(x => console.log(`\x1b[32m[Minecraft]\x1b[0m ${x}`))
|
||||||
|
|
||||||
})
|
})
|
||||||
child.stderr.on('data', (data) => {
|
child.stderr.on('data', (data) => {
|
||||||
loggerMCstderr.log(data)
|
data.trim().split('\n').forEach(x => console.log(`\x1b[31m[Minecraft]\x1b[0m ${x}`))
|
||||||
})
|
})
|
||||||
child.on('close', (code, signal) => {
|
child.on('close', (code, signal) => {
|
||||||
logger.log('Exited with code', code)
|
logger.info('Exited with code', code)
|
||||||
fs.remove(tempNativePath, (err) => {
|
fs.remove(tempNativePath, (err) => {
|
||||||
if(err){
|
if(err){
|
||||||
logger.warn('Error while deleting temp dir', err)
|
logger.warn('Error while deleting temp dir', err)
|
||||||
} else {
|
} else {
|
||||||
logger.log('Temp dir deleted successfully.')
|
logger.info('Temp dir deleted successfully.')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -96,6 +94,16 @@ class ProcessBuilder {
|
|||||||
return child
|
return child
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the platform specific classpath separator. On windows, this is a semicolon.
|
||||||
|
* On Unix, this is a colon.
|
||||||
|
*
|
||||||
|
* @returns {string} The classpath separator for the current operating system.
|
||||||
|
*/
|
||||||
|
static getClasspathSeparator() {
|
||||||
|
return process.platform === 'win32' ? ';' : ':'
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if an optional mod is enabled from its configuration value. If the
|
* Determine if an optional mod is enabled from its configuration value. If the
|
||||||
* configuration value is null, the required object will be used to
|
* configuration value is null, the required object will be used to
|
||||||
@ -339,16 +347,16 @@ class ProcessBuilder {
|
|||||||
|
|
||||||
// Classpath Argument
|
// Classpath Argument
|
||||||
args.push('-cp')
|
args.push('-cp')
|
||||||
args.push(this.classpathArg(mods, tempNativePath).join(process.platform === 'win32' ? ';' : ':'))
|
args.push(this.classpathArg(mods, tempNativePath).join(ProcessBuilder.getClasspathSeparator()))
|
||||||
|
|
||||||
// Java Arguments
|
// Java Arguments
|
||||||
if(process.platform === 'darwin'){
|
if(process.platform === 'darwin'){
|
||||||
args.push('-Xdock:name=HeliosLauncher')
|
args.push('-Xdock:name=HeliosLauncher')
|
||||||
args.push('-Xdock:icon=' + path.join(__dirname, '..', 'images', 'minecraft.icns'))
|
args.push('-Xdock:icon=' + path.join(__dirname, '..', 'images', 'minecraft.icns'))
|
||||||
}
|
}
|
||||||
args.push('-Xmx' + ConfigManager.getMaxRAM())
|
args.push('-Xmx' + ConfigManager.getMaxRAM(this.server.getID()))
|
||||||
args.push('-Xms' + ConfigManager.getMinRAM())
|
args.push('-Xms' + ConfigManager.getMinRAM(this.server.getID()))
|
||||||
args = args.concat(ConfigManager.getJVMOptions())
|
args = args.concat(ConfigManager.getJVMOptions(this.server.getID()))
|
||||||
args.push('-Djava.library.path=' + tempNativePath)
|
args.push('-Djava.library.path=' + tempNativePath)
|
||||||
|
|
||||||
// Main Java Class
|
// Main Java Class
|
||||||
@ -377,6 +385,19 @@ class ProcessBuilder {
|
|||||||
// JVM Arguments First
|
// JVM Arguments First
|
||||||
let args = this.versionData.arguments.jvm
|
let args = this.versionData.arguments.jvm
|
||||||
|
|
||||||
|
// Debug securejarhandler
|
||||||
|
// args.push('-Dbsl.debug=true')
|
||||||
|
|
||||||
|
if(this.forgeData.arguments.jvm != null) {
|
||||||
|
for(const argStr of this.forgeData.arguments.jvm) {
|
||||||
|
args.push(argStr
|
||||||
|
.replaceAll('${library_directory}', this.libPath)
|
||||||
|
.replaceAll('${classpath_separator}', ProcessBuilder.getClasspathSeparator())
|
||||||
|
.replaceAll('${version_name}', this.forgeData.id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//args.push('-Dlog4j.configurationFile=D:\\WesterosCraft\\game\\common\\assets\\log_configs\\client-1.12.xml')
|
//args.push('-Dlog4j.configurationFile=D:\\WesterosCraft\\game\\common\\assets\\log_configs\\client-1.12.xml')
|
||||||
|
|
||||||
// Java Arguments
|
// Java Arguments
|
||||||
@ -384,9 +405,9 @@ class ProcessBuilder {
|
|||||||
args.push('-Xdock:name=HeliosLauncher')
|
args.push('-Xdock:name=HeliosLauncher')
|
||||||
args.push('-Xdock:icon=' + path.join(__dirname, '..', 'images', 'minecraft.icns'))
|
args.push('-Xdock:icon=' + path.join(__dirname, '..', 'images', 'minecraft.icns'))
|
||||||
}
|
}
|
||||||
args.push('-Xmx' + ConfigManager.getMaxRAM())
|
args.push('-Xmx' + ConfigManager.getMaxRAM(this.server.getID()))
|
||||||
args.push('-Xms' + ConfigManager.getMinRAM())
|
args.push('-Xms' + ConfigManager.getMinRAM(this.server.getID()))
|
||||||
args = args.concat(ConfigManager.getJVMOptions())
|
args = args.concat(ConfigManager.getJVMOptions(this.server.getID()))
|
||||||
|
|
||||||
// Main Java Class
|
// Main Java Class
|
||||||
args.push(this.forgeData.mainClass)
|
args.push(this.forgeData.mainClass)
|
||||||
@ -489,7 +510,7 @@ class ProcessBuilder {
|
|||||||
val = args[i].replace(argDiscovery, this.launcherVersion)
|
val = args[i].replace(argDiscovery, this.launcherVersion)
|
||||||
break
|
break
|
||||||
case 'classpath':
|
case 'classpath':
|
||||||
val = this.classpathArg(mods, tempNativePath).join(process.platform === 'win32' ? ';' : ':')
|
val = this.classpathArg(mods, tempNativePath).join(ProcessBuilder.getClasspathSeparator())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if(val != null){
|
if(val != null){
|
||||||
@ -647,9 +668,13 @@ class ProcessBuilder {
|
|||||||
classpathArg(mods, tempNativePath){
|
classpathArg(mods, tempNativePath){
|
||||||
let cpArgs = []
|
let cpArgs = []
|
||||||
|
|
||||||
|
if(!Util.mcVersionAtLeast('1.17', this.server.getMinecraftVersion())) {
|
||||||
// Add the version.jar to the classpath.
|
// Add the version.jar to the classpath.
|
||||||
|
// Must not be added to the classpath for Forge 1.17+.
|
||||||
const version = this.versionData.id
|
const version = this.versionData.id
|
||||||
cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
|
cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(this.usingLiteLoader){
|
if(this.usingLiteLoader){
|
||||||
cpArgs.push(this.llPath)
|
cpArgs.push(this.llPath)
|
||||||
@ -682,6 +707,7 @@ class ProcessBuilder {
|
|||||||
* @returns {{[id: string]: string}} An object containing the paths of each library mojang declares.
|
* @returns {{[id: string]: string}} An object containing the paths of each library mojang declares.
|
||||||
*/
|
*/
|
||||||
_resolveMojangLibraries(tempNativePath){
|
_resolveMojangLibraries(tempNativePath){
|
||||||
|
const nativesRegex = /.+:natives-([^-]+)(?:-(.+))?/
|
||||||
const libs = {}
|
const libs = {}
|
||||||
|
|
||||||
const libArr = this.versionData.libraries
|
const libArr = this.versionData.libraries
|
||||||
@ -689,13 +715,9 @@ class ProcessBuilder {
|
|||||||
for(let i=0; i<libArr.length; i++){
|
for(let i=0; i<libArr.length; i++){
|
||||||
const lib = libArr[i]
|
const lib = libArr[i]
|
||||||
if(Library.validateRules(lib.rules, lib.natives)){
|
if(Library.validateRules(lib.rules, lib.natives)){
|
||||||
if(lib.natives == null){
|
|
||||||
const dlInfo = lib.downloads
|
// Pre-1.19 has a natives object.
|
||||||
const artifact = dlInfo.artifact
|
if(lib.natives != null) {
|
||||||
const to = path.join(this.libPath, artifact.path)
|
|
||||||
const versionIndependentId = lib.name.substring(0, lib.name.lastIndexOf(':'))
|
|
||||||
libs[versionIndependentId] = to
|
|
||||||
} else {
|
|
||||||
// Extract the native library.
|
// Extract the native library.
|
||||||
const exclusionArr = lib.extract != null ? lib.extract.exclude : ['META-INF/']
|
const exclusionArr = lib.extract != null ? lib.extract.exclude : ['META-INF/']
|
||||||
const artifact = lib.downloads.classifiers[lib.natives[Library.mojangFriendlyOS()].replace('${arch}', process.arch.replace('x', ''))]
|
const artifact = lib.downloads.classifiers[lib.natives[Library.mojangFriendlyOS()].replace('${arch}', process.arch.replace('x', ''))]
|
||||||
@ -730,6 +752,65 @@ class ProcessBuilder {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 1.19+ logic
|
||||||
|
else if(lib.name.includes('natives-')) {
|
||||||
|
|
||||||
|
const regexTest = nativesRegex.exec(lib.name)
|
||||||
|
// const os = regexTest[1]
|
||||||
|
const arch = regexTest[2] ?? 'x64'
|
||||||
|
|
||||||
|
if(arch != process.arch) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the native library.
|
||||||
|
const exclusionArr = lib.extract != null ? lib.extract.exclude : ['META-INF/', '.git', '.sha1']
|
||||||
|
const artifact = lib.downloads.artifact
|
||||||
|
|
||||||
|
// Location of native zip.
|
||||||
|
const to = path.join(this.libPath, artifact.path)
|
||||||
|
|
||||||
|
let zip = new AdmZip(to)
|
||||||
|
let zipEntries = zip.getEntries()
|
||||||
|
|
||||||
|
// Unzip the native zip.
|
||||||
|
for(let i=0; i<zipEntries.length; i++){
|
||||||
|
if(zipEntries[i].isDirectory) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileName = zipEntries[i].entryName
|
||||||
|
|
||||||
|
let shouldExclude = false
|
||||||
|
|
||||||
|
// Exclude noted files.
|
||||||
|
exclusionArr.forEach(function(exclusion){
|
||||||
|
if(fileName.indexOf(exclusion) > -1){
|
||||||
|
shouldExclude = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const extractName = fileName.includes('/') ? fileName.substring(fileName.lastIndexOf('/')) : fileName
|
||||||
|
|
||||||
|
// Extract the file.
|
||||||
|
if(!shouldExclude){
|
||||||
|
fs.writeFile(path.join(tempNativePath, extractName), zipEntries[i].getData(), (err) => {
|
||||||
|
if(err){
|
||||||
|
logger.error('Error while extracting native library:', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No natives
|
||||||
|
else {
|
||||||
|
const dlInfo = lib.downloads
|
||||||
|
const artifact = dlInfo.artifact
|
||||||
|
const to = path.join(this.libPath, artifact.path)
|
||||||
|
const versionIndependentId = lib.name.substring(0, lib.name.lastIndexOf(':'))
|
||||||
|
libs[versionIndependentId] = to
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -788,8 +869,11 @@ class ProcessBuilder {
|
|||||||
let libs = []
|
let libs = []
|
||||||
for(let sm of mdl.getSubModules()){
|
for(let sm of mdl.getSubModules()){
|
||||||
if(sm.getType() === DistroManager.Types.Library){
|
if(sm.getType() === DistroManager.Types.Library){
|
||||||
|
|
||||||
|
if(sm.getClasspath()) {
|
||||||
libs.push(sm.getArtifact().getPath())
|
libs.push(sm.getArtifact().getPath())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// If this module has submodules, we need to resolve the libraries for those.
|
// If this module has submodules, we need to resolve the libraries for those.
|
||||||
// To avoid unnecessary recursive calls, base case is checked here.
|
// To avoid unnecessary recursive calls, base case is checked here.
|
||||||
if(mdl.hasSubModules()){
|
if(mdl.hasSubModules()){
|
||||||
|
@ -10,7 +10,9 @@ const { MojangRestAPI, getServerStatus } = require('helios-core/mojang')
|
|||||||
// Internal Requirements
|
// Internal Requirements
|
||||||
const DiscordWrapper = require('./assets/js/discordwrapper')
|
const DiscordWrapper = require('./assets/js/discordwrapper')
|
||||||
const ProcessBuilder = require('./assets/js/processbuilder')
|
const ProcessBuilder = require('./assets/js/processbuilder')
|
||||||
|
const { Util } = require('./assets/js/assetguard')
|
||||||
const { RestResponseStatus, isDisplayableError } = require('helios-core/common')
|
const { RestResponseStatus, isDisplayableError } = require('helios-core/common')
|
||||||
|
const { stdout } = require('process')
|
||||||
|
|
||||||
// Launch Elements
|
// Launch Elements
|
||||||
const launch_content = document.getElementById('launch_content')
|
const launch_content = document.getElementById('launch_content')
|
||||||
@ -21,7 +23,7 @@ const launch_details_text = document.getElementById('launch_details_text')
|
|||||||
const server_selection_button = document.getElementById('server_selection_button')
|
const server_selection_button = document.getElementById('server_selection_button')
|
||||||
const user_text = document.getElementById('user_text')
|
const user_text = document.getElementById('user_text')
|
||||||
|
|
||||||
const loggerLanding = LoggerUtil1('%c[Landing]', 'color: #000668; font-weight: bold')
|
const loggerLanding = LoggerUtil.getLogger('Landing')
|
||||||
|
|
||||||
/* Launch Progress Wrapper Functions */
|
/* Launch Progress Wrapper Functions */
|
||||||
|
|
||||||
@ -85,9 +87,9 @@ function setLaunchEnabled(val){
|
|||||||
|
|
||||||
// Bind launch button
|
// Bind launch button
|
||||||
document.getElementById('launch_button').addEventListener('click', function(e){
|
document.getElementById('launch_button').addEventListener('click', function(e){
|
||||||
loggerLanding.log('Launching game..')
|
loggerLanding.info('Launching game..')
|
||||||
const mcVersion = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer()).getMinecraftVersion()
|
const mcVersion = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer()).getMinecraftVersion()
|
||||||
const jExe = ConfigManager.getJavaExecutable()
|
const jExe = ConfigManager.getJavaExecutable(ConfigManager.getSelectedServer())
|
||||||
if(jExe == null){
|
if(jExe == null){
|
||||||
asyncSystemScan(mcVersion)
|
asyncSystemScan(mcVersion)
|
||||||
} else {
|
} else {
|
||||||
@ -98,7 +100,7 @@ document.getElementById('launch_button').addEventListener('click', function(e){
|
|||||||
|
|
||||||
const jg = new JavaGuard(mcVersion)
|
const jg = new JavaGuard(mcVersion)
|
||||||
jg._validateJavaBinary(jExe).then((v) => {
|
jg._validateJavaBinary(jExe).then((v) => {
|
||||||
loggerLanding.log('Java version meta', v)
|
loggerLanding.info('Java version meta', v)
|
||||||
if(v.valid){
|
if(v.valid){
|
||||||
dlAsync()
|
dlAsync()
|
||||||
} else {
|
} else {
|
||||||
@ -140,13 +142,13 @@ updateSelectedAccount(ConfigManager.getSelectedAccount())
|
|||||||
// Bind selected server
|
// Bind selected server
|
||||||
function updateSelectedServer(serv){
|
function updateSelectedServer(serv){
|
||||||
if(getCurrentView() === VIEWS.settings){
|
if(getCurrentView() === VIEWS.settings){
|
||||||
saveAllModConfigurations()
|
fullSettingsSave()
|
||||||
}
|
}
|
||||||
ConfigManager.setSelectedServer(serv != null ? serv.getID() : null)
|
ConfigManager.setSelectedServer(serv != null ? serv.getID() : null)
|
||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
server_selection_button.innerHTML = '\u2022 ' + (serv != null ? serv.getName() : 'No Server Selected')
|
server_selection_button.innerHTML = '\u2022 ' + (serv != null ? serv.getName() : 'No Server Selected')
|
||||||
if(getCurrentView() === VIEWS.settings){
|
if(getCurrentView() === VIEWS.settings){
|
||||||
animateModsTabRefresh()
|
animateSettingsTabRefresh()
|
||||||
}
|
}
|
||||||
setLaunchEnabled(serv != null)
|
setLaunchEnabled(serv != null)
|
||||||
}
|
}
|
||||||
@ -159,7 +161,7 @@ server_selection_button.onclick = (e) => {
|
|||||||
|
|
||||||
// Update Mojang Status Color
|
// Update Mojang Status Color
|
||||||
const refreshMojangStatuses = async function(){
|
const refreshMojangStatuses = async function(){
|
||||||
loggerLanding.log('Refreshing Mojang Statuses..')
|
loggerLanding.info('Refreshing Mojang Statuses..')
|
||||||
|
|
||||||
let status = 'grey'
|
let status = 'grey'
|
||||||
let tooltipEssentialHTML = ''
|
let tooltipEssentialHTML = ''
|
||||||
@ -219,7 +221,7 @@ const refreshMojangStatuses = async function(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
const refreshServerStatus = async function(fade = false){
|
const refreshServerStatus = async function(fade = false){
|
||||||
loggerLanding.log('Refreshing Server Status')
|
loggerLanding.info('Refreshing Server Status')
|
||||||
const serv = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer())
|
const serv = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer())
|
||||||
|
|
||||||
let pLabel = 'SERVER'
|
let pLabel = 'SERVER'
|
||||||
@ -253,8 +255,9 @@ const refreshServerStatus = async function(fade = false){
|
|||||||
refreshMojangStatuses()
|
refreshMojangStatuses()
|
||||||
// Server Status is refreshed in uibinder.js on distributionIndexDone.
|
// Server Status is refreshed in uibinder.js on distributionIndexDone.
|
||||||
|
|
||||||
|
// Refresh statuses every hour. The status page itself refreshes every day so...
|
||||||
|
let mojangStatusListener = setInterval(() => refreshMojangStatuses(true), 60*60*1000)
|
||||||
// Set refresh rate to once every 5 minutes.
|
// Set refresh rate to once every 5 minutes.
|
||||||
let mojangStatusListener = setInterval(() => refreshMojangStatuses(true), 300000)
|
|
||||||
let serverStatusListener = setInterval(() => refreshServerStatus(true), 300000)
|
let serverStatusListener = setInterval(() => refreshServerStatus(true), 300000)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -293,8 +296,6 @@ function asyncSystemScan(mcVersion, launchAfter = true){
|
|||||||
toggleLaunchArea(true)
|
toggleLaunchArea(true)
|
||||||
setLaunchPercentage(0, 100)
|
setLaunchPercentage(0, 100)
|
||||||
|
|
||||||
const loggerSysAEx = LoggerUtil1('%c[SysAEx]', 'color: #353232; font-weight: bold')
|
|
||||||
|
|
||||||
const forkEnv = JSON.parse(JSON.stringify(process.env))
|
const forkEnv = JSON.parse(JSON.stringify(process.env))
|
||||||
forkEnv.CONFIG_DIRECT_PATH = ConfigManager.getLauncherDirectory()
|
forkEnv.CONFIG_DIRECT_PATH = ConfigManager.getLauncherDirectory()
|
||||||
|
|
||||||
@ -309,14 +310,16 @@ function asyncSystemScan(mcVersion, launchAfter = true){
|
|||||||
// Stdout
|
// Stdout
|
||||||
sysAEx.stdio[1].setEncoding('utf8')
|
sysAEx.stdio[1].setEncoding('utf8')
|
||||||
sysAEx.stdio[1].on('data', (data) => {
|
sysAEx.stdio[1].on('data', (data) => {
|
||||||
loggerSysAEx.log(data)
|
console.log(`\x1b[32m[SysAEx]\x1b[0m ${data}`)
|
||||||
})
|
})
|
||||||
// Stderr
|
// Stderr
|
||||||
sysAEx.stdio[2].setEncoding('utf8')
|
sysAEx.stdio[2].setEncoding('utf8')
|
||||||
sysAEx.stdio[2].on('data', (data) => {
|
sysAEx.stdio[2].on('data', (data) => {
|
||||||
loggerSysAEx.log(data)
|
console.log(`\x1b[31m[SysAEx]\x1b[0m ${data}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const javaVer = Util.mcVersionAtLeast('1.17', mcVersion) ? '17' : '8'
|
||||||
|
|
||||||
sysAEx.on('message', (m) => {
|
sysAEx.on('message', (m) => {
|
||||||
|
|
||||||
if(m.context === 'validateJava'){
|
if(m.context === 'validateJava'){
|
||||||
@ -325,14 +328,14 @@ function asyncSystemScan(mcVersion, launchAfter = true){
|
|||||||
// Show this information to the user.
|
// Show this information to the user.
|
||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
'No Compatible<br>Java Installation Found',
|
'No Compatible<br>Java Installation Found',
|
||||||
'In order to join WesterosCraft, you need a 64-bit installation of Java 8. Would you like us to install a copy?',
|
`In order to join WesterosCraft, you need a 64-bit installation of Java ${javaVer}. Would you like us to install a copy?`,
|
||||||
'Install Java',
|
'Install Java',
|
||||||
'Install Manually'
|
'Install Manually'
|
||||||
)
|
)
|
||||||
setOverlayHandler(() => {
|
setOverlayHandler(() => {
|
||||||
setLaunchDetails('Preparing Java Download..')
|
setLaunchDetails('Preparing Java Download..')
|
||||||
sysAEx.send({task: 'changeContext', class: 'AssetGuard', args: [ConfigManager.getCommonDirectory(),ConfigManager.getJavaExecutable()]})
|
sysAEx.send({task: 'changeContext', class: 'AssetGuard', args: [ConfigManager.getCommonDirectory(),ConfigManager.getJavaExecutable(ConfigManager.getSelectedServer())]})
|
||||||
sysAEx.send({task: 'execute', function: '_enqueueOpenJDK', argsArr: [ConfigManager.getDataDirectory()]})
|
sysAEx.send({task: 'execute', function: '_enqueueOpenJDK', argsArr: [ConfigManager.getDataDirectory(), mcVersion]})
|
||||||
toggleOverlay(false)
|
toggleOverlay(false)
|
||||||
})
|
})
|
||||||
setDismissHandler(() => {
|
setDismissHandler(() => {
|
||||||
@ -340,7 +343,7 @@ function asyncSystemScan(mcVersion, launchAfter = true){
|
|||||||
//$('#overlayDismiss').toggle(false)
|
//$('#overlayDismiss').toggle(false)
|
||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
'Java is Required<br>to Launch',
|
'Java is Required<br>to Launch',
|
||||||
'A valid x64 installation of Java 8 is required to launch.<br><br>Please refer to our <a href="https://github.com/dscalzi/HeliosLauncher/wiki/Java-Management#manually-installing-a-valid-version-of-java">Java Management Guide</a> for instructions on how to manually install Java.',
|
`A valid x64 installation of Java ${javaVer} is required to launch.<br><br>Please refer to our <a href="https://github.com/dscalzi/HeliosLauncher/wiki/Java-Management#manually-installing-a-valid-version-of-java">Java Management Guide</a> for instructions on how to manually install Java.`,
|
||||||
'I Understand',
|
'I Understand',
|
||||||
'Go Back'
|
'Go Back'
|
||||||
)
|
)
|
||||||
@ -359,7 +362,7 @@ function asyncSystemScan(mcVersion, launchAfter = true){
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Java installation found, use this to launch the game.
|
// Java installation found, use this to launch the game.
|
||||||
ConfigManager.setJavaExecutable(m.result)
|
ConfigManager.setJavaExecutable(ConfigManager.getSelectedServer(), m.result)
|
||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
|
|
||||||
// We need to make sure that the updated value is on the settings UI.
|
// We need to make sure that the updated value is on the settings UI.
|
||||||
@ -433,7 +436,7 @@ function asyncSystemScan(mcVersion, launchAfter = true){
|
|||||||
remote.getCurrentWindow().setProgressBar(-1)
|
remote.getCurrentWindow().setProgressBar(-1)
|
||||||
|
|
||||||
// Extraction completed successfully.
|
// Extraction completed successfully.
|
||||||
ConfigManager.setJavaExecutable(m.args[0])
|
ConfigManager.setJavaExecutable(ConfigManager.getSelectedServer(), m.args[0])
|
||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
|
|
||||||
if(extractListener != null){
|
if(extractListener != null){
|
||||||
@ -495,8 +498,7 @@ function dlAsync(login = true){
|
|||||||
toggleLaunchArea(true)
|
toggleLaunchArea(true)
|
||||||
setLaunchPercentage(0, 100)
|
setLaunchPercentage(0, 100)
|
||||||
|
|
||||||
const loggerAEx = LoggerUtil1('%c[AEx]', 'color: #353232; font-weight: bold')
|
const loggerLaunchSuite = LoggerUtil.getLogger('LaunchSuite')
|
||||||
const loggerLaunchSuite = LoggerUtil1('%c[LaunchSuite]', 'color: #000668; font-weight: bold')
|
|
||||||
|
|
||||||
const forkEnv = JSON.parse(JSON.stringify(process.env))
|
const forkEnv = JSON.parse(JSON.stringify(process.env))
|
||||||
forkEnv.CONFIG_DIRECT_PATH = ConfigManager.getLauncherDirectory()
|
forkEnv.CONFIG_DIRECT_PATH = ConfigManager.getLauncherDirectory()
|
||||||
@ -505,7 +507,7 @@ function dlAsync(login = true){
|
|||||||
aEx = cp.fork(path.join(__dirname, 'assets', 'js', 'assetexec.js'), [
|
aEx = cp.fork(path.join(__dirname, 'assets', 'js', 'assetexec.js'), [
|
||||||
'AssetGuard',
|
'AssetGuard',
|
||||||
ConfigManager.getCommonDirectory(),
|
ConfigManager.getCommonDirectory(),
|
||||||
ConfigManager.getJavaExecutable()
|
ConfigManager.getJavaExecutable(ConfigManager.getSelectedServer())
|
||||||
], {
|
], {
|
||||||
env: forkEnv,
|
env: forkEnv,
|
||||||
stdio: 'pipe'
|
stdio: 'pipe'
|
||||||
@ -513,12 +515,12 @@ function dlAsync(login = true){
|
|||||||
// Stdout
|
// Stdout
|
||||||
aEx.stdio[1].setEncoding('utf8')
|
aEx.stdio[1].setEncoding('utf8')
|
||||||
aEx.stdio[1].on('data', (data) => {
|
aEx.stdio[1].on('data', (data) => {
|
||||||
loggerAEx.log(data)
|
console.log(`\x1b[32m[AEx]\x1b[0m ${data}`)
|
||||||
})
|
})
|
||||||
// Stderr
|
// Stderr
|
||||||
aEx.stdio[2].setEncoding('utf8')
|
aEx.stdio[2].setEncoding('utf8')
|
||||||
aEx.stdio[2].on('data', (data) => {
|
aEx.stdio[2].on('data', (data) => {
|
||||||
loggerAEx.log(data)
|
console.log(`\x1b[31m[AEx]\x1b[0m ${data}`)
|
||||||
})
|
})
|
||||||
aEx.on('error', (err) => {
|
aEx.on('error', (err) => {
|
||||||
loggerLaunchSuite.error('Error during launch', err)
|
loggerLaunchSuite.error('Error during launch', err)
|
||||||
@ -538,27 +540,27 @@ function dlAsync(login = true){
|
|||||||
switch(m.data){
|
switch(m.data){
|
||||||
case 'distribution':
|
case 'distribution':
|
||||||
setLaunchPercentage(20, 100)
|
setLaunchPercentage(20, 100)
|
||||||
loggerLaunchSuite.log('Validated distibution index.')
|
loggerLaunchSuite.info('Validated distibution index.')
|
||||||
setLaunchDetails('Loading version information..')
|
setLaunchDetails('Loading version information..')
|
||||||
break
|
break
|
||||||
case 'version':
|
case 'version':
|
||||||
setLaunchPercentage(40, 100)
|
setLaunchPercentage(40, 100)
|
||||||
loggerLaunchSuite.log('Version data loaded.')
|
loggerLaunchSuite.info('Version data loaded.')
|
||||||
setLaunchDetails('Validating asset integrity..')
|
setLaunchDetails('Validating asset integrity..')
|
||||||
break
|
break
|
||||||
case 'assets':
|
case 'assets':
|
||||||
setLaunchPercentage(60, 100)
|
setLaunchPercentage(60, 100)
|
||||||
loggerLaunchSuite.log('Asset Validation Complete')
|
loggerLaunchSuite.info('Asset Validation Complete')
|
||||||
setLaunchDetails('Validating library integrity..')
|
setLaunchDetails('Validating library integrity..')
|
||||||
break
|
break
|
||||||
case 'libraries':
|
case 'libraries':
|
||||||
setLaunchPercentage(80, 100)
|
setLaunchPercentage(80, 100)
|
||||||
loggerLaunchSuite.log('Library validation complete.')
|
loggerLaunchSuite.info('Library validation complete.')
|
||||||
setLaunchDetails('Validating miscellaneous file integrity..')
|
setLaunchDetails('Validating miscellaneous file integrity..')
|
||||||
break
|
break
|
||||||
case 'files':
|
case 'files':
|
||||||
setLaunchPercentage(100, 100)
|
setLaunchPercentage(100, 100)
|
||||||
loggerLaunchSuite.log('File validation complete.')
|
loggerLaunchSuite.info('File validation complete.')
|
||||||
setLaunchDetails('Downloading files..')
|
setLaunchDetails('Downloading files..')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -646,7 +648,7 @@ function dlAsync(login = true){
|
|||||||
|
|
||||||
if(login && allGood) {
|
if(login && allGood) {
|
||||||
const authUser = ConfigManager.getSelectedAccount()
|
const authUser = ConfigManager.getSelectedAccount()
|
||||||
loggerLaunchSuite.log(`Sending selected account (${authUser.displayName}) to ProcessBuilder.`)
|
loggerLaunchSuite.info(`Sending selected account (${authUser.displayName}) to ProcessBuilder.`)
|
||||||
let pb = new ProcessBuilder(serv, versionData, forgeData, authUser, remote.app.getVersion())
|
let pb = new ProcessBuilder(serv, versionData, forgeData, authUser, remote.app.getVersion())
|
||||||
setLaunchDetails('Launching game..')
|
setLaunchDetails('Launching game..')
|
||||||
|
|
||||||
@ -713,7 +715,7 @@ function dlAsync(login = true){
|
|||||||
DiscordWrapper.initRPC(distro.discord, serv.discord)
|
DiscordWrapper.initRPC(distro.discord, serv.discord)
|
||||||
hasRPC = true
|
hasRPC = true
|
||||||
proc.on('close', (code, signal) => {
|
proc.on('close', (code, signal) => {
|
||||||
loggerLaunchSuite.log('Shutting down Discord Rich Presence..')
|
loggerLaunchSuite.info('Shutting down Discord Rich Presence..')
|
||||||
DiscordWrapper.shutdownRPC()
|
DiscordWrapper.shutdownRPC()
|
||||||
hasRPC = false
|
hasRPC = false
|
||||||
proc = null
|
proc = null
|
||||||
@ -744,7 +746,7 @@ function dlAsync(login = true){
|
|||||||
serv = data.getServer(ConfigManager.getSelectedServer())
|
serv = data.getServer(ConfigManager.getSelectedServer())
|
||||||
aEx.send({task: 'execute', function: 'validateEverything', argsArr: [ConfigManager.getSelectedServer(), DistroManager.isDevMode()]})
|
aEx.send({task: 'execute', function: 'validateEverything', argsArr: [ConfigManager.getSelectedServer(), DistroManager.isDevMode()]})
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
loggerLaunchSuite.log('Error while fetching a fresh copy of the distribution index.', err)
|
loggerLaunchSuite.info('Error while fetching a fresh copy of the distribution index.', err)
|
||||||
refreshDistributionIndex(false, (data) => {
|
refreshDistributionIndex(false, (data) => {
|
||||||
onDistroRefresh(data)
|
onDistroRefresh(data)
|
||||||
serv = data.getServer(ConfigManager.getSelectedServer())
|
serv = data.getServer(ConfigManager.getSelectedServer())
|
||||||
|
@ -21,8 +21,6 @@ const loginForm = document.getElementById('loginForm')
|
|||||||
// Control variables.
|
// Control variables.
|
||||||
let lu = false, lp = false
|
let lu = false, lp = false
|
||||||
|
|
||||||
const loggerLogin = LoggerUtil1('%c[Login]', 'color: #000668; font-weight: bold')
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a login error.
|
* Show a login error.
|
||||||
|
@ -127,29 +127,34 @@ function initSettingsValues(){
|
|||||||
const sEls = document.getElementById('settingsContainer').querySelectorAll('[cValue]')
|
const sEls = document.getElementById('settingsContainer').querySelectorAll('[cValue]')
|
||||||
Array.from(sEls).map((v, index, arr) => {
|
Array.from(sEls).map((v, index, arr) => {
|
||||||
const cVal = v.getAttribute('cValue')
|
const cVal = v.getAttribute('cValue')
|
||||||
|
const serverDependent = v.hasAttribute('serverDependent') // Means the first argument is the server id.
|
||||||
const gFn = ConfigManager['get' + cVal]
|
const gFn = ConfigManager['get' + cVal]
|
||||||
|
const gFnOpts = []
|
||||||
|
if(serverDependent) {
|
||||||
|
gFnOpts.push(ConfigManager.getSelectedServer())
|
||||||
|
}
|
||||||
if(typeof gFn === 'function'){
|
if(typeof gFn === 'function'){
|
||||||
if(v.tagName === 'INPUT'){
|
if(v.tagName === 'INPUT'){
|
||||||
if(v.type === 'number' || v.type === 'text'){
|
if(v.type === 'number' || v.type === 'text'){
|
||||||
// Special Conditions
|
// Special Conditions
|
||||||
if(cVal === 'JavaExecutable'){
|
if(cVal === 'JavaExecutable'){
|
||||||
|
v.value = gFn.apply(null, gFnOpts)
|
||||||
populateJavaExecDetails(v.value)
|
populateJavaExecDetails(v.value)
|
||||||
v.value = gFn()
|
|
||||||
} else if (cVal === 'DataDirectory'){
|
} else if (cVal === 'DataDirectory'){
|
||||||
v.value = gFn()
|
v.value = gFn.apply(null, gFnOpts)
|
||||||
} else if(cVal === 'JVMOptions'){
|
} else if(cVal === 'JVMOptions'){
|
||||||
v.value = gFn().join(' ')
|
v.value = gFn.apply(null, gFnOpts).join(' ')
|
||||||
} else {
|
} else {
|
||||||
v.value = gFn()
|
v.value = gFn.apply(null, gFnOpts)
|
||||||
}
|
}
|
||||||
} else if(v.type === 'checkbox'){
|
} else if(v.type === 'checkbox'){
|
||||||
v.checked = gFn()
|
v.checked = gFn.apply(null, gFnOpts)
|
||||||
}
|
}
|
||||||
} else if(v.tagName === 'DIV'){
|
} else if(v.tagName === 'DIV'){
|
||||||
if(v.classList.contains('rangeSlider')){
|
if(v.classList.contains('rangeSlider')){
|
||||||
// Special Conditions
|
// Special Conditions
|
||||||
if(cVal === 'MinRAM' || cVal === 'MaxRAM'){
|
if(cVal === 'MinRAM' || cVal === 'MaxRAM'){
|
||||||
let val = gFn()
|
let val = gFn.apply(null, gFnOpts)
|
||||||
if(val.endsWith('M')){
|
if(val.endsWith('M')){
|
||||||
val = Number(val.substring(0, val.length-1))/1000
|
val = Number(val.substring(0, val.length-1))/1000
|
||||||
} else {
|
} else {
|
||||||
@ -158,7 +163,7 @@ function initSettingsValues(){
|
|||||||
|
|
||||||
v.setAttribute('value', val)
|
v.setAttribute('value', val)
|
||||||
} else {
|
} else {
|
||||||
v.setAttribute('value', Number.parseFloat(gFn()))
|
v.setAttribute('value', Number.parseFloat(gFn.apply(null, gFnOpts)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,22 +179,31 @@ function saveSettingsValues(){
|
|||||||
const sEls = document.getElementById('settingsContainer').querySelectorAll('[cValue]')
|
const sEls = document.getElementById('settingsContainer').querySelectorAll('[cValue]')
|
||||||
Array.from(sEls).map((v, index, arr) => {
|
Array.from(sEls).map((v, index, arr) => {
|
||||||
const cVal = v.getAttribute('cValue')
|
const cVal = v.getAttribute('cValue')
|
||||||
|
const serverDependent = v.hasAttribute('serverDependent') // Means the first argument is the server id.
|
||||||
const sFn = ConfigManager['set' + cVal]
|
const sFn = ConfigManager['set' + cVal]
|
||||||
|
const sFnOpts = []
|
||||||
|
if(serverDependent) {
|
||||||
|
sFnOpts.push(ConfigManager.getSelectedServer())
|
||||||
|
}
|
||||||
if(typeof sFn === 'function'){
|
if(typeof sFn === 'function'){
|
||||||
if(v.tagName === 'INPUT'){
|
if(v.tagName === 'INPUT'){
|
||||||
if(v.type === 'number' || v.type === 'text'){
|
if(v.type === 'number' || v.type === 'text'){
|
||||||
// Special Conditions
|
// Special Conditions
|
||||||
if(cVal === 'JVMOptions'){
|
if(cVal === 'JVMOptions'){
|
||||||
if(!v.value.trim()) {
|
if(!v.value.trim()) {
|
||||||
sFn([])
|
sFnOpts.push([])
|
||||||
|
sFn.apply(null, sFnOpts)
|
||||||
} else {
|
} else {
|
||||||
sFn(v.value.trim().split(/\s+/))
|
sFnOpts.push(v.value.trim().split(/\s+/))
|
||||||
|
sFn.apply(null, sFnOpts)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sFn(v.value)
|
sFnOpts.push(v.value)
|
||||||
|
sFn.apply(null, sFnOpts)
|
||||||
}
|
}
|
||||||
} else if(v.type === 'checkbox'){
|
} else if(v.type === 'checkbox'){
|
||||||
sFn(v.checked)
|
sFnOpts.push(v.checked)
|
||||||
|
sFn.apply(null, sFnOpts)
|
||||||
// Special Conditions
|
// Special Conditions
|
||||||
if(cVal === 'AllowPrerelease'){
|
if(cVal === 'AllowPrerelease'){
|
||||||
changeAllowPrerelease(v.checked)
|
changeAllowPrerelease(v.checked)
|
||||||
@ -206,9 +220,11 @@ function saveSettingsValues(){
|
|||||||
val = val + 'G'
|
val = val + 'G'
|
||||||
}
|
}
|
||||||
|
|
||||||
sFn(val)
|
sFnOpts.push(val)
|
||||||
|
sFn.apply(null, sFnOpts)
|
||||||
} else {
|
} else {
|
||||||
sFn(v.getAttribute('value'))
|
sFnOpts.push(v.getAttribute('value'))
|
||||||
|
sFn.apply(null, sFnOpts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -305,13 +321,17 @@ function settingsSaveDisabled(v){
|
|||||||
settingsNavDone.disabled = v
|
settingsNavDone.disabled = v
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Closes the settings view and saves all data. */
|
function fullSettingsSave() {
|
||||||
settingsNavDone.onclick = () => {
|
|
||||||
saveSettingsValues()
|
saveSettingsValues()
|
||||||
saveModConfiguration()
|
saveModConfiguration()
|
||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
saveDropinModConfiguration()
|
saveDropinModConfiguration()
|
||||||
saveShaderpackSettings()
|
saveShaderpackSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Closes the settings view and saves all data. */
|
||||||
|
settingsNavDone.onclick = () => {
|
||||||
|
fullSettingsSave()
|
||||||
switchView(getCurrentView(), VIEWS.landing)
|
switchView(getCurrentView(), VIEWS.landing)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,12 +394,12 @@ ipcRenderer.on(MSFT_OPCODE.REPLY_LOGIN, (_, ...arguments_) => {
|
|||||||
switchView(getCurrentView(), viewOnClose, 500, 500, () => {
|
switchView(getCurrentView(), viewOnClose, 500, 500, () => {
|
||||||
// TODO Dont know what these errors are. Just show them I guess.
|
// TODO Dont know what these errors are. Just show them I guess.
|
||||||
// This is probably if you messed up the app registration with Azure.
|
// This is probably if you messed up the app registration with Azure.
|
||||||
|
let error = queryMap.error // Error might be 'access_denied' ?
|
||||||
|
let errorDesc = queryMap.error_description
|
||||||
console.log('Error getting authCode, is Azure application registered correctly?')
|
console.log('Error getting authCode, is Azure application registered correctly?')
|
||||||
console.log(error)
|
console.log(error)
|
||||||
console.log(errorDesc)
|
console.log(errorDesc)
|
||||||
console.log('Full query map', queryMap)
|
console.log('Full query map: ', queryMap)
|
||||||
let error = queryMap.error // Error might be 'access_denied' ?
|
|
||||||
let errorDesc = queryMap.error_description
|
|
||||||
setOverlayContent(
|
setOverlayContent(
|
||||||
error,
|
error,
|
||||||
errorDesc,
|
errorDesc,
|
||||||
@ -1060,7 +1080,8 @@ function bindShaderpackButton() {
|
|||||||
function loadSelectedServerOnModsTab(){
|
function loadSelectedServerOnModsTab(){
|
||||||
const serv = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer())
|
const serv = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer())
|
||||||
|
|
||||||
document.getElementById('settingsSelServContent').innerHTML = `
|
for(const el of document.getElementsByClassName('settingsSelServContent')) {
|
||||||
|
el.innerHTML = `
|
||||||
<img class="serverListingImg" src="${serv.getIcon()}"/>
|
<img class="serverListingImg" src="${serv.getIcon()}"/>
|
||||||
<div class="serverListingDetails">
|
<div class="serverListingDetails">
|
||||||
<span class="serverListingName">${serv.getName()}</span>
|
<span class="serverListingName">${serv.getName()}</span>
|
||||||
@ -1081,12 +1102,15 @@ function loadSelectedServerOnModsTab(){
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind functionality to the server switch button.
|
// Bind functionality to the server switch button.
|
||||||
document.getElementById('settingsSwitchServerButton').addEventListener('click', (e) => {
|
Array.from(document.getElementsByClassName('settingsSwitchServerButton')).forEach(el => {
|
||||||
|
el.addEventListener('click', (e) => {
|
||||||
e.target.blur()
|
e.target.blur()
|
||||||
toggleServerSelection(true)
|
toggleServerSelection(true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1099,13 +1123,13 @@ function saveAllModConfigurations(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to refresh the mods tab whenever the selected
|
* Function to refresh the current tab whenever the selected
|
||||||
* server is changed.
|
* server is changed.
|
||||||
*/
|
*/
|
||||||
function animateModsTabRefresh(){
|
function animateSettingsTabRefresh(){
|
||||||
$('#settingsTabMods').fadeOut(500, () => {
|
$(`#${selectedSettingsTab}`).fadeOut(500, () => {
|
||||||
prepareModsTab()
|
prepareSettings()
|
||||||
$('#settingsTabMods').fadeIn(500)
|
$(`#${selectedSettingsTab}`).fadeIn(500)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1135,6 +1159,8 @@ const settingsMinRAMLabel = document.getElementById('settingsMinRAMLabel')
|
|||||||
const settingsMemoryTotal = document.getElementById('settingsMemoryTotal')
|
const settingsMemoryTotal = document.getElementById('settingsMemoryTotal')
|
||||||
const settingsMemoryAvail = document.getElementById('settingsMemoryAvail')
|
const settingsMemoryAvail = document.getElementById('settingsMemoryAvail')
|
||||||
const settingsJavaExecDetails = document.getElementById('settingsJavaExecDetails')
|
const settingsJavaExecDetails = document.getElementById('settingsJavaExecDetails')
|
||||||
|
const settingsJavaReqDesc = document.getElementById('settingsJavaReqDesc')
|
||||||
|
const settingsJvmOptsLink = document.getElementById('settingsJvmOptsLink')
|
||||||
|
|
||||||
// Store maximum memory values.
|
// Store maximum memory values.
|
||||||
const SETTINGS_MAX_MEMORY = ConfigManager.getAbsoluteMaxRAM()
|
const SETTINGS_MAX_MEMORY = ConfigManager.getAbsoluteMaxRAM()
|
||||||
@ -1342,12 +1368,34 @@ function populateJavaExecDetails(execPath){
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function populateJavaReqDesc() {
|
||||||
|
const mcVer = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer()).getMinecraftVersion()
|
||||||
|
if(Util.mcVersionAtLeast('1.17', mcVer)) {
|
||||||
|
settingsJavaReqDesc.innerHTML = 'Requires Java 17 x64.'
|
||||||
|
} else {
|
||||||
|
settingsJavaReqDesc.innerHTML = 'Requires Java 8 x64.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function populateJvmOptsLink() {
|
||||||
|
const mcVer = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer()).getMinecraftVersion()
|
||||||
|
if(Util.mcVersionAtLeast('1.17', mcVer)) {
|
||||||
|
settingsJvmOptsLink.innerHTML = 'Available Options for Java 17 (HotSpot VM)'
|
||||||
|
settingsJvmOptsLink.href = 'https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html#extra-options-for-java'
|
||||||
|
} else {
|
||||||
|
settingsJvmOptsLink.innerHTML = 'Available Options for Java 8 (HotSpot VM)'
|
||||||
|
settingsJvmOptsLink.href = `https://docs.oracle.com/javase/8/docs/technotes/tools/${process.platform === 'win32' ? 'windows' : 'unix'}/java.html`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the Java tab for display.
|
* Prepare the Java tab for display.
|
||||||
*/
|
*/
|
||||||
function prepareJavaTab(){
|
function prepareJavaTab(){
|
||||||
bindRangeSlider()
|
bindRangeSlider()
|
||||||
populateMemoryStatus()
|
populateMemoryStatus()
|
||||||
|
populateJavaReqDesc()
|
||||||
|
populateJvmOptsLink()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,7 +60,7 @@ function getCurrentView(){
|
|||||||
function showMainUI(data){
|
function showMainUI(data){
|
||||||
|
|
||||||
if(!isDev){
|
if(!isDev){
|
||||||
loggerAutoUpdater.log('Initializing..')
|
loggerAutoUpdater.info('Initializing..')
|
||||||
ipcRenderer.send('autoUpdateAction', 'initAutoUpdater', ConfigManager.getAllowPrerelease())
|
ipcRenderer.send('autoUpdateAction', 'initAutoUpdater', ConfigManager.getAllowPrerelease())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,6 +137,7 @@ function onDistroRefresh(data){
|
|||||||
refreshServerStatus()
|
refreshServerStatus()
|
||||||
initNews()
|
initNews()
|
||||||
syncModConfigurations(data)
|
syncModConfigurations(data)
|
||||||
|
ensureJavaSettings(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -223,6 +224,21 @@ function syncModConfigurations(data){
|
|||||||
ConfigManager.save()
|
ConfigManager.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure java configurations are present for the available servers.
|
||||||
|
*
|
||||||
|
* @param {Object} data The distro index object.
|
||||||
|
*/
|
||||||
|
function ensureJavaSettings(data) {
|
||||||
|
|
||||||
|
// Nothing too fancy for now.
|
||||||
|
for(const serv of data.getServers()){
|
||||||
|
ConfigManager.ensureJavaConfig(serv.getID(), serv.getMinecraftVersion())
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigManager.save()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively scan for optional sub modules. If none are found,
|
* Recursively scan for optional sub modules. If none are found,
|
||||||
* this function returns a boolean. If optional sub modules do exist,
|
* this function returns a boolean. If optional sub modules do exist,
|
||||||
@ -434,6 +450,7 @@ ipcRenderer.on('distributionIndexDone', (event, res) => {
|
|||||||
if(res) {
|
if(res) {
|
||||||
const data = DistroManager.getDistribution()
|
const data = DistroManager.getDistribution()
|
||||||
syncModConfigurations(data)
|
syncModConfigurations(data)
|
||||||
|
ensureJavaSettings(data)
|
||||||
if(document.readyState === 'interactive' || document.readyState === 'complete'){
|
if(document.readyState === 'interactive' || document.readyState === 'complete'){
|
||||||
showMainUI(data)
|
showMainUI(data)
|
||||||
} else {
|
} else {
|
||||||
@ -448,3 +465,13 @@ ipcRenderer.on('distributionIndexDone', (event, res) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Util for development
|
||||||
|
function devModeToggle() {
|
||||||
|
DistroManager.setDevMode(true)
|
||||||
|
DistroManager.pullLocal().then((data) => {
|
||||||
|
ensureJavaSettings(data)
|
||||||
|
updateSelectedServer(data.getServers()[0])
|
||||||
|
syncModConfigurations(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -10,11 +10,9 @@ const {ipcRenderer, shell, webFrame} = require('electron')
|
|||||||
const remote = require('@electron/remote')
|
const remote = require('@electron/remote')
|
||||||
const isDev = require('./assets/js/isdev')
|
const isDev = require('./assets/js/isdev')
|
||||||
const { LoggerUtil } = require('helios-core')
|
const { LoggerUtil } = require('helios-core')
|
||||||
const LoggerUtil1 = require('./assets/js/loggerutil')
|
|
||||||
|
|
||||||
const loggerUICore = LoggerUtil1('%c[UICore]', 'color: #000668; font-weight: bold')
|
const loggerUICore = LoggerUtil.getLogger('UICore')
|
||||||
const loggerAutoUpdater = LoggerUtil1('%c[AutoUpdater]', 'color: #000668; font-weight: bold')
|
const loggerAutoUpdater = LoggerUtil.getLogger('AutoUpdater')
|
||||||
const loggerAutoUpdaterSuccess = LoggerUtil1('%c[AutoUpdater]', 'color: #209b07; font-weight: bold')
|
|
||||||
|
|
||||||
// Log deprecation and process warnings.
|
// Log deprecation and process warnings.
|
||||||
process.traceProcessWarnings = true
|
process.traceProcessWarnings = true
|
||||||
@ -43,11 +41,11 @@ if(!isDev){
|
|||||||
ipcRenderer.on('autoUpdateNotification', (event, arg, info) => {
|
ipcRenderer.on('autoUpdateNotification', (event, arg, info) => {
|
||||||
switch(arg){
|
switch(arg){
|
||||||
case 'checking-for-update':
|
case 'checking-for-update':
|
||||||
loggerAutoUpdater.log('Checking for update..')
|
loggerAutoUpdater.info('Checking for update..')
|
||||||
settingsUpdateButtonStatus('Checking for Updates..', true)
|
settingsUpdateButtonStatus('Checking for Updates..', true)
|
||||||
break
|
break
|
||||||
case 'update-available':
|
case 'update-available':
|
||||||
loggerAutoUpdaterSuccess.log('New update available', info.version)
|
loggerAutoUpdater.info('New update available', info.version)
|
||||||
|
|
||||||
if(process.platform === 'darwin'){
|
if(process.platform === 'darwin'){
|
||||||
info.darwindownload = `https://github.com/dscalzi/HeliosLauncher/releases/download/v${info.version}/Helios-Launcher-setup-${info.version}${process.arch === 'arm64' ? '-arm64' : '-x64'}.dmg`
|
info.darwindownload = `https://github.com/dscalzi/HeliosLauncher/releases/download/v${info.version}/Helios-Launcher-setup-${info.version}${process.arch === 'arm64' ? '-arm64' : '-x64'}.dmg`
|
||||||
@ -57,7 +55,7 @@ if(!isDev){
|
|||||||
populateSettingsUpdateInformation(info)
|
populateSettingsUpdateInformation(info)
|
||||||
break
|
break
|
||||||
case 'update-downloaded':
|
case 'update-downloaded':
|
||||||
loggerAutoUpdaterSuccess.log('Update ' + info.version + ' ready to be installed.')
|
loggerAutoUpdater.info('Update ' + info.version + ' ready to be installed.')
|
||||||
settingsUpdateButtonStatus('Install Now', false, () => {
|
settingsUpdateButtonStatus('Install Now', false, () => {
|
||||||
if(!isDev){
|
if(!isDev){
|
||||||
ipcRenderer.send('autoUpdateAction', 'installUpdateNow')
|
ipcRenderer.send('autoUpdateAction', 'installUpdateNow')
|
||||||
@ -66,7 +64,7 @@ if(!isDev){
|
|||||||
showUpdateUI(info)
|
showUpdateUI(info)
|
||||||
break
|
break
|
||||||
case 'update-not-available':
|
case 'update-not-available':
|
||||||
loggerAutoUpdater.log('No new update found.')
|
loggerAutoUpdater.info('No new update found.')
|
||||||
settingsUpdateButtonStatus('Check for Updates')
|
settingsUpdateButtonStatus('Check for Updates')
|
||||||
break
|
break
|
||||||
case 'ready':
|
case 'ready':
|
||||||
@ -78,9 +76,9 @@ if(!isDev){
|
|||||||
case 'realerror':
|
case 'realerror':
|
||||||
if(info != null && info.code != null){
|
if(info != null && info.code != null){
|
||||||
if(info.code === 'ERR_UPDATER_INVALID_RELEASE_FEED'){
|
if(info.code === 'ERR_UPDATER_INVALID_RELEASE_FEED'){
|
||||||
loggerAutoUpdater.log('No suitable releases found.')
|
loggerAutoUpdater.info('No suitable releases found.')
|
||||||
} else if(info.code === 'ERR_XML_MISSED_ELEMENT'){
|
} else if(info.code === 'ERR_XML_MISSED_ELEMENT'){
|
||||||
loggerAutoUpdater.log('No releases found.')
|
loggerAutoUpdater.info('No releases found.')
|
||||||
} else {
|
} else {
|
||||||
loggerAutoUpdater.error('Error during update check..', info)
|
loggerAutoUpdater.error('Error during update check..', info)
|
||||||
loggerAutoUpdater.debug('Error Code:', info.code)
|
loggerAutoUpdater.debug('Error Code:', info.code)
|
||||||
@ -88,7 +86,7 @@ if(!isDev){
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
loggerAutoUpdater.log('Unknown argument', arg)
|
loggerAutoUpdater.info('Unknown argument', arg)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -131,12 +129,12 @@ function showUpdateUI(info){
|
|||||||
|
|
||||||
/* jQuery Example
|
/* jQuery Example
|
||||||
$(function(){
|
$(function(){
|
||||||
loggerUICore.log('UICore Initialized');
|
loggerUICore.info('UICore Initialized');
|
||||||
})*/
|
})*/
|
||||||
|
|
||||||
document.addEventListener('readystatechange', function () {
|
document.addEventListener('readystatechange', function () {
|
||||||
if (document.readyState === 'interactive'){
|
if (document.readyState === 'interactive'){
|
||||||
loggerUICore.log('UICore Initializing..')
|
loggerUICore.info('UICore Initializing..')
|
||||||
|
|
||||||
// Bind close button.
|
// Bind close button.
|
||||||
Array.from(document.getElementsByClassName('fCb')).map((val) => {
|
Array.from(document.getElementsByClassName('fCb')).map((val) => {
|
||||||
|
@ -122,13 +122,13 @@
|
|||||||
<span class="settingsTabHeaderText">Mod Settings</span>
|
<span class="settingsTabHeaderText">Mod Settings</span>
|
||||||
<span class="settingsTabHeaderDesc">Enable or disable mods.</span>
|
<span class="settingsTabHeaderDesc">Enable or disable mods.</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="settingsSelServContainer">
|
<div class="settingsSelServContainer">
|
||||||
<div id="settingsSelServContent">
|
<div class="settingsSelServContent">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div id="settingsSwitchServerContainer">
|
<div class="settingsSwitchServerContainer">
|
||||||
<div id="settingsSwitchServerContent">
|
<div class="settingsSwitchServerContent">
|
||||||
<button id="settingsSwitchServerButton">Switch</button>
|
<button class="settingsSwitchServerButton">Switch</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -172,6 +172,16 @@
|
|||||||
<span class="settingsTabHeaderText">Java Settings</span>
|
<span class="settingsTabHeaderText">Java Settings</span>
|
||||||
<span class="settingsTabHeaderDesc">Manage the Java configuration (advanced).</span>
|
<span class="settingsTabHeaderDesc">Manage the Java configuration (advanced).</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="settingsSelServContainer">
|
||||||
|
<div class="settingsSelServContent">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="settingsSwitchServerContainer">
|
||||||
|
<div class="settingsSwitchServerContent">
|
||||||
|
<button class="settingsSwitchServerButton">Switch</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="settingsMemoryContainer">
|
<div id="settingsMemoryContainer">
|
||||||
<div id="settingsMemoryTitle">Memory</div>
|
<div id="settingsMemoryTitle">Memory</div>
|
||||||
<div id="settingsMemoryContent">
|
<div id="settingsMemoryContent">
|
||||||
@ -179,7 +189,7 @@
|
|||||||
<div class="settingsMemoryContentItem">
|
<div class="settingsMemoryContentItem">
|
||||||
<span class="settingsMemoryHeader">Maximum RAM</span>
|
<span class="settingsMemoryHeader">Maximum RAM</span>
|
||||||
<div class="settingsMemoryActionContainer">
|
<div class="settingsMemoryActionContainer">
|
||||||
<div id="settingsMaxRAMRange" class="rangeSlider" cValue="MaxRAM" min="3" max="8" value="3" step="0.5">
|
<div id="settingsMaxRAMRange" class="rangeSlider" cValue="MaxRAM" serverDependent min="3" max="8" value="3" step="0.5">
|
||||||
<div class="rangeSliderBar"></div>
|
<div class="rangeSliderBar"></div>
|
||||||
<div class="rangeSliderTrack"></div>
|
<div class="rangeSliderTrack"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -189,7 +199,7 @@
|
|||||||
<div class="settingsMemoryContentItem">
|
<div class="settingsMemoryContentItem">
|
||||||
<span class="settingsMemoryHeader">Minimum RAM</span>
|
<span class="settingsMemoryHeader">Minimum RAM</span>
|
||||||
<div class="settingsMemoryActionContainer">
|
<div class="settingsMemoryActionContainer">
|
||||||
<div id="settingsMinRAMRange" class="rangeSlider" cValue="MinRAM" min="3" max="8" value="3" step="0.5">
|
<div id="settingsMinRAMRange" class="rangeSlider" cValue="MinRAM" serverDependent min="3" max="8" value="3" step="0.5">
|
||||||
<div class="rangeSliderBar"></div>
|
<div class="rangeSliderBar"></div>
|
||||||
<div class="rangeSliderTrack"></div>
|
<div class="rangeSliderTrack"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -231,11 +241,11 @@
|
|||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<input class="settingsFileSelVal" id="settingsJavaExecVal" type="text" value="null" cValue="JavaExecutable" disabled>
|
<input class="settingsFileSelVal" id="settingsJavaExecVal" type="text" value="null" cValue="JavaExecutable" serverDependent disabled>
|
||||||
<button class="settingsFileSelButton" id="settingsJavaExecSel" dialogTitle="Select Java Executable" dialogDirectory="false">Choose File</button>
|
<button class="settingsFileSelButton" id="settingsJavaExecSel" dialogTitle="Select Java Executable" dialogDirectory="false">Choose File</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settingsFileSelDesc">The Java executable is validated before game launch. <strong>Requires Java 8 x64.</strong><br>The path should end with <strong>bin<%= process.platform === 'win32' ? '\\javaw.exe' : '/java' %></strong>.</div>
|
<div class="settingsFileSelDesc">The Java executable is validated before game launch. <strong id="settingsJavaReqDesc">Requires Java 8 x64.</strong><br>The path should end with <strong>bin<%= process.platform === 'win32' ? '\\javaw.exe' : '/java' %></strong>.</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="settingsJVMOptsContainer">
|
<div id="settingsJVMOptsContainer">
|
||||||
<div id="settingsJVMOptsTitle">Additional JVM Options</div>
|
<div id="settingsJVMOptsTitle">Additional JVM Options</div>
|
||||||
@ -254,9 +264,9 @@
|
|||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<input id="settingsJVMOptsVal" cValue="JVMOptions" type="text">
|
<input id="settingsJVMOptsVal" cValue="JVMOptions" serverDependent type="text">
|
||||||
</div>
|
</div>
|
||||||
<div id="settingsJVMOptsDesc">Options to be provided to the JVM at runtime. <em>-Xms</em> and <em>-Xmx</em> should not be included.<br><a href="https://docs.oracle.com/javase/8/docs/technotes/tools/<%= process.platform === 'win32' ? 'windows' : 'unix' %>/java.html">Available Options for Java 8</a>.</div>
|
<div id="settingsJVMOptsDesc">Options to be provided to the JVM at runtime. <em>-Xms</em> and <em>-Xmx</em> should not be included.<br><a href="https://docs.oracle.com/javase/8/docs/technotes/tools/<%= process.platform === 'win32' ? 'windows' : 'unix' %>/java.html" id="settingsJvmOptsLink">Available Options for Java 8</a>.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="settingsTabLauncher" class="settingsTab" style="display: none;">
|
<div id="settingsTabLauncher" class="settingsTab" style="display: none;">
|
||||||
|
@ -208,6 +208,12 @@ The name of the module. Used on the UI.
|
|||||||
|
|
||||||
The type of the module.
|
The type of the module.
|
||||||
|
|
||||||
|
### `Module.classpath: boolean`
|
||||||
|
|
||||||
|
**OPTIONAL**
|
||||||
|
|
||||||
|
If the module is of type `Library`, whether the library should be added to the classpath. Defaults to true.
|
||||||
|
|
||||||
### `Module.required: Required`
|
### `Module.required: Required`
|
||||||
|
|
||||||
**OPTIONAL**
|
**OPTIONAL**
|
||||||
|
5719
package-lock.json
generated
5719
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "helioslauncher",
|
"name": "helioslauncher",
|
||||||
"version": "1.9.0",
|
"version": "1.10.0",
|
||||||
"productName": "Helios Launcher",
|
"productName": "Helios Launcher",
|
||||||
"description": "Modded Minecraft Launcher",
|
"description": "Modded Minecraft Launcher",
|
||||||
"author": "Daniel Scalzi (https://github.com/dscalzi/)",
|
"author": "Daniel Scalzi (https://github.com/dscalzi/)",
|
||||||
@ -20,31 +20,32 @@
|
|||||||
"lint": "eslint --config .eslintrc.json ."
|
"lint": "eslint --config .eslintrc.json ."
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "16.x.x"
|
"node": "18.x.x"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/remote": "^2.0.8",
|
"@electron/remote": "^2.0.8",
|
||||||
"adm-zip": "^0.5.9",
|
"adm-zip": "^0.5.9",
|
||||||
"async": "^3.2.3",
|
"async": "^3.2.4",
|
||||||
"discord-rpc-patch": "^4.0.1",
|
"discord-rpc-patch": "^4.0.1",
|
||||||
"ejs": "^3.1.8",
|
"ejs": "^3.1.8",
|
||||||
"ejs-electron": "^2.1.1",
|
"ejs-electron": "^2.1.1",
|
||||||
"electron-updater": "^5.0.1",
|
"electron-updater": "^5.3.0",
|
||||||
"fs-extra": "^10.1.0",
|
"fs-extra": "^11.1.0",
|
||||||
"github-syntax-dark": "^0.5.0",
|
"github-syntax-dark": "^0.5.0",
|
||||||
"got": "^11.8.3",
|
"got": "^11.8.5",
|
||||||
"helios-core": "~0.1.0",
|
"helios-core": "~0.1.2",
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.1",
|
||||||
|
"node-disk-info": "^1.3.0",
|
||||||
"node-stream-zip": "^1.15.0",
|
"node-stream-zip": "^1.15.0",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
"semver": "^7.3.7",
|
"semver": "^7.3.8",
|
||||||
"tar-fs": "^2.1.1",
|
"tar-fs": "^2.1.1",
|
||||||
"winreg": "^1.2.4"
|
"winreg": "^1.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"electron": "^18.2.4",
|
"electron": "^23.0.0",
|
||||||
"electron-builder": "^23.0.3",
|
"electron-builder": "^23.6.0",
|
||||||
"eslint": "^8.16.0"
|
"eslint": "^8.34.0"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
Loading…
Reference in New Issue
Block a user