Finish assets update for 1.7.3
This commit is contained in:
parent
8db2e5db81
commit
3f5c46a1c4
@ -284,8 +284,8 @@ logic/InstanceLauncher.cpp
|
||||
|
||||
# network stuffs
|
||||
logic/net/NetAction.h
|
||||
logic/net/FileDownload.h
|
||||
logic/net/FileDownload.cpp
|
||||
logic/net/MD5EtagDownload.h
|
||||
logic/net/MD5EtagDownload.cpp
|
||||
logic/net/ByteArrayDownload.h
|
||||
logic/net/ByteArrayDownload.cpp
|
||||
logic/net/CacheDownload.h
|
||||
@ -325,8 +325,6 @@ logic/LegacyForge.h
|
||||
logic/LegacyForge.cpp
|
||||
|
||||
# 1.6 instances
|
||||
logic/OneSixAssets.h
|
||||
logic/OneSixAssets.cpp
|
||||
logic/OneSixInstance.h
|
||||
logic/OneSixInstance.cpp
|
||||
logic/OneSixInstance_p.h
|
||||
@ -385,13 +383,8 @@ logic/SkinUtils.h
|
||||
logic/SkinUtils.cpp
|
||||
|
||||
# Assets
|
||||
logic/assets/AssetsIndex.h
|
||||
logic/assets/AssetsIndex.cpp
|
||||
logic/assets/AssetsUtils.h
|
||||
logic/assets/AssetsUtils.cpp
|
||||
logic/assets/Assets.h
|
||||
logic/assets/Assets.cpp
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
@ -351,7 +351,8 @@ void MultiMC::initGlobalSettings()
|
||||
void MultiMC::initHttpMetaCache()
|
||||
{
|
||||
m_metacache.reset(new HttpMetaCache("metacache"));
|
||||
m_metacache->addBase("assets", QDir("assets").absolutePath());
|
||||
m_metacache->addBase("asset_indexes", QDir("assets/indexes").absolutePath());
|
||||
m_metacache->addBase("asset_objects", QDir("assets/objects").absolutePath());
|
||||
m_metacache->addBase("versions", QDir("versions").absolutePath());
|
||||
m_metacache->addBase("libraries", QDir("libraries").absolutePath());
|
||||
m_metacache->addBase("minecraftforge", QDir("mods/minecraftforge").absolutePath());
|
||||
|
@ -72,7 +72,6 @@
|
||||
#include "logic/BaseInstance.h"
|
||||
#include "logic/InstanceFactory.h"
|
||||
#include "logic/MinecraftProcess.h"
|
||||
#include "logic/OneSixAssets.h"
|
||||
#include "logic/OneSixUpdate.h"
|
||||
#include "logic/JavaUtils.h"
|
||||
#include "logic/NagUtils.h"
|
||||
@ -233,15 +232,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
||||
{
|
||||
MMC->lwjgllist()->loadList();
|
||||
}
|
||||
|
||||
assets_downloader = new OneSixAssets();
|
||||
connect(assets_downloader, SIGNAL(indexStarted()), SLOT(assetsIndexStarted()));
|
||||
connect(assets_downloader, SIGNAL(filesStarted()), SLOT(assetsFilesStarted()));
|
||||
connect(assets_downloader, SIGNAL(filesProgress(int, int, int)),
|
||||
SLOT(assetsFilesProgress(int, int, int)));
|
||||
connect(assets_downloader, SIGNAL(failed()), SLOT(assetsFailed()));
|
||||
connect(assets_downloader, SIGNAL(finished()), SLOT(assetsFinished()));
|
||||
//assets_downloader->start();
|
||||
}
|
||||
|
||||
const QString currentInstanceId = MMC->settings()->get("SelectedInstance").toString();
|
||||
@ -274,7 +264,6 @@ MainWindow::~MainWindow()
|
||||
delete ui;
|
||||
delete proxymodel;
|
||||
delete drawer;
|
||||
delete assets_downloader;
|
||||
}
|
||||
|
||||
void MainWindow::repopulateAccountsMenu()
|
||||
|
@ -31,7 +31,6 @@ class KCategorizedView;
|
||||
class KCategoryDrawer;
|
||||
class MinecraftProcess;
|
||||
class ConsoleWindow;
|
||||
class OneSixAssets;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@ -173,7 +172,6 @@ private:
|
||||
InstanceProxyModel *proxymodel;
|
||||
MinecraftProcess *proc;
|
||||
ConsoleWindow *console;
|
||||
OneSixAssets *assets_downloader;
|
||||
LabeledToolButton *renameButton;
|
||||
QToolButton *changeIconButton;
|
||||
|
||||
|
@ -266,7 +266,7 @@ void LegacyUpdate::jarStart()
|
||||
urlstr += intended_version_id + "/" + intended_version_id + ".jar";
|
||||
|
||||
auto dljob = new NetJob("Minecraft.jar for version " + intended_version_id);
|
||||
dljob->addNetAction(FileDownload::make(QUrl(urlstr), inst->defaultBaseJar()));
|
||||
dljob->addNetAction(MD5EtagDownload::make(QUrl(urlstr), inst->defaultBaseJar()));
|
||||
legacyDownloadJob.reset(dljob);
|
||||
connect(dljob, SIGNAL(succeeded()), SLOT(jarFinished()));
|
||||
connect(dljob, SIGNAL(failed()), SLOT(jarFailed()));
|
||||
|
@ -1,127 +0,0 @@
|
||||
/* 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
|
||||
*
|
||||
* 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 <QString>
|
||||
#include "logger/QsLog.h"
|
||||
#include <QtXml/QtXml>
|
||||
#include "OneSixAssets.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "net/HttpMetaCache.h"
|
||||
#include "net/S3ListBucket.h"
|
||||
#include "MultiMC.h"
|
||||
|
||||
#define ASSETS_URL "http://resources.download.minecraft.net/"
|
||||
|
||||
class ThreadedDeleter : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
void run()
|
||||
{
|
||||
QLOG_INFO() << "Cleaning up assets folder...";
|
||||
QDirIterator iter(m_base, QDirIterator::Subdirectories);
|
||||
int base_length = m_base.length();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
QString filename = iter.next();
|
||||
QFileInfo current(filename);
|
||||
// we keep the dirs... whatever
|
||||
if (current.isDir())
|
||||
continue;
|
||||
QString trimmedf = filename;
|
||||
trimmedf.remove(0, base_length + 1);
|
||||
if (m_whitelist.contains(trimmedf))
|
||||
{
|
||||
QLOG_TRACE() << trimmedf << " gets to live";
|
||||
}
|
||||
else
|
||||
{
|
||||
// DO NOT TOLERATE JUNK
|
||||
QLOG_TRACE() << trimmedf << " dies";
|
||||
QFile f(filename);
|
||||
f.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
QString m_base;
|
||||
QStringList m_whitelist;
|
||||
};
|
||||
|
||||
void OneSixAssets::downloadFinished()
|
||||
{
|
||||
deleter = new ThreadedDeleter();
|
||||
QDir dir("assets");
|
||||
deleter->m_base = dir.absolutePath();
|
||||
deleter->m_whitelist = nuke_whitelist;
|
||||
connect(deleter, SIGNAL(finished()), SIGNAL(finished()));
|
||||
deleter->start();
|
||||
}
|
||||
|
||||
void OneSixAssets::S3BucketFinished()
|
||||
{
|
||||
QString prefix(ASSETS_URL);
|
||||
nuke_whitelist.clear();
|
||||
|
||||
emit filesStarted();
|
||||
|
||||
auto firstJob = index_job->first();
|
||||
auto objectList = std::dynamic_pointer_cast<S3ListBucket>(firstJob)->objects;
|
||||
|
||||
NetJob *job = new NetJob("Assets");
|
||||
|
||||
connect(job, SIGNAL(succeeded()), SLOT(downloadFinished()));
|
||||
connect(job, SIGNAL(failed()), SIGNAL(failed()));
|
||||
connect(job, SIGNAL(filesProgress(int, int, int)), SIGNAL(filesProgress(int, int, int)));
|
||||
|
||||
auto metacache = MMC->metacache();
|
||||
|
||||
for (auto object : objectList)
|
||||
{
|
||||
// Filter folder keys (zero size)
|
||||
if (object.size == 0)
|
||||
continue;
|
||||
|
||||
nuke_whitelist.append(object.Key);
|
||||
|
||||
auto entry = metacache->resolveEntry("assets", object.Key, object.ETag);
|
||||
if (entry->stale)
|
||||
{
|
||||
job->addNetAction(CacheDownload::make(QUrl(prefix + object.Key), entry));
|
||||
}
|
||||
}
|
||||
if (job->size())
|
||||
{
|
||||
files_job.reset(job);
|
||||
files_job->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
delete job;
|
||||
emit finished();
|
||||
}
|
||||
}
|
||||
|
||||
void OneSixAssets::start()
|
||||
{
|
||||
auto job = new NetJob("Assets index");
|
||||
job->addNetAction(S3ListBucket::make(QUrl(ASSETS_URL)));
|
||||
connect(job, SIGNAL(succeeded()), SLOT(S3BucketFinished()));
|
||||
connect(job, SIGNAL(failed()), SIGNAL(failed()));
|
||||
emit indexStarted();
|
||||
index_job.reset(job);
|
||||
job->start();
|
||||
}
|
||||
|
||||
#include "OneSixAssets.moc"
|
@ -1,45 +0,0 @@
|
||||
/* 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "net/NetJob.h"
|
||||
|
||||
class Private;
|
||||
class ThreadedDeleter;
|
||||
|
||||
class OneSixAssets : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
signals:
|
||||
void failed();
|
||||
void finished();
|
||||
void indexStarted();
|
||||
void filesStarted();
|
||||
void filesProgress(int, int, int);
|
||||
|
||||
public
|
||||
slots:
|
||||
void S3BucketFinished();
|
||||
void downloadFinished();
|
||||
|
||||
public:
|
||||
void start();
|
||||
|
||||
private:
|
||||
ThreadedDeleter *deleter;
|
||||
QStringList nuke_whitelist;
|
||||
NetJobPtr index_job;
|
||||
NetJobPtr files_job;
|
||||
};
|
@ -26,7 +26,6 @@
|
||||
#include <JlCompress.h>
|
||||
#include "gui/dialogs/OneSixModEditDialog.h"
|
||||
#include "logger/QsLog.h"
|
||||
#include "logic/assets/AssetsIndex.h"
|
||||
#include "logic/assets/AssetsUtils.h"
|
||||
|
||||
OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_obj,
|
||||
@ -96,9 +95,9 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<OneSixVersion> version)
|
||||
{
|
||||
QLOG_INFO() << "Reconstructing virtual assets folder at" << virtualRoot.path();
|
||||
|
||||
for(QString map : index.objects->keys())
|
||||
for(QString map : index.objects.keys())
|
||||
{
|
||||
AssetObject asset_object = index.objects->value(map);
|
||||
AssetObject asset_object = index.objects.value(map);
|
||||
QString target_path = PathCombine(virtualRoot.path(), map);
|
||||
QFile target(target_path);
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "OneSixLibrary.h"
|
||||
#include "OneSixInstance.h"
|
||||
#include "net/ForgeMirrors.h"
|
||||
#include "assets/AssetsUtils.h"
|
||||
|
||||
#include "pathutils.h"
|
||||
#include <JlCompress.h>
|
||||
@ -50,7 +51,7 @@ void OneSixUpdate::executeTask()
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_only_prepare)
|
||||
if (m_only_prepare)
|
||||
{
|
||||
if (m_inst->shouldUpdate())
|
||||
{
|
||||
@ -93,7 +94,7 @@ void OneSixUpdate::checkJavaOnline()
|
||||
|
||||
checker.reset(new JavaChecker());
|
||||
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
|
||||
SLOT(checkFinishedOnline(JavaCheckResult)));
|
||||
SLOT(checkFinishedOnline(JavaCheckResult)));
|
||||
checker->performCheck(java_path);
|
||||
}
|
||||
|
||||
@ -193,6 +194,96 @@ void OneSixUpdate::versionFileFailed()
|
||||
emitFailed("Failed to download the version description. Try again.");
|
||||
}
|
||||
|
||||
void OneSixUpdate::assetIndexStart()
|
||||
{
|
||||
setStatus("Updating asset index.");
|
||||
OneSixInstance *inst = (OneSixInstance *)m_inst;
|
||||
std::shared_ptr<OneSixVersion> version = inst->getFullVersion();
|
||||
QString assetName = version->assets;
|
||||
QUrl indexUrl("https://s3.amazonaws.com/Minecraft.Download/indexes/" + assetName + ".json");
|
||||
QString localPath = assetName + ".json";
|
||||
auto job = new NetJob("Asset index for " + inst->name());
|
||||
|
||||
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;
|
||||
std::shared_ptr<OneSixVersion> version = inst->getFullVersion();
|
||||
QString assetName = version->assets;
|
||||
|
||||
QString asset_fname = "assets/indexes/" + assetName + ".json";
|
||||
if (!AssetsUtils::loadAssetsIndexJson(asset_fname, &index))
|
||||
{
|
||||
emitFailed("Failed to read the assets index!");
|
||||
}
|
||||
|
||||
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(
|
||||
QUrl("http://resources.download.minecraft.net/" + objectName),
|
||||
objectFile.filePath());
|
||||
dls.append(objectDL);
|
||||
/*
|
||||
Downloadable downloadable = new AssetDownloadable(
|
||||
proxy, new URL("http://resources.download.minecraft.net/" + filename), file,
|
||||
false, object.getHash(), object.getSize());
|
||||
downloadable.setExpectedSize(object.getSize());
|
||||
result.add(downloadable);
|
||||
*/
|
||||
}
|
||||
}
|
||||
if(dls.size())
|
||||
{
|
||||
auto job = new NetJob("Assets for " + inst->name());
|
||||
for(auto dl: dls)
|
||||
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)),
|
||||
SIGNAL(progress(qint64, qint64)));
|
||||
jarlibDownloadJob->start();
|
||||
return;
|
||||
}
|
||||
assetsFinished();
|
||||
}
|
||||
|
||||
void OneSixUpdate::assetIndexFailed()
|
||||
{
|
||||
emitFailed("Failed to download the assets index!");
|
||||
}
|
||||
|
||||
void OneSixUpdate::assetsFinished()
|
||||
{
|
||||
prepareForLaunch();
|
||||
}
|
||||
|
||||
void OneSixUpdate::assetsFailed()
|
||||
{
|
||||
emitFailed("Failed to download assets!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OneSixUpdate::jarlibStart()
|
||||
{
|
||||
setStatus("Getting the library files from Mojang.");
|
||||
@ -215,7 +306,7 @@ void OneSixUpdate::jarlibStart()
|
||||
targetstr += version->id + "/" + version->id + ".jar";
|
||||
|
||||
auto job = new NetJob("Libraries for instance " + inst->name());
|
||||
job->addNetAction(FileDownload::make(QUrl(urlstr), targetstr));
|
||||
job->addNetAction(MD5EtagDownload::make(QUrl(urlstr), targetstr));
|
||||
jarlibDownloadJob.reset(job);
|
||||
|
||||
auto libs = version->getActiveNativeLibs();
|
||||
@ -265,7 +356,7 @@ void OneSixUpdate::jarlibStart()
|
||||
|
||||
void OneSixUpdate::jarlibFinished()
|
||||
{
|
||||
prepareForLaunch();
|
||||
assetIndexStart();
|
||||
}
|
||||
|
||||
void OneSixUpdate::jarlibFailed()
|
||||
|
@ -43,6 +43,13 @@ slots:
|
||||
void jarlibFinished();
|
||||
void jarlibFailed();
|
||||
|
||||
void assetIndexStart();
|
||||
void assetIndexFinished();
|
||||
void assetIndexFailed();
|
||||
|
||||
void assetsFinished();
|
||||
void assetsFailed();
|
||||
|
||||
void checkJavaOnline();
|
||||
void checkFinishedOnline(JavaCheckResult result);
|
||||
void checkFinishedOffline(JavaCheckResult result);
|
||||
|
@ -1,14 +0,0 @@
|
||||
/* 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
@ -1,16 +0,0 @@
|
||||
/* 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
@ -1,31 +0,0 @@
|
||||
/* 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
|
||||
*
|
||||
* 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 "AssetsIndex.h"
|
||||
|
||||
AssetsIndex::AssetsIndex()
|
||||
{
|
||||
// TODO: leak?
|
||||
this->objects = new QMap<QString, AssetObject>();
|
||||
this->isVirtual = false;
|
||||
}
|
||||
|
||||
AssetObject::AssetObject(QString hash, qint64 size) : hash(hash), size(size)
|
||||
{
|
||||
}
|
||||
|
||||
AssetObject::AssetObject()
|
||||
{
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/* 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
|
||||
class AssetObject;
|
||||
|
||||
class AssetsIndex
|
||||
{
|
||||
public:
|
||||
QMap<QString, AssetObject> *objects;
|
||||
bool isVirtual;
|
||||
|
||||
AssetsIndex();
|
||||
};
|
||||
|
||||
class AssetObject
|
||||
{
|
||||
public:
|
||||
AssetObject(QString hash, qint64 size);
|
||||
AssetObject();
|
||||
bool equals(AssetObject* other);
|
||||
QString getHashCode();
|
||||
|
||||
QString hash;
|
||||
qint64 size;
|
||||
};
|
@ -28,54 +28,64 @@ namespace AssetsUtils
|
||||
void migrateOldAssets()
|
||||
{
|
||||
QDir assets_dir("assets");
|
||||
if(!assets_dir.exists()) return;
|
||||
if (!assets_dir.exists())
|
||||
return;
|
||||
assets_dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot);
|
||||
int base_length = assets_dir.path().length();
|
||||
|
||||
QList<QString> blacklist = {"indexes", "objects", "virtual"};
|
||||
|
||||
if(!assets_dir.exists("objects")) assets_dir.mkdir("objects");
|
||||
if (!assets_dir.exists("objects"))
|
||||
assets_dir.mkdir("objects");
|
||||
QDir objects_dir("assets/objects");
|
||||
|
||||
QDirIterator iterator(assets_dir, QDirIterator::Subdirectories);
|
||||
int successes = 0;
|
||||
int failures = 0;
|
||||
while (iterator.hasNext()) {
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
QString currentDir = iterator.next();
|
||||
currentDir = currentDir.remove(0, base_length+1);
|
||||
currentDir = currentDir.remove(0, base_length + 1);
|
||||
|
||||
bool ignore = false;
|
||||
for(QString blacklisted : blacklist)
|
||||
for (QString blacklisted : blacklist)
|
||||
{
|
||||
if(currentDir.startsWith(blacklisted)) ignore = true;
|
||||
if (currentDir.startsWith(blacklisted))
|
||||
ignore = true;
|
||||
}
|
||||
|
||||
if (!iterator.fileInfo().isDir() && !ignore) {
|
||||
if (!iterator.fileInfo().isDir() && !ignore)
|
||||
{
|
||||
QString filename = iterator.filePath();
|
||||
|
||||
QFile input(filename);
|
||||
input.open(QIODevice::ReadOnly | QIODevice::WriteOnly);
|
||||
QString sha1sum = QCryptographicHash::hash(input.readAll(), QCryptographicHash::Sha1)
|
||||
.toHex()
|
||||
.constData();
|
||||
QString sha1sum =
|
||||
QCryptographicHash::hash(input.readAll(), QCryptographicHash::Sha1)
|
||||
.toHex()
|
||||
.constData();
|
||||
|
||||
QString object_name = filename.remove(0, base_length+1);
|
||||
QString object_name = filename.remove(0, base_length + 1);
|
||||
QLOG_DEBUG() << "Processing" << object_name << ":" << sha1sum << input.size();
|
||||
|
||||
QString object_tlk = sha1sum.left(2);
|
||||
QString object_tlk_dir = objects_dir.path() + "/" + object_tlk;
|
||||
|
||||
QDir tlk_dir(object_tlk_dir);
|
||||
if(!tlk_dir.exists()) objects_dir.mkdir(object_tlk);
|
||||
if (!tlk_dir.exists())
|
||||
objects_dir.mkdir(object_tlk);
|
||||
|
||||
QString new_filename = tlk_dir.path() + "/" + sha1sum;
|
||||
QFile new_object(new_filename);
|
||||
if(!new_object.exists())
|
||||
if (!new_object.exists())
|
||||
{
|
||||
bool rename_success = input.rename(new_filename);
|
||||
QLOG_DEBUG() << " Doesn't exist, copying to" << new_filename << ":" << QString::number(rename_success);
|
||||
if(rename_success) successes++;
|
||||
else failures++;
|
||||
QLOG_DEBUG() << " Doesn't exist, copying to" << new_filename << ":"
|
||||
<< QString::number(rename_success);
|
||||
if (rename_success)
|
||||
successes++;
|
||||
else
|
||||
failures++;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -85,26 +95,31 @@ void migrateOldAssets()
|
||||
}
|
||||
}
|
||||
|
||||
if(successes + failures == 0) {
|
||||
if (successes + failures == 0)
|
||||
{
|
||||
QLOG_DEBUG() << "No legacy assets needed importing.";
|
||||
}
|
||||
else
|
||||
{
|
||||
QLOG_DEBUG() << "Finished copying legacy assets:" << successes << "successes and" << failures << "failures.";
|
||||
QLOG_DEBUG() << "Finished copying legacy assets:" << successes << "successes and"
|
||||
<< failures << "failures.";
|
||||
|
||||
QDirIterator cleanup_iterator(assets_dir);
|
||||
|
||||
while (cleanup_iterator.hasNext()) {
|
||||
while (cleanup_iterator.hasNext())
|
||||
{
|
||||
QString currentDir = cleanup_iterator.next();
|
||||
currentDir = currentDir.remove(0, base_length+1);
|
||||
currentDir = currentDir.remove(0, base_length + 1);
|
||||
|
||||
bool ignore = false;
|
||||
for(QString blacklisted : blacklist)
|
||||
for (QString blacklisted : blacklist)
|
||||
{
|
||||
if(currentDir.startsWith(blacklisted)) ignore = true;
|
||||
if (currentDir.startsWith(blacklisted))
|
||||
ignore = true;
|
||||
}
|
||||
|
||||
if (cleanup_iterator.fileInfo().isDir() && !ignore) {
|
||||
if (cleanup_iterator.fileInfo().isDir() && !ignore)
|
||||
{
|
||||
QString path = cleanup_iterator.filePath();
|
||||
QDir folder(path);
|
||||
|
||||
@ -122,18 +137,18 @@ void migrateOldAssets()
|
||||
*/
|
||||
bool loadAssetsIndexJson(QString path, AssetsIndex *index)
|
||||
{
|
||||
/*
|
||||
{
|
||||
"objects": {
|
||||
"icons/icon_16x16.png": {
|
||||
"hash": "bdf48ef6b5d0d23bbb02e17d04865216179f510a",
|
||||
"size": 3665
|
||||
},
|
||||
...
|
||||
/*
|
||||
{
|
||||
"objects": {
|
||||
"icons/icon_16x16.png": {
|
||||
"hash": "bdf48ef6b5d0d23bbb02e17d04865216179f510a",
|
||||
"size": 3665
|
||||
},
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
||||
QFile file(path);
|
||||
|
||||
@ -155,7 +170,8 @@ bool loadAssetsIndexJson(QString path, AssetsIndex *index)
|
||||
// Fail if the JSON is invalid.
|
||||
if (parseError.error != QJsonParseError::NoError)
|
||||
{
|
||||
QLOG_ERROR() << "Failed to parse assets index file:" << parseError.errorString() << "at offset " << QString::number(parseError.offset);
|
||||
QLOG_ERROR() << "Failed to parse assets index file:" << parseError.errorString()
|
||||
<< "at offset " << QString::number(parseError.offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -169,7 +185,7 @@ bool loadAssetsIndexJson(QString path, AssetsIndex *index)
|
||||
QJsonObject root = jsonDoc.object();
|
||||
|
||||
QJsonValue isVirtual = root.value("virtual");
|
||||
if(!isVirtual.isUndefined())
|
||||
if (!isVirtual.isUndefined())
|
||||
{
|
||||
index->isVirtual = isVirtual.toBool(false);
|
||||
}
|
||||
@ -177,48 +193,35 @@ bool loadAssetsIndexJson(QString path, AssetsIndex *index)
|
||||
QJsonValue objects = root.value("objects");
|
||||
QVariantMap map = objects.toVariant().toMap();
|
||||
|
||||
for(QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) {
|
||||
//QLOG_DEBUG() << iter.key();
|
||||
for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
|
||||
{
|
||||
// QLOG_DEBUG() << iter.key();
|
||||
|
||||
QVariant variant = iter.value();
|
||||
QVariantMap nested_objects = variant.toMap();
|
||||
|
||||
AssetObject object;
|
||||
|
||||
for(QVariantMap::const_iterator nested_iter = nested_objects.begin(); nested_iter != nested_objects.end(); ++nested_iter) {
|
||||
//QLOG_DEBUG() << nested_iter.key() << nested_iter.value().toString();
|
||||
for (QVariantMap::const_iterator nested_iter = nested_objects.begin();
|
||||
nested_iter != nested_objects.end(); ++nested_iter)
|
||||
{
|
||||
// QLOG_DEBUG() << nested_iter.key() << nested_iter.value().toString();
|
||||
QString key = nested_iter.key();
|
||||
QVariant value = nested_iter.value();
|
||||
|
||||
if(key == "hash")
|
||||
if (key == "hash")
|
||||
{
|
||||
object.hash = value.toString();
|
||||
}
|
||||
else if(key == "size")
|
||||
else if (key == "size")
|
||||
{
|
||||
object.size = value.toDouble();
|
||||
}
|
||||
}
|
||||
|
||||
index->objects->insert(iter.key(), object);
|
||||
index->objects.insert(iter.key(), object);
|
||||
}
|
||||
|
||||
return true;
|
||||
/*for (QJsonValue accountVal : objects)
|
||||
{
|
||||
QJsonObject accountObj = accountVal.toObject();
|
||||
MojangAccountPtr account = MojangAccount::loadFromJson(accountObj);
|
||||
if (account.get() != nullptr)
|
||||
{
|
||||
connect(account.get(), SIGNAL(changed()), SLOT(accountChanged()));
|
||||
m_accounts.append(account);
|
||||
}
|
||||
else
|
||||
{
|
||||
QLOG_WARN() << "Failed to load an account.";
|
||||
}
|
||||
}*/
|
||||
|
||||
//return false;
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AssetsIndex.h"
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
|
||||
class AssetObject;
|
||||
|
||||
struct AssetObject
|
||||
{
|
||||
QString hash;
|
||||
qint64 size;
|
||||
};
|
||||
|
||||
struct AssetsIndex
|
||||
{
|
||||
QMap<QString, AssetObject> objects;
|
||||
bool isVirtual = false;
|
||||
};
|
||||
|
||||
namespace AssetsUtils
|
||||
{
|
||||
|
@ -14,12 +14,12 @@
|
||||
*/
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "FileDownload.h"
|
||||
#include "MD5EtagDownload.h"
|
||||
#include <pathutils.h>
|
||||
#include <QCryptographicHash>
|
||||
#include "logger/QsLog.h"
|
||||
|
||||
FileDownload::FileDownload(QUrl url, QString target_path) : NetAction()
|
||||
MD5EtagDownload::MD5EtagDownload(QUrl url, QString target_path) : NetAction()
|
||||
{
|
||||
m_url = url;
|
||||
m_target_path = target_path;
|
||||
@ -27,7 +27,7 @@ FileDownload::FileDownload(QUrl url, QString target_path) : NetAction()
|
||||
m_status = Job_NotStarted;
|
||||
}
|
||||
|
||||
void FileDownload::start()
|
||||
void MD5EtagDownload::start()
|
||||
{
|
||||
QString filename = m_target_path;
|
||||
m_output_file.setFileName(filename);
|
||||
@ -58,7 +58,7 @@ void FileDownload::start()
|
||||
return;
|
||||
}
|
||||
|
||||
QLOG_INFO() << "Downloading " << m_url.toString();
|
||||
QLOG_INFO() << "Downloading " << m_url.toString() << " expecting " << m_expected_md5;
|
||||
QNetworkRequest request(m_url);
|
||||
request.setRawHeader(QString("If-None-Match").toLatin1(), m_expected_md5.toLatin1());
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)");
|
||||
@ -75,19 +75,19 @@ void FileDownload::start()
|
||||
connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead()));
|
||||
}
|
||||
|
||||
void FileDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
void MD5EtagDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
emit progress(index_within_job, bytesReceived, bytesTotal);
|
||||
}
|
||||
|
||||
void FileDownload::downloadError(QNetworkReply::NetworkError error)
|
||||
void MD5EtagDownload::downloadError(QNetworkReply::NetworkError error)
|
||||
{
|
||||
// error happened during download.
|
||||
// TODO: log the reason why
|
||||
m_status = Job_Failed;
|
||||
}
|
||||
|
||||
void FileDownload::downloadFinished()
|
||||
void MD5EtagDownload::downloadFinished()
|
||||
{
|
||||
// if the download succeeded
|
||||
if (m_status != Job_Failed)
|
||||
@ -96,6 +96,7 @@ void FileDownload::downloadFinished()
|
||||
m_status = Job_Finished;
|
||||
m_output_file.close();
|
||||
|
||||
QLOG_INFO() << "Finished " << m_url.toString() << " got " << m_reply->rawHeader("ETag").constData();
|
||||
m_reply.reset();
|
||||
emit succeeded(index_within_job);
|
||||
return;
|
||||
@ -110,7 +111,7 @@ void FileDownload::downloadFinished()
|
||||
}
|
||||
}
|
||||
|
||||
void FileDownload::downloadReadyRead()
|
||||
void MD5EtagDownload::downloadReadyRead()
|
||||
{
|
||||
if (!m_output_file.isOpen())
|
||||
{
|
@ -18,8 +18,8 @@
|
||||
#include "NetAction.h"
|
||||
#include <QFile>
|
||||
|
||||
typedef std::shared_ptr<class FileDownload> FileDownloadPtr;
|
||||
class FileDownload : public NetAction
|
||||
typedef std::shared_ptr<class MD5EtagDownload> Md5EtagDownloadPtr;
|
||||
class MD5EtagDownload : public NetAction
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@ -35,10 +35,10 @@ public:
|
||||
QFile m_output_file;
|
||||
|
||||
public:
|
||||
explicit FileDownload(QUrl url, QString target_path);
|
||||
static FileDownloadPtr make(QUrl url, QString target_path)
|
||||
explicit MD5EtagDownload(QUrl url, QString target_path);
|
||||
static Md5EtagDownloadPtr make(QUrl url, QString target_path)
|
||||
{
|
||||
return FileDownloadPtr(new FileDownload(url, target_path));
|
||||
return Md5EtagDownloadPtr(new MD5EtagDownload(url, target_path));
|
||||
}
|
||||
protected
|
||||
slots:
|
@ -16,7 +16,7 @@
|
||||
#include "NetJob.h"
|
||||
#include "pathutils.h"
|
||||
#include "MultiMC.h"
|
||||
#include "FileDownload.h"
|
||||
#include "MD5EtagDownload.h"
|
||||
#include "ByteArrayDownload.h"
|
||||
#include "CacheDownload.h"
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <QLabel>
|
||||
#include "NetAction.h"
|
||||
#include "ByteArrayDownload.h"
|
||||
#include "FileDownload.h"
|
||||
#include "MD5EtagDownload.h"
|
||||
#include "CacheDownload.h"
|
||||
#include "HttpMetaCache.h"
|
||||
#include "ForgeXzDownload.h"
|
||||
|
Loading…
Reference in New Issue
Block a user