PrismLauncher/api/logic/minecraft/Library.cpp
Petr Mrázek 6e80f03409 NOISSUE add instance-local library storage
Any libraries stored in $instanceroot/libraries/ will override
the libraries from MultiMC's global folders, as long as they are marked 'local'
in the json patch.
2016-10-02 00:26:10 +02:00

291 lines
6.7 KiB
C++

#include "Library.h"
#include "MinecraftInstance.h"
#include <net/Download.h>
#include <net/ChecksumValidator.h>
#include <minecraft/forge/ForgeXzDownload.h>
#include <Env.h>
#include <FileSystem.h>
void Library::getApplicableFiles(OpSys system, QStringList& jar, QStringList& native, QStringList& native32,
QStringList& native64, const QString &overridePath) const
{
bool isLocal = (hint() == "local");
auto actualPath = [&](QString relPath)
{
QFileInfo out(FS::PathCombine(storagePrefix(), relPath));
if(isLocal && !overridePath.isEmpty())
{
QString fileName = out.fileName();
auto fullPath = FS::PathCombine(overridePath, fileName);
qDebug() << fullPath;
QFileInfo fileinfo(fullPath);
if(fileinfo.exists())
{
return fileinfo.absoluteFilePath();
}
}
return out.absoluteFilePath();
};
if(m_mojangDownloads)
{
if(m_mojangDownloads->artifact)
{
auto artifact = m_mojangDownloads->artifact;
jar += actualPath(artifact->path);
}
if(!isNative())
return;
if(m_nativeClassifiers.contains(system))
{
auto nativeClassifier = m_nativeClassifiers[system];
if(nativeClassifier.contains("${arch}"))
{
auto nat32Classifier = nativeClassifier;
nat32Classifier.replace("${arch}", "32");
auto nat64Classifier = nativeClassifier;
nat64Classifier.replace("${arch}", "64");
auto nat32info = m_mojangDownloads->getDownloadInfo(nat32Classifier);
if(nat32info)
native32 += actualPath(nat32info->path);
auto nat64info = m_mojangDownloads->getDownloadInfo(nat64Classifier);
if(nat64info)
native64 += actualPath(nat64info->path);
}
else
{
native += actualPath(m_mojangDownloads->getDownloadInfo(nativeClassifier)->path);
}
}
}
else
{
QString raw_storage = storageSuffix(system);
if(isNative())
{
if (raw_storage.contains("${arch}"))
{
auto nat32Storage = raw_storage;
nat32Storage.replace("${arch}", "32");
auto nat64Storage = raw_storage;
nat64Storage.replace("${arch}", "64");
native32 += actualPath(nat32Storage);
native64 += actualPath(nat64Storage);
}
else
{
native += actualPath(raw_storage);
}
}
else
{
jar += actualPath(raw_storage);
}
}
}
QList< std::shared_ptr< NetAction > > Library::getDownloads(OpSys system, class HttpMetaCache* cache,
QStringList& failedFiles, const QString & overridePath) const
{
QList<NetActionPtr> out;
bool isAlwaysStale = (hint() == "always-stale");
bool isLocal = (hint() == "local");
bool isForge = (hint() == "forge-pack-xz");
auto add_download = [&](QString storage, QString url, QString sha1 = QString())
{
auto entry = cache->resolveEntry("libraries", storage);
if(isAlwaysStale)
{
entry->setStale(true);
}
if (!entry->isStale())
return true;
if(isLocal)
{
if(!overridePath.isEmpty())
{
QString fileName;
int position = storage.lastIndexOf('/');
if(position == -1)
{
fileName = storage;
}
else
{
fileName = storage.mid(position);
}
auto fullPath = FS::PathCombine(overridePath, fileName);
QFileInfo fileinfo(fullPath);
if(fileinfo.exists())
{
return true;
}
}
QFileInfo fileinfo(entry->getFullPath());
if(!fileinfo.exists())
{
failedFiles.append(entry->getFullPath());
return false;
}
return true;
}
if (isForge)
{
out.append(ForgeXzDownload::make(storage, entry));
}
else
{
if(sha1.size())
{
auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
auto dl = Net::Download::makeCached(url, entry);
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
out.append(dl);
}
else
out.append(Net::Download::makeCached(url, entry));
}
return true;
};
if(m_mojangDownloads)
{
if(m_mojangDownloads->artifact)
{
auto artifact = m_mojangDownloads->artifact;
add_download(artifact->path, artifact->url, artifact->sha1);
}
if(m_nativeClassifiers.contains(system))
{
auto nativeClassifier = m_nativeClassifiers[system];
if(nativeClassifier.contains("${arch}"))
{
auto nat32Classifier = nativeClassifier;
nat32Classifier.replace("${arch}", "32");
auto nat64Classifier = nativeClassifier;
nat64Classifier.replace("${arch}", "64");
auto nat32info = m_mojangDownloads->getDownloadInfo(nat32Classifier);
if(nat32info)
add_download(nat32info->path, nat32info->url, nat32info->sha1);
auto nat64info = m_mojangDownloads->getDownloadInfo(nat64Classifier);
if(nat64info)
add_download(nat64info->path, nat64info->url, nat64info->sha1);
}
else
{
auto info = m_mojangDownloads->getDownloadInfo(nativeClassifier);
if(info)
{
add_download(info->path, info->url, info->sha1);
}
}
}
}
else
{
QString raw_storage = storageSuffix(system);
auto raw_dl = [&](){
if (!m_absoluteURL.isEmpty())
{
return m_absoluteURL;
}
if (m_repositoryURL.isEmpty())
{
return QString("https://" + URLConstants::LIBRARY_BASE) + raw_storage;
}
if(m_repositoryURL.endsWith('/'))
{
return m_repositoryURL + raw_storage;
}
else
{
return m_repositoryURL + QChar('/') + raw_storage;
}
}();
if (raw_storage.contains("${arch}"))
{
QString cooked_storage = raw_storage;
QString cooked_dl = raw_dl;
add_download(cooked_storage.replace("${arch}", "32"), cooked_dl.replace("${arch}", "32"));
cooked_storage = raw_storage;
cooked_dl = raw_dl;
add_download(cooked_storage.replace("${arch}", "64"), cooked_dl.replace("${arch}", "64"));
}
else
{
add_download(raw_storage, raw_dl);
}
}
return out;
}
bool Library::isActive() const
{
bool result = true;
if (m_rules.empty())
{
result = true;
}
else
{
RuleAction ruleResult = Disallow;
for (auto rule : m_rules)
{
RuleAction temp = rule->apply(this);
if (temp != Defer)
ruleResult = temp;
}
result = result && (ruleResult == Allow);
}
if (isNative())
{
result = result && m_nativeClassifiers.contains(currentSystem);
}
return result;
}
void Library::setStoragePrefix(QString prefix)
{
m_storagePrefix = prefix;
}
QString Library::defaultStoragePrefix()
{
return "libraries/";
}
QString Library::storagePrefix() const
{
if(m_storagePrefix.isEmpty())
{
return defaultStoragePrefix();
}
return m_storagePrefix;
}
QString Library::storageSuffix(OpSys system) const
{
// non-native? use only the gradle specifier
if (!isNative())
{
return m_name.toPath();
}
// otherwise native, override classifiers. Mojang HACK!
GradleSpecifier nativeSpec = m_name;
if (m_nativeClassifiers.contains(system))
{
nativeSpec.setClassifier(m_nativeClassifiers[system]);
}
else
{
nativeSpec.setClassifier("INVALID");
}
return nativeSpec.toPath();
}