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:
@@ -1228,6 +1228,59 @@ body, button {
|
||||
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. */
|
||||
#settingsContainer input[type=number]::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
@@ -1638,59 +1691,6 @@ input:checked + .toggleSwitchSlider:before {
|
||||
* 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. */
|
||||
#settingsModsContainer {
|
||||
width: 75%;
|
||||
|
||||
@@ -5,6 +5,7 @@ const child_process = require('child_process')
|
||||
const crypto = require('crypto')
|
||||
const EventEmitter = require('events')
|
||||
const fs = require('fs-extra')
|
||||
const nodeDiskInfo = require('node-disk-info')
|
||||
const StreamZip = require('node-stream-zip')
|
||||
const path = require('path')
|
||||
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.
|
||||
*/
|
||||
static isJavaExecPath(pth){
|
||||
if(pth == null) {
|
||||
return false
|
||||
}
|
||||
if(process.platform === 'win32'){
|
||||
return pth.endsWith(path.join('bin', 'javaw.exe'))
|
||||
} else if(process.platform === 'darwin'){
|
||||
@@ -459,25 +463,30 @@ class JavaGuard extends EventEmitter {
|
||||
let verString = props[i].split('=')[1].trim()
|
||||
console.log(props[i].trim())
|
||||
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){
|
||||
// Java 8
|
||||
if(verOb.major === 8 && verOb.update > 52){
|
||||
if(!Util.mcVersionAtLeast('1.17', this.mcVersion)){
|
||||
if(verOb.major === 8 && verOb.update > 52){
|
||||
meta.version = verOb
|
||||
++checksum
|
||||
if(checksum === goal){
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(verOb.major >= 17) {
|
||||
// Java 9+
|
||||
if(Util.mcVersionAtLeast('1.17', this.mcVersion)){
|
||||
meta.version = verOb
|
||||
++checksum
|
||||
if(checksum === goal){
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Java 9+
|
||||
if(Util.mcVersionAtLeast('1.13', this.mcVersion)){
|
||||
console.log('Java 9+ not yet tested.')
|
||||
/* meta.version = verOb
|
||||
++checksum
|
||||
if(checksum === goal){
|
||||
break
|
||||
} */
|
||||
}
|
||||
}
|
||||
// Space included so we get only the vendor.
|
||||
} else if(props[i].lastIndexOf('java.vendor ') > -1) {
|
||||
@@ -804,13 +813,20 @@ class JavaGuard extends EventEmitter {
|
||||
// Get possible paths from the registry.
|
||||
let pathSet1 = await JavaGuard._scanRegistry()
|
||||
if(pathSet1.size === 0){
|
||||
|
||||
// Do a manual file system scan of program files.
|
||||
pathSet1 = new Set([
|
||||
...pathSet1,
|
||||
...(await JavaGuard._scanFileSystem('C:\\Program Files\\Java')),
|
||||
...(await JavaGuard._scanFileSystem('C:\\Program Files\\Eclipse Foundation')),
|
||||
...(await JavaGuard._scanFileSystem('C:\\Program Files\\AdoptOpenJDK'))
|
||||
])
|
||||
// Check all drives
|
||||
const driveMounts = nodeDiskInfo.getDiskInfoSync().map(({ mounted }) => mounted)
|
||||
for(const mount of driveMounts) {
|
||||
pathSet1 = new Set([
|
||||
...pathSet1,
|
||||
...(await JavaGuard._scanFileSystem(`${mount}\\Program Files\\Java`)),
|
||||
...(await JavaGuard._scanFileSystem(`${mount}\\Program Files\\Eclipse Adoptium`)),
|
||||
...(await JavaGuard._scanFileSystem(`${mount}\\Program Files\\Eclipse Foundation`)),
|
||||
...(await JavaGuard._scanFileSystem(`${mount}\\Program Files\\AdoptOpenJDK`))
|
||||
])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Get possible paths from the data directory.
|
||||
@@ -1542,9 +1558,10 @@ class AssetGuard extends EventEmitter {
|
||||
// Java (Category=''') Validation (download) Functions
|
||||
// #region
|
||||
|
||||
_enqueueOpenJDK(dataDir){
|
||||
_enqueueOpenJDK(dataDir, mcVersion){
|
||||
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){
|
||||
|
||||
dataDir = path.join(dataDir, 'runtime', 'x64')
|
||||
|
||||
@@ -63,6 +63,27 @@ function resolveMinRAM(){
|
||||
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:
|
||||
* Static = Explicitly declared.
|
||||
@@ -71,17 +92,6 @@ function resolveMinRAM(){
|
||||
*/
|
||||
const DEFAULT_CONFIG = {
|
||||
settings: {
|
||||
java: {
|
||||
minRAM: resolveMinRAM(),
|
||||
maxRAM: resolveMaxRAM(), // Dynamic
|
||||
executable: null,
|
||||
jvmOptions: [
|
||||
'-XX:+UseConcMarkSweepGC',
|
||||
'-XX:+CMSIncrementalMode',
|
||||
'-XX:-UseAdaptiveSizePolicy',
|
||||
'-Xmn128M'
|
||||
],
|
||||
},
|
||||
game: {
|
||||
resWidth: 1280,
|
||||
resHeight: 720,
|
||||
@@ -103,7 +113,8 @@ const DEFAULT_CONFIG = {
|
||||
selectedServer: null, // Resolved
|
||||
selectedAccount: null,
|
||||
authenticationDatabase: {},
|
||||
modConfigurations: []
|
||||
modConfigurations: [],
|
||||
javaConfig: {}
|
||||
}
|
||||
|
||||
let config = null
|
||||
@@ -177,7 +188,7 @@ function validateKeySet(srcObj, destObj){
|
||||
if(srcObj == null){
|
||||
srcObj = {}
|
||||
}
|
||||
const validationBlacklist = ['authenticationDatabase']
|
||||
const validationBlacklist = ['authenticationDatabase', 'javaConfig']
|
||||
const keys = Object.keys(srcObj)
|
||||
for(let i=0; i<keys.length; i++){
|
||||
if(typeof destObj[keys[i]] === 'undefined'){
|
||||
@@ -511,16 +522,66 @@ exports.setModConfiguration = function(serverid, configuration){
|
||||
|
||||
// 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
|
||||
* contains the units of memory. For example, '5G' = 5 GigaBytes, '1024M' =
|
||||
* 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.
|
||||
*/
|
||||
exports.getMinRAM = function(def = false){
|
||||
return !def ? config.settings.java.minRAM : DEFAULT_CONFIG.settings.java.minRAM
|
||||
exports.getMinRAM = function(serverid){
|
||||
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' =
|
||||
* 1024 MegaBytes, etc.
|
||||
*
|
||||
* @param {string} serverid The server id.
|
||||
* @param {string} minRAM The new minimum amount of memory for JVM initialization.
|
||||
*/
|
||||
exports.setMinRAM = function(minRAM){
|
||||
config.settings.java.minRAM = minRAM
|
||||
exports.setMinRAM = function(serverid, 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' =
|
||||
* 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.
|
||||
*/
|
||||
exports.getMaxRAM = function(def = false){
|
||||
return !def ? config.settings.java.maxRAM : resolveMaxRAM()
|
||||
exports.getMaxRAM = function(serverid){
|
||||
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' =
|
||||
* 1024 MegaBytes, etc.
|
||||
*
|
||||
* @param {string} serverid The server id.
|
||||
* @param {string} maxRAM The new maximum amount of memory for JVM initialization.
|
||||
*/
|
||||
exports.setMaxRAM = function(maxRAM){
|
||||
config.settings.java.maxRAM = maxRAM
|
||||
exports.setMaxRAM = function(serverid, 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.
|
||||
*
|
||||
* @param {string} serverid The server id.
|
||||
* @returns {string} The path of the Java Executable.
|
||||
*/
|
||||
exports.getJavaExecutable = function(){
|
||||
return config.settings.java.executable
|
||||
exports.getJavaExecutable = function(serverid){
|
||||
return config.javaConfig[serverid].executable
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path of the Java Executable.
|
||||
*
|
||||
* @param {string} serverid The server id.
|
||||
* @param {string} executable The new path of the Java Executable.
|
||||
*/
|
||||
exports.setJavaExecutable = function(executable){
|
||||
config.settings.java.executable = executable
|
||||
exports.setJavaExecutable = function(serverid, 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
|
||||
* 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.
|
||||
*/
|
||||
exports.getJVMOptions = function(def = false){
|
||||
return !def ? config.settings.java.jvmOptions : DEFAULT_CONFIG.settings.java.jvmOptions
|
||||
exports.getJVMOptions = function(serverid){
|
||||
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
|
||||
* included in this value.
|
||||
*
|
||||
* @param {string} serverid The server id.
|
||||
* @param {Array.<string>} jvmOptions An array of the new additional arguments for JVM
|
||||
* initialization.
|
||||
*/
|
||||
exports.setJVMOptions = function(jvmOptions){
|
||||
config.settings.java.jvmOptions = jvmOptions
|
||||
exports.setJVMOptions = function(serverid, jvmOptions){
|
||||
config.javaConfig[serverid].jvmOptions = jvmOptions
|
||||
}
|
||||
|
||||
// Game Settings
|
||||
|
||||
@@ -118,7 +118,7 @@ class Module {
|
||||
* @returns {Module} The parsed Module.
|
||||
*/
|
||||
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.type = type
|
||||
this.classpath = classpath
|
||||
this._resolveMetaData()
|
||||
this.name = name
|
||||
this.required = Required.fromJSON(required)
|
||||
@@ -306,6 +307,13 @@ class Module {
|
||||
return this.type
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean} Whether or not this library should be on the classpath.
|
||||
*/
|
||||
getClasspath(){
|
||||
return this.classpath ?? true
|
||||
}
|
||||
|
||||
}
|
||||
exports.Module
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ class ProcessBuilder {
|
||||
|
||||
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,
|
||||
detached: ConfigManager.getLaunchDetached()
|
||||
})
|
||||
@@ -96,6 +96,16 @@ class ProcessBuilder {
|
||||
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
|
||||
* configuration value is null, the required object will be used to
|
||||
@@ -339,16 +349,16 @@ class ProcessBuilder {
|
||||
|
||||
// Classpath Argument
|
||||
args.push('-cp')
|
||||
args.push(this.classpathArg(mods, tempNativePath).join(process.platform === 'win32' ? ';' : ':'))
|
||||
args.push(this.classpathArg(mods, tempNativePath).join(ProcessBuilder.getClasspathSeparator()))
|
||||
|
||||
// Java Arguments
|
||||
if(process.platform === 'darwin'){
|
||||
args.push('-Xdock:name=HeliosLauncher')
|
||||
args.push('-Xdock:icon=' + path.join(__dirname, '..', 'images', 'minecraft.icns'))
|
||||
}
|
||||
args.push('-Xmx' + ConfigManager.getMaxRAM())
|
||||
args.push('-Xms' + ConfigManager.getMinRAM())
|
||||
args = args.concat(ConfigManager.getJVMOptions())
|
||||
args.push('-Xmx' + ConfigManager.getMaxRAM(this.server.getID()))
|
||||
args.push('-Xms' + ConfigManager.getMinRAM(this.server.getID()))
|
||||
args = args.concat(ConfigManager.getJVMOptions(this.server.getID()))
|
||||
args.push('-Djava.library.path=' + tempNativePath)
|
||||
|
||||
// Main Java Class
|
||||
@@ -377,6 +387,19 @@ class ProcessBuilder {
|
||||
// JVM Arguments First
|
||||
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')
|
||||
|
||||
// Java Arguments
|
||||
@@ -384,9 +407,9 @@ class ProcessBuilder {
|
||||
args.push('-Xdock:name=HeliosLauncher')
|
||||
args.push('-Xdock:icon=' + path.join(__dirname, '..', 'images', 'minecraft.icns'))
|
||||
}
|
||||
args.push('-Xmx' + ConfigManager.getMaxRAM())
|
||||
args.push('-Xms' + ConfigManager.getMinRAM())
|
||||
args = args.concat(ConfigManager.getJVMOptions())
|
||||
args.push('-Xmx' + ConfigManager.getMaxRAM(this.server.getID()))
|
||||
args.push('-Xms' + ConfigManager.getMinRAM(this.server.getID()))
|
||||
args = args.concat(ConfigManager.getJVMOptions(this.server.getID()))
|
||||
|
||||
// Main Java Class
|
||||
args.push(this.forgeData.mainClass)
|
||||
@@ -489,7 +512,7 @@ class ProcessBuilder {
|
||||
val = args[i].replace(argDiscovery, this.launcherVersion)
|
||||
break
|
||||
case 'classpath':
|
||||
val = this.classpathArg(mods, tempNativePath).join(process.platform === 'win32' ? ';' : ':')
|
||||
val = this.classpathArg(mods, tempNativePath).join(ProcessBuilder.getClasspathSeparator())
|
||||
break
|
||||
}
|
||||
if(val != null){
|
||||
@@ -647,9 +670,13 @@ class ProcessBuilder {
|
||||
classpathArg(mods, tempNativePath){
|
||||
let cpArgs = []
|
||||
|
||||
// Add the version.jar to the classpath.
|
||||
const version = this.versionData.id
|
||||
cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
|
||||
if(!Util.mcVersionAtLeast('1.17', this.server.getMinecraftVersion())) {
|
||||
// Add the version.jar to the classpath.
|
||||
// Must not be added to the classpath for Forge 1.17+.
|
||||
const version = this.versionData.id
|
||||
cpArgs.push(path.join(this.commonDir, 'versions', version, version + '.jar'))
|
||||
}
|
||||
|
||||
|
||||
if(this.usingLiteLoader){
|
||||
cpArgs.push(this.llPath)
|
||||
@@ -682,6 +709,7 @@ class ProcessBuilder {
|
||||
* @returns {{[id: string]: string}} An object containing the paths of each library mojang declares.
|
||||
*/
|
||||
_resolveMojangLibraries(tempNativePath){
|
||||
const nativesRegex = /.+:natives-([^-]+)(?:-(.+))?/
|
||||
const libs = {}
|
||||
|
||||
const libArr = this.versionData.libraries
|
||||
@@ -689,27 +717,23 @@ class ProcessBuilder {
|
||||
for(let i=0; i<libArr.length; i++){
|
||||
const lib = libArr[i]
|
||||
if(Library.validateRules(lib.rules, lib.natives)){
|
||||
if(lib.natives == null){
|
||||
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
|
||||
} else {
|
||||
|
||||
// Pre-1.19 has a natives object.
|
||||
if(lib.natives != null) {
|
||||
// Extract the native library.
|
||||
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', ''))]
|
||||
|
||||
|
||||
// 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++){
|
||||
const fileName = zipEntries[i].entryName
|
||||
|
||||
|
||||
let shouldExclude = false
|
||||
|
||||
// Exclude noted files.
|
||||
@@ -727,9 +751,68 @@ 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,7 +871,10 @@ class ProcessBuilder {
|
||||
let libs = []
|
||||
for(let sm of mdl.getSubModules()){
|
||||
if(sm.getType() === DistroManager.Types.Library){
|
||||
libs.push(sm.getArtifact().getPath())
|
||||
|
||||
if(sm.getClasspath()) {
|
||||
libs.push(sm.getArtifact().getPath())
|
||||
}
|
||||
}
|
||||
// If this module has submodules, we need to resolve the libraries for those.
|
||||
// To avoid unnecessary recursive calls, base case is checked here.
|
||||
|
||||
@@ -10,6 +10,7 @@ const { MojangRestAPI, getServerStatus } = require('helios-core/mojang')
|
||||
// Internal Requirements
|
||||
const DiscordWrapper = require('./assets/js/discordwrapper')
|
||||
const ProcessBuilder = require('./assets/js/processbuilder')
|
||||
const { Util } = require('./assets/js/assetguard')
|
||||
const { RestResponseStatus, isDisplayableError } = require('helios-core/common')
|
||||
|
||||
// Launch Elements
|
||||
@@ -87,7 +88,7 @@ function setLaunchEnabled(val){
|
||||
document.getElementById('launch_button').addEventListener('click', function(e){
|
||||
loggerLanding.log('Launching game..')
|
||||
const mcVersion = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer()).getMinecraftVersion()
|
||||
const jExe = ConfigManager.getJavaExecutable()
|
||||
const jExe = ConfigManager.getJavaExecutable(ConfigManager.getSelectedServer())
|
||||
if(jExe == null){
|
||||
asyncSystemScan(mcVersion)
|
||||
} else {
|
||||
@@ -140,13 +141,13 @@ updateSelectedAccount(ConfigManager.getSelectedAccount())
|
||||
// Bind selected server
|
||||
function updateSelectedServer(serv){
|
||||
if(getCurrentView() === VIEWS.settings){
|
||||
saveAllModConfigurations()
|
||||
fullSettingsSave()
|
||||
}
|
||||
ConfigManager.setSelectedServer(serv != null ? serv.getID() : null)
|
||||
ConfigManager.save()
|
||||
server_selection_button.innerHTML = '\u2022 ' + (serv != null ? serv.getName() : 'No Server Selected')
|
||||
if(getCurrentView() === VIEWS.settings){
|
||||
animateModsTabRefresh()
|
||||
animateSettingsTabRefresh()
|
||||
}
|
||||
setLaunchEnabled(serv != null)
|
||||
}
|
||||
@@ -317,6 +318,8 @@ function asyncSystemScan(mcVersion, launchAfter = true){
|
||||
sysAEx.stdio[2].on('data', (data) => {
|
||||
loggerSysAEx.log(data)
|
||||
})
|
||||
|
||||
const javaVer = Util.mcVersionAtLeast('1.17', mcVersion) ? '17' : '8'
|
||||
|
||||
sysAEx.on('message', (m) => {
|
||||
|
||||
@@ -326,14 +329,14 @@ function asyncSystemScan(mcVersion, launchAfter = true){
|
||||
// Show this information to the user.
|
||||
setOverlayContent(
|
||||
'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 Manually'
|
||||
)
|
||||
setOverlayHandler(() => {
|
||||
setLaunchDetails('Preparing Java Download..')
|
||||
sysAEx.send({task: 'changeContext', class: 'AssetGuard', args: [ConfigManager.getCommonDirectory(),ConfigManager.getJavaExecutable()]})
|
||||
sysAEx.send({task: 'execute', function: '_enqueueOpenJDK', argsArr: [ConfigManager.getDataDirectory()]})
|
||||
sysAEx.send({task: 'changeContext', class: 'AssetGuard', args: [ConfigManager.getCommonDirectory(),ConfigManager.getJavaExecutable(ConfigManager.getSelectedServer())]})
|
||||
sysAEx.send({task: 'execute', function: '_enqueueOpenJDK', argsArr: [ConfigManager.getDataDirectory(), mcVersion]})
|
||||
toggleOverlay(false)
|
||||
})
|
||||
setDismissHandler(() => {
|
||||
@@ -341,7 +344,7 @@ function asyncSystemScan(mcVersion, launchAfter = true){
|
||||
//$('#overlayDismiss').toggle(false)
|
||||
setOverlayContent(
|
||||
'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',
|
||||
'Go Back'
|
||||
)
|
||||
@@ -360,7 +363,7 @@ function asyncSystemScan(mcVersion, launchAfter = true){
|
||||
|
||||
} else {
|
||||
// Java installation found, use this to launch the game.
|
||||
ConfigManager.setJavaExecutable(m.result)
|
||||
ConfigManager.setJavaExecutable(ConfigManager.getSelectedServer(), m.result)
|
||||
ConfigManager.save()
|
||||
|
||||
// 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)
|
||||
|
||||
// Extraction completed successfully.
|
||||
ConfigManager.setJavaExecutable(m.args[0])
|
||||
ConfigManager.setJavaExecutable(ConfigManager.getSelectedServer(), m.args[0])
|
||||
ConfigManager.save()
|
||||
|
||||
if(extractListener != null){
|
||||
@@ -506,7 +509,7 @@ function dlAsync(login = true){
|
||||
aEx = cp.fork(path.join(__dirname, 'assets', 'js', 'assetexec.js'), [
|
||||
'AssetGuard',
|
||||
ConfigManager.getCommonDirectory(),
|
||||
ConfigManager.getJavaExecutable()
|
||||
ConfigManager.getJavaExecutable(ConfigManager.getSelectedServer())
|
||||
], {
|
||||
env: forkEnv,
|
||||
stdio: 'pipe'
|
||||
|
||||
@@ -127,29 +127,34 @@ function initSettingsValues(){
|
||||
const sEls = document.getElementById('settingsContainer').querySelectorAll('[cValue]')
|
||||
Array.from(sEls).map((v, index, arr) => {
|
||||
const cVal = v.getAttribute('cValue')
|
||||
const serverDependent = v.hasAttribute('serverDependent') // Means the first argument is the server id.
|
||||
const gFn = ConfigManager['get' + cVal]
|
||||
const gFnOpts = []
|
||||
if(serverDependent) {
|
||||
gFnOpts.push(ConfigManager.getSelectedServer())
|
||||
}
|
||||
if(typeof gFn === 'function'){
|
||||
if(v.tagName === 'INPUT'){
|
||||
if(v.type === 'number' || v.type === 'text'){
|
||||
// Special Conditions
|
||||
if(cVal === 'JavaExecutable'){
|
||||
v.value = gFn.apply(null, gFnOpts)
|
||||
populateJavaExecDetails(v.value)
|
||||
v.value = gFn()
|
||||
} else if (cVal === 'DataDirectory'){
|
||||
v.value = gFn()
|
||||
v.value = gFn.apply(null, gFnOpts)
|
||||
} else if(cVal === 'JVMOptions'){
|
||||
v.value = gFn().join(' ')
|
||||
v.value = gFn.apply(null, gFnOpts).join(' ')
|
||||
} else {
|
||||
v.value = gFn()
|
||||
v.value = gFn.apply(null, gFnOpts)
|
||||
}
|
||||
} else if(v.type === 'checkbox'){
|
||||
v.checked = gFn()
|
||||
v.checked = gFn.apply(null, gFnOpts)
|
||||
}
|
||||
} else if(v.tagName === 'DIV'){
|
||||
if(v.classList.contains('rangeSlider')){
|
||||
// Special Conditions
|
||||
if(cVal === 'MinRAM' || cVal === 'MaxRAM'){
|
||||
let val = gFn()
|
||||
let val = gFn.apply(null, gFnOpts)
|
||||
if(val.endsWith('M')){
|
||||
val = Number(val.substring(0, val.length-1))/1000
|
||||
} else {
|
||||
@@ -158,7 +163,7 @@ function initSettingsValues(){
|
||||
|
||||
v.setAttribute('value', val)
|
||||
} 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]')
|
||||
Array.from(sEls).map((v, index, arr) => {
|
||||
const cVal = v.getAttribute('cValue')
|
||||
const serverDependent = v.hasAttribute('serverDependent') // Means the first argument is the server id.
|
||||
const sFn = ConfigManager['set' + cVal]
|
||||
const sFnOpts = []
|
||||
if(serverDependent) {
|
||||
sFnOpts.push(ConfigManager.getSelectedServer())
|
||||
}
|
||||
if(typeof sFn === 'function'){
|
||||
if(v.tagName === 'INPUT'){
|
||||
if(v.type === 'number' || v.type === 'text'){
|
||||
// Special Conditions
|
||||
if(cVal === 'JVMOptions'){
|
||||
if(!v.value.trim()) {
|
||||
sFn([])
|
||||
sFnOpts.push([])
|
||||
sFn.apply(null, sFnOpts)
|
||||
} else {
|
||||
sFn(v.value.trim().split(/\s+/))
|
||||
sFnOpts.push(v.value.trim().split(/\s+/))
|
||||
sFn.apply(null, sFnOpts)
|
||||
}
|
||||
} else {
|
||||
sFn(v.value)
|
||||
sFnOpts.push(v.value)
|
||||
sFn.apply(null, sFnOpts)
|
||||
}
|
||||
} else if(v.type === 'checkbox'){
|
||||
sFn(v.checked)
|
||||
sFnOpts.push(v.checked)
|
||||
sFn.apply(null, sFnOpts)
|
||||
// Special Conditions
|
||||
if(cVal === 'AllowPrerelease'){
|
||||
changeAllowPrerelease(v.checked)
|
||||
@@ -206,9 +220,11 @@ function saveSettingsValues(){
|
||||
val = val + 'G'
|
||||
}
|
||||
|
||||
sFn(val)
|
||||
sFnOpts.push(val)
|
||||
sFn.apply(null, sFnOpts)
|
||||
} else {
|
||||
sFn(v.getAttribute('value'))
|
||||
sFnOpts.push(v.getAttribute('value'))
|
||||
sFn.apply(null, sFnOpts)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,13 +321,17 @@ function settingsSaveDisabled(v){
|
||||
settingsNavDone.disabled = v
|
||||
}
|
||||
|
||||
/* Closes the settings view and saves all data. */
|
||||
settingsNavDone.onclick = () => {
|
||||
function fullSettingsSave() {
|
||||
saveSettingsValues()
|
||||
saveModConfiguration()
|
||||
ConfigManager.save()
|
||||
saveDropinModConfiguration()
|
||||
saveShaderpackSettings()
|
||||
}
|
||||
|
||||
/* Closes the settings view and saves all data. */
|
||||
settingsNavDone.onclick = () => {
|
||||
fullSettingsSave()
|
||||
switchView(getCurrentView(), VIEWS.landing)
|
||||
}
|
||||
|
||||
@@ -1056,33 +1076,37 @@ function bindShaderpackButton() {
|
||||
function loadSelectedServerOnModsTab(){
|
||||
const serv = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer())
|
||||
|
||||
document.getElementById('settingsSelServContent').innerHTML = `
|
||||
<img class="serverListingImg" src="${serv.getIcon()}"/>
|
||||
<div class="serverListingDetails">
|
||||
<span class="serverListingName">${serv.getName()}</span>
|
||||
<span class="serverListingDescription">${serv.getDescription()}</span>
|
||||
<div class="serverListingInfo">
|
||||
<div class="serverListingVersion">${serv.getMinecraftVersion()}</div>
|
||||
<div class="serverListingRevision">${serv.getVersion()}</div>
|
||||
${serv.isMainServer() ? `<div class="serverListingStarWrapper">
|
||||
<svg id="Layer_1" viewBox="0 0 107.45 104.74" width="20px" height="20px">
|
||||
<defs>
|
||||
<style>.cls-1{fill:#fff;}.cls-2{fill:none;stroke:#fff;stroke-miterlimit:10;}</style>
|
||||
</defs>
|
||||
<path class="cls-1" d="M100.93,65.54C89,62,68.18,55.65,63.54,52.13c2.7-5.23,18.8-19.2,28-27.55C81.36,31.74,63.74,43.87,58.09,45.3c-2.41-5.37-3.61-26.52-4.37-39-.77,12.46-2,33.64-4.36,39-5.7-1.46-23.3-13.57-33.49-20.72,9.26,8.37,25.39,22.36,28,27.55C39.21,55.68,18.47,62,6.52,65.55c12.32-2,33.63-6.06,39.34-4.9-.16,5.87-8.41,26.16-13.11,37.69,6.1-10.89,16.52-30.16,21-33.9,4.5,3.79,14.93,23.09,21,34C70,86.84,61.73,66.48,61.59,60.65,67.36,59.49,88.64,63.52,100.93,65.54Z"/>
|
||||
<circle class="cls-2" cx="53.73" cy="53.9" r="38"/>
|
||||
</svg>
|
||||
<span class="serverListingStarTooltip">Main Server</span>
|
||||
</div>` : ''}
|
||||
for(const el of document.getElementsByClassName('settingsSelServContent')) {
|
||||
el.innerHTML = `
|
||||
<img class="serverListingImg" src="${serv.getIcon()}"/>
|
||||
<div class="serverListingDetails">
|
||||
<span class="serverListingName">${serv.getName()}</span>
|
||||
<span class="serverListingDescription">${serv.getDescription()}</span>
|
||||
<div class="serverListingInfo">
|
||||
<div class="serverListingVersion">${serv.getMinecraftVersion()}</div>
|
||||
<div class="serverListingRevision">${serv.getVersion()}</div>
|
||||
${serv.isMainServer() ? `<div class="serverListingStarWrapper">
|
||||
<svg id="Layer_1" viewBox="0 0 107.45 104.74" width="20px" height="20px">
|
||||
<defs>
|
||||
<style>.cls-1{fill:#fff;}.cls-2{fill:none;stroke:#fff;stroke-miterlimit:10;}</style>
|
||||
</defs>
|
||||
<path class="cls-1" d="M100.93,65.54C89,62,68.18,55.65,63.54,52.13c2.7-5.23,18.8-19.2,28-27.55C81.36,31.74,63.74,43.87,58.09,45.3c-2.41-5.37-3.61-26.52-4.37-39-.77,12.46-2,33.64-4.36,39-5.7-1.46-23.3-13.57-33.49-20.72,9.26,8.37,25.39,22.36,28,27.55C39.21,55.68,18.47,62,6.52,65.55c12.32-2,33.63-6.06,39.34-4.9-.16,5.87-8.41,26.16-13.11,37.69,6.1-10.89,16.52-30.16,21-33.9,4.5,3.79,14.93,23.09,21,34C70,86.84,61.73,66.48,61.59,60.65,67.36,59.49,88.64,63.52,100.93,65.54Z"/>
|
||||
<circle class="cls-2" cx="53.73" cy="53.9" r="38"/>
|
||||
</svg>
|
||||
<span class="serverListingStarTooltip">Main Server</span>
|
||||
</div>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
// Bind functionality to the server switch button.
|
||||
document.getElementById('settingsSwitchServerButton').addEventListener('click', (e) => {
|
||||
e.target.blur()
|
||||
toggleServerSelection(true)
|
||||
Array.from(document.getElementsByClassName('settingsSwitchServerButton')).forEach(el => {
|
||||
el.addEventListener('click', (e) => {
|
||||
e.target.blur()
|
||||
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.
|
||||
*/
|
||||
function animateModsTabRefresh(){
|
||||
$('#settingsTabMods').fadeOut(500, () => {
|
||||
prepareModsTab()
|
||||
$('#settingsTabMods').fadeIn(500)
|
||||
function animateSettingsTabRefresh(){
|
||||
$(`#${selectedSettingsTab}`).fadeOut(500, () => {
|
||||
prepareSettings()
|
||||
$(`#${selectedSettingsTab}`).fadeIn(500)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1131,6 +1155,8 @@ const settingsMinRAMLabel = document.getElementById('settingsMinRAMLabel')
|
||||
const settingsMemoryTotal = document.getElementById('settingsMemoryTotal')
|
||||
const settingsMemoryAvail = document.getElementById('settingsMemoryAvail')
|
||||
const settingsJavaExecDetails = document.getElementById('settingsJavaExecDetails')
|
||||
const settingsJavaReqDesc = document.getElementById('settingsJavaReqDesc')
|
||||
const settingsJvmOptsLink = document.getElementById('settingsJvmOptsLink')
|
||||
|
||||
// Store maximum memory values.
|
||||
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.
|
||||
*/
|
||||
function prepareJavaTab(){
|
||||
bindRangeSlider()
|
||||
populateMemoryStatus()
|
||||
populateJavaReqDesc()
|
||||
populateJvmOptsLink()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -137,6 +137,7 @@ function onDistroRefresh(data){
|
||||
refreshServerStatus()
|
||||
initNews()
|
||||
syncModConfigurations(data)
|
||||
ensureJavaSettings(data)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,6 +224,21 @@ function syncModConfigurations(data){
|
||||
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,
|
||||
* this function returns a boolean. If optional sub modules do exist,
|
||||
@@ -434,6 +450,7 @@ ipcRenderer.on('distributionIndexDone', (event, res) => {
|
||||
if(res) {
|
||||
const data = DistroManager.getDistribution()
|
||||
syncModConfigurations(data)
|
||||
ensureJavaSettings(data)
|
||||
if(document.readyState === 'interactive' || document.readyState === 'complete'){
|
||||
showMainUI(data)
|
||||
} 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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -122,13 +122,13 @@
|
||||
<span class="settingsTabHeaderText">Mod Settings</span>
|
||||
<span class="settingsTabHeaderDesc">Enable or disable mods.</span>
|
||||
</div>
|
||||
<div id="settingsSelServContainer">
|
||||
<div id="settingsSelServContent">
|
||||
<div class="settingsSelServContainer">
|
||||
<div class="settingsSelServContent">
|
||||
|
||||
</div>
|
||||
<div id="settingsSwitchServerContainer">
|
||||
<div id="settingsSwitchServerContent">
|
||||
<button id="settingsSwitchServerButton">Switch</button>
|
||||
<div class="settingsSwitchServerContainer">
|
||||
<div class="settingsSwitchServerContent">
|
||||
<button class="settingsSwitchServerButton">Switch</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -172,6 +172,16 @@
|
||||
<span class="settingsTabHeaderText">Java Settings</span>
|
||||
<span class="settingsTabHeaderDesc">Manage the Java configuration (advanced).</span>
|
||||
</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="settingsMemoryTitle">Memory</div>
|
||||
<div id="settingsMemoryContent">
|
||||
@@ -179,7 +189,7 @@
|
||||
<div class="settingsMemoryContentItem">
|
||||
<span class="settingsMemoryHeader">Maximum RAM</span>
|
||||
<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="rangeSliderTrack"></div>
|
||||
</div>
|
||||
@@ -189,7 +199,7 @@
|
||||
<div class="settingsMemoryContentItem">
|
||||
<span class="settingsMemoryHeader">Minimum RAM</span>
|
||||
<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="rangeSliderTrack"></div>
|
||||
</div>
|
||||
@@ -231,11 +241,11 @@
|
||||
</g>
|
||||
</svg>
|
||||
</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>
|
||||
</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 id="settingsJVMOptsContainer">
|
||||
<div id="settingsJVMOptsTitle">Additional JVM Options</div>
|
||||
@@ -254,9 +264,9 @@
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<input id="settingsJVMOptsVal" cValue="JVMOptions" type="text">
|
||||
<input id="settingsJVMOptsVal" cValue="JVMOptions" serverDependent type="text">
|
||||
</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 id="settingsTabLauncher" class="settingsTab" style="display: none;">
|
||||
|
||||
Reference in New Issue
Block a user