PrismLauncher/logic/OneSixUpdate.cpp

214 lines
6.1 KiB
C++
Raw Normal View History

2013-02-22 00:10:17 +00:00
/* 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-02-22 00:10:17 +00:00
* 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.
*/
#include "MultiMC.h"
2013-08-04 13:46:33 +01:00
#include "OneSixUpdate.h"
2013-02-22 00:10:17 +00:00
#include <QtNetwork>
#include <QFile>
#include <QFileInfo>
#include <QTextStream>
#include <QDataStream>
2013-08-03 22:58:39 +01:00
#include "BaseInstance.h"
#include "lists/MinecraftVersionList.h"
#include "OneSixVersion.h"
2013-09-11 22:43:17 +01:00
#include "OneSixLibrary.h"
2013-08-05 02:29:50 +01:00
#include "OneSixInstance.h"
#include "net/ForgeMirrors.h"
#include "pathutils.h"
OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent) : BaseUpdate(inst, parent)
{
}
2013-08-04 13:46:33 +01:00
void OneSixUpdate::executeTask()
{
2013-08-05 02:29:50 +01:00
QString intendedVersion = m_inst->intendedVersionId();
// Make directories
QDir mcDir(m_inst->minecraftRoot());
if (!mcDir.exists() && !mcDir.mkpath("."))
{
emitFailed("Failed to create bin folder.");
return;
}
// Get a pointer to the version object that corresponds to the instance's version.
2013-10-06 00:13:40 +01:00
targetVersion = std::dynamic_pointer_cast<MinecraftVersion>(
MMC->minecraftlist()->findVersion(intendedVersion));
if (targetVersion == nullptr)
{
2013-08-05 02:29:50 +01:00
// don't do anything if it was invalid
emitSucceeded();
return;
}
if (m_inst->shouldUpdate())
2013-08-05 02:29:50 +01:00
{
versionFileStart();
}
else
{
jarlibStart();
}
}
void OneSixUpdate::versionFileStart()
{
2013-08-03 22:58:39 +01:00
setStatus("Getting the version files from Mojang.");
QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/");
urlstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json";
auto job = new NetJob("Version index");
job->addNetAction(ByteArrayDownload::make(QUrl(urlstr)));
specificVersionDownloadJob.reset(job);
2013-10-06 00:13:40 +01:00
connect(specificVersionDownloadJob.get(), SIGNAL(succeeded()), SLOT(versionFileFinished()));
connect(specificVersionDownloadJob.get(), SIGNAL(failed()), SLOT(versionFileFailed()));
connect(specificVersionDownloadJob.get(), SIGNAL(progress(qint64, qint64)),
SIGNAL(progress(qint64, qint64)));
2013-09-01 23:25:40 +01:00
specificVersionDownloadJob->start();
}
2013-08-04 13:46:33 +01:00
void OneSixUpdate::versionFileFinished()
{
NetActionPtr DlJob = specificVersionDownloadJob->first();
OneSixInstance *inst = (OneSixInstance *)m_inst;
QString version_id = targetVersion->descriptor();
QString inst_dir = m_inst->instanceRoot();
2013-08-05 02:29:50 +01:00
// save the version file in $instanceId/version.json
{
QString version1 = PathCombine(inst_dir, "/version.json");
ensureFilePathExists(version1);
2013-08-14 07:13:41 +01:00
// FIXME: detect errors here, download to a temp file, swap
QSaveFile vfile1(version1);
if (!vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly))
{
emitFailed("Can't open " + version1 + " for writing.");
return;
}
2013-10-06 00:13:40 +01:00
auto data = std::dynamic_pointer_cast<ByteArrayDownload>(DlJob)->m_data;
qint64 actual = 0;
if ((actual = vfile1.write(data)) != data.size())
{
emitFailed("Failed to write into " + version1 + ". Written " + actual + " out of " +
data.size() + '.');
return;
}
if (!vfile1.commit())
{
emitFailed("Can't commit changes to " + version1);
return;
}
}
2013-08-14 07:13:41 +01:00
// the version is downloaded safely. update is 'done' at this point
m_inst->setShouldUpdate(false);
// delete any custom version inside the instance (it's no longer relevant, we did an update)
QString custom = PathCombine(inst_dir, "/custom.json");
QFile finfo(custom);
if (finfo.exists())
{
finfo.remove();
}
inst->reloadFullVersion();
2013-08-05 02:29:50 +01:00
jarlibStart();
}
void OneSixUpdate::versionFileFailed()
{
emitFailed("Failed to download the version description. Try again.");
2013-08-05 02:29:50 +01:00
}
void OneSixUpdate::jarlibStart()
{
OneSixInstance *inst = (OneSixInstance *)m_inst;
2013-08-05 02:29:50 +01:00
bool successful = inst->reloadFullVersion();
if (!successful)
2013-08-05 02:29:50 +01:00
{
emitFailed("Failed to load the version description file (version.json). It might be "
"corrupted, missing or simply too new.");
2013-08-05 02:29:50 +01:00
return;
}
2013-10-06 00:13:40 +01:00
std::shared_ptr<OneSixVersion> version = inst->getFullVersion();
// download the right jar, save it in versions/$version/$version.jar
QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/");
2013-08-05 02:29:50 +01:00
urlstr += version->id + "/" + version->id + ".jar";
QString targetstr("versions/");
2013-08-05 02:29:50 +01:00
targetstr += version->id + "/" + version->id + ".jar";
auto job = new NetJob("Libraries for instance " + inst->name());
job->addNetAction(FileDownload::make(QUrl(urlstr), targetstr));
jarlibDownloadJob.reset(job);
2013-08-05 02:29:50 +01:00
auto libs = version->getActiveNativeLibs();
libs.append(version->getActiveNormalLibs());
auto metacache = MMC->metacache();
QList<ForgeXzDownloadPtr> ForgeLibs;
bool already_forge_xz = false;
for (auto lib : libs)
2013-08-05 02:29:50 +01:00
{
if (lib->hint() == "local")
continue;
auto entry = metacache->resolveEntry("libraries", lib->storagePath());
if (entry->stale)
{
2013-10-06 00:13:40 +01:00
if (lib->hint() == "forge-pack-xz")
{
ForgeLibs.append(ForgeXzDownload::make(lib->storagePath(), entry));
}
else
{
jarlibDownloadJob->addNetAction(CacheDownload::make(lib->downloadUrl(), entry));
}
}
2013-08-05 02:29:50 +01:00
}
// 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 00:13:40 +01:00
connect(jarlibDownloadJob.get(), SIGNAL(succeeded()), SLOT(jarlibFinished()));
connect(jarlibDownloadJob.get(), SIGNAL(failed()), SLOT(jarlibFailed()));
connect(jarlibDownloadJob.get(), SIGNAL(progress(qint64, qint64)),
SIGNAL(progress(qint64, qint64)));
2013-08-05 02:29:50 +01:00
2013-09-01 23:25:40 +01:00
jarlibDownloadJob->start();
}
2013-08-04 13:46:33 +01:00
void OneSixUpdate::jarlibFinished()
{
emitSucceeded();
}
2013-08-04 13:46:33 +01:00
void OneSixUpdate::jarlibFailed()
{
QStringList failed = jarlibDownloadJob->getFailedFiles();
QString failed_all = failed.join("\n");
emitFailed("Failed to download the following files:\n" + failed_all +
"\n\nPlease try again.");
}