2013-02-22 05:40:17 +05:30
/* Copyright 2013 MultiMC Contributors
*
* Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
2013-09-22 07:51:36 +05:30
*
2013-02-22 05:40:17 +05:30
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
2013-11-04 07:23:05 +05:30
2013-09-08 05:45:20 +05:30
# include "MultiMC.h"
2013-08-04 18:16:33 +05:30
# include "OneSixUpdate.h"
2013-02-22 05:40:17 +05:30
2013-05-08 23:26:43 +05:30
# include <QtNetwork>
# include <QFile>
# include <QFileInfo>
# include <QTextStream>
# include <QDataStream>
2013-08-04 03:28:39 +05:30
# include "BaseInstance.h"
2013-07-29 04:29:35 +05:30
# include "lists/MinecraftVersionList.h"
2014-03-02 03:36:47 +05:30
# include "VersionFinal.h"
2013-09-12 03:13:17 +05:30
# include "OneSixLibrary.h"
2013-08-05 06:59:50 +05:30
# include "OneSixInstance.h"
2014-04-23 05:57:40 +05:30
# include "logic/forge/ForgeMirrors.h"
2013-12-13 20:28:11 +05:30
# include "net/URLConstants.h"
2013-12-10 11:42:52 +05:30
# include "assets/AssetsUtils.h"
2013-05-08 23:26:43 +05:30
# include "pathutils.h"
2013-11-25 05:16:52 +05:30
# include <JlCompress.h>
2013-05-08 23:26:43 +05:30
2014-02-21 23:45:59 +05:30
OneSixUpdate : : OneSixUpdate ( OneSixInstance * inst , QObject * parent )
2014-01-27 07:30:49 +05:30
: Task ( parent ) , m_inst ( inst )
2013-09-22 07:51:36 +05:30
{
}
2013-05-08 23:26:43 +05:30
2013-08-04 18:16:33 +05:30
void OneSixUpdate : : executeTask ( )
2013-05-08 23:26:43 +05:30
{
2013-08-05 06:59:50 +05:30
QString intendedVersion = m_inst - > intendedVersionId ( ) ;
2013-09-22 07:51:36 +05:30
2013-08-12 04:09:19 +05:30
// Make directories
QDir mcDir ( m_inst - > minecraftRoot ( ) ) ;
if ( ! mcDir . exists ( ) & & ! mcDir . mkpath ( " . " ) )
{
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " Failed to create folder for minecraft binaries. " ) ) ;
2013-08-12 04:09:19 +05:30
return ;
}
2013-09-22 07:51:36 +05:30
if ( m_inst - > shouldUpdate ( ) )
2013-08-05 06:59:50 +05:30
{
2013-11-25 05:16:52 +05:30
// Get a pointer to the version object that corresponds to the instance's version.
targetVersion = std : : dynamic_pointer_cast < MinecraftVersion > (
MMC - > minecraftlist ( ) - > findVersion ( intendedVersion ) ) ;
if ( targetVersion = = nullptr )
{
// don't do anything if it was invalid
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " The specified Minecraft version is invalid. Choose a different one. " ) ) ;
2013-11-25 05:16:52 +05:30
return ;
}
2013-08-05 06:59:50 +05:30
versionFileStart ( ) ;
}
else
{
jarlibStart ( ) ;
}
}
void OneSixUpdate : : versionFileStart ( )
{
2014-02-21 23:45:59 +05:30
if ( m_inst - > providesVersionFile ( ) )
{
jarlibStart ( ) ;
return ;
}
2013-11-25 05:16:52 +05:30
QLOG_INFO ( ) < < m_inst - > name ( ) < < " : getting version file. " ;
2013-12-23 21:16:01 +05:30
setStatus ( tr ( " Getting the version files from Mojang... " ) ) ;
2013-09-22 07:51:36 +05:30
2014-01-14 05:43:35 +05:30
QString urlstr = " http:// " + URLConstants : : AWS_DOWNLOAD_VERSIONS +
targetVersion - > descriptor ( ) + " / " + targetVersion - > descriptor ( ) + " .json " ;
2013-10-26 23:25:48 +05:30
auto job = new NetJob ( " Version index " ) ;
job - > addNetAction ( ByteArrayDownload : : make ( QUrl ( urlstr ) ) ) ;
2013-09-08 05:45:20 +05:30
specificVersionDownloadJob . reset ( job ) ;
2013-10-06 04:43:40 +05:30
connect ( specificVersionDownloadJob . get ( ) , SIGNAL ( succeeded ( ) ) , SLOT ( versionFileFinished ( ) ) ) ;
connect ( specificVersionDownloadJob . get ( ) , SIGNAL ( failed ( ) ) , SLOT ( versionFileFailed ( ) ) ) ;
connect ( specificVersionDownloadJob . get ( ) , SIGNAL ( progress ( qint64 , qint64 ) ) ,
2013-09-22 07:51:36 +05:30
SIGNAL ( progress ( qint64 , qint64 ) ) ) ;
2013-09-02 03:55:40 +05:30
specificVersionDownloadJob - > start ( ) ;
2013-07-08 03:21:26 +05:30
}
2013-08-04 18:16:33 +05:30
void OneSixUpdate : : versionFileFinished ( )
2013-07-08 03:21:26 +05:30
{
2013-10-26 23:25:48 +05:30
NetActionPtr DlJob = specificVersionDownloadJob - > first ( ) ;
2013-09-22 07:51:36 +05:30
2013-09-16 04:24:39 +05:30
QString version_id = targetVersion - > descriptor ( ) ;
2013-08-12 04:09:19 +05:30
QString inst_dir = m_inst - > instanceRoot ( ) ;
2013-08-05 06:59:50 +05:30
// save the version file in $instanceId/version.json
2013-07-08 03:21:26 +05:30
{
2013-09-22 07:51:36 +05:30
QString version1 = PathCombine ( inst_dir , " /version.json " ) ;
2013-08-24 06:39:46 +05:30
ensureFilePathExists ( version1 ) ;
2013-08-14 11:43:41 +05:30
// FIXME: detect errors here, download to a temp file, swap
2013-09-22 07:51:36 +05:30
QSaveFile vfile1 ( version1 ) ;
if ( ! vfile1 . open ( QIODevice : : Truncate | QIODevice : : WriteOnly ) )
2013-09-16 04:24:39 +05:30
{
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " Can't open %1 for writing. " ) . arg ( version1 ) ) ;
2013-09-16 04:24:39 +05:30
return ;
}
2013-10-06 04:43:40 +05:30
auto data = std : : dynamic_pointer_cast < ByteArrayDownload > ( DlJob ) - > m_data ;
2013-09-16 04:24:39 +05:30
qint64 actual = 0 ;
2013-09-22 07:51:36 +05:30
if ( ( actual = vfile1 . write ( data ) ) ! = data . size ( ) )
2013-09-16 04:24:39 +05:30
{
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " Failed to write into %1. Written %2 out of %3. " ) . arg ( version1 ) . arg ( actual ) . arg ( data . size ( ) ) ) ;
2013-09-16 04:24:39 +05:30
return ;
}
2013-09-22 07:51:36 +05:30
if ( ! vfile1 . commit ( ) )
2013-09-16 04:24:39 +05:30
{
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " Can't commit changes to %1 " ) . arg ( version1 ) ) ;
2013-09-16 04:24:39 +05:30
return ;
}
2013-07-08 03:21:26 +05:30
}
2013-09-22 07:51:36 +05:30
2013-08-14 11:43:41 +05:30
// the version is downloaded safely. update is 'done' at this point
m_inst - > setShouldUpdate ( false ) ;
2013-09-22 07:51:36 +05:30
2013-09-16 04:24:39 +05:30
// delete any custom version inside the instance (it's no longer relevant, we did an update)
2013-09-22 07:51:36 +05:30
QString custom = PathCombine ( inst_dir , " /custom.json " ) ;
2013-09-16 04:24:39 +05:30
QFile finfo ( custom ) ;
2013-09-22 07:51:36 +05:30
if ( finfo . exists ( ) )
2013-09-16 04:24:39 +05:30
{
finfo . remove ( ) ;
}
2014-03-10 04:12:25 +05:30
// NOTE: Version is reloaded in jarlibStart
2014-01-14 05:43:35 +05:30
jarlibStart ( ) ;
2013-08-05 06:59:50 +05:30
}
void OneSixUpdate : : versionFileFailed ( )
{
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " Failed to download the version description. Try again. " ) ) ;
2013-08-05 06:59:50 +05:30
}
2013-12-10 11:42:52 +05:30
void OneSixUpdate : : assetIndexStart ( )
{
2013-12-23 21:16:01 +05:30
setStatus ( tr ( " Updating assets index... " ) ) ;
2013-12-10 11:42:52 +05:30
OneSixInstance * inst = ( OneSixInstance * ) m_inst ;
2014-03-02 03:36:47 +05:30
std : : shared_ptr < VersionFinal > version = inst - > getFullVersion ( ) ;
2013-12-10 11:42:52 +05:30
QString assetName = version - > assets ;
2013-12-13 20:28:11 +05:30
QUrl indexUrl = " http:// " + URLConstants : : AWS_DOWNLOAD_INDEXES + assetName + " .json " ;
2013-12-10 11:42:52 +05:30
QString localPath = assetName + " .json " ;
2014-03-23 23:37:13 +05:30
auto job = new NetJob ( tr ( " Asset index for %1 " ) . arg ( inst - > name ( ) ) ) ;
2013-12-10 11:42:52 +05:30
auto metacache = MMC - > metacache ( ) ;
auto entry = metacache - > resolveEntry ( " asset_indexes " , localPath ) ;
job - > addNetAction ( CacheDownload : : make ( indexUrl , entry ) ) ;
jarlibDownloadJob . reset ( job ) ;
connect ( jarlibDownloadJob . get ( ) , SIGNAL ( succeeded ( ) ) , SLOT ( assetIndexFinished ( ) ) ) ;
connect ( jarlibDownloadJob . get ( ) , SIGNAL ( failed ( ) ) , SLOT ( assetIndexFailed ( ) ) ) ;
connect ( jarlibDownloadJob . get ( ) , SIGNAL ( progress ( qint64 , qint64 ) ) ,
SIGNAL ( progress ( qint64 , qint64 ) ) ) ;
jarlibDownloadJob - > start ( ) ;
}
void OneSixUpdate : : assetIndexFinished ( )
{
AssetsIndex index ;
OneSixInstance * inst = ( OneSixInstance * ) m_inst ;
2014-03-02 03:36:47 +05:30
std : : shared_ptr < VersionFinal > version = inst - > getFullVersion ( ) ;
2013-12-10 11:42:52 +05:30
QString assetName = version - > assets ;
QString asset_fname = " assets/indexes/ " + assetName + " .json " ;
if ( ! AssetsUtils : : loadAssetsIndexJson ( asset_fname , & index ) )
{
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " Failed to read the assets index! " ) ) ;
2013-12-10 11:42:52 +05:30
}
2014-01-14 05:43:35 +05:30
2013-12-10 11:42:52 +05:30
QList < Md5EtagDownloadPtr > dls ;
for ( auto object : index . objects . values ( ) )
{
QString objectName = object . hash . left ( 2 ) + " / " + object . hash ;
QFileInfo objectFile ( " assets/objects/ " + objectName ) ;
if ( ( ! objectFile . isFile ( ) ) | | ( objectFile . size ( ) ! = object . size ) )
{
auto objectDL = MD5EtagDownload : : make (
2013-12-13 20:28:11 +05:30
QUrl ( " http:// " + URLConstants : : RESOURCE_BASE + objectName ) ,
2013-12-10 11:42:52 +05:30
objectFile . filePath ( ) ) ;
2013-12-15 19:30:09 +05:30
objectDL - > m_total_progress = object . size ;
2013-12-10 11:42:52 +05:30
dls . append ( objectDL ) ;
}
}
2014-01-14 05:43:35 +05:30
if ( dls . size ( ) )
2013-12-10 11:42:52 +05:30
{
2013-12-23 21:16:01 +05:30
setStatus ( tr ( " Getting the assets files from Mojang... " ) ) ;
2014-03-23 23:37:13 +05:30
auto job = new NetJob ( tr ( " Assets for %1 " ) . arg ( inst - > name ( ) ) ) ;
2014-01-14 05:43:35 +05:30
for ( auto dl : dls )
2013-12-10 11:42:52 +05:30
job - > addNetAction ( dl ) ;
jarlibDownloadJob . reset ( job ) ;
connect ( jarlibDownloadJob . get ( ) , SIGNAL ( succeeded ( ) ) , SLOT ( assetsFinished ( ) ) ) ;
connect ( jarlibDownloadJob . get ( ) , SIGNAL ( failed ( ) ) , SLOT ( assetsFailed ( ) ) ) ;
connect ( jarlibDownloadJob . get ( ) , SIGNAL ( progress ( qint64 , qint64 ) ) ,
2014-01-14 05:43:35 +05:30
SIGNAL ( progress ( qint64 , qint64 ) ) ) ;
2013-12-10 11:42:52 +05:30
jarlibDownloadJob - > start ( ) ;
return ;
}
assetsFinished ( ) ;
}
void OneSixUpdate : : assetIndexFailed ( )
{
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " Failed to download the assets index! " ) ) ;
2013-12-10 11:42:52 +05:30
}
void OneSixUpdate : : assetsFinished ( )
{
2014-01-27 07:30:49 +05:30
emitSucceeded ( ) ;
2013-12-10 11:42:52 +05:30
}
void OneSixUpdate : : assetsFailed ( )
{
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " Failed to download assets! " ) ) ;
2013-12-10 11:42:52 +05:30
}
2013-08-05 06:59:50 +05:30
void OneSixUpdate : : jarlibStart ( )
{
2013-12-23 21:16:01 +05:30
setStatus ( tr ( " Getting the library files from Mojang... " ) ) ;
2013-11-25 05:16:52 +05:30
QLOG_INFO ( ) < < m_inst - > name ( ) < < " : downloading libraries " ;
2013-09-22 07:51:36 +05:30
OneSixInstance * inst = ( OneSixInstance * ) m_inst ;
2014-03-10 04:12:25 +05:30
try
{
inst - > reloadVersion ( ) ;
}
catch ( MMCError & e )
{
emitFailed ( e . cause ( ) ) ;
return ;
}
catch ( . . . )
2013-08-05 06:59:50 +05:30
{
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " Failed to load the version description file for reasons unknown. " ) ) ;
2013-08-05 06:59:50 +05:30
return ;
}
2013-09-22 07:51:36 +05:30
2013-12-11 01:03:24 +05:30
// Build a list of URLs that will need to be downloaded.
2014-03-02 03:36:47 +05:30
std : : shared_ptr < VersionFinal > version = inst - > getFullVersion ( ) ;
2013-12-11 01:03:24 +05:30
// minecraft.jar for this version
{
QString version_id = version - > id ;
QString localPath = version_id + " / " + version_id + " .jar " ;
2013-12-13 20:28:11 +05:30
QString urlstr = " http:// " + URLConstants : : AWS_DOWNLOAD_VERSIONS + localPath ;
2013-09-22 07:51:36 +05:30
2014-03-23 23:37:13 +05:30
auto job = new NetJob ( tr ( " Libraries for instance %1 " ) . arg ( inst - > name ( ) ) ) ;
2013-09-22 07:51:36 +05:30
2013-12-11 01:03:24 +05:30
auto metacache = MMC - > metacache ( ) ;
auto entry = metacache - > resolveEntry ( " versions " , localPath ) ;
job - > addNetAction ( CacheDownload : : make ( QUrl ( urlstr ) , entry ) ) ;
2014-05-05 03:40:59 +05:30
jarHashOnEntry = entry - > md5sum ;
2013-12-11 01:03:24 +05:30
jarlibDownloadJob . reset ( job ) ;
}
2013-09-22 07:51:36 +05:30
2013-08-05 06:59:50 +05:30
auto libs = version - > getActiveNativeLibs ( ) ;
libs . append ( version - > getActiveNormalLibs ( ) ) ;
2013-09-22 07:51:36 +05:30
2013-09-08 05:45:20 +05:30
auto metacache = MMC - > metacache ( ) ;
2013-11-17 16:14:18 +05:30
QList < ForgeXzDownloadPtr > ForgeLibs ;
2014-04-14 02:36:28 +05:30
QList < std : : shared_ptr < OneSixLibrary > > brokenLocalLibs ;
2013-09-22 07:51:36 +05:30
for ( auto lib : libs )
2013-08-05 06:59:50 +05:30
{
2013-10-21 02:48:40 +05:30
if ( lib - > hint ( ) = = " local " )
2014-04-14 02:36:28 +05:30
{
2014-05-03 19:10:46 +05:30
if ( ! lib - > filesExist ( m_inst - > librariesPath ( ) ) )
2014-04-14 02:36:28 +05:30
brokenLocalLibs . append ( lib ) ;
2013-10-21 02:48:40 +05:30
continue ;
2014-04-14 02:36:28 +05:30
}
2013-11-25 05:16:52 +05:30
2014-01-14 05:43:35 +05:30
QString raw_storage = lib - > storagePath ( ) ;
QString raw_dl = lib - > downloadUrl ( ) ;
2013-11-25 05:16:52 +05:30
2014-01-14 05:43:35 +05:30
auto f = [ & ] ( QString storage , QString dl )
2013-09-08 05:45:20 +05:30
{
2014-01-14 05:43:35 +05:30
auto entry = metacache - > resolveEntry ( " libraries " , storage ) ;
if ( entry - > stale )
2013-11-17 16:14:18 +05:30
{
2014-01-14 05:43:35 +05:30
if ( lib - > hint ( ) = = " forge-pack-xz " )
{
ForgeLibs . append ( ForgeXzDownload : : make ( storage , entry ) ) ;
}
else
{
jarlibDownloadJob - > addNetAction ( CacheDownload : : make ( dl , entry ) ) ;
}
2013-11-17 16:14:18 +05:30
}
2014-01-14 05:43:35 +05:30
} ;
if ( raw_storage . contains ( " ${arch} " ) )
{
QString cooked_storage = raw_storage ;
QString cooked_dl = raw_dl ;
f ( cooked_storage . replace ( " ${arch} " , " 32 " ) , cooked_dl . replace ( " ${arch} " , " 32 " ) ) ;
cooked_storage = raw_storage ;
cooked_dl = raw_dl ;
f ( cooked_storage . replace ( " ${arch} " , " 64 " ) , cooked_dl . replace ( " ${arch} " , " 64 " ) ) ;
}
else
{
f ( raw_storage , raw_dl ) ;
2013-09-08 05:45:20 +05:30
}
2013-08-05 06:59:50 +05:30
}
2014-04-14 02:36:28 +05:30
if ( ! brokenLocalLibs . empty ( ) )
{
jarlibDownloadJob . reset ( ) ;
QStringList failed ;
for ( auto brokenLib : brokenLocalLibs )
{
failed . append ( brokenLib - > files ( ) ) ;
}
QString failed_all = failed . join ( " \n " ) ;
emitFailed ( tr ( " Some libraries marked as 'local' are missing their jar files: \n %1 \n \n You'll have to correct this problem manually. If this is an externally tracked instance, make sure to run it at least once outside of MultiMC. " ) . arg ( failed_all ) ) ;
return ;
}
2013-11-17 16:14:18 +05:30
// TODO: think about how to propagate this from the original json file... or IF AT ALL
QString forgeMirrorList = " http://files.minecraftforge.net/mirror-brand.list " ;
if ( ! ForgeLibs . empty ( ) )
{
jarlibDownloadJob - > addNetAction (
ForgeMirrors : : make ( ForgeLibs , jarlibDownloadJob , forgeMirrorList ) ) ;
}
2013-10-06 04:43:40 +05:30
connect ( jarlibDownloadJob . get ( ) , SIGNAL ( succeeded ( ) ) , SLOT ( jarlibFinished ( ) ) ) ;
connect ( jarlibDownloadJob . get ( ) , SIGNAL ( failed ( ) ) , SLOT ( jarlibFailed ( ) ) ) ;
connect ( jarlibDownloadJob . get ( ) , SIGNAL ( progress ( qint64 , qint64 ) ) ,
2013-09-22 07:51:36 +05:30
SIGNAL ( progress ( qint64 , qint64 ) ) ) ;
2013-08-05 06:59:50 +05:30
2013-09-02 03:55:40 +05:30
jarlibDownloadJob - > start ( ) ;
2013-07-10 02:16:33 +05:30
}
2013-08-04 18:16:33 +05:30
void OneSixUpdate : : jarlibFinished ( )
2013-07-10 02:16:33 +05:30
{
2014-05-05 03:40:59 +05:30
OneSixInstance * inst = ( OneSixInstance * ) m_inst ;
std : : shared_ptr < VersionFinal > version = inst - > getFullVersion ( ) ;
// create stripped jar, if needed
if ( version - > hasJarMods ( ) )
{
//FIXME: good candidate for moving elsewhere (jar location resolving/version caching).
QString version_id = version - > id ;
QString localPath = version_id + " / " + version_id + " .jar " ;
QString strippedPath = version_id + " / " + version_id + " -stripped.jar " ;
auto metacache = MMC - > metacache ( ) ;
auto entry = metacache - > resolveEntry ( " versions " , localPath ) ;
auto entryStripped = metacache - > resolveEntry ( " versions " , strippedPath ) ;
QString fullJarPath = entry - > getFullPath ( ) ;
QString fullStrippedJarPath = entryStripped - > getFullPath ( ) ;
if ( entry - > md5sum ! = jarHashOnEntry | | ! QFileInfo : : exists ( fullStrippedJarPath ) )
{
stripJar ( fullJarPath , fullStrippedJarPath ) ;
}
}
if ( version - > traits . contains ( " legacyFML " ) )
{
fmllibsStart ( ) ;
}
else
{
assetIndexStart ( ) ;
}
2013-07-10 02:16:33 +05:30
}
2013-08-04 18:16:33 +05:30
void OneSixUpdate : : jarlibFailed ( )
2013-07-10 02:16:33 +05:30
{
2013-09-26 06:28:09 +05:30
QStringList failed = jarlibDownloadJob - > getFailedFiles ( ) ;
QString failed_all = failed . join ( " \n " ) ;
2014-03-10 04:12:25 +05:30
emitFailed ( tr ( " Failed to download the following files: \n %1 \n \n Please try again. " ) . arg ( failed_all ) ) ;
2013-07-08 03:21:26 +05:30
}
2014-05-05 03:40:59 +05:30
void OneSixUpdate : : stripJar ( QString origPath , QString newPath )
{
QFileInfo runnableJar ( newPath ) ;
if ( runnableJar . exists ( ) & & ! QFile : : remove ( runnableJar . filePath ( ) ) )
{
emitFailed ( " Failed to delete old minecraft.jar " ) ;
return ;
}
// TaskStep(); // STEP 1
setStatus ( tr ( " Creating stripped jar: Opening minecraft.jar ... " ) ) ;
QuaZip zipOut ( runnableJar . filePath ( ) ) ;
if ( ! zipOut . open ( QuaZip : : mdCreate ) )
{
QFile : : remove ( runnableJar . filePath ( ) ) ;
emitFailed ( " Failed to open the minecraft.jar for stripping " ) ;
return ;
}
// Modify the jar
setStatus ( tr ( " Creating stripped jar: Adding files... " ) ) ;
if ( ! MergeZipFiles ( & zipOut , origPath ) )
{
zipOut . close ( ) ;
QFile : : remove ( runnableJar . filePath ( ) ) ;
emitFailed ( " Failed to add " + origPath + " to the jar. " ) ;
return ;
}
}
bool OneSixUpdate : : MergeZipFiles ( QuaZip * into , QString from )
{
setStatus ( tr ( " Installing mods: Adding " ) + from + " ... " ) ;
QuaZip modZip ( from ) ;
modZip . open ( QuaZip : : mdUnzip ) ;
QuaZipFile fileInsideMod ( & modZip ) ;
QuaZipFile zipOutFile ( into ) ;
for ( bool more = modZip . goToFirstFile ( ) ; more ; more = modZip . goToNextFile ( ) )
{
QString filename = modZip . getCurrentFileName ( ) ;
if ( filename . contains ( " META-INF " ) )
{
QLOG_INFO ( ) < < " Skipping META-INF " < < filename < < " from " < < from ;
continue ;
}
QLOG_INFO ( ) < < " Adding file " < < filename < < " from " < < from ;
if ( ! fileInsideMod . open ( QIODevice : : ReadOnly ) )
{
QLOG_ERROR ( ) < < " Failed to open " < < filename < < " from " < < from ;
return false ;
}
/*
QuaZipFileInfo old_info ;
fileInsideMod . getFileInfo ( & old_info ) ;
*/
QuaZipNewInfo info_out ( fileInsideMod . getActualFileName ( ) ) ;
/*
info_out . externalAttr = old_info . externalAttr ;
*/
if ( ! zipOutFile . open ( QIODevice : : WriteOnly , info_out ) )
{
QLOG_ERROR ( ) < < " Failed to open " < < filename < < " in the jar " ;
fileInsideMod . close ( ) ;
return false ;
}
if ( ! JlCompress : : copyData ( fileInsideMod , zipOutFile ) )
{
zipOutFile . close ( ) ;
fileInsideMod . close ( ) ;
QLOG_ERROR ( ) < < " Failed to copy data of " < < filename < < " into the jar " ;
return false ;
}
zipOutFile . close ( ) ;
fileInsideMod . close ( ) ;
}
return true ;
}
void OneSixUpdate : : fmllibsStart ( )
{
// Get the mod list
OneSixInstance * inst = ( OneSixInstance * ) m_inst ;
std : : shared_ptr < VersionFinal > fullversion = inst - > getFullVersion ( ) ;
bool forge_present = false ;
QString version = inst - > intendedVersionId ( ) ;
auto & fmlLibsMapping = g_VersionFilterData . fmlLibsMapping ;
if ( ! fmlLibsMapping . contains ( version ) )
{
assetIndexStart ( ) ;
return ;
}
auto & libList = fmlLibsMapping [ version ] ;
// determine if we need some libs for FML or forge
setStatus ( tr ( " Checking for FML libraries... " ) ) ;
forge_present = ( fullversion - > versionFile ( " net.minecraftforge " ) ! = nullptr ) ;
// we don't...
if ( ! forge_present )
{
assetIndexStart ( ) ;
return ;
}
// now check the lib folder inside the instance for files.
for ( auto & lib : libList )
{
QFileInfo libInfo ( PathCombine ( inst - > libDir ( ) , lib . filename ) ) ;
if ( libInfo . exists ( ) )
continue ;
fmlLibsToProcess . append ( lib ) ;
}
// if everything is in place, there's nothing to do here...
if ( fmlLibsToProcess . isEmpty ( ) )
{
assetIndexStart ( ) ;
return ;
}
// download missing libs to our place
setStatus ( tr ( " Dowloading FML libraries... " ) ) ;
auto dljob = new NetJob ( " FML libraries " ) ;
auto metacache = MMC - > metacache ( ) ;
for ( auto & lib : fmlLibsToProcess )
{
auto entry = metacache - > resolveEntry ( " fmllibs " , lib . filename ) ;
QString urlString = lib . ours ? URLConstants : : FMLLIBS_OUR_BASE_URL + lib . filename
: URLConstants : : FMLLIBS_FORGE_BASE_URL + lib . filename ;
dljob - > addNetAction ( CacheDownload : : make ( QUrl ( urlString ) , entry ) ) ;
}
connect ( dljob , SIGNAL ( succeeded ( ) ) , SLOT ( fmllibsFinished ( ) ) ) ;
connect ( dljob , SIGNAL ( failed ( ) ) , SLOT ( fmllibsFailed ( ) ) ) ;
connect ( dljob , SIGNAL ( progress ( qint64 , qint64 ) ) , SIGNAL ( progress ( qint64 , qint64 ) ) ) ;
legacyDownloadJob . reset ( dljob ) ;
legacyDownloadJob - > start ( ) ;
}
void OneSixUpdate : : fmllibsFinished ( )
{
legacyDownloadJob . reset ( ) ;
if ( ! fmlLibsToProcess . isEmpty ( ) )
{
setStatus ( tr ( " Copying FML libraries into the instance... " ) ) ;
OneSixInstance * inst = ( OneSixInstance * ) m_inst ;
auto metacache = MMC - > metacache ( ) ;
int index = 0 ;
for ( auto & lib : fmlLibsToProcess )
{
progress ( index , fmlLibsToProcess . size ( ) ) ;
auto entry = metacache - > resolveEntry ( " fmllibs " , lib . filename ) ;
auto path = PathCombine ( inst - > libDir ( ) , lib . filename ) ;
if ( ! ensureFilePathExists ( path ) )
{
emitFailed ( tr ( " Failed creating FML library folder inside the instance. " ) ) ;
return ;
}
if ( ! QFile : : copy ( entry - > getFullPath ( ) , PathCombine ( inst - > libDir ( ) , lib . filename ) ) )
{
emitFailed ( tr ( " Failed copying Forge/FML library: %1. " ) . arg ( lib . filename ) ) ;
return ;
}
index + + ;
}
progress ( index , fmlLibsToProcess . size ( ) ) ;
}
assetIndexStart ( ) ;
}
void OneSixUpdate : : fmllibsFailed ( )
{
emitFailed ( " Game update failed: it was impossible to fetch the required FML libraries. " ) ;
return ;
}