Working on launch process code with forge. Pending cleanup and optimizations.

This commit is contained in:
Daniel Scalzi 2017-05-21 18:06:48 -04:00
parent d00f09aaf0
commit bb566471b8
3 changed files with 171 additions and 24 deletions

View File

@ -109,6 +109,27 @@ class Library extends Asset{
} }
} }
class DistroModule extends Asset {
/**
* Create a DistroModule. This is for processing,
* not equivalent to the module objects in the
* distro index.
*
* @param {any} id - id of the asset.
* @param {String} hash - hash value of the asset.
* @param {Number} size - size in bytes of the asset.
* @param {String} from - url where the asset can be found.
* @param {String} to - absolute local file path of the asset.
* @param {String} type - the module type.
*/
constructor(id, hash, size, from, to, type){
super(id, hash, size, from, to)
this.type = type
}
}
/** /**
* Class representing a download tracker. This is used to store meta data * Class representing a download tracker. This is used to store meta data
* about a download queue, including the queue itself. * about a download queue, including the queue itself.
@ -320,6 +341,31 @@ function _extractPackXZ(filePaths){
}) })
} }
function _finalizeForgeAsset(asset, basePath){
return new Promise(function(fulfill, reject){
fs.readFile(asset.to, (err, data) => {
const zip = new AdmZip(data)
const zipEntries = zip.getEntries()
for(let i=0; i<zipEntries.length; i++){
if(zipEntries[i].entryName === 'version.json'){
const forgeVersion = JSON.parse(zip.readAsText(zipEntries[i]))
const versionPath = path.join(basePath, 'versions', forgeVersion.id)
const versionFile = path.join(versionPath, forgeVersion.id + '.json')
if(!fs.existsSync(versionFile)){
mkpath.sync(versionPath)
fs.writeFileSync(path.join(versionPath, forgeVersion.id + '.json'), zipEntries[i].getData())
fulfill(forgeVersion)
} else {
fulfill(JSON.parse(fs.readFileSync(versionFile, 'utf-8')))
}
return
}
}
})
})
}
/** /**
* Initiate an async download process for an AssetGuard DLTracker. * Initiate an async download process for an AssetGuard DLTracker.
* *
@ -625,7 +671,7 @@ function validateLogConfig(versionData, basePath){
function validateDistribution(serverpackid, basePath){ function validateDistribution(serverpackid, basePath){
return new Promise(function(fulfill, reject){ return new Promise(function(fulfill, reject){
let distroindex = _chainValidateDistributionIndex(basePath).then((value) => { _chainValidateDistributionIndex(basePath).then((value) => {
let servers = value.servers let servers = value.servers
let serv = null let serv = null
for(let i=0; i<servers.length; i++){ for(let i=0; i<servers.length; i++){
@ -642,8 +688,10 @@ function validateDistribution(serverpackid, basePath){
if(asset.to.toLowerCase().endsWith('.pack.xz')){ if(asset.to.toLowerCase().endsWith('.pack.xz')){
_extractPackXZ([asset.to]) _extractPackXZ([asset.to])
} }
if(asset.type === 'forge-hosted' || asset.type === 'forge'){
_finalizeForgeAsset(asset, basePath)
}
} }
console.log(instance.forge)
instance.totaldlsize += instance.forge.dlsize*1 instance.totaldlsize += instance.forge.dlsize*1
fulfill() fulfill()
}) })
@ -690,7 +738,7 @@ function _parseDistroModules(modules, basePath, version){
default: default:
obPath = path.join(basePath, obPath) obPath = path.join(basePath, obPath)
} }
let artifact = new Asset(ob.id, obArtifact.MD5, obArtifact.size, obArtifact.url, obPath) let artifact = new DistroModule(ob.id, obArtifact.MD5, obArtifact.size, obArtifact.url, obPath, obType)
if(obPath.toLowerCase().endsWith('.pack.xz')){ if(obPath.toLowerCase().endsWith('.pack.xz')){
if(!_validateLocal(obPath.substring(0, obPath.toLowerCase().lastIndexOf('.pack.xz')), 'MD5', artifact.hash)){ if(!_validateLocal(obPath.substring(0, obPath.toLowerCase().lastIndexOf('.pack.xz')), 'MD5', artifact.hash)){
asize += artifact.size*1 asize += artifact.size*1
@ -711,6 +759,35 @@ function _parseDistroModules(modules, basePath, version){
return new DLTracker(alist, asize, decompressqueue) return new DLTracker(alist, asize, decompressqueue)
} }
function loadForgeData(serverpack, basePath){
return new Promise(async function(fulfill, reject){
let distro = await _chainValidateDistributionIndex(basePath)
const servers = distro.servers
let serv = null
for(let i=0; i<servers.length; i++){
if(servers[i].id === serverpack){
serv = servers[i]
break
}
}
const modules = serv.modules
for(let i=0; i<modules.length; i++){
const ob = modules[i]
if(ob.type === 'forge-hosted' || ob.type === 'forge'){
let obArtifact = ob.artifact
let obPath = obArtifact.path == null ? path.join(basePath, 'libraries', _resolvePath(ob.id, obArtifact.extension)) : obArtifact.path
let asset = new DistroModule(ob.id, obArtifact.MD5, obArtifact.size, obArtifact.url, obPath, ob.type)
let forgeData = await _finalizeForgeAsset(asset, basePath)
fulfill(forgeData)
return
}
}
reject('No forge module found!')
})
}
/** /**
* This function will initiate the download processed for the specified identifiers. If no argument is * This function will initiate the download processed for the specified identifiers. If no argument is
* given, all identifiers will be initiated. Note that in order for files to be processed you need to run * given, all identifiers will be initiated. Note that in order for files to be processed you need to run
@ -740,6 +817,7 @@ function processDlQueues(identifiers = [{id:'assets', limit:20}, {id:'libraries'
module.exports = { module.exports = {
loadVersionData, loadVersionData,
loadForgeData,
validateAssets, validateAssets,
validateLibraries, validateLibraries,
validateMiscellaneous, validateMiscellaneous,
@ -747,5 +825,6 @@ module.exports = {
processDlQueues, processDlQueues,
instance, instance,
Asset, Asset,
Library Library,
_resolvePath
} }

View File

@ -7,41 +7,41 @@ const AdmZip = require('adm-zip')
const fs = require('fs') const fs = require('fs')
const mkpath = require('mkdirp'); const mkpath = require('mkdirp');
launchMinecraft = function(versionData, basePath){ function launchMinecraft(versionData, forgeData, basePath){
const authPromise = mojang.auth('EMAIL', 'PASS', uuidV4(), { const authPromise = mojang.auth('EMAIL', 'PASS', uuidV4(), {
name: 'Minecraft', name: 'Minecraft',
version: 1 version: 1
}) })
authPromise.then(function(data){ authPromise.then(function(data){
const args = finalizeArguments(versionData, data, basePath) const args = finalizeArgumentsForge(versionData, forgeData, data, basePath)
//TODO make this dynamic //TODO make this dynamic
const child = child_process.spawn('C:\\Program Files\\Java\\jre1.8.0_131\\bin\\javaw.exe', args) const child = child_process.spawn('C:\\Program Files\\Java\\jre1.8.0_131\\bin\\javaw.exe', args)
child.stdout.on('data', (data) => { child.stdout.on('data', (data) => {
console.log('minecraft:', data.toString('utf8')) console.log('Minecraft:', data.toString('utf8'))
}) })
child.stderr.on('data', (data) => { child.stderr.on('data', (data) => {
console.log('minecraft:', data.toString('utf8')) console.log('Minecraft:', data.toString('utf8'))
}) })
child.on('close', (code, signal) => { child.on('close', (code, signal) => {
console.log('exited with code', code) console.log('Exited with code', code)
}) })
}) })
} }
finalizeArguments = function(versionData, authData, basePath){ function finalizeArgumentsForge(versionData, forgeData, authData, basePath){
const mcArgs = versionData['minecraftArguments'] const mcArgs = forgeData['minecraftArguments']
const gameProfile = authData['selectedProfile'] const gameProfile = authData['selectedProfile']
const regex = new RegExp('\\${*(.*)}') const regex = new RegExp('\\${*(.*)}')
const argArr = mcArgs.split(' ') const argArr = mcArgs.split(' ')
argArr.unshift('net.minecraft.client.main.Main') const staticArgs = ['-Xmx4G',
argArr.unshift(classpathArg(versionData, basePath)) '-XX:+UseConcMarkSweepGC',
argArr.unshift('-cp') '-XX:+CMSIncrementalMode',
argArr.unshift('-Djava.library.path=' + path.join(basePath, 'natives')) '-XX:-UseAdaptiveSizePolicy',
argArr.unshift('-Xmn128M') '-Xmn128M',
argArr.unshift('-XX:-UseAdaptiveSizePolicy') '-Djava.library.path=' + path.join(basePath, 'natives'),
argArr.unshift('-XX:+CMSIncrementalMode') '-cp',
argArr.unshift('-XX:+UseConcMarkSweepGC') classpathArg(versionData, basePath).concat(forgeClasspathArg(forgeData, basePath)).join(';'),
argArr.unshift('-Xmx1G') forgeData.mainClass]
for(let i=0; i<argArr.length; i++){ for(let i=0; i<argArr.length; i++){
if(regex.test(argArr[i])){ if(regex.test(argArr[i])){
const identifier = argArr[i].match(regex)[1] const identifier = argArr[i].match(regex)[1]
@ -79,10 +79,76 @@ finalizeArguments = function(versionData, authData, basePath){
} }
} }
return argArr return staticArgs.concat(argArr)
} }
classpathArg = function(versionData, basePath){ function finalizeArguments(versionData, authData, basePath){
const mcArgs = versionData['minecraftArguments']
const gameProfile = authData['selectedProfile']
const regex = new RegExp('\\${*(.*)}')
const argArr = mcArgs.split(' ')
const staticArgs = ['-Xmx1G',
'-XX:+UseConcMarkSweepGC',
'-XX:+CMSIncrementalMode',
'-XX:-UseAdaptiveSizePolicy',
'-Xmn128M',
'-Djava.library.path=' + path.join(basePath, 'natives'),
'-cp',
classpathArg(versionData, basePath).join(';'),
versionData.mainClass]
for(let i=0; i<argArr.length; i++){
if(regex.test(argArr[i])){
const identifier = argArr[i].match(regex)[1]
let newVal = argArr[i]
switch(identifier){
case 'auth_player_name':
newVal = gameProfile['name']
break
case 'version_name':
newVal = versionData['id']
break
case 'game_directory':
newVal = basePath
break
case 'assets_root':
newVal = path.join(basePath, 'assets')
break
case 'assets_index_name':
newVal = versionData['assets']
break
case 'auth_uuid':
newVal = gameProfile['id']
break
case 'auth_access_token':
newVal = authData['accessToken']
break
case 'user_type':
newVal = 'MOJANG'
break
case 'version_type':
newVal = versionData['type']
break
}
argArr[i] = newVal
}
}
return staticArgs.concat(argArr)
}
function forgeClasspathArg(forgeData, basePath){
const libArr = forgeData['libraries']
const libPath = path.join(basePath, 'libraries')
const cpArgs = []
for(let i=0; i<libArr.length; i++){
const lib = libArr[i]
const to = path.join(libPath, ag._resolvePath(lib.name, '.jar'))
cpArgs.push(to)
}
return cpArgs
}
function classpathArg(versionData, basePath){
const libArr = versionData['libraries'] const libArr = versionData['libraries']
const libPath = path.join(basePath, 'libraries') const libPath = path.join(basePath, 'libraries')
const nativePath = path.join(basePath, 'natives') const nativePath = path.join(basePath, 'natives')
@ -134,7 +200,7 @@ classpathArg = function(versionData, basePath){
} }
}) })
return cpArgs.join(';') return cpArgs
} }
module.exports = { module.exports = {

View File

@ -58,7 +58,9 @@ testdownloads = async function(){
console.log('files done') console.log('files done')
await ag.validateDistribution('WesterosCraft-1.11.2', basePath) await ag.validateDistribution('WesterosCraft-1.11.2', basePath)
console.log('forge stuff done') console.log('forge stuff done')
ag.instance.on('dlcomplete', function(){ ag.instance.on('dlcomplete', async function(){
let forgeData = await ag.loadForgeData('WesterosCraft-1.11.2', basePath)
lp.launchMinecraft(versionData, forgeData, basePath)
//lp.launchMinecraft(versionData, basePath) //lp.launchMinecraft(versionData, basePath)
}) })
ag.processDlQueues() ag.processDlQueues()