Compare commits

...

2 Commits

Author SHA1 Message Date
Daniel Scalzi
4636f7200c
Java settings by instance 2022-11-26 16:57:30 -05:00
Daniel Scalzi
72cb45b271
Add server selection button to Java settings tab in preparation for by-instance java settings. 2022-11-26 14:57:50 -05:00
10 changed files with 342 additions and 166 deletions

View File

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

View File

@ -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,13 +463,19 @@ 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){
meta.version = verOb
++checksum
if(checksum === goal){
break
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 >= 16) {
@ -804,13 +814,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.

View File

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

View File

@ -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()
})
@ -356,9 +356,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()))
args.push('-Djava.library.path=' + tempNativePath)
// Main Java Class
@ -407,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)

View File

@ -87,7 +87,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 +140,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)
}
@ -332,7 +332,7 @@ function asyncSystemScan(mcVersion, launchAfter = true){
)
setOverlayHandler(() => {
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()]})
toggleOverlay(false)
})
@ -360,7 +360,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 +434,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 +506,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'

View File

@ -2,7 +2,7 @@
const os = require('os')
const semver = require('semver')
const { JavaGuard } = require('./assets/js/assetguard')
const { JavaGuard, Util } = require('./assets/js/assetguard')
const DropinModUtil = require('./assets/js/dropinmodutil')
const { MSFT_OPCODE, MSFT_REPLY_TYPE, MSFT_ERROR } = require('./assets/js/ipcconstants')
@ -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'){
populateJavaExecDetails(v.value)
v.value = gFn()
v.value = gFn.apply(null, gFnOpts)
} 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,7 @@ 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')
// Store maximum memory values.
const SETTINGS_MAX_MEMORY = ConfigManager.getAbsoluteMaxRAM()
@ -1338,12 +1363,24 @@ 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.'
}
}
/**
* Prepare the Java tab for display.
*/
function prepareJavaTab(){
bindRangeSlider()
populateMemoryStatus()
populateJavaReqDesc()
populateJavaExecDetails()
}
/**

View File

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

View File

@ -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,7 +264,7 @@
</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>

22
package-lock.json generated
View File

@ -21,6 +21,7 @@
"got": "^11.8.5",
"helios-core": "~0.1.2",
"jquery": "^3.6.1",
"node-disk-info": "^1.3.0",
"node-stream-zip": "^1.15.0",
"request": "^2.88.2",
"semver": "^7.3.8",
@ -2439,7 +2440,6 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
@ -2973,6 +2973,17 @@
"dev": 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": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@ -6107,7 +6118,6 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
@ -6510,6 +6520,14 @@
"dev": 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": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",

View File

@ -35,6 +35,7 @@
"got": "^11.8.5",
"helios-core": "~0.1.2",
"jquery": "^3.6.1",
"node-disk-info": "^1.3.0",
"node-stream-zip": "^1.15.0",
"request": "^2.88.2",
"semver": "^7.3.8",