cleanups
This commit is contained in:
@@ -21,8 +21,6 @@
|
||||
|
||||
namespace {
|
||||
|
||||
// Списки лоадеров меняются реже манифеста Mojang, но шесть часов держим те же:
|
||||
// одна цифра на весь лаунчер понятнее двух разных.
|
||||
constexpr qint64 kCacheTtlSeconds = 6 * 60 * 60;
|
||||
constexpr int kTransferTimeoutMs = 20000;
|
||||
|
||||
@@ -34,7 +32,6 @@ const QString kForgePromotions =
|
||||
QStringLiteral("https://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json");
|
||||
|
||||
const QString kNeoForgeMaven = QStringLiteral("https://maven.neoforged.net/releases/net/neoforged/neoforge/");
|
||||
// Под 1.20.1 NeoForge выходил ещё под старым именем артефакта.
|
||||
const QString kNeoForgeLegacyMaven =
|
||||
QStringLiteral("https://maven.neoforged.net/releases/net/neoforged/forge/");
|
||||
|
||||
@@ -46,8 +43,6 @@ bool looksUnstable(const QString &version)
|
||||
|| lower.contains(u'+');
|
||||
}
|
||||
|
||||
// Сравнение версий по числовым компонентам: «47.4.23» новее «47.4.2», хотя как
|
||||
// строка стоит раньше. Нечисловые хвосты (alpha, +snapshot) сравниваются как есть.
|
||||
bool isNewer(const QString &a, const QString &b)
|
||||
{
|
||||
const QStringList pa = a.split(QRegularExpression(QStringLiteral("[.\\-+]")), Qt::SkipEmptyParts);
|
||||
@@ -63,7 +58,6 @@ bool isNewer(const QString &a, const QString &b)
|
||||
return na > nb;
|
||||
continue;
|
||||
}
|
||||
// Число всегда «новее» суффикса: 26.1.0.0 идёт впереди 26.1.0.0-alpha.1.
|
||||
if (okA != okB)
|
||||
return okA;
|
||||
if (sa != sb)
|
||||
@@ -72,9 +66,6 @@ bool isNewer(const QString &a, const QString &b)
|
||||
return false;
|
||||
}
|
||||
|
||||
// «21.1.248» -> «1.21.1», «21.0.167» -> «1.21», «26.1.2.97» -> «26.1.2»,
|
||||
// «26.2.0.68» -> «26.2». До 1.20.2 Minecraft нумеровался как 1.x.y, с 26.1 —
|
||||
// как x.y, поэтому у NeoForge две схемы: три компонента и четыре.
|
||||
QString neoForgeGameVersion(const QString &neoVersion)
|
||||
{
|
||||
const QString head = neoVersion.section(u'-', 0, 0).section(u'+', 0, 0);
|
||||
@@ -111,7 +102,7 @@ LoaderVersionEntry entryFromJson(const QJsonObject &o)
|
||||
return entry;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
}
|
||||
|
||||
ModLoaderVersionService::ModLoaderVersionService(QObject *parent)
|
||||
: QObject(parent)
|
||||
@@ -138,8 +129,6 @@ const ModLoaderVersionService::Bucket &ModLoaderVersionService::bucket(ModLoader
|
||||
|
||||
QString ModLoaderVersionService::requestKey(ModLoader loader, const QString &gameVersion)
|
||||
{
|
||||
// У Forge и NeoForge один запрос покрывает все версии игры — они делят
|
||||
// очередь колбэков, чтобы не качать maven-metadata по разу на версию.
|
||||
return isPerGameVersion(loader) ? loaderKey(loader) + u'/' + gameVersion : loaderKey(loader);
|
||||
}
|
||||
|
||||
@@ -194,8 +183,6 @@ void ModLoaderVersionService::ensureLoaded(ModLoader loader,
|
||||
}
|
||||
|
||||
if (!forceRefresh && isFresh(loader, gameVersion)) {
|
||||
// Колбэк, который то синхронный, то нет, ломает вызывающий код —
|
||||
// на попадании в кэш отвечаем через событийный цикл.
|
||||
if (callback)
|
||||
QTimer::singleShot(0, this, [callback = std::move(callback)] { callback(true, {}); });
|
||||
return;
|
||||
@@ -236,8 +223,6 @@ void ModLoaderVersionService::startRefresh(ModLoader loader, const QString &game
|
||||
}
|
||||
|
||||
const QByteArray payload = reply->readAll();
|
||||
// Пустой список — законный ответ: этот лоадер не поддерживает такую
|
||||
// версию игры. Отличаем его от испорченного ответа по самому JSON.
|
||||
const QJsonDocument document = QJsonDocument::fromJson(payload);
|
||||
if (!document.isArray()) {
|
||||
finishRefresh(loader, gameVersion, false,
|
||||
@@ -255,14 +240,11 @@ void ModLoaderVersionService::startRefresh(ModLoader loader, const QString &game
|
||||
return;
|
||||
}
|
||||
|
||||
// Forge и NeoForge: основной maven-metadata плюс вспомогательный запрос
|
||||
// (рекомендованные сборки у Forge, старая схема 1.20.1 у NeoForge).
|
||||
// Считаем оба и сводим результат, когда придёт последний.
|
||||
struct Pending
|
||||
{
|
||||
int outstanding = 2;
|
||||
QHash<QString, QList<LoaderVersionEntry>> merged;
|
||||
QHash<QString, QString> recommended; // версия игры -> версия лоадера
|
||||
QHash<QString, QString> recommended;
|
||||
bool primaryOk = false;
|
||||
QString warning;
|
||||
};
|
||||
@@ -327,7 +309,6 @@ void ModLoaderVersionService::startRefresh(ModLoader loader, const QString &game
|
||||
it.value().toString());
|
||||
}
|
||||
}
|
||||
// Метка «рекомендовано» необязательна: без неё список всё равно рабочий.
|
||||
settle();
|
||||
});
|
||||
} else {
|
||||
@@ -354,12 +335,9 @@ void ModLoaderVersionService::finishRefresh(ModLoader loader,
|
||||
const QString key = requestKey(loader, gameVersion);
|
||||
m_inFlight.remove(key);
|
||||
emit refreshingChanged();
|
||||
|
||||
// Колбэк может снова позвать ensureLoaded — список забираем себе заранее.
|
||||
const QList<Callback> pending = m_pending.take(key);
|
||||
const bool haveData = !bucket(loader).byGame.isEmpty();
|
||||
for (const Callback &callback : pending) {
|
||||
// Сеть недоступна, но старые данные есть — работаем на них.
|
||||
if (!ok && haveData)
|
||||
callback(true, warning);
|
||||
else
|
||||
@@ -389,7 +367,6 @@ QList<LoaderVersionEntry> ModLoaderVersionService::parseFabricLike(const QByteAr
|
||||
list << entry;
|
||||
}
|
||||
|
||||
// Fabric и Quilt отдают новые сверху, но зависеть от этого не стоит.
|
||||
std::stable_sort(list.begin(), list.end(),
|
||||
[](const LoaderVersionEntry &a, const LoaderVersionEntry &b) {
|
||||
return isNewer(a.loaderVersion, b.loaderVersion);
|
||||
@@ -400,9 +377,6 @@ QList<LoaderVersionEntry> ModLoaderVersionService::parseFabricLike(const QByteAr
|
||||
QHash<QString, QList<LoaderVersionEntry>> ModLoaderVersionService::parseMavenMetadata(
|
||||
const QByteArray &xml, ModLoader loader, bool legacyNeoForge)
|
||||
{
|
||||
// Версия игры зашита в саму строку версии лоадера, поэтому раскладка по
|
||||
// версиям игры — это и есть проверка совместимости: несовместимой пары в
|
||||
// получившемся отображении просто не существует.
|
||||
const bool splitOnDash = loader == ModLoader::Forge || legacyNeoForge;
|
||||
const QString base = loader == ModLoader::Forge ? kForgeMaven
|
||||
: legacyNeoForge ? kNeoForgeLegacyMaven
|
||||
@@ -445,8 +419,6 @@ QHash<QString, QList<LoaderVersionEntry>> ModLoaderVersionService::parseMavenMet
|
||||
if (reader.hasError())
|
||||
return {};
|
||||
|
||||
// maven-metadata приходит неотсортированным: 1.20.1-47.4.23 стоит между
|
||||
// версиями 26.x. Без сортировки «самой новой» оказалась бы случайная сборка.
|
||||
for (auto it = byGame.begin(); it != byGame.end(); ++it) {
|
||||
std::stable_sort(it.value().begin(), it.value().end(),
|
||||
[](const LoaderVersionEntry &a, const LoaderVersionEntry &b) {
|
||||
@@ -488,7 +460,6 @@ bool ModLoaderVersionService::readCache(ModLoader loader)
|
||||
|
||||
void ModLoaderVersionService::writeCache(ModLoader loader)
|
||||
{
|
||||
// Папку кэша могли удалить уже после запуска лаунчера.
|
||||
if (!LauncherPaths::ensureRootExists())
|
||||
return;
|
||||
|
||||
@@ -507,8 +478,6 @@ void ModLoaderVersionService::writeCache(ModLoader loader)
|
||||
const QJsonObject root{{QStringLiteral("fetchedAt"), b.fetchedAt.toString(Qt::ISODate)},
|
||||
{QStringLiteral("games"), games}};
|
||||
|
||||
// QSaveFile: оборванная запись не оставит обрезанный кэш, который потом
|
||||
// пришлось бы отличать от настоящего.
|
||||
QSaveFile file(LauncherPaths::loaderCacheFile(loaderKey(loader)));
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user