Began working on launching minecraft process. Implementing hash validation for asset downloads. Full integration for the latter will be complete soon.

This commit is contained in:
Daniel Scalzi 2017-04-28 03:59:28 -04:00
parent ef420d4ba6
commit cf0afeb957
4 changed files with 108 additions and 17 deletions

View File

@ -3,11 +3,13 @@ const request = require('request')
const path = require('path') const path = require('path')
const mkpath = require('mkdirp'); const mkpath = require('mkdirp');
const async = require('async') const async = require('async')
const crypto = require('crypto')
function Asset(from, to, size){ function Asset(from, to, size, hash){
this.from = from this.from = from
this.to = to this.to = to
this.size = size this.size = size
this.hash = hash
} }
function AssetIndex(id, sha1, size, url, totalSize){ function AssetIndex(id, sha1, size, url, totalSize){
@ -213,22 +215,26 @@ exports.downloadAssets = function(versionData, basePath){
const hash = String(ob['hash']) const hash = String(ob['hash'])
const assetName = path.join(hash.substring(0, 2), hash) const assetName = path.join(hash.substring(0, 2), hash)
const urlName = hash.substring(0, 2) + "/" + hash const urlName = hash.substring(0, 2) + "/" + hash
const ast = new Asset(resourceURL + urlName, path.join(objectPath, assetName), ob['size']) const ast = new Asset(resourceURL + urlName, path.join(objectPath, assetName), ob['size'], hash)
assetArr.push(ast) assetArr.push(ast)
}) })
let acc = 0; let acc = 0;
async.eachLimit(assetArr, 5, function(asset, cb){ async.eachLimit(assetArr, 5, function(asset, cb){
mkpath.sync(path.join(asset.to, "..")) mkpath.sync(path.join(asset.to, ".."))
let req = request(asset.from) if(!validateLocalIntegrity(asset.to, 'sha1', asset.hash)){
let writeStream = fs.createWriteStream(asset.to) let req = request(asset.from)
req.pipe(writeStream) let writeStream = fs.createWriteStream(asset.to)
req.on('data', function(chunk){ req.pipe(writeStream)
acc += chunk.length req.on('data', function(chunk){
//console.log('Progress', acc/datasize) acc += chunk.length
}) //console.log('Progress', acc/datasize)
writeStream.on('close', function(){ })
writeStream.on('close', function(){
cb()
})
} else {
cb() cb()
}) }
}, function(err){ }, function(err){
if(err){ if(err){
console.log('An asset failed to process'); console.log('An asset failed to process');
@ -239,3 +245,22 @@ exports.downloadAssets = function(versionData, basePath){
}) })
}) })
} }
validateLocalIntegrity = function(filePath, algo, hash){
if(fs.existsSync(filePath)){
let fileName = path.basename(filePath)
console.log('Validating integrity of local file', fileName)
let shasum = crypto.createHash(algo)
let content = fs.readFileSync(filePath)
shasum.update(content)
let localhash = shasum.digest('hex')
if(localhash === hash){
console.log('Hash value of ' + fileName + ' matches the index hash, woo!')
return true
} else {
console.log('Hash value of ' + fileName + ' (' + localhash + ')' + ' does not match the index hash. Redownloading..')
return false
}
}
return false;
}

View File

@ -0,0 +1,64 @@
const mojang = require('mojang')
const uuidV4 = require('uuid/v4')
const path = require('path')
const child_process = require('child_process')
exports.launchMinecraft = function(versionData, basePath){
const authPromise = mojang.auth('EMAIL', 'PASS', uuidV4(), {
name: 'Minecraft',
version: 1
})
authPromise.then(function(data){
const hardcodedargs = ''
const args = finalizeArguments(versionData, data, basePath)
console.log(args)
const child = child_process.execFile(basePath)
})
}
finalizeArguments = function(versionData, authData, basePath){
const mcArgs = versionData['minecraftArguments']
const regex = new RegExp('\\${*(.*)}')
const argArr = mcArgs.split(' ')
for(let i=0; i<argArr.length; i++){
if(regex.test(argArr[i])){
const identifier = argArr[i].match(regex)[1]
//console.log(argArr[i].match(regex)[1])
let newVal = argArr[i]
switch(identifier){
case 'auth_player_name':
//TODO make this DYNAMIC
newVal = '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':
//TODO make this DYNAMIC
newVal = 'UUID'
break
case 'auth_access_token':
newVal = authData['accessToken']
break
case 'user_type':
//TODO make this DYNAMIC
newVal = 'MOJANG'
break
case 'version_type':
newVal = versionData['type']
break
}
argArr[i] = newVal
}
}
return argArr.join(' ')
}

View File

@ -18,15 +18,16 @@ function createWindow() {
win.setMenu(null) win.setMenu(null)
//Code for testing, marked for removal one it's properly implemented. //Code for testing, marked for removal one it's properly implemented.
/*const assetdl = require('./app/assets/js/assetdownload.js') const assetdl = require('./app/assets/js/assetdownload.js')
const basePath = path.join(__dirname, 'mcfiles') const basePath = path.join(__dirname, 'mcfiles')
const dataPromise = assetdl.parseVersionData('1.11.2', basePath) const dataPromise = assetdl.parseVersionData('1.11.2', basePath)
dataPromise.then(function(data){ dataPromise.then(function(data){
assetdl.downloadAssets(data, basePath) assetdl.downloadAssets(data, basePath)
assetdl.downloadClient(data, basePath) //assetdl.downloadClient(data, basePath)
assetdl.downloadLogConfig(data, basePath) //assetdl.downloadLogConfig(data, basePath)
assetdl.downloadLibraries(data, basePath) //assetdl.downloadLibraries(data, basePath)
})*/ //require('./app/assets/js/launchprocess.js').launchMinecraft(data, basePath)
})
win.on('closed', () => { win.on('closed', () => {
win = null win = null

View File

@ -20,6 +20,7 @@
"async": "^2.3.0", "async": "^2.3.0",
"electron": "^1.6.5", "electron": "^1.6.5",
"mojang": "^0.4.0", "mojang": "^0.4.0",
"promise": "^7.1.1" "promise": "^7.1.1",
"uuid": "^3.0.1"
} }
} }