Preliminary Java 9+ Support (#20).

We will still not allow these versions to be used until they have been fully verified on our far-future 1.13 test server.
This commit is contained in:
Daniel Scalzi 2018-12-31 10:39:27 -05:00
parent be533af38b
commit d7fe519923
No known key found for this signature in database
GPG Key ID: 5CA2F145B63535F9
4 changed files with 146 additions and 43 deletions

View File

@ -475,12 +475,29 @@ class AssetGuard extends EventEmitter {
/**
* Parses a **full** Java Runtime version string and resolves
* the version information. Uses Java 8 formatting.
* the version information. Dynamically detects the formatting
* to use.
*
* @param {string} verString Full version string to parse.
* @returns Object containing the version information.
*/
static parseJavaRuntimeVersion(verString){
const major = verString.split('.')[0]
if(major == 1){
return AssetGuard._parseJavaRuntimeVersion_8(verString)
} else {
return AssetGuard._parseJavaRuntimeVersion_9(verString)
}
}
/**
* Parses a **full** Java Runtime version string and resolves
* the version information. Uses Java 8 formatting.
*
* @param {string} verString Full version string to parse.
* @returns Object containing the version information.
*/
static _parseJavaRuntimeVersion_8(verString){
// 1.{major}.0_{update}-b{build}
// ex. 1.8.0_152-b16
const ret = {}
@ -492,16 +509,56 @@ class AssetGuard extends EventEmitter {
return ret
}
/**
* Parses a **full** Java Runtime version string and resolves
* the version information. Uses Java 9+ formatting.
*
* @param {string} verString Full version string to parse.
* @returns Object containing the version information.
*/
static _parseJavaRuntimeVersion_9(verString){
// {major}.{minor}.{revision}+{build}
// ex. 10.0.2+13
const ret = {}
let pts = verString.split('+')
ret.build = parseInt(pts[1])
pts = pts[0].split('.')
ret.major = parseInt(pts[0])
ret.minor = parseInt(pts[1])
ret.revision = parseInt(pts[2])
return ret
}
/**
* 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.
*/
static 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
}
/**
* Validates the output of a JVM's properties. Currently validates that a JRE is x64
* and that the major = 8, update > 52.
*
* @param {string} stderr The output to validate.
* @param {string} mcVersion The minecraft version we are scanning for.
*
* @returns {Promise.<Object>} A promise which resolves to a meta object about the JVM.
* The validity is stored inside the `valid` property.
*/
static _validateJVMProperties(stderr){
static _validateJVMProperties(stderr, mcVersion){
const res = stderr
const props = res.split('\n')
@ -526,11 +583,24 @@ class AssetGuard extends EventEmitter {
let verString = props[i].split('=')[1].trim()
console.log(props[i].trim())
const verOb = AssetGuard.parseJavaRuntimeVersion(verString)
if(verOb.major === 8 && verOb.update > 52){
meta.version = verOb
++checksum
if(checksum === goal){
break
if(verOb.major < 9){
// Java 8
if(verOb.major === 8 && verOb.update > 52){
meta.version = verOb
++checksum
if(checksum === goal){
break
}
}
} else {
// Java 9+
if(AssetGuard.mcVersionAtLeast('1.13', mcVersion)){
console.log('Java 9+ not yet tested.')
/* meta.version = verOb
++checksum
if(checksum === goal){
break
} */
}
}
}
@ -550,11 +620,12 @@ class AssetGuard extends EventEmitter {
* removed.
*
* @param {string} binaryExecPath Path to the java executable we wish to validate.
* @param {string} mcVersion The minecraft version we are scanning for.
*
* @returns {Promise.<Object>} A promise which resolves to a meta object about the JVM.
* The validity is stored inside the `valid` property.
*/
static _validateJavaBinary(binaryExecPath){
static _validateJavaBinary(binaryExecPath, mcVersion){
return new Promise((resolve, reject) => {
if(!AssetGuard.isJavaExecPath(binaryExecPath)){
@ -563,7 +634,7 @@ class AssetGuard extends EventEmitter {
child_process.exec('"' + binaryExecPath + '" -XshowSettings:properties', (err, stdout, stderr) => {
try {
// Output is stored in stderr?
resolve(this._validateJVMProperties(stderr))
resolve(this._validateJVMProperties(stderr, mcVersion))
} catch (err){
// Output format might have changed, validation cannot be completed.
resolve({valid: false})
@ -772,10 +843,11 @@ class AssetGuard extends EventEmitter {
/**
*
* @param {Set.<string>} rootSet A set of JVM root strings to validate.
* @param {string} mcVersion The minecraft version we are scanning for.
* @returns {Promise.<Object[]>} A promise which resolves to an array of meta objects
* for each valid JVM root directory.
*/
static async _validateJavaRootSet(rootSet){
static async _validateJavaRootSet(rootSet, mcVersion){
const rootArr = Array.from(rootSet)
const validArr = []
@ -783,7 +855,7 @@ class AssetGuard extends EventEmitter {
for(let i=0; i<rootArr.length; i++){
const execPath = AssetGuard.javaExecFromRoot(rootArr[i])
const metaOb = await AssetGuard._validateJavaBinary(execPath)
const metaOb = await AssetGuard._validateJavaBinary(execPath, mcVersion)
if(metaOb.valid){
metaOb.execPath = execPath
@ -805,36 +877,50 @@ class AssetGuard extends EventEmitter {
*/
static _sortValidJavaArray(validArr){
const retArr = validArr.sort((a, b) => {
// Note that Java 9+ uses semver and that will need to be accounted for in
// the future.
if(a.version.major === b.version.major){
if(a.version.update === b.version.update){
if(a.version.build === b.version.build){
// Same version, give priority to JRE.
if(a.execPath.toLowerCase().indexOf('jdk') > -1){
return b.execPath.toLowerCase().indexOf('jdk') > -1 ? 0 : 1
if(a.version.major < 9){
// Java 8
if(a.version.update === b.version.update){
if(a.version.build === b.version.build){
// Same version, give priority to JRE.
if(a.execPath.toLowerCase().indexOf('jdk') > -1){
return b.execPath.toLowerCase().indexOf('jdk') > -1 ? 0 : 1
} else {
return -1
}
} else {
return -1
return a.version.build > b.version.build ? -1 : 1
}
} else {
return a.version.build > b.version.build ? -1 : 1
return a.version.update > b.version.update ? -1 : 1
}
} else {
return a.version.update > b.version.update ? -1 : 1
// Java 9+
if(a.version.minor === b.version.minor){
if(a.version.revision === b.version.revision){
// Same version, give priority to JRE.
if(a.execPath.toLowerCase().indexOf('jdk') > -1){
return b.execPath.toLowerCase().indexOf('jdk') > -1 ? 0 : 1
} else {
return -1
}
} else {
return a.version.revision > b.version.revision ? -1 : 1
}
} else {
return a.version.minor > b.version.minor ? -1 : 1
}
}
} else {
return a.version.major > b.version.major ? -1 : 1
}
})
return retArr
@ -851,10 +937,11 @@ class AssetGuard extends EventEmitter {
* If versions are equal, JRE > JDK.
*
* @param {string} dataDir The base launcher directory.
* @param {string} mcVersion The minecraft version we are scanning for.
* @returns {Promise.<string>} A Promise which resolves to the executable path of a valid
* x64 Java installation. If none are found, null is returned.
*/
static async _win32JavaValidate(dataDir){
static async _win32JavaValidate(dataDir, mcVersion){
// Get possible paths from the registry.
let pathSet1 = await AssetGuard._scanRegistry()
@ -875,7 +962,7 @@ class AssetGuard extends EventEmitter {
uberSet.add(jHome)
}
let pathArr = await AssetGuard._validateJavaRootSet(uberSet)
let pathArr = await AssetGuard._validateJavaRootSet(uberSet, mcVersion)
pathArr = AssetGuard._sortValidJavaArray(pathArr)
if(pathArr.length > 0){
@ -896,10 +983,11 @@ class AssetGuard extends EventEmitter {
* If versions are equal, JRE > JDK.
*
* @param {string} dataDir The base launcher directory.
* @param {string} mcVersion The minecraft version we are scanning for.
* @returns {Promise.<string>} A Promise which resolves to the executable path of a valid
* x64 Java installation. If none are found, null is returned.
*/
static async _darwinJavaValidate(dataDir){
static async _darwinJavaValidate(dataDir, mcVersion){
const pathSet1 = await AssetGuard._scanFileSystem('/Library/Java/JavaVirtualMachines')
const pathSet2 = await AssetGuard._scanFileSystem(path.join(dataDir, 'runtime', 'x64'))
@ -922,7 +1010,7 @@ class AssetGuard extends EventEmitter {
uberSet.add(jHome)
}
let pathArr = await AssetGuard._validateJavaRootSet(uberSet)
let pathArr = await AssetGuard._validateJavaRootSet(uberSet, mcVersion)
pathArr = AssetGuard._sortValidJavaArray(pathArr)
if(pathArr.length > 0){
@ -941,10 +1029,11 @@ class AssetGuard extends EventEmitter {
* If versions are equal, JRE > JDK.
*
* @param {string} dataDir The base launcher directory.
* @param {string} mcVersion The minecraft version we are scanning for.
* @returns {Promise.<string>} A Promise which resolves to the executable path of a valid
* x64 Java installation. If none are found, null is returned.
*/
static async _linuxJavaValidate(dataDir){
static async _linuxJavaValidate(dataDir, mcVersion){
const pathSet1 = await AssetGuard._scanFileSystem('/usr/lib/jvm')
const pathSet2 = await AssetGuard._scanFileSystem(path.join(dataDir, 'runtime', 'x64'))
@ -957,7 +1046,7 @@ class AssetGuard extends EventEmitter {
uberSet.add(jHome)
}
let pathArr = await AssetGuard._validateJavaRootSet(uberSet)
let pathArr = await AssetGuard._validateJavaRootSet(uberSet, mcVersion)
pathArr = AssetGuard._sortValidJavaArray(pathArr)
if(pathArr.length > 0){
@ -971,10 +1060,11 @@ class AssetGuard extends EventEmitter {
* Retrieve the path of a valid x64 Java installation.
*
* @param {string} dataDir The base launcher directory.
* @param {string} mcVersion The minecraft version we are scanning for.
* @returns {string} A path to a valid x64 Java installation, null if none found.
*/
static async validateJava(dataDir){
return await AssetGuard['_' + process.platform + 'JavaValidate'](dataDir)
static async validateJava(dataDir, mcVersion){
return await AssetGuard['_' + process.platform + 'JavaValidate'](dataDir, mcVersion)
}
// #endregion

View File

@ -86,21 +86,22 @@ function setLaunchEnabled(val){
// Bind launch button
document.getElementById('launch_button').addEventListener('click', function(e){
loggerLanding.log('Launching game..')
const mcVersion = DistroManager.getDistribution().getServer(ConfigManager.getSelectedServer()).getMinecraftVersion()
const jExe = ConfigManager.getJavaExecutable()
if(jExe == null){
asyncSystemScan()
asyncSystemScan(mcVersion)
} else {
setLaunchDetails('Please wait..')
toggleLaunchArea(true)
setLaunchPercentage(0, 100)
AssetGuard._validateJavaBinary(jExe).then((v) => {
AssetGuard._validateJavaBinary(jExe, mcVersion).then((v) => {
loggerLanding.log('Java version meta', v)
if(v.valid){
dlAsync()
} else {
asyncSystemScan()
asyncSystemScan(mcVersion)
}
})
}
@ -260,7 +261,13 @@ let scanAt
let extractListener
function asyncSystemScan(launchAfter = true){
/**
* Asynchronously scan the system for valid Java installations.
*
* @param {string} mcVersion The Minecraft version we are scanning for.
* @param {boolean} launchAfter Whether we should begin to launch after scanning.
*/
function asyncSystemScan(mcVersion, launchAfter = true){
setLaunchDetails('Please wait..')
toggleLaunchArea(true)
@ -424,7 +431,7 @@ function asyncSystemScan(launchAfter = true){
// Begin system Java scan.
setLaunchDetails('Checking system info..')
sysAEx.send({task: 'execute', function: 'validateJava', argsArr: [ConfigManager.getLauncherDirectory()]})
sysAEx.send({task: 'execute', function: 'validateJava', argsArr: [ConfigManager.getLauncherDirectory(), mcVersion]})
}

View File

@ -237,6 +237,8 @@ loginCancelButton.onclick = (e) => {
loginCancelEnabled(false)
if(loginViewCancelHandler != null){
loginViewCancelHandler()
loginUsername.value = ''
loginPassword.value = ''
loginViewCancelHandler = null
}
})

View File

@ -1107,7 +1107,11 @@ settingsJavaExecSel.onchange = (e) => {
function populateJavaExecDetails(execPath){
AssetGuard._validateJavaBinary(execPath).then(v => {
if(v.valid){
settingsJavaExecDetails.innerHTML = `Selected: Java ${v.version.major} Update ${v.version.update} (x${v.arch})`
if(v.version.major < 9) {
settingsJavaExecDetails.innerHTML = `Selected: Java ${v.version.major} Update ${v.version.update} (x${v.arch})`
} else {
settingsJavaExecDetails.innerHTML = `Selected: Java ${v.version.major}.${v.version.minor}.${v.version.revision} (x${v.arch})`
}
} else {
settingsJavaExecDetails.innerHTML = 'Invalid Selection'
}