1.17+ Support / Java Settings by Instance (#261)

* Patches to get 1.17 working, need to revise into real solutions.

* Add version.jar to cp until 1.17.

* Add server selection button to Java settings tab in preparation for by-instance java settings.

* Java settings by instance

* Use classpath flag instead of hardcode.

* Support 1.19.

* Fix refresh of java exec details.

* Add doc.

* Fix auto download of jdk 17.

* Dependency upgrade.
This commit is contained in:
Daniel Scalzi 2022-11-27 18:13:50 -05:00 committed by GitHub
parent 190bb4cf85
commit e3ee03ef73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 579 additions and 283 deletions

View File

@ -5,7 +5,7 @@
}, },
"extends": "eslint:recommended", "extends": "eslint:recommended",
"parserOptions": { "parserOptions": {
"ecmaVersion": 2019, "ecmaVersion": 2021,
"sourceType": "module" "sourceType": "module"
}, },
"rules": { "rules": {

View File

@ -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%;

View File

@ -5,6 +5,7 @@ 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 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')
@ -342,6 +343,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'){
@ -459,8 +463,13 @@ class JavaGuard extends EventEmitter {
let verString = props[i].split('=')[1].trim() let verString = props[i].split('=')[1].trim()
console.log(props[i].trim()) console.log(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,15 +477,15 @@ 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.
@ -804,15 +813,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'))
@ -1542,9 +1558,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')

View File

@ -63,6 +63,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 +92,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 +113,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
@ -177,7 +188,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 +522,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 +589,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 +601,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 +613,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 +625,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 +647,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 +659,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

View File

@ -118,7 +118,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 +143,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 +307,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

View File

@ -61,7 +61,7 @@ class ProcessBuilder {
logger.log('Launch Arguments:', args) logger.log('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()
}) })
@ -96,6 +96,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 +349,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 +387,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 +407,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 +512,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 +670,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 +709,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 +717,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 +754,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 +871,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()){

View File

@ -10,6 +10,7 @@ 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')
// Launch Elements // Launch Elements
@ -87,7 +88,7 @@ function setLaunchEnabled(val){
document.getElementById('launch_button').addEventListener('click', function(e){ document.getElementById('launch_button').addEventListener('click', function(e){
loggerLanding.log('Launching game..') loggerLanding.log('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 {
@ -140,13 +141,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)
} }
@ -318,6 +319,8 @@ function asyncSystemScan(mcVersion, launchAfter = true){
loggerSysAEx.log(data) loggerSysAEx.log(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'){
@ -326,14 +329,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(() => {
@ -341,7 +344,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'
) )
@ -360,7 +363,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.
@ -434,7 +437,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){
@ -506,7 +509,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'

View File

@ -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)
} }
@ -1056,7 +1076,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>
@ -1077,12 +1098,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)
})
}) })
/** /**
@ -1095,13 +1119,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)
}) })
} }
@ -1131,6 +1155,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()
@ -1338,12 +1364,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()
} }
/** /**

View File

@ -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)
})
}

View File

@ -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;">

View File

@ -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**

194
package-lock.json generated
View File

@ -21,6 +21,7 @@
"got": "^11.8.5", "got": "^11.8.5",
"helios-core": "~0.1.2", "helios-core": "~0.1.2",
"jquery": "^3.6.1", "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.8", "semver": "^7.3.8",
@ -28,9 +29,9 @@
"winreg": "^1.2.4" "winreg": "^1.2.4"
}, },
"devDependencies": { "devDependencies": {
"electron": "^21.2.2", "electron": "^21.3.1",
"electron-builder": "^23.6.0", "electron-builder": "^23.6.0",
"eslint": "^8.27.0" "eslint": "^8.28.0"
}, },
"engines": { "engines": {
"node": "16.x.x" "node": "16.x.x"
@ -482,14 +483,14 @@
} }
}, },
"node_modules/@types/cacheable-request": { "node_modules/@types/cacheable-request": {
"version": "6.0.2", "version": "6.0.3",
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
"integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
"dependencies": { "dependencies": {
"@types/http-cache-semantics": "*", "@types/http-cache-semantics": "*",
"@types/keyv": "*", "@types/keyv": "^3.1.4",
"@types/node": "*", "@types/node": "*",
"@types/responselike": "*" "@types/responselike": "^1.0.0"
} }
}, },
"node_modules/@types/debug": { "node_modules/@types/debug": {
@ -527,12 +528,11 @@
"integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ=="
}, },
"node_modules/@types/keyv": { "node_modules/@types/keyv": {
"version": "4.2.0", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-4.2.0.tgz", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
"integrity": "sha512-xoBtGl5R9jeKUhc8ZqeYaRDx04qqJ10yhhXYGmJ4Jr8qKpvMsDQQrNUvF/wUJ4klOtmJeJM+p2Xo3zp9uaC3tw==", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
"deprecated": "This is a stub types definition. keyv provides its own type definitions, so you do not need this installed.",
"dependencies": { "dependencies": {
"keyv": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/minimatch": { "node_modules/@types/minimatch": {
@ -585,9 +585,9 @@
"optional": true "optional": true
}, },
"node_modules/@types/yargs": { "node_modules/@types/yargs": {
"version": "17.0.13", "version": "17.0.14",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.14.tgz",
"integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "integrity": "sha512-9Pj7abXoW1RSTcZaL2Hk6G2XyLMlp5ECdVC/Zf2p/KBjC3srijLGgRAXOBjtFrJoIrvxdTKyKDA14bEcbxBaWw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/yargs-parser": "*" "@types/yargs-parser": "*"
@ -1086,10 +1086,13 @@
"dev": true "dev": true
}, },
"node_modules/ci-info": { "node_modules/ci-info": {
"version": "3.5.0", "version": "3.7.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz",
"integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==",
"dev": true "dev": true,
"engines": {
"node": ">=8"
}
}, },
"node_modules/cli-truncate": { "node_modules/cli-truncate": {
"version": "2.1.0", "version": "2.1.0",
@ -1523,9 +1526,9 @@
} }
}, },
"node_modules/electron": { "node_modules/electron": {
"version": "21.2.2", "version": "21.3.1",
"resolved": "https://registry.npmjs.org/electron/-/electron-21.2.2.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-21.3.1.tgz",
"integrity": "sha512-Q0j1tzLTM5JRjSJVAfDSONZgdtuyruHR1pc1y2IbMYQz62pVJWVWAvcJXzpty5iRh2HKzW9+B9WVlmfWNFA8ag==", "integrity": "sha512-Ik/I9oFHA1h32JRtRm6GMgYdUctFpF/tPnHyATg4r3LXBTUT6habGh3GxSdmmTa5JgtA7uJUEm8EjjZItk7T3g==",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@electron/get": "^1.14.1", "@electron/get": "^1.14.1",
@ -1710,9 +1713,9 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.27.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz",
"integrity": "sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==", "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint/eslintrc": "^1.3.3", "@eslint/eslintrc": "^1.3.3",
@ -2201,9 +2204,9 @@
} }
}, },
"node_modules/globals": { "node_modules/globals": {
"version": "13.17.0", "version": "13.18.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-13.18.0.tgz",
"integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", "integrity": "sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"type-fest": "^0.20.2" "type-fest": "^0.20.2"
@ -2439,7 +2442,6 @@
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"dependencies": { "dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0" "safer-buffer": ">= 2.1.2 < 3.0.0"
}, },
@ -2467,9 +2469,9 @@
] ]
}, },
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.2.0", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz",
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 4" "node": ">= 4"
@ -2639,10 +2641,14 @@
"integrity": "sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw==" "integrity": "sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw=="
}, },
"node_modules/js-sdsl": { "node_modules/js-sdsl": {
"version": "4.1.5", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz",
"integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==",
"dev": true "dev": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/js-sdsl"
}
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
"version": "4.1.0", "version": "4.1.0",
@ -2737,9 +2743,9 @@
} }
}, },
"node_modules/keyv": { "node_modules/keyv": {
"version": "4.5.1", "version": "4.5.2",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.1.tgz", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
"integrity": "sha512-DONNzZ8b9FLIRIX8kF+JByejgBoGUD4msUvRlHnPMqTb49MwW3thKgB6yGsshzOLW0Bol6SGu5TysvSsM6apdA==", "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==",
"dependencies": { "dependencies": {
"json-buffer": "3.0.1" "json-buffer": "3.0.1"
} }
@ -2914,9 +2920,9 @@
} }
}, },
"node_modules/minipass": { "node_modules/minipass": {
"version": "3.3.4", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
@ -2973,6 +2979,17 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"node_modules/node-disk-info": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/node-disk-info/-/node-disk-info-1.3.0.tgz",
"integrity": "sha512-NEx858vJZ0AoBtmD/ChBIHLjFTF28xCsDIgmFl4jtGKsvlUx9DU/OrMDjvj3qp/E4hzLN0HvTg7eJx5XFQvbeg==",
"dependencies": {
"iconv-lite": "^0.6.2"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/node-fetch": { "node_modules/node-fetch": {
"version": "2.6.7", "version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@ -3595,9 +3612,9 @@
} }
}, },
"node_modules/simple-update-notifier": { "node_modules/simple-update-notifier": {
"version": "1.0.7", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz",
"integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"semver": "~7.0.0" "semver": "~7.0.0"
@ -4559,14 +4576,14 @@
"dev": true "dev": true
}, },
"@types/cacheable-request": { "@types/cacheable-request": {
"version": "6.0.2", "version": "6.0.3",
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
"integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
"requires": { "requires": {
"@types/http-cache-semantics": "*", "@types/http-cache-semantics": "*",
"@types/keyv": "*", "@types/keyv": "^3.1.4",
"@types/node": "*", "@types/node": "*",
"@types/responselike": "*" "@types/responselike": "^1.0.0"
} }
}, },
"@types/debug": { "@types/debug": {
@ -4604,11 +4621,11 @@
"integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ=="
}, },
"@types/keyv": { "@types/keyv": {
"version": "4.2.0", "version": "3.1.4",
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-4.2.0.tgz", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
"integrity": "sha512-xoBtGl5R9jeKUhc8ZqeYaRDx04qqJ10yhhXYGmJ4Jr8qKpvMsDQQrNUvF/wUJ4klOtmJeJM+p2Xo3zp9uaC3tw==", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
"requires": { "requires": {
"keyv": "*" "@types/node": "*"
} }
}, },
"@types/minimatch": { "@types/minimatch": {
@ -4661,9 +4678,9 @@
"optional": true "optional": true
}, },
"@types/yargs": { "@types/yargs": {
"version": "17.0.13", "version": "17.0.14",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.14.tgz",
"integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==", "integrity": "sha512-9Pj7abXoW1RSTcZaL2Hk6G2XyLMlp5ECdVC/Zf2p/KBjC3srijLGgRAXOBjtFrJoIrvxdTKyKDA14bEcbxBaWw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/yargs-parser": "*" "@types/yargs-parser": "*"
@ -5051,9 +5068,9 @@
"dev": true "dev": true
}, },
"ci-info": { "ci-info": {
"version": "3.5.0", "version": "3.7.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz",
"integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==",
"dev": true "dev": true
}, },
"cli-truncate": { "cli-truncate": {
@ -5397,9 +5414,9 @@
} }
}, },
"electron": { "electron": {
"version": "21.2.2", "version": "21.3.1",
"resolved": "https://registry.npmjs.org/electron/-/electron-21.2.2.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-21.3.1.tgz",
"integrity": "sha512-Q0j1tzLTM5JRjSJVAfDSONZgdtuyruHR1pc1y2IbMYQz62pVJWVWAvcJXzpty5iRh2HKzW9+B9WVlmfWNFA8ag==", "integrity": "sha512-Ik/I9oFHA1h32JRtRm6GMgYdUctFpF/tPnHyATg4r3LXBTUT6habGh3GxSdmmTa5JgtA7uJUEm8EjjZItk7T3g==",
"requires": { "requires": {
"@electron/get": "^1.14.1", "@electron/get": "^1.14.1",
"@types/node": "^16.11.26", "@types/node": "^16.11.26",
@ -5546,9 +5563,9 @@
"devOptional": true "devOptional": true
}, },
"eslint": { "eslint": {
"version": "8.27.0", "version": "8.28.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.27.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.28.0.tgz",
"integrity": "sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==", "integrity": "sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@eslint/eslintrc": "^1.3.3", "@eslint/eslintrc": "^1.3.3",
@ -5931,9 +5948,9 @@
} }
}, },
"globals": { "globals": {
"version": "13.17.0", "version": "13.18.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-13.18.0.tgz",
"integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", "integrity": "sha512-/mR4KI8Ps2spmoc0Ulu9L7agOF0du1CZNQ3dke8yItYlyKNmGrkONemBbd6V8UTc1Wgcqn21t3WYB7dbRmh6/A==",
"dev": true, "dev": true,
"requires": { "requires": {
"type-fest": "^0.20.2" "type-fest": "^0.20.2"
@ -6107,7 +6124,6 @@
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"requires": { "requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0" "safer-buffer": ">= 2.1.2 < 3.0.0"
} }
@ -6118,9 +6134,9 @@
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
}, },
"ignore": { "ignore": {
"version": "5.2.0", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz",
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==",
"dev": true "dev": true
}, },
"import-fresh": { "import-fresh": {
@ -6245,9 +6261,9 @@
"integrity": "sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw==" "integrity": "sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw=="
}, },
"js-sdsl": { "js-sdsl": {
"version": "4.1.5", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz",
"integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==",
"dev": true "dev": true
}, },
"js-yaml": { "js-yaml": {
@ -6328,9 +6344,9 @@
} }
}, },
"keyv": { "keyv": {
"version": "4.5.1", "version": "4.5.2",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.1.tgz", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
"integrity": "sha512-DONNzZ8b9FLIRIX8kF+JByejgBoGUD4msUvRlHnPMqTb49MwW3thKgB6yGsshzOLW0Bol6SGu5TysvSsM6apdA==", "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==",
"requires": { "requires": {
"json-buffer": "3.0.1" "json-buffer": "3.0.1"
} }
@ -6463,9 +6479,9 @@
"dev": true "dev": true
}, },
"minipass": { "minipass": {
"version": "3.3.4", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dev": true, "dev": true,
"requires": { "requires": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
@ -6510,6 +6526,14 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"node-disk-info": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/node-disk-info/-/node-disk-info-1.3.0.tgz",
"integrity": "sha512-NEx858vJZ0AoBtmD/ChBIHLjFTF28xCsDIgmFl4jtGKsvlUx9DU/OrMDjvj3qp/E4hzLN0HvTg7eJx5XFQvbeg==",
"requires": {
"iconv-lite": "^0.6.2"
}
},
"node-fetch": { "node-fetch": {
"version": "2.6.7", "version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@ -6936,9 +6960,9 @@
} }
}, },
"simple-update-notifier": { "simple-update-notifier": {
"version": "1.0.7", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz",
"integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==",
"dev": true, "dev": true,
"requires": { "requires": {
"semver": "~7.0.0" "semver": "~7.0.0"

View File

@ -35,6 +35,7 @@
"got": "^11.8.5", "got": "^11.8.5",
"helios-core": "~0.1.2", "helios-core": "~0.1.2",
"jquery": "^3.6.1", "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.8", "semver": "^7.3.8",
@ -42,9 +43,9 @@
"winreg": "^1.2.4" "winreg": "^1.2.4"
}, },
"devDependencies": { "devDependencies": {
"electron": "^21.2.2", "electron": "^21.3.1",
"electron-builder": "^23.6.0", "electron-builder": "^23.6.0",
"eslint": "^8.27.0" "eslint": "^8.28.0"
}, },
"repository": { "repository": {
"type": "git", "type": "git",