2026-08-23 03:30:31 +03:00
|
|
|
#include "launcherpaths.h"
|
|
|
|
|
|
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
#include <QDir>
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
const QString kFolderName = QStringLiteral("galeonLauncher");
|
|
|
|
|
|
|
|
|
|
QString translate(const char *text)
|
|
|
|
|
{
|
|
|
|
|
return QCoreApplication::translate("LauncherPaths", text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
QString LauncherPaths::containerDir()
|
|
|
|
|
{
|
|
|
|
|
#if defined(Q_OS_WIN)
|
|
|
|
|
return QDir::homePath() + QStringLiteral("/AppData/Roaming");
|
|
|
|
|
#elif defined(Q_OS_MACOS)
|
|
|
|
|
return QDir::homePath() + QStringLiteral("/Library/Application Support");
|
|
|
|
|
#else // Linux и прочие Unix-системы
|
|
|
|
|
return QDir::homePath();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString LauncherPaths::rootDir()
|
|
|
|
|
{
|
|
|
|
|
return containerDir() + u'/' + kFolderName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString LauncherPaths::defaultMinecraftDir()
|
|
|
|
|
{
|
|
|
|
|
#if defined(Q_OS_MACOS)
|
|
|
|
|
// На macOS папка игры исторически без точки.
|
|
|
|
|
return containerDir() + QStringLiteral("/minecraft");
|
|
|
|
|
#else
|
|
|
|
|
return containerDir() + QStringLiteral("/.minecraft");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString LauncherPaths::settingsFile()
|
|
|
|
|
{
|
|
|
|
|
return rootDir() + QStringLiteral("/settings.json");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString LauncherPaths::profilesFile()
|
|
|
|
|
{
|
|
|
|
|
return rootDir() + QStringLiteral("/profiles.json");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-27 09:21:51 +03:00
|
|
|
QString LauncherPaths::customBuildsFile()
|
|
|
|
|
{
|
|
|
|
|
return rootDir() + QStringLiteral("/customBuilds.json");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString LauncherPaths::legacyCustomBuildsFile()
|
2026-08-23 03:30:31 +03:00
|
|
|
{
|
|
|
|
|
return rootDir() + QStringLiteral("/versions.json");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-27 09:21:51 +03:00
|
|
|
QString LauncherPaths::buildStorageDir()
|
|
|
|
|
{
|
|
|
|
|
return rootDir() + QStringLiteral("/builds");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-23 03:30:31 +03:00
|
|
|
QString LauncherPaths::runtimeDir()
|
|
|
|
|
{
|
|
|
|
|
return rootDir() + QStringLiteral("/runtime");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-27 19:35:11 +03:00
|
|
|
QString LauncherPaths::javaDir()
|
|
|
|
|
{
|
|
|
|
|
return rootDir() + QStringLiteral("/java");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString LauncherPaths::javaCatalogFile()
|
|
|
|
|
{
|
|
|
|
|
return cacheDir() + QStringLiteral("/java_runtimes.json");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString LauncherPaths::javaDownloadDir()
|
|
|
|
|
{
|
|
|
|
|
return cacheDir() + QStringLiteral("/java");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-24 21:09:52 +03:00
|
|
|
QString LauncherPaths::cacheDir()
|
|
|
|
|
{
|
|
|
|
|
return rootDir() + QStringLiteral("/cache");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString LauncherPaths::versionManifestFile()
|
|
|
|
|
{
|
|
|
|
|
return cacheDir() + QStringLiteral("/version_manifest.json");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-27 09:21:51 +03:00
|
|
|
QString LauncherPaths::loaderCacheFile(const QString &loaderKey)
|
|
|
|
|
{
|
|
|
|
|
return cacheDir() + QStringLiteral("/loader_") + loaderKey + QStringLiteral(".json");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString LauncherPaths::loaderDownloadDir()
|
|
|
|
|
{
|
|
|
|
|
return cacheDir() + QStringLiteral("/loaders");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-23 03:30:31 +03:00
|
|
|
bool LauncherPaths::ensureRootExists(QString *error)
|
|
|
|
|
{
|
2026-08-27 19:35:11 +03:00
|
|
|
const QStringList required{rootDir(), runtimeDir(), cacheDir(),
|
|
|
|
|
loaderDownloadDir(), buildStorageDir(), javaDir(),
|
|
|
|
|
javaDownloadDir()};
|
2026-08-23 03:30:31 +03:00
|
|
|
for (const QString &path : required) {
|
|
|
|
|
if (!QDir().mkpath(path)) {
|
|
|
|
|
if (error)
|
|
|
|
|
*error = translate("не удалось создать %1").arg(QDir::toNativeSeparators(path));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mkpath отвечает true и для существующего каталога, в который нельзя писать,
|
|
|
|
|
// и для подсунутого вместо папки файла — тогда все сохранения провалились бы молча.
|
|
|
|
|
const QFileInfo info(path);
|
|
|
|
|
if (!info.isDir() || !info.isWritable()) {
|
|
|
|
|
if (error)
|
|
|
|
|
*error = translate("нет доступа на запись в %1").arg(QDir::toNativeSeparators(path));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|